| //===- lib/MC/ELFObjectWriter.h - ELF File Writer -------------------------===// | |
| // | |
| // The LLVM Compiler Infrastructure | |
| // | |
| // This file is distributed under the University of Illinois Open Source | |
| // License. See LICENSE.TXT for details. | |
| // | |
| //===----------------------------------------------------------------------===// | |
| // | |
| // This file implements ELF object file writer information. | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #ifndef LLVM_MC_ELFOBJECTWRITER_H | |
| #define LLVM_MC_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/MC/MCAssembler.h" | |
| #include "llvm/MC/MCELFObjectWriter.h" | |
| #include "llvm/MC/MCELFSymbolFlags.h" | |
| #include "llvm/MC/MCObjectWriter.h" | |
| #include "llvm/MC/MCExpr.h" | |
| #include "llvm/MC/MCSymbol.h" | |
| #include <vector> | |
| namespace llvm { | |
| class MCSection; | |
| class MCDataFragment; | |
| class MCSectionELF; | |
| 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; | |
| virtual const MCSymbol *SymbolToReloc(const MCAssembler &Asm, | |
| const MCValue &Target, | |
| const MCFragment &F, | |
| const MCFixup &Fixup, | |
| bool IsPCRel) const; | |
| // For arch-specific emission of explicit reloc symbol | |
| virtual const MCSymbol *ExplicitRelSym(const MCAssembler &Asm, | |
| const MCValue &Target, | |
| const MCFragment &F, | |
| const MCFixup &Fixup, | |
| bool IsPCRel) const { | |
| return NULL; | |
| } | |
| bool is64Bit() const { return TargetObjectWriter->is64Bit(); } | |
| bool hasRelocationAddend() const { | |
| return TargetObjectWriter->hasRelocationAddend(); | |
| } | |
| 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); | |
| } | |
| virtual void WriteHeader(uint64_t SectionDataSize, unsigned NumberOfSections); | |
| /// Default e_flags = 0 | |
| virtual void WriteEFlags() { Write32(0); } | |
| 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); | |
| 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; | |
| // 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. | |
| virtual void ComputeSymbolTable(MCAssembler &Asm, | |
| const SectionIndexMapTy &SectionIndexMap, | |
| RevGroupMapTy RevGroupMap, | |
| unsigned NumRegularSections); | |
| virtual 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); | |
| virtual 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. | |
| virtual 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); | |
| 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 | |
| IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, | |
| const MCSymbolData &DataA, | |
| const MCFragment &FB, | |
| bool InSet, | |
| bool IsPCRel) 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); | |
| protected: | |
| virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, | |
| bool IsPCRel, bool IsRelocWithSymbol, | |
| int64_t Addend) = 0; | |
| virtual void adjustFixupOffset(const MCFixup &Fixup, uint64_t &RelocOffset) { } | |
| }; | |
| //===- X86ELFObjectWriter -------------------------------------------===// | |
| class X86ELFObjectWriter : public ELFObjectWriter { | |
| public: | |
| X86ELFObjectWriter(MCELFObjectTargetWriter *MOTW, | |
| raw_ostream &_OS, | |
| bool IsLittleEndian); | |
| virtual ~X86ELFObjectWriter(); | |
| protected: | |
| virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, | |
| bool IsPCRel, bool IsRelocWithSymbol, | |
| int64_t Addend); | |
| }; | |
| //===- ARMELFObjectWriter -------------------------------------------===// | |
| class ARMELFObjectWriter : public ELFObjectWriter { | |
| public: | |
| // FIXME: MCAssembler can't yet return the Subtarget, | |
| enum { DefaultEABIVersion = 0x05000000U }; | |
| ARMELFObjectWriter(MCELFObjectTargetWriter *MOTW, | |
| raw_ostream &_OS, | |
| bool IsLittleEndian); | |
| virtual ~ARMELFObjectWriter(); | |
| virtual void WriteEFlags(); | |
| protected: | |
| virtual const MCSymbol *ExplicitRelSym(const MCAssembler &Asm, | |
| const MCValue &Target, | |
| const MCFragment &F, | |
| const MCFixup &Fixup, | |
| bool IsPCRel) const; | |
| virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, | |
| bool IsPCRel, bool IsRelocWithSymbol, | |
| int64_t Addend); | |
| private: | |
| unsigned GetRelocTypeInner(const MCValue &Target, | |
| const MCFixup &Fixup, bool IsPCRel) const; | |
| }; | |
| //===- PPCELFObjectWriter -------------------------------------------===// | |
| class PPCELFObjectWriter : public ELFObjectWriter { | |
| public: | |
| PPCELFObjectWriter(MCELFObjectTargetWriter *MOTW, | |
| raw_ostream &_OS, | |
| bool IsLittleEndian); | |
| virtual ~PPCELFObjectWriter(); | |
| protected: | |
| virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, | |
| bool IsPCRel, bool IsRelocWithSymbol, | |
| int64_t Addend); | |
| virtual void adjustFixupOffset(const MCFixup &Fixup, uint64_t &RelocOffset); | |
| }; | |
| //===- MBlazeELFObjectWriter -------------------------------------------===// | |
| class MBlazeELFObjectWriter : public ELFObjectWriter { | |
| public: | |
| MBlazeELFObjectWriter(MCELFObjectTargetWriter *MOTW, | |
| raw_ostream &_OS, | |
| bool IsLittleEndian); | |
| virtual ~MBlazeELFObjectWriter(); | |
| protected: | |
| virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, | |
| bool IsPCRel, bool IsRelocWithSymbol, | |
| int64_t Addend); | |
| }; | |
| //===- MipsELFObjectWriter -------------------------------------------===// | |
| class MipsELFObjectWriter : public ELFObjectWriter { | |
| public: | |
| MipsELFObjectWriter(MCELFObjectTargetWriter *MOTW, | |
| raw_ostream &_OS, | |
| bool IsLittleEndian); | |
| virtual ~MipsELFObjectWriter(); | |
| protected: | |
| virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, | |
| bool IsPCRel, bool IsRelocWithSymbol, | |
| int64_t Addend); | |
| }; | |
| } | |
| #endif |