| Index: lib/MC/ELFObjectWriter.cpp
|
| ===================================================================
|
| --- lib/MC/ELFObjectWriter.cpp (revision 118813)
|
| +++ lib/MC/ELFObjectWriter.cpp (working copy)
|
| @@ -98,266 +98,46 @@
|
| }
|
| }
|
|
|
| -namespace {
|
| +//===- ELFObjectWriter -------------------===//
|
| +ELFObjectWriter::~ELFObjectWriter()
|
| +{}
|
|
|
| - class ELFObjectWriterImpl {
|
| - /*static bool isFixupKindX86RIPRel(unsigned Kind) {
|
| - return Kind == X86::reloc_riprel_4byte ||
|
| - Kind == X86::reloc_riprel_4byte_movq_load;
|
| - }*/
|
| +void ELFObjectWriter::String8(MCDataFragment &F, uint8_t Value) {
|
| + char buf[1];
|
| + buf[0] = Value;
|
| + F.getContents() += StringRef(buf, 1);
|
| +}
|
|
|
| +void ELFObjectWriter::String16(MCDataFragment &F, uint16_t Value) {
|
| + char buf[2];
|
| + if (isLittleEndian())
|
| + StringLE16(buf, Value);
|
| + else
|
| + StringBE16(buf, Value);
|
| + F.getContents() += StringRef(buf, 2);
|
| +}
|
|
|
| - /// ELFSymbolData - Helper struct for containing some precomputed information
|
| - /// on symbols.
|
| - struct ELFSymbolData {
|
| - MCSymbolData *SymbolData;
|
| - uint64_t StringIndex;
|
| - uint32_t SectionIndex;
|
| +void ELFObjectWriter::String32(MCDataFragment &F, uint32_t Value) {
|
| + char buf[4];
|
| + if (isLittleEndian())
|
| + StringLE32(buf, Value);
|
| + else
|
| + StringBE32(buf, Value);
|
| + F.getContents() += StringRef(buf, 4);
|
| +}
|
|
|
| - // 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;
|
| -
|
| - /// @}
|
| -
|
| - int NumRegularSections;
|
| -
|
| - bool NeedsGOT;
|
| -
|
| - bool NeedsSymtabShndx;
|
| -
|
| - ELFObjectWriter *Writer;
|
| -
|
| - raw_ostream &OS;
|
| -
|
| - 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;
|
| -
|
| - public:
|
| - ELFObjectWriterImpl(ELFObjectWriter *_Writer, bool _Is64Bit,
|
| - uint16_t _EMachine, bool _HasRelAddend,
|
| - Triple::OSType _OSType)
|
| - : NeedsGOT(false), NeedsSymtabShndx(false), Writer(_Writer),
|
| - OS(Writer->getStream()),
|
| - Is64Bit(_Is64Bit), HasRelocationAddend(_HasRelAddend),
|
| - OSType(_OSType), EMachine(_EMachine) {
|
| - }
|
| -
|
| - void Write8(uint8_t Value) { Writer->Write8(Value); }
|
| - void Write16(uint16_t Value) { Writer->Write16(Value); }
|
| - void Write32(uint32_t Value) { Writer->Write32(Value); }
|
| - //void Write64(uint64_t Value) { Writer->Write64(Value); }
|
| - void WriteZeros(unsigned N) { Writer->WriteZeros(N); }
|
| - //void WriteBytes(StringRef Str, unsigned ZeroFillSize = 0) {
|
| - // Writer->WriteBytes(Str, ZeroFillSize);
|
| - //}
|
| -
|
| - void WriteWord(uint64_t W) {
|
| - if (Is64Bit)
|
| - Writer->Write64(W);
|
| - else
|
| - Writer->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 (Writer->isLittleEndian())
|
| - StringLE16(buf, Value);
|
| - else
|
| - StringBE16(buf, Value);
|
| - F.getContents() += StringRef(buf, 2);
|
| - }
|
| -
|
| - void String32(MCDataFragment &F, uint32_t Value) {
|
| - char buf[4];
|
| - if (Writer->isLittleEndian())
|
| - StringLE32(buf, Value);
|
| - else
|
| - StringBE32(buf, Value);
|
| - F.getContents() += StringRef(buf, 4);
|
| - }
|
| -
|
| - void String64(MCDataFragment &F, uint64_t Value) {
|
| - char buf[8];
|
| - if (Writer->isLittleEndian())
|
| - StringLE64(buf, Value);
|
| - else
|
| - StringBE64(buf, Value);
|
| - F.getContents() += StringRef(buf, 8);
|
| - }
|
| -
|
| - void WriteHeader(uint64_t SectionDataSize, unsigned NumberOfSections);
|
| -
|
| - 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);
|
| -
|
| - void WriteSymbol(MCDataFragment *SymtabF, MCDataFragment *ShndxF,
|
| - ELFSymbolData &MSD,
|
| - const MCAsmLayout &Layout);
|
| -
|
| - typedef DenseMap<const MCSectionELF*, uint32_t> SectionIndexMapTy;
|
| - void WriteSymbolTable(MCDataFragment *SymtabF, MCDataFragment *ShndxF,
|
| - const MCAssembler &Asm,
|
| - const MCAsmLayout &Layout,
|
| - const SectionIndexMapTy &SectionIndexMap);
|
| -
|
| - void RecordRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout,
|
| - const MCFragment *Fragment, const MCFixup &Fixup,
|
| - MCValue Target, uint64_t &FixedValue);
|
| -
|
| - uint64_t getSymbolIndexInSymbolTable(const MCAssembler &Asm,
|
| - const MCSymbol *S);
|
| -
|
| - /// 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.
|
| - void ComputeSymbolTable(MCAssembler &Asm,
|
| - const SectionIndexMapTy &SectionIndexMap);
|
| -
|
| - void ComputeIndexMap(MCAssembler &Asm,
|
| - SectionIndexMapTy &SectionIndexMap);
|
| -
|
| - void WriteRelocation(MCAssembler &Asm, MCAsmLayout &Layout,
|
| - const MCSectionData &SD);
|
| -
|
| - void WriteRelocations(MCAssembler &Asm, MCAsmLayout &Layout) {
|
| - for (MCAssembler::const_iterator it = Asm.begin(),
|
| - ie = Asm.end(); it != ie; ++it) {
|
| - WriteRelocation(Asm, Layout, *it);
|
| - }
|
| - }
|
| -
|
| - void CreateMetadataSections(MCAssembler &Asm, MCAsmLayout &Layout,
|
| - const SectionIndexMapTy &SectionIndexMap);
|
| -
|
| - // Map from a group section to the signature symbol
|
| - typedef DenseMap<const MCSectionELF*, const MCSymbol*> GroupMapTy;
|
| - void CreateGroupSections(MCAssembler &Asm, MCAsmLayout &Layout,
|
| - GroupMapTy &GroupMap);
|
| -
|
| - void ExecutePostLayoutBinding(MCAssembler &Asm);
|
| -
|
| - 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);
|
| -
|
| - void WriteRelocationsFragment(const MCAssembler &Asm, MCDataFragment *F,
|
| - const MCSectionData *SD);
|
| -
|
| - bool IsFixupFullyResolved(const MCAssembler &Asm,
|
| - const MCValue Target,
|
| - bool IsPCRel,
|
| - const MCFragment *DF) const;
|
| -
|
| - void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout);
|
| - void WriteSection(MCAssembler &Asm,
|
| - const SectionIndexMapTy &SectionIndexMap,
|
| - uint32_t GroupSymbolIndex,
|
| - uint64_t Offset, uint64_t Size, uint64_t Alignment,
|
| - const MCSectionELF &Section);
|
| - };
|
| -
|
| +void ELFObjectWriter::String64(MCDataFragment &F, uint64_t Value) {
|
| + char buf[8];
|
| + if (isLittleEndian())
|
| + StringLE64(buf, Value);
|
| + else
|
| + StringBE64(buf, Value);
|
| + F.getContents() += StringRef(buf, 8);
|
| }
|
|
|
| +
|
| // Emit the ELF header.
|
| -void ELFObjectWriterImpl::WriteHeader(uint64_t SectionDataSize,
|
| +void ELFObjectWriter::WriteHeader(uint64_t SectionDataSize,
|
| unsigned NumberOfSections) {
|
| // ELF Header
|
| // ----------
|
| @@ -375,7 +155,7 @@
|
| Write8(Is64Bit ? ELF::ELFCLASS64 : ELF::ELFCLASS32); // e_ident[EI_CLASS]
|
|
|
| // e_ident[EI_DATA]
|
| - Write8(Writer->isLittleEndian() ? ELF::ELFDATA2LSB : ELF::ELFDATA2MSB);
|
| + Write8(isLittleEndian() ? ELF::ELFDATA2LSB : ELF::ELFDATA2MSB);
|
|
|
| Write8(ELF::EV_CURRENT); // e_ident[EI_VERSION]
|
| // e_ident[EI_OSABI]
|
| @@ -423,7 +203,7 @@
|
| Write16(ShstrtabIndex);
|
| }
|
|
|
| -void ELFObjectWriterImpl::WriteSymbolEntry(MCDataFragment *SymtabF,
|
| +void ELFObjectWriter::WriteSymbolEntry(MCDataFragment *SymtabF,
|
| MCDataFragment *ShndxF,
|
| uint64_t name,
|
| uint8_t info, uint64_t value,
|
| @@ -497,7 +277,25 @@
|
| return *S;
|
| }
|
|
|
| -void ELFObjectWriterImpl::ExecutePostLayoutBinding(MCAssembler &Asm) {
|
| +
|
| +// Helper routines
|
| +
|
| +bool ELFObjectWriter::ELFSymbolData::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();
|
| +}
|
| +
|
| +
|
| +bool ELFObjectWriter::ELFRelocationEntry::operator<(const ELFRelocationEntry &RE) const {
|
| + return RE.r_offset < r_offset;
|
| +}
|
| +
|
| +
|
| +void ELFObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm) {
|
| // The presence of symbol versions causes undefined symbols and
|
| // versions declared with @@@ to be renamed.
|
|
|
| @@ -543,7 +341,7 @@
|
| }
|
| }
|
|
|
| -void ELFObjectWriterImpl::WriteSymbol(MCDataFragment *SymtabF,
|
| +void ELFObjectWriter::WriteSymbol(MCDataFragment *SymtabF,
|
| MCDataFragment *ShndxF,
|
| ELFSymbolData &MSD,
|
| const MCAsmLayout &Layout) {
|
| @@ -590,7 +388,7 @@
|
| Size, Other, MSD.SectionIndex, IsReserved);
|
| }
|
|
|
| -void ELFObjectWriterImpl::WriteSymbolTable(MCDataFragment *SymtabF,
|
| +void ELFObjectWriter::WriteSymbolTable(MCDataFragment *SymtabF,
|
| MCDataFragment *ShndxF,
|
| const MCAssembler &Asm,
|
| const MCAsmLayout &Layout,
|
| @@ -678,215 +476,9 @@
|
| return false;
|
| }
|
|
|
| -// FIXME: this is currently X86/X86_64 only
|
| -void ELFObjectWriterImpl::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 = AliasedSymbol(Symbol);
|
| - const MCSymbol *RenamedP = Renames.lookup(&Symbol);
|
| - if (!RenamedP)
|
| - RenamedP = &ASymbol;
|
| - const MCSymbol &Renamed = *RenamedP;
|
|
|
| - bool IsPCRel = isFixupKindX86PCRel(Fixup.getKind());
|
| - if (!Target.isAbsolute()) {
|
| - MCSymbolData &SD = Asm.getSymbolData(Symbol);
|
| - MCFragment *F = SD.getFragment();
|
| -
|
| - if (const MCSymbolRefExpr *RefB = Target.getSymB()) {
|
| - const MCSymbol &SymbolB = RefB->getSymbol();
|
| - MCSymbolData &SDB = Asm.getSymbolData(SymbolB);
|
| - IsPCRel = true;
|
| - MCSectionData *Sec = Fragment->getParent();
|
| -
|
| - // Offset of the symbol in the section
|
| - int64_t a = Layout.getSymbolAddress(&SDB) - Layout.getSectionAddress(Sec);
|
| -
|
| - // Ofeset of the relocation in the section
|
| - int64_t b = Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
|
| - Value += b - a;
|
| - }
|
| -
|
| - bool RelocOnSymbol = ShouldRelocOnSymbol(SD, Target, *Fragment);
|
| - if (!RelocOnSymbol) {
|
| - 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(&Renamed);
|
| - else
|
| - UsedInReloc.insert(&Renamed);
|
| - Index = -1;
|
| - }
|
| - Addend = Value;
|
| - // Compensate for the addend on i386.
|
| - if (Is64Bit)
|
| - Value = 0;
|
| - }
|
| -
|
| - FixedValue = Value;
|
| -
|
| - // determine the type of the relocation
|
| -
|
| - MCSymbolRefExpr::VariantKind Modifier = Target.getSymA()->getKind();
|
| - unsigned Type;
|
| - 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;
|
| - 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_TLSGD:
|
| - Type = ELF::R_X86_64_TLSGD;
|
| - break;
|
| - case MCSymbolRefExpr::VK_TLSLD:
|
| - Type = ELF::R_X86_64_TLSLD;
|
| - break;
|
| - }
|
| - } else {
|
| - switch ((unsigned)Fixup.getKind()) {
|
| - 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:
|
| - llvm_unreachable("Unimplemented");
|
| - case MCSymbolRefExpr::VK_None:
|
| - Type = ELF::R_X86_64_32S;
|
| - break;
|
| - case MCSymbolRefExpr::VK_GOT:
|
| - Type = ELF::R_X86_64_GOT32;
|
| - break;
|
| - case MCSymbolRefExpr::VK_GOTPCREL:
|
| - Type = ELF::R_X86_64_GOTPCREL;
|
| - break;
|
| - case MCSymbolRefExpr::VK_TPOFF:
|
| - Type = ELF::R_X86_64_TPOFF32;
|
| - break;
|
| - case MCSymbolRefExpr::VK_DTPOFF:
|
| - Type = ELF::R_X86_64_DTPOFF32;
|
| - break;
|
| - }
|
| - break;
|
| - case FK_Data_4:
|
| - 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_Data_1: Type = ELF::R_X86_64_8; break;
|
| - }
|
| - }
|
| - } else {
|
| - if (IsPCRel) {
|
| - switch (Modifier) {
|
| - default:
|
| - llvm_unreachable("Unimplemented");
|
| - case MCSymbolRefExpr::VK_None:
|
| - Type = ELF::R_386_PC32;
|
| - break;
|
| - case MCSymbolRefExpr::VK_PLT:
|
| - Type = ELF::R_386_PLT32;
|
| - break;
|
| - }
|
| - } else {
|
| - switch ((unsigned)Fixup.getKind()) {
|
| - default: llvm_unreachable("invalid fixup kind!");
|
| -
|
| - case X86::reloc_global_offset_table:
|
| - Type = ELF::R_386_GOTPC;
|
| - break;
|
| -
|
| - // 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_Data_4:
|
| - switch (Modifier) {
|
| - default:
|
| - llvm_unreachable("Unimplemented");
|
| - case MCSymbolRefExpr::VK_None:
|
| - Type = ELF::R_386_32;
|
| - break;
|
| - case MCSymbolRefExpr::VK_GOT:
|
| - Type = ELF::R_386_GOT32;
|
| - break;
|
| - case MCSymbolRefExpr::VK_GOTOFF:
|
| - Type = ELF::R_386_GOTOFF;
|
| - break;
|
| - case MCSymbolRefExpr::VK_TLSGD:
|
| - Type = ELF::R_386_TLS_GD;
|
| - break;
|
| - case MCSymbolRefExpr::VK_TPOFF:
|
| - Type = ELF::R_386_TLS_LE_32;
|
| - break;
|
| - case MCSymbolRefExpr::VK_INDNTPOFF:
|
| - Type = ELF::R_386_TLS_IE;
|
| - break;
|
| - case MCSymbolRefExpr::VK_NTPOFF:
|
| - Type = ELF::R_386_TLS_LE;
|
| - break;
|
| - case MCSymbolRefExpr::VK_GOTNTPOFF:
|
| - Type = ELF::R_386_TLS_GOTIE;
|
| - break;
|
| - case MCSymbolRefExpr::VK_TLSLDM:
|
| - Type = ELF::R_386_TLS_LDM;
|
| - break;
|
| - case MCSymbolRefExpr::VK_DTPOFF:
|
| - Type = ELF::R_386_TLS_LDO_32;
|
| - break;
|
| - }
|
| - break;
|
| - case FK_Data_2: Type = ELF::R_386_16; break;
|
| - case X86::reloc_pcrel_1byte:
|
| - case FK_Data_1: Type = ELF::R_386_8; break;
|
| - }
|
| - }
|
| - }
|
| -
|
| - if (RelocNeedsGOT(Modifier))
|
| - NeedsGOT = true;
|
| -
|
| - ELFRelocationEntry ERE;
|
| -
|
| - ERE.Index = Index;
|
| - ERE.Type = Type;
|
| - ERE.Symbol = &Renamed;
|
| -
|
| - 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);
|
| -}
|
| -
|
| uint64_t
|
| -ELFObjectWriterImpl::getSymbolIndexInSymbolTable(const MCAssembler &Asm,
|
| +ELFObjectWriter::getSymbolIndexInSymbolTable(const MCAssembler &Asm,
|
| const MCSymbol *S) {
|
| MCSymbolData &SD = Asm.getSymbolData(*S);
|
|
|
| @@ -938,7 +530,7 @@
|
| return true;
|
| }
|
|
|
| -void ELFObjectWriterImpl::ComputeIndexMap(MCAssembler &Asm,
|
| +void ELFObjectWriter::ComputeIndexMap(MCAssembler &Asm,
|
| SectionIndexMapTy &SectionIndexMap) {
|
| unsigned Index = 1;
|
| for (MCAssembler::iterator it = Asm.begin(),
|
| @@ -960,7 +552,7 @@
|
| }
|
| }
|
|
|
| -void ELFObjectWriterImpl::ComputeSymbolTable(MCAssembler &Asm,
|
| +void ELFObjectWriter::ComputeSymbolTable(MCAssembler &Asm,
|
| const SectionIndexMapTy &SectionIndexMap) {
|
| // FIXME: Is this the correct place to do this?
|
| if (NeedsGOT) {
|
| @@ -1058,7 +650,7 @@
|
| UndefinedSymbolData[i].SymbolData->setIndex(Index++);
|
| }
|
|
|
| -void ELFObjectWriterImpl::WriteRelocation(MCAssembler &Asm, MCAsmLayout &Layout,
|
| +void ELFObjectWriter::WriteRelocation(MCAssembler &Asm, MCAsmLayout &Layout,
|
| const MCSectionData &SD) {
|
| if (!Relocations[&SD].empty()) {
|
| MCContext &Ctx = Asm.getContext();
|
| @@ -1088,11 +680,20 @@
|
|
|
| WriteRelocationsFragment(Asm, F, &SD);
|
|
|
| - Asm.AddSectionToTheEnd(*Writer, RelaSD, Layout);
|
| + Asm.AddSectionToTheEnd(*this, RelaSD, Layout);
|
| }
|
| }
|
|
|
| -void ELFObjectWriterImpl::WriteSecHdrEntry(uint32_t Name, uint32_t Type,
|
| +
|
| +void ELFObjectWriter::WriteRelocations(MCAssembler &Asm, MCAsmLayout &Layout) {
|
| + for (MCAssembler::const_iterator it = Asm.begin(),
|
| + ie = Asm.end(); it != ie; ++it) {
|
| + WriteRelocation(Asm, Layout, *it);
|
| + }
|
| +}
|
| +
|
| +
|
| +void ELFObjectWriter::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,
|
| @@ -1110,7 +711,7 @@
|
| WriteWord(EntrySize); // sh_entsize
|
| }
|
|
|
| -void ELFObjectWriterImpl::WriteRelocationsFragment(const MCAssembler &Asm,
|
| +void ELFObjectWriter::WriteRelocationsFragment(const MCAssembler &Asm,
|
| MCDataFragment *F,
|
| const MCSectionData *SD) {
|
| std::vector<ELFRelocationEntry> &Relocs = Relocations[SD];
|
| @@ -1146,7 +747,7 @@
|
| }
|
| }
|
|
|
| -void ELFObjectWriterImpl::CreateMetadataSections(MCAssembler &Asm,
|
| +void ELFObjectWriter::CreateMetadataSections(MCAssembler &Asm,
|
| MCAsmLayout &Layout,
|
| const SectionIndexMapTy &SectionIndexMap) {
|
| MCContext &Ctx = Asm.getContext();
|
| @@ -1194,14 +795,14 @@
|
| MCDataFragment *ShndxF = NULL;
|
| if (NeedsSymtabShndx) {
|
| ShndxF = new MCDataFragment(SymtabShndxSD);
|
| - Asm.AddSectionToTheEnd(*Writer, *SymtabShndxSD, Layout);
|
| + Asm.AddSectionToTheEnd(*this, *SymtabShndxSD, Layout);
|
| }
|
| WriteSymbolTable(F, ShndxF, Asm, Layout, SectionIndexMap);
|
| - Asm.AddSectionToTheEnd(*Writer, SymtabSD, Layout);
|
| + Asm.AddSectionToTheEnd(*this, SymtabSD, Layout);
|
|
|
| F = new MCDataFragment(&StrtabSD);
|
| F->getContents().append(StringTable.begin(), StringTable.end());
|
| - Asm.AddSectionToTheEnd(*Writer, StrtabSD, Layout);
|
| + Asm.AddSectionToTheEnd(*this, StrtabSD, Layout);
|
|
|
| F = new MCDataFragment(&ShstrtabSD);
|
|
|
| @@ -1234,10 +835,10 @@
|
| F->getContents() += '\x00';
|
| }
|
|
|
| - Asm.AddSectionToTheEnd(*Writer, ShstrtabSD, Layout);
|
| + Asm.AddSectionToTheEnd(*this, ShstrtabSD, Layout);
|
| }
|
|
|
| -bool ELFObjectWriterImpl::IsFixupFullyResolved(const MCAssembler &Asm,
|
| +bool ELFObjectWriter::IsFixupFullyResolved(const MCAssembler &Asm,
|
| const MCValue Target,
|
| bool IsPCRel,
|
| const MCFragment *DF) const {
|
| @@ -1271,7 +872,7 @@
|
| return !SectionB && BaseSection == SectionA;
|
| }
|
|
|
| -void ELFObjectWriterImpl::CreateGroupSections(MCAssembler &Asm,
|
| +void ELFObjectWriter::CreateGroupSections(MCAssembler &Asm,
|
| MCAsmLayout &Layout,
|
| GroupMapTy &GroupMap) {
|
| typedef DenseMap<const MCSymbol*, const MCSectionELF*> RevGroupMapTy;
|
| @@ -1317,11 +918,11 @@
|
| i != e; ++i) {
|
| const MCSectionELF *Group = i->second;
|
| MCSectionData &Data = Asm.getOrCreateSectionData(*Group);
|
| - Asm.AddSectionToTheEnd(*Writer, Data, Layout);
|
| + Asm.AddSectionToTheEnd(*this, Data, Layout);
|
| }
|
| }
|
|
|
| -void ELFObjectWriterImpl::WriteSection(MCAssembler &Asm,
|
| +void ELFObjectWriter::WriteSection(MCAssembler &Asm,
|
| const SectionIndexMapTy &SectionIndexMap,
|
| uint32_t GroupSymbolIndex,
|
| uint64_t Offset, uint64_t Size,
|
| @@ -1391,7 +992,7 @@
|
| Alignment, Section.getEntrySize());
|
| }
|
|
|
| -void ELFObjectWriterImpl::WriteObject(MCAssembler &Asm,
|
| +void ELFObjectWriter::WriteObject(MCAssembler &Asm,
|
| const MCAsmLayout &Layout) {
|
|
|
| GroupMapTy GroupMap;
|
| @@ -1461,7 +1062,7 @@
|
|
|
| FileOff += Layout.getSectionFileSize(&SD);
|
|
|
| - Asm.WriteSectionData(&SD, Layout, Writer);
|
| + Asm.WriteSectionData(&SD, Layout, this);
|
| }
|
|
|
| uint64_t Padding = OffsetToAlignment(FileOff, NaturalAlignment);
|
| @@ -1493,44 +1094,261 @@
|
| }
|
| }
|
|
|
| -ELFObjectWriter::ELFObjectWriter(raw_ostream &OS,
|
| - bool Is64Bit,
|
| - Triple::OSType OSType,
|
| - uint16_t EMachine,
|
| - bool IsLittleEndian,
|
| - bool HasRelocationAddend)
|
| - : MCObjectWriter(OS, IsLittleEndian)
|
| +ELFObjectWriter::ELFObjectWriter(raw_ostream &_OS,
|
| + bool _Is64Bit,
|
| + Triple::OSType _OSType,
|
| + uint16_t _EMachine,
|
| + bool _IsLittleEndian,
|
| + bool _HasRelocationAddend)
|
| + : MCObjectWriter(_OS, _IsLittleEndian),
|
| + NeedsGOT(false), NeedsSymtabShndx(false),
|
| + Is64Bit(_Is64Bit), HasRelocationAddend(_HasRelocationAddend),
|
| + OSType(_OSType), EMachine(_EMachine)
|
| {
|
| - Impl = new ELFObjectWriterImpl(this, Is64Bit, EMachine,
|
| - HasRelocationAddend, OSType);
|
| +// Impl = new ELFObjectWriterImpl(this, Is64Bit, EMachine,
|
| +// HasRelocationAddend, OSType);
|
| }
|
|
|
| -ELFObjectWriter::~ELFObjectWriter() {
|
| - delete (ELFObjectWriterImpl*) Impl;
|
| -}
|
| +//===- ARMELFObjectWriter -------------------------------------------===//
|
|
|
| -void ELFObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm) {
|
| - ((ELFObjectWriterImpl*) Impl)->ExecutePostLayoutBinding(Asm);
|
| -}
|
| +ARMELFObjectWriter::ARMELFObjectWriter(raw_ostream &OS, bool Is64Bit,
|
| + Triple::OSType OSType,
|
| + uint16_t EMachine, bool IsLittleEndian,
|
| + bool HasRelocationAddend)
|
| + : ELFObjectWriter(OS, Is64Bit, OSType, EMachine, IsLittleEndian,
|
| + HasRelocationAddend)
|
| +{}
|
|
|
| -void ELFObjectWriter::RecordRelocation(const MCAssembler &Asm,
|
| - const MCAsmLayout &Layout,
|
| - const MCFragment *Fragment,
|
| - const MCFixup &Fixup, MCValue Target,
|
| - uint64_t &FixedValue) {
|
| - ((ELFObjectWriterImpl*) Impl)->RecordRelocation(Asm, Layout, Fragment, Fixup,
|
| - Target, FixedValue);
|
| -}
|
| +ARMELFObjectWriter::~ARMELFObjectWriter()
|
| +{}
|
|
|
| -bool ELFObjectWriter::IsFixupFullyResolved(const MCAssembler &Asm,
|
| - const MCValue Target,
|
| - bool IsPCRel,
|
| - const MCFragment *DF) const {
|
| - return ((ELFObjectWriterImpl*) Impl)->IsFixupFullyResolved(Asm, Target,
|
| - IsPCRel, DF);
|
| +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");
|
| }
|
|
|
| -void ELFObjectWriter::WriteObject(MCAssembler &Asm,
|
| - const MCAsmLayout &Layout) {
|
| - ((ELFObjectWriterImpl*) Impl)->WriteObject(Asm, Layout);
|
| +
|
| +
|
| +//===- X86ELFObjectWriter -------------------------------------------===//
|
| +
|
| +
|
| +X86ELFObjectWriter::X86ELFObjectWriter(raw_ostream &OS, bool Is64Bit,
|
| + Triple::OSType OSType,
|
| + uint16_t EMachine, bool IsLittleEndian,
|
| + bool HasRelocationAddend)
|
| + : ELFObjectWriter(OS, Is64Bit, OSType, EMachine, IsLittleEndian,
|
| + HasRelocationAddend)
|
| +{}
|
| +
|
| +X86ELFObjectWriter::~X86ELFObjectWriter()
|
| +{}
|
| +
|
| +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 = AliasedSymbol(Symbol);
|
| + const MCSymbol *RenamedP = Renames.lookup(&Symbol);
|
| + if (!RenamedP)
|
| + RenamedP = &ASymbol;
|
| + const MCSymbol &Renamed = *RenamedP;
|
| +
|
| + bool IsPCRel = isFixupKindX86PCRel(Fixup.getKind());
|
| + if (!Target.isAbsolute()) {
|
| + MCSymbolData &SD = Asm.getSymbolData(Symbol);
|
| + MCFragment *F = SD.getFragment();
|
| +
|
| + if (const MCSymbolRefExpr *RefB = Target.getSymB()) {
|
| + const MCSymbol &SymbolB = RefB->getSymbol();
|
| + MCSymbolData &SDB = Asm.getSymbolData(SymbolB);
|
| + IsPCRel = true;
|
| + MCSectionData *Sec = Fragment->getParent();
|
| +
|
| + // Offset of the symbol in the section
|
| + int64_t a = Layout.getSymbolAddress(&SDB) - Layout.getSectionAddress(Sec);
|
| +
|
| + // Ofeset of the relocation in the section
|
| + int64_t b = Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
|
| + Value += b - a;
|
| + }
|
| +
|
| + bool RelocOnSymbol = ShouldRelocOnSymbol(SD, Target, *Fragment);
|
| + if (!RelocOnSymbol) {
|
| + 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(&Renamed);
|
| + else
|
| + UsedInReloc.insert(&Renamed);
|
| + Index = -1;
|
| + }
|
| + Addend = Value;
|
| + // Compensate for the addend on i386.
|
| + if (Is64Bit)
|
| + Value = 0;
|
| + }
|
| +
|
| + FixedValue = Value;
|
| +
|
| + // determine the type of the relocation
|
| +
|
| + MCSymbolRefExpr::VariantKind Modifier = Target.getSymA()->getKind();
|
| + unsigned Type;
|
| + 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;
|
| + 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_TLSGD:
|
| + Type = ELF::R_X86_64_TLSGD;
|
| + break;
|
| + case MCSymbolRefExpr::VK_TLSLD:
|
| + Type = ELF::R_X86_64_TLSLD;
|
| + break;
|
| + }
|
| + } else {
|
| + switch ((unsigned)Fixup.getKind()) {
|
| + 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:
|
| + llvm_unreachable("Unimplemented");
|
| + case MCSymbolRefExpr::VK_None:
|
| + Type = ELF::R_X86_64_32S;
|
| + break;
|
| + case MCSymbolRefExpr::VK_GOT:
|
| + Type = ELF::R_X86_64_GOT32;
|
| + break;
|
| + case MCSymbolRefExpr::VK_GOTPCREL:
|
| + Type = ELF::R_X86_64_GOTPCREL;
|
| + break;
|
| + case MCSymbolRefExpr::VK_TPOFF:
|
| + Type = ELF::R_X86_64_TPOFF32;
|
| + break;
|
| + case MCSymbolRefExpr::VK_DTPOFF:
|
| + Type = ELF::R_X86_64_DTPOFF32;
|
| + break;
|
| + }
|
| + break;
|
| + case FK_Data_4:
|
| + 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_Data_1: Type = ELF::R_X86_64_8; break;
|
| + }
|
| + }
|
| + } else {
|
| + if (IsPCRel) {
|
| + switch (Modifier) {
|
| + default:
|
| + llvm_unreachable("Unimplemented");
|
| + case MCSymbolRefExpr::VK_None:
|
| + Type = ELF::R_386_PC32;
|
| + break;
|
| + case MCSymbolRefExpr::VK_PLT:
|
| + Type = ELF::R_386_PLT32;
|
| + break;
|
| + }
|
| + } else {
|
| + switch ((unsigned)Fixup.getKind()) {
|
| + default: llvm_unreachable("invalid fixup kind!");
|
| +
|
| + case X86::reloc_global_offset_table:
|
| + Type = ELF::R_386_GOTPC;
|
| + break;
|
| +
|
| + // 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_Data_4:
|
| + switch (Modifier) {
|
| + default:
|
| + llvm_unreachable("Unimplemented");
|
| + case MCSymbolRefExpr::VK_None:
|
| + Type = ELF::R_386_32;
|
| + break;
|
| + case MCSymbolRefExpr::VK_GOT:
|
| + Type = ELF::R_386_GOT32;
|
| + break;
|
| + case MCSymbolRefExpr::VK_GOTOFF:
|
| + Type = ELF::R_386_GOTOFF;
|
| + break;
|
| + case MCSymbolRefExpr::VK_TLSGD:
|
| + Type = ELF::R_386_TLS_GD;
|
| + break;
|
| + case MCSymbolRefExpr::VK_TPOFF:
|
| + Type = ELF::R_386_TLS_LE_32;
|
| + break;
|
| + case MCSymbolRefExpr::VK_INDNTPOFF:
|
| + Type = ELF::R_386_TLS_IE;
|
| + break;
|
| + case MCSymbolRefExpr::VK_NTPOFF:
|
| + Type = ELF::R_386_TLS_LE;
|
| + break;
|
| + case MCSymbolRefExpr::VK_GOTNTPOFF:
|
| + Type = ELF::R_386_TLS_GOTIE;
|
| + break;
|
| + case MCSymbolRefExpr::VK_TLSLDM:
|
| + Type = ELF::R_386_TLS_LDM;
|
| + break;
|
| + case MCSymbolRefExpr::VK_DTPOFF:
|
| + Type = ELF::R_386_TLS_LDO_32;
|
| + break;
|
| + }
|
| + break;
|
| + case FK_Data_2: Type = ELF::R_386_16; break;
|
| + case X86::reloc_pcrel_1byte:
|
| + case FK_Data_1: Type = ELF::R_386_8; break;
|
| + }
|
| + }
|
| + }
|
| +
|
| + if (RelocNeedsGOT(Modifier))
|
| + NeedsGOT = true;
|
| +
|
| + ELFRelocationEntry ERE;
|
| +
|
| + ERE.Index = Index;
|
| + ERE.Type = Type;
|
| + ERE.Symbol = &Renamed;
|
| +
|
| + 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);
|
| }
|
|
|