1*81ad6265SDimitry Andric //===- MachOLayoutBuilder.cpp -----------------------------------*- C++ -*-===// 2*81ad6265SDimitry Andric // 3*81ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*81ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*81ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*81ad6265SDimitry Andric // 7*81ad6265SDimitry Andric //===----------------------------------------------------------------------===// 8*81ad6265SDimitry Andric 9*81ad6265SDimitry Andric #include "MachOLayoutBuilder.h" 10*81ad6265SDimitry Andric #include "llvm/Support/Alignment.h" 11*81ad6265SDimitry Andric #include "llvm/Support/Errc.h" 12*81ad6265SDimitry Andric #include "llvm/Support/ErrorHandling.h" 13*81ad6265SDimitry Andric 14*81ad6265SDimitry Andric using namespace llvm; 15*81ad6265SDimitry Andric using namespace llvm::objcopy::macho; 16*81ad6265SDimitry Andric 17*81ad6265SDimitry Andric StringTableBuilder::Kind 18*81ad6265SDimitry Andric MachOLayoutBuilder::getStringTableBuilderKind(const Object &O, bool Is64Bit) { 19*81ad6265SDimitry Andric if (O.Header.FileType == MachO::HeaderFileType::MH_OBJECT) 20*81ad6265SDimitry Andric return Is64Bit ? StringTableBuilder::MachO64 : StringTableBuilder::MachO; 21*81ad6265SDimitry Andric return Is64Bit ? StringTableBuilder::MachO64Linked 22*81ad6265SDimitry Andric : StringTableBuilder::MachOLinked; 23*81ad6265SDimitry Andric } 24*81ad6265SDimitry Andric 25*81ad6265SDimitry Andric uint32_t MachOLayoutBuilder::computeSizeOfCmds() const { 26*81ad6265SDimitry Andric uint32_t Size = 0; 27*81ad6265SDimitry Andric for (const LoadCommand &LC : O.LoadCommands) { 28*81ad6265SDimitry Andric const MachO::macho_load_command &MLC = LC.MachOLoadCommand; 29*81ad6265SDimitry Andric auto cmd = MLC.load_command_data.cmd; 30*81ad6265SDimitry Andric switch (cmd) { 31*81ad6265SDimitry Andric case MachO::LC_SEGMENT: 32*81ad6265SDimitry Andric Size += sizeof(MachO::segment_command) + 33*81ad6265SDimitry Andric sizeof(MachO::section) * LC.Sections.size(); 34*81ad6265SDimitry Andric continue; 35*81ad6265SDimitry Andric case MachO::LC_SEGMENT_64: 36*81ad6265SDimitry Andric Size += sizeof(MachO::segment_command_64) + 37*81ad6265SDimitry Andric sizeof(MachO::section_64) * LC.Sections.size(); 38*81ad6265SDimitry Andric continue; 39*81ad6265SDimitry Andric } 40*81ad6265SDimitry Andric 41*81ad6265SDimitry Andric switch (cmd) { 42*81ad6265SDimitry Andric #define HANDLE_LOAD_COMMAND(LCName, LCValue, LCStruct) \ 43*81ad6265SDimitry Andric case MachO::LCName: \ 44*81ad6265SDimitry Andric Size += sizeof(MachO::LCStruct) + LC.Payload.size(); \ 45*81ad6265SDimitry Andric break; 46*81ad6265SDimitry Andric #include "llvm/BinaryFormat/MachO.def" 47*81ad6265SDimitry Andric #undef HANDLE_LOAD_COMMAND 48*81ad6265SDimitry Andric } 49*81ad6265SDimitry Andric } 50*81ad6265SDimitry Andric 51*81ad6265SDimitry Andric return Size; 52*81ad6265SDimitry Andric } 53*81ad6265SDimitry Andric 54*81ad6265SDimitry Andric void MachOLayoutBuilder::constructStringTable() { 55*81ad6265SDimitry Andric for (std::unique_ptr<SymbolEntry> &Sym : O.SymTable.Symbols) 56*81ad6265SDimitry Andric StrTableBuilder.add(Sym->Name); 57*81ad6265SDimitry Andric StrTableBuilder.finalize(); 58*81ad6265SDimitry Andric } 59*81ad6265SDimitry Andric 60*81ad6265SDimitry Andric void MachOLayoutBuilder::updateSymbolIndexes() { 61*81ad6265SDimitry Andric uint32_t Index = 0; 62*81ad6265SDimitry Andric for (auto &Symbol : O.SymTable.Symbols) 63*81ad6265SDimitry Andric Symbol->Index = Index++; 64*81ad6265SDimitry Andric } 65*81ad6265SDimitry Andric 66*81ad6265SDimitry Andric // Updates the index and the number of local/external/undefined symbols. 67*81ad6265SDimitry Andric void MachOLayoutBuilder::updateDySymTab(MachO::macho_load_command &MLC) { 68*81ad6265SDimitry Andric assert(MLC.load_command_data.cmd == MachO::LC_DYSYMTAB); 69*81ad6265SDimitry Andric // Make sure that nlist entries in the symbol table are sorted by the those 70*81ad6265SDimitry Andric // types. The order is: local < defined external < undefined external. 71*81ad6265SDimitry Andric assert(llvm::is_sorted(O.SymTable.Symbols, 72*81ad6265SDimitry Andric [](const std::unique_ptr<SymbolEntry> &A, 73*81ad6265SDimitry Andric const std::unique_ptr<SymbolEntry> &B) { 74*81ad6265SDimitry Andric bool AL = A->isLocalSymbol(), 75*81ad6265SDimitry Andric BL = B->isLocalSymbol(); 76*81ad6265SDimitry Andric if (AL != BL) 77*81ad6265SDimitry Andric return AL; 78*81ad6265SDimitry Andric return !AL && !A->isUndefinedSymbol() && 79*81ad6265SDimitry Andric B->isUndefinedSymbol(); 80*81ad6265SDimitry Andric }) && 81*81ad6265SDimitry Andric "Symbols are not sorted by their types."); 82*81ad6265SDimitry Andric 83*81ad6265SDimitry Andric uint32_t NumLocalSymbols = 0; 84*81ad6265SDimitry Andric auto Iter = O.SymTable.Symbols.begin(); 85*81ad6265SDimitry Andric auto End = O.SymTable.Symbols.end(); 86*81ad6265SDimitry Andric for (; Iter != End; ++Iter) { 87*81ad6265SDimitry Andric if ((*Iter)->isExternalSymbol()) 88*81ad6265SDimitry Andric break; 89*81ad6265SDimitry Andric 90*81ad6265SDimitry Andric ++NumLocalSymbols; 91*81ad6265SDimitry Andric } 92*81ad6265SDimitry Andric 93*81ad6265SDimitry Andric uint32_t NumExtDefSymbols = 0; 94*81ad6265SDimitry Andric for (; Iter != End; ++Iter) { 95*81ad6265SDimitry Andric if ((*Iter)->isUndefinedSymbol()) 96*81ad6265SDimitry Andric break; 97*81ad6265SDimitry Andric 98*81ad6265SDimitry Andric ++NumExtDefSymbols; 99*81ad6265SDimitry Andric } 100*81ad6265SDimitry Andric 101*81ad6265SDimitry Andric MLC.dysymtab_command_data.ilocalsym = 0; 102*81ad6265SDimitry Andric MLC.dysymtab_command_data.nlocalsym = NumLocalSymbols; 103*81ad6265SDimitry Andric MLC.dysymtab_command_data.iextdefsym = NumLocalSymbols; 104*81ad6265SDimitry Andric MLC.dysymtab_command_data.nextdefsym = NumExtDefSymbols; 105*81ad6265SDimitry Andric MLC.dysymtab_command_data.iundefsym = NumLocalSymbols + NumExtDefSymbols; 106*81ad6265SDimitry Andric MLC.dysymtab_command_data.nundefsym = 107*81ad6265SDimitry Andric O.SymTable.Symbols.size() - (NumLocalSymbols + NumExtDefSymbols); 108*81ad6265SDimitry Andric } 109*81ad6265SDimitry Andric 110*81ad6265SDimitry Andric // Recomputes and updates offset and size fields in load commands and sections 111*81ad6265SDimitry Andric // since they could be modified. 112*81ad6265SDimitry Andric uint64_t MachOLayoutBuilder::layoutSegments() { 113*81ad6265SDimitry Andric auto HeaderSize = 114*81ad6265SDimitry Andric Is64Bit ? sizeof(MachO::mach_header_64) : sizeof(MachO::mach_header); 115*81ad6265SDimitry Andric const bool IsObjectFile = 116*81ad6265SDimitry Andric O.Header.FileType == MachO::HeaderFileType::MH_OBJECT; 117*81ad6265SDimitry Andric uint64_t Offset = IsObjectFile ? (HeaderSize + O.Header.SizeOfCmds) : 0; 118*81ad6265SDimitry Andric for (LoadCommand &LC : O.LoadCommands) { 119*81ad6265SDimitry Andric auto &MLC = LC.MachOLoadCommand; 120*81ad6265SDimitry Andric StringRef Segname; 121*81ad6265SDimitry Andric uint64_t SegmentVmAddr; 122*81ad6265SDimitry Andric uint64_t SegmentVmSize; 123*81ad6265SDimitry Andric switch (MLC.load_command_data.cmd) { 124*81ad6265SDimitry Andric case MachO::LC_SEGMENT: 125*81ad6265SDimitry Andric SegmentVmAddr = MLC.segment_command_data.vmaddr; 126*81ad6265SDimitry Andric SegmentVmSize = MLC.segment_command_data.vmsize; 127*81ad6265SDimitry Andric Segname = StringRef(MLC.segment_command_data.segname, 128*81ad6265SDimitry Andric strnlen(MLC.segment_command_data.segname, 129*81ad6265SDimitry Andric sizeof(MLC.segment_command_data.segname))); 130*81ad6265SDimitry Andric break; 131*81ad6265SDimitry Andric case MachO::LC_SEGMENT_64: 132*81ad6265SDimitry Andric SegmentVmAddr = MLC.segment_command_64_data.vmaddr; 133*81ad6265SDimitry Andric SegmentVmSize = MLC.segment_command_64_data.vmsize; 134*81ad6265SDimitry Andric Segname = StringRef(MLC.segment_command_64_data.segname, 135*81ad6265SDimitry Andric strnlen(MLC.segment_command_64_data.segname, 136*81ad6265SDimitry Andric sizeof(MLC.segment_command_64_data.segname))); 137*81ad6265SDimitry Andric break; 138*81ad6265SDimitry Andric default: 139*81ad6265SDimitry Andric continue; 140*81ad6265SDimitry Andric } 141*81ad6265SDimitry Andric 142*81ad6265SDimitry Andric if (Segname == "__LINKEDIT") { 143*81ad6265SDimitry Andric // We update the __LINKEDIT segment later (in layoutTail). 144*81ad6265SDimitry Andric assert(LC.Sections.empty() && "__LINKEDIT segment has sections"); 145*81ad6265SDimitry Andric LinkEditLoadCommand = &MLC; 146*81ad6265SDimitry Andric continue; 147*81ad6265SDimitry Andric } 148*81ad6265SDimitry Andric 149*81ad6265SDimitry Andric // Update file offsets and sizes of sections. 150*81ad6265SDimitry Andric uint64_t SegOffset = Offset; 151*81ad6265SDimitry Andric uint64_t SegFileSize = 0; 152*81ad6265SDimitry Andric uint64_t VMSize = 0; 153*81ad6265SDimitry Andric for (std::unique_ptr<Section> &Sec : LC.Sections) { 154*81ad6265SDimitry Andric assert(SegmentVmAddr <= Sec->Addr && 155*81ad6265SDimitry Andric "Section's address cannot be smaller than Segment's one"); 156*81ad6265SDimitry Andric uint32_t SectOffset = Sec->Addr - SegmentVmAddr; 157*81ad6265SDimitry Andric if (IsObjectFile) { 158*81ad6265SDimitry Andric if (!Sec->hasValidOffset()) { 159*81ad6265SDimitry Andric Sec->Offset = 0; 160*81ad6265SDimitry Andric } else { 161*81ad6265SDimitry Andric uint64_t PaddingSize = 162*81ad6265SDimitry Andric offsetToAlignment(SegFileSize, Align(1ull << Sec->Align)); 163*81ad6265SDimitry Andric Sec->Offset = SegOffset + SegFileSize + PaddingSize; 164*81ad6265SDimitry Andric Sec->Size = Sec->Content.size(); 165*81ad6265SDimitry Andric SegFileSize += PaddingSize + Sec->Size; 166*81ad6265SDimitry Andric } 167*81ad6265SDimitry Andric } else { 168*81ad6265SDimitry Andric if (!Sec->hasValidOffset()) { 169*81ad6265SDimitry Andric Sec->Offset = 0; 170*81ad6265SDimitry Andric } else { 171*81ad6265SDimitry Andric Sec->Offset = SegOffset + SectOffset; 172*81ad6265SDimitry Andric Sec->Size = Sec->Content.size(); 173*81ad6265SDimitry Andric SegFileSize = std::max(SegFileSize, SectOffset + Sec->Size); 174*81ad6265SDimitry Andric } 175*81ad6265SDimitry Andric } 176*81ad6265SDimitry Andric VMSize = std::max(VMSize, SectOffset + Sec->Size); 177*81ad6265SDimitry Andric } 178*81ad6265SDimitry Andric 179*81ad6265SDimitry Andric if (IsObjectFile) { 180*81ad6265SDimitry Andric Offset += SegFileSize; 181*81ad6265SDimitry Andric } else { 182*81ad6265SDimitry Andric Offset = alignTo(Offset + SegFileSize, PageSize); 183*81ad6265SDimitry Andric SegFileSize = alignTo(SegFileSize, PageSize); 184*81ad6265SDimitry Andric // Use the original vmsize if the segment is __PAGEZERO. 185*81ad6265SDimitry Andric VMSize = 186*81ad6265SDimitry Andric Segname == "__PAGEZERO" ? SegmentVmSize : alignTo(VMSize, PageSize); 187*81ad6265SDimitry Andric } 188*81ad6265SDimitry Andric 189*81ad6265SDimitry Andric switch (MLC.load_command_data.cmd) { 190*81ad6265SDimitry Andric case MachO::LC_SEGMENT: 191*81ad6265SDimitry Andric MLC.segment_command_data.cmdsize = 192*81ad6265SDimitry Andric sizeof(MachO::segment_command) + 193*81ad6265SDimitry Andric sizeof(MachO::section) * LC.Sections.size(); 194*81ad6265SDimitry Andric MLC.segment_command_data.nsects = LC.Sections.size(); 195*81ad6265SDimitry Andric MLC.segment_command_data.fileoff = SegOffset; 196*81ad6265SDimitry Andric MLC.segment_command_data.vmsize = VMSize; 197*81ad6265SDimitry Andric MLC.segment_command_data.filesize = SegFileSize; 198*81ad6265SDimitry Andric break; 199*81ad6265SDimitry Andric case MachO::LC_SEGMENT_64: 200*81ad6265SDimitry Andric MLC.segment_command_64_data.cmdsize = 201*81ad6265SDimitry Andric sizeof(MachO::segment_command_64) + 202*81ad6265SDimitry Andric sizeof(MachO::section_64) * LC.Sections.size(); 203*81ad6265SDimitry Andric MLC.segment_command_64_data.nsects = LC.Sections.size(); 204*81ad6265SDimitry Andric MLC.segment_command_64_data.fileoff = SegOffset; 205*81ad6265SDimitry Andric MLC.segment_command_64_data.vmsize = VMSize; 206*81ad6265SDimitry Andric MLC.segment_command_64_data.filesize = SegFileSize; 207*81ad6265SDimitry Andric break; 208*81ad6265SDimitry Andric } 209*81ad6265SDimitry Andric } 210*81ad6265SDimitry Andric 211*81ad6265SDimitry Andric return Offset; 212*81ad6265SDimitry Andric } 213*81ad6265SDimitry Andric 214*81ad6265SDimitry Andric uint64_t MachOLayoutBuilder::layoutRelocations(uint64_t Offset) { 215*81ad6265SDimitry Andric for (LoadCommand &LC : O.LoadCommands) 216*81ad6265SDimitry Andric for (std::unique_ptr<Section> &Sec : LC.Sections) { 217*81ad6265SDimitry Andric Sec->RelOff = Sec->Relocations.empty() ? 0 : Offset; 218*81ad6265SDimitry Andric Sec->NReloc = Sec->Relocations.size(); 219*81ad6265SDimitry Andric Offset += sizeof(MachO::any_relocation_info) * Sec->NReloc; 220*81ad6265SDimitry Andric } 221*81ad6265SDimitry Andric 222*81ad6265SDimitry Andric return Offset; 223*81ad6265SDimitry Andric } 224*81ad6265SDimitry Andric 225*81ad6265SDimitry Andric Error MachOLayoutBuilder::layoutTail(uint64_t Offset) { 226*81ad6265SDimitry Andric // If we are building the layout of an executable or dynamic library 227*81ad6265SDimitry Andric // which does not have any segments other than __LINKEDIT, 228*81ad6265SDimitry Andric // the Offset can be equal to zero by this time. It happens because of the 229*81ad6265SDimitry Andric // convention that in such cases the file offsets specified by LC_SEGMENT 230*81ad6265SDimitry Andric // start with zero (unlike the case of a relocatable object file). 231*81ad6265SDimitry Andric const uint64_t HeaderSize = 232*81ad6265SDimitry Andric Is64Bit ? sizeof(MachO::mach_header_64) : sizeof(MachO::mach_header); 233*81ad6265SDimitry Andric assert((!(O.Header.FileType == MachO::HeaderFileType::MH_OBJECT) || 234*81ad6265SDimitry Andric Offset >= HeaderSize + O.Header.SizeOfCmds) && 235*81ad6265SDimitry Andric "Incorrect tail offset"); 236*81ad6265SDimitry Andric Offset = std::max(Offset, HeaderSize + O.Header.SizeOfCmds); 237*81ad6265SDimitry Andric 238*81ad6265SDimitry Andric // The order of LINKEDIT elements is as follows: 239*81ad6265SDimitry Andric // rebase info, binding info, weak binding info, lazy binding info, export 240*81ad6265SDimitry Andric // trie, data-in-code, symbol table, indirect symbol table, symbol table 241*81ad6265SDimitry Andric // strings, code signature. 242*81ad6265SDimitry Andric uint64_t NListSize = Is64Bit ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist); 243*81ad6265SDimitry Andric uint64_t StartOfLinkEdit = Offset; 244*81ad6265SDimitry Andric uint64_t StartOfRebaseInfo = StartOfLinkEdit; 245*81ad6265SDimitry Andric uint64_t StartOfBindingInfo = StartOfRebaseInfo + O.Rebases.Opcodes.size(); 246*81ad6265SDimitry Andric uint64_t StartOfWeakBindingInfo = StartOfBindingInfo + O.Binds.Opcodes.size(); 247*81ad6265SDimitry Andric uint64_t StartOfLazyBindingInfo = 248*81ad6265SDimitry Andric StartOfWeakBindingInfo + O.WeakBinds.Opcodes.size(); 249*81ad6265SDimitry Andric uint64_t StartOfExportTrie = 250*81ad6265SDimitry Andric StartOfLazyBindingInfo + O.LazyBinds.Opcodes.size(); 251*81ad6265SDimitry Andric uint64_t StartOfFunctionStarts = StartOfExportTrie + O.Exports.Trie.size(); 252*81ad6265SDimitry Andric uint64_t StartOfDyldExportsTrie = 253*81ad6265SDimitry Andric StartOfFunctionStarts + O.FunctionStarts.Data.size(); 254*81ad6265SDimitry Andric uint64_t StartOfChainedFixups = 255*81ad6265SDimitry Andric StartOfDyldExportsTrie + O.ExportsTrie.Data.size(); 256*81ad6265SDimitry Andric uint64_t StartOfDataInCode = 257*81ad6265SDimitry Andric StartOfChainedFixups + O.ChainedFixups.Data.size(); 258*81ad6265SDimitry Andric uint64_t StartOfLinkerOptimizationHint = 259*81ad6265SDimitry Andric StartOfDataInCode + O.DataInCode.Data.size(); 260*81ad6265SDimitry Andric uint64_t StartOfSymbols = 261*81ad6265SDimitry Andric StartOfLinkerOptimizationHint + O.LinkerOptimizationHint.Data.size(); 262*81ad6265SDimitry Andric uint64_t StartOfIndirectSymbols = 263*81ad6265SDimitry Andric StartOfSymbols + NListSize * O.SymTable.Symbols.size(); 264*81ad6265SDimitry Andric uint64_t StartOfSymbolStrings = 265*81ad6265SDimitry Andric StartOfIndirectSymbols + 266*81ad6265SDimitry Andric sizeof(uint32_t) * O.IndirectSymTable.Symbols.size(); 267*81ad6265SDimitry Andric uint64_t StartOfCodeSignature = 268*81ad6265SDimitry Andric StartOfSymbolStrings + StrTableBuilder.getSize(); 269*81ad6265SDimitry Andric uint32_t CodeSignatureSize = 0; 270*81ad6265SDimitry Andric if (O.CodeSignatureCommandIndex) { 271*81ad6265SDimitry Andric StartOfCodeSignature = alignTo(StartOfCodeSignature, 16); 272*81ad6265SDimitry Andric 273*81ad6265SDimitry Andric // Note: These calculations are to be kept in sync with the same 274*81ad6265SDimitry Andric // calculations performed in LLD's CodeSignatureSection. 275*81ad6265SDimitry Andric const uint32_t AllHeadersSize = 276*81ad6265SDimitry Andric alignTo(CodeSignature.FixedHeadersSize + OutputFileName.size() + 1, 277*81ad6265SDimitry Andric CodeSignature.Align); 278*81ad6265SDimitry Andric const uint32_t BlockCount = 279*81ad6265SDimitry Andric (StartOfCodeSignature + CodeSignature.BlockSize - 1) / 280*81ad6265SDimitry Andric CodeSignature.BlockSize; 281*81ad6265SDimitry Andric const uint32_t Size = 282*81ad6265SDimitry Andric alignTo(AllHeadersSize + BlockCount * CodeSignature.HashSize, 283*81ad6265SDimitry Andric CodeSignature.Align); 284*81ad6265SDimitry Andric 285*81ad6265SDimitry Andric CodeSignature.StartOffset = StartOfCodeSignature; 286*81ad6265SDimitry Andric CodeSignature.AllHeadersSize = AllHeadersSize; 287*81ad6265SDimitry Andric CodeSignature.BlockCount = BlockCount; 288*81ad6265SDimitry Andric CodeSignature.OutputFileName = OutputFileName; 289*81ad6265SDimitry Andric CodeSignature.Size = Size; 290*81ad6265SDimitry Andric CodeSignatureSize = Size; 291*81ad6265SDimitry Andric } 292*81ad6265SDimitry Andric uint64_t LinkEditSize = 293*81ad6265SDimitry Andric StartOfCodeSignature + CodeSignatureSize - StartOfLinkEdit; 294*81ad6265SDimitry Andric 295*81ad6265SDimitry Andric // Now we have determined the layout of the contents of the __LINKEDIT 296*81ad6265SDimitry Andric // segment. Update its load command. 297*81ad6265SDimitry Andric if (LinkEditLoadCommand) { 298*81ad6265SDimitry Andric MachO::macho_load_command *MLC = LinkEditLoadCommand; 299*81ad6265SDimitry Andric switch (LinkEditLoadCommand->load_command_data.cmd) { 300*81ad6265SDimitry Andric case MachO::LC_SEGMENT: 301*81ad6265SDimitry Andric MLC->segment_command_data.cmdsize = sizeof(MachO::segment_command); 302*81ad6265SDimitry Andric MLC->segment_command_data.fileoff = StartOfLinkEdit; 303*81ad6265SDimitry Andric MLC->segment_command_data.vmsize = alignTo(LinkEditSize, PageSize); 304*81ad6265SDimitry Andric MLC->segment_command_data.filesize = LinkEditSize; 305*81ad6265SDimitry Andric break; 306*81ad6265SDimitry Andric case MachO::LC_SEGMENT_64: 307*81ad6265SDimitry Andric MLC->segment_command_64_data.cmdsize = sizeof(MachO::segment_command_64); 308*81ad6265SDimitry Andric MLC->segment_command_64_data.fileoff = StartOfLinkEdit; 309*81ad6265SDimitry Andric MLC->segment_command_64_data.vmsize = alignTo(LinkEditSize, PageSize); 310*81ad6265SDimitry Andric MLC->segment_command_64_data.filesize = LinkEditSize; 311*81ad6265SDimitry Andric break; 312*81ad6265SDimitry Andric } 313*81ad6265SDimitry Andric } 314*81ad6265SDimitry Andric 315*81ad6265SDimitry Andric for (LoadCommand &LC : O.LoadCommands) { 316*81ad6265SDimitry Andric auto &MLC = LC.MachOLoadCommand; 317*81ad6265SDimitry Andric auto cmd = MLC.load_command_data.cmd; 318*81ad6265SDimitry Andric switch (cmd) { 319*81ad6265SDimitry Andric case MachO::LC_CODE_SIGNATURE: 320*81ad6265SDimitry Andric MLC.linkedit_data_command_data.dataoff = StartOfCodeSignature; 321*81ad6265SDimitry Andric MLC.linkedit_data_command_data.datasize = CodeSignatureSize; 322*81ad6265SDimitry Andric break; 323*81ad6265SDimitry Andric case MachO::LC_SYMTAB: 324*81ad6265SDimitry Andric MLC.symtab_command_data.symoff = StartOfSymbols; 325*81ad6265SDimitry Andric MLC.symtab_command_data.nsyms = O.SymTable.Symbols.size(); 326*81ad6265SDimitry Andric MLC.symtab_command_data.stroff = StartOfSymbolStrings; 327*81ad6265SDimitry Andric MLC.symtab_command_data.strsize = StrTableBuilder.getSize(); 328*81ad6265SDimitry Andric break; 329*81ad6265SDimitry Andric case MachO::LC_DYSYMTAB: { 330*81ad6265SDimitry Andric if (MLC.dysymtab_command_data.ntoc != 0 || 331*81ad6265SDimitry Andric MLC.dysymtab_command_data.nmodtab != 0 || 332*81ad6265SDimitry Andric MLC.dysymtab_command_data.nextrefsyms != 0 || 333*81ad6265SDimitry Andric MLC.dysymtab_command_data.nlocrel != 0 || 334*81ad6265SDimitry Andric MLC.dysymtab_command_data.nextrel != 0) 335*81ad6265SDimitry Andric return createStringError(llvm::errc::not_supported, 336*81ad6265SDimitry Andric "shared library is not yet supported"); 337*81ad6265SDimitry Andric 338*81ad6265SDimitry Andric if (!O.IndirectSymTable.Symbols.empty()) { 339*81ad6265SDimitry Andric MLC.dysymtab_command_data.indirectsymoff = StartOfIndirectSymbols; 340*81ad6265SDimitry Andric MLC.dysymtab_command_data.nindirectsyms = 341*81ad6265SDimitry Andric O.IndirectSymTable.Symbols.size(); 342*81ad6265SDimitry Andric } 343*81ad6265SDimitry Andric 344*81ad6265SDimitry Andric updateDySymTab(MLC); 345*81ad6265SDimitry Andric break; 346*81ad6265SDimitry Andric } 347*81ad6265SDimitry Andric case MachO::LC_DATA_IN_CODE: 348*81ad6265SDimitry Andric MLC.linkedit_data_command_data.dataoff = StartOfDataInCode; 349*81ad6265SDimitry Andric MLC.linkedit_data_command_data.datasize = O.DataInCode.Data.size(); 350*81ad6265SDimitry Andric break; 351*81ad6265SDimitry Andric case MachO::LC_LINKER_OPTIMIZATION_HINT: 352*81ad6265SDimitry Andric MLC.linkedit_data_command_data.dataoff = StartOfLinkerOptimizationHint; 353*81ad6265SDimitry Andric MLC.linkedit_data_command_data.datasize = 354*81ad6265SDimitry Andric O.LinkerOptimizationHint.Data.size(); 355*81ad6265SDimitry Andric break; 356*81ad6265SDimitry Andric case MachO::LC_FUNCTION_STARTS: 357*81ad6265SDimitry Andric MLC.linkedit_data_command_data.dataoff = StartOfFunctionStarts; 358*81ad6265SDimitry Andric MLC.linkedit_data_command_data.datasize = O.FunctionStarts.Data.size(); 359*81ad6265SDimitry Andric break; 360*81ad6265SDimitry Andric case MachO::LC_DYLD_CHAINED_FIXUPS: 361*81ad6265SDimitry Andric MLC.linkedit_data_command_data.dataoff = StartOfChainedFixups; 362*81ad6265SDimitry Andric MLC.linkedit_data_command_data.datasize = O.ChainedFixups.Data.size(); 363*81ad6265SDimitry Andric break; 364*81ad6265SDimitry Andric case MachO::LC_DYLD_EXPORTS_TRIE: 365*81ad6265SDimitry Andric MLC.linkedit_data_command_data.dataoff = StartOfDyldExportsTrie; 366*81ad6265SDimitry Andric MLC.linkedit_data_command_data.datasize = O.ExportsTrie.Data.size(); 367*81ad6265SDimitry Andric break; 368*81ad6265SDimitry Andric case MachO::LC_DYLD_INFO: 369*81ad6265SDimitry Andric case MachO::LC_DYLD_INFO_ONLY: 370*81ad6265SDimitry Andric MLC.dyld_info_command_data.rebase_off = 371*81ad6265SDimitry Andric O.Rebases.Opcodes.empty() ? 0 : StartOfRebaseInfo; 372*81ad6265SDimitry Andric MLC.dyld_info_command_data.rebase_size = O.Rebases.Opcodes.size(); 373*81ad6265SDimitry Andric MLC.dyld_info_command_data.bind_off = 374*81ad6265SDimitry Andric O.Binds.Opcodes.empty() ? 0 : StartOfBindingInfo; 375*81ad6265SDimitry Andric MLC.dyld_info_command_data.bind_size = O.Binds.Opcodes.size(); 376*81ad6265SDimitry Andric MLC.dyld_info_command_data.weak_bind_off = 377*81ad6265SDimitry Andric O.WeakBinds.Opcodes.empty() ? 0 : StartOfWeakBindingInfo; 378*81ad6265SDimitry Andric MLC.dyld_info_command_data.weak_bind_size = O.WeakBinds.Opcodes.size(); 379*81ad6265SDimitry Andric MLC.dyld_info_command_data.lazy_bind_off = 380*81ad6265SDimitry Andric O.LazyBinds.Opcodes.empty() ? 0 : StartOfLazyBindingInfo; 381*81ad6265SDimitry Andric MLC.dyld_info_command_data.lazy_bind_size = O.LazyBinds.Opcodes.size(); 382*81ad6265SDimitry Andric MLC.dyld_info_command_data.export_off = 383*81ad6265SDimitry Andric O.Exports.Trie.empty() ? 0 : StartOfExportTrie; 384*81ad6265SDimitry Andric MLC.dyld_info_command_data.export_size = O.Exports.Trie.size(); 385*81ad6265SDimitry Andric break; 386*81ad6265SDimitry Andric // Note that LC_ENCRYPTION_INFO.cryptoff despite its name and the comment in 387*81ad6265SDimitry Andric // <mach-o/loader.h> is not an offset in the binary file, instead, it is a 388*81ad6265SDimitry Andric // relative virtual address. At the moment modification of the __TEXT 389*81ad6265SDimitry Andric // segment of executables isn't supported anyway (e.g. data in code entries 390*81ad6265SDimitry Andric // are not recalculated). Moreover, in general 391*81ad6265SDimitry Andric // LC_ENCRYPT_INFO/LC_ENCRYPTION_INFO_64 are nontrivial to update because 392*81ad6265SDimitry Andric // without making additional assumptions (e.g. that the entire __TEXT 393*81ad6265SDimitry Andric // segment should be encrypted) we do not know how to recalculate the 394*81ad6265SDimitry Andric // boundaries of the encrypted part. For now just copy over these load 395*81ad6265SDimitry Andric // commands until we encounter a real world usecase where 396*81ad6265SDimitry Andric // LC_ENCRYPT_INFO/LC_ENCRYPTION_INFO_64 need to be adjusted. 397*81ad6265SDimitry Andric case MachO::LC_ENCRYPTION_INFO: 398*81ad6265SDimitry Andric case MachO::LC_ENCRYPTION_INFO_64: 399*81ad6265SDimitry Andric case MachO::LC_LOAD_DYLINKER: 400*81ad6265SDimitry Andric case MachO::LC_MAIN: 401*81ad6265SDimitry Andric case MachO::LC_RPATH: 402*81ad6265SDimitry Andric case MachO::LC_SEGMENT: 403*81ad6265SDimitry Andric case MachO::LC_SEGMENT_64: 404*81ad6265SDimitry Andric case MachO::LC_VERSION_MIN_MACOSX: 405*81ad6265SDimitry Andric case MachO::LC_VERSION_MIN_IPHONEOS: 406*81ad6265SDimitry Andric case MachO::LC_VERSION_MIN_TVOS: 407*81ad6265SDimitry Andric case MachO::LC_VERSION_MIN_WATCHOS: 408*81ad6265SDimitry Andric case MachO::LC_BUILD_VERSION: 409*81ad6265SDimitry Andric case MachO::LC_ID_DYLIB: 410*81ad6265SDimitry Andric case MachO::LC_LOAD_DYLIB: 411*81ad6265SDimitry Andric case MachO::LC_LOAD_WEAK_DYLIB: 412*81ad6265SDimitry Andric case MachO::LC_UUID: 413*81ad6265SDimitry Andric case MachO::LC_SOURCE_VERSION: 414*81ad6265SDimitry Andric case MachO::LC_THREAD: 415*81ad6265SDimitry Andric case MachO::LC_UNIXTHREAD: 416*81ad6265SDimitry Andric case MachO::LC_SUB_FRAMEWORK: 417*81ad6265SDimitry Andric case MachO::LC_SUB_UMBRELLA: 418*81ad6265SDimitry Andric case MachO::LC_SUB_CLIENT: 419*81ad6265SDimitry Andric case MachO::LC_SUB_LIBRARY: 420*81ad6265SDimitry Andric case MachO::LC_LINKER_OPTION: 421*81ad6265SDimitry Andric // Nothing to update. 422*81ad6265SDimitry Andric break; 423*81ad6265SDimitry Andric default: 424*81ad6265SDimitry Andric // Abort if it's unsupported in order to prevent corrupting the object. 425*81ad6265SDimitry Andric return createStringError(llvm::errc::not_supported, 426*81ad6265SDimitry Andric "unsupported load command (cmd=0x%x)", cmd); 427*81ad6265SDimitry Andric } 428*81ad6265SDimitry Andric } 429*81ad6265SDimitry Andric 430*81ad6265SDimitry Andric return Error::success(); 431*81ad6265SDimitry Andric } 432*81ad6265SDimitry Andric 433*81ad6265SDimitry Andric Error MachOLayoutBuilder::layout() { 434*81ad6265SDimitry Andric O.Header.NCmds = O.LoadCommands.size(); 435*81ad6265SDimitry Andric O.Header.SizeOfCmds = computeSizeOfCmds(); 436*81ad6265SDimitry Andric constructStringTable(); 437*81ad6265SDimitry Andric updateSymbolIndexes(); 438*81ad6265SDimitry Andric uint64_t Offset = layoutSegments(); 439*81ad6265SDimitry Andric Offset = layoutRelocations(Offset); 440*81ad6265SDimitry Andric return layoutTail(Offset); 441*81ad6265SDimitry Andric } 442