blob: 4b0077efb0c24ad47245b66143519805afb07433 [file] [log] [blame]
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001//===- lib/MC/MachObjectWriter.cpp - Mach-O File Writer -------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "llvm/MC/MachObjectWriter.h"
11#include "llvm/ADT/StringMap.h"
12#include "llvm/ADT/Twine.h"
13#include "llvm/MC/MCAssembler.h"
14#include "llvm/MC/MCExpr.h"
15#include "llvm/MC/MCObjectWriter.h"
16#include "llvm/MC/MCSectionMachO.h"
17#include "llvm/MC/MCSymbol.h"
18#include "llvm/MC/MCValue.h"
19#include "llvm/Support/ErrorHandling.h"
20#include "llvm/Support/MachO.h"
21#include "llvm/Target/TargetAsmBackend.h"
22
23// FIXME: Gross.
24#include "../Target/X86/X86FixupKinds.h"
25
26#include <vector>
27using namespace llvm;
28
29static unsigned getFixupKindLog2Size(unsigned Kind) {
30 switch (Kind) {
31 default: llvm_unreachable("invalid fixup kind!");
32 case X86::reloc_pcrel_1byte:
33 case FK_Data_1: return 0;
34 case FK_Data_2: return 1;
35 case X86::reloc_pcrel_4byte:
36 case X86::reloc_riprel_4byte:
37 case FK_Data_4: return 2;
38 case FK_Data_8: return 3;
39 }
40}
41
42static bool isFixupKindPCRel(unsigned Kind) {
43 switch (Kind) {
44 default:
45 return false;
46 case X86::reloc_pcrel_1byte:
47 case X86::reloc_pcrel_4byte:
48 case X86::reloc_riprel_4byte:
49 return true;
50 }
51}
52
53namespace {
54
55class MachObjectWriterImpl {
56 // See <mach-o/loader.h>.
57 enum {
58 Header_Magic32 = 0xFEEDFACE,
59 Header_Magic64 = 0xFEEDFACF
60 };
61
62 enum {
63 Header32Size = 28,
64 Header64Size = 32,
65 SegmentLoadCommand32Size = 56,
66 SegmentLoadCommand64Size = 72,
67 Section32Size = 68,
68 Section64Size = 80,
69 SymtabLoadCommandSize = 24,
70 DysymtabLoadCommandSize = 80,
71 Nlist32Size = 12,
72 Nlist64Size = 16,
73 RelocationInfoSize = 8
74 };
75
76 enum HeaderFileType {
77 HFT_Object = 0x1
78 };
79
80 enum HeaderFlags {
81 HF_SubsectionsViaSymbols = 0x2000
82 };
83
84 enum LoadCommandType {
85 LCT_Segment = 0x1,
86 LCT_Symtab = 0x2,
87 LCT_Dysymtab = 0xb,
88 LCT_Segment64 = 0x19
89 };
90
91 // See <mach-o/nlist.h>.
92 enum SymbolTypeType {
93 STT_Undefined = 0x00,
94 STT_Absolute = 0x02,
95 STT_Section = 0x0e
96 };
97
98 enum SymbolTypeFlags {
99 // If any of these bits are set, then the entry is a stab entry number (see
100 // <mach-o/stab.h>. Otherwise the other masks apply.
101 STF_StabsEntryMask = 0xe0,
102
103 STF_TypeMask = 0x0e,
104 STF_External = 0x01,
105 STF_PrivateExtern = 0x10
106 };
107
108 /// IndirectSymbolFlags - Flags for encoding special values in the indirect
109 /// symbol entry.
110 enum IndirectSymbolFlags {
111 ISF_Local = 0x80000000,
112 ISF_Absolute = 0x40000000
113 };
114
115 /// RelocationFlags - Special flags for addresses.
116 enum RelocationFlags {
117 RF_Scattered = 0x80000000
118 };
119
120 enum RelocationInfoType {
121 RIT_Vanilla = 0,
122 RIT_Pair = 1,
123 RIT_Difference = 2,
124 RIT_PreboundLazyPointer = 3,
125 RIT_LocalDifference = 4
126 };
127
128 /// MachSymbolData - Helper struct for containing some precomputed information
129 /// on symbols.
130 struct MachSymbolData {
131 MCSymbolData *SymbolData;
132 uint64_t StringIndex;
133 uint8_t SectionIndex;
134
135 // Support lexicographic sorting.
136 bool operator<(const MachSymbolData &RHS) const {
137 const std::string &Name = SymbolData->getSymbol().getName();
138 return Name < RHS.SymbolData->getSymbol().getName();
139 }
140 };
141
142 /// @name Relocation Data
143 /// @{
144
145 struct MachRelocationEntry {
146 uint32_t Word0;
147 uint32_t Word1;
148 };
149
150 llvm::DenseMap<const MCSectionData*,
151 std::vector<MachRelocationEntry> > Relocations;
152
153 /// @}
154 /// @name Symbol Table Data
155 /// @{
156
157 SmallString<256> StringTable;
158 std::vector<MachSymbolData> LocalSymbolData;
159 std::vector<MachSymbolData> ExternalSymbolData;
160 std::vector<MachSymbolData> UndefinedSymbolData;
161
162 /// @}
163
164 MachObjectWriter *Writer;
165
166 raw_ostream &OS;
167
168 unsigned Is64Bit : 1;
169
170public:
171 MachObjectWriterImpl(MachObjectWriter *_Writer, bool _Is64Bit)
172 : Writer(_Writer), OS(Writer->getStream()), Is64Bit(_Is64Bit) {
173 }
174
175 void Write8(uint8_t Value) { Writer->Write8(Value); }
176 void Write16(uint16_t Value) { Writer->Write16(Value); }
177 void Write32(uint32_t Value) { Writer->Write32(Value); }
178 void Write64(uint64_t Value) { Writer->Write64(Value); }
179 void WriteZeros(unsigned N) { Writer->WriteZeros(N); }
180 void WriteBytes(StringRef Str, unsigned ZeroFillSize = 0) {
181 Writer->WriteBytes(Str, ZeroFillSize);
182 }
183
184 void WriteHeader(unsigned NumLoadCommands, unsigned LoadCommandsSize,
185 bool SubsectionsViaSymbols) {
186 uint32_t Flags = 0;
187
188 if (SubsectionsViaSymbols)
189 Flags |= HF_SubsectionsViaSymbols;
190
191 // struct mach_header (28 bytes) or
192 // struct mach_header_64 (32 bytes)
193
194 uint64_t Start = OS.tell();
195 (void) Start;
196
197 Write32(Is64Bit ? Header_Magic64 : Header_Magic32);
198
199 // FIXME: Support cputype.
200 Write32(Is64Bit ? MachO::CPUTypeX86_64 : MachO::CPUTypeI386);
201 // FIXME: Support cpusubtype.
202 Write32(MachO::CPUSubType_I386_ALL);
203 Write32(HFT_Object);
204 Write32(NumLoadCommands); // Object files have a single load command, the
205 // segment.
206 Write32(LoadCommandsSize);
207 Write32(Flags);
208 if (Is64Bit)
209 Write32(0); // reserved
210
211 assert(OS.tell() - Start == Is64Bit ? Header64Size : Header32Size);
212 }
213
214 /// WriteSegmentLoadCommand - Write a segment load command.
215 ///
216 /// \arg NumSections - The number of sections in this segment.
217 /// \arg SectionDataSize - The total size of the sections.
218 void WriteSegmentLoadCommand(unsigned NumSections,
219 uint64_t VMSize,
220 uint64_t SectionDataStartOffset,
221 uint64_t SectionDataSize) {
222 // struct segment_command (56 bytes) or
223 // struct segment_command_64 (72 bytes)
224
225 uint64_t Start = OS.tell();
226 (void) Start;
227
228 unsigned SegmentLoadCommandSize = Is64Bit ? SegmentLoadCommand64Size :
229 SegmentLoadCommand32Size;
230 Write32(Is64Bit ? LCT_Segment64 : LCT_Segment);
231 Write32(SegmentLoadCommandSize +
232 NumSections * (Is64Bit ? Section64Size : Section32Size));
233
234 WriteBytes("", 16);
235 if (Is64Bit) {
236 Write64(0); // vmaddr
237 Write64(VMSize); // vmsize
238 Write64(SectionDataStartOffset); // file offset
239 Write64(SectionDataSize); // file size
240 } else {
241 Write32(0); // vmaddr
242 Write32(VMSize); // vmsize
243 Write32(SectionDataStartOffset); // file offset
244 Write32(SectionDataSize); // file size
245 }
246 Write32(0x7); // maxprot
247 Write32(0x7); // initprot
248 Write32(NumSections);
249 Write32(0); // flags
250
251 assert(OS.tell() - Start == SegmentLoadCommandSize);
252 }
253
254 void WriteSection(const MCAssembler &Asm, const MCSectionData &SD,
255 uint64_t FileOffset, uint64_t RelocationsStart,
256 unsigned NumRelocations) {
257 // The offset is unused for virtual sections.
258 if (Asm.getBackend().isVirtualSection(SD.getSection())) {
259 assert(SD.getFileSize() == 0 && "Invalid file size!");
260 FileOffset = 0;
261 }
262
263 // struct section (68 bytes) or
264 // struct section_64 (80 bytes)
265
266 uint64_t Start = OS.tell();
267 (void) Start;
268
269 // FIXME: cast<> support!
270 const MCSectionMachO &Section =
271 static_cast<const MCSectionMachO&>(SD.getSection());
272 WriteBytes(Section.getSectionName(), 16);
273 WriteBytes(Section.getSegmentName(), 16);
274 if (Is64Bit) {
275 Write64(SD.getAddress()); // address
276 Write64(SD.getSize()); // size
277 } else {
278 Write32(SD.getAddress()); // address
279 Write32(SD.getSize()); // size
280 }
281 Write32(FileOffset);
282
283 unsigned Flags = Section.getTypeAndAttributes();
284 if (SD.hasInstructions())
285 Flags |= MCSectionMachO::S_ATTR_SOME_INSTRUCTIONS;
286
287 assert(isPowerOf2_32(SD.getAlignment()) && "Invalid alignment!");
288 Write32(Log2_32(SD.getAlignment()));
289 Write32(NumRelocations ? RelocationsStart : 0);
290 Write32(NumRelocations);
291 Write32(Flags);
292 Write32(0); // reserved1
293 Write32(Section.getStubSize()); // reserved2
294 if (Is64Bit)
295 Write32(0); // reserved3
296
297 assert(OS.tell() - Start == Is64Bit ? Section64Size : Section32Size);
298 }
299
300 void WriteSymtabLoadCommand(uint32_t SymbolOffset, uint32_t NumSymbols,
301 uint32_t StringTableOffset,
302 uint32_t StringTableSize) {
303 // struct symtab_command (24 bytes)
304
305 uint64_t Start = OS.tell();
306 (void) Start;
307
308 Write32(LCT_Symtab);
309 Write32(SymtabLoadCommandSize);
310 Write32(SymbolOffset);
311 Write32(NumSymbols);
312 Write32(StringTableOffset);
313 Write32(StringTableSize);
314
315 assert(OS.tell() - Start == SymtabLoadCommandSize);
316 }
317
318 void WriteDysymtabLoadCommand(uint32_t FirstLocalSymbol,
319 uint32_t NumLocalSymbols,
320 uint32_t FirstExternalSymbol,
321 uint32_t NumExternalSymbols,
322 uint32_t FirstUndefinedSymbol,
323 uint32_t NumUndefinedSymbols,
324 uint32_t IndirectSymbolOffset,
325 uint32_t NumIndirectSymbols) {
326 // struct dysymtab_command (80 bytes)
327
328 uint64_t Start = OS.tell();
329 (void) Start;
330
331 Write32(LCT_Dysymtab);
332 Write32(DysymtabLoadCommandSize);
333 Write32(FirstLocalSymbol);
334 Write32(NumLocalSymbols);
335 Write32(FirstExternalSymbol);
336 Write32(NumExternalSymbols);
337 Write32(FirstUndefinedSymbol);
338 Write32(NumUndefinedSymbols);
339 Write32(0); // tocoff
340 Write32(0); // ntoc
341 Write32(0); // modtaboff
342 Write32(0); // nmodtab
343 Write32(0); // extrefsymoff
344 Write32(0); // nextrefsyms
345 Write32(IndirectSymbolOffset);
346 Write32(NumIndirectSymbols);
347 Write32(0); // extreloff
348 Write32(0); // nextrel
349 Write32(0); // locreloff
350 Write32(0); // nlocrel
351
352 assert(OS.tell() - Start == DysymtabLoadCommandSize);
353 }
354
355 void WriteNlist(MachSymbolData &MSD) {
356 MCSymbolData &Data = *MSD.SymbolData;
357 const MCSymbol &Symbol = Data.getSymbol();
358 uint8_t Type = 0;
359 uint16_t Flags = Data.getFlags();
360 uint32_t Address = 0;
361
362 // Set the N_TYPE bits. See <mach-o/nlist.h>.
363 //
364 // FIXME: Are the prebound or indirect fields possible here?
365 if (Symbol.isUndefined())
366 Type = STT_Undefined;
367 else if (Symbol.isAbsolute())
368 Type = STT_Absolute;
369 else
370 Type = STT_Section;
371
372 // FIXME: Set STAB bits.
373
374 if (Data.isPrivateExtern())
375 Type |= STF_PrivateExtern;
376
377 // Set external bit.
378 if (Data.isExternal() || Symbol.isUndefined())
379 Type |= STF_External;
380
381 // Compute the symbol address.
382 if (Symbol.isDefined()) {
383 if (Symbol.isAbsolute()) {
384 llvm_unreachable("FIXME: Not yet implemented!");
385 } else {
386 Address = Data.getAddress();
387 }
388 } else if (Data.isCommon()) {
389 // Common symbols are encoded with the size in the address
390 // field, and their alignment in the flags.
391 Address = Data.getCommonSize();
392
393 // Common alignment is packed into the 'desc' bits.
394 if (unsigned Align = Data.getCommonAlignment()) {
395 unsigned Log2Size = Log2_32(Align);
396 assert((1U << Log2Size) == Align && "Invalid 'common' alignment!");
397 if (Log2Size > 15)
398 llvm_report_error("invalid 'common' alignment '" +
399 Twine(Align) + "'");
400 // FIXME: Keep this mask with the SymbolFlags enumeration.
401 Flags = (Flags & 0xF0FF) | (Log2Size << 8);
402 }
403 }
404
405 // struct nlist (12 bytes)
406
407 Write32(MSD.StringIndex);
408 Write8(Type);
409 Write8(MSD.SectionIndex);
410
411 // The Mach-O streamer uses the lowest 16-bits of the flags for the 'desc'
412 // value.
413 Write16(Flags);
414 if (Is64Bit)
415 Write64(Address);
416 else
417 Write32(Address);
418 }
419
420 void RecordScatteredRelocation(const MCAssembler &Asm,
421 const MCFragment &Fragment,
422 const MCAsmFixup &Fixup, MCValue Target,
423 uint64_t &FixedValue) {
424 uint32_t Address = Fragment.getOffset() + Fixup.Offset;
425 unsigned IsPCRel = isFixupKindPCRel(Fixup.Kind);
426 unsigned Log2Size = getFixupKindLog2Size(Fixup.Kind);
427 unsigned Type = RIT_Vanilla;
428
429 // See <reloc.h>.
430 const MCSymbol *A = &Target.getSymA()->getSymbol();
431 MCSymbolData *A_SD = &Asm.getSymbolData(*A);
432
433 if (!A_SD->getFragment())
434 llvm_report_error("symbol '" + A->getName() +
435 "' can not be undefined in a subtraction expression");
436
437 uint32_t Value = A_SD->getAddress();
438 uint32_t Value2 = 0;
439
440 if (const MCSymbolRefExpr *B = Target.getSymB()) {
441 MCSymbolData *B_SD = &Asm.getSymbolData(B->getSymbol());
442
443 if (!B_SD->getFragment())
444 llvm_report_error("symbol '" + B->getSymbol().getName() +
445 "' can not be undefined in a subtraction expression");
446
447 // Select the appropriate difference relocation type.
448 //
449 // Note that there is no longer any semantic difference between these two
450 // relocation types from the linkers point of view, this is done solely
451 // for pedantic compatibility with 'as'.
452 Type = A_SD->isExternal() ? RIT_Difference : RIT_LocalDifference;
453 Value2 = B_SD->getAddress();
454 }
455
456 // Relocations are written out in reverse order, so the PAIR comes first.
457 if (Type == RIT_Difference || Type == RIT_LocalDifference) {
458 MachRelocationEntry MRE;
459 MRE.Word0 = ((0 << 0) |
460 (RIT_Pair << 24) |
461 (Log2Size << 28) |
462 (IsPCRel << 30) |
463 RF_Scattered);
464 MRE.Word1 = Value2;
465 Relocations[Fragment.getParent()].push_back(MRE);
466 }
467
468 MachRelocationEntry MRE;
469 MRE.Word0 = ((Address << 0) |
470 (Type << 24) |
471 (Log2Size << 28) |
472 (IsPCRel << 30) |
473 RF_Scattered);
474 MRE.Word1 = Value;
475 Relocations[Fragment.getParent()].push_back(MRE);
476 }
477
478 virtual void RecordRelocation(const MCAssembler &Asm,
479 const MCDataFragment &Fragment,
480 const MCAsmFixup &Fixup, MCValue Target,
481 uint64_t &FixedValue) {
482 unsigned IsPCRel = isFixupKindPCRel(Fixup.Kind);
483 unsigned Log2Size = getFixupKindLog2Size(Fixup.Kind);
484
485 // If this is a difference or a defined symbol plus an offset, then we need
486 // a scattered relocation entry.
487 uint32_t Offset = Target.getConstant();
488 if (IsPCRel)
489 Offset += 1 << Log2Size;
490 if (Target.getSymB() ||
491 (Target.getSymA() && !Target.getSymA()->getSymbol().isUndefined() &&
492 Offset)) {
493 RecordScatteredRelocation(Asm, Fragment, Fixup, Target, FixedValue);
494 return;
495 }
496
497 // See <reloc.h>.
498 uint32_t Address = Fragment.getOffset() + Fixup.Offset;
499 uint32_t Value = 0;
500 unsigned Index = 0;
501 unsigned IsExtern = 0;
502 unsigned Type = 0;
503
504 if (Target.isAbsolute()) { // constant
505 // SymbolNum of 0 indicates the absolute section.
506 //
507 // FIXME: Currently, these are never generated (see code below). I cannot
508 // find a case where they are actually emitted.
509 Type = RIT_Vanilla;
510 Value = 0;
511 } else {
512 const MCSymbol *Symbol = &Target.getSymA()->getSymbol();
513 MCSymbolData *SD = &Asm.getSymbolData(*Symbol);
514
515 if (Symbol->isUndefined()) {
516 IsExtern = 1;
517 Index = SD->getIndex();
518 Value = 0;
519 } else {
520 // The index is the section ordinal.
521 //
522 // FIXME: O(N)
523 Index = 1;
524 MCAssembler::const_iterator it = Asm.begin(), ie = Asm.end();
525 for (; it != ie; ++it, ++Index)
526 if (&*it == SD->getFragment()->getParent())
527 break;
528 assert(it != ie && "Unable to find section index!");
529 Value = SD->getAddress();
530 }
531
532 Type = RIT_Vanilla;
533 }
534
535 // struct relocation_info (8 bytes)
536 MachRelocationEntry MRE;
537 MRE.Word0 = Address;
538 MRE.Word1 = ((Index << 0) |
539 (IsPCRel << 24) |
540 (Log2Size << 25) |
541 (IsExtern << 27) |
542 (Type << 28));
543 Relocations[Fragment.getParent()].push_back(MRE);
544 }
545
546 void BindIndirectSymbols(MCAssembler &Asm) {
547 // This is the point where 'as' creates actual symbols for indirect symbols
548 // (in the following two passes). It would be easier for us to do this
549 // sooner when we see the attribute, but that makes getting the order in the
550 // symbol table much more complicated than it is worth.
551 //
552 // FIXME: Revisit this when the dust settles.
553
554 // Bind non lazy symbol pointers first.
555 for (MCAssembler::indirect_symbol_iterator it = Asm.indirect_symbol_begin(),
556 ie = Asm.indirect_symbol_end(); it != ie; ++it) {
557 // FIXME: cast<> support!
558 const MCSectionMachO &Section =
559 static_cast<const MCSectionMachO&>(it->SectionData->getSection());
560
561 if (Section.getType() != MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS)
562 continue;
563
564 Asm.getOrCreateSymbolData(*it->Symbol);
565 }
566
567 // Then lazy symbol pointers and symbol stubs.
568 for (MCAssembler::indirect_symbol_iterator it = Asm.indirect_symbol_begin(),
569 ie = Asm.indirect_symbol_end(); it != ie; ++it) {
570 // FIXME: cast<> support!
571 const MCSectionMachO &Section =
572 static_cast<const MCSectionMachO&>(it->SectionData->getSection());
573
574 if (Section.getType() != MCSectionMachO::S_LAZY_SYMBOL_POINTERS &&
575 Section.getType() != MCSectionMachO::S_SYMBOL_STUBS)
576 continue;
577
578 // Set the symbol type to undefined lazy, but only on construction.
579 //
580 // FIXME: Do not hardcode.
581 bool Created;
582 MCSymbolData &Entry = Asm.getOrCreateSymbolData(*it->Symbol, &Created);
583 if (Created)
584 Entry.setFlags(Entry.getFlags() | 0x0001);
585 }
586 }
587
588 /// ComputeSymbolTable - Compute the symbol table data
589 ///
590 /// \param StringTable [out] - The string table data.
591 /// \param StringIndexMap [out] - Map from symbol names to offsets in the
592 /// string table.
593 void ComputeSymbolTable(MCAssembler &Asm, SmallString<256> &StringTable,
594 std::vector<MachSymbolData> &LocalSymbolData,
595 std::vector<MachSymbolData> &ExternalSymbolData,
596 std::vector<MachSymbolData> &UndefinedSymbolData) {
597 // Build section lookup table.
598 DenseMap<const MCSection*, uint8_t> SectionIndexMap;
599 unsigned Index = 1;
600 for (MCAssembler::iterator it = Asm.begin(),
601 ie = Asm.end(); it != ie; ++it, ++Index)
602 SectionIndexMap[&it->getSection()] = Index;
603 assert(Index <= 256 && "Too many sections!");
604
605 // Index 0 is always the empty string.
606 StringMap<uint64_t> StringIndexMap;
607 StringTable += '\x00';
608
609 // Build the symbol arrays and the string table, but only for non-local
610 // symbols.
611 //
612 // The particular order that we collect the symbols and create the string
613 // table, then sort the symbols is chosen to match 'as'. Even though it
614 // doesn't matter for correctness, this is important for letting us diff .o
615 // files.
616 for (MCAssembler::symbol_iterator it = Asm.symbol_begin(),
617 ie = Asm.symbol_end(); it != ie; ++it) {
618 const MCSymbol &Symbol = it->getSymbol();
619
620 // Ignore non-linker visible symbols.
621 if (!Asm.isSymbolLinkerVisible(it))
622 continue;
623
624 if (!it->isExternal() && !Symbol.isUndefined())
625 continue;
626
627 uint64_t &Entry = StringIndexMap[Symbol.getName()];
628 if (!Entry) {
629 Entry = StringTable.size();
630 StringTable += Symbol.getName();
631 StringTable += '\x00';
632 }
633
634 MachSymbolData MSD;
635 MSD.SymbolData = it;
636 MSD.StringIndex = Entry;
637
638 if (Symbol.isUndefined()) {
639 MSD.SectionIndex = 0;
640 UndefinedSymbolData.push_back(MSD);
641 } else if (Symbol.isAbsolute()) {
642 MSD.SectionIndex = 0;
643 ExternalSymbolData.push_back(MSD);
644 } else {
645 MSD.SectionIndex = SectionIndexMap.lookup(&Symbol.getSection());
646 assert(MSD.SectionIndex && "Invalid section index!");
647 ExternalSymbolData.push_back(MSD);
648 }
649 }
650
651 // Now add the data for local symbols.
652 for (MCAssembler::symbol_iterator it = Asm.symbol_begin(),
653 ie = Asm.symbol_end(); it != ie; ++it) {
654 const MCSymbol &Symbol = it->getSymbol();
655
656 // Ignore non-linker visible symbols.
657 if (!Asm.isSymbolLinkerVisible(it))
658 continue;
659
660 if (it->isExternal() || Symbol.isUndefined())
661 continue;
662
663 uint64_t &Entry = StringIndexMap[Symbol.getName()];
664 if (!Entry) {
665 Entry = StringTable.size();
666 StringTable += Symbol.getName();
667 StringTable += '\x00';
668 }
669
670 MachSymbolData MSD;
671 MSD.SymbolData = it;
672 MSD.StringIndex = Entry;
673
674 if (Symbol.isAbsolute()) {
675 MSD.SectionIndex = 0;
676 LocalSymbolData.push_back(MSD);
677 } else {
678 MSD.SectionIndex = SectionIndexMap.lookup(&Symbol.getSection());
679 assert(MSD.SectionIndex && "Invalid section index!");
680 LocalSymbolData.push_back(MSD);
681 }
682 }
683
684 // External and undefined symbols are required to be in lexicographic order.
685 std::sort(ExternalSymbolData.begin(), ExternalSymbolData.end());
686 std::sort(UndefinedSymbolData.begin(), UndefinedSymbolData.end());
687
688 // Set the symbol indices.
689 Index = 0;
690 for (unsigned i = 0, e = LocalSymbolData.size(); i != e; ++i)
691 LocalSymbolData[i].SymbolData->setIndex(Index++);
692 for (unsigned i = 0, e = ExternalSymbolData.size(); i != e; ++i)
693 ExternalSymbolData[i].SymbolData->setIndex(Index++);
694 for (unsigned i = 0, e = UndefinedSymbolData.size(); i != e; ++i)
695 UndefinedSymbolData[i].SymbolData->setIndex(Index++);
696
697 // The string table is padded to a multiple of 4.
698 while (StringTable.size() % 4)
699 StringTable += '\x00';
700 }
701
702 virtual void ExecutePostLayoutBinding(MCAssembler &Asm) {
703 // Create symbol data for any indirect symbols.
704 BindIndirectSymbols(Asm);
705
706 // Compute symbol table information and bind symbol indices.
707 ComputeSymbolTable(Asm, StringTable, LocalSymbolData, ExternalSymbolData,
708 UndefinedSymbolData);
709 }
710
711 virtual void WriteObject(const MCAssembler &Asm) {
712 unsigned NumSections = Asm.size();
713
714 // The section data starts after the header, the segment load command (and
715 // section headers) and the symbol table.
716 unsigned NumLoadCommands = 1;
717 uint64_t LoadCommandsSize = Is64Bit ?
718 SegmentLoadCommand64Size + NumSections * Section64Size :
719 SegmentLoadCommand32Size + NumSections * Section32Size;
720
721 // Add the symbol table load command sizes, if used.
722 unsigned NumSymbols = LocalSymbolData.size() + ExternalSymbolData.size() +
723 UndefinedSymbolData.size();
724 if (NumSymbols) {
725 NumLoadCommands += 2;
726 LoadCommandsSize += SymtabLoadCommandSize + DysymtabLoadCommandSize;
727 }
728
729 // Compute the total size of the section data, as well as its file size and
730 // vm size.
731 uint64_t SectionDataStart = (Is64Bit ? Header64Size : Header32Size)
732 + LoadCommandsSize;
733 uint64_t SectionDataSize = 0;
734 uint64_t SectionDataFileSize = 0;
735 uint64_t VMSize = 0;
736 for (MCAssembler::const_iterator it = Asm.begin(),
737 ie = Asm.end(); it != ie; ++it) {
738 const MCSectionData &SD = *it;
739
740 VMSize = std::max(VMSize, SD.getAddress() + SD.getSize());
741
742 if (Asm.getBackend().isVirtualSection(SD.getSection()))
743 continue;
744
745 SectionDataSize = std::max(SectionDataSize,
746 SD.getAddress() + SD.getSize());
747 SectionDataFileSize = std::max(SectionDataFileSize,
748 SD.getAddress() + SD.getFileSize());
749 }
750
751 // The section data is padded to 4 bytes.
752 //
753 // FIXME: Is this machine dependent?
754 unsigned SectionDataPadding = OffsetToAlignment(SectionDataFileSize, 4);
755 SectionDataFileSize += SectionDataPadding;
756
757 // Write the prolog, starting with the header and load command...
758 WriteHeader(NumLoadCommands, LoadCommandsSize,
759 Asm.getSubsectionsViaSymbols());
760 WriteSegmentLoadCommand(NumSections, VMSize,
761 SectionDataStart, SectionDataSize);
762
763 // ... and then the section headers.
764 uint64_t RelocTableEnd = SectionDataStart + SectionDataFileSize;
765 for (MCAssembler::const_iterator it = Asm.begin(),
766 ie = Asm.end(); it != ie; ++it) {
767 std::vector<MachRelocationEntry> &Relocs = Relocations[it];
768 unsigned NumRelocs = Relocs.size();
769 uint64_t SectionStart = SectionDataStart + it->getAddress();
770 WriteSection(Asm, *it, SectionStart, RelocTableEnd, NumRelocs);
771 RelocTableEnd += NumRelocs * RelocationInfoSize;
772 }
773
774 // Write the symbol table load command, if used.
775 if (NumSymbols) {
776 unsigned FirstLocalSymbol = 0;
777 unsigned NumLocalSymbols = LocalSymbolData.size();
778 unsigned FirstExternalSymbol = FirstLocalSymbol + NumLocalSymbols;
779 unsigned NumExternalSymbols = ExternalSymbolData.size();
780 unsigned FirstUndefinedSymbol = FirstExternalSymbol + NumExternalSymbols;
781 unsigned NumUndefinedSymbols = UndefinedSymbolData.size();
782 unsigned NumIndirectSymbols = Asm.indirect_symbol_size();
783 unsigned NumSymTabSymbols =
784 NumLocalSymbols + NumExternalSymbols + NumUndefinedSymbols;
785 uint64_t IndirectSymbolSize = NumIndirectSymbols * 4;
786 uint64_t IndirectSymbolOffset = 0;
787
788 // If used, the indirect symbols are written after the section data.
789 if (NumIndirectSymbols)
790 IndirectSymbolOffset = RelocTableEnd;
791
792 // The symbol table is written after the indirect symbol data.
793 uint64_t SymbolTableOffset = RelocTableEnd + IndirectSymbolSize;
794
795 // The string table is written after symbol table.
796 uint64_t StringTableOffset =
797 SymbolTableOffset + NumSymTabSymbols * (Is64Bit ? Nlist64Size :
798 Nlist32Size);
799 WriteSymtabLoadCommand(SymbolTableOffset, NumSymTabSymbols,
800 StringTableOffset, StringTable.size());
801
802 WriteDysymtabLoadCommand(FirstLocalSymbol, NumLocalSymbols,
803 FirstExternalSymbol, NumExternalSymbols,
804 FirstUndefinedSymbol, NumUndefinedSymbols,
805 IndirectSymbolOffset, NumIndirectSymbols);
806 }
807
808 // Write the actual section data.
809 for (MCAssembler::const_iterator it = Asm.begin(),
810 ie = Asm.end(); it != ie; ++it)
811 Asm.WriteSectionData(it, Writer);
812
813 // Write the extra padding.
814 WriteZeros(SectionDataPadding);
815
816 // Write the relocation entries.
817 for (MCAssembler::const_iterator it = Asm.begin(),
818 ie = Asm.end(); it != ie; ++it) {
819 // Write the section relocation entries, in reverse order to match 'as'
820 // (approximately, the exact algorithm is more complicated than this).
821 std::vector<MachRelocationEntry> &Relocs = Relocations[it];
822 for (unsigned i = 0, e = Relocs.size(); i != e; ++i) {
823 Write32(Relocs[e - i - 1].Word0);
824 Write32(Relocs[e - i - 1].Word1);
825 }
826 }
827
828 // Write the symbol table data, if used.
829 if (NumSymbols) {
830 // Write the indirect symbol entries.
831 for (MCAssembler::const_indirect_symbol_iterator
832 it = Asm.indirect_symbol_begin(),
833 ie = Asm.indirect_symbol_end(); it != ie; ++it) {
834 // Indirect symbols in the non lazy symbol pointer section have some
835 // special handling.
836 const MCSectionMachO &Section =
837 static_cast<const MCSectionMachO&>(it->SectionData->getSection());
838 if (Section.getType() == MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS) {
839 // If this symbol is defined and internal, mark it as such.
840 if (it->Symbol->isDefined() &&
841 !Asm.getSymbolData(*it->Symbol).isExternal()) {
842 uint32_t Flags = ISF_Local;
843 if (it->Symbol->isAbsolute())
844 Flags |= ISF_Absolute;
845 Write32(Flags);
846 continue;
847 }
848 }
849
850 Write32(Asm.getSymbolData(*it->Symbol).getIndex());
851 }
852
853 // FIXME: Check that offsets match computed ones.
854
855 // Write the symbol table entries.
856 for (unsigned i = 0, e = LocalSymbolData.size(); i != e; ++i)
857 WriteNlist(LocalSymbolData[i]);
858 for (unsigned i = 0, e = ExternalSymbolData.size(); i != e; ++i)
859 WriteNlist(ExternalSymbolData[i]);
860 for (unsigned i = 0, e = UndefinedSymbolData.size(); i != e; ++i)
861 WriteNlist(UndefinedSymbolData[i]);
862
863 // Write the string table.
864 OS << StringTable.str();
865 }
866 }
867};
868
869}
870
871MachObjectWriter::MachObjectWriter(raw_ostream &OS,
872 bool Is64Bit,
873 bool IsLittleEndian)
874 : MCObjectWriter(OS, IsLittleEndian)
875{
876 Impl = new MachObjectWriterImpl(this, Is64Bit);
877}
878
879MachObjectWriter::~MachObjectWriter() {
880 delete (MachObjectWriterImpl*) Impl;
881}
882
883void MachObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm) {
884 ((MachObjectWriterImpl*) Impl)->ExecutePostLayoutBinding(Asm);
885}
886
887void MachObjectWriter::RecordRelocation(const MCAssembler &Asm,
888 const MCDataFragment &Fragment,
889 const MCAsmFixup &Fixup, MCValue Target,
890 uint64_t &FixedValue) {
891 ((MachObjectWriterImpl*) Impl)->RecordRelocation(Asm, Fragment, Fixup,
892 Target, FixedValue);
893}
894
895void MachObjectWriter::WriteObject(const MCAssembler &Asm) {
896 ((MachObjectWriterImpl*) Impl)->WriteObject(Asm);
897}