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