1 //===- lib/MC/MachObjectWriter.cpp - Mach-O File Writer -------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "llvm/MC/MCMachObjectWriter.h"
11 #include "llvm/ADT/OwningPtr.h"
12 #include "llvm/ADT/StringMap.h"
13 #include "llvm/ADT/Twine.h"
14 #include "llvm/MC/MCAssembler.h"
15 #include "llvm/MC/MCAsmLayout.h"
16 #include "llvm/MC/MCExpr.h"
17 #include "llvm/MC/MCObjectWriter.h"
18 #include "llvm/MC/MCSectionMachO.h"
19 #include "llvm/MC/MCSymbol.h"
20 #include "llvm/MC/MCMachOSymbolFlags.h"
21 #include "llvm/MC/MCValue.h"
22 #include "llvm/Object/MachOFormat.h"
23 #include "llvm/Support/ErrorHandling.h"
24 #include "llvm/Target/TargetAsmBackend.h"
28 using namespace llvm::object
;
30 bool MachObjectWriter::
31 doesSymbolRequireExternRelocation(const MCSymbolData
*SD
) {
32 // Undefined symbols are always extern.
33 if (SD
->Symbol
->isUndefined())
36 // References to weak definitions require external relocation entries; the
37 // definition may not always be the one in the same object file.
38 if (SD
->getFlags() & SF_WeakDefinition
)
41 // Otherwise, we can use an internal relocation.
45 bool MachObjectWriter::
46 MachSymbolData::operator<(const MachSymbolData
&RHS
) const {
47 return SymbolData
->getSymbol().getName() <
48 RHS
.SymbolData
->getSymbol().getName();
51 bool MachObjectWriter::isFixupKindPCRel(const MCAssembler
&Asm
, unsigned Kind
) {
52 const MCFixupKindInfo
&FKI
= Asm
.getBackend().getFixupKindInfo(
55 return FKI
.Flags
& MCFixupKindInfo::FKF_IsPCRel
;
58 uint64_t MachObjectWriter::getFragmentAddress(const MCFragment
*Fragment
,
59 const MCAsmLayout
&Layout
) const {
60 return getSectionAddress(Fragment
->getParent()) +
61 Layout
.getFragmentOffset(Fragment
);
64 uint64_t MachObjectWriter::getSymbolAddress(const MCSymbolData
* SD
,
65 const MCAsmLayout
&Layout
) const {
66 const MCSymbol
&S
= SD
->getSymbol();
68 // If this is a variable, then recursively evaluate now.
71 if (!S
.getVariableValue()->EvaluateAsRelocatable(Target
, Layout
))
72 report_fatal_error("unable to evaluate offset for variable '" +
75 // Verify that any used symbols are defined.
76 if (Target
.getSymA() && Target
.getSymA()->getSymbol().isUndefined())
77 report_fatal_error("unable to evaluate offset to undefined symbol '" +
78 Target
.getSymA()->getSymbol().getName() + "'");
79 if (Target
.getSymB() && Target
.getSymB()->getSymbol().isUndefined())
80 report_fatal_error("unable to evaluate offset to undefined symbol '" +
81 Target
.getSymB()->getSymbol().getName() + "'");
83 uint64_t Address
= Target
.getConstant();
85 Address
+= getSymbolAddress(&Layout
.getAssembler().getSymbolData(
86 Target
.getSymA()->getSymbol()), Layout
);
88 Address
+= getSymbolAddress(&Layout
.getAssembler().getSymbolData(
89 Target
.getSymB()->getSymbol()), Layout
);
93 return getSectionAddress(SD
->getFragment()->getParent()) +
94 Layout
.getSymbolOffset(SD
);
97 uint64_t MachObjectWriter::getPaddingSize(const MCSectionData
*SD
,
98 const MCAsmLayout
&Layout
) const {
99 uint64_t EndAddr
= getSectionAddress(SD
) + Layout
.getSectionAddressSize(SD
);
100 unsigned Next
= SD
->getLayoutOrder() + 1;
101 if (Next
>= Layout
.getSectionOrder().size())
104 const MCSectionData
&NextSD
= *Layout
.getSectionOrder()[Next
];
105 if (NextSD
.getSection().isVirtualSection())
107 return OffsetToAlignment(EndAddr
, NextSD
.getAlignment());
110 void MachObjectWriter::WriteHeader(unsigned NumLoadCommands
,
111 unsigned LoadCommandsSize
,
112 bool SubsectionsViaSymbols
) {
115 if (SubsectionsViaSymbols
)
116 Flags
|= macho::HF_SubsectionsViaSymbols
;
118 // struct mach_header (28 bytes) or
119 // struct mach_header_64 (32 bytes)
121 uint64_t Start
= OS
.tell();
124 Write32(is64Bit() ? macho::HM_Object64
: macho::HM_Object32
);
126 Write32(TargetObjectWriter
->getCPUType());
127 Write32(TargetObjectWriter
->getCPUSubtype());
129 Write32(macho::HFT_Object
);
130 Write32(NumLoadCommands
);
131 Write32(LoadCommandsSize
);
134 Write32(0); // reserved
136 assert(OS
.tell() - Start
==
137 (is64Bit() ? macho::Header64Size
: macho::Header32Size
));
140 /// WriteSegmentLoadCommand - Write a segment load command.
142 /// \arg NumSections - The number of sections in this segment.
143 /// \arg SectionDataSize - The total size of the sections.
144 void MachObjectWriter::WriteSegmentLoadCommand(unsigned NumSections
,
146 uint64_t SectionDataStartOffset
,
147 uint64_t SectionDataSize
) {
148 // struct segment_command (56 bytes) or
149 // struct segment_command_64 (72 bytes)
151 uint64_t Start
= OS
.tell();
154 unsigned SegmentLoadCommandSize
=
155 is64Bit() ? macho::SegmentLoadCommand64Size
:
156 macho::SegmentLoadCommand32Size
;
157 Write32(is64Bit() ? macho::LCT_Segment64
: macho::LCT_Segment
);
158 Write32(SegmentLoadCommandSize
+
159 NumSections
* (is64Bit() ? macho::Section64Size
:
160 macho::Section32Size
));
164 Write64(0); // vmaddr
165 Write64(VMSize
); // vmsize
166 Write64(SectionDataStartOffset
); // file offset
167 Write64(SectionDataSize
); // file size
169 Write32(0); // vmaddr
170 Write32(VMSize
); // vmsize
171 Write32(SectionDataStartOffset
); // file offset
172 Write32(SectionDataSize
); // file size
174 Write32(0x7); // maxprot
175 Write32(0x7); // initprot
176 Write32(NumSections
);
179 assert(OS
.tell() - Start
== SegmentLoadCommandSize
);
182 void MachObjectWriter::WriteSection(const MCAssembler
&Asm
,
183 const MCAsmLayout
&Layout
,
184 const MCSectionData
&SD
,
186 uint64_t RelocationsStart
,
187 unsigned NumRelocations
) {
188 uint64_t SectionSize
= Layout
.getSectionAddressSize(&SD
);
190 // The offset is unused for virtual sections.
191 if (SD
.getSection().isVirtualSection()) {
192 assert(Layout
.getSectionFileSize(&SD
) == 0 && "Invalid file size!");
196 // struct section (68 bytes) or
197 // struct section_64 (80 bytes)
199 uint64_t Start
= OS
.tell();
202 const MCSectionMachO
&Section
= cast
<MCSectionMachO
>(SD
.getSection());
203 WriteBytes(Section
.getSectionName(), 16);
204 WriteBytes(Section
.getSegmentName(), 16);
206 Write64(getSectionAddress(&SD
)); // address
207 Write64(SectionSize
); // size
209 Write32(getSectionAddress(&SD
)); // address
210 Write32(SectionSize
); // size
214 unsigned Flags
= Section
.getTypeAndAttributes();
215 if (SD
.hasInstructions())
216 Flags
|= MCSectionMachO::S_ATTR_SOME_INSTRUCTIONS
;
218 assert(isPowerOf2_32(SD
.getAlignment()) && "Invalid alignment!");
219 Write32(Log2_32(SD
.getAlignment()));
220 Write32(NumRelocations
? RelocationsStart
: 0);
221 Write32(NumRelocations
);
223 Write32(IndirectSymBase
.lookup(&SD
)); // reserved1
224 Write32(Section
.getStubSize()); // reserved2
226 Write32(0); // reserved3
228 assert(OS
.tell() - Start
== (is64Bit() ? macho::Section64Size
:
229 macho::Section32Size
));
232 void MachObjectWriter::WriteSymtabLoadCommand(uint32_t SymbolOffset
,
234 uint32_t StringTableOffset
,
235 uint32_t StringTableSize
) {
236 // struct symtab_command (24 bytes)
238 uint64_t Start
= OS
.tell();
241 Write32(macho::LCT_Symtab
);
242 Write32(macho::SymtabLoadCommandSize
);
243 Write32(SymbolOffset
);
245 Write32(StringTableOffset
);
246 Write32(StringTableSize
);
248 assert(OS
.tell() - Start
== macho::SymtabLoadCommandSize
);
251 void MachObjectWriter::WriteDysymtabLoadCommand(uint32_t FirstLocalSymbol
,
252 uint32_t NumLocalSymbols
,
253 uint32_t FirstExternalSymbol
,
254 uint32_t NumExternalSymbols
,
255 uint32_t FirstUndefinedSymbol
,
256 uint32_t NumUndefinedSymbols
,
257 uint32_t IndirectSymbolOffset
,
258 uint32_t NumIndirectSymbols
) {
259 // struct dysymtab_command (80 bytes)
261 uint64_t Start
= OS
.tell();
264 Write32(macho::LCT_Dysymtab
);
265 Write32(macho::DysymtabLoadCommandSize
);
266 Write32(FirstLocalSymbol
);
267 Write32(NumLocalSymbols
);
268 Write32(FirstExternalSymbol
);
269 Write32(NumExternalSymbols
);
270 Write32(FirstUndefinedSymbol
);
271 Write32(NumUndefinedSymbols
);
272 Write32(0); // tocoff
274 Write32(0); // modtaboff
275 Write32(0); // nmodtab
276 Write32(0); // extrefsymoff
277 Write32(0); // nextrefsyms
278 Write32(IndirectSymbolOffset
);
279 Write32(NumIndirectSymbols
);
280 Write32(0); // extreloff
281 Write32(0); // nextrel
282 Write32(0); // locreloff
283 Write32(0); // nlocrel
285 assert(OS
.tell() - Start
== macho::DysymtabLoadCommandSize
);
288 void MachObjectWriter::WriteNlist(MachSymbolData
&MSD
,
289 const MCAsmLayout
&Layout
) {
290 MCSymbolData
&Data
= *MSD
.SymbolData
;
291 const MCSymbol
&Symbol
= Data
.getSymbol();
293 uint16_t Flags
= Data
.getFlags();
294 uint32_t Address
= 0;
296 // Set the N_TYPE bits. See <mach-o/nlist.h>.
298 // FIXME: Are the prebound or indirect fields possible here?
299 if (Symbol
.isUndefined())
300 Type
= macho::STT_Undefined
;
301 else if (Symbol
.isAbsolute())
302 Type
= macho::STT_Absolute
;
304 Type
= macho::STT_Section
;
306 // FIXME: Set STAB bits.
308 if (Data
.isPrivateExtern())
309 Type
|= macho::STF_PrivateExtern
;
312 if (Data
.isExternal() || Symbol
.isUndefined())
313 Type
|= macho::STF_External
;
315 // Compute the symbol address.
316 if (Symbol
.isDefined()) {
317 if (Symbol
.isAbsolute()) {
318 Address
= cast
<MCConstantExpr
>(Symbol
.getVariableValue())->getValue();
320 Address
= getSymbolAddress(&Data
, Layout
);
322 } else if (Data
.isCommon()) {
323 // Common symbols are encoded with the size in the address
324 // field, and their alignment in the flags.
325 Address
= Data
.getCommonSize();
327 // Common alignment is packed into the 'desc' bits.
328 if (unsigned Align
= Data
.getCommonAlignment()) {
329 unsigned Log2Size
= Log2_32(Align
);
330 assert((1U << Log2Size
) == Align
&& "Invalid 'common' alignment!");
332 report_fatal_error("invalid 'common' alignment '" +
334 // FIXME: Keep this mask with the SymbolFlags enumeration.
335 Flags
= (Flags
& 0xF0FF) | (Log2Size
<< 8);
339 // struct nlist (12 bytes)
341 Write32(MSD
.StringIndex
);
343 Write8(MSD
.SectionIndex
);
345 // The Mach-O streamer uses the lowest 16-bits of the flags for the 'desc'
354 void MachObjectWriter::RecordRelocation(const MCAssembler
&Asm
,
355 const MCAsmLayout
&Layout
,
356 const MCFragment
*Fragment
,
357 const MCFixup
&Fixup
,
359 uint64_t &FixedValue
) {
360 TargetObjectWriter
->RecordRelocation(this, Asm
, Layout
, Fragment
, Fixup
,
364 void MachObjectWriter::BindIndirectSymbols(MCAssembler
&Asm
) {
365 // This is the point where 'as' creates actual symbols for indirect symbols
366 // (in the following two passes). It would be easier for us to do this sooner
367 // when we see the attribute, but that makes getting the order in the symbol
368 // table much more complicated than it is worth.
370 // FIXME: Revisit this when the dust settles.
372 // Bind non lazy symbol pointers first.
373 unsigned IndirectIndex
= 0;
374 for (MCAssembler::indirect_symbol_iterator it
= Asm
.indirect_symbol_begin(),
375 ie
= Asm
.indirect_symbol_end(); it
!= ie
; ++it
, ++IndirectIndex
) {
376 const MCSectionMachO
&Section
=
377 cast
<MCSectionMachO
>(it
->SectionData
->getSection());
379 if (Section
.getType() != MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS
)
382 // Initialize the section indirect symbol base, if necessary.
383 if (!IndirectSymBase
.count(it
->SectionData
))
384 IndirectSymBase
[it
->SectionData
] = IndirectIndex
;
386 Asm
.getOrCreateSymbolData(*it
->Symbol
);
389 // Then lazy symbol pointers and symbol stubs.
391 for (MCAssembler::indirect_symbol_iterator it
= Asm
.indirect_symbol_begin(),
392 ie
= Asm
.indirect_symbol_end(); it
!= ie
; ++it
, ++IndirectIndex
) {
393 const MCSectionMachO
&Section
=
394 cast
<MCSectionMachO
>(it
->SectionData
->getSection());
396 if (Section
.getType() != MCSectionMachO::S_LAZY_SYMBOL_POINTERS
&&
397 Section
.getType() != MCSectionMachO::S_SYMBOL_STUBS
)
400 // Initialize the section indirect symbol base, if necessary.
401 if (!IndirectSymBase
.count(it
->SectionData
))
402 IndirectSymBase
[it
->SectionData
] = IndirectIndex
;
404 // Set the symbol type to undefined lazy, but only on construction.
406 // FIXME: Do not hardcode.
408 MCSymbolData
&Entry
= Asm
.getOrCreateSymbolData(*it
->Symbol
, &Created
);
410 Entry
.setFlags(Entry
.getFlags() | 0x0001);
414 /// ComputeSymbolTable - Compute the symbol table data
416 /// \param StringTable [out] - The string table data.
417 /// \param StringIndexMap [out] - Map from symbol names to offsets in the
419 void MachObjectWriter::
420 ComputeSymbolTable(MCAssembler
&Asm
, SmallString
<256> &StringTable
,
421 std::vector
<MachSymbolData
> &LocalSymbolData
,
422 std::vector
<MachSymbolData
> &ExternalSymbolData
,
423 std::vector
<MachSymbolData
> &UndefinedSymbolData
) {
424 // Build section lookup table.
425 DenseMap
<const MCSection
*, uint8_t> SectionIndexMap
;
427 for (MCAssembler::iterator it
= Asm
.begin(),
428 ie
= Asm
.end(); it
!= ie
; ++it
, ++Index
)
429 SectionIndexMap
[&it
->getSection()] = Index
;
430 assert(Index
<= 256 && "Too many sections!");
432 // Index 0 is always the empty string.
433 StringMap
<uint64_t> StringIndexMap
;
434 StringTable
+= '\x00';
436 // Build the symbol arrays and the string table, but only for non-local
439 // The particular order that we collect the symbols and create the string
440 // table, then sort the symbols is chosen to match 'as'. Even though it
441 // doesn't matter for correctness, this is important for letting us diff .o
443 for (MCAssembler::symbol_iterator it
= Asm
.symbol_begin(),
444 ie
= Asm
.symbol_end(); it
!= ie
; ++it
) {
445 const MCSymbol
&Symbol
= it
->getSymbol();
447 // Ignore non-linker visible symbols.
448 if (!Asm
.isSymbolLinkerVisible(it
->getSymbol()))
451 if (!it
->isExternal() && !Symbol
.isUndefined())
454 uint64_t &Entry
= StringIndexMap
[Symbol
.getName()];
456 Entry
= StringTable
.size();
457 StringTable
+= Symbol
.getName();
458 StringTable
+= '\x00';
463 MSD
.StringIndex
= Entry
;
465 if (Symbol
.isUndefined()) {
466 MSD
.SectionIndex
= 0;
467 UndefinedSymbolData
.push_back(MSD
);
468 } else if (Symbol
.isAbsolute()) {
469 MSD
.SectionIndex
= 0;
470 ExternalSymbolData
.push_back(MSD
);
472 MSD
.SectionIndex
= SectionIndexMap
.lookup(&Symbol
.getSection());
473 assert(MSD
.SectionIndex
&& "Invalid section index!");
474 ExternalSymbolData
.push_back(MSD
);
478 // Now add the data for local symbols.
479 for (MCAssembler::symbol_iterator it
= Asm
.symbol_begin(),
480 ie
= Asm
.symbol_end(); it
!= ie
; ++it
) {
481 const MCSymbol
&Symbol
= it
->getSymbol();
483 // Ignore non-linker visible symbols.
484 if (!Asm
.isSymbolLinkerVisible(it
->getSymbol()))
487 if (it
->isExternal() || Symbol
.isUndefined())
490 uint64_t &Entry
= StringIndexMap
[Symbol
.getName()];
492 Entry
= StringTable
.size();
493 StringTable
+= Symbol
.getName();
494 StringTable
+= '\x00';
499 MSD
.StringIndex
= Entry
;
501 if (Symbol
.isAbsolute()) {
502 MSD
.SectionIndex
= 0;
503 LocalSymbolData
.push_back(MSD
);
505 MSD
.SectionIndex
= SectionIndexMap
.lookup(&Symbol
.getSection());
506 assert(MSD
.SectionIndex
&& "Invalid section index!");
507 LocalSymbolData
.push_back(MSD
);
511 // External and undefined symbols are required to be in lexicographic order.
512 std::sort(ExternalSymbolData
.begin(), ExternalSymbolData
.end());
513 std::sort(UndefinedSymbolData
.begin(), UndefinedSymbolData
.end());
515 // Set the symbol indices.
517 for (unsigned i
= 0, e
= LocalSymbolData
.size(); i
!= e
; ++i
)
518 LocalSymbolData
[i
].SymbolData
->setIndex(Index
++);
519 for (unsigned i
= 0, e
= ExternalSymbolData
.size(); i
!= e
; ++i
)
520 ExternalSymbolData
[i
].SymbolData
->setIndex(Index
++);
521 for (unsigned i
= 0, e
= UndefinedSymbolData
.size(); i
!= e
; ++i
)
522 UndefinedSymbolData
[i
].SymbolData
->setIndex(Index
++);
524 // The string table is padded to a multiple of 4.
525 while (StringTable
.size() % 4)
526 StringTable
+= '\x00';
529 void MachObjectWriter::computeSectionAddresses(const MCAssembler
&Asm
,
530 const MCAsmLayout
&Layout
) {
531 uint64_t StartAddress
= 0;
532 const SmallVectorImpl
<MCSectionData
*> &Order
= Layout
.getSectionOrder();
533 for (int i
= 0, n
= Order
.size(); i
!= n
; ++i
) {
534 const MCSectionData
*SD
= Order
[i
];
535 StartAddress
= RoundUpToAlignment(StartAddress
, SD
->getAlignment());
536 SectionAddress
[SD
] = StartAddress
;
537 StartAddress
+= Layout
.getSectionAddressSize(SD
);
539 // Explicitly pad the section to match the alignment requirements of the
540 // following one. This is for 'gas' compatibility, it shouldn't
541 /// strictly be necessary.
542 StartAddress
+= getPaddingSize(SD
, Layout
);
546 void MachObjectWriter::ExecutePostLayoutBinding(MCAssembler
&Asm
,
547 const MCAsmLayout
&Layout
) {
548 computeSectionAddresses(Asm
, Layout
);
550 // Create symbol data for any indirect symbols.
551 BindIndirectSymbols(Asm
);
553 // Compute symbol table information and bind symbol indices.
554 ComputeSymbolTable(Asm
, StringTable
, LocalSymbolData
, ExternalSymbolData
,
555 UndefinedSymbolData
);
558 bool MachObjectWriter::
559 IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler
&Asm
,
560 const MCSymbolData
&DataA
,
561 const MCFragment
&FB
,
563 bool IsPCRel
) const {
567 // The effective address is
568 // addr(atom(A)) + offset(A)
569 // - addr(atom(B)) - offset(B)
570 // and the offsets are not relocatable, so the fixup is fully resolved when
571 // addr(atom(A)) - addr(atom(B)) == 0.
572 const MCSymbolData
*A_Base
= 0, *B_Base
= 0;
574 const MCSymbol
&SA
= DataA
.getSymbol().AliasedSymbol();
575 const MCSection
&SecA
= SA
.getSection();
576 const MCSection
&SecB
= FB
.getParent()->getSection();
579 // The simple (Darwin, except on x86_64) way of dealing with this was to
580 // assume that any reference to a temporary symbol *must* be a temporary
581 // symbol in the same atom, unless the sections differ. Therefore, any PCrel
582 // relocation to a temporary symbol (in the same section) is fully
583 // resolved. This also works in conjunction with absolutized .set, which
584 // requires the compiler to use .set to absolutize the differences between
585 // symbols which the compiler knows to be assembly time constants, so we
586 // don't need to worry about considering symbol differences fully resolved.
588 if (!Asm
.getBackend().hasReliableSymbolDifference()) {
589 if (!SA
.isTemporary() || !SA
.isInSection() || &SecA
!= &SecB
)
594 if (!TargetObjectWriter
->useAggressiveSymbolFolding())
598 const MCFragment
&FA
= *Asm
.getSymbolData(SA
).getFragment();
600 A_Base
= FA
.getAtom();
604 B_Base
= FB
.getAtom();
608 // If the atoms are the same, they are guaranteed to have the same address.
609 if (A_Base
== B_Base
)
612 // Otherwise, we can't prove this is fully resolved.
616 void MachObjectWriter::WriteObject(MCAssembler
&Asm
, const MCAsmLayout
&Layout
) {
617 unsigned NumSections
= Asm
.size();
619 // The section data starts after the header, the segment load command (and
620 // section headers) and the symbol table.
621 unsigned NumLoadCommands
= 1;
622 uint64_t LoadCommandsSize
= is64Bit() ?
623 macho::SegmentLoadCommand64Size
+ NumSections
* macho::Section64Size
:
624 macho::SegmentLoadCommand32Size
+ NumSections
* macho::Section32Size
;
626 // Add the symbol table load command sizes, if used.
627 unsigned NumSymbols
= LocalSymbolData
.size() + ExternalSymbolData
.size() +
628 UndefinedSymbolData
.size();
630 NumLoadCommands
+= 2;
631 LoadCommandsSize
+= (macho::SymtabLoadCommandSize
+
632 macho::DysymtabLoadCommandSize
);
635 // Compute the total size of the section data, as well as its file size and vm
637 uint64_t SectionDataStart
= (is64Bit() ? macho::Header64Size
:
638 macho::Header32Size
) + LoadCommandsSize
;
639 uint64_t SectionDataSize
= 0;
640 uint64_t SectionDataFileSize
= 0;
642 for (MCAssembler::const_iterator it
= Asm
.begin(),
643 ie
= Asm
.end(); it
!= ie
; ++it
) {
644 const MCSectionData
&SD
= *it
;
645 uint64_t Address
= getSectionAddress(&SD
);
646 uint64_t Size
= Layout
.getSectionAddressSize(&SD
);
647 uint64_t FileSize
= Layout
.getSectionFileSize(&SD
);
648 FileSize
+= getPaddingSize(&SD
, Layout
);
650 VMSize
= std::max(VMSize
, Address
+ Size
);
652 if (SD
.getSection().isVirtualSection())
655 SectionDataSize
= std::max(SectionDataSize
, Address
+ Size
);
656 SectionDataFileSize
= std::max(SectionDataFileSize
, Address
+ FileSize
);
659 // The section data is padded to 4 bytes.
661 // FIXME: Is this machine dependent?
662 unsigned SectionDataPadding
= OffsetToAlignment(SectionDataFileSize
, 4);
663 SectionDataFileSize
+= SectionDataPadding
;
665 // Write the prolog, starting with the header and load command...
666 WriteHeader(NumLoadCommands
, LoadCommandsSize
,
667 Asm
.getSubsectionsViaSymbols());
668 WriteSegmentLoadCommand(NumSections
, VMSize
,
669 SectionDataStart
, SectionDataSize
);
671 // ... and then the section headers.
672 uint64_t RelocTableEnd
= SectionDataStart
+ SectionDataFileSize
;
673 for (MCAssembler::const_iterator it
= Asm
.begin(),
674 ie
= Asm
.end(); it
!= ie
; ++it
) {
675 std::vector
<macho::RelocationEntry
> &Relocs
= Relocations
[it
];
676 unsigned NumRelocs
= Relocs
.size();
677 uint64_t SectionStart
= SectionDataStart
+ getSectionAddress(it
);
678 WriteSection(Asm
, Layout
, *it
, SectionStart
, RelocTableEnd
, NumRelocs
);
679 RelocTableEnd
+= NumRelocs
* macho::RelocationInfoSize
;
682 // Write the symbol table load command, if used.
684 unsigned FirstLocalSymbol
= 0;
685 unsigned NumLocalSymbols
= LocalSymbolData
.size();
686 unsigned FirstExternalSymbol
= FirstLocalSymbol
+ NumLocalSymbols
;
687 unsigned NumExternalSymbols
= ExternalSymbolData
.size();
688 unsigned FirstUndefinedSymbol
= FirstExternalSymbol
+ NumExternalSymbols
;
689 unsigned NumUndefinedSymbols
= UndefinedSymbolData
.size();
690 unsigned NumIndirectSymbols
= Asm
.indirect_symbol_size();
691 unsigned NumSymTabSymbols
=
692 NumLocalSymbols
+ NumExternalSymbols
+ NumUndefinedSymbols
;
693 uint64_t IndirectSymbolSize
= NumIndirectSymbols
* 4;
694 uint64_t IndirectSymbolOffset
= 0;
696 // If used, the indirect symbols are written after the section data.
697 if (NumIndirectSymbols
)
698 IndirectSymbolOffset
= RelocTableEnd
;
700 // The symbol table is written after the indirect symbol data.
701 uint64_t SymbolTableOffset
= RelocTableEnd
+ IndirectSymbolSize
;
703 // The string table is written after symbol table.
704 uint64_t StringTableOffset
=
705 SymbolTableOffset
+ NumSymTabSymbols
* (is64Bit() ? macho::Nlist64Size
:
707 WriteSymtabLoadCommand(SymbolTableOffset
, NumSymTabSymbols
,
708 StringTableOffset
, StringTable
.size());
710 WriteDysymtabLoadCommand(FirstLocalSymbol
, NumLocalSymbols
,
711 FirstExternalSymbol
, NumExternalSymbols
,
712 FirstUndefinedSymbol
, NumUndefinedSymbols
,
713 IndirectSymbolOffset
, NumIndirectSymbols
);
716 // Write the actual section data.
717 for (MCAssembler::const_iterator it
= Asm
.begin(),
718 ie
= Asm
.end(); it
!= ie
; ++it
) {
719 Asm
.WriteSectionData(it
, Layout
);
721 uint64_t Pad
= getPaddingSize(it
, Layout
);
722 for (unsigned int i
= 0; i
< Pad
; ++i
)
726 // Write the extra padding.
727 WriteZeros(SectionDataPadding
);
729 // Write the relocation entries.
730 for (MCAssembler::const_iterator it
= Asm
.begin(),
731 ie
= Asm
.end(); it
!= ie
; ++it
) {
732 // Write the section relocation entries, in reverse order to match 'as'
733 // (approximately, the exact algorithm is more complicated than this).
734 std::vector
<macho::RelocationEntry
> &Relocs
= Relocations
[it
];
735 for (unsigned i
= 0, e
= Relocs
.size(); i
!= e
; ++i
) {
736 Write32(Relocs
[e
- i
- 1].Word0
);
737 Write32(Relocs
[e
- i
- 1].Word1
);
741 // Write the symbol table data, if used.
743 // Write the indirect symbol entries.
744 for (MCAssembler::const_indirect_symbol_iterator
745 it
= Asm
.indirect_symbol_begin(),
746 ie
= Asm
.indirect_symbol_end(); it
!= ie
; ++it
) {
747 // Indirect symbols in the non lazy symbol pointer section have some
749 const MCSectionMachO
&Section
=
750 static_cast<const MCSectionMachO
&>(it
->SectionData
->getSection());
751 if (Section
.getType() == MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS
) {
752 // If this symbol is defined and internal, mark it as such.
753 if (it
->Symbol
->isDefined() &&
754 !Asm
.getSymbolData(*it
->Symbol
).isExternal()) {
755 uint32_t Flags
= macho::ISF_Local
;
756 if (it
->Symbol
->isAbsolute())
757 Flags
|= macho::ISF_Absolute
;
763 Write32(Asm
.getSymbolData(*it
->Symbol
).getIndex());
766 // FIXME: Check that offsets match computed ones.
768 // Write the symbol table entries.
769 for (unsigned i
= 0, e
= LocalSymbolData
.size(); i
!= e
; ++i
)
770 WriteNlist(LocalSymbolData
[i
], Layout
);
771 for (unsigned i
= 0, e
= ExternalSymbolData
.size(); i
!= e
; ++i
)
772 WriteNlist(ExternalSymbolData
[i
], Layout
);
773 for (unsigned i
= 0, e
= UndefinedSymbolData
.size(); i
!= e
; ++i
)
774 WriteNlist(UndefinedSymbolData
[i
], Layout
);
776 // Write the string table.
777 OS
<< StringTable
.str();
781 MCObjectWriter
*llvm::createMachObjectWriter(MCMachObjectTargetWriter
*MOTW
,
783 bool IsLittleEndian
) {
784 return new MachObjectWriter(MOTW
, OS
, IsLittleEndian
);