X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FMC%2FMachObjectWriter.cpp;h=8af07c74fdfe707b194da7e613e7a3fdba655fdf;hb=6d857ca4d71548f5cdb57b106cc1a12fc2c93e9d;hp=41c11fba1d07a1e84bfef1a6b1c8a17835a6bcb8;hpb=115a3dd066c277c5417f4d9b9f642b732b76f4e7;p=oota-llvm.git diff --git a/lib/MC/MachObjectWriter.cpp b/lib/MC/MachObjectWriter.cpp index 41c11fba1d0..8af07c74fdf 100644 --- a/lib/MC/MachObjectWriter.cpp +++ b/lib/MC/MachObjectWriter.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +#include "llvm/MC/MCMachObjectWriter.h" +#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/Twine.h" #include "llvm/MC/MCAssembler.h" @@ -17,25 +19,29 @@ #include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCMachOSymbolFlags.h" #include "llvm/MC/MCValue.h" +#include "llvm/Object/MachOFormat.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/MachO.h" #include "llvm/Target/TargetAsmBackend.h" // FIXME: Gross. +#include "../Target/ARM/ARMFixupKinds.h" #include "../Target/X86/X86FixupKinds.h" #include using namespace llvm; +using namespace llvm::object; // FIXME: this has been copied from (or to) X86AsmBackend.cpp static unsigned getFixupKindLog2Size(unsigned Kind) { switch (Kind) { - default: llvm_unreachable("invalid fixup kind!"); - case X86::reloc_pcrel_1byte: + default: + llvm_unreachable("invalid fixup kind!"); + case FK_PCRel_1: case FK_Data_1: return 0; - case X86::reloc_pcrel_2byte: + case FK_PCRel_2: case FK_Data_2: return 1; - case X86::reloc_pcrel_4byte: + case FK_PCRel_4: + // FIXME: Remove these!!! case X86::reloc_riprel_4byte: case X86::reloc_riprel_4byte_movq_load: case X86::reloc_signed_4byte: @@ -44,24 +50,6 @@ static unsigned getFixupKindLog2Size(unsigned Kind) { } } -static bool isFixupKindPCRel(unsigned Kind) { - switch (Kind) { - default: - return false; - case X86::reloc_pcrel_1byte: - case X86::reloc_pcrel_2byte: - case X86::reloc_pcrel_4byte: - case X86::reloc_riprel_4byte: - case X86::reloc_riprel_4byte_movq_load: - return true; - } -} - -static bool isFixupKindRIPRel(unsigned Kind) { - return Kind == X86::reloc_riprel_4byte || - Kind == X86::reloc_riprel_4byte_movq_load; -} - static bool doesSymbolRequireExternRelocation(MCSymbolData *SD) { // Undefined symbols are always extern. if (SD->Symbol->isUndefined()) @@ -76,176 +64,9 @@ static bool doesSymbolRequireExternRelocation(MCSymbolData *SD) { return false; } -static bool isScatteredFixupFullyResolved(const MCAssembler &Asm, - const MCValue Target, - const MCSymbolData *BaseSymbol) { - // The effective fixup address is - // addr(atom(A)) + offset(A) - // - addr(atom(B)) - offset(B) - // - addr(BaseSymbol) + - // and the offsets are not relocatable, so the fixup is fully resolved when - // addr(atom(A)) - addr(atom(B)) - addr(BaseSymbol) == 0. - // - // Note that "false" is almost always conservatively correct (it means we emit - // a relocation which is unnecessary), except when it would force us to emit a - // relocation which the target cannot encode. - - const MCSymbolData *A_Base = 0, *B_Base = 0; - if (const MCSymbolRefExpr *A = Target.getSymA()) { - // Modified symbol references cannot be resolved. - if (A->getKind() != MCSymbolRefExpr::VK_None) - return false; - - A_Base = Asm.getAtom(&Asm.getSymbolData(A->getSymbol())); - if (!A_Base) - return false; - } - - if (const MCSymbolRefExpr *B = Target.getSymB()) { - // Modified symbol references cannot be resolved. - if (B->getKind() != MCSymbolRefExpr::VK_None) - return false; - - B_Base = Asm.getAtom(&Asm.getSymbolData(B->getSymbol())); - if (!B_Base) - return false; - } - - // If there is no base, A and B have to be the same atom for this fixup to be - // fully resolved. - if (!BaseSymbol) - return A_Base == B_Base; - - // Otherwise, B must be missing and A must be the base. - return !B_Base && BaseSymbol == A_Base; -} - -static bool isScatteredFixupFullyResolvedSimple(const MCAssembler &Asm, - const MCValue Target, - const MCSection *BaseSection) { - // The effective fixup address is - // addr(atom(A)) + offset(A) - // - addr(atom(B)) - offset(B) - // - addr() + - // and the offsets are not relocatable, so the fixup is fully resolved when - // addr(atom(A)) - addr(atom(B)) - addr()) == 0. - // - // The simple (Darwin, except on x86_64) way of dealing with this was to - // assume that any reference to a temporary symbol *must* be a temporary - // symbol in the same atom, unless the sections differ. Therefore, any PCrel - // relocation to a temporary symbol (in the same section) is fully - // resolved. This also works in conjunction with absolutized .set, which - // requires the compiler to use .set to absolutize the differences between - // symbols which the compiler knows to be assembly time constants, so we don't - // need to worry about considering symbol differences fully resolved. - - // Non-relative fixups are only resolved if constant. - if (!BaseSection) - return Target.isAbsolute(); - - // Otherwise, relative fixups are only resolved if not a difference and the - // target is a temporary in the same section. - if (Target.isAbsolute() || Target.getSymB()) - return false; - - const MCSymbol *A = &Target.getSymA()->getSymbol(); - if (!A->isTemporary() || !A->isInSection() || - &A->getSection() != BaseSection) - return false; - - return true; -} - namespace { class MachObjectWriter : public MCObjectWriter { - // See . - enum { - Header_Magic32 = 0xFEEDFACE, - Header_Magic64 = 0xFEEDFACF - }; - - enum { - Header32Size = 28, - Header64Size = 32, - SegmentLoadCommand32Size = 56, - SegmentLoadCommand64Size = 72, - Section32Size = 68, - Section64Size = 80, - SymtabLoadCommandSize = 24, - DysymtabLoadCommandSize = 80, - Nlist32Size = 12, - Nlist64Size = 16, - RelocationInfoSize = 8 - }; - - enum HeaderFileType { - HFT_Object = 0x1 - }; - - enum HeaderFlags { - HF_SubsectionsViaSymbols = 0x2000 - }; - - enum LoadCommandType { - LCT_Segment = 0x1, - LCT_Symtab = 0x2, - LCT_Dysymtab = 0xb, - LCT_Segment64 = 0x19 - }; - - // See . - enum SymbolTypeType { - STT_Undefined = 0x00, - STT_Absolute = 0x02, - STT_Section = 0x0e - }; - - enum SymbolTypeFlags { - // If any of these bits are set, then the entry is a stab entry number (see - // . Otherwise the other masks apply. - STF_StabsEntryMask = 0xe0, - - STF_TypeMask = 0x0e, - STF_External = 0x01, - STF_PrivateExtern = 0x10 - }; - - /// IndirectSymbolFlags - Flags for encoding special values in the indirect - /// symbol entry. - enum IndirectSymbolFlags { - ISF_Local = 0x80000000, - ISF_Absolute = 0x40000000 - }; - - /// RelocationFlags - Special flags for addresses. - enum RelocationFlags { - RF_Scattered = 0x80000000 - }; - - enum RelocationInfoType { - RIT_Vanilla = 0, - RIT_Pair = 1, - RIT_Difference = 2, - RIT_PreboundLazyPointer = 3, - RIT_LocalDifference = 4, - RIT_TLV = 5 - }; - - /// X86_64 uses its own relocation types. - enum RelocationInfoTypeX86_64 { - RIT_X86_64_Unsigned = 0, - RIT_X86_64_Signed = 1, - RIT_X86_64_Branch = 2, - RIT_X86_64_GOTLoad = 3, - RIT_X86_64_GOT = 4, - RIT_X86_64_Subtractor = 5, - RIT_X86_64_Signed1 = 6, - RIT_X86_64_Signed2 = 7, - RIT_X86_64_Signed4 = 8, - RIT_X86_64_TLV = 9 - }; - /// MachSymbolData - Helper struct for containing some precomputed information /// on symbols. struct MachSymbolData { @@ -260,16 +81,14 @@ class MachObjectWriter : public MCObjectWriter { } }; + /// The target specific Mach-O writer instance. + llvm::OwningPtr TargetObjectWriter; + /// @name Relocation Data /// @{ - struct MachRelocationEntry { - uint32_t Word0; - uint32_t Word1; - }; - llvm::DenseMap > Relocations; + std::vector > Relocations; llvm::DenseMap IndirectSymBase; /// @} @@ -283,25 +102,70 @@ class MachObjectWriter : public MCObjectWriter { /// @} - unsigned Is64Bit : 1; +private: + /// @name Utility Methods + /// @{ + + bool isFixupKindPCRel(const MCAssembler &Asm, unsigned Kind) { + const MCFixupKindInfo &FKI = Asm.getBackend().getFixupKindInfo( + (MCFixupKind) Kind); + + return FKI.Flags & MCFixupKindInfo::FKF_IsPCRel; + } + + /// @} + + SectionAddrMap SectionAddress; + uint64_t getSectionAddress(const MCSectionData* SD) const { + return SectionAddress.lookup(SD); + } + uint64_t getSymbolAddress(const MCSymbolData* SD, + const MCAsmLayout &Layout) const { + return getSectionAddress(SD->getFragment()->getParent()) + + Layout.getSymbolOffset(SD); + } + uint64_t getFragmentAddress(const MCFragment *Fragment, + const MCAsmLayout &Layout) const { + return getSectionAddress(Fragment->getParent()) + + Layout.getFragmentOffset(Fragment); + } - uint32_t CPUType; - uint32_t CPUSubtype; + uint64_t getPaddingSize(const MCSectionData *SD, + const MCAsmLayout &Layout) const { + uint64_t EndAddr = getSectionAddress(SD) + Layout.getSectionAddressSize(SD); + unsigned Next = SD->getLayoutOrder() + 1; + if (Next >= Layout.getSectionOrder().size()) + return 0; + + const MCSectionData &NextSD = *Layout.getSectionOrder()[Next]; + if (NextSD.getSection().isVirtualSection()) + return 0; + return OffsetToAlignment(EndAddr, NextSD.getAlignment()); + } public: - MachObjectWriter(raw_ostream &_OS, - bool _Is64Bit, uint32_t _CPUType, uint32_t _CPUSubtype, + MachObjectWriter(MCMachObjectTargetWriter *MOTW, raw_ostream &_OS, bool _IsLittleEndian) - : MCObjectWriter(_OS, _IsLittleEndian), - Is64Bit(_Is64Bit), CPUType(_CPUType), CPUSubtype(_CPUSubtype) { + : MCObjectWriter(_OS, _IsLittleEndian), TargetObjectWriter(MOTW) { + } + + /// @name Target Writer Proxy Accessors + /// @{ + + bool is64Bit() const { return TargetObjectWriter->is64Bit(); } + bool isARM() const { + uint32_t CPUType = TargetObjectWriter->getCPUType() & ~mach::CTFM_ArchMask; + return CPUType == mach::CTM_ARM; } + /// @} + void WriteHeader(unsigned NumLoadCommands, unsigned LoadCommandsSize, bool SubsectionsViaSymbols) { uint32_t Flags = 0; if (SubsectionsViaSymbols) - Flags |= HF_SubsectionsViaSymbols; + Flags |= macho::HF_SubsectionsViaSymbols; // struct mach_header (28 bytes) or // struct mach_header_64 (32 bytes) @@ -309,20 +173,20 @@ public: uint64_t Start = OS.tell(); (void) Start; - Write32(Is64Bit ? Header_Magic64 : Header_Magic32); + Write32(is64Bit() ? macho::HM_Object64 : macho::HM_Object32); - Write32(CPUType); - Write32(CPUSubtype); + Write32(TargetObjectWriter->getCPUType()); + Write32(TargetObjectWriter->getCPUSubtype()); - Write32(HFT_Object); - Write32(NumLoadCommands); // Object files have a single load command, the - // segment. + Write32(macho::HFT_Object); + Write32(NumLoadCommands); Write32(LoadCommandsSize); Write32(Flags); - if (Is64Bit) + if (is64Bit()) Write32(0); // reserved - assert(OS.tell() - Start == Is64Bit ? Header64Size : Header32Size); + assert(OS.tell() - Start == + (is64Bit() ? macho::Header64Size : macho::Header32Size)); } /// WriteSegmentLoadCommand - Write a segment load command. @@ -339,14 +203,16 @@ public: uint64_t Start = OS.tell(); (void) Start; - unsigned SegmentLoadCommandSize = Is64Bit ? SegmentLoadCommand64Size : - SegmentLoadCommand32Size; - Write32(Is64Bit ? LCT_Segment64 : LCT_Segment); + unsigned SegmentLoadCommandSize = + is64Bit() ? macho::SegmentLoadCommand64Size: + macho::SegmentLoadCommand32Size; + Write32(is64Bit() ? macho::LCT_Segment64 : macho::LCT_Segment); Write32(SegmentLoadCommandSize + - NumSections * (Is64Bit ? Section64Size : Section32Size)); + NumSections * (is64Bit() ? macho::Section64Size : + macho::Section32Size)); WriteBytes("", 16); - if (Is64Bit) { + if (is64Bit()) { Write64(0); // vmaddr Write64(VMSize); // vmsize Write64(SectionDataStartOffset); // file offset @@ -368,10 +234,10 @@ public: void WriteSection(const MCAssembler &Asm, const MCAsmLayout &Layout, const MCSectionData &SD, uint64_t FileOffset, uint64_t RelocationsStart, unsigned NumRelocations) { - uint64_t SectionSize = Layout.getSectionSize(&SD); + uint64_t SectionSize = Layout.getSectionAddressSize(&SD); // The offset is unused for virtual sections. - if (Asm.getBackend().isVirtualSection(SD.getSection())) { + if (SD.getSection().isVirtualSection()) { assert(Layout.getSectionFileSize(&SD) == 0 && "Invalid file size!"); FileOffset = 0; } @@ -385,11 +251,11 @@ public: const MCSectionMachO &Section = cast(SD.getSection()); WriteBytes(Section.getSectionName(), 16); WriteBytes(Section.getSegmentName(), 16); - if (Is64Bit) { - Write64(Layout.getSectionAddress(&SD)); // address + if (is64Bit()) { + Write64(getSectionAddress(&SD)); // address Write64(SectionSize); // size } else { - Write32(Layout.getSectionAddress(&SD)); // address + Write32(getSectionAddress(&SD)); // address Write32(SectionSize); // size } Write32(FileOffset); @@ -405,10 +271,11 @@ public: Write32(Flags); Write32(IndirectSymBase.lookup(&SD)); // reserved1 Write32(Section.getStubSize()); // reserved2 - if (Is64Bit) + if (is64Bit()) Write32(0); // reserved3 - assert(OS.tell() - Start == Is64Bit ? Section64Size : Section32Size); + assert(OS.tell() - Start == is64Bit() ? macho::Section64Size : + macho::Section32Size); } void WriteSymtabLoadCommand(uint32_t SymbolOffset, uint32_t NumSymbols, @@ -419,14 +286,14 @@ public: uint64_t Start = OS.tell(); (void) Start; - Write32(LCT_Symtab); - Write32(SymtabLoadCommandSize); + Write32(macho::LCT_Symtab); + Write32(macho::SymtabLoadCommandSize); Write32(SymbolOffset); Write32(NumSymbols); Write32(StringTableOffset); Write32(StringTableSize); - assert(OS.tell() - Start == SymtabLoadCommandSize); + assert(OS.tell() - Start == macho::SymtabLoadCommandSize); } void WriteDysymtabLoadCommand(uint32_t FirstLocalSymbol, @@ -442,8 +309,8 @@ public: uint64_t Start = OS.tell(); (void) Start; - Write32(LCT_Dysymtab); - Write32(DysymtabLoadCommandSize); + Write32(macho::LCT_Dysymtab); + Write32(macho::DysymtabLoadCommandSize); Write32(FirstLocalSymbol); Write32(NumLocalSymbols); Write32(FirstExternalSymbol); @@ -463,7 +330,7 @@ public: Write32(0); // locreloff Write32(0); // nlocrel - assert(OS.tell() - Start == DysymtabLoadCommandSize); + assert(OS.tell() - Start == macho::DysymtabLoadCommandSize); } void WriteNlist(MachSymbolData &MSD, const MCAsmLayout &Layout) { @@ -477,27 +344,27 @@ public: // // FIXME: Are the prebound or indirect fields possible here? if (Symbol.isUndefined()) - Type = STT_Undefined; + Type = macho::STT_Undefined; else if (Symbol.isAbsolute()) - Type = STT_Absolute; + Type = macho::STT_Absolute; else - Type = STT_Section; + Type = macho::STT_Section; // FIXME: Set STAB bits. if (Data.isPrivateExtern()) - Type |= STF_PrivateExtern; + Type |= macho::STF_PrivateExtern; // Set external bit. if (Data.isExternal() || Symbol.isUndefined()) - Type |= STF_External; + Type |= macho::STF_External; // Compute the symbol address. if (Symbol.isDefined()) { if (Symbol.isAbsolute()) { Address = cast(Symbol.getVariableValue())->getValue(); } else { - Address = Layout.getSymbolAddress(&Data); + Address = getSymbolAddress(&Data, Layout); } } else if (Data.isCommon()) { // Common symbols are encoded with the size in the address @@ -525,7 +392,7 @@ public: // The Mach-O streamer uses the lowest 16-bits of the flags for the 'desc' // value. Write16(Flags); - if (Is64Bit) + if (is64Bit()) Write64(Address); else Write32(Address); @@ -545,11 +412,15 @@ public: // - Input errors, where something cannot be correctly encoded. 'as' allows // these through in many cases. + static bool isFixupKindRIPRel(unsigned Kind) { + return Kind == X86::reloc_riprel_4byte || + Kind == X86::reloc_riprel_4byte_movq_load; + } void RecordX86_64Relocation(const MCAssembler &Asm, const MCAsmLayout &Layout, const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target, uint64_t &FixedValue) { - unsigned IsPCRel = isFixupKindPCRel(Fixup.getKind()); + unsigned IsPCRel = isFixupKindPCRel(Asm, Fixup.getKind()); unsigned IsRIPRel = isFixupKindRIPRel(Fixup.getKind()); unsigned Log2Size = getFixupKindLog2Size(Fixup.getKind()); @@ -557,7 +428,7 @@ public: uint32_t FixupOffset = Layout.getFragmentOffset(Fragment) + Fixup.getOffset(); uint32_t FixupAddress = - Layout.getFragmentAddress(Fragment) + Fixup.getOffset(); + getFragmentAddress(Fragment, Layout) + Fixup.getOffset(); int64_t Value = 0; unsigned Index = 0; unsigned IsExtern = 0; @@ -576,7 +447,7 @@ public: if (Target.isAbsolute()) { // constant // SymbolNum of 0 indicates the absolute section. - Type = RIT_X86_64_Unsigned; + Type = macho::RIT_X86_64_Unsigned; Index = 0; // FIXME: I believe this is broken, I don't think the linker can @@ -586,7 +457,7 @@ public: // yet). if (IsPCRel) { IsExtern = 1; - Type = RIT_X86_64_Branch; + Type = macho::RIT_X86_64_Branch; } } else if (Target.getSymB()) { // A - B + constant const MCSymbol *A = &Target.getSymA()->getSymbol(); @@ -620,10 +491,10 @@ public: if (A_Base == B_Base && A_Base) report_fatal_error("unsupported relocation with identical base"); - Value += Layout.getSymbolAddress(&A_SD) - - (A_Base == NULL ? 0 : Layout.getSymbolAddress(A_Base)); - Value -= Layout.getSymbolAddress(&B_SD) - - (B_Base == NULL ? 0 : Layout.getSymbolAddress(B_Base)); + Value += getSymbolAddress(&A_SD, Layout) - + (A_Base == NULL ? 0 : getSymbolAddress(A_Base, Layout)); + Value -= getSymbolAddress(&B_SD, Layout) - + (B_Base == NULL ? 0 : getSymbolAddress(B_Base, Layout)); if (A_Base) { Index = A_Base->getIndex(); @@ -633,9 +504,9 @@ public: Index = A_SD.getFragment()->getParent()->getOrdinal() + 1; IsExtern = 0; } - Type = RIT_X86_64_Unsigned; + Type = macho::RIT_X86_64_Unsigned; - MachRelocationEntry MRE; + macho::RelocationEntry MRE; MRE.Word0 = FixupOffset; MRE.Word1 = ((Index << 0) | (IsPCRel << 24) | @@ -652,7 +523,7 @@ public: Index = B_SD.getFragment()->getParent()->getOrdinal() + 1; IsExtern = 0; } - Type = RIT_X86_64_Subtractor; + Type = macho::RIT_X86_64_Subtractor; } else { const MCSymbol *Symbol = &Target.getSymA()->getSymbol(); MCSymbolData &SD = Asm.getSymbolData(*Symbol); @@ -678,15 +549,26 @@ public: // Add the local offset, if needed. if (Base != &SD) - Value += Layout.getSymbolAddress(&SD) - Layout.getSymbolAddress(Base); + Value += Layout.getSymbolOffset(&SD) - Layout.getSymbolOffset(Base); } else if (Symbol->isInSection()) { // The index is the section ordinal (1-based). Index = SD.getFragment()->getParent()->getOrdinal() + 1; IsExtern = 0; - Value += Layout.getSymbolAddress(&SD); + Value += getSymbolAddress(&SD, Layout); if (IsPCRel) Value -= FixupAddress + (1 << Log2Size); + } else if (Symbol->isVariable()) { + const MCExpr *Value = Symbol->getVariableValue(); + int64_t Res; + bool isAbs = Value->EvaluateAsAbsolute(Res, Layout, SectionAddress); + if (isAbs) { + FixedValue = Res; + return; + } else { + report_fatal_error("unsupported relocation of variable '" + + Symbol->getName() + "'"); + } } else { report_fatal_error("unsupported relocation of undefined symbol '" + Symbol->getName() + "'"); @@ -700,15 +582,15 @@ public: // rewrite the movq to an leaq at link time if the symbol ends up in // the same linkage unit. if (unsigned(Fixup.getKind()) == X86::reloc_riprel_4byte_movq_load) - Type = RIT_X86_64_GOTLoad; + Type = macho::RIT_X86_64_GOTLoad; else - Type = RIT_X86_64_GOT; + Type = macho::RIT_X86_64_GOT; } else if (Modifier == MCSymbolRefExpr::VK_TLVP) { - Type = RIT_X86_64_TLV; + Type = macho::RIT_X86_64_TLV; } else if (Modifier != MCSymbolRefExpr::VK_None) { report_fatal_error("unsupported symbol modifier in relocation"); } else { - Type = RIT_X86_64_Signed; + Type = macho::RIT_X86_64_Signed; // The Darwin x86_64 relocation format has a problem where it cannot // encode an address (L + ) which is outside the atom @@ -725,9 +607,9 @@ public: // (the additional bias), but instead appear to just look at the // final offset. switch (-(Target.getConstant() + (1LL << Log2Size))) { - case 1: Type = RIT_X86_64_Signed1; break; - case 2: Type = RIT_X86_64_Signed2; break; - case 4: Type = RIT_X86_64_Signed4; break; + case 1: Type = macho::RIT_X86_64_Signed1; break; + case 2: Type = macho::RIT_X86_64_Signed2; break; + case 4: Type = macho::RIT_X86_64_Signed4; break; } } } else { @@ -735,24 +617,24 @@ public: report_fatal_error("unsupported symbol modifier in branch " "relocation"); - Type = RIT_X86_64_Branch; + Type = macho::RIT_X86_64_Branch; } } else { if (Modifier == MCSymbolRefExpr::VK_GOT) { - Type = RIT_X86_64_GOT; + Type = macho::RIT_X86_64_GOT; } else if (Modifier == MCSymbolRefExpr::VK_GOTPCREL) { // GOTPCREL is allowed as a modifier on non-PCrel instructions, in // which case all we do is set the PCrel bit in the relocation entry; // this is used with exception handling, for example. The source is // required to include any necessary offset directly. - Type = RIT_X86_64_GOT; + Type = macho::RIT_X86_64_GOT; IsPCRel = 1; } else if (Modifier == MCSymbolRefExpr::VK_TLVP) { report_fatal_error("TLVP symbol modifier should have been rip-rel"); } else if (Modifier != MCSymbolRefExpr::VK_None) report_fatal_error("unsupported symbol modifier in relocation"); else - Type = RIT_X86_64_Unsigned; + Type = macho::RIT_X86_64_Unsigned; } } @@ -760,7 +642,7 @@ public: FixedValue = Value; // struct relocation_info (8 bytes) - MachRelocationEntry MRE; + macho::RelocationEntry MRE; MRE.Word0 = FixupOffset; MRE.Word1 = ((Index << 0) | (IsPCRel << 24) | @@ -774,11 +656,11 @@ public: const MCAsmLayout &Layout, const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target, + unsigned Log2Size, uint64_t &FixedValue) { uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset(); - unsigned IsPCRel = isFixupKindPCRel(Fixup.getKind()); - unsigned Log2Size = getFixupKindLog2Size(Fixup.getKind()); - unsigned Type = RIT_Vanilla; + unsigned IsPCRel = isFixupKindPCRel(Asm, Fixup.getKind()); + unsigned Type = macho::RIT_Vanilla; // See . const MCSymbol *A = &Target.getSymA()->getSymbol(); @@ -788,7 +670,9 @@ public: report_fatal_error("symbol '" + A->getName() + "' can not be undefined in a subtraction expression"); - uint32_t Value = Layout.getSymbolAddress(A_SD); + uint32_t Value = getSymbolAddress(A_SD, Layout); + uint64_t SecAddr = getSectionAddress(A_SD->getFragment()->getParent()); + FixedValue += SecAddr; uint32_t Value2 = 0; if (const MCSymbolRefExpr *B = Target.getSymB()) { @@ -803,28 +687,184 @@ public: // Note that there is no longer any semantic difference between these two // relocation types from the linkers point of view, this is done solely // for pedantic compatibility with 'as'. - Type = A_SD->isExternal() ? RIT_Difference : RIT_LocalDifference; - Value2 = Layout.getSymbolAddress(B_SD); + Type = A_SD->isExternal() ? (unsigned)macho::RIT_Difference : + (unsigned)macho::RIT_Generic_LocalDifference; + Value2 = getSymbolAddress(B_SD, Layout); + FixedValue -= getSectionAddress(B_SD->getFragment()->getParent()); } // Relocations are written out in reverse order, so the PAIR comes first. - if (Type == RIT_Difference || Type == RIT_LocalDifference) { - MachRelocationEntry MRE; + if (Type == macho::RIT_Difference || + Type == macho::RIT_Generic_LocalDifference) { + macho::RelocationEntry MRE; MRE.Word0 = ((0 << 0) | - (RIT_Pair << 24) | + (macho::RIT_Pair << 24) | (Log2Size << 28) | (IsPCRel << 30) | - RF_Scattered); + macho::RF_Scattered); MRE.Word1 = Value2; Relocations[Fragment->getParent()].push_back(MRE); } - MachRelocationEntry MRE; + macho::RelocationEntry MRE; MRE.Word0 = ((FixupOffset << 0) | (Type << 24) | (Log2Size << 28) | (IsPCRel << 30) | - RF_Scattered); + macho::RF_Scattered); + MRE.Word1 = Value; + Relocations[Fragment->getParent()].push_back(MRE); + } + + void RecordARMScatteredRelocation(const MCAssembler &Asm, + const MCAsmLayout &Layout, + const MCFragment *Fragment, + const MCFixup &Fixup, MCValue Target, + unsigned Log2Size, + uint64_t &FixedValue) { + uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset(); + unsigned IsPCRel = isFixupKindPCRel(Asm, Fixup.getKind()); + unsigned Type = macho::RIT_Vanilla; + + // See . + const MCSymbol *A = &Target.getSymA()->getSymbol(); + MCSymbolData *A_SD = &Asm.getSymbolData(*A); + + if (!A_SD->getFragment()) + report_fatal_error("symbol '" + A->getName() + + "' can not be undefined in a subtraction expression"); + + uint32_t Value = getSymbolAddress(A_SD, Layout); + uint64_t SecAddr = getSectionAddress(A_SD->getFragment()->getParent()); + FixedValue += SecAddr; + uint32_t Value2 = 0; + + if (const MCSymbolRefExpr *B = Target.getSymB()) { + MCSymbolData *B_SD = &Asm.getSymbolData(B->getSymbol()); + + if (!B_SD->getFragment()) + report_fatal_error("symbol '" + B->getSymbol().getName() + + "' can not be undefined in a subtraction expression"); + + // Select the appropriate difference relocation type. + Type = macho::RIT_Difference; + Value2 = getSymbolAddress(B_SD, Layout); + FixedValue -= getSectionAddress(B_SD->getFragment()->getParent()); + } + + // Relocations are written out in reverse order, so the PAIR comes first. + if (Type == macho::RIT_Difference || + Type == macho::RIT_Generic_LocalDifference) { + macho::RelocationEntry MRE; + MRE.Word0 = ((0 << 0) | + (macho::RIT_Pair << 24) | + (Log2Size << 28) | + (IsPCRel << 30) | + macho::RF_Scattered); + MRE.Word1 = Value2; + Relocations[Fragment->getParent()].push_back(MRE); + } + + macho::RelocationEntry MRE; + MRE.Word0 = ((FixupOffset << 0) | + (Type << 24) | + (Log2Size << 28) | + (IsPCRel << 30) | + macho::RF_Scattered); + MRE.Word1 = Value; + Relocations[Fragment->getParent()].push_back(MRE); + } + + void RecordARMMovwMovtRelocation(const MCAssembler &Asm, + const MCAsmLayout &Layout, + const MCFragment *Fragment, + const MCFixup &Fixup, MCValue Target, + uint64_t &FixedValue) { + uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset(); + unsigned IsPCRel = isFixupKindPCRel(Asm, Fixup.getKind()); + unsigned Type = macho::RIT_ARM_Half; + + // See . + const MCSymbol *A = &Target.getSymA()->getSymbol(); + MCSymbolData *A_SD = &Asm.getSymbolData(*A); + + if (!A_SD->getFragment()) + report_fatal_error("symbol '" + A->getName() + + "' can not be undefined in a subtraction expression"); + + uint32_t Value = getSymbolAddress(A_SD, Layout); + uint32_t Value2 = 0; + uint64_t SecAddr = getSectionAddress(A_SD->getFragment()->getParent()); + FixedValue += SecAddr; + + if (const MCSymbolRefExpr *B = Target.getSymB()) { + MCSymbolData *B_SD = &Asm.getSymbolData(B->getSymbol()); + + if (!B_SD->getFragment()) + report_fatal_error("symbol '" + B->getSymbol().getName() + + "' can not be undefined in a subtraction expression"); + + // Select the appropriate difference relocation type. + Type = macho::RIT_ARM_HalfDifference; + Value2 = getSymbolAddress(B_SD, Layout); + FixedValue -= getSectionAddress(B_SD->getFragment()->getParent()); + } + + // Relocations are written out in reverse order, so the PAIR comes first. + // ARM_RELOC_HALF and ARM_RELOC_HALF_SECTDIFF abuse the r_length field: + // + // For these two r_type relocations they always have a pair following them + // and the r_length bits are used differently. The encoding of the + // r_length is as follows: + // low bit of r_length: + // 0 - :lower16: for movw instructions + // 1 - :upper16: for movt instructions + // high bit of r_length: + // 0 - arm instructions + // 1 - thumb instructions + // the other half of the relocated expression is in the following pair + // relocation entry in the the low 16 bits of r_address field. + unsigned ThumbBit = 0; + unsigned MovtBit = 0; + switch (Fixup.getKind()) { + default: break; + case ARM::fixup_arm_movt_hi16: + case ARM::fixup_arm_movt_hi16_pcrel: + MovtBit = 1; + break; + case ARM::fixup_t2_movt_hi16: + case ARM::fixup_t2_movt_hi16_pcrel: + MovtBit = 1; + // Fallthrough + case ARM::fixup_t2_movw_lo16: + case ARM::fixup_t2_movw_lo16_pcrel: + ThumbBit = 1; + break; + } + + + if (Type == macho::RIT_ARM_HalfDifference) { + uint32_t OtherHalf = MovtBit + ? (FixedValue & 0xffff) : ((FixedValue & 0xffff0000) >> 16); + + macho::RelocationEntry MRE; + MRE.Word0 = ((OtherHalf << 0) | + (macho::RIT_Pair << 24) | + (MovtBit << 28) | + (ThumbBit << 29) | + (IsPCRel << 30) | + macho::RF_Scattered); + MRE.Word1 = Value2; + Relocations[Fragment->getParent()].push_back(MRE); + } + + macho::RelocationEntry MRE; + MRE.Word0 = ((FixupOffset << 0) | + (Type << 24) | + (MovtBit << 28) | + (ThumbBit << 29) | + (IsPCRel << 30) | + macho::RF_Scattered); MRE.Word1 = Value; Relocations[Fragment->getParent()].push_back(MRE); } @@ -835,7 +875,7 @@ public: const MCFixup &Fixup, MCValue Target, uint64_t &FixedValue) { assert(Target.getSymA()->getKind() == MCSymbolRefExpr::VK_TLVP && - !Is64Bit && + !is64Bit() && "Should only be called with a 32-bit TLVP relocation!"); unsigned Log2Size = getFixupKindLog2Size(Fixup.getKind()); @@ -853,10 +893,10 @@ public: if (Target.getSymB()) { // If this is a subtraction then we're pcrel. uint32_t FixupAddress = - Layout.getFragmentAddress(Fragment) + Fixup.getOffset(); + getFragmentAddress(Fragment, Layout) + Fixup.getOffset(); MCSymbolData *SD_B = &Asm.getSymbolData(Target.getSymB()->getSymbol()); IsPCRel = 1; - FixedValue = (FixupAddress - Layout.getSymbolAddress(SD_B) + + FixedValue = (FixupAddress - getSymbolAddress(SD_B, Layout) + Target.getConstant()); FixedValue += 1ULL << Log2Size; } else { @@ -864,25 +904,192 @@ public: } // struct relocation_info (8 bytes) - MachRelocationEntry MRE; + macho::RelocationEntry MRE; MRE.Word0 = Value; + MRE.Word1 = ((Index << 0) | + (IsPCRel << 24) | + (Log2Size << 25) | + (1 << 27) | // Extern + (macho::RIT_Generic_TLV << 28)); // Type + Relocations[Fragment->getParent()].push_back(MRE); + } + + static bool getARMFixupKindMachOInfo(unsigned Kind, unsigned &RelocType, + unsigned &Log2Size) { + RelocType = unsigned(macho::RIT_Vanilla); + Log2Size = ~0U; + + switch (Kind) { + default: + return false; + + case FK_Data_1: + Log2Size = llvm::Log2_32(1); + return true; + case FK_Data_2: + Log2Size = llvm::Log2_32(2); + return true; + case FK_Data_4: + Log2Size = llvm::Log2_32(4); + return true; + case FK_Data_8: + Log2Size = llvm::Log2_32(8); + return true; + + // Handle 24-bit branch kinds. + case ARM::fixup_arm_ldst_pcrel_12: + case ARM::fixup_arm_pcrel_10: + case ARM::fixup_arm_adr_pcrel_12: + case ARM::fixup_arm_condbranch: + case ARM::fixup_arm_uncondbranch: + RelocType = unsigned(macho::RIT_ARM_Branch24Bit); + // Report as 'long', even though that is not quite accurate. + Log2Size = llvm::Log2_32(4); + return true; + + // Handle Thumb branches. + case ARM::fixup_arm_thumb_br: + RelocType = unsigned(macho::RIT_ARM_ThumbBranch22Bit); + Log2Size = llvm::Log2_32(2); + return true; + + case ARM::fixup_arm_thumb_bl: + RelocType = unsigned(macho::RIT_ARM_ThumbBranch32Bit); + Log2Size = llvm::Log2_32(4); + return true; + + case ARM::fixup_arm_thumb_blx: + RelocType = unsigned(macho::RIT_ARM_ThumbBranch22Bit); + // Report as 'long', even though that is not quite accurate. + Log2Size = llvm::Log2_32(4); + return true; + + case ARM::fixup_arm_movt_hi16: + case ARM::fixup_arm_movt_hi16_pcrel: + case ARM::fixup_t2_movt_hi16: + case ARM::fixup_t2_movt_hi16_pcrel: + RelocType = unsigned(macho::RIT_ARM_HalfDifference); + // Report as 'long', even though that is not quite accurate. + Log2Size = llvm::Log2_32(4); + return true; + + case ARM::fixup_arm_movw_lo16: + case ARM::fixup_arm_movw_lo16_pcrel: + case ARM::fixup_t2_movw_lo16: + case ARM::fixup_t2_movw_lo16_pcrel: + RelocType = unsigned(macho::RIT_ARM_Half); + // Report as 'long', even though that is not quite accurate. + Log2Size = llvm::Log2_32(4); + return true; + } + } + void RecordARMRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout, + const MCFragment *Fragment, const MCFixup &Fixup, + MCValue Target, uint64_t &FixedValue) { + unsigned IsPCRel = isFixupKindPCRel(Asm, Fixup.getKind()); + unsigned Log2Size; + unsigned RelocType = macho::RIT_Vanilla; + if (!getARMFixupKindMachOInfo(Fixup.getKind(), RelocType, Log2Size)) { + report_fatal_error("unknown ARM fixup kind!"); + return; + } + + // If this is a difference or a defined symbol plus an offset, then we need + // a scattered relocation entry. Differences always require scattered + // relocations. + if (Target.getSymB()) { + if (RelocType == macho::RIT_ARM_Half || + RelocType == macho::RIT_ARM_HalfDifference) + return RecordARMMovwMovtRelocation(Asm, Layout, Fragment, Fixup, + Target, FixedValue); + return RecordARMScatteredRelocation(Asm, Layout, Fragment, Fixup, + Target, Log2Size, FixedValue); + } + + // Get the symbol data, if any. + MCSymbolData *SD = 0; + if (Target.getSymA()) + SD = &Asm.getSymbolData(Target.getSymA()->getSymbol()); + + // FIXME: For other platforms, we need to use scattered relocations for + // internal relocations with offsets. If this is an internal relocation + // with an offset, it also needs a scattered relocation entry. + // + // Is this right for ARM? + uint32_t Offset = Target.getConstant(); + if (IsPCRel && RelocType == macho::RIT_Vanilla) + Offset += 1 << Log2Size; + if (Offset && SD && !doesSymbolRequireExternRelocation(SD)) + return RecordARMScatteredRelocation(Asm, Layout, Fragment, Fixup, Target, + Log2Size, FixedValue); + + // See . + uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset(); + unsigned Index = 0; + unsigned IsExtern = 0; + unsigned Type = 0; + + if (Target.isAbsolute()) { // constant + // FIXME! + report_fatal_error("FIXME: relocations to absolute targets " + "not yet implemented"); + } else if (SD->getSymbol().isVariable()) { + int64_t Res; + if (SD->getSymbol().getVariableValue()->EvaluateAsAbsolute( + Res, Layout, SectionAddress)) { + FixedValue = Res; + return; + } + + report_fatal_error("unsupported relocation of variable '" + + SD->getSymbol().getName() + "'"); + } else { + // Check whether we need an external or internal relocation. + if (doesSymbolRequireExternRelocation(SD)) { + IsExtern = 1; + Index = SD->getIndex(); + // For external relocations, make sure to offset the fixup value to + // compensate for the addend of the symbol address, if it was + // undefined. This occurs with weak definitions, for example. + if (!SD->Symbol->isUndefined()) + FixedValue -= Layout.getSymbolOffset(SD); + } else { + // The index is the section ordinal (1-based). + Index = SD->getFragment()->getParent()->getOrdinal() + 1; + FixedValue += getSectionAddress(SD->getFragment()->getParent()); + } + if (IsPCRel) + FixedValue -= getSectionAddress(Fragment->getParent()); + + // The type is determined by the fixup kind. + Type = RelocType; + } + + // struct relocation_info (8 bytes) + macho::RelocationEntry MRE; + MRE.Word0 = FixupOffset; MRE.Word1 = ((Index << 0) | (IsPCRel << 24) | (Log2Size << 25) | - (1 << 27) | // Extern - (RIT_TLV << 28)); // Type + (IsExtern << 27) | + (Type << 28)); Relocations[Fragment->getParent()].push_back(MRE); } void RecordRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout, const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target, uint64_t &FixedValue) { - if (Is64Bit) { + // FIXME: These needs to be factored into the target Mach-O writer. + if (isARM()) { + RecordARMRelocation(Asm, Layout, Fragment, Fixup, Target, FixedValue); + return; + } + if (is64Bit()) { RecordX86_64Relocation(Asm, Layout, Fragment, Fixup, Target, FixedValue); return; } - unsigned IsPCRel = isFixupKindPCRel(Fixup.getKind()); + unsigned IsPCRel = isFixupKindPCRel(Asm, Fixup.getKind()); unsigned Log2Size = getFixupKindLog2Size(Fixup.getKind()); // If this is a 32-bit TLVP reloc it's handled a bit differently. @@ -897,7 +1104,7 @@ public: // Differences always require scattered relocations. if (Target.getSymB()) return RecordScatteredRelocation(Asm, Layout, Fragment, Fixup, - Target, FixedValue); + Target, Log2Size, FixedValue); // Get the symbol data, if any. MCSymbolData *SD = 0; @@ -911,7 +1118,7 @@ public: Offset += 1 << Log2Size; if (Offset && SD && !doesSymbolRequireExternRelocation(SD)) return RecordScatteredRelocation(Asm, Layout, Fragment, Fixup, - Target, FixedValue); + Target, Log2Size, FixedValue); // See . uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset(); @@ -924,7 +1131,17 @@ public: // // FIXME: Currently, these are never generated (see code below). I cannot // find a case where they are actually emitted. - Type = RIT_Vanilla; + Type = macho::RIT_Vanilla; + } else if (SD->getSymbol().isVariable()) { + int64_t Res; + if (SD->getSymbol().getVariableValue()->EvaluateAsAbsolute( + Res, Layout, SectionAddress)) { + FixedValue = Res; + return; + } + + report_fatal_error("unsupported relocation of variable '" + + SD->getSymbol().getName() + "'"); } else { // Check whether we need an external or internal relocation. if (doesSymbolRequireExternRelocation(SD)) { @@ -934,17 +1151,20 @@ public: // compensate for the addend of the symbol address, if it was // undefined. This occurs with weak definitions, for example. if (!SD->Symbol->isUndefined()) - FixedValue -= Layout.getSymbolAddress(SD); + FixedValue -= Layout.getSymbolOffset(SD); } else { // The index is the section ordinal (1-based). Index = SD->getFragment()->getParent()->getOrdinal() + 1; + FixedValue += getSectionAddress(SD->getFragment()->getParent()); } + if (IsPCRel) + FixedValue -= getSectionAddress(Fragment->getParent()); - Type = RIT_Vanilla; + Type = macho::RIT_Vanilla; } // struct relocation_info (8 bytes) - MachRelocationEntry MRE; + macho::RelocationEntry MRE; MRE.Word0 = FixupOffset; MRE.Word1 = ((Index << 0) | (IsPCRel << 24) | @@ -1118,7 +1338,25 @@ public: StringTable += '\x00'; } - void ExecutePostLayoutBinding(MCAssembler &Asm) { + void computeSectionAddresses(const MCAssembler &Asm, + const MCAsmLayout &Layout) { + uint64_t StartAddress = 0; + const SmallVectorImpl &Order = Layout.getSectionOrder(); + for (int i = 0, n = Order.size(); i != n ; ++i) { + const MCSectionData *SD = Order[i]; + StartAddress = RoundUpToAlignment(StartAddress, SD->getAlignment()); + SectionAddress[SD] = StartAddress; + StartAddress += Layout.getSectionAddressSize(SD); + // Explicitly pad the section to match the alignment requirements of the + // following one. This is for 'gas' compatibility, it shouldn't + /// strictly be necessary. + StartAddress += getPaddingSize(SD, Layout); + } + } + + void ExecutePostLayoutBinding(MCAssembler &Asm, const MCAsmLayout &Layout) { + computeSectionAddresses(Asm, Layout); + // Create symbol data for any indirect symbols. BindIndirectSymbols(Asm); @@ -1127,34 +1365,62 @@ public: UndefinedSymbolData); } + virtual bool IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, + const MCSymbolData &DataA, + const MCFragment &FB, + bool InSet, + bool IsPCRel) const { + if (InSet) + return true; + + // The effective address is + // addr(atom(A)) + offset(A) + // - addr(atom(B)) - offset(B) + // and the offsets are not relocatable, so the fixup is fully resolved when + // addr(atom(A)) - addr(atom(B)) == 0. + const MCSymbolData *A_Base = 0, *B_Base = 0; + + const MCSymbol &SA = DataA.getSymbol().AliasedSymbol(); + const MCSection &SecA = SA.getSection(); + const MCSection &SecB = FB.getParent()->getSection(); - bool IsFixupFullyResolved(const MCAssembler &Asm, - const MCValue Target, - bool IsPCRel, - const MCFragment *DF) const { - // If we are using scattered symbols, determine whether this value is - // actually resolved; scattering may cause atoms to move. - if (Asm.getBackend().hasScatteredSymbols()) { - if (Asm.getBackend().hasReliableSymbolDifference()) { - // If this is a PCrel relocation, find the base atom (identified by its - // symbol) that the fixup value is relative to. - const MCSymbolData *BaseSymbol = 0; - if (IsPCRel) { - BaseSymbol = DF->getAtom(); - if (!BaseSymbol) - return false; - } - - return isScatteredFixupFullyResolved(Asm, Target, BaseSymbol); - } else { - const MCSection *BaseSection = 0; - if (IsPCRel) - BaseSection = &DF->getParent()->getSection(); - - return isScatteredFixupFullyResolvedSimple(Asm, Target, BaseSection); + if (IsPCRel) { + // The simple (Darwin, except on x86_64) way of dealing with this was to + // assume that any reference to a temporary symbol *must* be a temporary + // symbol in the same atom, unless the sections differ. Therefore, any + // PCrel relocation to a temporary symbol (in the same section) is fully + // resolved. This also works in conjunction with absolutized .set, which + // requires the compiler to use .set to absolutize the differences between + // symbols which the compiler knows to be assembly time constants, so we + // don't need to worry about considering symbol differences fully + // resolved. + + if (!Asm.getBackend().hasReliableSymbolDifference()) { + if (!SA.isTemporary() || !SA.isInSection() || &SecA != &SecB) + return false; + return true; } + } else { + if (!TargetObjectWriter->useAggressiveSymbolFolding()) + return false; } - return true; + + const MCFragment &FA = *Asm.getSymbolData(SA).getFragment(); + + A_Base = FA.getAtom(); + if (!A_Base) + return false; + + B_Base = FB.getAtom(); + if (!B_Base) + return false; + + // If the atoms are the same, they are guaranteed to have the same address. + if (A_Base == B_Base) + return true; + + // Otherwise, we can't prove this is fully resolved. + return false; } void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout) { @@ -1163,35 +1429,37 @@ public: // The section data starts after the header, the segment load command (and // section headers) and the symbol table. unsigned NumLoadCommands = 1; - uint64_t LoadCommandsSize = Is64Bit ? - SegmentLoadCommand64Size + NumSections * Section64Size : - SegmentLoadCommand32Size + NumSections * Section32Size; + uint64_t LoadCommandsSize = is64Bit() ? + macho::SegmentLoadCommand64Size + NumSections * macho::Section64Size : + macho::SegmentLoadCommand32Size + NumSections * macho::Section32Size; // Add the symbol table load command sizes, if used. unsigned NumSymbols = LocalSymbolData.size() + ExternalSymbolData.size() + UndefinedSymbolData.size(); if (NumSymbols) { NumLoadCommands += 2; - LoadCommandsSize += SymtabLoadCommandSize + DysymtabLoadCommandSize; + LoadCommandsSize += (macho::SymtabLoadCommandSize + + macho::DysymtabLoadCommandSize); } // Compute the total size of the section data, as well as its file size and // vm size. - uint64_t SectionDataStart = (Is64Bit ? Header64Size : Header32Size) - + LoadCommandsSize; + uint64_t SectionDataStart = (is64Bit() ? macho::Header64Size : + macho::Header32Size) + LoadCommandsSize; uint64_t SectionDataSize = 0; uint64_t SectionDataFileSize = 0; uint64_t VMSize = 0; for (MCAssembler::const_iterator it = Asm.begin(), ie = Asm.end(); it != ie; ++it) { const MCSectionData &SD = *it; - uint64_t Address = Layout.getSectionAddress(&SD); - uint64_t Size = Layout.getSectionSize(&SD); + uint64_t Address = getSectionAddress(&SD); + uint64_t Size = Layout.getSectionAddressSize(&SD); uint64_t FileSize = Layout.getSectionFileSize(&SD); + FileSize += getPaddingSize(&SD, Layout); VMSize = std::max(VMSize, Address + Size); - if (Asm.getBackend().isVirtualSection(SD.getSection())) + if (SD.getSection().isVirtualSection()) continue; SectionDataSize = std::max(SectionDataSize, Address + Size); @@ -1214,11 +1482,11 @@ public: uint64_t RelocTableEnd = SectionDataStart + SectionDataFileSize; for (MCAssembler::const_iterator it = Asm.begin(), ie = Asm.end(); it != ie; ++it) { - std::vector &Relocs = Relocations[it]; + std::vector &Relocs = Relocations[it]; unsigned NumRelocs = Relocs.size(); - uint64_t SectionStart = SectionDataStart + Layout.getSectionAddress(it); + uint64_t SectionStart = SectionDataStart + getSectionAddress(it); WriteSection(Asm, Layout, *it, SectionStart, RelocTableEnd, NumRelocs); - RelocTableEnd += NumRelocs * RelocationInfoSize; + RelocTableEnd += NumRelocs * macho::RelocationInfoSize; } // Write the symbol table load command, if used. @@ -1244,8 +1512,8 @@ public: // The string table is written after symbol table. uint64_t StringTableOffset = - SymbolTableOffset + NumSymTabSymbols * (Is64Bit ? Nlist64Size : - Nlist32Size); + SymbolTableOffset + NumSymTabSymbols * (is64Bit() ? macho::Nlist64Size : + macho::Nlist32Size); WriteSymtabLoadCommand(SymbolTableOffset, NumSymTabSymbols, StringTableOffset, StringTable.size()); @@ -1257,8 +1525,13 @@ public: // Write the actual section data. for (MCAssembler::const_iterator it = Asm.begin(), - ie = Asm.end(); it != ie; ++it) - Asm.WriteSectionData(it, Layout, this); + ie = Asm.end(); it != ie; ++it) { + Asm.WriteSectionData(it, Layout); + + uint64_t Pad = getPaddingSize(it, Layout); + for (unsigned int i = 0; i < Pad; ++i) + Write8(0); + } // Write the extra padding. WriteZeros(SectionDataPadding); @@ -1268,7 +1541,7 @@ public: ie = Asm.end(); it != ie; ++it) { // Write the section relocation entries, in reverse order to match 'as' // (approximately, the exact algorithm is more complicated than this). - std::vector &Relocs = Relocations[it]; + std::vector &Relocs = Relocations[it]; for (unsigned i = 0, e = Relocs.size(); i != e; ++i) { Write32(Relocs[e - i - 1].Word0); Write32(Relocs[e - i - 1].Word1); @@ -1289,9 +1562,9 @@ public: // If this symbol is defined and internal, mark it as such. if (it->Symbol->isDefined() && !Asm.getSymbolData(*it->Symbol).isExternal()) { - uint32_t Flags = ISF_Local; + uint32_t Flags = macho::ISF_Local; if (it->Symbol->isAbsolute()) - Flags |= ISF_Absolute; + Flags |= macho::ISF_Absolute; Write32(Flags); continue; } @@ -1318,9 +1591,8 @@ public: } -MCObjectWriter *llvm::createMachObjectWriter(raw_ostream &OS, bool is64Bit, - uint32_t CPUType, - uint32_t CPUSubtype, +MCObjectWriter *llvm::createMachObjectWriter(MCMachObjectTargetWriter *MOTW, + raw_ostream &OS, bool IsLittleEndian) { - return new MachObjectWriter(OS, is64Bit, CPUType, CPUSubtype, IsLittleEndian); + return new MachObjectWriter(MOTW, OS, IsLittleEndian); }