1 //===- MachOWriter.cpp ------------------------------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 #include "MachOWriter.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"
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
);
92 Ends
.push_back(S
.RelOff
+
93 S
.NReloc
* sizeof(MachO::any_relocation_info
));
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
);
119 Is64Bit
? sizeof(MachO::mach_header_64
) : sizeof(MachO::mach_header
);
120 memcpy(B
.getBufferStart(), &Header
, HeaderSize
);
123 void MachOWriter::updateSymbolIndexes() {
125 for (auto &Symbol
: O
.SymTable
.Symbols
) {
126 Symbol
->Index
= 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
);
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
);
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(); \
170 // Copy the load command as it is.
171 switch (MLC
.load_command_data
.cmd
) {
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();
182 #include "llvm/BinaryFormat/MachO.def"
187 template <typename StructType
>
188 void MachOWriter::writeSectionInLoadCommand(const Section
&Sec
, uint8_t *&Out
) {
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())
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(),
222 for (size_t Index
= 0; Index
< Sec
.Relocations
.size(); ++Index
) {
223 auto RelocInfo
= Sec
.Relocations
[Index
];
224 if (!RelocInfo
.Scattered
) {
226 reinterpret_cast<MachO::relocation_info
*>(&RelocInfo
.Info
);
227 Info
->r_symbolnum
= RelocInfo
.Symbol
->Index
;
230 if (IsLittleEndian
!= sys::IsLittleEndianHost
)
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
,
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
)
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
)
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
);
281 writeNListEntry
<MachO::nlist_64
>(*Sym
, IsLittleEndian
, SymTable
, Nstrx
);
283 writeNListEntry
<MachO::nlist
>(*Sym
, IsLittleEndian
, SymTable
, Nstrx
);
287 void MachOWriter::writeRebaseInfo() {
288 if (!O
.DyLdInfoCommandIndex
)
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
)
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
)
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
)
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
)
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
)
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
)
373 {DyLdInfoCommand
.weak_bind_off
, &MachOWriter::writeWeakBindInfo
});
374 if (DyLdInfoCommand
.lazy_bind_off
)
376 {DyLdInfoCommand
.lazy_bind_off
, &MachOWriter::writeLazyBindInfo
});
377 if (DyLdInfoCommand
.export_off
)
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() {
392 for (const auto &LC
: O
.LoadCommands
) {
393 auto &MLC
= LC
.MachOLoadCommand
;
394 auto cmd
= MLC
.load_command_data
.cmd
;
397 case MachO::LC_SEGMENT
:
398 Size
+= sizeof(MachO::segment_command
) +
399 sizeof(MachO::section
) * LC
.Sections
.size();
401 case MachO::LC_SEGMENT_64
:
402 Size
+= sizeof(MachO::segment_command_64
) +
403 sizeof(MachO::section_64
) * LC
.Sections
.size();
408 #define HANDLE_LOAD_COMMAND(LCName, LCValue, LCStruct) \
409 case MachO::LCName: \
410 Size += sizeof(MachO::LCStruct); \
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
))
434 uint32_t NumExtDefSymbols
= 0;
435 for (; Iter
!= End
; Iter
++) {
436 if (((*Iter
)->n_type
& MachO::N_TYPE
) == MachO::N_UNDF
)
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
;
460 for (auto &LC
: O
.LoadCommands
) {
461 uint64_t FileOff
= Offset
;
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
;
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
;
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
;
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
;
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");
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
:
547 case MachO::LC_SOURCE_VERSION
:
548 // Nothing to update.
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() {
568 constructStringTable();
570 if (auto E
= layout())
573 return Error::success();
576 Error
MachOWriter::write() {
577 if (Error E
= B
.allocate(totalSize()))
579 memset(B
.getBufferStart(), 0, totalSize());
581 updateSymbolIndexes();
588 } // end namespace macho
589 } // end namespace objcopy
590 } // end namespace llvm