diff options
author | Rafael Espindola <rafael.espindola@gmail.com> | 2011-12-22 03:38:00 +0000 |
---|---|---|
committer | Rafael Espindola <rafael.espindola@gmail.com> | 2011-12-22 03:38:00 +0000 |
commit | 3963d617b3709c510003ac816fb42f28539fc62b (patch) | |
tree | 937accefd8911fc515462c86c72ec049bf09a8c7 /lib/MC/ELFObjectWriter.cpp | |
parent | 7bd278019d745d8b339f6b896926ce32ce118db7 (diff) | |
download | llvm-3963d617b3709c510003ac816fb42f28539fc62b.tar.gz llvm-3963d617b3709c510003ac816fb42f28539fc62b.tar.bz2 llvm-3963d617b3709c510003ac816fb42f28539fc62b.tar.xz |
Kill the monstrosity that was ELFObjectWriter.h.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@147136 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/MC/ELFObjectWriter.cpp')
-rw-r--r-- | lib/MC/ELFObjectWriter.cpp | 332 |
1 files changed, 331 insertions, 1 deletions
diff --git a/lib/MC/ELFObjectWriter.cpp b/lib/MC/ELFObjectWriter.cpp index e342429797..8a66e04ed4 100644 --- a/lib/MC/ELFObjectWriter.cpp +++ b/lib/MC/ELFObjectWriter.cpp @@ -11,13 +11,19 @@ // //===----------------------------------------------------------------------===// -#include "ELFObjectWriter.h" +#include "MCELF.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/Twine.h" #include "llvm/MC/MCAsmBackend.h" #include "llvm/MC/MCAsmLayout.h" +#include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCContext.h" +#include "llvm/MC/MCELFObjectWriter.h" +#include "llvm/MC/MCELFSymbolFlags.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCSectionELF.h" #include "llvm/MC/MCValue.h" @@ -33,6 +39,330 @@ using namespace llvm; #undef DEBUG_TYPE #define DEBUG_TYPE "reloc-info" +namespace { +class ELFObjectWriter : public MCObjectWriter { + protected: + + static bool isFixupKindPCRel(const MCAssembler &Asm, unsigned Kind); + static bool RelocNeedsGOT(MCSymbolRefExpr::VariantKind Variant); + static uint64_t SymbolValue(MCSymbolData &Data, const MCAsmLayout &Layout); + static bool isInSymtab(const MCAssembler &Asm, const MCSymbolData &Data, + bool Used, bool Renamed); + static bool isLocal(const MCSymbolData &Data, bool isSignature, + bool isUsedInReloc); + static bool IsELFMetaDataSection(const MCSectionData &SD); + static uint64_t DataSectionSize(const MCSectionData &SD); + static uint64_t GetSectionFileSize(const MCAsmLayout &Layout, + const MCSectionData &SD); + static uint64_t GetSectionAddressSize(const MCAsmLayout &Layout, + const MCSectionData &SD); + + void WriteDataSectionData(MCAssembler &Asm, + const MCAsmLayout &Layout, + const MCSectionELF &Section); + + /*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 (MCELF::GetType(*SymbolData) == ELF::STT_FILE) + return true; + if (MCELF::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; + + ELFRelocationEntry() + : r_offset(0), Index(0), Type(0), Symbol(0), r_addend(0) {} + + ELFRelocationEntry(uint64_t RelocOffset, int Idx, + unsigned RelType, const MCSymbol *Sym, + uint64_t Addend) + : r_offset(RelocOffset), Index(Idx), Type(RelType), + Symbol(Sym), r_addend(Addend) {} + + // Support lexicographic sorting. + bool operator<(const ELFRelocationEntry &RE) const { + return RE.r_offset < r_offset; + } + }; + + /// The target specific ELF writer instance. + llvm::OwningPtr<MCELFObjectTargetWriter> TargetObjectWriter; + + 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; + + // 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 MCFixup &Fixup, + bool IsPCRel) const; + + // TargetObjectWriter wrappers. + const MCSymbol *ExplicitRelSym(const MCAssembler &Asm, + const MCValue &Target, + const MCFragment &F, + const MCFixup &Fixup, + bool IsPCRel) const { + return TargetObjectWriter->ExplicitRelSym(Asm, Target, F, Fixup, IsPCRel); + } + + bool is64Bit() const { return TargetObjectWriter->is64Bit(); } + bool hasRelocationAddend() const { + return TargetObjectWriter->hasRelocationAddend(); + } + unsigned getEFlags() const { + return TargetObjectWriter->getEFlags(); + } + unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, + bool IsPCRel, bool IsRelocWithSymbol, + int64_t Addend) const { + return TargetObjectWriter->GetRelocType(Target, Fixup, IsPCRel, + IsRelocWithSymbol, Addend); + } + + + public: + ELFObjectWriter(MCELFObjectTargetWriter *MOTW, + raw_ostream &_OS, bool IsLittleEndian) + : MCObjectWriter(_OS, IsLittleEndian), + TargetObjectWriter(MOTW), + NeedsGOT(false), NeedsSymtabShndx(false){ + } + + 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); + } + + 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); + + virtual 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); + + // 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; + // Map from a section to the section with the relocations + typedef DenseMap<const MCSectionELF*, const MCSectionELF*> RelMapTy; + // Map from a section to its offset + typedef DenseMap<const MCSectionELF*, uint64_t> SectionOffsetMapTy; + + /// 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, + RevGroupMapTy RevGroupMap, + unsigned NumRegularSections); + + void ComputeIndexMap(MCAssembler &Asm, + SectionIndexMapTy &SectionIndexMap, + const RelMapTy &RelMap); + + void CreateRelocationSections(MCAssembler &Asm, MCAsmLayout &Layout, + RelMapTy &RelMap); + + void WriteRelocations(MCAssembler &Asm, MCAsmLayout &Layout, + const RelMapTy &RelMap); + + void CreateMetadataSections(MCAssembler &Asm, MCAsmLayout &Layout, + SectionIndexMapTy &SectionIndexMap, + const RelMapTy &RelMap); + + // Create the sections that show up in the symbol table. Currently + // those are the .note.GNU-stack section and the group sections. + void CreateIndexedSections(MCAssembler &Asm, MCAsmLayout &Layout, + GroupMapTy &GroupMap, + RevGroupMapTy &RevGroupMap, + SectionIndexMapTy &SectionIndexMap, + const RelMapTy &RelMap); + + virtual void ExecutePostLayoutBinding(MCAssembler &Asm, + const MCAsmLayout &Layout); + + void WriteSectionHeader(MCAssembler &Asm, const GroupMapTy &GroupMap, + const MCAsmLayout &Layout, + const SectionIndexMapTy &SectionIndexMap, + const SectionOffsetMapTy &SectionOffsetMap); + + void ComputeSectionOrder(MCAssembler &Asm, + std::vector<const MCSectionELF*> &Sections); + + 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); + + virtual bool + IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, + const MCSymbolData &DataA, + const MCFragment &FB, + bool InSet, + bool IsPCRel) const; + + virtual 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); + }; +} + bool ELFObjectWriter::isFixupKindPCRel(const MCAssembler &Asm, unsigned Kind) { const MCFixupKindInfo &FKI = Asm.getBackend().getFixupKindInfo((MCFixupKind) Kind); |