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