7
7
// ===----------------------------------------------------------------------===//
8
8
9
9
#include " MachOWriter.h"
10
+ #include " MachOLayoutBuilder.h"
10
11
#include " Object.h"
11
12
#include " llvm/ADT/STLExtras.h"
12
13
#include " llvm/BinaryFormat/MachO.h"
@@ -40,16 +41,10 @@ size_t MachOWriter::totalSize() const {
40
41
const MachO::symtab_command &SymTabCommand =
41
42
O.LoadCommands [*O.SymTabCommandIndex ]
42
43
.MachOLoadCommand .symtab_command_data ;
43
- if (SymTabCommand.symoff ) {
44
- assert ((SymTabCommand.nsyms == O.SymTable .Symbols .size ()) &&
45
- " Incorrect number of symbols" );
44
+ if (SymTabCommand.symoff )
46
45
Ends.push_back (SymTabCommand.symoff + symTableSize ());
47
- }
48
- if (SymTabCommand.stroff ) {
49
- assert ((SymTabCommand.strsize == StrTableBuilder.getSize ()) &&
50
- " Incorrect string table size" );
46
+ if (SymTabCommand.stroff )
51
47
Ends.push_back (SymTabCommand.stroff + SymTabCommand.strsize );
52
- }
53
48
}
54
49
if (O.DyLdInfoCommandIndex ) {
55
50
const MachO::dyld_info_command &DyLdInfoCommand =
@@ -84,6 +79,36 @@ size_t MachOWriter::totalSize() const {
84
79
}
85
80
}
86
81
82
+ if (O.DySymTabCommandIndex ) {
83
+ const MachO::dysymtab_command &DySymTabCommand =
84
+ O.LoadCommands [*O.DySymTabCommandIndex ]
85
+ .MachOLoadCommand .dysymtab_command_data ;
86
+
87
+ if (DySymTabCommand.indirectsymoff )
88
+ Ends.push_back (DySymTabCommand.indirectsymoff +
89
+ sizeof (uint32_t ) * O.IndirectSymTable .Symbols .size ());
90
+ }
91
+
92
+ if (O.DataInCodeCommandIndex ) {
93
+ const MachO::linkedit_data_command &LinkEditDataCommand =
94
+ O.LoadCommands [*O.DataInCodeCommandIndex ]
95
+ .MachOLoadCommand .linkedit_data_command_data ;
96
+
97
+ if (LinkEditDataCommand.dataoff )
98
+ Ends.push_back (LinkEditDataCommand.dataoff +
99
+ LinkEditDataCommand.datasize );
100
+ }
101
+
102
+ if (O.FunctionStartsCommandIndex ) {
103
+ const MachO::linkedit_data_command &LinkEditDataCommand =
104
+ O.LoadCommands [*O.FunctionStartsCommandIndex ]
105
+ .MachOLoadCommand .linkedit_data_command_data ;
106
+
107
+ if (LinkEditDataCommand.dataoff )
108
+ Ends.push_back (LinkEditDataCommand.dataoff +
109
+ LinkEditDataCommand.datasize );
110
+ }
111
+
87
112
// Otherwise, use the last section / reloction.
88
113
for (const auto &LC : O.LoadCommands )
89
114
for (const auto &S : LC.Sections ) {
@@ -120,14 +145,6 @@ void MachOWriter::writeHeader() {
120
145
memcpy (B.getBufferStart (), &Header, HeaderSize);
121
146
}
122
147
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
148
void MachOWriter::writeLoadCommands () {
132
149
uint8_t *Begin = B.getBufferStart () + headerSize ();
133
150
for (const auto &LC : O.LoadCommands ) {
@@ -261,7 +278,7 @@ void MachOWriter::writeSymbolTable() {
261
278
.MachOLoadCommand .symtab_command_data ;
262
279
263
280
uint8_t *StrTable = (uint8_t *)B.getBufferStart () + SymTabCommand.stroff ;
264
- StrTableBuilder .write (StrTable);
281
+ LayoutBuilder. getStringTableBuilder () .write (StrTable);
265
282
}
266
283
267
284
void MachOWriter::writeStringTable () {
@@ -275,7 +292,7 @@ void MachOWriter::writeStringTable() {
275
292
for (auto Iter = O.SymTable .Symbols .begin (), End = O.SymTable .Symbols .end ();
276
293
Iter != End; Iter++) {
277
294
SymbolEntry *Sym = Iter->get ();
278
- auto Nstrx = StrTableBuilder .getOffset (Sym->Name );
295
+ uint32_t Nstrx = LayoutBuilder. getStringTableBuilder () .getOffset (Sym->Name );
279
296
280
297
if (Is64Bit)
281
298
writeNListEntry<MachO::nlist_64>(*Sym, IsLittleEndian, SymTable, Nstrx);
@@ -344,6 +361,45 @@ void MachOWriter::writeExportInfo() {
344
361
memcpy (Out, O.Exports .Trie .data (), O.Exports .Trie .size ());
345
362
}
346
363
364
+ void MachOWriter::writeIndirectSymbolTable () {
365
+ if (!O.DySymTabCommandIndex )
366
+ return ;
367
+
368
+ const MachO::dysymtab_command &DySymTabCommand =
369
+ O.LoadCommands [*O.DySymTabCommandIndex ]
370
+ .MachOLoadCommand .dysymtab_command_data ;
371
+
372
+ char *Out = (char *)B.getBufferStart () + DySymTabCommand.indirectsymoff ;
373
+ assert ((DySymTabCommand.nindirectsyms == O.IndirectSymTable .Symbols .size ()) &&
374
+ " Incorrect indirect symbol table size" );
375
+ memcpy (Out, O.IndirectSymTable .Symbols .data (),
376
+ sizeof (uint32_t ) * O.IndirectSymTable .Symbols .size ());
377
+ }
378
+
379
+ void MachOWriter::writeDataInCodeData () {
380
+ if (!O.DataInCodeCommandIndex )
381
+ return ;
382
+ const MachO::linkedit_data_command &LinkEditDataCommand =
383
+ O.LoadCommands [*O.DataInCodeCommandIndex ]
384
+ .MachOLoadCommand .linkedit_data_command_data ;
385
+ char *Out = (char *)B.getBufferStart () + LinkEditDataCommand.dataoff ;
386
+ assert ((LinkEditDataCommand.datasize == O.DataInCode .Data .size ()) &&
387
+ " Incorrect data in code data size" );
388
+ memcpy (Out, O.DataInCode .Data .data (), O.DataInCode .Data .size ());
389
+ }
390
+
391
+ void MachOWriter::writeFunctionStartsData () {
392
+ if (!O.FunctionStartsCommandIndex )
393
+ return ;
394
+ const MachO::linkedit_data_command &LinkEditDataCommand =
395
+ O.LoadCommands [*O.FunctionStartsCommandIndex ]
396
+ .MachOLoadCommand .linkedit_data_command_data ;
397
+ char *Out = (char *)B.getBufferStart () + LinkEditDataCommand.dataoff ;
398
+ assert ((LinkEditDataCommand.datasize == O.FunctionStarts .Data .size ()) &&
399
+ " Incorrect function starts data size" );
400
+ memcpy (Out, O.FunctionStarts .Data .data (), O.FunctionStarts .Data .size ());
401
+ }
402
+
347
403
void MachOWriter::writeTail () {
348
404
typedef void (MachOWriter::*WriteHandlerType)(void );
349
405
typedef std::pair<uint64_t , WriteHandlerType> WriteOperation;
@@ -379,206 +435,51 @@ void MachOWriter::writeTail() {
379
435
{DyLdInfoCommand.export_off , &MachOWriter::writeExportInfo});
380
436
}
381
437
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
+ if (O.DySymTabCommandIndex ) {
439
+ const MachO::dysymtab_command &DySymTabCommand =
440
+ O.LoadCommands [*O.DySymTabCommandIndex ]
441
+ .MachOLoadCommand .dysymtab_command_data ;
438
442
439
- NumExtDefSymbols++;
443
+ if (DySymTabCommand.indirectsymoff )
444
+ Queue.emplace_back (DySymTabCommand.indirectsymoff ,
445
+ &MachOWriter::writeIndirectSymbolTable);
440
446
}
441
447
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
- }
448
+ if (O.DataInCodeCommandIndex ) {
449
+ const MachO::linkedit_data_command &LinkEditDataCommand =
450
+ O.LoadCommands [*O.DataInCodeCommandIndex ]
451
+ .MachOLoadCommand .linkedit_data_command_data ;
498
452
499
- Offset += FileOffsetInSegment;
453
+ if (LinkEditDataCommand.dataoff )
454
+ Queue.emplace_back (LinkEditDataCommand.dataoff ,
455
+ &MachOWriter::writeDataInCodeData);
500
456
}
501
457
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
- }
458
+ if (O.FunctionStartsCommandIndex ) {
459
+ const MachO::linkedit_data_command &LinkEditDataCommand =
460
+ O.LoadCommands [*O.FunctionStartsCommandIndex ]
461
+ .MachOLoadCommand .linkedit_data_command_data ;
509
462
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
- }
463
+ if (LinkEditDataCommand.dataoff )
464
+ Queue.emplace_back (LinkEditDataCommand.dataoff ,
465
+ &MachOWriter::writeFunctionStartsData);
555
466
}
556
467
557
- return Error::success ();
558
- }
468
+ llvm::sort (Queue, [](const WriteOperation &LHS, const WriteOperation &RHS) {
469
+ return LHS.first < RHS.first ;
470
+ });
559
471
560
- void MachOWriter::constructStringTable () {
561
- for (std::unique_ptr<SymbolEntry> &Sym : O.SymTable .Symbols )
562
- StrTableBuilder.add (Sym->Name );
563
- StrTableBuilder.finalize ();
472
+ for (auto WriteOp : Queue)
473
+ (this ->*WriteOp.second )();
564
474
}
565
475
566
- Error MachOWriter::finalize () {
567
- updateSizeOfCmds ();
568
- constructStringTable ();
569
-
570
- if (auto E = layout ())
571
- return E;
572
-
573
- return Error::success ();
574
- }
476
+ Error MachOWriter::finalize () { return LayoutBuilder.layout (); }
575
477
576
478
Error MachOWriter::write () {
577
479
if (Error E = B.allocate (totalSize ()))
578
480
return E;
579
481
memset (B.getBufferStart (), 0 , totalSize ());
580
482
writeHeader ();
581
- updateSymbolIndexes ();
582
483
writeLoadCommands ();
583
484
writeSections ();
584
485
writeTail ();
0 commit comments