181ad6265SDimitry Andric //===- MachOLayoutBuilder.cpp -----------------------------------*- C++ -*-===// 281ad6265SDimitry Andric // 381ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 481ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 581ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 681ad6265SDimitry Andric // 781ad6265SDimitry Andric //===----------------------------------------------------------------------===// 881ad6265SDimitry Andric 981ad6265SDimitry Andric #include "MachOLayoutBuilder.h" 1081ad6265SDimitry Andric #include "llvm/Support/Alignment.h" 1181ad6265SDimitry Andric #include "llvm/Support/Errc.h" 1281ad6265SDimitry Andric #include "llvm/Support/ErrorHandling.h" 1381ad6265SDimitry Andric 1481ad6265SDimitry Andric using namespace llvm; 1581ad6265SDimitry Andric using namespace llvm::objcopy::macho; 1681ad6265SDimitry Andric 1781ad6265SDimitry Andric StringTableBuilder::Kind 1881ad6265SDimitry Andric MachOLayoutBuilder::getStringTableBuilderKind(const Object &O, bool Is64Bit) { 1981ad6265SDimitry Andric if (O.Header.FileType == MachO::HeaderFileType::MH_OBJECT) 2081ad6265SDimitry Andric return Is64Bit ? StringTableBuilder::MachO64 : StringTableBuilder::MachO; 2181ad6265SDimitry Andric return Is64Bit ? StringTableBuilder::MachO64Linked 2281ad6265SDimitry Andric : StringTableBuilder::MachOLinked; 2381ad6265SDimitry Andric } 2481ad6265SDimitry Andric 2581ad6265SDimitry Andric uint32_t MachOLayoutBuilder::computeSizeOfCmds() const { 2681ad6265SDimitry Andric uint32_t Size = 0; 2781ad6265SDimitry Andric for (const LoadCommand &LC : O.LoadCommands) { 2881ad6265SDimitry Andric const MachO::macho_load_command &MLC = LC.MachOLoadCommand; 2981ad6265SDimitry Andric auto cmd = MLC.load_command_data.cmd; 3081ad6265SDimitry Andric switch (cmd) { 3181ad6265SDimitry Andric case MachO::LC_SEGMENT: 3281ad6265SDimitry Andric Size += sizeof(MachO::segment_command) + 3381ad6265SDimitry Andric sizeof(MachO::section) * LC.Sections.size(); 3481ad6265SDimitry Andric continue; 3581ad6265SDimitry Andric case MachO::LC_SEGMENT_64: 3681ad6265SDimitry Andric Size += sizeof(MachO::segment_command_64) + 3781ad6265SDimitry Andric sizeof(MachO::section_64) * LC.Sections.size(); 3881ad6265SDimitry Andric continue; 3981ad6265SDimitry Andric } 4081ad6265SDimitry Andric 4181ad6265SDimitry Andric switch (cmd) { 4281ad6265SDimitry Andric #define HANDLE_LOAD_COMMAND(LCName, LCValue, LCStruct) \ 4381ad6265SDimitry Andric case MachO::LCName: \ 4481ad6265SDimitry Andric Size += sizeof(MachO::LCStruct) + LC.Payload.size(); \ 4581ad6265SDimitry Andric break; 4681ad6265SDimitry Andric #include "llvm/BinaryFormat/MachO.def" 4781ad6265SDimitry Andric #undef HANDLE_LOAD_COMMAND 4881ad6265SDimitry Andric } 4981ad6265SDimitry Andric } 5081ad6265SDimitry Andric 5181ad6265SDimitry Andric return Size; 5281ad6265SDimitry Andric } 5381ad6265SDimitry Andric 5481ad6265SDimitry Andric void MachOLayoutBuilder::constructStringTable() { 5581ad6265SDimitry Andric for (std::unique_ptr<SymbolEntry> &Sym : O.SymTable.Symbols) 5681ad6265SDimitry Andric StrTableBuilder.add(Sym->Name); 5781ad6265SDimitry Andric StrTableBuilder.finalize(); 5881ad6265SDimitry Andric } 5981ad6265SDimitry Andric 6081ad6265SDimitry Andric void MachOLayoutBuilder::updateSymbolIndexes() { 6181ad6265SDimitry Andric uint32_t Index = 0; 6281ad6265SDimitry Andric for (auto &Symbol : O.SymTable.Symbols) 6381ad6265SDimitry Andric Symbol->Index = Index++; 6481ad6265SDimitry Andric } 6581ad6265SDimitry Andric 6681ad6265SDimitry Andric // Updates the index and the number of local/external/undefined symbols. 6781ad6265SDimitry Andric void MachOLayoutBuilder::updateDySymTab(MachO::macho_load_command &MLC) { 6881ad6265SDimitry Andric assert(MLC.load_command_data.cmd == MachO::LC_DYSYMTAB); 6981ad6265SDimitry Andric // Make sure that nlist entries in the symbol table are sorted by the those 7081ad6265SDimitry Andric // types. The order is: local < defined external < undefined external. 7181ad6265SDimitry Andric assert(llvm::is_sorted(O.SymTable.Symbols, 7281ad6265SDimitry Andric [](const std::unique_ptr<SymbolEntry> &A, 7381ad6265SDimitry Andric const std::unique_ptr<SymbolEntry> &B) { 7481ad6265SDimitry Andric bool AL = A->isLocalSymbol(), 7581ad6265SDimitry Andric BL = B->isLocalSymbol(); 7681ad6265SDimitry Andric if (AL != BL) 7781ad6265SDimitry Andric return AL; 7881ad6265SDimitry Andric return !AL && !A->isUndefinedSymbol() && 7981ad6265SDimitry Andric B->isUndefinedSymbol(); 8081ad6265SDimitry Andric }) && 8181ad6265SDimitry Andric "Symbols are not sorted by their types."); 8281ad6265SDimitry Andric 8381ad6265SDimitry Andric uint32_t NumLocalSymbols = 0; 8481ad6265SDimitry Andric auto Iter = O.SymTable.Symbols.begin(); 8581ad6265SDimitry Andric auto End = O.SymTable.Symbols.end(); 8681ad6265SDimitry Andric for (; Iter != End; ++Iter) { 8781ad6265SDimitry Andric if ((*Iter)->isExternalSymbol()) 8881ad6265SDimitry Andric break; 8981ad6265SDimitry Andric 9081ad6265SDimitry Andric ++NumLocalSymbols; 9181ad6265SDimitry Andric } 9281ad6265SDimitry Andric 9381ad6265SDimitry Andric uint32_t NumExtDefSymbols = 0; 9481ad6265SDimitry Andric for (; Iter != End; ++Iter) { 9581ad6265SDimitry Andric if ((*Iter)->isUndefinedSymbol()) 9681ad6265SDimitry Andric break; 9781ad6265SDimitry Andric 9881ad6265SDimitry Andric ++NumExtDefSymbols; 9981ad6265SDimitry Andric } 10081ad6265SDimitry Andric 10181ad6265SDimitry Andric MLC.dysymtab_command_data.ilocalsym = 0; 10281ad6265SDimitry Andric MLC.dysymtab_command_data.nlocalsym = NumLocalSymbols; 10381ad6265SDimitry Andric MLC.dysymtab_command_data.iextdefsym = NumLocalSymbols; 10481ad6265SDimitry Andric MLC.dysymtab_command_data.nextdefsym = NumExtDefSymbols; 10581ad6265SDimitry Andric MLC.dysymtab_command_data.iundefsym = NumLocalSymbols + NumExtDefSymbols; 10681ad6265SDimitry Andric MLC.dysymtab_command_data.nundefsym = 10781ad6265SDimitry Andric O.SymTable.Symbols.size() - (NumLocalSymbols + NumExtDefSymbols); 10881ad6265SDimitry Andric } 10981ad6265SDimitry Andric 11081ad6265SDimitry Andric // Recomputes and updates offset and size fields in load commands and sections 11181ad6265SDimitry Andric // since they could be modified. 11281ad6265SDimitry Andric uint64_t MachOLayoutBuilder::layoutSegments() { 11381ad6265SDimitry Andric auto HeaderSize = 11481ad6265SDimitry Andric Is64Bit ? sizeof(MachO::mach_header_64) : sizeof(MachO::mach_header); 11581ad6265SDimitry Andric const bool IsObjectFile = 11681ad6265SDimitry Andric O.Header.FileType == MachO::HeaderFileType::MH_OBJECT; 11781ad6265SDimitry Andric uint64_t Offset = IsObjectFile ? (HeaderSize + O.Header.SizeOfCmds) : 0; 11881ad6265SDimitry Andric for (LoadCommand &LC : O.LoadCommands) { 11981ad6265SDimitry Andric auto &MLC = LC.MachOLoadCommand; 12081ad6265SDimitry Andric StringRef Segname; 12181ad6265SDimitry Andric uint64_t SegmentVmAddr; 12281ad6265SDimitry Andric uint64_t SegmentVmSize; 12381ad6265SDimitry Andric switch (MLC.load_command_data.cmd) { 12481ad6265SDimitry Andric case MachO::LC_SEGMENT: 12581ad6265SDimitry Andric SegmentVmAddr = MLC.segment_command_data.vmaddr; 12681ad6265SDimitry Andric SegmentVmSize = MLC.segment_command_data.vmsize; 12781ad6265SDimitry Andric Segname = StringRef(MLC.segment_command_data.segname, 12881ad6265SDimitry Andric strnlen(MLC.segment_command_data.segname, 12981ad6265SDimitry Andric sizeof(MLC.segment_command_data.segname))); 13081ad6265SDimitry Andric break; 13181ad6265SDimitry Andric case MachO::LC_SEGMENT_64: 13281ad6265SDimitry Andric SegmentVmAddr = MLC.segment_command_64_data.vmaddr; 13381ad6265SDimitry Andric SegmentVmSize = MLC.segment_command_64_data.vmsize; 13481ad6265SDimitry Andric Segname = StringRef(MLC.segment_command_64_data.segname, 13581ad6265SDimitry Andric strnlen(MLC.segment_command_64_data.segname, 13681ad6265SDimitry Andric sizeof(MLC.segment_command_64_data.segname))); 13781ad6265SDimitry Andric break; 13881ad6265SDimitry Andric default: 13981ad6265SDimitry Andric continue; 14081ad6265SDimitry Andric } 14181ad6265SDimitry Andric 14281ad6265SDimitry Andric if (Segname == "__LINKEDIT") { 14381ad6265SDimitry Andric // We update the __LINKEDIT segment later (in layoutTail). 14481ad6265SDimitry Andric assert(LC.Sections.empty() && "__LINKEDIT segment has sections"); 14581ad6265SDimitry Andric LinkEditLoadCommand = &MLC; 14681ad6265SDimitry Andric continue; 14781ad6265SDimitry Andric } 14881ad6265SDimitry Andric 14981ad6265SDimitry Andric // Update file offsets and sizes of sections. 15081ad6265SDimitry Andric uint64_t SegOffset = Offset; 15181ad6265SDimitry Andric uint64_t SegFileSize = 0; 15281ad6265SDimitry Andric uint64_t VMSize = 0; 15381ad6265SDimitry Andric for (std::unique_ptr<Section> &Sec : LC.Sections) { 15481ad6265SDimitry Andric assert(SegmentVmAddr <= Sec->Addr && 15581ad6265SDimitry Andric "Section's address cannot be smaller than Segment's one"); 15681ad6265SDimitry Andric uint32_t SectOffset = Sec->Addr - SegmentVmAddr; 15781ad6265SDimitry Andric if (IsObjectFile) { 15881ad6265SDimitry Andric if (!Sec->hasValidOffset()) { 15981ad6265SDimitry Andric Sec->Offset = 0; 16081ad6265SDimitry Andric } else { 16181ad6265SDimitry Andric uint64_t PaddingSize = 16281ad6265SDimitry Andric offsetToAlignment(SegFileSize, Align(1ull << Sec->Align)); 16381ad6265SDimitry Andric Sec->Offset = SegOffset + SegFileSize + PaddingSize; 16481ad6265SDimitry Andric Sec->Size = Sec->Content.size(); 16581ad6265SDimitry Andric SegFileSize += PaddingSize + Sec->Size; 16681ad6265SDimitry Andric } 16781ad6265SDimitry Andric } else { 16881ad6265SDimitry Andric if (!Sec->hasValidOffset()) { 16981ad6265SDimitry Andric Sec->Offset = 0; 17081ad6265SDimitry Andric } else { 17181ad6265SDimitry Andric Sec->Offset = SegOffset + SectOffset; 17281ad6265SDimitry Andric Sec->Size = Sec->Content.size(); 17381ad6265SDimitry Andric SegFileSize = std::max(SegFileSize, SectOffset + Sec->Size); 17481ad6265SDimitry Andric } 17581ad6265SDimitry Andric } 17681ad6265SDimitry Andric VMSize = std::max(VMSize, SectOffset + Sec->Size); 17781ad6265SDimitry Andric } 17881ad6265SDimitry Andric 17981ad6265SDimitry Andric if (IsObjectFile) { 18081ad6265SDimitry Andric Offset += SegFileSize; 18181ad6265SDimitry Andric } else { 18281ad6265SDimitry Andric Offset = alignTo(Offset + SegFileSize, PageSize); 18381ad6265SDimitry Andric SegFileSize = alignTo(SegFileSize, PageSize); 18481ad6265SDimitry Andric // Use the original vmsize if the segment is __PAGEZERO. 18581ad6265SDimitry Andric VMSize = 18681ad6265SDimitry Andric Segname == "__PAGEZERO" ? SegmentVmSize : alignTo(VMSize, PageSize); 18781ad6265SDimitry Andric } 18881ad6265SDimitry Andric 18981ad6265SDimitry Andric switch (MLC.load_command_data.cmd) { 19081ad6265SDimitry Andric case MachO::LC_SEGMENT: 19181ad6265SDimitry Andric MLC.segment_command_data.cmdsize = 19281ad6265SDimitry Andric sizeof(MachO::segment_command) + 19381ad6265SDimitry Andric sizeof(MachO::section) * LC.Sections.size(); 19481ad6265SDimitry Andric MLC.segment_command_data.nsects = LC.Sections.size(); 19581ad6265SDimitry Andric MLC.segment_command_data.fileoff = SegOffset; 19681ad6265SDimitry Andric MLC.segment_command_data.vmsize = VMSize; 19781ad6265SDimitry Andric MLC.segment_command_data.filesize = SegFileSize; 19881ad6265SDimitry Andric break; 19981ad6265SDimitry Andric case MachO::LC_SEGMENT_64: 20081ad6265SDimitry Andric MLC.segment_command_64_data.cmdsize = 20181ad6265SDimitry Andric sizeof(MachO::segment_command_64) + 20281ad6265SDimitry Andric sizeof(MachO::section_64) * LC.Sections.size(); 20381ad6265SDimitry Andric MLC.segment_command_64_data.nsects = LC.Sections.size(); 20481ad6265SDimitry Andric MLC.segment_command_64_data.fileoff = SegOffset; 20581ad6265SDimitry Andric MLC.segment_command_64_data.vmsize = VMSize; 20681ad6265SDimitry Andric MLC.segment_command_64_data.filesize = SegFileSize; 20781ad6265SDimitry Andric break; 20881ad6265SDimitry Andric } 20981ad6265SDimitry Andric } 21081ad6265SDimitry Andric 21181ad6265SDimitry Andric return Offset; 21281ad6265SDimitry Andric } 21381ad6265SDimitry Andric 21481ad6265SDimitry Andric uint64_t MachOLayoutBuilder::layoutRelocations(uint64_t Offset) { 21581ad6265SDimitry Andric for (LoadCommand &LC : O.LoadCommands) 21681ad6265SDimitry Andric for (std::unique_ptr<Section> &Sec : LC.Sections) { 21781ad6265SDimitry Andric Sec->RelOff = Sec->Relocations.empty() ? 0 : Offset; 21881ad6265SDimitry Andric Sec->NReloc = Sec->Relocations.size(); 21981ad6265SDimitry Andric Offset += sizeof(MachO::any_relocation_info) * Sec->NReloc; 22081ad6265SDimitry Andric } 22181ad6265SDimitry Andric 22281ad6265SDimitry Andric return Offset; 22381ad6265SDimitry Andric } 22481ad6265SDimitry Andric 22581ad6265SDimitry Andric Error MachOLayoutBuilder::layoutTail(uint64_t Offset) { 22681ad6265SDimitry Andric // If we are building the layout of an executable or dynamic library 22781ad6265SDimitry Andric // which does not have any segments other than __LINKEDIT, 22881ad6265SDimitry Andric // the Offset can be equal to zero by this time. It happens because of the 22981ad6265SDimitry Andric // convention that in such cases the file offsets specified by LC_SEGMENT 23081ad6265SDimitry Andric // start with zero (unlike the case of a relocatable object file). 23181ad6265SDimitry Andric const uint64_t HeaderSize = 23281ad6265SDimitry Andric Is64Bit ? sizeof(MachO::mach_header_64) : sizeof(MachO::mach_header); 23381ad6265SDimitry Andric assert((!(O.Header.FileType == MachO::HeaderFileType::MH_OBJECT) || 23481ad6265SDimitry Andric Offset >= HeaderSize + O.Header.SizeOfCmds) && 23581ad6265SDimitry Andric "Incorrect tail offset"); 23681ad6265SDimitry Andric Offset = std::max(Offset, HeaderSize + O.Header.SizeOfCmds); 23781ad6265SDimitry Andric 238*bdd1243dSDimitry Andric // The exports trie can be in either LC_DYLD_INFO or in 239*bdd1243dSDimitry Andric // LC_DYLD_EXPORTS_TRIE, but not both. 240*bdd1243dSDimitry Andric size_t DyldInfoExportsTrieSize = 0; 241*bdd1243dSDimitry Andric size_t DyldExportsTrieSize = 0; 242*bdd1243dSDimitry Andric for (const auto &LC : O.LoadCommands) { 243*bdd1243dSDimitry Andric switch (LC.MachOLoadCommand.load_command_data.cmd) { 244*bdd1243dSDimitry Andric case MachO::LC_DYLD_INFO: 245*bdd1243dSDimitry Andric case MachO::LC_DYLD_INFO_ONLY: 246*bdd1243dSDimitry Andric DyldInfoExportsTrieSize = O.Exports.Trie.size(); 247*bdd1243dSDimitry Andric break; 248*bdd1243dSDimitry Andric case MachO::LC_DYLD_EXPORTS_TRIE: 249*bdd1243dSDimitry Andric DyldExportsTrieSize = O.Exports.Trie.size(); 250*bdd1243dSDimitry Andric break; 251*bdd1243dSDimitry Andric default: 252*bdd1243dSDimitry Andric break; 253*bdd1243dSDimitry Andric } 254*bdd1243dSDimitry Andric } 255*bdd1243dSDimitry Andric assert((DyldInfoExportsTrieSize == 0 || DyldExportsTrieSize == 0) && 256*bdd1243dSDimitry Andric "Export trie in both LCs"); 257*bdd1243dSDimitry Andric 25881ad6265SDimitry Andric uint64_t NListSize = Is64Bit ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist); 25981ad6265SDimitry Andric uint64_t StartOfLinkEdit = Offset; 260*bdd1243dSDimitry Andric 261*bdd1243dSDimitry Andric // The order of LINKEDIT elements is as follows: 262*bdd1243dSDimitry Andric // rebase info, binding info, weak binding info, lazy binding info, export 263*bdd1243dSDimitry Andric // trie, chained fixups, dyld exports trie, function starts, data-in-code, 264*bdd1243dSDimitry Andric // symbol table, indirect symbol table, symbol table strings, 265*bdd1243dSDimitry Andric // dylib codesign drs, and code signature. 266*bdd1243dSDimitry Andric auto updateOffset = [&Offset](size_t Size) { 267*bdd1243dSDimitry Andric uint64_t PreviousOffset = Offset; 268*bdd1243dSDimitry Andric Offset += Size; 269*bdd1243dSDimitry Andric return PreviousOffset; 270*bdd1243dSDimitry Andric }; 271*bdd1243dSDimitry Andric 272*bdd1243dSDimitry Andric uint64_t StartOfRebaseInfo = updateOffset(O.Rebases.Opcodes.size()); 273*bdd1243dSDimitry Andric uint64_t StartOfBindingInfo = updateOffset(O.Binds.Opcodes.size()); 274*bdd1243dSDimitry Andric uint64_t StartOfWeakBindingInfo = updateOffset(O.WeakBinds.Opcodes.size()); 275*bdd1243dSDimitry Andric uint64_t StartOfLazyBindingInfo = updateOffset(O.LazyBinds.Opcodes.size()); 276*bdd1243dSDimitry Andric uint64_t StartOfExportTrie = updateOffset(DyldInfoExportsTrieSize); 277*bdd1243dSDimitry Andric uint64_t StartOfChainedFixups = updateOffset(O.ChainedFixups.Data.size()); 278*bdd1243dSDimitry Andric uint64_t StartOfDyldExportsTrie = updateOffset(DyldExportsTrieSize); 279*bdd1243dSDimitry Andric uint64_t StartOfFunctionStarts = updateOffset(O.FunctionStarts.Data.size()); 280*bdd1243dSDimitry Andric uint64_t StartOfDataInCode = updateOffset(O.DataInCode.Data.size()); 28181ad6265SDimitry Andric uint64_t StartOfLinkerOptimizationHint = 282*bdd1243dSDimitry Andric updateOffset(O.LinkerOptimizationHint.Data.size()); 283*bdd1243dSDimitry Andric uint64_t StartOfSymbols = updateOffset(NListSize * O.SymTable.Symbols.size()); 28481ad6265SDimitry Andric uint64_t StartOfIndirectSymbols = 285*bdd1243dSDimitry Andric updateOffset(sizeof(uint32_t) * O.IndirectSymTable.Symbols.size()); 286*bdd1243dSDimitry Andric uint64_t StartOfSymbolStrings = updateOffset(StrTableBuilder.getSize()); 287*bdd1243dSDimitry Andric uint64_t StartOfDylibCodeSignDRs = updateOffset(O.DylibCodeSignDRs.Data.size()); 288*bdd1243dSDimitry Andric 289*bdd1243dSDimitry Andric uint64_t StartOfCodeSignature = Offset; 29081ad6265SDimitry Andric uint32_t CodeSignatureSize = 0; 29181ad6265SDimitry Andric if (O.CodeSignatureCommandIndex) { 29281ad6265SDimitry Andric StartOfCodeSignature = alignTo(StartOfCodeSignature, 16); 29381ad6265SDimitry Andric 29481ad6265SDimitry Andric // Note: These calculations are to be kept in sync with the same 29581ad6265SDimitry Andric // calculations performed in LLD's CodeSignatureSection. 29681ad6265SDimitry Andric const uint32_t AllHeadersSize = 29781ad6265SDimitry Andric alignTo(CodeSignature.FixedHeadersSize + OutputFileName.size() + 1, 29881ad6265SDimitry Andric CodeSignature.Align); 29981ad6265SDimitry Andric const uint32_t BlockCount = 30081ad6265SDimitry Andric (StartOfCodeSignature + CodeSignature.BlockSize - 1) / 30181ad6265SDimitry Andric CodeSignature.BlockSize; 30281ad6265SDimitry Andric const uint32_t Size = 30381ad6265SDimitry Andric alignTo(AllHeadersSize + BlockCount * CodeSignature.HashSize, 30481ad6265SDimitry Andric CodeSignature.Align); 30581ad6265SDimitry Andric 30681ad6265SDimitry Andric CodeSignature.StartOffset = StartOfCodeSignature; 30781ad6265SDimitry Andric CodeSignature.AllHeadersSize = AllHeadersSize; 30881ad6265SDimitry Andric CodeSignature.BlockCount = BlockCount; 30981ad6265SDimitry Andric CodeSignature.OutputFileName = OutputFileName; 31081ad6265SDimitry Andric CodeSignature.Size = Size; 31181ad6265SDimitry Andric CodeSignatureSize = Size; 31281ad6265SDimitry Andric } 31381ad6265SDimitry Andric uint64_t LinkEditSize = 31481ad6265SDimitry Andric StartOfCodeSignature + CodeSignatureSize - StartOfLinkEdit; 31581ad6265SDimitry Andric 31681ad6265SDimitry Andric // Now we have determined the layout of the contents of the __LINKEDIT 31781ad6265SDimitry Andric // segment. Update its load command. 31881ad6265SDimitry Andric if (LinkEditLoadCommand) { 31981ad6265SDimitry Andric MachO::macho_load_command *MLC = LinkEditLoadCommand; 32081ad6265SDimitry Andric switch (LinkEditLoadCommand->load_command_data.cmd) { 32181ad6265SDimitry Andric case MachO::LC_SEGMENT: 32281ad6265SDimitry Andric MLC->segment_command_data.cmdsize = sizeof(MachO::segment_command); 32381ad6265SDimitry Andric MLC->segment_command_data.fileoff = StartOfLinkEdit; 32481ad6265SDimitry Andric MLC->segment_command_data.vmsize = alignTo(LinkEditSize, PageSize); 32581ad6265SDimitry Andric MLC->segment_command_data.filesize = LinkEditSize; 32681ad6265SDimitry Andric break; 32781ad6265SDimitry Andric case MachO::LC_SEGMENT_64: 32881ad6265SDimitry Andric MLC->segment_command_64_data.cmdsize = sizeof(MachO::segment_command_64); 32981ad6265SDimitry Andric MLC->segment_command_64_data.fileoff = StartOfLinkEdit; 33081ad6265SDimitry Andric MLC->segment_command_64_data.vmsize = alignTo(LinkEditSize, PageSize); 33181ad6265SDimitry Andric MLC->segment_command_64_data.filesize = LinkEditSize; 33281ad6265SDimitry Andric break; 33381ad6265SDimitry Andric } 33481ad6265SDimitry Andric } 33581ad6265SDimitry Andric 33681ad6265SDimitry Andric for (LoadCommand &LC : O.LoadCommands) { 33781ad6265SDimitry Andric auto &MLC = LC.MachOLoadCommand; 33881ad6265SDimitry Andric auto cmd = MLC.load_command_data.cmd; 33981ad6265SDimitry Andric switch (cmd) { 34081ad6265SDimitry Andric case MachO::LC_CODE_SIGNATURE: 34181ad6265SDimitry Andric MLC.linkedit_data_command_data.dataoff = StartOfCodeSignature; 34281ad6265SDimitry Andric MLC.linkedit_data_command_data.datasize = CodeSignatureSize; 34381ad6265SDimitry Andric break; 344*bdd1243dSDimitry Andric case MachO::LC_DYLIB_CODE_SIGN_DRS: 345*bdd1243dSDimitry Andric MLC.linkedit_data_command_data.dataoff = StartOfDylibCodeSignDRs; 346*bdd1243dSDimitry Andric MLC.linkedit_data_command_data.datasize = O.DylibCodeSignDRs.Data.size(); 347*bdd1243dSDimitry Andric break; 34881ad6265SDimitry Andric case MachO::LC_SYMTAB: 34981ad6265SDimitry Andric MLC.symtab_command_data.symoff = StartOfSymbols; 35081ad6265SDimitry Andric MLC.symtab_command_data.nsyms = O.SymTable.Symbols.size(); 35181ad6265SDimitry Andric MLC.symtab_command_data.stroff = StartOfSymbolStrings; 35281ad6265SDimitry Andric MLC.symtab_command_data.strsize = StrTableBuilder.getSize(); 35381ad6265SDimitry Andric break; 35481ad6265SDimitry Andric case MachO::LC_DYSYMTAB: { 35581ad6265SDimitry Andric if (MLC.dysymtab_command_data.ntoc != 0 || 35681ad6265SDimitry Andric MLC.dysymtab_command_data.nmodtab != 0 || 35781ad6265SDimitry Andric MLC.dysymtab_command_data.nextrefsyms != 0 || 35881ad6265SDimitry Andric MLC.dysymtab_command_data.nlocrel != 0 || 35981ad6265SDimitry Andric MLC.dysymtab_command_data.nextrel != 0) 36081ad6265SDimitry Andric return createStringError(llvm::errc::not_supported, 36181ad6265SDimitry Andric "shared library is not yet supported"); 36281ad6265SDimitry Andric 36381ad6265SDimitry Andric if (!O.IndirectSymTable.Symbols.empty()) { 36481ad6265SDimitry Andric MLC.dysymtab_command_data.indirectsymoff = StartOfIndirectSymbols; 36581ad6265SDimitry Andric MLC.dysymtab_command_data.nindirectsyms = 36681ad6265SDimitry Andric O.IndirectSymTable.Symbols.size(); 36781ad6265SDimitry Andric } 36881ad6265SDimitry Andric 36981ad6265SDimitry Andric updateDySymTab(MLC); 37081ad6265SDimitry Andric break; 37181ad6265SDimitry Andric } 37281ad6265SDimitry Andric case MachO::LC_DATA_IN_CODE: 37381ad6265SDimitry Andric MLC.linkedit_data_command_data.dataoff = StartOfDataInCode; 37481ad6265SDimitry Andric MLC.linkedit_data_command_data.datasize = O.DataInCode.Data.size(); 37581ad6265SDimitry Andric break; 37681ad6265SDimitry Andric case MachO::LC_LINKER_OPTIMIZATION_HINT: 37781ad6265SDimitry Andric MLC.linkedit_data_command_data.dataoff = StartOfLinkerOptimizationHint; 37881ad6265SDimitry Andric MLC.linkedit_data_command_data.datasize = 37981ad6265SDimitry Andric O.LinkerOptimizationHint.Data.size(); 38081ad6265SDimitry Andric break; 38181ad6265SDimitry Andric case MachO::LC_FUNCTION_STARTS: 38281ad6265SDimitry Andric MLC.linkedit_data_command_data.dataoff = StartOfFunctionStarts; 38381ad6265SDimitry Andric MLC.linkedit_data_command_data.datasize = O.FunctionStarts.Data.size(); 38481ad6265SDimitry Andric break; 38581ad6265SDimitry Andric case MachO::LC_DYLD_CHAINED_FIXUPS: 38681ad6265SDimitry Andric MLC.linkedit_data_command_data.dataoff = StartOfChainedFixups; 38781ad6265SDimitry Andric MLC.linkedit_data_command_data.datasize = O.ChainedFixups.Data.size(); 38881ad6265SDimitry Andric break; 38981ad6265SDimitry Andric case MachO::LC_DYLD_EXPORTS_TRIE: 39081ad6265SDimitry Andric MLC.linkedit_data_command_data.dataoff = StartOfDyldExportsTrie; 391*bdd1243dSDimitry Andric MLC.linkedit_data_command_data.datasize = DyldExportsTrieSize; 39281ad6265SDimitry Andric break; 39381ad6265SDimitry Andric case MachO::LC_DYLD_INFO: 39481ad6265SDimitry Andric case MachO::LC_DYLD_INFO_ONLY: 39581ad6265SDimitry Andric MLC.dyld_info_command_data.rebase_off = 39681ad6265SDimitry Andric O.Rebases.Opcodes.empty() ? 0 : StartOfRebaseInfo; 39781ad6265SDimitry Andric MLC.dyld_info_command_data.rebase_size = O.Rebases.Opcodes.size(); 39881ad6265SDimitry Andric MLC.dyld_info_command_data.bind_off = 39981ad6265SDimitry Andric O.Binds.Opcodes.empty() ? 0 : StartOfBindingInfo; 40081ad6265SDimitry Andric MLC.dyld_info_command_data.bind_size = O.Binds.Opcodes.size(); 40181ad6265SDimitry Andric MLC.dyld_info_command_data.weak_bind_off = 40281ad6265SDimitry Andric O.WeakBinds.Opcodes.empty() ? 0 : StartOfWeakBindingInfo; 40381ad6265SDimitry Andric MLC.dyld_info_command_data.weak_bind_size = O.WeakBinds.Opcodes.size(); 40481ad6265SDimitry Andric MLC.dyld_info_command_data.lazy_bind_off = 40581ad6265SDimitry Andric O.LazyBinds.Opcodes.empty() ? 0 : StartOfLazyBindingInfo; 40681ad6265SDimitry Andric MLC.dyld_info_command_data.lazy_bind_size = O.LazyBinds.Opcodes.size(); 40781ad6265SDimitry Andric MLC.dyld_info_command_data.export_off = 40881ad6265SDimitry Andric O.Exports.Trie.empty() ? 0 : StartOfExportTrie; 409*bdd1243dSDimitry Andric MLC.dyld_info_command_data.export_size = DyldInfoExportsTrieSize; 41081ad6265SDimitry Andric break; 41181ad6265SDimitry Andric // Note that LC_ENCRYPTION_INFO.cryptoff despite its name and the comment in 41281ad6265SDimitry Andric // <mach-o/loader.h> is not an offset in the binary file, instead, it is a 41381ad6265SDimitry Andric // relative virtual address. At the moment modification of the __TEXT 41481ad6265SDimitry Andric // segment of executables isn't supported anyway (e.g. data in code entries 41581ad6265SDimitry Andric // are not recalculated). Moreover, in general 41681ad6265SDimitry Andric // LC_ENCRYPT_INFO/LC_ENCRYPTION_INFO_64 are nontrivial to update because 41781ad6265SDimitry Andric // without making additional assumptions (e.g. that the entire __TEXT 41881ad6265SDimitry Andric // segment should be encrypted) we do not know how to recalculate the 41981ad6265SDimitry Andric // boundaries of the encrypted part. For now just copy over these load 42081ad6265SDimitry Andric // commands until we encounter a real world usecase where 42181ad6265SDimitry Andric // LC_ENCRYPT_INFO/LC_ENCRYPTION_INFO_64 need to be adjusted. 42281ad6265SDimitry Andric case MachO::LC_ENCRYPTION_INFO: 42381ad6265SDimitry Andric case MachO::LC_ENCRYPTION_INFO_64: 42481ad6265SDimitry Andric case MachO::LC_LOAD_DYLINKER: 42581ad6265SDimitry Andric case MachO::LC_MAIN: 42681ad6265SDimitry Andric case MachO::LC_RPATH: 42781ad6265SDimitry Andric case MachO::LC_SEGMENT: 42881ad6265SDimitry Andric case MachO::LC_SEGMENT_64: 42981ad6265SDimitry Andric case MachO::LC_VERSION_MIN_MACOSX: 43081ad6265SDimitry Andric case MachO::LC_VERSION_MIN_IPHONEOS: 43181ad6265SDimitry Andric case MachO::LC_VERSION_MIN_TVOS: 43281ad6265SDimitry Andric case MachO::LC_VERSION_MIN_WATCHOS: 43381ad6265SDimitry Andric case MachO::LC_BUILD_VERSION: 43481ad6265SDimitry Andric case MachO::LC_ID_DYLIB: 43581ad6265SDimitry Andric case MachO::LC_LOAD_DYLIB: 43681ad6265SDimitry Andric case MachO::LC_LOAD_WEAK_DYLIB: 43781ad6265SDimitry Andric case MachO::LC_UUID: 43881ad6265SDimitry Andric case MachO::LC_SOURCE_VERSION: 43981ad6265SDimitry Andric case MachO::LC_THREAD: 44081ad6265SDimitry Andric case MachO::LC_UNIXTHREAD: 44181ad6265SDimitry Andric case MachO::LC_SUB_FRAMEWORK: 44281ad6265SDimitry Andric case MachO::LC_SUB_UMBRELLA: 44381ad6265SDimitry Andric case MachO::LC_SUB_CLIENT: 44481ad6265SDimitry Andric case MachO::LC_SUB_LIBRARY: 44581ad6265SDimitry Andric case MachO::LC_LINKER_OPTION: 44681ad6265SDimitry Andric // Nothing to update. 44781ad6265SDimitry Andric break; 44881ad6265SDimitry Andric default: 44981ad6265SDimitry Andric // Abort if it's unsupported in order to prevent corrupting the object. 45081ad6265SDimitry Andric return createStringError(llvm::errc::not_supported, 45181ad6265SDimitry Andric "unsupported load command (cmd=0x%x)", cmd); 45281ad6265SDimitry Andric } 45381ad6265SDimitry Andric } 45481ad6265SDimitry Andric 45581ad6265SDimitry Andric return Error::success(); 45681ad6265SDimitry Andric } 45781ad6265SDimitry Andric 45881ad6265SDimitry Andric Error MachOLayoutBuilder::layout() { 45981ad6265SDimitry Andric O.Header.NCmds = O.LoadCommands.size(); 46081ad6265SDimitry Andric O.Header.SizeOfCmds = computeSizeOfCmds(); 46181ad6265SDimitry Andric constructStringTable(); 46281ad6265SDimitry Andric updateSymbolIndexes(); 46381ad6265SDimitry Andric uint64_t Offset = layoutSegments(); 46481ad6265SDimitry Andric Offset = layoutRelocations(Offset); 46581ad6265SDimitry Andric return layoutTail(Offset); 46681ad6265SDimitry Andric } 467