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