blob: f0c0aeec6dba507e07308e4b084df462d9fbbb25 [file] [log] [blame]
Alexander Shaposhnikovd911ed12019-02-02 00:38:07 +00001//===- MachOWriter.cpp ------------------------------------------*- C++ -*-===//
2//
Chandler Carruth127252b2019-02-11 08:25:19 +00003// 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
Alexander Shaposhnikovd911ed12019-02-02 00:38:07 +00006//
7//===----------------------------------------------------------------------===//
8
9#include "MachOWriter.h"
Alexander Shaposhnikovd911ed12019-02-02 00:38:07 +000010#include "Object.h"
11#include "llvm/ADT/STLExtras.h"
12#include "llvm/BinaryFormat/MachO.h"
13#include "llvm/Object/MachO.h"
Seiya Nutab728e532019-06-08 01:22:54 +000014#include "llvm/Support/Errc.h"
15#include "llvm/Support/ErrorHandling.h"
Alexander Shaposhnikovd911ed12019-02-02 00:38:07 +000016#include <memory>
17
18namespace llvm {
19namespace objcopy {
20namespace macho {
21
22size_t MachOWriter::headerSize() const {
23 return Is64Bit ? sizeof(MachO::mach_header_64) : sizeof(MachO::mach_header);
24}
25
26size_t MachOWriter::loadCommandsSize() const { return O.Header.SizeOfCmds; }
27
28size_t MachOWriter::symTableSize() const {
29 return O.SymTable.NameList.size() *
30 (Is64Bit ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist));
31}
32
33size_t MachOWriter::strTableSize() const {
34 size_t S = 0;
35 for (const auto &Str : O.StrTable.Strings)
36 S += Str.size();
37 S += (O.StrTable.Strings.empty() ? 0 : O.StrTable.Strings.size() - 1);
38 return S;
39}
40
41size_t MachOWriter::totalSize() const {
42 // Going from tail to head and looking for an appropriate "anchor" to
43 // calculate the total size assuming that all the offsets are either valid
44 // ("true") or 0 (0 indicates that the corresponding part is missing).
45
46 SmallVector<size_t, 7> Ends;
47 if (O.SymTabCommandIndex) {
48 const MachO::symtab_command &SymTabCommand =
49 O.LoadCommands[*O.SymTabCommandIndex]
50 .MachOLoadCommand.symtab_command_data;
51 if (SymTabCommand.symoff) {
52 assert((SymTabCommand.nsyms == O.SymTable.NameList.size()) &&
53 "Incorrect number of symbols");
54 Ends.push_back(SymTabCommand.symoff + symTableSize());
55 }
56 if (SymTabCommand.stroff) {
57 assert((SymTabCommand.strsize == strTableSize()) &&
58 "Incorrect string table size");
59 Ends.push_back(SymTabCommand.stroff + SymTabCommand.strsize);
60 }
61 }
62 if (O.DyLdInfoCommandIndex) {
63 const MachO::dyld_info_command &DyLdInfoCommand =
64 O.LoadCommands[*O.DyLdInfoCommandIndex]
65 .MachOLoadCommand.dyld_info_command_data;
66 if (DyLdInfoCommand.rebase_off) {
67 assert((DyLdInfoCommand.rebase_size == O.Rebases.Opcodes.size()) &&
68 "Incorrect rebase opcodes size");
69 Ends.push_back(DyLdInfoCommand.rebase_off + DyLdInfoCommand.rebase_size);
70 }
71 if (DyLdInfoCommand.bind_off) {
72 assert((DyLdInfoCommand.bind_size == O.Binds.Opcodes.size()) &&
73 "Incorrect bind opcodes size");
74 Ends.push_back(DyLdInfoCommand.bind_off + DyLdInfoCommand.bind_size);
75 }
76 if (DyLdInfoCommand.weak_bind_off) {
77 assert((DyLdInfoCommand.weak_bind_size == O.WeakBinds.Opcodes.size()) &&
78 "Incorrect weak bind opcodes size");
79 Ends.push_back(DyLdInfoCommand.weak_bind_off +
80 DyLdInfoCommand.weak_bind_size);
81 }
82 if (DyLdInfoCommand.lazy_bind_off) {
83 assert((DyLdInfoCommand.lazy_bind_size == O.LazyBinds.Opcodes.size()) &&
84 "Incorrect lazy bind opcodes size");
85 Ends.push_back(DyLdInfoCommand.lazy_bind_off +
86 DyLdInfoCommand.lazy_bind_size);
87 }
88 if (DyLdInfoCommand.export_off) {
89 assert((DyLdInfoCommand.export_size == O.Exports.Trie.size()) &&
90 "Incorrect trie size");
91 Ends.push_back(DyLdInfoCommand.export_off + DyLdInfoCommand.export_size);
92 }
93 }
94
95 // Otherwise, use the last section / reloction.
96 for (const auto &LC : O.LoadCommands)
97 for (const auto &S : LC.Sections) {
98 Ends.push_back(S.Offset + S.Size);
99 if (S.RelOff)
100 Ends.push_back(S.RelOff +
101 S.NReloc * sizeof(MachO::any_relocation_info));
102 }
103
104 if (!Ends.empty())
105 return *std::max_element(Ends.begin(), Ends.end());
106
107 // Otherwise, we have only Mach header and load commands.
108 return headerSize() + loadCommandsSize();
109}
110
111void MachOWriter::writeHeader() {
112 MachO::mach_header_64 Header;
113
114 Header.magic = O.Header.Magic;
115 Header.cputype = O.Header.CPUType;
116 Header.cpusubtype = O.Header.CPUSubType;
117 Header.filetype = O.Header.FileType;
118 Header.ncmds = O.Header.NCmds;
119 Header.sizeofcmds = O.Header.SizeOfCmds;
120 Header.flags = O.Header.Flags;
121 Header.reserved = O.Header.Reserved;
122
123 if (IsLittleEndian != sys::IsLittleEndianHost)
124 MachO::swapStruct(Header);
125
126 auto HeaderSize =
127 Is64Bit ? sizeof(MachO::mach_header_64) : sizeof(MachO::mach_header);
128 memcpy(B.getBufferStart(), &Header, HeaderSize);
129}
130
131void MachOWriter::writeLoadCommands() {
132 uint8_t *Begin = B.getBufferStart() + headerSize();
Alexander Shaposhnikovd911ed12019-02-02 00:38:07 +0000133 for (const auto &LC : O.LoadCommands) {
Seiya Nutab728e532019-06-08 01:22:54 +0000134 // 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
Alexander Shaposhnikovd911ed12019-02-02 00:38:07 +0000158#define HANDLE_LOAD_COMMAND(LCName, LCValue, LCStruct) \
159 case MachO::LCName: \
160 assert(sizeof(MachO::LCStruct) + LC.Payload.size() == \
Seiya Nutab728e532019-06-08 01:22:54 +0000161 MLC.load_command_data.cmdsize); \
Alexander Shaposhnikovd911ed12019-02-02 00:38:07 +0000162 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
Seiya Nutab728e532019-06-08 01:22:54 +0000170 // Copy the load command as it is.
171 switch (MLC.load_command_data.cmd) {
Alexander Shaposhnikovd911ed12019-02-02 00:38:07 +0000172 default:
173 assert(sizeof(MachO::load_command) + LC.Payload.size() ==
Seiya Nutab728e532019-06-08 01:22:54 +0000174 MLC.load_command_data.cmdsize);
Alexander Shaposhnikovd911ed12019-02-02 00:38:07 +0000175 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
Seiya Nutab728e532019-06-08 01:22:54 +0000187template <typename StructType>
188void 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
Alexander Shaposhnikovd911ed12019-02-02 00:38:07 +0000212void MachOWriter::writeSections() {
213 for (const auto &LC : O.LoadCommands)
214 for (const auto &Sec : LC.Sections) {
Seiya Nutab728e532019-06-08 01:22:54 +0000215 if (Sec.isVirtualSection())
216 continue;
217
Alexander Shaposhnikovd911ed12019-02-02 00:38:07 +0000218 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 MachO::any_relocation_info R = Sec.Relocations[Index];
224 if (IsLittleEndian != sys::IsLittleEndianHost)
225 MachO::swapStruct(R);
226 memcpy(B.getBufferStart() + Sec.RelOff +
227 Index * sizeof(MachO::any_relocation_info),
228 &R, sizeof(R));
229 }
230 }
231}
232
233template <typename NListType>
234void writeNListEntry(const NListEntry &NLE, bool IsLittleEndian, char *&Out) {
235 NListType ListEntry;
236 ListEntry.n_strx = NLE.n_strx;
237 ListEntry.n_type = NLE.n_type;
238 ListEntry.n_sect = NLE.n_sect;
239 ListEntry.n_desc = NLE.n_desc;
240 ListEntry.n_value = NLE.n_value;
241
242 if (IsLittleEndian != sys::IsLittleEndianHost)
243 MachO::swapStruct(ListEntry);
244 memcpy(Out, reinterpret_cast<const char *>(&ListEntry), sizeof(NListType));
245 Out += sizeof(NListType);
246}
247
248void MachOWriter::writeSymbolTable() {
249 if (!O.SymTabCommandIndex)
250 return;
251 const MachO::symtab_command &SymTabCommand =
252 O.LoadCommands[*O.SymTabCommandIndex]
253 .MachOLoadCommand.symtab_command_data;
254 assert((SymTabCommand.nsyms == O.SymTable.NameList.size()) &&
255 "Incorrect number of symbols");
256 char *Out = (char *)B.getBufferStart() + SymTabCommand.symoff;
257 for (auto NLE : O.SymTable.NameList) {
258 if (Is64Bit)
259 writeNListEntry<MachO::nlist_64>(NLE, IsLittleEndian, Out);
260 else
261 writeNListEntry<MachO::nlist>(NLE, IsLittleEndian, Out);
262 }
263}
264
265void MachOWriter::writeStringTable() {
266 if (!O.SymTabCommandIndex)
267 return;
268 const MachO::symtab_command &SymTabCommand =
269 O.LoadCommands[*O.SymTabCommandIndex]
270 .MachOLoadCommand.symtab_command_data;
271 char *Out = (char *)B.getBufferStart() + SymTabCommand.stroff;
272 assert((SymTabCommand.strsize == strTableSize()) &&
273 "Incorrect string table size");
274 for (size_t Index = 0; Index < O.StrTable.Strings.size(); ++Index) {
275 memcpy(Out, O.StrTable.Strings[Index].data(),
276 O.StrTable.Strings[Index].size());
277 Out += O.StrTable.Strings[Index].size();
278 if (Index + 1 != O.StrTable.Strings.size()) {
279 memcpy(Out, "\0", 1);
280 Out += 1;
281 }
282 }
283}
284
285void MachOWriter::writeRebaseInfo() {
286 if (!O.DyLdInfoCommandIndex)
287 return;
288 const MachO::dyld_info_command &DyLdInfoCommand =
289 O.LoadCommands[*O.DyLdInfoCommandIndex]
290 .MachOLoadCommand.dyld_info_command_data;
291 char *Out = (char *)B.getBufferStart() + DyLdInfoCommand.rebase_off;
292 assert((DyLdInfoCommand.rebase_size == O.Rebases.Opcodes.size()) &&
293 "Incorrect rebase opcodes size");
294 memcpy(Out, O.Rebases.Opcodes.data(), O.Rebases.Opcodes.size());
295}
296
297void MachOWriter::writeBindInfo() {
298 if (!O.DyLdInfoCommandIndex)
299 return;
300 const MachO::dyld_info_command &DyLdInfoCommand =
301 O.LoadCommands[*O.DyLdInfoCommandIndex]
302 .MachOLoadCommand.dyld_info_command_data;
303 char *Out = (char *)B.getBufferStart() + DyLdInfoCommand.bind_off;
304 assert((DyLdInfoCommand.bind_size == O.Binds.Opcodes.size()) &&
305 "Incorrect bind opcodes size");
306 memcpy(Out, O.Binds.Opcodes.data(), O.Binds.Opcodes.size());
307}
308
309void MachOWriter::writeWeakBindInfo() {
310 if (!O.DyLdInfoCommandIndex)
311 return;
312 const MachO::dyld_info_command &DyLdInfoCommand =
313 O.LoadCommands[*O.DyLdInfoCommandIndex]
314 .MachOLoadCommand.dyld_info_command_data;
315 char *Out = (char *)B.getBufferStart() + DyLdInfoCommand.weak_bind_off;
316 assert((DyLdInfoCommand.weak_bind_size == O.WeakBinds.Opcodes.size()) &&
317 "Incorrect weak bind opcodes size");
318 memcpy(Out, O.WeakBinds.Opcodes.data(), O.WeakBinds.Opcodes.size());
319}
320
321void MachOWriter::writeLazyBindInfo() {
322 if (!O.DyLdInfoCommandIndex)
323 return;
324 const MachO::dyld_info_command &DyLdInfoCommand =
325 O.LoadCommands[*O.DyLdInfoCommandIndex]
326 .MachOLoadCommand.dyld_info_command_data;
327 char *Out = (char *)B.getBufferStart() + DyLdInfoCommand.lazy_bind_off;
328 assert((DyLdInfoCommand.lazy_bind_size == O.LazyBinds.Opcodes.size()) &&
329 "Incorrect lazy bind opcodes size");
330 memcpy(Out, O.LazyBinds.Opcodes.data(), O.LazyBinds.Opcodes.size());
331}
332
333void MachOWriter::writeExportInfo() {
334 if (!O.DyLdInfoCommandIndex)
335 return;
336 const MachO::dyld_info_command &DyLdInfoCommand =
337 O.LoadCommands[*O.DyLdInfoCommandIndex]
338 .MachOLoadCommand.dyld_info_command_data;
339 char *Out = (char *)B.getBufferStart() + DyLdInfoCommand.export_off;
340 assert((DyLdInfoCommand.export_size == O.Exports.Trie.size()) &&
341 "Incorrect export trie size");
342 memcpy(Out, O.Exports.Trie.data(), O.Exports.Trie.size());
343}
344
345void MachOWriter::writeTail() {
346 typedef void (MachOWriter::*WriteHandlerType)(void);
347 typedef std::pair<uint64_t, WriteHandlerType> WriteOperation;
348 SmallVector<WriteOperation, 7> Queue;
349
350 if (O.SymTabCommandIndex) {
351 const MachO::symtab_command &SymTabCommand =
352 O.LoadCommands[*O.SymTabCommandIndex]
353 .MachOLoadCommand.symtab_command_data;
354 if (SymTabCommand.symoff)
355 Queue.push_back({SymTabCommand.symoff, &MachOWriter::writeSymbolTable});
356 if (SymTabCommand.stroff)
357 Queue.push_back({SymTabCommand.stroff, &MachOWriter::writeStringTable});
358 }
359
360 if (O.DyLdInfoCommandIndex) {
361 const MachO::dyld_info_command &DyLdInfoCommand =
362 O.LoadCommands[*O.DyLdInfoCommandIndex]
363 .MachOLoadCommand.dyld_info_command_data;
364 if (DyLdInfoCommand.rebase_off)
365 Queue.push_back(
366 {DyLdInfoCommand.rebase_off, &MachOWriter::writeRebaseInfo});
367 if (DyLdInfoCommand.bind_off)
368 Queue.push_back({DyLdInfoCommand.bind_off, &MachOWriter::writeBindInfo});
369 if (DyLdInfoCommand.weak_bind_off)
370 Queue.push_back(
371 {DyLdInfoCommand.weak_bind_off, &MachOWriter::writeWeakBindInfo});
372 if (DyLdInfoCommand.lazy_bind_off)
373 Queue.push_back(
374 {DyLdInfoCommand.lazy_bind_off, &MachOWriter::writeLazyBindInfo});
375 if (DyLdInfoCommand.export_off)
376 Queue.push_back(
377 {DyLdInfoCommand.export_off, &MachOWriter::writeExportInfo});
378 }
379
380 llvm::sort(Queue, [](const WriteOperation &LHS, const WriteOperation &RHS) {
381 return LHS.first < RHS.first;
382 });
383
384 for (auto WriteOp : Queue)
385 (this->*WriteOp.second)();
386}
387
Seiya Nutab728e532019-06-08 01:22:54 +0000388void MachOWriter::updateSizeOfCmds() {
389 auto Size = 0;
390 for (const auto &LC : O.LoadCommands) {
391 auto &MLC = LC.MachOLoadCommand;
392 auto cmd = MLC.load_command_data.cmd;
393
394 switch (cmd) {
395 case MachO::LC_SEGMENT:
396 Size += sizeof(MachO::segment_command) +
397 sizeof(MachO::section) * LC.Sections.size();
398 continue;
399 case MachO::LC_SEGMENT_64:
400 Size += sizeof(MachO::segment_command_64) +
401 sizeof(MachO::section_64) * LC.Sections.size();
402 continue;
403 }
404
405 switch (cmd) {
406#define HANDLE_LOAD_COMMAND(LCName, LCValue, LCStruct) \
407 case MachO::LCName: \
408 Size += sizeof(MachO::LCStruct); \
409 break;
410#include "llvm/BinaryFormat/MachO.def"
411#undef HANDLE_LOAD_COMMAND
412 }
413 }
414
415 O.Header.SizeOfCmds = Size;
416}
417
418// Updates the index and the number of local/external/undefined symbols. Here we
419// assume that MLC is a LC_DYSYMTAB and the nlist entries in the symbol table
420// are already sorted by the those types.
421void MachOWriter::updateDySymTab(MachO::macho_load_command &MLC) {
422 uint32_t NumLocalSymbols = 0;
423 auto Iter = O.SymTable.NameList.begin();
424 auto End = O.SymTable.NameList.end();
425 for (; Iter != End; Iter++) {
426 if (Iter->n_type & (MachO::N_EXT | MachO::N_PEXT))
427 break;
428
429 NumLocalSymbols++;
430 }
431
432 uint32_t NumExtDefSymbols = 0;
433 for (; Iter != End; Iter++) {
434 if ((Iter->n_type & MachO::N_TYPE) == MachO::N_UNDF)
435 break;
436
437 NumExtDefSymbols++;
438 }
439
440 MLC.dysymtab_command_data.ilocalsym = 0;
441 MLC.dysymtab_command_data.nlocalsym = NumLocalSymbols;
442 MLC.dysymtab_command_data.iextdefsym = NumLocalSymbols;
443 MLC.dysymtab_command_data.nextdefsym = NumExtDefSymbols;
444 MLC.dysymtab_command_data.iundefsym = NumLocalSymbols + NumExtDefSymbols;
445 MLC.dysymtab_command_data.nundefsym =
446 O.SymTable.NameList.size() - (NumLocalSymbols + NumExtDefSymbols);
447}
448
449// Recomputes and updates offset and size fields in load commands and sections
450// since they could be modified.
451Error MachOWriter::layout() {
452 auto SizeOfCmds = loadCommandsSize();
453 auto Offset = headerSize() + SizeOfCmds;
454 O.Header.NCmds = O.LoadCommands.size();
455 O.Header.SizeOfCmds = SizeOfCmds;
456
457 // Lay out sections.
458 for (auto &LC : O.LoadCommands) {
459 uint64_t FileOff = Offset;
460 uint64_t VMSize = 0;
461 uint64_t FileOffsetInSegment = 0;
462 for (auto &Sec : LC.Sections) {
463 if (!Sec.isVirtualSection()) {
464 auto FilePaddingSize =
Simon Pilgrimc6a930e2019-06-10 10:13:32 +0000465 OffsetToAlignment(FileOffsetInSegment, 1ull << Sec.Align);
Seiya Nutab728e532019-06-08 01:22:54 +0000466 Sec.Offset = Offset + FileOffsetInSegment + FilePaddingSize;
467 Sec.Size = Sec.Content.size();
468 FileOffsetInSegment += FilePaddingSize + Sec.Size;
469 }
470
471 VMSize = std::max(VMSize, Sec.Addr + Sec.Size);
472 }
473
474 // TODO: Handle the __PAGEZERO segment.
475 auto &MLC = LC.MachOLoadCommand;
476 switch (MLC.load_command_data.cmd) {
477 case MachO::LC_SEGMENT:
478 MLC.segment_command_data.cmdsize =
479 sizeof(MachO::segment_command) +
480 sizeof(MachO::section) * LC.Sections.size();
481 MLC.segment_command_data.nsects = LC.Sections.size();
482 MLC.segment_command_data.fileoff = FileOff;
483 MLC.segment_command_data.vmsize = VMSize;
484 MLC.segment_command_data.filesize = FileOffsetInSegment;
485 break;
486 case MachO::LC_SEGMENT_64:
487 MLC.segment_command_64_data.cmdsize =
488 sizeof(MachO::segment_command_64) +
489 sizeof(MachO::section_64) * LC.Sections.size();
490 MLC.segment_command_64_data.nsects = LC.Sections.size();
491 MLC.segment_command_64_data.fileoff = FileOff;
492 MLC.segment_command_64_data.vmsize = VMSize;
493 MLC.segment_command_64_data.filesize = FileOffsetInSegment;
494 break;
495 }
496
497 Offset += FileOffsetInSegment;
498 }
499
500 // Lay out relocations.
501 for (auto &LC : O.LoadCommands)
502 for (auto &Sec : LC.Sections) {
503 Sec.RelOff = Sec.Relocations.empty() ? 0 : Offset;
504 Sec.NReloc = Sec.Relocations.size();
505 Offset += sizeof(MachO::any_relocation_info) * Sec.NReloc;
506 }
507
508 // Lay out tail stuff.
509 auto NListSize = Is64Bit ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
510 for (auto &LC : O.LoadCommands) {
511 auto &MLC = LC.MachOLoadCommand;
512 auto cmd = MLC.load_command_data.cmd;
513 switch (cmd) {
514 case MachO::LC_SYMTAB:
515 MLC.symtab_command_data.symoff = Offset;
516 MLC.symtab_command_data.nsyms = O.SymTable.NameList.size();
517 Offset += NListSize * MLC.symtab_command_data.nsyms;
518 MLC.symtab_command_data.stroff = Offset;
519 Offset += MLC.symtab_command_data.strsize;
520 break;
521 case MachO::LC_DYSYMTAB: {
522 if (MLC.dysymtab_command_data.ntoc != 0 ||
523 MLC.dysymtab_command_data.nmodtab != 0 ||
524 MLC.dysymtab_command_data.nextrefsyms != 0 ||
525 MLC.dysymtab_command_data.nlocrel != 0 ||
526 MLC.dysymtab_command_data.nextrel != 0)
527 return createStringError(llvm::errc::not_supported,
528 "shared library is not yet supported");
529
530 if (MLC.dysymtab_command_data.nindirectsyms != 0)
531 return createStringError(llvm::errc::not_supported,
532 "indirect symbol table is not yet supported");
533
534 updateDySymTab(MLC);
535 break;
536 }
537 case MachO::LC_SEGMENT:
538 case MachO::LC_SEGMENT_64:
539 case MachO::LC_VERSION_MIN_MACOSX:
540 case MachO::LC_BUILD_VERSION:
541 case MachO::LC_ID_DYLIB:
542 case MachO::LC_LOAD_DYLIB:
543 case MachO::LC_UUID:
544 case MachO::LC_SOURCE_VERSION:
545 // Nothing to update.
546 break;
547 default:
548 // Abort if it's unsupported in order to prevent corrupting the object.
549 return createStringError(llvm::errc::not_supported,
550 "unsupported load command (cmd=0x%x)", cmd);
551 }
552 }
553
554 return Error::success();
555}
556
557Error MachOWriter::finalize() {
558 updateSizeOfCmds();
559
560 if (auto E = layout())
561 return E;
562
563 return Error::success();
564}
565
Alexander Shaposhnikovd911ed12019-02-02 00:38:07 +0000566Error MachOWriter::write() {
567 if (Error E = B.allocate(totalSize()))
568 return E;
569 memset(B.getBufferStart(), 0, totalSize());
570 writeHeader();
571 writeLoadCommands();
572 writeSections();
573 writeTail();
Jordan Rupprecht2e862c72019-02-04 19:09:20 +0000574 return B.commit();
Alexander Shaposhnikovd911ed12019-02-02 00:38:07 +0000575}
576
577} // end namespace macho
578} // end namespace objcopy
579} // end namespace llvm