xref: /freebsd-src/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/MachOBuilder.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
15f757f3fSDimitry Andric //===------------ MachOBuilder.h -- Build MachO Objects ---------*- C++ -*-===//
25f757f3fSDimitry Andric //
35f757f3fSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45f757f3fSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55f757f3fSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65f757f3fSDimitry Andric //
75f757f3fSDimitry Andric //===----------------------------------------------------------------------===//
85f757f3fSDimitry Andric //
95f757f3fSDimitry Andric // Build MachO object files for interaction with the ObjC runtime and debugger.
105f757f3fSDimitry Andric //
115f757f3fSDimitry Andric //===----------------------------------------------------------------------===//
125f757f3fSDimitry Andric 
135f757f3fSDimitry Andric #ifndef LLVM_EXECUTIONENGINE_ORC_MACHOBUILDER_H
145f757f3fSDimitry Andric #define LLVM_EXECUTIONENGINE_ORC_MACHOBUILDER_H
155f757f3fSDimitry Andric 
165f757f3fSDimitry Andric #include "llvm/BinaryFormat/MachO.h"
175f757f3fSDimitry Andric #include "llvm/Support/Endian.h"
185f757f3fSDimitry Andric #include "llvm/Support/MathExtras.h"
195f757f3fSDimitry Andric 
205f757f3fSDimitry Andric #include <list>
215f757f3fSDimitry Andric #include <map>
225f757f3fSDimitry Andric #include <vector>
235f757f3fSDimitry Andric 
245f757f3fSDimitry Andric namespace llvm {
255f757f3fSDimitry Andric namespace orc {
265f757f3fSDimitry Andric 
275f757f3fSDimitry Andric template <typename MachOStruct>
285f757f3fSDimitry Andric size_t writeMachOStruct(MutableArrayRef<char> Buf, size_t Offset, MachOStruct S,
295f757f3fSDimitry Andric                         bool SwapStruct) {
305f757f3fSDimitry Andric   if (SwapStruct)
315f757f3fSDimitry Andric     MachO::swapStruct(S);
325f757f3fSDimitry Andric   assert(Offset + sizeof(MachOStruct) <= Buf.size() && "Buffer overflow");
335f757f3fSDimitry Andric   memcpy(&Buf[Offset], reinterpret_cast<const char *>(&S), sizeof(MachOStruct));
345f757f3fSDimitry Andric   return Offset + sizeof(MachOStruct);
355f757f3fSDimitry Andric }
365f757f3fSDimitry Andric 
375f757f3fSDimitry Andric /// Base type for MachOBuilder load command wrappers.
385f757f3fSDimitry Andric struct MachOBuilderLoadCommandBase {
395f757f3fSDimitry Andric   virtual ~MachOBuilderLoadCommandBase() {}
405f757f3fSDimitry Andric   virtual size_t size() const = 0;
415f757f3fSDimitry Andric   virtual size_t write(MutableArrayRef<char> Buf, size_t Offset,
425f757f3fSDimitry Andric                        bool SwapStruct) = 0;
435f757f3fSDimitry Andric };
445f757f3fSDimitry Andric 
455f757f3fSDimitry Andric /// MachOBuilder load command wrapper type.
467a6dacacSDimitry Andric template <MachO::LoadCommandType LCType> struct MachOBuilderLoadCommandImplBase;
475f757f3fSDimitry Andric 
485f757f3fSDimitry Andric #define HANDLE_LOAD_COMMAND(Name, Value, LCStruct)                             \
495f757f3fSDimitry Andric   template <>                                                                  \
507a6dacacSDimitry Andric   struct MachOBuilderLoadCommandImplBase<MachO::Name>                          \
515f757f3fSDimitry Andric       : public MachO::LCStruct, public MachOBuilderLoadCommandBase {           \
525f757f3fSDimitry Andric     using CmdStruct = LCStruct;                                                \
537a6dacacSDimitry Andric     MachOBuilderLoadCommandImplBase() {                                        \
545f757f3fSDimitry Andric       memset(&rawStruct(), 0, sizeof(CmdStruct));                              \
555f757f3fSDimitry Andric       cmd = Value;                                                             \
565f757f3fSDimitry Andric       cmdsize = sizeof(CmdStruct);                                             \
575f757f3fSDimitry Andric     }                                                                          \
585f757f3fSDimitry Andric     template <typename... ArgTs>                                               \
597a6dacacSDimitry Andric     MachOBuilderLoadCommandImplBase(ArgTs &&...Args)                           \
605f757f3fSDimitry Andric         : CmdStruct{Value, sizeof(CmdStruct), std::forward<ArgTs>(Args)...} {} \
615f757f3fSDimitry Andric     CmdStruct &rawStruct() { return static_cast<CmdStruct &>(*this); }         \
625f757f3fSDimitry Andric     size_t size() const override { return cmdsize; }                           \
635f757f3fSDimitry Andric     size_t write(MutableArrayRef<char> Buf, size_t Offset,                     \
645f757f3fSDimitry Andric                  bool SwapStruct) override {                                   \
655f757f3fSDimitry Andric       return writeMachOStruct(Buf, Offset, rawStruct(), SwapStruct);           \
665f757f3fSDimitry Andric     }                                                                          \
675f757f3fSDimitry Andric   };
685f757f3fSDimitry Andric 
695f757f3fSDimitry Andric #include "llvm/BinaryFormat/MachO.def"
705f757f3fSDimitry Andric 
715f757f3fSDimitry Andric #undef HANDLE_LOAD_COMMAND
725f757f3fSDimitry Andric 
737a6dacacSDimitry Andric template <MachO::LoadCommandType LCType>
747a6dacacSDimitry Andric struct MachOBuilderLoadCommand
757a6dacacSDimitry Andric     : public MachOBuilderLoadCommandImplBase<LCType> {
767a6dacacSDimitry Andric public:
777a6dacacSDimitry Andric   MachOBuilderLoadCommand() = default;
787a6dacacSDimitry Andric 
797a6dacacSDimitry Andric   template <typename... ArgTs>
807a6dacacSDimitry Andric   MachOBuilderLoadCommand(ArgTs &&...Args)
81*0fca6ea1SDimitry Andric       : MachOBuilderLoadCommandImplBase<LCType>(std::forward<ArgTs>(Args)...) {}
827a6dacacSDimitry Andric };
837a6dacacSDimitry Andric 
847a6dacacSDimitry Andric template <>
857a6dacacSDimitry Andric struct MachOBuilderLoadCommand<MachO::LC_ID_DYLIB>
867a6dacacSDimitry Andric     : public MachOBuilderLoadCommandImplBase<MachO::LC_ID_DYLIB> {
877a6dacacSDimitry Andric 
887a6dacacSDimitry Andric   MachOBuilderLoadCommand(std::string Name, uint32_t Timestamp,
897a6dacacSDimitry Andric                           uint32_t CurrentVersion,
907a6dacacSDimitry Andric                           uint32_t CompatibilityVersion)
917a6dacacSDimitry Andric       : MachOBuilderLoadCommandImplBase(
927a6dacacSDimitry Andric             MachO::dylib{24, Timestamp, CurrentVersion, CompatibilityVersion}),
937a6dacacSDimitry Andric         Name(std::move(Name)) {
947a6dacacSDimitry Andric     cmdsize += (this->Name.size() + 1 + 3) & ~0x3;
957a6dacacSDimitry Andric   }
967a6dacacSDimitry Andric 
977a6dacacSDimitry Andric   size_t write(MutableArrayRef<char> Buf, size_t Offset,
987a6dacacSDimitry Andric                bool SwapStruct) override {
997a6dacacSDimitry Andric     Offset = writeMachOStruct(Buf, Offset, rawStruct(), SwapStruct);
1007a6dacacSDimitry Andric     strcpy(Buf.data() + Offset, Name.data());
1017a6dacacSDimitry Andric     return Offset + ((Name.size() + 1 + 3) & ~0x3);
1027a6dacacSDimitry Andric   }
1037a6dacacSDimitry Andric 
1047a6dacacSDimitry Andric   std::string Name;
1057a6dacacSDimitry Andric };
1067a6dacacSDimitry Andric 
1077a6dacacSDimitry Andric template <>
1087a6dacacSDimitry Andric struct MachOBuilderLoadCommand<MachO::LC_LOAD_DYLIB>
1097a6dacacSDimitry Andric     : public MachOBuilderLoadCommandImplBase<MachO::LC_LOAD_DYLIB> {
1107a6dacacSDimitry Andric 
1117a6dacacSDimitry Andric   MachOBuilderLoadCommand(std::string Name, uint32_t Timestamp,
1127a6dacacSDimitry Andric                           uint32_t CurrentVersion,
1137a6dacacSDimitry Andric                           uint32_t CompatibilityVersion)
1147a6dacacSDimitry Andric       : MachOBuilderLoadCommandImplBase(
1157a6dacacSDimitry Andric             MachO::dylib{24, Timestamp, CurrentVersion, CompatibilityVersion}),
1167a6dacacSDimitry Andric         Name(std::move(Name)) {
1177a6dacacSDimitry Andric     cmdsize += (this->Name.size() + 1 + 3) & ~0x3;
1187a6dacacSDimitry Andric   }
1197a6dacacSDimitry Andric 
1207a6dacacSDimitry Andric   size_t write(MutableArrayRef<char> Buf, size_t Offset,
1217a6dacacSDimitry Andric                bool SwapStruct) override {
1227a6dacacSDimitry Andric     Offset = writeMachOStruct(Buf, Offset, rawStruct(), SwapStruct);
1237a6dacacSDimitry Andric     strcpy(Buf.data() + Offset, Name.data());
1247a6dacacSDimitry Andric     return Offset + ((Name.size() + 1 + 3) & ~0x3);
1257a6dacacSDimitry Andric   }
1267a6dacacSDimitry Andric 
1277a6dacacSDimitry Andric   std::string Name;
1287a6dacacSDimitry Andric };
1297a6dacacSDimitry Andric 
1307a6dacacSDimitry Andric template <>
1317a6dacacSDimitry Andric struct MachOBuilderLoadCommand<MachO::LC_RPATH>
1327a6dacacSDimitry Andric     : public MachOBuilderLoadCommandImplBase<MachO::LC_RPATH> {
1337a6dacacSDimitry Andric   MachOBuilderLoadCommand(std::string Path)
1347a6dacacSDimitry Andric       : MachOBuilderLoadCommandImplBase(12u), Path(std::move(Path)) {
1357a6dacacSDimitry Andric     cmdsize += (this->Path.size() + 1 + 3) & ~0x3;
1367a6dacacSDimitry Andric   }
1377a6dacacSDimitry Andric 
1387a6dacacSDimitry Andric   size_t write(MutableArrayRef<char> Buf, size_t Offset,
1397a6dacacSDimitry Andric                bool SwapStruct) override {
1407a6dacacSDimitry Andric     Offset = writeMachOStruct(Buf, Offset, rawStruct(), SwapStruct);
1417a6dacacSDimitry Andric     strcpy(Buf.data() + Offset, Path.data());
1427a6dacacSDimitry Andric     return Offset + ((Path.size() + 1 + 3) & ~0x3);
1437a6dacacSDimitry Andric   }
1447a6dacacSDimitry Andric 
1457a6dacacSDimitry Andric   std::string Path;
1467a6dacacSDimitry Andric };
1477a6dacacSDimitry Andric 
1485f757f3fSDimitry Andric // Builds MachO objects.
1495f757f3fSDimitry Andric template <typename MachOTraits> class MachOBuilder {
1505f757f3fSDimitry Andric private:
1515f757f3fSDimitry Andric   struct SymbolContainer {
1525f757f3fSDimitry Andric     size_t SymbolIndexBase = 0;
1535f757f3fSDimitry Andric     std::vector<typename MachOTraits::NList> Symbols;
1545f757f3fSDimitry Andric   };
1555f757f3fSDimitry Andric 
1565f757f3fSDimitry Andric   struct StringTableEntry {
1575f757f3fSDimitry Andric     StringRef S;
1585f757f3fSDimitry Andric     size_t Offset;
1595f757f3fSDimitry Andric   };
1605f757f3fSDimitry Andric 
1615f757f3fSDimitry Andric   using StringTable = std::vector<StringTableEntry>;
1625f757f3fSDimitry Andric 
1635f757f3fSDimitry Andric   static bool swapStruct() {
1645f757f3fSDimitry Andric     return MachOTraits::Endianness != llvm::endianness::native;
1655f757f3fSDimitry Andric   }
1665f757f3fSDimitry Andric 
1675f757f3fSDimitry Andric public:
1685f757f3fSDimitry Andric   using StringId = size_t;
1695f757f3fSDimitry Andric 
1705f757f3fSDimitry Andric   struct Section;
1715f757f3fSDimitry Andric 
1725f757f3fSDimitry Andric   // Points to either an nlist entry (as a (symbol-container, index) pair), or
1735f757f3fSDimitry Andric   // a section.
1745f757f3fSDimitry Andric   class RelocTarget {
1755f757f3fSDimitry Andric   public:
1765f757f3fSDimitry Andric     RelocTarget(const Section &S) : S(&S), Idx(~0U) {}
1775f757f3fSDimitry Andric     RelocTarget(SymbolContainer &SC, size_t Idx) : SC(&SC), Idx(Idx) {}
1785f757f3fSDimitry Andric 
1795f757f3fSDimitry Andric     bool isSymbol() { return Idx != ~0U; }
1805f757f3fSDimitry Andric 
1815f757f3fSDimitry Andric     uint32_t getSymbolNum() {
1825f757f3fSDimitry Andric       assert(isSymbol() && "Target is not a symbol");
1835f757f3fSDimitry Andric       return SC->SymbolIndexBase + Idx;
1845f757f3fSDimitry Andric     }
1855f757f3fSDimitry Andric 
1865f757f3fSDimitry Andric     uint32_t getSectionId() {
1875f757f3fSDimitry Andric       assert(!isSymbol() && "Target is not a section");
1885f757f3fSDimitry Andric       return S->SectionNumber;
1895f757f3fSDimitry Andric     }
1905f757f3fSDimitry Andric 
1915f757f3fSDimitry Andric     typename MachOTraits::NList &nlist() {
1925f757f3fSDimitry Andric       assert(isSymbol() && "Target is not a symbol");
1935f757f3fSDimitry Andric       return SC->Symbols[Idx];
1945f757f3fSDimitry Andric     }
1955f757f3fSDimitry Andric 
1965f757f3fSDimitry Andric   private:
1975f757f3fSDimitry Andric     union {
1985f757f3fSDimitry Andric       const Section *S;
1995f757f3fSDimitry Andric       SymbolContainer *SC;
2005f757f3fSDimitry Andric     };
2015f757f3fSDimitry Andric     size_t Idx;
2025f757f3fSDimitry Andric   };
2035f757f3fSDimitry Andric 
2045f757f3fSDimitry Andric   struct Reloc : public MachO::relocation_info {
2055f757f3fSDimitry Andric     RelocTarget Target;
2065f757f3fSDimitry Andric 
2075f757f3fSDimitry Andric     Reloc(int32_t Offset, RelocTarget Target, bool PCRel, unsigned Length,
2085f757f3fSDimitry Andric           unsigned Type)
2095f757f3fSDimitry Andric         : Target(Target) {
2105f757f3fSDimitry Andric       assert(Type < 16 && "Relocation type out of range");
2115f757f3fSDimitry Andric       r_address = Offset; // Will slide to account for sec addr during layout
2125f757f3fSDimitry Andric       r_symbolnum = 0;
2135f757f3fSDimitry Andric       r_pcrel = PCRel;
2145f757f3fSDimitry Andric       r_length = Length;
2155f757f3fSDimitry Andric       r_extern = Target.isSymbol();
2165f757f3fSDimitry Andric       r_type = Type;
2175f757f3fSDimitry Andric     }
2185f757f3fSDimitry Andric 
2195f757f3fSDimitry Andric     MachO::relocation_info &rawStruct() {
2205f757f3fSDimitry Andric       return static_cast<MachO::relocation_info &>(*this);
2215f757f3fSDimitry Andric     }
2225f757f3fSDimitry Andric   };
2235f757f3fSDimitry Andric 
2245f757f3fSDimitry Andric   struct SectionContent {
2255f757f3fSDimitry Andric     const char *Data = nullptr;
2265f757f3fSDimitry Andric     size_t Size = 0;
2275f757f3fSDimitry Andric   };
2285f757f3fSDimitry Andric 
2295f757f3fSDimitry Andric   struct Section : public MachOTraits::Section, public RelocTarget {
2305f757f3fSDimitry Andric     MachOBuilder &Builder;
2315f757f3fSDimitry Andric     SectionContent Content;
2325f757f3fSDimitry Andric     size_t SectionNumber = 0;
2335f757f3fSDimitry Andric     SymbolContainer SC;
2345f757f3fSDimitry Andric     std::vector<Reloc> Relocs;
2355f757f3fSDimitry Andric 
2365f757f3fSDimitry Andric     Section(MachOBuilder &Builder, StringRef SecName, StringRef SegName)
2375f757f3fSDimitry Andric         : RelocTarget(*this), Builder(Builder) {
2385f757f3fSDimitry Andric       memset(&rawStruct(), 0, sizeof(typename MachOTraits::Section));
2395f757f3fSDimitry Andric       assert(SecName.size() <= 16 && "SecName too long");
2405f757f3fSDimitry Andric       assert(SegName.size() <= 16 && "SegName too long");
2415f757f3fSDimitry Andric       memcpy(this->sectname, SecName.data(), SecName.size());
2425f757f3fSDimitry Andric       memcpy(this->segname, SegName.data(), SegName.size());
2435f757f3fSDimitry Andric     }
2445f757f3fSDimitry Andric 
2455f757f3fSDimitry Andric     RelocTarget addSymbol(int32_t Offset, StringRef Name, uint8_t Type,
2465f757f3fSDimitry Andric                           uint16_t Desc) {
2475f757f3fSDimitry Andric       StringId SI = Builder.addString(Name);
2485f757f3fSDimitry Andric       typename MachOTraits::NList Sym;
2495f757f3fSDimitry Andric       Sym.n_strx = SI;
2505f757f3fSDimitry Andric       Sym.n_type = Type | MachO::N_SECT;
2515f757f3fSDimitry Andric       Sym.n_sect = MachO::NO_SECT; // Will be filled in later.
2525f757f3fSDimitry Andric       Sym.n_desc = Desc;
2535f757f3fSDimitry Andric       Sym.n_value = Offset;
2545f757f3fSDimitry Andric       SC.Symbols.push_back(Sym);
2555f757f3fSDimitry Andric       return {SC, SC.Symbols.size() - 1};
2565f757f3fSDimitry Andric     }
2575f757f3fSDimitry Andric 
2585f757f3fSDimitry Andric     void addReloc(int32_t Offset, RelocTarget Target, bool PCRel,
2595f757f3fSDimitry Andric                   unsigned Length, unsigned Type) {
2605f757f3fSDimitry Andric       Relocs.push_back({Offset, Target, PCRel, Length, Type});
2615f757f3fSDimitry Andric     }
2625f757f3fSDimitry Andric 
2635f757f3fSDimitry Andric     auto &rawStruct() {
2645f757f3fSDimitry Andric       return static_cast<typename MachOTraits::Section &>(*this);
2655f757f3fSDimitry Andric     }
2665f757f3fSDimitry Andric   };
2675f757f3fSDimitry Andric 
2685f757f3fSDimitry Andric   struct Segment : public MachOBuilderLoadCommand<MachOTraits::SegmentCmd> {
2695f757f3fSDimitry Andric     MachOBuilder &Builder;
2705f757f3fSDimitry Andric     std::vector<std::unique_ptr<Section>> Sections;
2715f757f3fSDimitry Andric 
2725f757f3fSDimitry Andric     Segment(MachOBuilder &Builder, StringRef SegName)
2735f757f3fSDimitry Andric         : MachOBuilderLoadCommand<MachOTraits::SegmentCmd>(), Builder(Builder) {
2745f757f3fSDimitry Andric       assert(SegName.size() <= 16 && "SegName too long");
2755f757f3fSDimitry Andric       memcpy(this->segname, SegName.data(), SegName.size());
2765f757f3fSDimitry Andric       this->maxprot =
2775f757f3fSDimitry Andric           MachO::VM_PROT_READ | MachO::VM_PROT_WRITE | MachO::VM_PROT_EXECUTE;
2785f757f3fSDimitry Andric       this->initprot = this->maxprot;
2795f757f3fSDimitry Andric     }
2805f757f3fSDimitry Andric 
2815f757f3fSDimitry Andric     Section &addSection(StringRef SecName, StringRef SegName) {
2825f757f3fSDimitry Andric       Sections.push_back(std::make_unique<Section>(Builder, SecName, SegName));
2835f757f3fSDimitry Andric       return *Sections.back();
2845f757f3fSDimitry Andric     }
2855f757f3fSDimitry Andric 
2865f757f3fSDimitry Andric     size_t write(MutableArrayRef<char> Buf, size_t Offset,
2875f757f3fSDimitry Andric                  bool SwapStruct) override {
2885f757f3fSDimitry Andric       Offset = MachOBuilderLoadCommand<MachOTraits::SegmentCmd>::write(
2895f757f3fSDimitry Andric           Buf, Offset, SwapStruct);
2905f757f3fSDimitry Andric       for (auto &Sec : Sections)
2915f757f3fSDimitry Andric         Offset = writeMachOStruct(Buf, Offset, Sec->rawStruct(), SwapStruct);
2925f757f3fSDimitry Andric       return Offset;
2935f757f3fSDimitry Andric     }
2945f757f3fSDimitry Andric   };
2955f757f3fSDimitry Andric 
2965f757f3fSDimitry Andric   MachOBuilder(size_t PageSize) : PageSize(PageSize) {
2975f757f3fSDimitry Andric     memset((char *)&Header, 0, sizeof(Header));
2985f757f3fSDimitry Andric     Header.magic = MachOTraits::Magic;
2995f757f3fSDimitry Andric   }
3005f757f3fSDimitry Andric 
3015f757f3fSDimitry Andric   template <MachO::LoadCommandType LCType, typename... ArgTs>
3025f757f3fSDimitry Andric   MachOBuilderLoadCommand<LCType> &addLoadCommand(ArgTs &&...Args) {
3035f757f3fSDimitry Andric     static_assert(LCType != MachOTraits::SegmentCmd,
3045f757f3fSDimitry Andric                   "Use addSegment to add segment load command");
3055f757f3fSDimitry Andric     auto LC = std::make_unique<MachOBuilderLoadCommand<LCType>>(
3065f757f3fSDimitry Andric         std::forward<ArgTs>(Args)...);
3075f757f3fSDimitry Andric     auto &Tmp = *LC;
3085f757f3fSDimitry Andric     LoadCommands.push_back(std::move(LC));
3095f757f3fSDimitry Andric     return Tmp;
3105f757f3fSDimitry Andric   }
3115f757f3fSDimitry Andric 
3125f757f3fSDimitry Andric   StringId addString(StringRef Str) {
3135f757f3fSDimitry Andric     if (Strings.empty() && !Str.empty())
3145f757f3fSDimitry Andric       addString("");
3155f757f3fSDimitry Andric     return Strings.insert(std::make_pair(Str, Strings.size())).first->second;
3165f757f3fSDimitry Andric   }
3175f757f3fSDimitry Andric 
3185f757f3fSDimitry Andric   Segment &addSegment(StringRef SegName) {
3195f757f3fSDimitry Andric     Segments.push_back(Segment(*this, SegName));
3205f757f3fSDimitry Andric     return Segments.back();
3215f757f3fSDimitry Andric   }
3225f757f3fSDimitry Andric 
3235f757f3fSDimitry Andric   RelocTarget addSymbol(StringRef Name, uint8_t Type, uint8_t Sect,
3245f757f3fSDimitry Andric                         uint16_t Desc, typename MachOTraits::UIntPtr Value) {
3255f757f3fSDimitry Andric     StringId SI = addString(Name);
3265f757f3fSDimitry Andric     typename MachOTraits::NList Sym;
3275f757f3fSDimitry Andric     Sym.n_strx = SI;
3285f757f3fSDimitry Andric     Sym.n_type = Type;
3295f757f3fSDimitry Andric     Sym.n_sect = Sect;
3305f757f3fSDimitry Andric     Sym.n_desc = Desc;
3315f757f3fSDimitry Andric     Sym.n_value = Value;
3325f757f3fSDimitry Andric     SC.Symbols.push_back(Sym);
3335f757f3fSDimitry Andric     return {SC, SC.Symbols.size() - 1};
3345f757f3fSDimitry Andric   }
3355f757f3fSDimitry Andric 
3365f757f3fSDimitry Andric   // Call to perform layout on the MachO. Returns the total size of the
3375f757f3fSDimitry Andric   // resulting file.
3385f757f3fSDimitry Andric   // This method will automatically insert some load commands (e.g.
3395f757f3fSDimitry Andric   // LC_SYMTAB) and fill in load command fields.
3405f757f3fSDimitry Andric   size_t layout() {
3415f757f3fSDimitry Andric 
3425f757f3fSDimitry Andric     // Build symbol table and add LC_SYMTAB command.
3435f757f3fSDimitry Andric     makeStringTable();
3445f757f3fSDimitry Andric     MachOBuilderLoadCommand<MachOTraits::SymTabCmd> *SymTabLC = nullptr;
3455f757f3fSDimitry Andric     if (!StrTab.empty())
3465f757f3fSDimitry Andric       SymTabLC = &addLoadCommand<MachOTraits::SymTabCmd>();
3475f757f3fSDimitry Andric 
3485f757f3fSDimitry Andric     // Lay out header, segment load command, and other load commands.
3495f757f3fSDimitry Andric     size_t Offset = sizeof(Header);
3505f757f3fSDimitry Andric     for (auto &Seg : Segments) {
3515f757f3fSDimitry Andric       Seg.cmdsize +=
3525f757f3fSDimitry Andric           Seg.Sections.size() * sizeof(typename MachOTraits::Section);
3535f757f3fSDimitry Andric       Seg.nsects = Seg.Sections.size();
3545f757f3fSDimitry Andric       Offset += Seg.cmdsize;
3555f757f3fSDimitry Andric     }
3565f757f3fSDimitry Andric     for (auto &LC : LoadCommands)
3575f757f3fSDimitry Andric       Offset += LC->size();
3585f757f3fSDimitry Andric 
3595f757f3fSDimitry Andric     Header.sizeofcmds = Offset - sizeof(Header);
3605f757f3fSDimitry Andric 
3615f757f3fSDimitry Andric     // Lay out content, set segment / section addrs and offsets.
3625f757f3fSDimitry Andric     size_t SegVMAddr = 0;
3635f757f3fSDimitry Andric     for (auto &Seg : Segments) {
3645f757f3fSDimitry Andric       Seg.vmaddr = SegVMAddr;
3655f757f3fSDimitry Andric       Seg.fileoff = Offset;
3665f757f3fSDimitry Andric       for (auto &Sec : Seg.Sections) {
367*0fca6ea1SDimitry Andric         Offset = alignTo(Offset, 1ULL << Sec->align);
3685f757f3fSDimitry Andric         if (Sec->Content.Size)
3695f757f3fSDimitry Andric           Sec->offset = Offset;
3705f757f3fSDimitry Andric         Sec->size = Sec->Content.Size;
3715f757f3fSDimitry Andric         Sec->addr = SegVMAddr + Sec->offset - Seg.fileoff;
3725f757f3fSDimitry Andric         Offset += Sec->Content.Size;
3735f757f3fSDimitry Andric       }
3745f757f3fSDimitry Andric       size_t SegContentSize = Offset - Seg.fileoff;
3755f757f3fSDimitry Andric       Seg.filesize = SegContentSize;
3765f757f3fSDimitry Andric       Seg.vmsize = Header.filetype == MachO::MH_OBJECT
3775f757f3fSDimitry Andric                        ? SegContentSize
3785f757f3fSDimitry Andric                        : alignTo(SegContentSize, PageSize);
3795f757f3fSDimitry Andric       SegVMAddr += Seg.vmsize;
3805f757f3fSDimitry Andric     }
3815f757f3fSDimitry Andric 
3825f757f3fSDimitry Andric     // Set string table offsets for non-section symbols.
3835f757f3fSDimitry Andric     for (auto &Sym : SC.Symbols)
3845f757f3fSDimitry Andric       Sym.n_strx = StrTab[Sym.n_strx].Offset;
3855f757f3fSDimitry Andric 
3865f757f3fSDimitry Andric     // Number sections, set symbol section numbers and string table offsets,
3875f757f3fSDimitry Andric     // count relocations.
3885f757f3fSDimitry Andric     size_t NumSymbols = SC.Symbols.size();
3895f757f3fSDimitry Andric     size_t SectionNumber = 0;
3905f757f3fSDimitry Andric     for (auto &Seg : Segments) {
3915f757f3fSDimitry Andric       for (auto &Sec : Seg.Sections) {
3925f757f3fSDimitry Andric         ++SectionNumber;
3935f757f3fSDimitry Andric         Sec->SectionNumber = SectionNumber;
3945f757f3fSDimitry Andric         Sec->SC.SymbolIndexBase = NumSymbols;
3955f757f3fSDimitry Andric         NumSymbols += Sec->SC.Symbols.size();
3965f757f3fSDimitry Andric         for (auto &Sym : Sec->SC.Symbols) {
3975f757f3fSDimitry Andric           Sym.n_sect = SectionNumber;
3985f757f3fSDimitry Andric           Sym.n_strx = StrTab[Sym.n_strx].Offset;
3995f757f3fSDimitry Andric           Sym.n_value += Sec->addr;
4005f757f3fSDimitry Andric         }
4015f757f3fSDimitry Andric       }
4025f757f3fSDimitry Andric     }
4035f757f3fSDimitry Andric 
4045f757f3fSDimitry Andric     // Handle relocations
4055f757f3fSDimitry Andric     bool OffsetAlignedForRelocs = false;
4065f757f3fSDimitry Andric     for (auto &Seg : Segments) {
4075f757f3fSDimitry Andric       for (auto &Sec : Seg.Sections) {
4085f757f3fSDimitry Andric         if (!Sec->Relocs.empty()) {
4095f757f3fSDimitry Andric           if (!OffsetAlignedForRelocs) {
4105f757f3fSDimitry Andric             Offset = alignTo(Offset, sizeof(MachO::relocation_info));
4115f757f3fSDimitry Andric             OffsetAlignedForRelocs = true;
4125f757f3fSDimitry Andric           }
4135f757f3fSDimitry Andric           Sec->reloff = Offset;
4145f757f3fSDimitry Andric           Sec->nreloc = Sec->Relocs.size();
4155f757f3fSDimitry Andric           Offset += Sec->Relocs.size() * sizeof(MachO::relocation_info);
4165f757f3fSDimitry Andric           for (auto &R : Sec->Relocs)
4175f757f3fSDimitry Andric             R.r_symbolnum = R.Target.isSymbol() ? R.Target.getSymbolNum()
4185f757f3fSDimitry Andric                                                 : R.Target.getSectionId();
4195f757f3fSDimitry Andric         }
4205f757f3fSDimitry Andric       }
4215f757f3fSDimitry Andric     }
4225f757f3fSDimitry Andric 
4235f757f3fSDimitry Andric     // Calculate offset to start of nlist and update symtab command.
4245f757f3fSDimitry Andric     if (NumSymbols > 0) {
4255f757f3fSDimitry Andric       Offset = alignTo(Offset, sizeof(typename MachOTraits::NList));
4265f757f3fSDimitry Andric       SymTabLC->symoff = Offset;
4275f757f3fSDimitry Andric       SymTabLC->nsyms = NumSymbols;
4285f757f3fSDimitry Andric 
4295f757f3fSDimitry Andric       // Calculate string table bounds and update symtab command.
4305f757f3fSDimitry Andric       if (!StrTab.empty()) {
4315f757f3fSDimitry Andric         Offset += NumSymbols * sizeof(typename MachOTraits::NList);
4325f757f3fSDimitry Andric         size_t StringTableSize =
4335f757f3fSDimitry Andric             StrTab.back().Offset + StrTab.back().S.size() + 1;
4345f757f3fSDimitry Andric 
4355f757f3fSDimitry Andric         SymTabLC->stroff = Offset;
4365f757f3fSDimitry Andric         SymTabLC->strsize = StringTableSize;
4375f757f3fSDimitry Andric         Offset += StringTableSize;
4385f757f3fSDimitry Andric       }
4395f757f3fSDimitry Andric     }
4405f757f3fSDimitry Andric 
4415f757f3fSDimitry Andric     return Offset;
4425f757f3fSDimitry Andric   }
4435f757f3fSDimitry Andric 
4445f757f3fSDimitry Andric   void write(MutableArrayRef<char> Buffer) {
4455f757f3fSDimitry Andric     size_t Offset = 0;
4465f757f3fSDimitry Andric     Offset = writeHeader(Buffer, Offset);
4475f757f3fSDimitry Andric     Offset = writeSegments(Buffer, Offset);
4485f757f3fSDimitry Andric     Offset = writeLoadCommands(Buffer, Offset);
4495f757f3fSDimitry Andric     Offset = writeSectionContent(Buffer, Offset);
4505f757f3fSDimitry Andric     Offset = writeRelocations(Buffer, Offset);
4515f757f3fSDimitry Andric     Offset = writeSymbols(Buffer, Offset);
4525f757f3fSDimitry Andric     Offset = writeStrings(Buffer, Offset);
4535f757f3fSDimitry Andric   }
4545f757f3fSDimitry Andric 
4555f757f3fSDimitry Andric   typename MachOTraits::Header Header;
4565f757f3fSDimitry Andric 
4575f757f3fSDimitry Andric private:
4585f757f3fSDimitry Andric   void makeStringTable() {
4595f757f3fSDimitry Andric     if (Strings.empty())
4605f757f3fSDimitry Andric       return;
4615f757f3fSDimitry Andric 
4625f757f3fSDimitry Andric     StrTab.resize(Strings.size());
4635f757f3fSDimitry Andric     for (auto &KV : Strings)
4645f757f3fSDimitry Andric       StrTab[KV.second] = {KV.first, 0};
4655f757f3fSDimitry Andric     size_t Offset = 0;
4665f757f3fSDimitry Andric     for (auto &Elem : StrTab) {
4675f757f3fSDimitry Andric       Elem.Offset = Offset;
4685f757f3fSDimitry Andric       Offset += Elem.S.size() + 1;
4695f757f3fSDimitry Andric     }
4705f757f3fSDimitry Andric   }
4715f757f3fSDimitry Andric 
4725f757f3fSDimitry Andric   size_t writeHeader(MutableArrayRef<char> Buf, size_t Offset) {
4735f757f3fSDimitry Andric     Header.ncmds = Segments.size() + LoadCommands.size();
4745f757f3fSDimitry Andric     return writeMachOStruct(Buf, Offset, Header, swapStruct());
4755f757f3fSDimitry Andric   }
4765f757f3fSDimitry Andric 
4775f757f3fSDimitry Andric   size_t writeSegments(MutableArrayRef<char> Buf, size_t Offset) {
4785f757f3fSDimitry Andric     for (auto &Seg : Segments)
4795f757f3fSDimitry Andric       Offset = Seg.write(Buf, Offset, swapStruct());
4805f757f3fSDimitry Andric     return Offset;
4815f757f3fSDimitry Andric   }
4825f757f3fSDimitry Andric 
4835f757f3fSDimitry Andric   size_t writeLoadCommands(MutableArrayRef<char> Buf, size_t Offset) {
4845f757f3fSDimitry Andric     for (auto &LC : LoadCommands)
4855f757f3fSDimitry Andric       Offset = LC->write(Buf, Offset, swapStruct());
4865f757f3fSDimitry Andric     return Offset;
4875f757f3fSDimitry Andric   }
4885f757f3fSDimitry Andric 
4895f757f3fSDimitry Andric   size_t writeSectionContent(MutableArrayRef<char> Buf, size_t Offset) {
4905f757f3fSDimitry Andric     for (auto &Seg : Segments) {
4915f757f3fSDimitry Andric       for (auto &Sec : Seg.Sections) {
4925f757f3fSDimitry Andric         if (!Sec->Content.Data) {
4935f757f3fSDimitry Andric           assert(Sec->Relocs.empty() &&
4945f757f3fSDimitry Andric                  "Cant' have relocs for zero-fill segment");
4955f757f3fSDimitry Andric           continue;
4965f757f3fSDimitry Andric         }
4975f757f3fSDimitry Andric         while (Offset != Sec->offset)
4985f757f3fSDimitry Andric           Buf[Offset++] = '\0';
4995f757f3fSDimitry Andric 
5005f757f3fSDimitry Andric         assert(Offset + Sec->Content.Size <= Buf.size() && "Buffer overflow");
5015f757f3fSDimitry Andric         memcpy(&Buf[Offset], Sec->Content.Data, Sec->Content.Size);
5025f757f3fSDimitry Andric         Offset += Sec->Content.Size;
5035f757f3fSDimitry Andric       }
5045f757f3fSDimitry Andric     }
5055f757f3fSDimitry Andric     return Offset;
5065f757f3fSDimitry Andric   }
5075f757f3fSDimitry Andric 
5085f757f3fSDimitry Andric   size_t writeRelocations(MutableArrayRef<char> Buf, size_t Offset) {
5095f757f3fSDimitry Andric     for (auto &Seg : Segments) {
5105f757f3fSDimitry Andric       for (auto &Sec : Seg.Sections) {
5115f757f3fSDimitry Andric         if (!Sec->Relocs.empty()) {
5125f757f3fSDimitry Andric           while (Offset % sizeof(MachO::relocation_info))
5135f757f3fSDimitry Andric             Buf[Offset++] = '\0';
5145f757f3fSDimitry Andric         }
5155f757f3fSDimitry Andric         for (auto &R : Sec->Relocs) {
5165f757f3fSDimitry Andric           assert(Offset + sizeof(MachO::relocation_info) <= Buf.size() &&
5175f757f3fSDimitry Andric                  "Buffer overflow");
5185f757f3fSDimitry Andric           memcpy(&Buf[Offset], reinterpret_cast<const char *>(&R.rawStruct()),
5195f757f3fSDimitry Andric                  sizeof(MachO::relocation_info));
5205f757f3fSDimitry Andric           Offset += sizeof(MachO::relocation_info);
5215f757f3fSDimitry Andric         }
5225f757f3fSDimitry Andric       }
5235f757f3fSDimitry Andric     }
5245f757f3fSDimitry Andric     return Offset;
5255f757f3fSDimitry Andric   }
5265f757f3fSDimitry Andric 
5275f757f3fSDimitry Andric   size_t writeSymbols(MutableArrayRef<char> Buf, size_t Offset) {
5285f757f3fSDimitry Andric 
5295f757f3fSDimitry Andric     // Count symbols.
5305f757f3fSDimitry Andric     size_t NumSymbols = SC.Symbols.size();
5315f757f3fSDimitry Andric     for (auto &Seg : Segments)
5325f757f3fSDimitry Andric       for (auto &Sec : Seg.Sections)
5335f757f3fSDimitry Andric         NumSymbols += Sec->SC.Symbols.size();
5345f757f3fSDimitry Andric 
5355f757f3fSDimitry Andric     // If none then return.
5365f757f3fSDimitry Andric     if (NumSymbols == 0)
5375f757f3fSDimitry Andric       return Offset;
5385f757f3fSDimitry Andric 
5395f757f3fSDimitry Andric     // Align to nlist entry size.
5405f757f3fSDimitry Andric     while (Offset % sizeof(typename MachOTraits::NList))
5415f757f3fSDimitry Andric       Buf[Offset++] = '\0';
5425f757f3fSDimitry Andric 
5435f757f3fSDimitry Andric     // Write non-section symbols.
5445f757f3fSDimitry Andric     for (auto &Sym : SC.Symbols)
5455f757f3fSDimitry Andric       Offset = writeMachOStruct(Buf, Offset, Sym, swapStruct());
5465f757f3fSDimitry Andric 
5475f757f3fSDimitry Andric     // Write section symbols.
5485f757f3fSDimitry Andric     for (auto &Seg : Segments) {
5495f757f3fSDimitry Andric       for (auto &Sec : Seg.Sections) {
5505f757f3fSDimitry Andric         for (auto &Sym : Sec->SC.Symbols) {
5515f757f3fSDimitry Andric           Offset = writeMachOStruct(Buf, Offset, Sym, swapStruct());
5525f757f3fSDimitry Andric         }
5535f757f3fSDimitry Andric       }
5545f757f3fSDimitry Andric     }
5555f757f3fSDimitry Andric     return Offset;
5565f757f3fSDimitry Andric   }
5575f757f3fSDimitry Andric 
5585f757f3fSDimitry Andric   size_t writeStrings(MutableArrayRef<char> Buf, size_t Offset) {
5595f757f3fSDimitry Andric     for (auto &Elem : StrTab) {
5605f757f3fSDimitry Andric       assert(Offset + Elem.S.size() + 1 <= Buf.size() && "Buffer overflow");
5615f757f3fSDimitry Andric       memcpy(&Buf[Offset], Elem.S.data(), Elem.S.size());
5625f757f3fSDimitry Andric       Offset += Elem.S.size();
5635f757f3fSDimitry Andric       Buf[Offset++] = '\0';
5645f757f3fSDimitry Andric     }
5655f757f3fSDimitry Andric     return Offset;
5665f757f3fSDimitry Andric   }
5675f757f3fSDimitry Andric 
5685f757f3fSDimitry Andric   size_t PageSize;
5695f757f3fSDimitry Andric   std::list<Segment> Segments;
5705f757f3fSDimitry Andric   std::vector<std::unique_ptr<MachOBuilderLoadCommandBase>> LoadCommands;
5715f757f3fSDimitry Andric   SymbolContainer SC;
5725f757f3fSDimitry Andric 
5735f757f3fSDimitry Andric   // Maps strings to their "id" (addition order).
5745f757f3fSDimitry Andric   std::map<StringRef, size_t> Strings;
5755f757f3fSDimitry Andric   StringTable StrTab;
5765f757f3fSDimitry Andric };
5775f757f3fSDimitry Andric 
5785f757f3fSDimitry Andric struct MachO64LE {
5795f757f3fSDimitry Andric   using UIntPtr = uint64_t;
5805f757f3fSDimitry Andric   using Header = MachO::mach_header_64;
5815f757f3fSDimitry Andric   using Section = MachO::section_64;
5825f757f3fSDimitry Andric   using NList = MachO::nlist_64;
5835f757f3fSDimitry Andric   using Relocation = MachO::relocation_info;
5845f757f3fSDimitry Andric 
5855f757f3fSDimitry Andric   static constexpr llvm::endianness Endianness = llvm::endianness::little;
5865f757f3fSDimitry Andric   static constexpr uint32_t Magic = MachO::MH_MAGIC_64;
5875f757f3fSDimitry Andric   static constexpr MachO::LoadCommandType SegmentCmd = MachO::LC_SEGMENT_64;
5885f757f3fSDimitry Andric   static constexpr MachO::LoadCommandType SymTabCmd = MachO::LC_SYMTAB;
5895f757f3fSDimitry Andric };
5905f757f3fSDimitry Andric 
5915f757f3fSDimitry Andric } // namespace orc
5925f757f3fSDimitry Andric } // namespace llvm
5935f757f3fSDimitry Andric 
5945f757f3fSDimitry Andric #endif // LLVM_EXECUTIONENGINE_ORC_MACHOBUILDER_H
595