|  | //===- 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 |