Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:43:53

0001 //===------------ MachOBuilder.h -- Build MachO Objects ---------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 // Build MachO object files for interaction with the ObjC runtime and debugger.
0010 //
0011 //===----------------------------------------------------------------------===//
0012 
0013 #ifndef LLVM_EXECUTIONENGINE_ORC_MACHOBUILDER_H
0014 #define LLVM_EXECUTIONENGINE_ORC_MACHOBUILDER_H
0015 
0016 #include "llvm/BinaryFormat/MachO.h"
0017 #include "llvm/Support/Endian.h"
0018 #include "llvm/Support/MathExtras.h"
0019 
0020 #include <list>
0021 #include <map>
0022 #include <vector>
0023 
0024 namespace llvm {
0025 namespace orc {
0026 
0027 template <typename MachOStruct>
0028 size_t writeMachOStruct(MutableArrayRef<char> Buf, size_t Offset, MachOStruct S,
0029                         bool SwapStruct) {
0030   if (SwapStruct)
0031     MachO::swapStruct(S);
0032   assert(Offset + sizeof(MachOStruct) <= Buf.size() && "Buffer overflow");
0033   memcpy(&Buf[Offset], reinterpret_cast<const char *>(&S), sizeof(MachOStruct));
0034   return Offset + sizeof(MachOStruct);
0035 }
0036 
0037 /// Base type for MachOBuilder load command wrappers.
0038 struct MachOBuilderLoadCommandBase {
0039   virtual ~MachOBuilderLoadCommandBase() {}
0040   virtual size_t size() const = 0;
0041   virtual size_t write(MutableArrayRef<char> Buf, size_t Offset,
0042                        bool SwapStruct) = 0;
0043 };
0044 
0045 /// MachOBuilder load command wrapper type.
0046 template <MachO::LoadCommandType LCType> struct MachOBuilderLoadCommandImplBase;
0047 
0048 #define HANDLE_LOAD_COMMAND(Name, Value, LCStruct)                             \
0049   template <>                                                                  \
0050   struct MachOBuilderLoadCommandImplBase<MachO::Name>                          \
0051       : public MachO::LCStruct, public MachOBuilderLoadCommandBase {           \
0052     using CmdStruct = LCStruct;                                                \
0053     MachOBuilderLoadCommandImplBase() {                                        \
0054       memset(&rawStruct(), 0, sizeof(CmdStruct));                              \
0055       cmd = Value;                                                             \
0056       cmdsize = sizeof(CmdStruct);                                             \
0057     }                                                                          \
0058     template <typename... ArgTs>                                               \
0059     MachOBuilderLoadCommandImplBase(ArgTs &&...Args)                           \
0060         : CmdStruct{Value, sizeof(CmdStruct), std::forward<ArgTs>(Args)...} {} \
0061     CmdStruct &rawStruct() { return static_cast<CmdStruct &>(*this); }         \
0062     size_t size() const override { return cmdsize; }                           \
0063     size_t write(MutableArrayRef<char> Buf, size_t Offset,                     \
0064                  bool SwapStruct) override {                                   \
0065       return writeMachOStruct(Buf, Offset, rawStruct(), SwapStruct);           \
0066     }                                                                          \
0067   };
0068 
0069 #include "llvm/BinaryFormat/MachO.def"
0070 
0071 #undef HANDLE_LOAD_COMMAND
0072 
0073 template <MachO::LoadCommandType LCType>
0074 struct MachOBuilderLoadCommand
0075     : public MachOBuilderLoadCommandImplBase<LCType> {
0076 public:
0077   MachOBuilderLoadCommand() = default;
0078 
0079   template <typename... ArgTs>
0080   MachOBuilderLoadCommand(ArgTs &&...Args)
0081       : MachOBuilderLoadCommandImplBase<LCType>(std::forward<ArgTs>(Args)...) {}
0082 };
0083 
0084 template <>
0085 struct MachOBuilderLoadCommand<MachO::LC_ID_DYLIB>
0086     : public MachOBuilderLoadCommandImplBase<MachO::LC_ID_DYLIB> {
0087 
0088   MachOBuilderLoadCommand(std::string Name, uint32_t Timestamp,
0089                           uint32_t CurrentVersion,
0090                           uint32_t CompatibilityVersion)
0091       : MachOBuilderLoadCommandImplBase(
0092             MachO::dylib{24, Timestamp, CurrentVersion, CompatibilityVersion}),
0093         Name(std::move(Name)) {
0094     cmdsize += (this->Name.size() + 1 + 3) & ~0x3;
0095   }
0096 
0097   size_t write(MutableArrayRef<char> Buf, size_t Offset,
0098                bool SwapStruct) override {
0099     Offset = writeMachOStruct(Buf, Offset, rawStruct(), SwapStruct);
0100     strcpy(Buf.data() + Offset, Name.data());
0101     return Offset + ((Name.size() + 1 + 3) & ~0x3);
0102   }
0103 
0104   std::string Name;
0105 };
0106 
0107 template <>
0108 struct MachOBuilderLoadCommand<MachO::LC_LOAD_DYLIB>
0109     : public MachOBuilderLoadCommandImplBase<MachO::LC_LOAD_DYLIB> {
0110 
0111   MachOBuilderLoadCommand(std::string Name, uint32_t Timestamp,
0112                           uint32_t CurrentVersion,
0113                           uint32_t CompatibilityVersion)
0114       : MachOBuilderLoadCommandImplBase(
0115             MachO::dylib{24, Timestamp, CurrentVersion, CompatibilityVersion}),
0116         Name(std::move(Name)) {
0117     cmdsize += (this->Name.size() + 1 + 3) & ~0x3;
0118   }
0119 
0120   size_t write(MutableArrayRef<char> Buf, size_t Offset,
0121                bool SwapStruct) override {
0122     Offset = writeMachOStruct(Buf, Offset, rawStruct(), SwapStruct);
0123     strcpy(Buf.data() + Offset, Name.data());
0124     return Offset + ((Name.size() + 1 + 3) & ~0x3);
0125   }
0126 
0127   std::string Name;
0128 };
0129 
0130 template <>
0131 struct MachOBuilderLoadCommand<MachO::LC_RPATH>
0132     : public MachOBuilderLoadCommandImplBase<MachO::LC_RPATH> {
0133   MachOBuilderLoadCommand(std::string Path)
0134       : MachOBuilderLoadCommandImplBase(12u), Path(std::move(Path)) {
0135     cmdsize += (this->Path.size() + 1 + 3) & ~0x3;
0136   }
0137 
0138   size_t write(MutableArrayRef<char> Buf, size_t Offset,
0139                bool SwapStruct) override {
0140     Offset = writeMachOStruct(Buf, Offset, rawStruct(), SwapStruct);
0141     strcpy(Buf.data() + Offset, Path.data());
0142     return Offset + ((Path.size() + 1 + 3) & ~0x3);
0143   }
0144 
0145   std::string Path;
0146 };
0147 
0148 // Builds MachO objects.
0149 template <typename MachOTraits> class MachOBuilder {
0150 private:
0151   struct SymbolContainer {
0152     size_t SymbolIndexBase = 0;
0153     std::vector<typename MachOTraits::NList> Symbols;
0154   };
0155 
0156   struct StringTableEntry {
0157     StringRef S;
0158     size_t Offset;
0159   };
0160 
0161   using StringTable = std::vector<StringTableEntry>;
0162 
0163   static bool swapStruct() {
0164     return MachOTraits::Endianness != llvm::endianness::native;
0165   }
0166 
0167 public:
0168   using StringId = size_t;
0169 
0170   struct Section;
0171 
0172   // Points to either an nlist entry (as a (symbol-container, index) pair), or
0173   // a section.
0174   class RelocTarget {
0175   public:
0176     RelocTarget(const Section &S) : S(&S), Idx(~0U) {}
0177     RelocTarget(SymbolContainer &SC, size_t Idx) : SC(&SC), Idx(Idx) {}
0178 
0179     bool isSymbol() { return Idx != ~0U; }
0180 
0181     uint32_t getSymbolNum() {
0182       assert(isSymbol() && "Target is not a symbol");
0183       return SC->SymbolIndexBase + Idx;
0184     }
0185 
0186     uint32_t getSectionId() {
0187       assert(!isSymbol() && "Target is not a section");
0188       return S->SectionNumber;
0189     }
0190 
0191     typename MachOTraits::NList &nlist() {
0192       assert(isSymbol() && "Target is not a symbol");
0193       return SC->Symbols[Idx];
0194     }
0195 
0196   private:
0197     union {
0198       const Section *S;
0199       SymbolContainer *SC;
0200     };
0201     size_t Idx;
0202   };
0203 
0204   struct Reloc : public MachO::relocation_info {
0205     RelocTarget Target;
0206 
0207     Reloc(int32_t Offset, RelocTarget Target, bool PCRel, unsigned Length,
0208           unsigned Type)
0209         : Target(Target) {
0210       assert(Type < 16 && "Relocation type out of range");
0211       r_address = Offset; // Will slide to account for sec addr during layout
0212       r_symbolnum = 0;
0213       r_pcrel = PCRel;
0214       r_length = Length;
0215       r_extern = Target.isSymbol();
0216       r_type = Type;
0217     }
0218 
0219     MachO::relocation_info &rawStruct() {
0220       return static_cast<MachO::relocation_info &>(*this);
0221     }
0222   };
0223 
0224   struct SectionContent {
0225     const char *Data = nullptr;
0226     size_t Size = 0;
0227   };
0228 
0229   struct Section : public MachOTraits::Section, public RelocTarget {
0230     MachOBuilder &Builder;
0231     SectionContent Content;
0232     size_t SectionNumber = 0;
0233     SymbolContainer SC;
0234     std::vector<Reloc> Relocs;
0235 
0236     Section(MachOBuilder &Builder, StringRef SecName, StringRef SegName)
0237         : RelocTarget(*this), Builder(Builder) {
0238       memset(&rawStruct(), 0, sizeof(typename MachOTraits::Section));
0239       assert(SecName.size() <= 16 && "SecName too long");
0240       assert(SegName.size() <= 16 && "SegName too long");
0241       memcpy(this->sectname, SecName.data(), SecName.size());
0242       memcpy(this->segname, SegName.data(), SegName.size());
0243     }
0244 
0245     RelocTarget addSymbol(int32_t Offset, StringRef Name, uint8_t Type,
0246                           uint16_t Desc) {
0247       StringId SI = Builder.addString(Name);
0248       typename MachOTraits::NList Sym;
0249       Sym.n_strx = SI;
0250       Sym.n_type = Type | MachO::N_SECT;
0251       Sym.n_sect = MachO::NO_SECT; // Will be filled in later.
0252       Sym.n_desc = Desc;
0253       Sym.n_value = Offset;
0254       SC.Symbols.push_back(Sym);
0255       return {SC, SC.Symbols.size() - 1};
0256     }
0257 
0258     void addReloc(int32_t Offset, RelocTarget Target, bool PCRel,
0259                   unsigned Length, unsigned Type) {
0260       Relocs.push_back({Offset, Target, PCRel, Length, Type});
0261     }
0262 
0263     auto &rawStruct() {
0264       return static_cast<typename MachOTraits::Section &>(*this);
0265     }
0266   };
0267 
0268   struct Segment : public MachOBuilderLoadCommand<MachOTraits::SegmentCmd> {
0269     MachOBuilder &Builder;
0270     std::vector<std::unique_ptr<Section>> Sections;
0271 
0272     Segment(MachOBuilder &Builder, StringRef SegName)
0273         : MachOBuilderLoadCommand<MachOTraits::SegmentCmd>(), Builder(Builder) {
0274       assert(SegName.size() <= 16 && "SegName too long");
0275       memcpy(this->segname, SegName.data(), SegName.size());
0276       this->maxprot =
0277           MachO::VM_PROT_READ | MachO::VM_PROT_WRITE | MachO::VM_PROT_EXECUTE;
0278       this->initprot = this->maxprot;
0279     }
0280 
0281     Section &addSection(StringRef SecName, StringRef SegName) {
0282       Sections.push_back(std::make_unique<Section>(Builder, SecName, SegName));
0283       return *Sections.back();
0284     }
0285 
0286     size_t write(MutableArrayRef<char> Buf, size_t Offset,
0287                  bool SwapStruct) override {
0288       Offset = MachOBuilderLoadCommand<MachOTraits::SegmentCmd>::write(
0289           Buf, Offset, SwapStruct);
0290       for (auto &Sec : Sections)
0291         Offset = writeMachOStruct(Buf, Offset, Sec->rawStruct(), SwapStruct);
0292       return Offset;
0293     }
0294   };
0295 
0296   MachOBuilder(size_t PageSize) : PageSize(PageSize) {
0297     memset((char *)&Header, 0, sizeof(Header));
0298     Header.magic = MachOTraits::Magic;
0299   }
0300 
0301   template <MachO::LoadCommandType LCType, typename... ArgTs>
0302   MachOBuilderLoadCommand<LCType> &addLoadCommand(ArgTs &&...Args) {
0303     static_assert(LCType != MachOTraits::SegmentCmd,
0304                   "Use addSegment to add segment load command");
0305     auto LC = std::make_unique<MachOBuilderLoadCommand<LCType>>(
0306         std::forward<ArgTs>(Args)...);
0307     auto &Tmp = *LC;
0308     LoadCommands.push_back(std::move(LC));
0309     return Tmp;
0310   }
0311 
0312   StringId addString(StringRef Str) {
0313     if (Strings.empty() && !Str.empty())
0314       addString("");
0315     return Strings.insert(std::make_pair(Str, Strings.size())).first->second;
0316   }
0317 
0318   Segment &addSegment(StringRef SegName) {
0319     Segments.push_back(Segment(*this, SegName));
0320     return Segments.back();
0321   }
0322 
0323   RelocTarget addSymbol(StringRef Name, uint8_t Type, uint8_t Sect,
0324                         uint16_t Desc, typename MachOTraits::UIntPtr Value) {
0325     StringId SI = addString(Name);
0326     typename MachOTraits::NList Sym;
0327     Sym.n_strx = SI;
0328     Sym.n_type = Type;
0329     Sym.n_sect = Sect;
0330     Sym.n_desc = Desc;
0331     Sym.n_value = Value;
0332     SC.Symbols.push_back(Sym);
0333     return {SC, SC.Symbols.size() - 1};
0334   }
0335 
0336   // Call to perform layout on the MachO. Returns the total size of the
0337   // resulting file.
0338   // This method will automatically insert some load commands (e.g.
0339   // LC_SYMTAB) and fill in load command fields.
0340   size_t layout() {
0341 
0342     // Build symbol table and add LC_SYMTAB command.
0343     makeStringTable();
0344     MachOBuilderLoadCommand<MachOTraits::SymTabCmd> *SymTabLC = nullptr;
0345     if (!StrTab.empty())
0346       SymTabLC = &addLoadCommand<MachOTraits::SymTabCmd>();
0347 
0348     // Lay out header, segment load command, and other load commands.
0349     size_t Offset = sizeof(Header);
0350     for (auto &Seg : Segments) {
0351       Seg.cmdsize +=
0352           Seg.Sections.size() * sizeof(typename MachOTraits::Section);
0353       Seg.nsects = Seg.Sections.size();
0354       Offset += Seg.cmdsize;
0355     }
0356     for (auto &LC : LoadCommands)
0357       Offset += LC->size();
0358 
0359     Header.sizeofcmds = Offset - sizeof(Header);
0360 
0361     // Lay out content, set segment / section addrs and offsets.
0362     size_t SegVMAddr = 0;
0363     for (auto &Seg : Segments) {
0364       Seg.vmaddr = SegVMAddr;
0365       Seg.fileoff = Offset;
0366       for (auto &Sec : Seg.Sections) {
0367         Offset = alignTo(Offset, 1ULL << Sec->align);
0368         if (Sec->Content.Size)
0369           Sec->offset = Offset;
0370         Sec->size = Sec->Content.Size;
0371         Sec->addr = SegVMAddr + Sec->offset - Seg.fileoff;
0372         Offset += Sec->Content.Size;
0373       }
0374       size_t SegContentSize = Offset - Seg.fileoff;
0375       Seg.filesize = SegContentSize;
0376       Seg.vmsize = Header.filetype == MachO::MH_OBJECT
0377                        ? SegContentSize
0378                        : alignTo(SegContentSize, PageSize);
0379       SegVMAddr += Seg.vmsize;
0380     }
0381 
0382     // Set string table offsets for non-section symbols.
0383     for (auto &Sym : SC.Symbols)
0384       Sym.n_strx = StrTab[Sym.n_strx].Offset;
0385 
0386     // Number sections, set symbol section numbers and string table offsets,
0387     // count relocations.
0388     size_t NumSymbols = SC.Symbols.size();
0389     size_t SectionNumber = 0;
0390     for (auto &Seg : Segments) {
0391       for (auto &Sec : Seg.Sections) {
0392         ++SectionNumber;
0393         Sec->SectionNumber = SectionNumber;
0394         Sec->SC.SymbolIndexBase = NumSymbols;
0395         NumSymbols += Sec->SC.Symbols.size();
0396         for (auto &Sym : Sec->SC.Symbols) {
0397           Sym.n_sect = SectionNumber;
0398           Sym.n_strx = StrTab[Sym.n_strx].Offset;
0399           Sym.n_value += Sec->addr;
0400         }
0401       }
0402     }
0403 
0404     // Handle relocations
0405     bool OffsetAlignedForRelocs = false;
0406     for (auto &Seg : Segments) {
0407       for (auto &Sec : Seg.Sections) {
0408         if (!Sec->Relocs.empty()) {
0409           if (!OffsetAlignedForRelocs) {
0410             Offset = alignTo(Offset, sizeof(MachO::relocation_info));
0411             OffsetAlignedForRelocs = true;
0412           }
0413           Sec->reloff = Offset;
0414           Sec->nreloc = Sec->Relocs.size();
0415           Offset += Sec->Relocs.size() * sizeof(MachO::relocation_info);
0416           for (auto &R : Sec->Relocs)
0417             R.r_symbolnum = R.Target.isSymbol() ? R.Target.getSymbolNum()
0418                                                 : R.Target.getSectionId();
0419         }
0420       }
0421     }
0422 
0423     // Calculate offset to start of nlist and update symtab command.
0424     if (NumSymbols > 0) {
0425       Offset = alignTo(Offset, sizeof(typename MachOTraits::NList));
0426       SymTabLC->symoff = Offset;
0427       SymTabLC->nsyms = NumSymbols;
0428 
0429       // Calculate string table bounds and update symtab command.
0430       if (!StrTab.empty()) {
0431         Offset += NumSymbols * sizeof(typename MachOTraits::NList);
0432         size_t StringTableSize =
0433             StrTab.back().Offset + StrTab.back().S.size() + 1;
0434 
0435         SymTabLC->stroff = Offset;
0436         SymTabLC->strsize = StringTableSize;
0437         Offset += StringTableSize;
0438       }
0439     }
0440 
0441     return Offset;
0442   }
0443 
0444   void write(MutableArrayRef<char> Buffer) {
0445     size_t Offset = 0;
0446     Offset = writeHeader(Buffer, Offset);
0447     Offset = writeSegments(Buffer, Offset);
0448     Offset = writeLoadCommands(Buffer, Offset);
0449     Offset = writeSectionContent(Buffer, Offset);
0450     Offset = writeRelocations(Buffer, Offset);
0451     Offset = writeSymbols(Buffer, Offset);
0452     Offset = writeStrings(Buffer, Offset);
0453   }
0454 
0455   typename MachOTraits::Header Header;
0456 
0457 private:
0458   void makeStringTable() {
0459     if (Strings.empty())
0460       return;
0461 
0462     StrTab.resize(Strings.size());
0463     for (auto &[Str, Idx] : Strings)
0464       StrTab[Idx] = {Str, 0};
0465     size_t Offset = 0;
0466     for (auto &Elem : StrTab) {
0467       Elem.Offset = Offset;
0468       Offset += Elem.S.size() + 1;
0469     }
0470   }
0471 
0472   size_t writeHeader(MutableArrayRef<char> Buf, size_t Offset) {
0473     Header.ncmds = Segments.size() + LoadCommands.size();
0474     return writeMachOStruct(Buf, Offset, Header, swapStruct());
0475   }
0476 
0477   size_t writeSegments(MutableArrayRef<char> Buf, size_t Offset) {
0478     for (auto &Seg : Segments)
0479       Offset = Seg.write(Buf, Offset, swapStruct());
0480     return Offset;
0481   }
0482 
0483   size_t writeLoadCommands(MutableArrayRef<char> Buf, size_t Offset) {
0484     for (auto &LC : LoadCommands)
0485       Offset = LC->write(Buf, Offset, swapStruct());
0486     return Offset;
0487   }
0488 
0489   size_t writeSectionContent(MutableArrayRef<char> Buf, size_t Offset) {
0490     for (auto &Seg : Segments) {
0491       for (auto &Sec : Seg.Sections) {
0492         if (!Sec->Content.Data) {
0493           assert(Sec->Relocs.empty() &&
0494                  "Cant' have relocs for zero-fill segment");
0495           continue;
0496         }
0497         while (Offset != Sec->offset)
0498           Buf[Offset++] = '\0';
0499 
0500         assert(Offset + Sec->Content.Size <= Buf.size() && "Buffer overflow");
0501         memcpy(&Buf[Offset], Sec->Content.Data, Sec->Content.Size);
0502         Offset += Sec->Content.Size;
0503       }
0504     }
0505     return Offset;
0506   }
0507 
0508   size_t writeRelocations(MutableArrayRef<char> Buf, size_t Offset) {
0509     for (auto &Seg : Segments) {
0510       for (auto &Sec : Seg.Sections) {
0511         if (!Sec->Relocs.empty()) {
0512           while (Offset % sizeof(MachO::relocation_info))
0513             Buf[Offset++] = '\0';
0514         }
0515         for (auto &R : Sec->Relocs) {
0516           assert(Offset + sizeof(MachO::relocation_info) <= Buf.size() &&
0517                  "Buffer overflow");
0518           memcpy(&Buf[Offset], reinterpret_cast<const char *>(&R.rawStruct()),
0519                  sizeof(MachO::relocation_info));
0520           Offset += sizeof(MachO::relocation_info);
0521         }
0522       }
0523     }
0524     return Offset;
0525   }
0526 
0527   size_t writeSymbols(MutableArrayRef<char> Buf, size_t Offset) {
0528 
0529     // Count symbols.
0530     size_t NumSymbols = SC.Symbols.size();
0531     for (auto &Seg : Segments)
0532       for (auto &Sec : Seg.Sections)
0533         NumSymbols += Sec->SC.Symbols.size();
0534 
0535     // If none then return.
0536     if (NumSymbols == 0)
0537       return Offset;
0538 
0539     // Align to nlist entry size.
0540     while (Offset % sizeof(typename MachOTraits::NList))
0541       Buf[Offset++] = '\0';
0542 
0543     // Write non-section symbols.
0544     for (auto &Sym : SC.Symbols)
0545       Offset = writeMachOStruct(Buf, Offset, Sym, swapStruct());
0546 
0547     // Write section symbols.
0548     for (auto &Seg : Segments) {
0549       for (auto &Sec : Seg.Sections) {
0550         for (auto &Sym : Sec->SC.Symbols) {
0551           Offset = writeMachOStruct(Buf, Offset, Sym, swapStruct());
0552         }
0553       }
0554     }
0555     return Offset;
0556   }
0557 
0558   size_t writeStrings(MutableArrayRef<char> Buf, size_t Offset) {
0559     for (auto &Elem : StrTab) {
0560       assert(Offset + Elem.S.size() + 1 <= Buf.size() && "Buffer overflow");
0561       memcpy(&Buf[Offset], Elem.S.data(), Elem.S.size());
0562       Offset += Elem.S.size();
0563       Buf[Offset++] = '\0';
0564     }
0565     return Offset;
0566   }
0567 
0568   size_t PageSize;
0569   std::list<Segment> Segments;
0570   std::vector<std::unique_ptr<MachOBuilderLoadCommandBase>> LoadCommands;
0571   SymbolContainer SC;
0572 
0573   // Maps strings to their "id" (addition order).
0574   std::map<StringRef, size_t> Strings;
0575   StringTable StrTab;
0576 };
0577 
0578 struct MachO64LE {
0579   using UIntPtr = uint64_t;
0580   using Header = MachO::mach_header_64;
0581   using Section = MachO::section_64;
0582   using NList = MachO::nlist_64;
0583   using Relocation = MachO::relocation_info;
0584 
0585   static constexpr llvm::endianness Endianness = llvm::endianness::little;
0586   static constexpr uint32_t Magic = MachO::MH_MAGIC_64;
0587   static constexpr MachO::LoadCommandType SegmentCmd = MachO::LC_SEGMENT_64;
0588   static constexpr MachO::LoadCommandType SymTabCmd = MachO::LC_SYMTAB;
0589 };
0590 
0591 } // namespace orc
0592 } // namespace llvm
0593 
0594 #endif // LLVM_EXECUTIONENGINE_ORC_MACHOBUILDER_H