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