diff options
author | Jush Lu <jush.msn@gmail.com> | 2011-03-09 19:39:16 +0800 |
---|---|---|
committer | Jush Lu <jush.msn@gmail.com> | 2011-03-09 19:39:16 +0800 |
commit | b5530586d68bd25831a6796b5d3199cb0769a35c (patch) | |
tree | fac4a03b53b6a64b0c00f433e4d8b3c9f2bc67cd /lib/MC/ELFObjectWriter.cpp | |
parent | b4e17c5bf4361bbdeced39aa071150d7fa9c3c10 (diff) | |
parent | d01f50f42ce60207ed6d27fb1778e456d83be06c (diff) | |
download | external_llvm-b5530586d68bd25831a6796b5d3199cb0769a35c.zip external_llvm-b5530586d68bd25831a6796b5d3199cb0769a35c.tar.gz external_llvm-b5530586d68bd25831a6796b5d3199cb0769a35c.tar.bz2 |
Merge upstream r127116
Diffstat (limited to 'lib/MC/ELFObjectWriter.cpp')
-rw-r--r-- | lib/MC/ELFObjectWriter.cpp | 1062 |
1 files changed, 487 insertions, 575 deletions
diff --git a/lib/MC/ELFObjectWriter.cpp b/lib/MC/ELFObjectWriter.cpp index b15c2d4..3492cbc 100644 --- a/lib/MC/ELFObjectWriter.cpp +++ b/lib/MC/ELFObjectWriter.cpp @@ -11,73 +11,35 @@ // //===----------------------------------------------------------------------===// -#include "llvm/ADT/SmallPtrSet.h" +#include "ELFObjectWriter.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/Twine.h" -#include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCAsmLayout.h" #include "llvm/MC/MCContext.h" -#include "llvm/MC/MCELFSymbolFlags.h" #include "llvm/MC/MCExpr.h" -#include "llvm/MC/MCObjectWriter.h" #include "llvm/MC/MCSectionELF.h" -#include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCValue.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ELF.h" #include "llvm/Target/TargetAsmBackend.h" +#include "llvm/ADT/StringSwitch.h" #include "../Target/X86/X86FixupKinds.h" +#include "../Target/ARM/ARMFixupKinds.h" #include <vector> using namespace llvm; -static unsigned GetType(const MCSymbolData &SD) { - uint32_t Type = (SD.getFlags() & (0xf << ELF_STT_Shift)) >> ELF_STT_Shift; - assert(Type == ELF::STT_NOTYPE || Type == ELF::STT_OBJECT || - Type == ELF::STT_FUNC || Type == ELF::STT_SECTION || - Type == ELF::STT_FILE || Type == ELF::STT_COMMON || - Type == ELF::STT_TLS); - return Type; -} - -static unsigned GetBinding(const MCSymbolData &SD) { - uint32_t Binding = (SD.getFlags() & (0xf << ELF_STB_Shift)) >> ELF_STB_Shift; - assert(Binding == ELF::STB_LOCAL || Binding == ELF::STB_GLOBAL || - Binding == ELF::STB_WEAK); - return Binding; -} - -static void SetBinding(MCSymbolData &SD, unsigned Binding) { - assert(Binding == ELF::STB_LOCAL || Binding == ELF::STB_GLOBAL || - Binding == ELF::STB_WEAK); - uint32_t OtherFlags = SD.getFlags() & ~(0xf << ELF_STB_Shift); - SD.setFlags(OtherFlags | (Binding << ELF_STB_Shift)); -} +bool ELFObjectWriter::isFixupKindPCRel(const MCAssembler &Asm, unsigned Kind) { + const MCFixupKindInfo &FKI = + Asm.getBackend().getFixupKindInfo((MCFixupKind) Kind); -static unsigned GetVisibility(MCSymbolData &SD) { - unsigned Visibility = - (SD.getFlags() & (0xf << ELF_STV_Shift)) >> ELF_STV_Shift; - assert(Visibility == ELF::STV_DEFAULT || Visibility == ELF::STV_INTERNAL || - Visibility == ELF::STV_HIDDEN || Visibility == ELF::STV_PROTECTED); - return Visibility; + return FKI.Flags & MCFixupKindInfo::FKF_IsPCRel; } -static bool isFixupKindX86PCRel(unsigned Kind) { - switch (Kind) { - default: - return false; - case X86::reloc_pcrel_1byte: - case X86::reloc_pcrel_4byte: - case X86::reloc_riprel_4byte: - case X86::reloc_riprel_4byte_movq_load: - return true; - } -} - -static bool RelocNeedsGOT(MCSymbolRefExpr::VariantKind Variant) { +bool ELFObjectWriter::RelocNeedsGOT(MCSymbolRefExpr::VariantKind Variant) { switch (Variant) { default: return false; @@ -97,294 +59,6 @@ static bool RelocNeedsGOT(MCSymbolRefExpr::VariantKind Variant) { } } -namespace { - class ELFObjectWriter : public MCObjectWriter { - protected: - /*static bool isFixupKindX86RIPRel(unsigned Kind) { - return Kind == X86::reloc_riprel_4byte || - Kind == X86::reloc_riprel_4byte_movq_load; - }*/ - - - /// ELFSymbolData - Helper struct for containing some precomputed information - /// on symbols. - struct ELFSymbolData { - MCSymbolData *SymbolData; - uint64_t StringIndex; - uint32_t SectionIndex; - - // Support lexicographic sorting. - bool operator<(const ELFSymbolData &RHS) const { - if (GetType(*SymbolData) == ELF::STT_FILE) - return true; - if (GetType(*RHS.SymbolData) == ELF::STT_FILE) - return false; - return SymbolData->getSymbol().getName() < - RHS.SymbolData->getSymbol().getName(); - } - }; - - /// @name Relocation Data - /// @{ - - struct ELFRelocationEntry { - // Make these big enough for both 32-bit and 64-bit - uint64_t r_offset; - int Index; - unsigned Type; - const MCSymbol *Symbol; - uint64_t r_addend; - - // Support lexicographic sorting. - bool operator<(const ELFRelocationEntry &RE) const { - return RE.r_offset < r_offset; - } - }; - - SmallPtrSet<const MCSymbol *, 16> UsedInReloc; - SmallPtrSet<const MCSymbol *, 16> WeakrefUsedInReloc; - DenseMap<const MCSymbol *, const MCSymbol *> Renames; - - llvm::DenseMap<const MCSectionData*, - std::vector<ELFRelocationEntry> > Relocations; - DenseMap<const MCSection*, uint64_t> SectionStringTableIndex; - - /// @} - /// @name Symbol Table Data - /// @{ - - SmallString<256> StringTable; - std::vector<ELFSymbolData> LocalSymbolData; - std::vector<ELFSymbolData> ExternalSymbolData; - std::vector<ELFSymbolData> UndefinedSymbolData; - - /// @} - - bool NeedsGOT; - - bool NeedsSymtabShndx; - - unsigned Is64Bit : 1; - - bool HasRelocationAddend; - - Triple::OSType OSType; - - uint16_t EMachine; - - // This holds the symbol table index of the last local symbol. - unsigned LastLocalSymbolIndex; - // This holds the .strtab section index. - unsigned StringTableIndex; - // This holds the .symtab section index. - unsigned SymbolTableIndex; - - unsigned ShstrtabIndex; - - - const MCSymbol *SymbolToReloc(const MCAssembler &Asm, - const MCValue &Target, - const MCFragment &F) const; - - public: - ELFObjectWriter(raw_ostream &_OS, bool _Is64Bit, bool IsLittleEndian, - uint16_t _EMachine, bool _HasRelAddend, - Triple::OSType _OSType) - : MCObjectWriter(_OS, IsLittleEndian), - NeedsGOT(false), NeedsSymtabShndx(false), - Is64Bit(_Is64Bit), HasRelocationAddend(_HasRelAddend), - OSType(_OSType), EMachine(_EMachine) { - } - - virtual ~ELFObjectWriter(); - - void WriteWord(uint64_t W) { - if (Is64Bit) - Write64(W); - else - Write32(W); - } - - void StringLE16(char *buf, uint16_t Value) { - buf[0] = char(Value >> 0); - buf[1] = char(Value >> 8); - } - - void StringLE32(char *buf, uint32_t Value) { - StringLE16(buf, uint16_t(Value >> 0)); - StringLE16(buf + 2, uint16_t(Value >> 16)); - } - - void StringLE64(char *buf, uint64_t Value) { - StringLE32(buf, uint32_t(Value >> 0)); - StringLE32(buf + 4, uint32_t(Value >> 32)); - } - - void StringBE16(char *buf ,uint16_t Value) { - buf[0] = char(Value >> 8); - buf[1] = char(Value >> 0); - } - - void StringBE32(char *buf, uint32_t Value) { - StringBE16(buf, uint16_t(Value >> 16)); - StringBE16(buf + 2, uint16_t(Value >> 0)); - } - - void StringBE64(char *buf, uint64_t Value) { - StringBE32(buf, uint32_t(Value >> 32)); - StringBE32(buf + 4, uint32_t(Value >> 0)); - } - - void String8(MCDataFragment &F, uint8_t Value) { - char buf[1]; - buf[0] = Value; - F.getContents() += StringRef(buf, 1); - } - - void String16(MCDataFragment &F, uint16_t Value) { - char buf[2]; - if (isLittleEndian()) - StringLE16(buf, Value); - else - StringBE16(buf, Value); - F.getContents() += StringRef(buf, 2); - } - - void String32(MCDataFragment &F, uint32_t Value) { - char buf[4]; - if (isLittleEndian()) - StringLE32(buf, Value); - else - StringBE32(buf, Value); - F.getContents() += StringRef(buf, 4); - } - - void String64(MCDataFragment &F, uint64_t Value) { - char buf[8]; - if (isLittleEndian()) - StringLE64(buf, Value); - else - StringBE64(buf, Value); - F.getContents() += StringRef(buf, 8); - } - - virtual void WriteHeader(uint64_t SectionDataSize, unsigned NumberOfSections); - - virtual void WriteSymbolEntry(MCDataFragment *SymtabF, MCDataFragment *ShndxF, - uint64_t name, uint8_t info, - uint64_t value, uint64_t size, - uint8_t other, uint32_t shndx, - bool Reserved); - - virtual void WriteSymbol(MCDataFragment *SymtabF, MCDataFragment *ShndxF, - ELFSymbolData &MSD, - const MCAsmLayout &Layout); - - typedef DenseMap<const MCSectionELF*, uint32_t> SectionIndexMapTy; - virtual void WriteSymbolTable(MCDataFragment *SymtabF, MCDataFragment *ShndxF, - const MCAssembler &Asm, - const MCAsmLayout &Layout, - const SectionIndexMapTy &SectionIndexMap); - - virtual void RecordRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout, - const MCFragment *Fragment, const MCFixup &Fixup, - MCValue Target, uint64_t &FixedValue) { - assert(0 && "RecordRelocation is not specific enough"); - } - - virtual uint64_t getSymbolIndexInSymbolTable(const MCAssembler &Asm, - const MCSymbol *S); - - // Map from a group section to the signature symbol - typedef DenseMap<const MCSectionELF*, const MCSymbol*> GroupMapTy; - // Map from a signature symbol to the group section - typedef DenseMap<const MCSymbol*, const MCSectionELF*> RevGroupMapTy; - - /// ComputeSymbolTable - Compute the symbol table data - /// - /// \param StringTable [out] - The string table data. - /// \param StringIndexMap [out] - Map from symbol names to offsets in the - /// string table. - virtual void ComputeSymbolTable(MCAssembler &Asm, - const SectionIndexMapTy &SectionIndexMap, - RevGroupMapTy RevGroupMap); - - virtual void ComputeIndexMap(MCAssembler &Asm, - SectionIndexMapTy &SectionIndexMap); - - virtual void WriteRelocation(MCAssembler &Asm, MCAsmLayout &Layout, - const MCSectionData &SD); - - virtual void WriteRelocations(MCAssembler &Asm, MCAsmLayout &Layout) { - for (MCAssembler::const_iterator it = Asm.begin(), - ie = Asm.end(); it != ie; ++it) { - WriteRelocation(Asm, Layout, *it); - } - } - - virtual void CreateMetadataSections(MCAssembler &Asm, MCAsmLayout &Layout, - const SectionIndexMapTy &SectionIndexMap); - - virtual void CreateGroupSections(MCAssembler &Asm, MCAsmLayout &Layout, - GroupMapTy &GroupMap, RevGroupMapTy &RevGroupMap); - - virtual void ExecutePostLayoutBinding(MCAssembler &Asm); - - virtual void WriteSecHdrEntry(uint32_t Name, uint32_t Type, uint64_t Flags, - uint64_t Address, uint64_t Offset, - uint64_t Size, uint32_t Link, uint32_t Info, - uint64_t Alignment, uint64_t EntrySize); - - virtual void WriteRelocationsFragment(const MCAssembler &Asm, MCDataFragment *F, - const MCSectionData *SD); - - virtual bool IsFixupFullyResolved(const MCAssembler &Asm, - const MCValue Target, - bool IsPCRel, - const MCFragment *DF) const; - - virtual void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout); - virtual void WriteSection(MCAssembler &Asm, - const SectionIndexMapTy &SectionIndexMap, - uint32_t GroupSymbolIndex, - uint64_t Offset, uint64_t Size, uint64_t Alignment, - const MCSectionELF &Section); - }; - - //===- X86ELFObjectWriter -------------------------------------------===// - - class X86ELFObjectWriter : public ELFObjectWriter { - public: - X86ELFObjectWriter(raw_ostream &_OS, bool _Is64Bit, bool IsLittleEndian, - uint16_t _EMachine, bool _HasRelAddend, - Triple::OSType _OSType); - - virtual ~X86ELFObjectWriter(); - virtual void RecordRelocation(const MCAssembler &Asm, - const MCAsmLayout &Layout, - const MCFragment *Fragment, - const MCFixup &Fixup, MCValue Target, - uint64_t &FixedValue); - }; - - - //===- ARMELFObjectWriter -------------------------------------------===// - - class ARMELFObjectWriter : public ELFObjectWriter { - public: - ARMELFObjectWriter(raw_ostream &_OS, bool _Is64Bit, bool IsLittleEndian, - uint16_t _EMachine, bool _HasRelAddend, - Triple::OSType _OSType); - - virtual ~ARMELFObjectWriter(); - virtual void RecordRelocation(const MCAssembler &Asm, - const MCAsmLayout &Layout, - const MCFragment *Fragment, - const MCFixup &Fixup, MCValue Target, - uint64_t &FixedValue); - }; -} - ELFObjectWriter::~ELFObjectWriter() {} @@ -404,14 +78,14 @@ void ELFObjectWriter::WriteHeader(uint64_t SectionDataSize, Write8('L'); // e_ident[EI_MAG2] Write8('F'); // e_ident[EI_MAG3] - Write8(Is64Bit ? ELF::ELFCLASS64 : ELF::ELFCLASS32); // e_ident[EI_CLASS] + Write8(is64Bit() ? ELF::ELFCLASS64 : ELF::ELFCLASS32); // e_ident[EI_CLASS] // e_ident[EI_DATA] Write8(isLittleEndian() ? ELF::ELFDATA2LSB : ELF::ELFDATA2MSB); Write8(ELF::EV_CURRENT); // e_ident[EI_VERSION] // e_ident[EI_OSABI] - switch (OSType) { + switch (TargetObjectWriter->getOSType()) { case Triple::FreeBSD: Write8(ELF::ELFOSABI_FREEBSD); break; case Triple::Linux: Write8(ELF::ELFOSABI_LINUX); break; default: Write8(ELF::ELFOSABI_NONE); break; @@ -422,25 +96,25 @@ void ELFObjectWriter::WriteHeader(uint64_t SectionDataSize, Write16(ELF::ET_REL); // e_type - Write16(EMachine); // e_machine = target + Write16(TargetObjectWriter->getEMachine()); // e_machine = target Write32(ELF::EV_CURRENT); // e_version WriteWord(0); // e_entry, no entry point in .o file WriteWord(0); // e_phoff, no program header for .o - WriteWord(SectionDataSize + (Is64Bit ? sizeof(ELF::Elf64_Ehdr) : + WriteWord(SectionDataSize + (is64Bit() ? sizeof(ELF::Elf64_Ehdr) : sizeof(ELF::Elf32_Ehdr))); // e_shoff = sec hdr table off in bytes - // FIXME: Make this configurable. - Write32(0); // e_flags = whatever the target wants + // e_flags = whatever the target wants + WriteEFlags(); // e_ehsize = ELF header size - Write16(Is64Bit ? sizeof(ELF::Elf64_Ehdr) : sizeof(ELF::Elf32_Ehdr)); + Write16(is64Bit() ? sizeof(ELF::Elf64_Ehdr) : sizeof(ELF::Elf32_Ehdr)); Write16(0); // e_phentsize = prog header entry size Write16(0); // e_phnum = # prog header entries = 0 // e_shentsize = Section header entry size - Write16(Is64Bit ? sizeof(ELF::Elf64_Shdr) : sizeof(ELF::Elf32_Shdr)); + Write16(is64Bit() ? sizeof(ELF::Elf64_Shdr) : sizeof(ELF::Elf32_Shdr)); // e_shnum = # of section header ents if (NumberOfSections >= ELF::SHN_LORESERVE) @@ -472,7 +146,7 @@ void ELFObjectWriter::WriteSymbolEntry(MCDataFragment *SymtabF, uint16_t Index = (shndx >= ELF::SHN_LORESERVE && !Reserved) ? uint16_t(ELF::SHN_XINDEX) : shndx; - if (Is64Bit) { + if (is64Bit()) { String32(*SymtabF, name); // st_name String8(*SymtabF, info); // st_info String8(*SymtabF, other); // st_other @@ -489,22 +163,32 @@ void ELFObjectWriter::WriteSymbolEntry(MCDataFragment *SymtabF, } } -static uint64_t SymbolValue(MCSymbolData &Data, const MCAsmLayout &Layout) { +uint64_t ELFObjectWriter::SymbolValue(MCSymbolData &Data, + const MCAsmLayout &Layout) { if (Data.isCommon() && Data.isExternal()) return Data.getCommonAlignment(); const MCSymbol &Symbol = Data.getSymbol(); + + if (Symbol.isAbsolute() && Symbol.isVariable()) { + if (const MCExpr *Value = Symbol.getVariableValue()) { + int64_t IntValue; + if (Value->EvaluateAsAbsolute(IntValue, Layout)) + return (uint64_t)IntValue; + } + } + if (!Symbol.isInSection()) return 0; - if (MCFragment *FF = Data.getFragment()) - return Layout.getSymbolAddress(&Data) - - Layout.getSectionAddress(FF->getParent()); + if (Data.getFragment()) + return Layout.getSymbolOffset(&Data); return 0; } -void ELFObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm) { +void ELFObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm, + const MCAsmLayout &Layout) { // The presence of symbol versions causes undefined symbols and // versions declared with @@@ to be renamed. @@ -526,7 +210,7 @@ void ELFObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm) { // Aliases defined with .symvar copy the binding from the symbol they alias. // This is the first place we are able to copy this information. it->setExternal(SD.isExternal()); - SetBinding(*it, GetBinding(SD)); + MCELF::SetBinding(*it, MCELF::GetBinding(SD)); StringRef Rest = AliasName.substr(Pos); if (!Symbol.isUndefined() && !Rest.startswith("@@@")) @@ -552,35 +236,24 @@ void ELFObjectWriter::WriteSymbol(MCDataFragment *SymtabF, bool IsReserved = Data.isCommon() || Data.getSymbol().isAbsolute() || Data.getSymbol().isVariable(); - uint8_t Binding = GetBinding(OrigData); - uint8_t Visibility = GetVisibility(OrigData); - uint8_t Type = GetType(Data); + uint8_t Binding = MCELF::GetBinding(OrigData); + uint8_t Visibility = MCELF::GetVisibility(OrigData); + uint8_t Type = MCELF::GetType(Data); uint8_t Info = (Binding << ELF_STB_Shift) | (Type << ELF_STT_Shift); uint8_t Other = Visibility; uint64_t Value = SymbolValue(Data, Layout); uint64_t Size = 0; - const MCExpr *ESize; assert(!(Data.isCommon() && !Data.isExternal())); - ESize = Data.getSize(); - if (Data.getSize()) { - MCValue Res; - if (ESize->getKind() == MCExpr::Binary) { - const MCBinaryExpr *BE = static_cast<const MCBinaryExpr *>(ESize); - - if (BE->EvaluateAsRelocatable(Res, &Layout)) { - assert(!Res.getSymA() || !Res.getSymA()->getSymbol().isDefined()); - assert(!Res.getSymB() || !Res.getSymB()->getSymbol().isDefined()); - Size = Res.getConstant(); - } - } else if (ESize->getKind() == MCExpr::Constant) { - Size = static_cast<const MCConstantExpr *>(ESize)->getValue(); - } else { - assert(0 && "Unsupported size expression"); - } + const MCExpr *ESize = Data.getSize(); + if (ESize) { + int64_t Res; + if (!ESize->EvaluateAsAbsolute(Res, Layout)) + report_fatal_error("Size expression must be absolute."); + Size = Res; } // Write out the symbol table entry @@ -631,7 +304,7 @@ void ELFObjectWriter::WriteSymbolTable(MCDataFragment *SymtabF, (Data.getFlags() & ELF_STB_Weak)) && "External symbol requires STB_GLOBAL or STB_WEAK flag"); WriteSymbol(SymtabF, ShndxF, MSD, Layout); - if (GetBinding(Data) == ELF::STB_LOCAL) + if (MCELF::GetBinding(Data) == ELF::STB_LOCAL) LastLocalSymbolIndex++; } @@ -639,7 +312,7 @@ void ELFObjectWriter::WriteSymbolTable(MCDataFragment *SymtabF, ELFSymbolData &MSD = UndefinedSymbolData[i]; MCSymbolData &Data = *MSD.SymbolData; WriteSymbol(SymtabF, ShndxF, MSD, Layout); - if (GetBinding(Data) == ELF::STB_LOCAL) + if (MCELF::GetBinding(Data) == ELF::STB_LOCAL) LastLocalSymbolIndex++; } } @@ -666,9 +339,16 @@ const MCSymbol *ELFObjectWriter::SymbolToReloc(const MCAssembler &Asm, const MCSectionELF &Section = static_cast<const MCSectionELF&>(ASymbol.getSection()); + const SectionKind secKind = Section.getKind(); - if (Section.getKind().isBSS()) - return NULL; + if (secKind.isBSS()) + return ExplicitRelSym(Asm, Target, F, true); + + if (secKind.isThreadLocal()) { + if (Renamed) + return Renamed; + return &Symbol; + } MCSymbolRefExpr::VariantKind Kind = Target.getSymA()->getKind(); const MCSectionELF &Sec2 = @@ -683,7 +363,7 @@ const MCSymbol *ELFObjectWriter::SymbolToReloc(const MCAssembler &Asm, return &Symbol; } - if (Section.getFlags() & MCSectionELF::SHF_MERGE) { + if (Section.getFlags() & ELF::SHF_MERGE) { if (Target.getConstant() == 0) return NULL; if (Renamed) @@ -691,7 +371,72 @@ const MCSymbol *ELFObjectWriter::SymbolToReloc(const MCAssembler &Asm, return &Symbol; } - return NULL; + return ExplicitRelSym(Asm, Target, F, false); +} + + +void ELFObjectWriter::RecordRelocation(const MCAssembler &Asm, + const MCAsmLayout &Layout, + const MCFragment *Fragment, + const MCFixup &Fixup, + MCValue Target, + uint64_t &FixedValue) { + int64_t Addend = 0; + int Index = 0; + int64_t Value = Target.getConstant(); + const MCSymbol *RelocSymbol = NULL; + + bool IsPCRel = isFixupKindPCRel(Asm, Fixup.getKind()); + if (!Target.isAbsolute()) { + const MCSymbol &Symbol = Target.getSymA()->getSymbol(); + const MCSymbol &ASymbol = Symbol.AliasedSymbol(); + RelocSymbol = SymbolToReloc(Asm, Target, *Fragment); + + if (const MCSymbolRefExpr *RefB = Target.getSymB()) { + const MCSymbol &SymbolB = RefB->getSymbol(); + MCSymbolData &SDB = Asm.getSymbolData(SymbolB); + IsPCRel = true; + + // Offset of the symbol in the section + int64_t a = Layout.getSymbolOffset(&SDB); + + // Ofeset of the relocation in the section + int64_t b = Layout.getFragmentOffset(Fragment) + Fixup.getOffset(); + Value += b - a; + } + + if (!RelocSymbol) { + MCSymbolData &SD = Asm.getSymbolData(ASymbol); + MCFragment *F = SD.getFragment(); + + Index = F->getParent()->getOrdinal() + 1; + + // Offset of the symbol in the section + Value += Layout.getSymbolOffset(&SD); + } else { + if (Asm.getSymbolData(Symbol).getFlags() & ELF_Other_Weakref) + WeakrefUsedInReloc.insert(RelocSymbol); + else + UsedInReloc.insert(RelocSymbol); + Index = -1; + } + Addend = Value; + // Compensate for the addend on i386. + if (is64Bit()) + Value = 0; + } + + FixedValue = Value; + unsigned Type = GetRelocType(Target, Fixup, IsPCRel, + (RelocSymbol != 0), Addend); + + uint64_t RelocOffset = Layout.getFragmentOffset(Fragment) + + Fixup.getOffset(); + + if (!hasRelocationAddend()) + Addend = 0; + ELFRelocationEntry ERE(RelocOffset, Index, Type, RelocSymbol, Addend); + Relocations[Fragment->getParent()].push_back(ERE); } @@ -702,8 +447,9 @@ ELFObjectWriter::getSymbolIndexInSymbolTable(const MCAssembler &Asm, return SD.getIndex(); } -static bool isInSymtab(const MCAssembler &Asm, const MCSymbolData &Data, - bool Used, bool Renamed) { +bool ELFObjectWriter::isInSymtab(const MCAssembler &Asm, + const MCSymbolData &Data, + bool Used, bool Renamed) { if (Data.getFlags() & ELF_Other_Weakref) return false; @@ -719,7 +465,11 @@ static bool isInSymtab(const MCAssembler &Asm, const MCSymbolData &Data, return true; const MCSymbol &A = Symbol.AliasedSymbol(); - if (!A.isVariable() && A.isUndefined() && !Data.isCommon()) + if (Symbol.isVariable() && !A.isVariable() && A.isUndefined()) + return false; + + bool IsGlobal = MCELF::GetBinding(Data) == ELF::STB_GLOBAL; + if (!Symbol.isVariable() && Symbol.isUndefined() && !IsGlobal) return false; if (!Asm.isSymbolLinkerVisible(Symbol) && !Symbol.isUndefined()) @@ -731,8 +481,8 @@ static bool isInSymtab(const MCAssembler &Asm, const MCSymbolData &Data, return true; } -static bool isLocal(const MCSymbolData &Data, bool isSignature, - bool isUsedInReloc) { +bool ELFObjectWriter::isLocal(const MCSymbolData &Data, bool isSignature, + bool isUsedInReloc) { if (Data.isExternal()) return false; @@ -780,7 +530,7 @@ void ELFObjectWriter::ComputeSymbolTable(MCAssembler &Asm, MCSymbol *Sym = Asm.getContext().GetOrCreateSymbol(Name); MCSymbolData &Data = Asm.getOrCreateSymbolData(*Sym); Data.setExternal(true); - SetBinding(Data, ELF::STB_GLOBAL); + MCELF::SetBinding(Data, ELF::STB_GLOBAL); } // Build section lookup table. @@ -811,14 +561,14 @@ void ELFObjectWriter::ComputeSymbolTable(MCAssembler &Asm, // Undefined symbols are global, but this is the first place we // are able to set it. bool Local = isLocal(*it, isSignature, Used); - if (!Local && GetBinding(*it) == ELF::STB_LOCAL) { + if (!Local && MCELF::GetBinding(*it) == ELF::STB_LOCAL) { MCSymbolData &SD = Asm.getSymbolData(RefSymbol); - SetBinding(*it, ELF::STB_GLOBAL); - SetBinding(SD, ELF::STB_GLOBAL); + MCELF::SetBinding(*it, ELF::STB_GLOBAL); + MCELF::SetBinding(SD, ELF::STB_GLOBAL); } if (RefSymbol.isUndefined() && !Used && WeakrefUsed) - SetBinding(*it, ELF::STB_WEAK); + MCELF::SetBinding(*it, ELF::STB_WEAK); if (it->isCommon()) { assert(!Local); @@ -895,28 +645,26 @@ void ELFObjectWriter::WriteRelocation(MCAssembler &Asm, MCAsmLayout &Layout, static_cast<const MCSectionELF&>(SD.getSection()); const StringRef SectionName = Section.getSectionName(); - std::string RelaSectionName = HasRelocationAddend ? ".rela" : ".rel"; + std::string RelaSectionName = hasRelocationAddend() ? ".rela" : ".rel"; RelaSectionName += SectionName; unsigned EntrySize; - if (HasRelocationAddend) - EntrySize = Is64Bit ? sizeof(ELF::Elf64_Rela) : sizeof(ELF::Elf32_Rela); + if (hasRelocationAddend()) + EntrySize = is64Bit() ? sizeof(ELF::Elf64_Rela) : sizeof(ELF::Elf32_Rela); else - EntrySize = Is64Bit ? sizeof(ELF::Elf64_Rel) : sizeof(ELF::Elf32_Rel); + EntrySize = is64Bit() ? sizeof(ELF::Elf64_Rel) : sizeof(ELF::Elf32_Rel); - RelaSection = Ctx.getELFSection(RelaSectionName, HasRelocationAddend ? + RelaSection = Ctx.getELFSection(RelaSectionName, hasRelocationAddend() ? ELF::SHT_RELA : ELF::SHT_REL, 0, SectionKind::getReadOnly(), EntrySize, ""); MCSectionData &RelaSD = Asm.getOrCreateSectionData(*RelaSection); - RelaSD.setAlignment(Is64Bit ? 8 : 4); + RelaSD.setAlignment(is64Bit() ? 8 : 4); MCDataFragment *F = new MCDataFragment(&RelaSD); WriteRelocationsFragment(Asm, F, &SD); - - Asm.AddSectionToTheEnd(*this, RelaSD, Layout); } } @@ -948,18 +696,20 @@ void ELFObjectWriter::WriteRelocationsFragment(const MCAssembler &Asm, for (unsigned i = 0, e = Relocs.size(); i != e; ++i) { ELFRelocationEntry entry = Relocs[e - i - 1]; - if (entry.Index < 0) + if (!entry.Index) + ; + else if (entry.Index < 0) entry.Index = getSymbolIndexInSymbolTable(Asm, entry.Symbol); else - entry.Index += LocalSymbolData.size() + 1; - if (Is64Bit) { + entry.Index += LocalSymbolData.size(); + if (is64Bit()) { String64(*F, entry.r_offset); struct ELF::Elf64_Rela ERE64; ERE64.setSymbolAndType(entry.Index, entry.Type); String64(*F, ERE64.r_info); - if (HasRelocationAddend) + if (hasRelocationAddend()) String64(*F, entry.r_addend); } else { String32(*F, entry.r_offset); @@ -968,7 +718,7 @@ void ELFObjectWriter::WriteRelocationsFragment(const MCAssembler &Asm, ERE32.setSymbolAndType(entry.Index, entry.Type); String32(*F, ERE32.r_info); - if (HasRelocationAddend) + if (hasRelocationAddend()) String32(*F, entry.r_addend); } } @@ -980,7 +730,7 @@ void ELFObjectWriter::CreateMetadataSections(MCAssembler &Asm, MCContext &Ctx = Asm.getContext(); MCDataFragment *F; - unsigned EntrySize = Is64Bit ? ELF::SYMENTRY_SIZE64 : ELF::SYMENTRY_SIZE32; + unsigned EntrySize = is64Bit() ? ELF::SYMENTRY_SIZE64 : ELF::SYMENTRY_SIZE32; // We construct .shstrtab, .symtab and .strtab in this order to match gnu as. const MCSectionELF *ShstrtabSection = @@ -995,7 +745,7 @@ void ELFObjectWriter::CreateMetadataSections(MCAssembler &Asm, SectionKind::getReadOnly(), EntrySize, ""); MCSectionData &SymtabSD = Asm.getOrCreateSectionData(*SymtabSection); - SymtabSD.setAlignment(Is64Bit ? 8 : 4); + SymtabSD.setAlignment(is64Bit() ? 8 : 4); SymbolTableIndex = Asm.size(); MCSectionData *SymtabShndxSD = NULL; @@ -1022,14 +772,11 @@ void ELFObjectWriter::CreateMetadataSections(MCAssembler &Asm, MCDataFragment *ShndxF = NULL; if (NeedsSymtabShndx) { ShndxF = new MCDataFragment(SymtabShndxSD); - Asm.AddSectionToTheEnd(*this, *SymtabShndxSD, Layout); } WriteSymbolTable(F, ShndxF, Asm, Layout, SectionIndexMap); - Asm.AddSectionToTheEnd(*this, SymtabSD, Layout); F = new MCDataFragment(&StrtabSD); F->getContents().append(StringTable.begin(), StringTable.end()); - Asm.AddSectionToTheEnd(*this, StrtabSD, Layout); F = new MCDataFragment(&ShstrtabSD); @@ -1061,61 +808,34 @@ void ELFObjectWriter::CreateMetadataSections(MCAssembler &Asm, F->getContents() += Name; F->getContents() += '\x00'; } - - Asm.AddSectionToTheEnd(*this, ShstrtabSD, Layout); } -bool ELFObjectWriter::IsFixupFullyResolved(const MCAssembler &Asm, - const MCValue Target, - bool IsPCRel, - const MCFragment *DF) const { - // If this is a PCrel relocation, find the section this fixup value is - // relative to. - const MCSection *BaseSection = 0; - if (IsPCRel) { - BaseSection = &DF->getParent()->getSection(); - assert(BaseSection); - } - - const MCSection *SectionA = 0; - const MCSymbol *SymbolA = 0; - if (const MCSymbolRefExpr *A = Target.getSymA()) { - SymbolA = &A->getSymbol().AliasedSymbol(); - SectionA = &SymbolA->getSection(); - } - - const MCSection *SectionB = 0; - if (const MCSymbolRefExpr *B = Target.getSymB()) { - SectionB = &B->getSymbol().AliasedSymbol().getSection(); +void ELFObjectWriter::CreateIndexedSections(MCAssembler &Asm, + MCAsmLayout &Layout, + GroupMapTy &GroupMap, + RevGroupMapTy &RevGroupMap) { + // Create the .note.GNU-stack section if needed. + MCContext &Ctx = Asm.getContext(); + if (Asm.getNoExecStack()) { + const MCSectionELF *GnuStackSection = + Ctx.getELFSection(".note.GNU-stack", ELF::SHT_PROGBITS, 0, + SectionKind::getReadOnly()); + Asm.getOrCreateSectionData(*GnuStackSection); } - if (!BaseSection) - return SectionA == SectionB; - - const MCSymbolData &DataA = Asm.getSymbolData(*SymbolA); - if (DataA.isExternal()) - return false; - - return !SectionB && BaseSection == SectionA; -} - -void ELFObjectWriter::CreateGroupSections(MCAssembler &Asm, - MCAsmLayout &Layout, - GroupMapTy &GroupMap, - RevGroupMapTy &RevGroupMap) { // Build the groups for (MCAssembler::const_iterator it = Asm.begin(), ie = Asm.end(); it != ie; ++it) { const MCSectionELF &Section = static_cast<const MCSectionELF&>(it->getSection()); - if (!(Section.getFlags() & MCSectionELF::SHF_GROUP)) + if (!(Section.getFlags() & ELF::SHF_GROUP)) continue; const MCSymbol *SignatureSymbol = Section.getGroup(); Asm.getOrCreateSymbolData(*SignatureSymbol); const MCSectionELF *&Group = RevGroupMap[SignatureSymbol]; if (!Group) { - Group = Asm.getContext().CreateELFGroupSection(); + Group = Ctx.CreateELFGroupSection(); MCSectionData &Data = Asm.getOrCreateSectionData(*Group); Data.setAlignment(4); MCDataFragment *F = new MCDataFragment(&Data); @@ -1131,7 +851,7 @@ void ELFObjectWriter::CreateGroupSections(MCAssembler &Asm, it != ie; ++it, ++Index) { const MCSectionELF &Section = static_cast<const MCSectionELF&>(it->getSection()); - if (!(Section.getFlags() & MCSectionELF::SHF_GROUP)) + if (!(Section.getFlags() & ELF::SHF_GROUP)) continue; const MCSectionELF *Group = RevGroupMap[Section.getGroup()]; MCSectionData &Data = Asm.getOrCreateSectionData(*Group); @@ -1139,13 +859,6 @@ void ELFObjectWriter::CreateGroupSections(MCAssembler &Asm, MCDataFragment *F = new MCDataFragment(&Data); String32(*F, NumGroups + Index); } - - for (RevGroupMapTy::const_iterator i = RevGroupMap.begin(), - e = RevGroupMap.end(); i != e; ++i) { - const MCSectionELF *Group = i->second; - MCSectionData &Data = Asm.getOrCreateSectionData(*Group); - Asm.AddSectionToTheEnd(*this, Data, Layout); - } } void ELFObjectWriter::WriteSection(MCAssembler &Asm, @@ -1197,8 +910,13 @@ void ELFObjectWriter::WriteSection(MCAssembler &Asm, case ELF::SHT_PROGBITS: case ELF::SHT_STRTAB: case ELF::SHT_NOBITS: + case ELF::SHT_NOTE: case ELF::SHT_NULL: case ELF::SHT_ARM_ATTRIBUTES: + case ELF::SHT_INIT_ARRAY: + case ELF::SHT_FINI_ARRAY: + case ELF::SHT_PREINIT_ARRAY: + case ELF::SHT_X86_64_UNWIND: // Nothing to do. break; @@ -1218,12 +936,52 @@ void ELFObjectWriter::WriteSection(MCAssembler &Asm, Alignment, Section.getEntrySize()); } +bool ELFObjectWriter::IsELFMetaDataSection(const MCSectionData &SD) { + return SD.getOrdinal() == ~UINT32_C(0) && + !SD.getSection().isVirtualSection(); +} + +uint64_t ELFObjectWriter::DataSectionSize(const MCSectionData &SD) { + uint64_t Ret = 0; + for (MCSectionData::const_iterator i = SD.begin(), e = SD.end(); i != e; + ++i) { + const MCFragment &F = *i; + assert(F.getKind() == MCFragment::FT_Data); + Ret += cast<MCDataFragment>(F).getContents().size(); + } + return Ret; +} + +uint64_t ELFObjectWriter::GetSectionFileSize(const MCAsmLayout &Layout, + const MCSectionData &SD) { + if (IsELFMetaDataSection(SD)) + return DataSectionSize(SD); + return Layout.getSectionFileSize(&SD); +} + +uint64_t ELFObjectWriter::GetSectionAddressSize(const MCAsmLayout &Layout, + const MCSectionData &SD) { + if (IsELFMetaDataSection(SD)) + return DataSectionSize(SD); + return Layout.getSectionAddressSize(&SD); +} + +void ELFObjectWriter::WriteDataSectionData(ELFObjectWriter *W, + const MCSectionData &SD) { + for (MCSectionData::const_iterator i = SD.begin(), e = SD.end(); i != e; + ++i) { + const MCFragment &F = *i; + assert(F.getKind() == MCFragment::FT_Data); + W->WriteBytes(cast<MCDataFragment>(F).getContents().str()); + } +} + void ELFObjectWriter::WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout) { GroupMapTy GroupMap; RevGroupMapTy RevGroupMap; - CreateGroupSections(Asm, const_cast<MCAsmLayout&>(Layout), GroupMap, - RevGroupMap); + CreateIndexedSections(Asm, const_cast<MCAsmLayout&>(Layout), GroupMap, + RevGroupMap); SectionIndexMapTy SectionIndexMap; @@ -1241,8 +999,9 @@ void ELFObjectWriter::WriteObject(MCAssembler &Asm, // Add 1 for the null section. unsigned NumSections = Asm.size() + 1; - uint64_t NaturalAlignment = Is64Bit ? 8 : 4; - uint64_t HeaderSize = Is64Bit ? sizeof(ELF::Elf64_Ehdr) : sizeof(ELF::Elf32_Ehdr); + uint64_t NaturalAlignment = is64Bit() ? 8 : 4; + uint64_t HeaderSize = is64Bit() ? sizeof(ELF::Elf64_Ehdr) : + sizeof(ELF::Elf32_Ehdr); uint64_t FileOff = HeaderSize; std::vector<const MCSectionELF*> Sections; @@ -1261,9 +1020,7 @@ void ELFObjectWriter::WriteObject(MCAssembler &Asm, FileOff = RoundUpToAlignment(FileOff, SD.getAlignment()); // Get the size of the section in the output file (including padding). - uint64_t Size = Layout.getSectionFileSize(&SD); - - FileOff += Size; + FileOff += GetSectionFileSize(Layout, SD); } FileOff = RoundUpToAlignment(FileOff, NaturalAlignment); @@ -1287,9 +1044,12 @@ void ELFObjectWriter::WriteObject(MCAssembler &Asm, // Remember the offset into the file for this section. SectionOffsetMap[&Section] = FileOff; - FileOff += Layout.getSectionFileSize(&SD); + FileOff += GetSectionFileSize(Layout, SD); - Asm.WriteSectionData(&SD, Layout, this); + if (IsELFMetaDataSection(SD)) + WriteDataSectionData(this, SD); + else + Asm.WriteSectionData(&SD, Layout); } uint64_t Padding = OffsetToAlignment(FileOff, NaturalAlignment); @@ -1315,26 +1075,37 @@ void ELFObjectWriter::WriteObject(MCAssembler &Asm, else GroupSymbolIndex = getSymbolIndexInSymbolTable(Asm, GroupMap[&Section]); + uint64_t Size = GetSectionAddressSize(Layout, SD); + WriteSection(Asm, SectionIndexMap, GroupSymbolIndex, - SectionOffsetMap[&Section], Layout.getSectionSize(&SD), + SectionOffsetMap[&Section], Size, SD.getAlignment(), Section); } } -MCObjectWriter *llvm::createELFObjectWriter(raw_ostream &OS, - bool Is64Bit, - Triple::OSType OSType, - uint16_t EMachine, - bool IsLittleEndian, - bool HasRelocationAddend) { - switch (EMachine) { +bool +ELFObjectWriter::IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, + const MCSymbolData &DataA, + const MCFragment &FB, + bool InSet, + bool IsPCRel) const { + if (DataA.getFlags() & ELF_STB_Weak) + return false; + return MCObjectWriter::IsSymbolRefDifferenceFullyResolvedImpl( + Asm, DataA, FB,InSet, IsPCRel); +} + +MCObjectWriter *llvm::createELFObjectWriter(MCELFObjectTargetWriter *MOTW, + raw_ostream &OS, + bool IsLittleEndian) { + switch (MOTW->getEMachine()) { case ELF::EM_386: case ELF::EM_X86_64: - return new X86ELFObjectWriter(OS, Is64Bit, IsLittleEndian, EMachine, - HasRelocationAddend, OSType); break; + return new X86ELFObjectWriter(MOTW, OS, IsLittleEndian); break; case ELF::EM_ARM: - return new ARMELFObjectWriter(OS, Is64Bit, IsLittleEndian, EMachine, - HasRelocationAddend, OSType); break; + return new ARMELFObjectWriter(MOTW, OS, IsLittleEndian); break; + case ELF::EM_MBLAZE: + return new MBlazeELFObjectWriter(MOTW, OS, IsLittleEndian); break; default: llvm_unreachable("Unsupported architecture"); break; } } @@ -1343,121 +1114,276 @@ MCObjectWriter *llvm::createELFObjectWriter(raw_ostream &OS, /// START OF SUBCLASSES for ELFObjectWriter //===- ARMELFObjectWriter -------------------------------------------===// -ARMELFObjectWriter::ARMELFObjectWriter(raw_ostream &_OS, bool _Is64Bit, - bool _IsLittleEndian, - uint16_t _EMachine, bool _HasRelocationAddend, - Triple::OSType _OSType) - : ELFObjectWriter(_OS, _Is64Bit, _IsLittleEndian, _EMachine, - _HasRelocationAddend, _OSType) +ARMELFObjectWriter::ARMELFObjectWriter(MCELFObjectTargetWriter *MOTW, + raw_ostream &_OS, + bool IsLittleEndian) + : ELFObjectWriter(MOTW, _OS, IsLittleEndian) {} ARMELFObjectWriter::~ARMELFObjectWriter() {} -void ARMELFObjectWriter::RecordRelocation(const MCAssembler &Asm, - const MCAsmLayout &Layout, - const MCFragment *Fragment, - const MCFixup &Fixup, - MCValue Target, - uint64_t &FixedValue) { - assert(0 && "ARMELFObjectWriter::RecordRelocation() unimplemented"); +// FIXME: get the real EABI Version from the Triple. +void ARMELFObjectWriter::WriteEFlags() { + Write32(ELF::EF_ARM_EABIMASK & DefaultEABIVersion); } +// In ARM, _MergedGlobals and other most symbols get emitted directly. +// I.e. not as an offset to a section symbol. +// This code is a first-cut approximation of what ARM/gcc does. +const MCSymbol *ARMELFObjectWriter::ExplicitRelSym(const MCAssembler &Asm, + const MCValue &Target, + const MCFragment &F, + bool IsBSS) const { + const MCSymbol &Symbol = Target.getSymA()->getSymbol(); + bool EmitThisSym = false; -//===- X86ELFObjectWriter -------------------------------------------===// + if (IsBSS) { + EmitThisSym = StringSwitch<bool>(Symbol.getName()) + .Case("_MergedGlobals", true) + .Default(false); + } else { + EmitThisSym = StringSwitch<bool>(Symbol.getName()) + .Case("_MergedGlobals", true) + .StartsWith(".L.str", true) + .Default(false); + } + if (EmitThisSym) + return &Symbol; + if (! Symbol.isTemporary()) + return &Symbol; + return NULL; +} +unsigned ARMELFObjectWriter::GetRelocType(const MCValue &Target, + const MCFixup &Fixup, + bool IsPCRel, + bool IsRelocWithSymbol, + int64_t Addend) { + MCSymbolRefExpr::VariantKind Modifier = Target.isAbsolute() ? + MCSymbolRefExpr::VK_None : Target.getSymA()->getKind(); -X86ELFObjectWriter::X86ELFObjectWriter(raw_ostream &_OS, bool _Is64Bit, - bool _IsLittleEndian, - uint16_t _EMachine, bool _HasRelocationAddend, - Triple::OSType _OSType) - : ELFObjectWriter(_OS, _Is64Bit, _IsLittleEndian, _EMachine, - _HasRelocationAddend, _OSType) -{} + unsigned Type = 0; + if (IsPCRel) { + switch ((unsigned)Fixup.getKind()) { + default: assert(0 && "Unimplemented"); + case FK_Data_4: + switch (Modifier) { + default: llvm_unreachable("Unsupported Modifier"); + case MCSymbolRefExpr::VK_None: + Type = ELF::R_ARM_BASE_PREL; + break; + case MCSymbolRefExpr::VK_ARM_TLSGD: + assert(0 && "unimplemented"); + break; + case MCSymbolRefExpr::VK_ARM_GOTTPOFF: + Type = ELF::R_ARM_TLS_IE32; + break; + } + break; + case ARM::fixup_arm_uncondbranch: + switch (Modifier) { + case MCSymbolRefExpr::VK_ARM_PLT: + Type = ELF::R_ARM_PLT32; + break; + default: + Type = ELF::R_ARM_CALL; + break; + } + break; + case ARM::fixup_arm_condbranch: + Type = ELF::R_ARM_JUMP24; + break; + case ARM::fixup_arm_movt_hi16: + case ARM::fixup_arm_movt_hi16_pcrel: + Type = ELF::R_ARM_MOVT_PREL; + break; + case ARM::fixup_arm_movw_lo16: + case ARM::fixup_arm_movw_lo16_pcrel: + Type = ELF::R_ARM_MOVW_PREL_NC; + break; + case ARM::fixup_t2_movt_hi16: + case ARM::fixup_t2_movt_hi16_pcrel: + Type = ELF::R_ARM_THM_MOVT_PREL; + break; + case ARM::fixup_t2_movw_lo16: + case ARM::fixup_t2_movw_lo16_pcrel: + Type = ELF::R_ARM_THM_MOVW_PREL_NC; + break; + } + } else { + switch ((unsigned)Fixup.getKind()) { + default: llvm_unreachable("invalid fixup kind!"); + case FK_Data_4: + switch (Modifier) { + default: llvm_unreachable("Unsupported Modifier"); break; + case MCSymbolRefExpr::VK_ARM_GOT: + Type = ELF::R_ARM_GOT_BREL; + break; + case MCSymbolRefExpr::VK_ARM_TLSGD: + Type = ELF::R_ARM_TLS_GD32; + break; + case MCSymbolRefExpr::VK_ARM_TPOFF: + Type = ELF::R_ARM_TLS_LE32; + break; + case MCSymbolRefExpr::VK_ARM_GOTTPOFF: + Type = ELF::R_ARM_TLS_IE32; + break; + case MCSymbolRefExpr::VK_None: + Type = ELF::R_ARM_ABS32; + break; + case MCSymbolRefExpr::VK_ARM_GOTOFF: + Type = ELF::R_ARM_GOTOFF32; + break; + } + break; + case ARM::fixup_arm_ldst_pcrel_12: + case ARM::fixup_arm_pcrel_10: + case ARM::fixup_arm_adr_pcrel_12: + case ARM::fixup_arm_thumb_bl: + case ARM::fixup_arm_thumb_cb: + case ARM::fixup_arm_thumb_cp: + case ARM::fixup_arm_thumb_br: + assert(0 && "Unimplemented"); + break; + case ARM::fixup_arm_uncondbranch: + Type = ELF::R_ARM_CALL; + break; + case ARM::fixup_arm_condbranch: + Type = ELF::R_ARM_JUMP24; + break; + case ARM::fixup_arm_movt_hi16: + Type = ELF::R_ARM_MOVT_ABS; + break; + case ARM::fixup_arm_movw_lo16: + Type = ELF::R_ARM_MOVW_ABS_NC; + break; + case ARM::fixup_t2_movt_hi16: + Type = ELF::R_ARM_THM_MOVT_ABS; + break; + case ARM::fixup_t2_movw_lo16: + Type = ELF::R_ARM_THM_MOVW_ABS_NC; + break; + } + } -X86ELFObjectWriter::~X86ELFObjectWriter() -{} + if (RelocNeedsGOT(Modifier)) + NeedsGOT = true; -void X86ELFObjectWriter::RecordRelocation(const MCAssembler &Asm, - const MCAsmLayout &Layout, - const MCFragment *Fragment, - const MCFixup &Fixup, - MCValue Target, - uint64_t &FixedValue) { - int64_t Addend = 0; - int Index = 0; - int64_t Value = Target.getConstant(); - const MCSymbol &Symbol = Target.getSymA()->getSymbol(); - const MCSymbol &ASymbol = Symbol.AliasedSymbol(); - const MCSymbol *RelocSymbol = SymbolToReloc(Asm, Target, *Fragment); + return Type; +} - bool IsPCRel = isFixupKindX86PCRel(Fixup.getKind()); - if (!Target.isAbsolute()) { - if (const MCSymbolRefExpr *RefB = Target.getSymB()) { - const MCSymbol &SymbolB = RefB->getSymbol(); - MCSymbolData &SDB = Asm.getSymbolData(SymbolB); - IsPCRel = true; - MCSectionData *Sec = Fragment->getParent(); +//===- MBlazeELFObjectWriter -------------------------------------------===// - // Offset of the symbol in the section - int64_t a = Layout.getSymbolAddress(&SDB) - Layout.getSectionAddress(Sec); +MBlazeELFObjectWriter::MBlazeELFObjectWriter(MCELFObjectTargetWriter *MOTW, + raw_ostream &_OS, + bool IsLittleEndian) + : ELFObjectWriter(MOTW, _OS, IsLittleEndian) { +} - // Ofeset of the relocation in the section - int64_t b = Layout.getFragmentOffset(Fragment) + Fixup.getOffset(); - Value += b - a; +MBlazeELFObjectWriter::~MBlazeELFObjectWriter() { +} + +unsigned MBlazeELFObjectWriter::GetRelocType(const MCValue &Target, + const MCFixup &Fixup, + bool IsPCRel, + bool IsRelocWithSymbol, + int64_t Addend) { + // determine the type of the relocation + unsigned Type; + if (IsPCRel) { + switch ((unsigned)Fixup.getKind()) { + default: + llvm_unreachable("Unimplemented"); + case FK_PCRel_4: + Type = ELF::R_MICROBLAZE_64_PCREL; + break; + case FK_PCRel_2: + Type = ELF::R_MICROBLAZE_32_PCREL; + break; } + } else { + switch ((unsigned)Fixup.getKind()) { + default: llvm_unreachable("invalid fixup kind!"); + case FK_Data_4: + Type = ((IsRelocWithSymbol || Addend !=0) + ? ELF::R_MICROBLAZE_32 + : ELF::R_MICROBLAZE_64); + break; + case FK_Data_2: + Type = ELF::R_MICROBLAZE_32; + break; + } + } + return Type; +} - if (!RelocSymbol) { - MCSymbolData &SD = Asm.getSymbolData(ASymbol); - MCFragment *F = SD.getFragment(); +//===- X86ELFObjectWriter -------------------------------------------===// - Index = F->getParent()->getOrdinal(); - MCSectionData *FSD = F->getParent(); - // Offset of the symbol in the section - Value += Layout.getSymbolAddress(&SD) - Layout.getSectionAddress(FSD); - } else { - if (Asm.getSymbolData(Symbol).getFlags() & ELF_Other_Weakref) - WeakrefUsedInReloc.insert(RelocSymbol); - else - UsedInReloc.insert(RelocSymbol); - Index = -1; - } - Addend = Value; - // Compensate for the addend on i386. - if (Is64Bit) - Value = 0; - } +X86ELFObjectWriter::X86ELFObjectWriter(MCELFObjectTargetWriter *MOTW, + raw_ostream &_OS, + bool IsLittleEndian) + : ELFObjectWriter(MOTW, _OS, IsLittleEndian) +{} - FixedValue = Value; +X86ELFObjectWriter::~X86ELFObjectWriter() +{} +unsigned X86ELFObjectWriter::GetRelocType(const MCValue &Target, + const MCFixup &Fixup, + bool IsPCRel, + bool IsRelocWithSymbol, + int64_t Addend) { // determine the type of the relocation - MCSymbolRefExpr::VariantKind Modifier = Target.getSymA()->getKind(); + MCSymbolRefExpr::VariantKind Modifier = Target.isAbsolute() ? + MCSymbolRefExpr::VK_None : Target.getSymA()->getKind(); unsigned Type; - if (Is64Bit) { + if (is64Bit()) { if (IsPCRel) { - switch (Modifier) { - default: - llvm_unreachable("Unimplemented"); - case MCSymbolRefExpr::VK_None: - Type = ELF::R_X86_64_PC32; - break; - case MCSymbolRefExpr::VK_PLT: - Type = ELF::R_X86_64_PLT32; + switch ((unsigned)Fixup.getKind()) { + default: llvm_unreachable("invalid fixup kind!"); + case FK_PCRel_8: + assert(Modifier == MCSymbolRefExpr::VK_None); + Type = ELF::R_X86_64_PC64; break; - case MCSymbolRefExpr::VK_GOTPCREL: - Type = ELF::R_X86_64_GOTPCREL; + case X86::reloc_signed_4byte: + case X86::reloc_riprel_4byte_movq_load: + case FK_Data_4: // FIXME? + case X86::reloc_riprel_4byte: + case FK_PCRel_4: + switch (Modifier) { + default: + llvm_unreachable("Unimplemented"); + case MCSymbolRefExpr::VK_None: + Type = ELF::R_X86_64_PC32; + break; + case MCSymbolRefExpr::VK_PLT: + Type = ELF::R_X86_64_PLT32; + break; + case MCSymbolRefExpr::VK_GOTPCREL: + Type = ELF::R_X86_64_GOTPCREL; + break; + case MCSymbolRefExpr::VK_GOTTPOFF: + Type = ELF::R_X86_64_GOTTPOFF; break; - case MCSymbolRefExpr::VK_GOTTPOFF: - Type = ELF::R_X86_64_GOTTPOFF; + case MCSymbolRefExpr::VK_TLSGD: + Type = ELF::R_X86_64_TLSGD; + break; + case MCSymbolRefExpr::VK_TLSLD: + Type = ELF::R_X86_64_TLSLD; + break; + } break; - case MCSymbolRefExpr::VK_TLSGD: - Type = ELF::R_X86_64_TLSGD; + case FK_PCRel_2: + assert(Modifier == MCSymbolRefExpr::VK_None); + Type = ELF::R_X86_64_PC16; break; - case MCSymbolRefExpr::VK_TLSLD: - Type = ELF::R_X86_64_TLSLD; + case FK_PCRel_1: + assert(Modifier == MCSymbolRefExpr::VK_None); + Type = ELF::R_X86_64_PC8; break; } } else { @@ -1465,7 +1391,6 @@ void X86ELFObjectWriter::RecordRelocation(const MCAssembler &Asm, default: llvm_unreachable("invalid fixup kind!"); case FK_Data_8: Type = ELF::R_X86_64_64; break; case X86::reloc_signed_4byte: - case X86::reloc_pcrel_4byte: assert(isInt<32>(Target.getConstant())); switch (Modifier) { default: @@ -1491,7 +1416,7 @@ void X86ELFObjectWriter::RecordRelocation(const MCAssembler &Asm, Type = ELF::R_X86_64_32; break; case FK_Data_2: Type = ELF::R_X86_64_16; break; - case X86::reloc_pcrel_1byte: + case FK_PCRel_1: case FK_Data_1: Type = ELF::R_X86_64_8; break; } } @@ -1518,7 +1443,7 @@ void X86ELFObjectWriter::RecordRelocation(const MCAssembler &Asm, // FIXME: Should we avoid selecting reloc_signed_4byte in 32 bit mode // instead? case X86::reloc_signed_4byte: - case X86::reloc_pcrel_4byte: + case FK_PCRel_4: case FK_Data_4: switch (Modifier) { default: @@ -1556,7 +1481,7 @@ void X86ELFObjectWriter::RecordRelocation(const MCAssembler &Asm, } break; case FK_Data_2: Type = ELF::R_386_16; break; - case X86::reloc_pcrel_1byte: + case FK_PCRel_1: case FK_Data_1: Type = ELF::R_386_8; break; } } @@ -1565,18 +1490,5 @@ void X86ELFObjectWriter::RecordRelocation(const MCAssembler &Asm, if (RelocNeedsGOT(Modifier)) NeedsGOT = true; - ELFRelocationEntry ERE; - - ERE.Index = Index; - ERE.Type = Type; - ERE.Symbol = RelocSymbol; - - ERE.r_offset = Layout.getFragmentOffset(Fragment) + Fixup.getOffset(); - - if (HasRelocationAddend) - ERE.r_addend = Addend; - else - ERE.r_addend = 0; // Silence compiler warning. - - Relocations[Fragment->getParent()].push_back(ERE); + return Type; } |