[ARM] Tighten up VLDRH.32 with low alignments
[llvm-complete.git] / tools / llvm-objcopy / MachO / MachOWriter.cpp
blob74200c5aa62a0b646601f0ee19b60e59367f3ece
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 //===----------------------------------------------------------------------===//
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>
18 namespace llvm {
19 namespace objcopy {
20 namespace macho {
22 size_t MachOWriter::headerSize() const {
23 return Is64Bit ? sizeof(MachO::mach_header_64) : sizeof(MachO::mach_header);
26 size_t MachOWriter::loadCommandsSize() const { return O.Header.SizeOfCmds; }
28 size_t MachOWriter::symTableSize() const {
29 return O.SymTable.Symbols.size() *
30 (Is64Bit ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist));
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).
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());
48 if (SymTabCommand.stroff) {
49 assert((SymTabCommand.strsize == StrTableBuilder.getSize()) &&
50 "Incorrect string table size");
51 Ends.push_back(SymTabCommand.stroff + SymTabCommand.strsize);
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);
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);
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);
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);
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);
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));
96 if (!Ends.empty())
97 return *std::max_element(Ends.begin(), Ends.end());
99 // Otherwise, we have only Mach header and load commands.
100 return headerSize() + loadCommandsSize();
103 void MachOWriter::writeHeader() {
104 MachO::mach_header_64 Header;
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;
115 if (IsLittleEndian != sys::IsLittleEndianHost)
116 MachO::swapStruct(Header);
118 auto HeaderSize =
119 Is64Bit ? sizeof(MachO::mach_header_64) : sizeof(MachO::mach_header);
120 memcpy(B.getBufferStart(), &Header, HeaderSize);
123 void MachOWriter::updateSymbolIndexes() {
124 uint32_t Index = 0;
125 for (auto &Symbol : O.SymTable.Symbols) {
126 Symbol->Index = Index;
127 Index++;
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);
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);
153 for (const auto &Sec : LC.Sections)
154 writeSectionInLoadCommand<MachO::section_64>(Sec, Begin);
155 continue;
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;
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"
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;
206 if (IsLittleEndian != sys::IsLittleEndianHost)
207 MachO::swapStruct(Temp);
208 memcpy(Out, &Temp, sizeof(StructType));
209 Out += sizeof(StructType);
212 void MachOWriter::writeSections() {
213 for (const auto &LC : O.LoadCommands)
214 for (const auto &Sec : LC.Sections) {
215 if (Sec.isVirtualSection())
216 continue;
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;
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));
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;
250 if (IsLittleEndian != sys::IsLittleEndianHost)
251 MachO::swapStruct(ListEntry);
252 memcpy(Out, reinterpret_cast<const char *>(&ListEntry), sizeof(NListType));
253 Out += sizeof(NListType);
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;
263 uint8_t *StrTable = (uint8_t *)B.getBufferStart() + SymTabCommand.stroff;
264 StrTableBuilder.write(StrTable);
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;
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);
280 if (Is64Bit)
281 writeNListEntry<MachO::nlist_64>(*Sym, IsLittleEndian, SymTable, Nstrx);
282 else
283 writeNListEntry<MachO::nlist>(*Sym, IsLittleEndian, SymTable, Nstrx);
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());
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());
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());
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());
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());
347 void MachOWriter::writeTail() {
348 typedef void (MachOWriter::*WriteHandlerType)(void);
349 typedef std::pair<uint64_t, WriteHandlerType> WriteOperation;
350 SmallVector<WriteOperation, 7> Queue;
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});
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});
382 llvm::sort(Queue, [](const WriteOperation &LHS, const WriteOperation &RHS) {
383 return LHS.first < RHS.first;
386 for (auto WriteOp : Queue)
387 (this->*WriteOp.second)();
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;
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;
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
417 O.Header.SizeOfCmds = Size;
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;
431 NumLocalSymbols++;
434 uint32_t NumExtDefSymbols = 0;
435 for (; Iter != End; Iter++) {
436 if (((*Iter)->n_type & MachO::N_TYPE) == MachO::N_UNDF)
437 break;
439 NumExtDefSymbols++;
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);
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;
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;
473 VMSize = std::max(VMSize, Sec.Addr + Sec.Size);
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;
499 Offset += FileOffsetInSegment;
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;
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");
533 if (MLC.dysymtab_command_data.nindirectsyms != 0)
534 return createStringError(llvm::errc::not_supported,
535 "indirect symbol table is not yet supported");
537 updateDySymTab(MLC);
538 break;
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);
557 return Error::success();
560 void MachOWriter::constructStringTable() {
561 for (std::unique_ptr<SymbolEntry> &Sym : O.SymTable.Symbols)
562 StrTableBuilder.add(Sym->Name);
563 StrTableBuilder.finalize();
566 Error MachOWriter::finalize() {
567 updateSizeOfCmds();
568 constructStringTable();
570 if (auto E = layout())
571 return E;
573 return Error::success();
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();
588 } // end namespace macho
589 } // end namespace objcopy
590 } // end namespace llvm