1*81ad6265SDimitry Andric //===- MachOWriter.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 "MachOWriter.h"
10*81ad6265SDimitry Andric #include "MachOLayoutBuilder.h"
11*81ad6265SDimitry Andric #include "MachOObject.h"
12*81ad6265SDimitry Andric #include "llvm/ADT/STLExtras.h"
13*81ad6265SDimitry Andric #include "llvm/BinaryFormat/MachO.h"
14*81ad6265SDimitry Andric #include "llvm/Object/MachO.h"
15*81ad6265SDimitry Andric #include "llvm/Support/Errc.h"
16*81ad6265SDimitry Andric #include "llvm/Support/ErrorHandling.h"
17*81ad6265SDimitry Andric #include "llvm/Support/SHA256.h"
18*81ad6265SDimitry Andric #include <memory>
19*81ad6265SDimitry Andric 
20*81ad6265SDimitry Andric #if defined(__APPLE__)
21*81ad6265SDimitry Andric #include <sys/mman.h>
22*81ad6265SDimitry Andric #endif
23*81ad6265SDimitry Andric 
24*81ad6265SDimitry Andric using namespace llvm;
25*81ad6265SDimitry Andric using namespace llvm::objcopy::macho;
26*81ad6265SDimitry Andric using namespace llvm::support::endian;
27*81ad6265SDimitry Andric 
28*81ad6265SDimitry Andric size_t MachOWriter::headerSize() const {
29*81ad6265SDimitry Andric   return Is64Bit ? sizeof(MachO::mach_header_64) : sizeof(MachO::mach_header);
30*81ad6265SDimitry Andric }
31*81ad6265SDimitry Andric 
32*81ad6265SDimitry Andric size_t MachOWriter::loadCommandsSize() const { return O.Header.SizeOfCmds; }
33*81ad6265SDimitry Andric 
34*81ad6265SDimitry Andric size_t MachOWriter::symTableSize() const {
35*81ad6265SDimitry Andric   return O.SymTable.Symbols.size() *
36*81ad6265SDimitry Andric          (Is64Bit ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist));
37*81ad6265SDimitry Andric }
38*81ad6265SDimitry Andric 
39*81ad6265SDimitry Andric size_t MachOWriter::totalSize() const {
40*81ad6265SDimitry Andric   // Going from tail to head and looking for an appropriate "anchor" to
41*81ad6265SDimitry Andric   // calculate the total size assuming that all the offsets are either valid
42*81ad6265SDimitry Andric   // ("true") or 0 (0 indicates that the corresponding part is missing).
43*81ad6265SDimitry Andric 
44*81ad6265SDimitry Andric   SmallVector<size_t, 7> Ends;
45*81ad6265SDimitry Andric   if (O.SymTabCommandIndex) {
46*81ad6265SDimitry Andric     const MachO::symtab_command &SymTabCommand =
47*81ad6265SDimitry Andric         O.LoadCommands[*O.SymTabCommandIndex]
48*81ad6265SDimitry Andric             .MachOLoadCommand.symtab_command_data;
49*81ad6265SDimitry Andric     if (SymTabCommand.symoff)
50*81ad6265SDimitry Andric       Ends.push_back(SymTabCommand.symoff + symTableSize());
51*81ad6265SDimitry Andric     if (SymTabCommand.stroff)
52*81ad6265SDimitry Andric       Ends.push_back(SymTabCommand.stroff + SymTabCommand.strsize);
53*81ad6265SDimitry Andric   }
54*81ad6265SDimitry Andric   if (O.DyLdInfoCommandIndex) {
55*81ad6265SDimitry Andric     const MachO::dyld_info_command &DyLdInfoCommand =
56*81ad6265SDimitry Andric         O.LoadCommands[*O.DyLdInfoCommandIndex]
57*81ad6265SDimitry Andric             .MachOLoadCommand.dyld_info_command_data;
58*81ad6265SDimitry Andric     if (DyLdInfoCommand.rebase_off) {
59*81ad6265SDimitry Andric       assert((DyLdInfoCommand.rebase_size == O.Rebases.Opcodes.size()) &&
60*81ad6265SDimitry Andric              "Incorrect rebase opcodes size");
61*81ad6265SDimitry Andric       Ends.push_back(DyLdInfoCommand.rebase_off + DyLdInfoCommand.rebase_size);
62*81ad6265SDimitry Andric     }
63*81ad6265SDimitry Andric     if (DyLdInfoCommand.bind_off) {
64*81ad6265SDimitry Andric       assert((DyLdInfoCommand.bind_size == O.Binds.Opcodes.size()) &&
65*81ad6265SDimitry Andric              "Incorrect bind opcodes size");
66*81ad6265SDimitry Andric       Ends.push_back(DyLdInfoCommand.bind_off + DyLdInfoCommand.bind_size);
67*81ad6265SDimitry Andric     }
68*81ad6265SDimitry Andric     if (DyLdInfoCommand.weak_bind_off) {
69*81ad6265SDimitry Andric       assert((DyLdInfoCommand.weak_bind_size == O.WeakBinds.Opcodes.size()) &&
70*81ad6265SDimitry Andric              "Incorrect weak bind opcodes size");
71*81ad6265SDimitry Andric       Ends.push_back(DyLdInfoCommand.weak_bind_off +
72*81ad6265SDimitry Andric                      DyLdInfoCommand.weak_bind_size);
73*81ad6265SDimitry Andric     }
74*81ad6265SDimitry Andric     if (DyLdInfoCommand.lazy_bind_off) {
75*81ad6265SDimitry Andric       assert((DyLdInfoCommand.lazy_bind_size == O.LazyBinds.Opcodes.size()) &&
76*81ad6265SDimitry Andric              "Incorrect lazy bind opcodes size");
77*81ad6265SDimitry Andric       Ends.push_back(DyLdInfoCommand.lazy_bind_off +
78*81ad6265SDimitry Andric                      DyLdInfoCommand.lazy_bind_size);
79*81ad6265SDimitry Andric     }
80*81ad6265SDimitry Andric     if (DyLdInfoCommand.export_off) {
81*81ad6265SDimitry Andric       assert((DyLdInfoCommand.export_size == O.Exports.Trie.size()) &&
82*81ad6265SDimitry Andric              "Incorrect trie size");
83*81ad6265SDimitry Andric       Ends.push_back(DyLdInfoCommand.export_off + DyLdInfoCommand.export_size);
84*81ad6265SDimitry Andric     }
85*81ad6265SDimitry Andric   }
86*81ad6265SDimitry Andric 
87*81ad6265SDimitry Andric   if (O.DySymTabCommandIndex) {
88*81ad6265SDimitry Andric     const MachO::dysymtab_command &DySymTabCommand =
89*81ad6265SDimitry Andric         O.LoadCommands[*O.DySymTabCommandIndex]
90*81ad6265SDimitry Andric             .MachOLoadCommand.dysymtab_command_data;
91*81ad6265SDimitry Andric 
92*81ad6265SDimitry Andric     if (DySymTabCommand.indirectsymoff)
93*81ad6265SDimitry Andric       Ends.push_back(DySymTabCommand.indirectsymoff +
94*81ad6265SDimitry Andric                      sizeof(uint32_t) * O.IndirectSymTable.Symbols.size());
95*81ad6265SDimitry Andric   }
96*81ad6265SDimitry Andric 
97*81ad6265SDimitry Andric   for (Optional<size_t> LinkEditDataCommandIndex :
98*81ad6265SDimitry Andric        {O.CodeSignatureCommandIndex, O.DataInCodeCommandIndex,
99*81ad6265SDimitry Andric         O.LinkerOptimizationHintCommandIndex, O.FunctionStartsCommandIndex,
100*81ad6265SDimitry Andric         O.ChainedFixupsCommandIndex, O.ExportsTrieCommandIndex})
101*81ad6265SDimitry Andric     if (LinkEditDataCommandIndex) {
102*81ad6265SDimitry Andric       const MachO::linkedit_data_command &LinkEditDataCommand =
103*81ad6265SDimitry Andric           O.LoadCommands[*LinkEditDataCommandIndex]
104*81ad6265SDimitry Andric               .MachOLoadCommand.linkedit_data_command_data;
105*81ad6265SDimitry Andric       if (LinkEditDataCommand.dataoff)
106*81ad6265SDimitry Andric         Ends.push_back(LinkEditDataCommand.dataoff +
107*81ad6265SDimitry Andric                        LinkEditDataCommand.datasize);
108*81ad6265SDimitry Andric     }
109*81ad6265SDimitry Andric 
110*81ad6265SDimitry Andric   // Otherwise, use the last section / reloction.
111*81ad6265SDimitry Andric   for (const LoadCommand &LC : O.LoadCommands)
112*81ad6265SDimitry Andric     for (const std::unique_ptr<Section> &S : LC.Sections) {
113*81ad6265SDimitry Andric       if (!S->hasValidOffset()) {
114*81ad6265SDimitry Andric         assert((S->Offset == 0) && "Skipped section's offset must be zero");
115*81ad6265SDimitry Andric         assert((S->isVirtualSection() || S->Size == 0) &&
116*81ad6265SDimitry Andric                "Non-zero-fill sections with zero offset must have zero size");
117*81ad6265SDimitry Andric         continue;
118*81ad6265SDimitry Andric       }
119*81ad6265SDimitry Andric       assert((S->Offset != 0) &&
120*81ad6265SDimitry Andric              "Non-zero-fill section's offset cannot be zero");
121*81ad6265SDimitry Andric       Ends.push_back(S->Offset + S->Size);
122*81ad6265SDimitry Andric       if (S->RelOff)
123*81ad6265SDimitry Andric         Ends.push_back(S->RelOff +
124*81ad6265SDimitry Andric                        S->NReloc * sizeof(MachO::any_relocation_info));
125*81ad6265SDimitry Andric     }
126*81ad6265SDimitry Andric 
127*81ad6265SDimitry Andric   if (!Ends.empty())
128*81ad6265SDimitry Andric     return *std::max_element(Ends.begin(), Ends.end());
129*81ad6265SDimitry Andric 
130*81ad6265SDimitry Andric   // Otherwise, we have only Mach header and load commands.
131*81ad6265SDimitry Andric   return headerSize() + loadCommandsSize();
132*81ad6265SDimitry Andric }
133*81ad6265SDimitry Andric 
134*81ad6265SDimitry Andric void MachOWriter::writeHeader() {
135*81ad6265SDimitry Andric   MachO::mach_header_64 Header;
136*81ad6265SDimitry Andric 
137*81ad6265SDimitry Andric   Header.magic = O.Header.Magic;
138*81ad6265SDimitry Andric   Header.cputype = O.Header.CPUType;
139*81ad6265SDimitry Andric   Header.cpusubtype = O.Header.CPUSubType;
140*81ad6265SDimitry Andric   Header.filetype = O.Header.FileType;
141*81ad6265SDimitry Andric   Header.ncmds = O.Header.NCmds;
142*81ad6265SDimitry Andric   Header.sizeofcmds = O.Header.SizeOfCmds;
143*81ad6265SDimitry Andric   Header.flags = O.Header.Flags;
144*81ad6265SDimitry Andric   Header.reserved = O.Header.Reserved;
145*81ad6265SDimitry Andric 
146*81ad6265SDimitry Andric   if (IsLittleEndian != sys::IsLittleEndianHost)
147*81ad6265SDimitry Andric     MachO::swapStruct(Header);
148*81ad6265SDimitry Andric 
149*81ad6265SDimitry Andric   auto HeaderSize =
150*81ad6265SDimitry Andric       Is64Bit ? sizeof(MachO::mach_header_64) : sizeof(MachO::mach_header);
151*81ad6265SDimitry Andric   memcpy(Buf->getBufferStart(), &Header, HeaderSize);
152*81ad6265SDimitry Andric }
153*81ad6265SDimitry Andric 
154*81ad6265SDimitry Andric void MachOWriter::writeLoadCommands() {
155*81ad6265SDimitry Andric   uint8_t *Begin =
156*81ad6265SDimitry Andric       reinterpret_cast<uint8_t *>(Buf->getBufferStart()) + headerSize();
157*81ad6265SDimitry Andric   for (const LoadCommand &LC : O.LoadCommands) {
158*81ad6265SDimitry Andric     // Construct a load command.
159*81ad6265SDimitry Andric     MachO::macho_load_command MLC = LC.MachOLoadCommand;
160*81ad6265SDimitry Andric     switch (MLC.load_command_data.cmd) {
161*81ad6265SDimitry Andric     case MachO::LC_SEGMENT:
162*81ad6265SDimitry Andric       if (IsLittleEndian != sys::IsLittleEndianHost)
163*81ad6265SDimitry Andric         MachO::swapStruct(MLC.segment_command_data);
164*81ad6265SDimitry Andric       memcpy(Begin, &MLC.segment_command_data, sizeof(MachO::segment_command));
165*81ad6265SDimitry Andric       Begin += sizeof(MachO::segment_command);
166*81ad6265SDimitry Andric 
167*81ad6265SDimitry Andric       for (const std::unique_ptr<Section> &Sec : LC.Sections)
168*81ad6265SDimitry Andric         writeSectionInLoadCommand<MachO::section>(*Sec, Begin);
169*81ad6265SDimitry Andric       continue;
170*81ad6265SDimitry Andric     case MachO::LC_SEGMENT_64:
171*81ad6265SDimitry Andric       if (IsLittleEndian != sys::IsLittleEndianHost)
172*81ad6265SDimitry Andric         MachO::swapStruct(MLC.segment_command_64_data);
173*81ad6265SDimitry Andric       memcpy(Begin, &MLC.segment_command_64_data,
174*81ad6265SDimitry Andric              sizeof(MachO::segment_command_64));
175*81ad6265SDimitry Andric       Begin += sizeof(MachO::segment_command_64);
176*81ad6265SDimitry Andric 
177*81ad6265SDimitry Andric       for (const std::unique_ptr<Section> &Sec : LC.Sections)
178*81ad6265SDimitry Andric         writeSectionInLoadCommand<MachO::section_64>(*Sec, Begin);
179*81ad6265SDimitry Andric       continue;
180*81ad6265SDimitry Andric     }
181*81ad6265SDimitry Andric 
182*81ad6265SDimitry Andric #define HANDLE_LOAD_COMMAND(LCName, LCValue, LCStruct)                         \
183*81ad6265SDimitry Andric   case MachO::LCName:                                                          \
184*81ad6265SDimitry Andric     assert(sizeof(MachO::LCStruct) + LC.Payload.size() ==                      \
185*81ad6265SDimitry Andric            MLC.load_command_data.cmdsize);                                     \
186*81ad6265SDimitry Andric     if (IsLittleEndian != sys::IsLittleEndianHost)                             \
187*81ad6265SDimitry Andric       MachO::swapStruct(MLC.LCStruct##_data);                                  \
188*81ad6265SDimitry Andric     memcpy(Begin, &MLC.LCStruct##_data, sizeof(MachO::LCStruct));              \
189*81ad6265SDimitry Andric     Begin += sizeof(MachO::LCStruct);                                          \
190*81ad6265SDimitry Andric     if (!LC.Payload.empty())                                                   \
191*81ad6265SDimitry Andric       memcpy(Begin, LC.Payload.data(), LC.Payload.size());                     \
192*81ad6265SDimitry Andric     Begin += LC.Payload.size();                                                \
193*81ad6265SDimitry Andric     break;
194*81ad6265SDimitry Andric 
195*81ad6265SDimitry Andric     // Copy the load command as it is.
196*81ad6265SDimitry Andric     switch (MLC.load_command_data.cmd) {
197*81ad6265SDimitry Andric     default:
198*81ad6265SDimitry Andric       assert(sizeof(MachO::load_command) + LC.Payload.size() ==
199*81ad6265SDimitry Andric              MLC.load_command_data.cmdsize);
200*81ad6265SDimitry Andric       if (IsLittleEndian != sys::IsLittleEndianHost)
201*81ad6265SDimitry Andric         MachO::swapStruct(MLC.load_command_data);
202*81ad6265SDimitry Andric       memcpy(Begin, &MLC.load_command_data, sizeof(MachO::load_command));
203*81ad6265SDimitry Andric       Begin += sizeof(MachO::load_command);
204*81ad6265SDimitry Andric       if (!LC.Payload.empty())
205*81ad6265SDimitry Andric         memcpy(Begin, LC.Payload.data(), LC.Payload.size());
206*81ad6265SDimitry Andric       Begin += LC.Payload.size();
207*81ad6265SDimitry Andric       break;
208*81ad6265SDimitry Andric #include "llvm/BinaryFormat/MachO.def"
209*81ad6265SDimitry Andric     }
210*81ad6265SDimitry Andric   }
211*81ad6265SDimitry Andric }
212*81ad6265SDimitry Andric 
213*81ad6265SDimitry Andric template <typename StructType>
214*81ad6265SDimitry Andric void MachOWriter::writeSectionInLoadCommand(const Section &Sec, uint8_t *&Out) {
215*81ad6265SDimitry Andric   StructType Temp;
216*81ad6265SDimitry Andric   assert(Sec.Segname.size() <= sizeof(Temp.segname) && "too long segment name");
217*81ad6265SDimitry Andric   assert(Sec.Sectname.size() <= sizeof(Temp.sectname) &&
218*81ad6265SDimitry Andric          "too long section name");
219*81ad6265SDimitry Andric   memset(&Temp, 0, sizeof(StructType));
220*81ad6265SDimitry Andric   memcpy(Temp.segname, Sec.Segname.data(), Sec.Segname.size());
221*81ad6265SDimitry Andric   memcpy(Temp.sectname, Sec.Sectname.data(), Sec.Sectname.size());
222*81ad6265SDimitry Andric   Temp.addr = Sec.Addr;
223*81ad6265SDimitry Andric   Temp.size = Sec.Size;
224*81ad6265SDimitry Andric   Temp.offset = Sec.Offset;
225*81ad6265SDimitry Andric   Temp.align = Sec.Align;
226*81ad6265SDimitry Andric   Temp.reloff = Sec.RelOff;
227*81ad6265SDimitry Andric   Temp.nreloc = Sec.NReloc;
228*81ad6265SDimitry Andric   Temp.flags = Sec.Flags;
229*81ad6265SDimitry Andric   Temp.reserved1 = Sec.Reserved1;
230*81ad6265SDimitry Andric   Temp.reserved2 = Sec.Reserved2;
231*81ad6265SDimitry Andric 
232*81ad6265SDimitry Andric   if (IsLittleEndian != sys::IsLittleEndianHost)
233*81ad6265SDimitry Andric     MachO::swapStruct(Temp);
234*81ad6265SDimitry Andric   memcpy(Out, &Temp, sizeof(StructType));
235*81ad6265SDimitry Andric   Out += sizeof(StructType);
236*81ad6265SDimitry Andric }
237*81ad6265SDimitry Andric 
238*81ad6265SDimitry Andric void MachOWriter::writeSections() {
239*81ad6265SDimitry Andric   for (const LoadCommand &LC : O.LoadCommands)
240*81ad6265SDimitry Andric     for (const std::unique_ptr<Section> &Sec : LC.Sections) {
241*81ad6265SDimitry Andric       if (!Sec->hasValidOffset()) {
242*81ad6265SDimitry Andric         assert((Sec->Offset == 0) && "Skipped section's offset must be zero");
243*81ad6265SDimitry Andric         assert((Sec->isVirtualSection() || Sec->Size == 0) &&
244*81ad6265SDimitry Andric                "Non-zero-fill sections with zero offset must have zero size");
245*81ad6265SDimitry Andric         continue;
246*81ad6265SDimitry Andric       }
247*81ad6265SDimitry Andric 
248*81ad6265SDimitry Andric       assert(Sec->Offset && "Section offset can not be zero");
249*81ad6265SDimitry Andric       assert((Sec->Size == Sec->Content.size()) && "Incorrect section size");
250*81ad6265SDimitry Andric       memcpy(Buf->getBufferStart() + Sec->Offset, Sec->Content.data(),
251*81ad6265SDimitry Andric              Sec->Content.size());
252*81ad6265SDimitry Andric       for (size_t Index = 0; Index < Sec->Relocations.size(); ++Index) {
253*81ad6265SDimitry Andric         RelocationInfo RelocInfo = Sec->Relocations[Index];
254*81ad6265SDimitry Andric         if (!RelocInfo.Scattered && !RelocInfo.IsAddend) {
255*81ad6265SDimitry Andric           const uint32_t SymbolNum = RelocInfo.Extern
256*81ad6265SDimitry Andric                                          ? (*RelocInfo.Symbol)->Index
257*81ad6265SDimitry Andric                                          : (*RelocInfo.Sec)->Index;
258*81ad6265SDimitry Andric           RelocInfo.setPlainRelocationSymbolNum(SymbolNum, IsLittleEndian);
259*81ad6265SDimitry Andric         }
260*81ad6265SDimitry Andric         if (IsLittleEndian != sys::IsLittleEndianHost)
261*81ad6265SDimitry Andric           MachO::swapStruct(
262*81ad6265SDimitry Andric               reinterpret_cast<MachO::any_relocation_info &>(RelocInfo.Info));
263*81ad6265SDimitry Andric         memcpy(Buf->getBufferStart() + Sec->RelOff +
264*81ad6265SDimitry Andric                    Index * sizeof(MachO::any_relocation_info),
265*81ad6265SDimitry Andric                &RelocInfo.Info, sizeof(RelocInfo.Info));
266*81ad6265SDimitry Andric       }
267*81ad6265SDimitry Andric     }
268*81ad6265SDimitry Andric }
269*81ad6265SDimitry Andric 
270*81ad6265SDimitry Andric template <typename NListType>
271*81ad6265SDimitry Andric void writeNListEntry(const SymbolEntry &SE, bool IsLittleEndian, char *&Out,
272*81ad6265SDimitry Andric                      uint32_t Nstrx) {
273*81ad6265SDimitry Andric   NListType ListEntry;
274*81ad6265SDimitry Andric   ListEntry.n_strx = Nstrx;
275*81ad6265SDimitry Andric   ListEntry.n_type = SE.n_type;
276*81ad6265SDimitry Andric   ListEntry.n_sect = SE.n_sect;
277*81ad6265SDimitry Andric   ListEntry.n_desc = SE.n_desc;
278*81ad6265SDimitry Andric   ListEntry.n_value = SE.n_value;
279*81ad6265SDimitry Andric 
280*81ad6265SDimitry Andric   if (IsLittleEndian != sys::IsLittleEndianHost)
281*81ad6265SDimitry Andric     MachO::swapStruct(ListEntry);
282*81ad6265SDimitry Andric   memcpy(Out, reinterpret_cast<const char *>(&ListEntry), sizeof(NListType));
283*81ad6265SDimitry Andric   Out += sizeof(NListType);
284*81ad6265SDimitry Andric }
285*81ad6265SDimitry Andric 
286*81ad6265SDimitry Andric void MachOWriter::writeStringTable() {
287*81ad6265SDimitry Andric   if (!O.SymTabCommandIndex)
288*81ad6265SDimitry Andric     return;
289*81ad6265SDimitry Andric   const MachO::symtab_command &SymTabCommand =
290*81ad6265SDimitry Andric       O.LoadCommands[*O.SymTabCommandIndex]
291*81ad6265SDimitry Andric           .MachOLoadCommand.symtab_command_data;
292*81ad6265SDimitry Andric 
293*81ad6265SDimitry Andric   uint8_t *StrTable = (uint8_t *)Buf->getBufferStart() + SymTabCommand.stroff;
294*81ad6265SDimitry Andric   LayoutBuilder.getStringTableBuilder().write(StrTable);
295*81ad6265SDimitry Andric }
296*81ad6265SDimitry Andric 
297*81ad6265SDimitry Andric void MachOWriter::writeSymbolTable() {
298*81ad6265SDimitry Andric   if (!O.SymTabCommandIndex)
299*81ad6265SDimitry Andric     return;
300*81ad6265SDimitry Andric   const MachO::symtab_command &SymTabCommand =
301*81ad6265SDimitry Andric       O.LoadCommands[*O.SymTabCommandIndex]
302*81ad6265SDimitry Andric           .MachOLoadCommand.symtab_command_data;
303*81ad6265SDimitry Andric 
304*81ad6265SDimitry Andric   char *SymTable = (char *)Buf->getBufferStart() + SymTabCommand.symoff;
305*81ad6265SDimitry Andric   for (auto Iter = O.SymTable.Symbols.begin(), End = O.SymTable.Symbols.end();
306*81ad6265SDimitry Andric        Iter != End; Iter++) {
307*81ad6265SDimitry Andric     SymbolEntry *Sym = Iter->get();
308*81ad6265SDimitry Andric     uint32_t Nstrx = LayoutBuilder.getStringTableBuilder().getOffset(Sym->Name);
309*81ad6265SDimitry Andric 
310*81ad6265SDimitry Andric     if (Is64Bit)
311*81ad6265SDimitry Andric       writeNListEntry<MachO::nlist_64>(*Sym, IsLittleEndian, SymTable, Nstrx);
312*81ad6265SDimitry Andric     else
313*81ad6265SDimitry Andric       writeNListEntry<MachO::nlist>(*Sym, IsLittleEndian, SymTable, Nstrx);
314*81ad6265SDimitry Andric   }
315*81ad6265SDimitry Andric }
316*81ad6265SDimitry Andric 
317*81ad6265SDimitry Andric void MachOWriter::writeRebaseInfo() {
318*81ad6265SDimitry Andric   if (!O.DyLdInfoCommandIndex)
319*81ad6265SDimitry Andric     return;
320*81ad6265SDimitry Andric   const MachO::dyld_info_command &DyLdInfoCommand =
321*81ad6265SDimitry Andric       O.LoadCommands[*O.DyLdInfoCommandIndex]
322*81ad6265SDimitry Andric           .MachOLoadCommand.dyld_info_command_data;
323*81ad6265SDimitry Andric   char *Out = (char *)Buf->getBufferStart() + DyLdInfoCommand.rebase_off;
324*81ad6265SDimitry Andric   assert((DyLdInfoCommand.rebase_size == O.Rebases.Opcodes.size()) &&
325*81ad6265SDimitry Andric          "Incorrect rebase opcodes size");
326*81ad6265SDimitry Andric   memcpy(Out, O.Rebases.Opcodes.data(), O.Rebases.Opcodes.size());
327*81ad6265SDimitry Andric }
328*81ad6265SDimitry Andric 
329*81ad6265SDimitry Andric void MachOWriter::writeBindInfo() {
330*81ad6265SDimitry Andric   if (!O.DyLdInfoCommandIndex)
331*81ad6265SDimitry Andric     return;
332*81ad6265SDimitry Andric   const MachO::dyld_info_command &DyLdInfoCommand =
333*81ad6265SDimitry Andric       O.LoadCommands[*O.DyLdInfoCommandIndex]
334*81ad6265SDimitry Andric           .MachOLoadCommand.dyld_info_command_data;
335*81ad6265SDimitry Andric   char *Out = (char *)Buf->getBufferStart() + DyLdInfoCommand.bind_off;
336*81ad6265SDimitry Andric   assert((DyLdInfoCommand.bind_size == O.Binds.Opcodes.size()) &&
337*81ad6265SDimitry Andric          "Incorrect bind opcodes size");
338*81ad6265SDimitry Andric   memcpy(Out, O.Binds.Opcodes.data(), O.Binds.Opcodes.size());
339*81ad6265SDimitry Andric }
340*81ad6265SDimitry Andric 
341*81ad6265SDimitry Andric void MachOWriter::writeWeakBindInfo() {
342*81ad6265SDimitry Andric   if (!O.DyLdInfoCommandIndex)
343*81ad6265SDimitry Andric     return;
344*81ad6265SDimitry Andric   const MachO::dyld_info_command &DyLdInfoCommand =
345*81ad6265SDimitry Andric       O.LoadCommands[*O.DyLdInfoCommandIndex]
346*81ad6265SDimitry Andric           .MachOLoadCommand.dyld_info_command_data;
347*81ad6265SDimitry Andric   char *Out = (char *)Buf->getBufferStart() + DyLdInfoCommand.weak_bind_off;
348*81ad6265SDimitry Andric   assert((DyLdInfoCommand.weak_bind_size == O.WeakBinds.Opcodes.size()) &&
349*81ad6265SDimitry Andric          "Incorrect weak bind opcodes size");
350*81ad6265SDimitry Andric   memcpy(Out, O.WeakBinds.Opcodes.data(), O.WeakBinds.Opcodes.size());
351*81ad6265SDimitry Andric }
352*81ad6265SDimitry Andric 
353*81ad6265SDimitry Andric void MachOWriter::writeLazyBindInfo() {
354*81ad6265SDimitry Andric   if (!O.DyLdInfoCommandIndex)
355*81ad6265SDimitry Andric     return;
356*81ad6265SDimitry Andric   const MachO::dyld_info_command &DyLdInfoCommand =
357*81ad6265SDimitry Andric       O.LoadCommands[*O.DyLdInfoCommandIndex]
358*81ad6265SDimitry Andric           .MachOLoadCommand.dyld_info_command_data;
359*81ad6265SDimitry Andric   char *Out = (char *)Buf->getBufferStart() + DyLdInfoCommand.lazy_bind_off;
360*81ad6265SDimitry Andric   assert((DyLdInfoCommand.lazy_bind_size == O.LazyBinds.Opcodes.size()) &&
361*81ad6265SDimitry Andric          "Incorrect lazy bind opcodes size");
362*81ad6265SDimitry Andric   memcpy(Out, O.LazyBinds.Opcodes.data(), O.LazyBinds.Opcodes.size());
363*81ad6265SDimitry Andric }
364*81ad6265SDimitry Andric 
365*81ad6265SDimitry Andric void MachOWriter::writeExportInfo() {
366*81ad6265SDimitry Andric   if (!O.DyLdInfoCommandIndex)
367*81ad6265SDimitry Andric     return;
368*81ad6265SDimitry Andric   const MachO::dyld_info_command &DyLdInfoCommand =
369*81ad6265SDimitry Andric       O.LoadCommands[*O.DyLdInfoCommandIndex]
370*81ad6265SDimitry Andric           .MachOLoadCommand.dyld_info_command_data;
371*81ad6265SDimitry Andric   char *Out = (char *)Buf->getBufferStart() + DyLdInfoCommand.export_off;
372*81ad6265SDimitry Andric   assert((DyLdInfoCommand.export_size == O.Exports.Trie.size()) &&
373*81ad6265SDimitry Andric          "Incorrect export trie size");
374*81ad6265SDimitry Andric   memcpy(Out, O.Exports.Trie.data(), O.Exports.Trie.size());
375*81ad6265SDimitry Andric }
376*81ad6265SDimitry Andric 
377*81ad6265SDimitry Andric void MachOWriter::writeIndirectSymbolTable() {
378*81ad6265SDimitry Andric   if (!O.DySymTabCommandIndex)
379*81ad6265SDimitry Andric     return;
380*81ad6265SDimitry Andric 
381*81ad6265SDimitry Andric   const MachO::dysymtab_command &DySymTabCommand =
382*81ad6265SDimitry Andric       O.LoadCommands[*O.DySymTabCommandIndex]
383*81ad6265SDimitry Andric           .MachOLoadCommand.dysymtab_command_data;
384*81ad6265SDimitry Andric 
385*81ad6265SDimitry Andric   uint32_t *Out =
386*81ad6265SDimitry Andric       (uint32_t *)(Buf->getBufferStart() + DySymTabCommand.indirectsymoff);
387*81ad6265SDimitry Andric   for (const IndirectSymbolEntry &Sym : O.IndirectSymTable.Symbols) {
388*81ad6265SDimitry Andric     uint32_t Entry = (Sym.Symbol) ? (*Sym.Symbol)->Index : Sym.OriginalIndex;
389*81ad6265SDimitry Andric     if (IsLittleEndian != sys::IsLittleEndianHost)
390*81ad6265SDimitry Andric       sys::swapByteOrder(Entry);
391*81ad6265SDimitry Andric     *Out++ = Entry;
392*81ad6265SDimitry Andric   }
393*81ad6265SDimitry Andric }
394*81ad6265SDimitry Andric 
395*81ad6265SDimitry Andric void MachOWriter::writeLinkData(Optional<size_t> LCIndex, const LinkData &LD) {
396*81ad6265SDimitry Andric   if (!LCIndex)
397*81ad6265SDimitry Andric     return;
398*81ad6265SDimitry Andric   const MachO::linkedit_data_command &LinkEditDataCommand =
399*81ad6265SDimitry Andric       O.LoadCommands[*LCIndex].MachOLoadCommand.linkedit_data_command_data;
400*81ad6265SDimitry Andric   char *Out = (char *)Buf->getBufferStart() + LinkEditDataCommand.dataoff;
401*81ad6265SDimitry Andric   assert((LinkEditDataCommand.datasize == LD.Data.size()) &&
402*81ad6265SDimitry Andric          "Incorrect data size");
403*81ad6265SDimitry Andric   memcpy(Out, LD.Data.data(), LD.Data.size());
404*81ad6265SDimitry Andric }
405*81ad6265SDimitry Andric 
406*81ad6265SDimitry Andric static uint64_t
407*81ad6265SDimitry Andric getSegmentFileOffset(const LoadCommand &TextSegmentLoadCommand) {
408*81ad6265SDimitry Andric   const MachO::macho_load_command &MLC =
409*81ad6265SDimitry Andric       TextSegmentLoadCommand.MachOLoadCommand;
410*81ad6265SDimitry Andric   switch (MLC.load_command_data.cmd) {
411*81ad6265SDimitry Andric   case MachO::LC_SEGMENT:
412*81ad6265SDimitry Andric     return MLC.segment_command_data.fileoff;
413*81ad6265SDimitry Andric   case MachO::LC_SEGMENT_64:
414*81ad6265SDimitry Andric     return MLC.segment_command_64_data.fileoff;
415*81ad6265SDimitry Andric   default:
416*81ad6265SDimitry Andric     return 0;
417*81ad6265SDimitry Andric   }
418*81ad6265SDimitry Andric }
419*81ad6265SDimitry Andric 
420*81ad6265SDimitry Andric static uint64_t getSegmentFileSize(const LoadCommand &TextSegmentLoadCommand) {
421*81ad6265SDimitry Andric   const MachO::macho_load_command &MLC =
422*81ad6265SDimitry Andric       TextSegmentLoadCommand.MachOLoadCommand;
423*81ad6265SDimitry Andric   switch (MLC.load_command_data.cmd) {
424*81ad6265SDimitry Andric   case MachO::LC_SEGMENT:
425*81ad6265SDimitry Andric     return MLC.segment_command_data.filesize;
426*81ad6265SDimitry Andric   case MachO::LC_SEGMENT_64:
427*81ad6265SDimitry Andric     return MLC.segment_command_64_data.filesize;
428*81ad6265SDimitry Andric   default:
429*81ad6265SDimitry Andric     return 0;
430*81ad6265SDimitry Andric   }
431*81ad6265SDimitry Andric }
432*81ad6265SDimitry Andric 
433*81ad6265SDimitry Andric void MachOWriter::writeCodeSignatureData() {
434*81ad6265SDimitry Andric   // NOTE: This CodeSignature section behaviour must be kept in sync with that
435*81ad6265SDimitry Andric   // performed in LLD's CodeSignatureSection::write /
436*81ad6265SDimitry Andric   // CodeSignatureSection::writeHashes. Furthermore, this call must occur only
437*81ad6265SDimitry Andric   // after the rest of the binary has already been written to the buffer. This
438*81ad6265SDimitry Andric   // is because the buffer is read from to perform the necessary hashing.
439*81ad6265SDimitry Andric 
440*81ad6265SDimitry Andric   // The CodeSignature section is the last section in the MachO binary and
441*81ad6265SDimitry Andric   // contains a hash of all content in the binary before it. Since llvm-objcopy
442*81ad6265SDimitry Andric   // has likely modified the target binary, the hash must be regenerated
443*81ad6265SDimitry Andric   // entirely. To generate this hash, we must read from the start of the binary
444*81ad6265SDimitry Andric   // (HashReadStart) to just before the start of the CodeSignature section
445*81ad6265SDimitry Andric   // (HashReadEnd).
446*81ad6265SDimitry Andric 
447*81ad6265SDimitry Andric   const CodeSignatureInfo &CodeSignature = LayoutBuilder.getCodeSignature();
448*81ad6265SDimitry Andric 
449*81ad6265SDimitry Andric   uint8_t *BufferStart = reinterpret_cast<uint8_t *>(Buf->getBufferStart());
450*81ad6265SDimitry Andric   uint8_t *HashReadStart = BufferStart;
451*81ad6265SDimitry Andric   uint8_t *HashReadEnd = BufferStart + CodeSignature.StartOffset;
452*81ad6265SDimitry Andric 
453*81ad6265SDimitry Andric   // The CodeSignature section begins with a header, after which the hashes
454*81ad6265SDimitry Andric   // of each page of the binary are written.
455*81ad6265SDimitry Andric   uint8_t *HashWriteStart = HashReadEnd + CodeSignature.AllHeadersSize;
456*81ad6265SDimitry Andric 
457*81ad6265SDimitry Andric   uint32_t TextSegmentFileOff = 0;
458*81ad6265SDimitry Andric   uint32_t TextSegmentFileSize = 0;
459*81ad6265SDimitry Andric   if (O.TextSegmentCommandIndex) {
460*81ad6265SDimitry Andric     const LoadCommand &TextSegmentLoadCommand =
461*81ad6265SDimitry Andric         O.LoadCommands[*O.TextSegmentCommandIndex];
462*81ad6265SDimitry Andric     assert(TextSegmentLoadCommand.MachOLoadCommand.load_command_data.cmd ==
463*81ad6265SDimitry Andric                MachO::LC_SEGMENT ||
464*81ad6265SDimitry Andric            TextSegmentLoadCommand.MachOLoadCommand.load_command_data.cmd ==
465*81ad6265SDimitry Andric                MachO::LC_SEGMENT_64);
466*81ad6265SDimitry Andric     assert(StringRef(TextSegmentLoadCommand.MachOLoadCommand
467*81ad6265SDimitry Andric                          .segment_command_data.segname) == "__TEXT");
468*81ad6265SDimitry Andric     TextSegmentFileOff = getSegmentFileOffset(TextSegmentLoadCommand);
469*81ad6265SDimitry Andric     TextSegmentFileSize = getSegmentFileSize(TextSegmentLoadCommand);
470*81ad6265SDimitry Andric   }
471*81ad6265SDimitry Andric 
472*81ad6265SDimitry Andric   const uint32_t FileNamePad = CodeSignature.AllHeadersSize -
473*81ad6265SDimitry Andric                                CodeSignature.FixedHeadersSize -
474*81ad6265SDimitry Andric                                CodeSignature.OutputFileName.size();
475*81ad6265SDimitry Andric 
476*81ad6265SDimitry Andric   // Write code section header.
477*81ad6265SDimitry Andric   auto *SuperBlob = reinterpret_cast<MachO::CS_SuperBlob *>(HashReadEnd);
478*81ad6265SDimitry Andric   write32be(&SuperBlob->magic, MachO::CSMAGIC_EMBEDDED_SIGNATURE);
479*81ad6265SDimitry Andric   write32be(&SuperBlob->length, CodeSignature.Size);
480*81ad6265SDimitry Andric   write32be(&SuperBlob->count, 1);
481*81ad6265SDimitry Andric   auto *BlobIndex = reinterpret_cast<MachO::CS_BlobIndex *>(&SuperBlob[1]);
482*81ad6265SDimitry Andric   write32be(&BlobIndex->type, MachO::CSSLOT_CODEDIRECTORY);
483*81ad6265SDimitry Andric   write32be(&BlobIndex->offset, CodeSignature.BlobHeadersSize);
484*81ad6265SDimitry Andric   auto *CodeDirectory = reinterpret_cast<MachO::CS_CodeDirectory *>(
485*81ad6265SDimitry Andric       HashReadEnd + CodeSignature.BlobHeadersSize);
486*81ad6265SDimitry Andric   write32be(&CodeDirectory->magic, MachO::CSMAGIC_CODEDIRECTORY);
487*81ad6265SDimitry Andric   write32be(&CodeDirectory->length,
488*81ad6265SDimitry Andric             CodeSignature.Size - CodeSignature.BlobHeadersSize);
489*81ad6265SDimitry Andric   write32be(&CodeDirectory->version, MachO::CS_SUPPORTSEXECSEG);
490*81ad6265SDimitry Andric   write32be(&CodeDirectory->flags, MachO::CS_ADHOC | MachO::CS_LINKER_SIGNED);
491*81ad6265SDimitry Andric   write32be(&CodeDirectory->hashOffset,
492*81ad6265SDimitry Andric             sizeof(MachO::CS_CodeDirectory) +
493*81ad6265SDimitry Andric                 CodeSignature.OutputFileName.size() + FileNamePad);
494*81ad6265SDimitry Andric   write32be(&CodeDirectory->identOffset, sizeof(MachO::CS_CodeDirectory));
495*81ad6265SDimitry Andric   CodeDirectory->nSpecialSlots = 0;
496*81ad6265SDimitry Andric   write32be(&CodeDirectory->nCodeSlots, CodeSignature.BlockCount);
497*81ad6265SDimitry Andric   write32be(&CodeDirectory->codeLimit, CodeSignature.StartOffset);
498*81ad6265SDimitry Andric   CodeDirectory->hashSize = static_cast<uint8_t>(CodeSignature.HashSize);
499*81ad6265SDimitry Andric   CodeDirectory->hashType = MachO::kSecCodeSignatureHashSHA256;
500*81ad6265SDimitry Andric   CodeDirectory->platform = 0;
501*81ad6265SDimitry Andric   CodeDirectory->pageSize = CodeSignature.BlockSizeShift;
502*81ad6265SDimitry Andric   CodeDirectory->spare2 = 0;
503*81ad6265SDimitry Andric   CodeDirectory->scatterOffset = 0;
504*81ad6265SDimitry Andric   CodeDirectory->teamOffset = 0;
505*81ad6265SDimitry Andric   CodeDirectory->spare3 = 0;
506*81ad6265SDimitry Andric   CodeDirectory->codeLimit64 = 0;
507*81ad6265SDimitry Andric   write64be(&CodeDirectory->execSegBase, TextSegmentFileOff);
508*81ad6265SDimitry Andric   write64be(&CodeDirectory->execSegLimit, TextSegmentFileSize);
509*81ad6265SDimitry Andric   write64be(&CodeDirectory->execSegFlags, O.Header.FileType == MachO::MH_EXECUTE
510*81ad6265SDimitry Andric                                               ? MachO::CS_EXECSEG_MAIN_BINARY
511*81ad6265SDimitry Andric                                               : 0);
512*81ad6265SDimitry Andric 
513*81ad6265SDimitry Andric   auto *Id = reinterpret_cast<char *>(&CodeDirectory[1]);
514*81ad6265SDimitry Andric   memcpy(Id, CodeSignature.OutputFileName.begin(),
515*81ad6265SDimitry Andric          CodeSignature.OutputFileName.size());
516*81ad6265SDimitry Andric   memset(Id + CodeSignature.OutputFileName.size(), 0, FileNamePad);
517*81ad6265SDimitry Andric 
518*81ad6265SDimitry Andric   // Write the hashes.
519*81ad6265SDimitry Andric   uint8_t *CurrHashReadPosition = HashReadStart;
520*81ad6265SDimitry Andric   uint8_t *CurrHashWritePosition = HashWriteStart;
521*81ad6265SDimitry Andric   while (CurrHashReadPosition < HashReadEnd) {
522*81ad6265SDimitry Andric     StringRef Block(reinterpret_cast<char *>(CurrHashReadPosition),
523*81ad6265SDimitry Andric                     std::min(static_cast<size_t>(HashReadEnd
524*81ad6265SDimitry Andric                              - CurrHashReadPosition),
525*81ad6265SDimitry Andric                              static_cast<size_t>(CodeSignature.BlockSize)));
526*81ad6265SDimitry Andric     SHA256 Hasher;
527*81ad6265SDimitry Andric     Hasher.update(Block);
528*81ad6265SDimitry Andric     std::array<uint8_t, 32> Hash = Hasher.final();
529*81ad6265SDimitry Andric     assert(Hash.size() == CodeSignature.HashSize);
530*81ad6265SDimitry Andric     memcpy(CurrHashWritePosition, Hash.data(), CodeSignature.HashSize);
531*81ad6265SDimitry Andric     CurrHashReadPosition += CodeSignature.BlockSize;
532*81ad6265SDimitry Andric     CurrHashWritePosition += CodeSignature.HashSize;
533*81ad6265SDimitry Andric   }
534*81ad6265SDimitry Andric #if defined(__APPLE__)
535*81ad6265SDimitry Andric   // This is macOS-specific work-around and makes no sense for any
536*81ad6265SDimitry Andric   // other host OS. See https://openradar.appspot.com/FB8914231
537*81ad6265SDimitry Andric   //
538*81ad6265SDimitry Andric   // The macOS kernel maintains a signature-verification cache to
539*81ad6265SDimitry Andric   // quickly validate applications at time of execve(2).  The trouble
540*81ad6265SDimitry Andric   // is that for the kernel creates the cache entry at the time of the
541*81ad6265SDimitry Andric   // mmap(2) call, before we have a chance to write either the code to
542*81ad6265SDimitry Andric   // sign or the signature header+hashes.  The fix is to invalidate
543*81ad6265SDimitry Andric   // all cached data associated with the output file, thus discarding
544*81ad6265SDimitry Andric   // the bogus prematurely-cached signature.
545*81ad6265SDimitry Andric   msync(BufferStart, CodeSignature.StartOffset + CodeSignature.Size,
546*81ad6265SDimitry Andric         MS_INVALIDATE);
547*81ad6265SDimitry Andric #endif
548*81ad6265SDimitry Andric }
549*81ad6265SDimitry Andric 
550*81ad6265SDimitry Andric void MachOWriter::writeDataInCodeData() {
551*81ad6265SDimitry Andric   return writeLinkData(O.DataInCodeCommandIndex, O.DataInCode);
552*81ad6265SDimitry Andric }
553*81ad6265SDimitry Andric 
554*81ad6265SDimitry Andric void MachOWriter::writeLinkerOptimizationHint() {
555*81ad6265SDimitry Andric   return writeLinkData(O.LinkerOptimizationHintCommandIndex,
556*81ad6265SDimitry Andric                        O.LinkerOptimizationHint);
557*81ad6265SDimitry Andric }
558*81ad6265SDimitry Andric 
559*81ad6265SDimitry Andric void MachOWriter::writeFunctionStartsData() {
560*81ad6265SDimitry Andric   return writeLinkData(O.FunctionStartsCommandIndex, O.FunctionStarts);
561*81ad6265SDimitry Andric }
562*81ad6265SDimitry Andric 
563*81ad6265SDimitry Andric void MachOWriter::writeChainedFixupsData() {
564*81ad6265SDimitry Andric   return writeLinkData(O.ChainedFixupsCommandIndex, O.ChainedFixups);
565*81ad6265SDimitry Andric }
566*81ad6265SDimitry Andric 
567*81ad6265SDimitry Andric void MachOWriter::writeExportsTrieData() {
568*81ad6265SDimitry Andric   return writeLinkData(O.ExportsTrieCommandIndex, O.ExportsTrie);
569*81ad6265SDimitry Andric }
570*81ad6265SDimitry Andric 
571*81ad6265SDimitry Andric void MachOWriter::writeTail() {
572*81ad6265SDimitry Andric   typedef void (MachOWriter::*WriteHandlerType)();
573*81ad6265SDimitry Andric   typedef std::pair<uint64_t, WriteHandlerType> WriteOperation;
574*81ad6265SDimitry Andric   SmallVector<WriteOperation, 7> Queue;
575*81ad6265SDimitry Andric 
576*81ad6265SDimitry Andric   if (O.SymTabCommandIndex) {
577*81ad6265SDimitry Andric     const MachO::symtab_command &SymTabCommand =
578*81ad6265SDimitry Andric         O.LoadCommands[*O.SymTabCommandIndex]
579*81ad6265SDimitry Andric             .MachOLoadCommand.symtab_command_data;
580*81ad6265SDimitry Andric     if (SymTabCommand.symoff)
581*81ad6265SDimitry Andric       Queue.push_back({SymTabCommand.symoff, &MachOWriter::writeSymbolTable});
582*81ad6265SDimitry Andric     if (SymTabCommand.stroff)
583*81ad6265SDimitry Andric       Queue.push_back({SymTabCommand.stroff, &MachOWriter::writeStringTable});
584*81ad6265SDimitry Andric   }
585*81ad6265SDimitry Andric 
586*81ad6265SDimitry Andric   if (O.DyLdInfoCommandIndex) {
587*81ad6265SDimitry Andric     const MachO::dyld_info_command &DyLdInfoCommand =
588*81ad6265SDimitry Andric         O.LoadCommands[*O.DyLdInfoCommandIndex]
589*81ad6265SDimitry Andric             .MachOLoadCommand.dyld_info_command_data;
590*81ad6265SDimitry Andric     if (DyLdInfoCommand.rebase_off)
591*81ad6265SDimitry Andric       Queue.push_back(
592*81ad6265SDimitry Andric           {DyLdInfoCommand.rebase_off, &MachOWriter::writeRebaseInfo});
593*81ad6265SDimitry Andric     if (DyLdInfoCommand.bind_off)
594*81ad6265SDimitry Andric       Queue.push_back({DyLdInfoCommand.bind_off, &MachOWriter::writeBindInfo});
595*81ad6265SDimitry Andric     if (DyLdInfoCommand.weak_bind_off)
596*81ad6265SDimitry Andric       Queue.push_back(
597*81ad6265SDimitry Andric           {DyLdInfoCommand.weak_bind_off, &MachOWriter::writeWeakBindInfo});
598*81ad6265SDimitry Andric     if (DyLdInfoCommand.lazy_bind_off)
599*81ad6265SDimitry Andric       Queue.push_back(
600*81ad6265SDimitry Andric           {DyLdInfoCommand.lazy_bind_off, &MachOWriter::writeLazyBindInfo});
601*81ad6265SDimitry Andric     if (DyLdInfoCommand.export_off)
602*81ad6265SDimitry Andric       Queue.push_back(
603*81ad6265SDimitry Andric           {DyLdInfoCommand.export_off, &MachOWriter::writeExportInfo});
604*81ad6265SDimitry Andric   }
605*81ad6265SDimitry Andric 
606*81ad6265SDimitry Andric   if (O.DySymTabCommandIndex) {
607*81ad6265SDimitry Andric     const MachO::dysymtab_command &DySymTabCommand =
608*81ad6265SDimitry Andric         O.LoadCommands[*O.DySymTabCommandIndex]
609*81ad6265SDimitry Andric             .MachOLoadCommand.dysymtab_command_data;
610*81ad6265SDimitry Andric 
611*81ad6265SDimitry Andric     if (DySymTabCommand.indirectsymoff)
612*81ad6265SDimitry Andric       Queue.emplace_back(DySymTabCommand.indirectsymoff,
613*81ad6265SDimitry Andric                          &MachOWriter::writeIndirectSymbolTable);
614*81ad6265SDimitry Andric   }
615*81ad6265SDimitry Andric 
616*81ad6265SDimitry Andric   std::initializer_list<std::pair<Optional<size_t>, WriteHandlerType>>
617*81ad6265SDimitry Andric       LinkEditDataCommandWriters = {
618*81ad6265SDimitry Andric           {O.CodeSignatureCommandIndex, &MachOWriter::writeCodeSignatureData},
619*81ad6265SDimitry Andric           {O.DataInCodeCommandIndex, &MachOWriter::writeDataInCodeData},
620*81ad6265SDimitry Andric           {O.LinkerOptimizationHintCommandIndex,
621*81ad6265SDimitry Andric            &MachOWriter::writeLinkerOptimizationHint},
622*81ad6265SDimitry Andric           {O.FunctionStartsCommandIndex, &MachOWriter::writeFunctionStartsData},
623*81ad6265SDimitry Andric           {O.ChainedFixupsCommandIndex, &MachOWriter::writeChainedFixupsData},
624*81ad6265SDimitry Andric           {O.ExportsTrieCommandIndex, &MachOWriter::writeExportsTrieData}};
625*81ad6265SDimitry Andric   for (const auto &W : LinkEditDataCommandWriters) {
626*81ad6265SDimitry Andric     Optional<size_t> LinkEditDataCommandIndex;
627*81ad6265SDimitry Andric     WriteHandlerType WriteHandler;
628*81ad6265SDimitry Andric     std::tie(LinkEditDataCommandIndex, WriteHandler) = W;
629*81ad6265SDimitry Andric     if (LinkEditDataCommandIndex) {
630*81ad6265SDimitry Andric       const MachO::linkedit_data_command &LinkEditDataCommand =
631*81ad6265SDimitry Andric           O.LoadCommands[*LinkEditDataCommandIndex]
632*81ad6265SDimitry Andric               .MachOLoadCommand.linkedit_data_command_data;
633*81ad6265SDimitry Andric       if (LinkEditDataCommand.dataoff)
634*81ad6265SDimitry Andric         Queue.emplace_back(LinkEditDataCommand.dataoff, WriteHandler);
635*81ad6265SDimitry Andric     }
636*81ad6265SDimitry Andric   }
637*81ad6265SDimitry Andric 
638*81ad6265SDimitry Andric   llvm::sort(Queue, llvm::less_first());
639*81ad6265SDimitry Andric 
640*81ad6265SDimitry Andric   for (auto WriteOp : Queue)
641*81ad6265SDimitry Andric     (this->*WriteOp.second)();
642*81ad6265SDimitry Andric }
643*81ad6265SDimitry Andric 
644*81ad6265SDimitry Andric Error MachOWriter::finalize() { return LayoutBuilder.layout(); }
645*81ad6265SDimitry Andric 
646*81ad6265SDimitry Andric Error MachOWriter::write() {
647*81ad6265SDimitry Andric   size_t TotalSize = totalSize();
648*81ad6265SDimitry Andric   Buf = WritableMemoryBuffer::getNewMemBuffer(TotalSize);
649*81ad6265SDimitry Andric   if (!Buf)
650*81ad6265SDimitry Andric     return createStringError(errc::not_enough_memory,
651*81ad6265SDimitry Andric                              "failed to allocate memory buffer of " +
652*81ad6265SDimitry Andric                                  Twine::utohexstr(TotalSize) + " bytes");
653*81ad6265SDimitry Andric   writeHeader();
654*81ad6265SDimitry Andric   writeLoadCommands();
655*81ad6265SDimitry Andric   writeSections();
656*81ad6265SDimitry Andric   writeTail();
657*81ad6265SDimitry Andric 
658*81ad6265SDimitry Andric   // TODO: Implement direct writing to the output stream (without intermediate
659*81ad6265SDimitry Andric   // memory buffer Buf).
660*81ad6265SDimitry Andric   Out.write(Buf->getBufferStart(), Buf->getBufferSize());
661*81ad6265SDimitry Andric   return Error::success();
662*81ad6265SDimitry Andric }
663