]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/llvm-objcopy/MachO/MachOWriter.cpp
Fix a memory leak in if_delgroups() introduced in r334118.
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / llvm-objcopy / MachO / MachOWriter.cpp
1 //===- MachOWriter.cpp ------------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "MachOWriter.h"
10 #include "Object.h"
11 #include "llvm/ADT/STLExtras.h"
12 #include "llvm/BinaryFormat/MachO.h"
13 #include "llvm/Object/MachO.h"
14 #include "llvm/Support/Errc.h"
15 #include "llvm/Support/ErrorHandling.h"
16 #include <memory>
17
18 namespace llvm {
19 namespace objcopy {
20 namespace macho {
21
22 size_t MachOWriter::headerSize() const {
23   return Is64Bit ? sizeof(MachO::mach_header_64) : sizeof(MachO::mach_header);
24 }
25
26 size_t MachOWriter::loadCommandsSize() const { return O.Header.SizeOfCmds; }
27
28 size_t MachOWriter::symTableSize() const {
29   return O.SymTable.Symbols.size() *
30          (Is64Bit ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist));
31 }
32
33 size_t MachOWriter::totalSize() const {
34   // Going from tail to head and looking for an appropriate "anchor" to
35   // calculate the total size assuming that all the offsets are either valid
36   // ("true") or 0 (0 indicates that the corresponding part is missing).
37
38   SmallVector<size_t, 7> Ends;
39   if (O.SymTabCommandIndex) {
40     const MachO::symtab_command &SymTabCommand =
41         O.LoadCommands[*O.SymTabCommandIndex]
42             .MachOLoadCommand.symtab_command_data;
43     if (SymTabCommand.symoff) {
44       assert((SymTabCommand.nsyms == O.SymTable.Symbols.size()) &&
45              "Incorrect number of symbols");
46       Ends.push_back(SymTabCommand.symoff + symTableSize());
47     }
48     if (SymTabCommand.stroff) {
49       assert((SymTabCommand.strsize == StrTableBuilder.getSize()) &&
50              "Incorrect string table size");
51       Ends.push_back(SymTabCommand.stroff + SymTabCommand.strsize);
52     }
53   }
54   if (O.DyLdInfoCommandIndex) {
55     const MachO::dyld_info_command &DyLdInfoCommand =
56         O.LoadCommands[*O.DyLdInfoCommandIndex]
57             .MachOLoadCommand.dyld_info_command_data;
58     if (DyLdInfoCommand.rebase_off) {
59       assert((DyLdInfoCommand.rebase_size == O.Rebases.Opcodes.size()) &&
60              "Incorrect rebase opcodes size");
61       Ends.push_back(DyLdInfoCommand.rebase_off + DyLdInfoCommand.rebase_size);
62     }
63     if (DyLdInfoCommand.bind_off) {
64       assert((DyLdInfoCommand.bind_size == O.Binds.Opcodes.size()) &&
65              "Incorrect bind opcodes size");
66       Ends.push_back(DyLdInfoCommand.bind_off + DyLdInfoCommand.bind_size);
67     }
68     if (DyLdInfoCommand.weak_bind_off) {
69       assert((DyLdInfoCommand.weak_bind_size == O.WeakBinds.Opcodes.size()) &&
70              "Incorrect weak bind opcodes size");
71       Ends.push_back(DyLdInfoCommand.weak_bind_off +
72                      DyLdInfoCommand.weak_bind_size);
73     }
74     if (DyLdInfoCommand.lazy_bind_off) {
75       assert((DyLdInfoCommand.lazy_bind_size == O.LazyBinds.Opcodes.size()) &&
76              "Incorrect lazy bind opcodes size");
77       Ends.push_back(DyLdInfoCommand.lazy_bind_off +
78                      DyLdInfoCommand.lazy_bind_size);
79     }
80     if (DyLdInfoCommand.export_off) {
81       assert((DyLdInfoCommand.export_size == O.Exports.Trie.size()) &&
82              "Incorrect trie size");
83       Ends.push_back(DyLdInfoCommand.export_off + DyLdInfoCommand.export_size);
84     }
85   }
86
87   // Otherwise, use the last section / reloction.
88   for (const auto &LC : O.LoadCommands)
89     for (const auto &S : LC.Sections) {
90       Ends.push_back(S.Offset + S.Size);
91       if (S.RelOff)
92         Ends.push_back(S.RelOff +
93                        S.NReloc * sizeof(MachO::any_relocation_info));
94     }
95
96   if (!Ends.empty())
97     return *std::max_element(Ends.begin(), Ends.end());
98
99   // Otherwise, we have only Mach header and load commands.
100   return headerSize() + loadCommandsSize();
101 }
102
103 void MachOWriter::writeHeader() {
104   MachO::mach_header_64 Header;
105
106   Header.magic = O.Header.Magic;
107   Header.cputype = O.Header.CPUType;
108   Header.cpusubtype = O.Header.CPUSubType;
109   Header.filetype = O.Header.FileType;
110   Header.ncmds = O.Header.NCmds;
111   Header.sizeofcmds = O.Header.SizeOfCmds;
112   Header.flags = O.Header.Flags;
113   Header.reserved = O.Header.Reserved;
114
115   if (IsLittleEndian != sys::IsLittleEndianHost)
116     MachO::swapStruct(Header);
117
118   auto HeaderSize =
119       Is64Bit ? sizeof(MachO::mach_header_64) : sizeof(MachO::mach_header);
120   memcpy(B.getBufferStart(), &Header, HeaderSize);
121 }
122
123 void MachOWriter::updateSymbolIndexes() {
124   uint32_t Index = 0;
125   for (auto &Symbol : O.SymTable.Symbols) {
126     Symbol->Index = Index;
127     Index++;
128   }
129 }
130
131 void MachOWriter::writeLoadCommands() {
132   uint8_t *Begin = B.getBufferStart() + headerSize();
133   for (const auto &LC : O.LoadCommands) {
134     // Construct a load command.
135     MachO::macho_load_command MLC = LC.MachOLoadCommand;
136     switch (MLC.load_command_data.cmd) {
137     case MachO::LC_SEGMENT:
138       if (IsLittleEndian != sys::IsLittleEndianHost)
139         MachO::swapStruct(MLC.segment_command_data);
140       memcpy(Begin, &MLC.segment_command_data, sizeof(MachO::segment_command));
141       Begin += sizeof(MachO::segment_command);
142
143       for (const auto &Sec : LC.Sections)
144         writeSectionInLoadCommand<MachO::section>(Sec, Begin);
145       continue;
146     case MachO::LC_SEGMENT_64:
147       if (IsLittleEndian != sys::IsLittleEndianHost)
148         MachO::swapStruct(MLC.segment_command_64_data);
149       memcpy(Begin, &MLC.segment_command_64_data,
150              sizeof(MachO::segment_command_64));
151       Begin += sizeof(MachO::segment_command_64);
152
153       for (const auto &Sec : LC.Sections)
154         writeSectionInLoadCommand<MachO::section_64>(Sec, Begin);
155       continue;
156     }
157
158 #define HANDLE_LOAD_COMMAND(LCName, LCValue, LCStruct)                         \
159   case MachO::LCName:                                                          \
160     assert(sizeof(MachO::LCStruct) + LC.Payload.size() ==                      \
161            MLC.load_command_data.cmdsize);                                     \
162     if (IsLittleEndian != sys::IsLittleEndianHost)                             \
163       MachO::swapStruct(MLC.LCStruct##_data);                                  \
164     memcpy(Begin, &MLC.LCStruct##_data, sizeof(MachO::LCStruct));              \
165     Begin += sizeof(MachO::LCStruct);                                          \
166     memcpy(Begin, LC.Payload.data(), LC.Payload.size());                       \
167     Begin += LC.Payload.size();                                                \
168     break;
169
170     // Copy the load command as it is.
171     switch (MLC.load_command_data.cmd) {
172     default:
173       assert(sizeof(MachO::load_command) + LC.Payload.size() ==
174              MLC.load_command_data.cmdsize);
175       if (IsLittleEndian != sys::IsLittleEndianHost)
176         MachO::swapStruct(MLC.load_command_data);
177       memcpy(Begin, &MLC.load_command_data, sizeof(MachO::load_command));
178       Begin += sizeof(MachO::load_command);
179       memcpy(Begin, LC.Payload.data(), LC.Payload.size());
180       Begin += LC.Payload.size();
181       break;
182 #include "llvm/BinaryFormat/MachO.def"
183     }
184   }
185 }
186
187 template <typename StructType>
188 void MachOWriter::writeSectionInLoadCommand(const Section &Sec, uint8_t *&Out) {
189   StructType Temp;
190   assert(Sec.Segname.size() <= sizeof(Temp.segname) && "too long segment name");
191   assert(Sec.Sectname.size() <= sizeof(Temp.sectname) &&
192          "too long section name");
193   memset(&Temp, 0, sizeof(StructType));
194   memcpy(Temp.segname, Sec.Segname.data(), Sec.Segname.size());
195   memcpy(Temp.sectname, Sec.Sectname.data(), Sec.Sectname.size());
196   Temp.addr = Sec.Addr;
197   Temp.size = Sec.Size;
198   Temp.offset = Sec.Offset;
199   Temp.align = Sec.Align;
200   Temp.reloff = Sec.RelOff;
201   Temp.nreloc = Sec.NReloc;
202   Temp.flags = Sec.Flags;
203   Temp.reserved1 = Sec.Reserved1;
204   Temp.reserved2 = Sec.Reserved2;
205
206   if (IsLittleEndian != sys::IsLittleEndianHost)
207     MachO::swapStruct(Temp);
208   memcpy(Out, &Temp, sizeof(StructType));
209   Out += sizeof(StructType);
210 }
211
212 void MachOWriter::writeSections() {
213   for (const auto &LC : O.LoadCommands)
214     for (const auto &Sec : LC.Sections) {
215       if (Sec.isVirtualSection())
216         continue;
217
218       assert(Sec.Offset && "Section offset can not be zero");
219       assert((Sec.Size == Sec.Content.size()) && "Incorrect section size");
220       memcpy(B.getBufferStart() + Sec.Offset, Sec.Content.data(),
221              Sec.Content.size());
222       for (size_t Index = 0; Index < Sec.Relocations.size(); ++Index) {
223         auto RelocInfo = Sec.Relocations[Index];
224         if (!RelocInfo.Scattered) {
225           auto *Info =
226               reinterpret_cast<MachO::relocation_info *>(&RelocInfo.Info);
227           Info->r_symbolnum = RelocInfo.Symbol->Index;
228         }
229
230         if (IsLittleEndian != sys::IsLittleEndianHost)
231           MachO::swapStruct(
232               reinterpret_cast<MachO::any_relocation_info &>(RelocInfo.Info));
233         memcpy(B.getBufferStart() + Sec.RelOff +
234                    Index * sizeof(MachO::any_relocation_info),
235                &RelocInfo.Info, sizeof(RelocInfo.Info));
236       }
237     }
238 }
239
240 template <typename NListType>
241 void writeNListEntry(const SymbolEntry &SE, bool IsLittleEndian, char *&Out,
242                      uint32_t Nstrx) {
243   NListType ListEntry;
244   ListEntry.n_strx = Nstrx;
245   ListEntry.n_type = SE.n_type;
246   ListEntry.n_sect = SE.n_sect;
247   ListEntry.n_desc = SE.n_desc;
248   ListEntry.n_value = SE.n_value;
249
250   if (IsLittleEndian != sys::IsLittleEndianHost)
251     MachO::swapStruct(ListEntry);
252   memcpy(Out, reinterpret_cast<const char *>(&ListEntry), sizeof(NListType));
253   Out += sizeof(NListType);
254 }
255
256 void MachOWriter::writeSymbolTable() {
257   if (!O.SymTabCommandIndex)
258     return;
259   const MachO::symtab_command &SymTabCommand =
260       O.LoadCommands[*O.SymTabCommandIndex]
261           .MachOLoadCommand.symtab_command_data;
262
263   uint8_t *StrTable = (uint8_t *)B.getBufferStart() + SymTabCommand.stroff;
264   StrTableBuilder.write(StrTable);
265 }
266
267 void MachOWriter::writeStringTable() {
268   if (!O.SymTabCommandIndex)
269     return;
270   const MachO::symtab_command &SymTabCommand =
271       O.LoadCommands[*O.SymTabCommandIndex]
272           .MachOLoadCommand.symtab_command_data;
273
274   char *SymTable = (char *)B.getBufferStart() + SymTabCommand.symoff;
275   for (auto Iter = O.SymTable.Symbols.begin(), End = O.SymTable.Symbols.end();
276        Iter != End; Iter++) {
277     SymbolEntry *Sym = Iter->get();
278     auto Nstrx = StrTableBuilder.getOffset(Sym->Name);
279
280     if (Is64Bit)
281       writeNListEntry<MachO::nlist_64>(*Sym, IsLittleEndian, SymTable, Nstrx);
282     else
283       writeNListEntry<MachO::nlist>(*Sym, IsLittleEndian, SymTable, Nstrx);
284   }
285 }
286
287 void MachOWriter::writeRebaseInfo() {
288   if (!O.DyLdInfoCommandIndex)
289     return;
290   const MachO::dyld_info_command &DyLdInfoCommand =
291       O.LoadCommands[*O.DyLdInfoCommandIndex]
292           .MachOLoadCommand.dyld_info_command_data;
293   char *Out = (char *)B.getBufferStart() + DyLdInfoCommand.rebase_off;
294   assert((DyLdInfoCommand.rebase_size == O.Rebases.Opcodes.size()) &&
295          "Incorrect rebase opcodes size");
296   memcpy(Out, O.Rebases.Opcodes.data(), O.Rebases.Opcodes.size());
297 }
298
299 void MachOWriter::writeBindInfo() {
300   if (!O.DyLdInfoCommandIndex)
301     return;
302   const MachO::dyld_info_command &DyLdInfoCommand =
303       O.LoadCommands[*O.DyLdInfoCommandIndex]
304           .MachOLoadCommand.dyld_info_command_data;
305   char *Out = (char *)B.getBufferStart() + DyLdInfoCommand.bind_off;
306   assert((DyLdInfoCommand.bind_size == O.Binds.Opcodes.size()) &&
307          "Incorrect bind opcodes size");
308   memcpy(Out, O.Binds.Opcodes.data(), O.Binds.Opcodes.size());
309 }
310
311 void MachOWriter::writeWeakBindInfo() {
312   if (!O.DyLdInfoCommandIndex)
313     return;
314   const MachO::dyld_info_command &DyLdInfoCommand =
315       O.LoadCommands[*O.DyLdInfoCommandIndex]
316           .MachOLoadCommand.dyld_info_command_data;
317   char *Out = (char *)B.getBufferStart() + DyLdInfoCommand.weak_bind_off;
318   assert((DyLdInfoCommand.weak_bind_size == O.WeakBinds.Opcodes.size()) &&
319          "Incorrect weak bind opcodes size");
320   memcpy(Out, O.WeakBinds.Opcodes.data(), O.WeakBinds.Opcodes.size());
321 }
322
323 void MachOWriter::writeLazyBindInfo() {
324   if (!O.DyLdInfoCommandIndex)
325     return;
326   const MachO::dyld_info_command &DyLdInfoCommand =
327       O.LoadCommands[*O.DyLdInfoCommandIndex]
328           .MachOLoadCommand.dyld_info_command_data;
329   char *Out = (char *)B.getBufferStart() + DyLdInfoCommand.lazy_bind_off;
330   assert((DyLdInfoCommand.lazy_bind_size == O.LazyBinds.Opcodes.size()) &&
331          "Incorrect lazy bind opcodes size");
332   memcpy(Out, O.LazyBinds.Opcodes.data(), O.LazyBinds.Opcodes.size());
333 }
334
335 void MachOWriter::writeExportInfo() {
336   if (!O.DyLdInfoCommandIndex)
337     return;
338   const MachO::dyld_info_command &DyLdInfoCommand =
339       O.LoadCommands[*O.DyLdInfoCommandIndex]
340           .MachOLoadCommand.dyld_info_command_data;
341   char *Out = (char *)B.getBufferStart() + DyLdInfoCommand.export_off;
342   assert((DyLdInfoCommand.export_size == O.Exports.Trie.size()) &&
343          "Incorrect export trie size");
344   memcpy(Out, O.Exports.Trie.data(), O.Exports.Trie.size());
345 }
346
347 void MachOWriter::writeTail() {
348   typedef void (MachOWriter::*WriteHandlerType)(void);
349   typedef std::pair<uint64_t, WriteHandlerType> WriteOperation;
350   SmallVector<WriteOperation, 7> Queue;
351
352   if (O.SymTabCommandIndex) {
353     const MachO::symtab_command &SymTabCommand =
354         O.LoadCommands[*O.SymTabCommandIndex]
355             .MachOLoadCommand.symtab_command_data;
356     if (SymTabCommand.symoff)
357       Queue.push_back({SymTabCommand.symoff, &MachOWriter::writeSymbolTable});
358     if (SymTabCommand.stroff)
359       Queue.push_back({SymTabCommand.stroff, &MachOWriter::writeStringTable});
360   }
361
362   if (O.DyLdInfoCommandIndex) {
363     const MachO::dyld_info_command &DyLdInfoCommand =
364         O.LoadCommands[*O.DyLdInfoCommandIndex]
365             .MachOLoadCommand.dyld_info_command_data;
366     if (DyLdInfoCommand.rebase_off)
367       Queue.push_back(
368           {DyLdInfoCommand.rebase_off, &MachOWriter::writeRebaseInfo});
369     if (DyLdInfoCommand.bind_off)
370       Queue.push_back({DyLdInfoCommand.bind_off, &MachOWriter::writeBindInfo});
371     if (DyLdInfoCommand.weak_bind_off)
372       Queue.push_back(
373           {DyLdInfoCommand.weak_bind_off, &MachOWriter::writeWeakBindInfo});
374     if (DyLdInfoCommand.lazy_bind_off)
375       Queue.push_back(
376           {DyLdInfoCommand.lazy_bind_off, &MachOWriter::writeLazyBindInfo});
377     if (DyLdInfoCommand.export_off)
378       Queue.push_back(
379           {DyLdInfoCommand.export_off, &MachOWriter::writeExportInfo});
380   }
381
382   llvm::sort(Queue, [](const WriteOperation &LHS, const WriteOperation &RHS) {
383     return LHS.first < RHS.first;
384   });
385
386   for (auto WriteOp : Queue)
387     (this->*WriteOp.second)();
388 }
389
390 void MachOWriter::updateSizeOfCmds() {
391   auto Size = 0;
392   for (const auto &LC : O.LoadCommands) {
393     auto &MLC = LC.MachOLoadCommand;
394     auto cmd = MLC.load_command_data.cmd;
395
396     switch (cmd) {
397     case MachO::LC_SEGMENT:
398       Size += sizeof(MachO::segment_command) +
399               sizeof(MachO::section) * LC.Sections.size();
400       continue;
401     case MachO::LC_SEGMENT_64:
402       Size += sizeof(MachO::segment_command_64) +
403               sizeof(MachO::section_64) * LC.Sections.size();
404       continue;
405     }
406
407     switch (cmd) {
408 #define HANDLE_LOAD_COMMAND(LCName, LCValue, LCStruct)                         \
409   case MachO::LCName:                                                          \
410     Size += sizeof(MachO::LCStruct);                                           \
411     break;
412 #include "llvm/BinaryFormat/MachO.def"
413 #undef HANDLE_LOAD_COMMAND
414     }
415   }
416
417   O.Header.SizeOfCmds = Size;
418 }
419
420 // Updates the index and the number of local/external/undefined symbols. Here we
421 // assume that MLC is a LC_DYSYMTAB and the nlist entries in the symbol table
422 // are already sorted by the those types.
423 void MachOWriter::updateDySymTab(MachO::macho_load_command &MLC) {
424   uint32_t NumLocalSymbols = 0;
425   auto Iter = O.SymTable.Symbols.begin();
426   auto End = O.SymTable.Symbols.end();
427   for (; Iter != End; Iter++) {
428     if ((*Iter)->n_type & (MachO::N_EXT | MachO::N_PEXT))
429       break;
430
431     NumLocalSymbols++;
432   }
433
434   uint32_t NumExtDefSymbols = 0;
435   for (; Iter != End; Iter++) {
436     if (((*Iter)->n_type & MachO::N_TYPE) == MachO::N_UNDF)
437       break;
438
439     NumExtDefSymbols++;
440   }
441
442   MLC.dysymtab_command_data.ilocalsym = 0;
443   MLC.dysymtab_command_data.nlocalsym = NumLocalSymbols;
444   MLC.dysymtab_command_data.iextdefsym = NumLocalSymbols;
445   MLC.dysymtab_command_data.nextdefsym = NumExtDefSymbols;
446   MLC.dysymtab_command_data.iundefsym = NumLocalSymbols + NumExtDefSymbols;
447   MLC.dysymtab_command_data.nundefsym =
448       O.SymTable.Symbols.size() - (NumLocalSymbols + NumExtDefSymbols);
449 }
450
451 // Recomputes and updates offset and size fields in load commands and sections
452 // since they could be modified.
453 Error MachOWriter::layout() {
454   auto SizeOfCmds = loadCommandsSize();
455   auto Offset = headerSize() + SizeOfCmds;
456   O.Header.NCmds = O.LoadCommands.size();
457   O.Header.SizeOfCmds = SizeOfCmds;
458
459   // Lay out sections.
460   for (auto &LC : O.LoadCommands) {
461     uint64_t FileOff = Offset;
462     uint64_t VMSize = 0;
463     uint64_t FileOffsetInSegment = 0;
464     for (auto &Sec : LC.Sections) {
465       if (!Sec.isVirtualSection()) {
466         auto FilePaddingSize =
467             OffsetToAlignment(FileOffsetInSegment, 1ull << Sec.Align);
468         Sec.Offset = Offset + FileOffsetInSegment + FilePaddingSize;
469         Sec.Size = Sec.Content.size();
470         FileOffsetInSegment += FilePaddingSize + Sec.Size;
471       }
472
473       VMSize = std::max(VMSize, Sec.Addr + Sec.Size);
474     }
475
476     // TODO: Handle the __PAGEZERO segment.
477     auto &MLC = LC.MachOLoadCommand;
478     switch (MLC.load_command_data.cmd) {
479     case MachO::LC_SEGMENT:
480       MLC.segment_command_data.cmdsize =
481           sizeof(MachO::segment_command) +
482           sizeof(MachO::section) * LC.Sections.size();
483       MLC.segment_command_data.nsects = LC.Sections.size();
484       MLC.segment_command_data.fileoff = FileOff;
485       MLC.segment_command_data.vmsize = VMSize;
486       MLC.segment_command_data.filesize = FileOffsetInSegment;
487       break;
488     case MachO::LC_SEGMENT_64:
489       MLC.segment_command_64_data.cmdsize =
490           sizeof(MachO::segment_command_64) +
491           sizeof(MachO::section_64) * LC.Sections.size();
492       MLC.segment_command_64_data.nsects = LC.Sections.size();
493       MLC.segment_command_64_data.fileoff = FileOff;
494       MLC.segment_command_64_data.vmsize = VMSize;
495       MLC.segment_command_64_data.filesize = FileOffsetInSegment;
496       break;
497     }
498
499     Offset += FileOffsetInSegment;
500   }
501
502   // Lay out relocations.
503   for (auto &LC : O.LoadCommands)
504     for (auto &Sec : LC.Sections) {
505       Sec.RelOff = Sec.Relocations.empty() ? 0 : Offset;
506       Sec.NReloc = Sec.Relocations.size();
507       Offset += sizeof(MachO::any_relocation_info) * Sec.NReloc;
508     }
509
510   // Lay out tail stuff.
511   auto NListSize = Is64Bit ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
512   for (auto &LC : O.LoadCommands) {
513     auto &MLC = LC.MachOLoadCommand;
514     auto cmd = MLC.load_command_data.cmd;
515     switch (cmd) {
516     case MachO::LC_SYMTAB:
517       MLC.symtab_command_data.nsyms = O.SymTable.Symbols.size();
518       MLC.symtab_command_data.strsize = StrTableBuilder.getSize();
519       MLC.symtab_command_data.symoff = Offset;
520       Offset += NListSize * MLC.symtab_command_data.nsyms;
521       MLC.symtab_command_data.stroff = Offset;
522       Offset += MLC.symtab_command_data.strsize;
523       break;
524     case MachO::LC_DYSYMTAB: {
525       if (MLC.dysymtab_command_data.ntoc != 0 ||
526           MLC.dysymtab_command_data.nmodtab != 0 ||
527           MLC.dysymtab_command_data.nextrefsyms != 0 ||
528           MLC.dysymtab_command_data.nlocrel != 0 ||
529           MLC.dysymtab_command_data.nextrel != 0)
530         return createStringError(llvm::errc::not_supported,
531                                  "shared library is not yet supported");
532
533       if (MLC.dysymtab_command_data.nindirectsyms != 0)
534         return createStringError(llvm::errc::not_supported,
535                                  "indirect symbol table is not yet supported");
536
537       updateDySymTab(MLC);
538       break;
539     }
540     case MachO::LC_SEGMENT:
541     case MachO::LC_SEGMENT_64:
542     case MachO::LC_VERSION_MIN_MACOSX:
543     case MachO::LC_BUILD_VERSION:
544     case MachO::LC_ID_DYLIB:
545     case MachO::LC_LOAD_DYLIB:
546     case MachO::LC_UUID:
547     case MachO::LC_SOURCE_VERSION:
548       // Nothing to update.
549       break;
550     default:
551       // Abort if it's unsupported in order to prevent corrupting the object.
552       return createStringError(llvm::errc::not_supported,
553                                "unsupported load command (cmd=0x%x)", cmd);
554     }
555   }
556
557   return Error::success();
558 }
559
560 void MachOWriter::constructStringTable() {
561   for (std::unique_ptr<SymbolEntry> &Sym : O.SymTable.Symbols)
562     StrTableBuilder.add(Sym->Name);
563   StrTableBuilder.finalize();
564 }
565
566 Error MachOWriter::finalize() {
567   updateSizeOfCmds();
568   constructStringTable();
569
570   if (auto E = layout())
571     return E;
572
573   return Error::success();
574 }
575
576 Error MachOWriter::write() {
577   if (Error E = B.allocate(totalSize()))
578     return E;
579   memset(B.getBufferStart(), 0, totalSize());
580   writeHeader();
581   updateSymbolIndexes();
582   writeLoadCommands();
583   writeSections();
584   writeTail();
585   return B.commit();
586 }
587
588 } // end namespace macho
589 } // end namespace objcopy
590 } // end namespace llvm