X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=include%2Fllvm%2FObject%2FELF.h;h=823491613a0416809202a53de805b14713bdca20;hb=f38cc38fa647d4e72c053c39bbe0cdec1342535f;hp=46b62de19e310785a629c64bd30489326c1ff4e1;hpb=95abfbe8e9567e08188ada7d29f589f08e539bd6;p=oota-llvm.git diff --git a/include/llvm/Object/ELF.h b/include/llvm/Object/ELF.h index 46b62de19e3..823491613a0 100644 --- a/include/llvm/Object/ELF.h +++ b/include/llvm/Object/ELF.h @@ -35,6 +35,13 @@ namespace object { using support::endianness; +template +struct ELFType { + static const endianness TargetEndianness = target_endianness; + static const std::size_t MaxAlignment = max_alignment; + static const bool Is64Bits = is64Bits; +}; + template struct MaximumAlignment { enum {value = AlignOf::Alignment > max_align ? max_align @@ -46,8 +53,8 @@ inline std::pair getElfArchType(MemoryBuffer *Object) { if (Object->getBufferSize() < ELF::EI_NIDENT) return std::make_pair((uint8_t)ELF::ELFCLASSNONE,(uint8_t)ELF::ELFDATANONE); - return std::make_pair( (uint8_t)Object->getBufferStart()[ELF::EI_CLASS] - , (uint8_t)Object->getBufferStart()[ELF::EI_DATA]); + return std::make_pair((uint8_t) Object->getBufferStart()[ELF::EI_CLASS], + (uint8_t) Object->getBufferStart()[ELF::EI_DATA]); } // Templates to choose Elf_Addr and Elf_Off depending on is64Bits. @@ -70,59 +77,59 @@ struct ELFDataTypeTypedefHelperCommon { MaximumAlignment::value> Elf_Sxword; }; -template +template struct ELFDataTypeTypedefHelper; /// ELF 32bit types. -template -struct ELFDataTypeTypedefHelper - : ELFDataTypeTypedefHelperCommon { +template +struct ELFDataTypeTypedefHelper > + : ELFDataTypeTypedefHelperCommon { typedef uint32_t value_type; typedef support::detail::packed_endian_specific_integral - ::value> Elf_Addr; + ::value> Elf_Addr; typedef support::detail::packed_endian_specific_integral - ::value> Elf_Off; + ::value> Elf_Off; }; /// ELF 64bit types. -template -struct ELFDataTypeTypedefHelper - : ELFDataTypeTypedefHelperCommon{ +template +struct ELFDataTypeTypedefHelper > + : ELFDataTypeTypedefHelperCommon { typedef uint64_t value_type; typedef support::detail::packed_endian_specific_integral - ::value> Elf_Addr; + ::value> Elf_Addr; typedef support::detail::packed_endian_specific_integral - ::value> Elf_Off; + ::value> Elf_Off; }; // I really don't like doing this, but the alternative is copypasta. -#define LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, is64Bits) \ -typedef typename ELFDataTypeTypedefHelper \ - ::Elf_Addr Elf_Addr; \ -typedef typename ELFDataTypeTypedefHelper \ - ::Elf_Off Elf_Off; \ -typedef typename ELFDataTypeTypedefHelper \ - ::Elf_Half Elf_Half; \ -typedef typename ELFDataTypeTypedefHelper \ - ::Elf_Word Elf_Word; \ -typedef typename ELFDataTypeTypedefHelper \ - ::Elf_Sword Elf_Sword; \ -typedef typename ELFDataTypeTypedefHelper \ - ::Elf_Xword Elf_Xword; \ -typedef typename ELFDataTypeTypedefHelper \ - ::Elf_Sxword Elf_Sxword; - - // Section header. -template +#define LLVM_ELF_IMPORT_TYPES(E, M, W) \ +typedef typename ELFDataTypeTypedefHelper >::Elf_Addr Elf_Addr; \ +typedef typename ELFDataTypeTypedefHelper >::Elf_Off Elf_Off; \ +typedef typename ELFDataTypeTypedefHelper >::Elf_Half Elf_Half; \ +typedef typename ELFDataTypeTypedefHelper >::Elf_Word Elf_Word; \ +typedef typename \ + ELFDataTypeTypedefHelper >::Elf_Sword Elf_Sword; \ +typedef typename \ + ELFDataTypeTypedefHelper >::Elf_Xword Elf_Xword; \ +typedef typename \ + ELFDataTypeTypedefHelper >::Elf_Sxword Elf_Sxword; + +#define LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) \ + LLVM_ELF_IMPORT_TYPES(ELFT::TargetEndianness, ELFT::MaxAlignment, \ + ELFT::Is64Bits) + +// Section header. +template struct Elf_Shdr_Base; -template -struct Elf_Shdr_Base { - LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, false) +template +struct Elf_Shdr_Base > { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) Elf_Word sh_name; // Section name (index into string table) Elf_Word sh_type; // Section type (SHT_*) Elf_Word sh_flags; // Section flags (SHF_*) @@ -135,9 +142,9 @@ struct Elf_Shdr_Base { Elf_Word sh_entsize; // Size of records contained within the section }; -template -struct Elf_Shdr_Base { - LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, true) +template +struct Elf_Shdr_Base > { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) Elf_Word sh_name; // Section name (index into string table) Elf_Word sh_type; // Section type (SHT_*) Elf_Xword sh_flags; // Section flags (SHF_*) @@ -150,11 +157,10 @@ struct Elf_Shdr_Base { Elf_Xword sh_entsize; // Size of records contained within the section }; -template -struct Elf_Shdr_Impl - : Elf_Shdr_Base { - using Elf_Shdr_Base::sh_entsize; - using Elf_Shdr_Base::sh_size; +template +struct Elf_Shdr_Impl : Elf_Shdr_Base { + using Elf_Shdr_Base::sh_entsize; + using Elf_Shdr_Base::sh_size; /// @brief Get the number of entities this section contains if it has any. unsigned getEntityCount() const { @@ -164,14 +170,12 @@ struct Elf_Shdr_Impl } }; -template< endianness target_endianness - , std::size_t max_alignment - , bool is64Bits> +template struct Elf_Sym_Base; -template -struct Elf_Sym_Base { - LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, false) +template +struct Elf_Sym_Base > { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) Elf_Word st_name; // Symbol name (index into string table) Elf_Addr st_value; // Value or address associated with the symbol Elf_Word st_size; // Size of the symbol @@ -180,9 +184,9 @@ struct Elf_Sym_Base { Elf_Half st_shndx; // Which section (header table index) it's defined in }; -template -struct Elf_Sym_Base { - LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, true) +template +struct Elf_Sym_Base > { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) Elf_Word st_name; // Symbol name (index into string table) unsigned char st_info; // Symbol's type and binding attributes unsigned char st_other; // Must be zero; reserved @@ -191,10 +195,9 @@ struct Elf_Sym_Base { Elf_Xword st_size; // Size of the symbol }; -template -struct Elf_Sym_Impl - : Elf_Sym_Base { - using Elf_Sym_Base::st_info; +template +struct Elf_Sym_Impl : Elf_Sym_Base { + using Elf_Sym_Base::st_info; // These accessors and mutators correspond to the ELF32_ST_BIND, // ELF32_ST_TYPE, and ELF32_ST_INFO macros defined in the ELF specification: @@ -209,22 +212,21 @@ struct Elf_Sym_Impl /// Elf_Versym: This is the structure of entries in the SHT_GNU_versym section /// (.gnu.version). This structure is identical for ELF32 and ELF64. -template +template struct Elf_Versym_Impl { - LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, is64Bits) + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) Elf_Half vs_index; // Version index with flags (e.g. VERSYM_HIDDEN) }; -template +template struct Elf_Verdaux_Impl; /// Elf_Verdef: This is the structure of entries in the SHT_GNU_verdef section /// (.gnu.version_d). This structure is identical for ELF32 and ELF64. -template +template struct Elf_Verdef_Impl { - LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, is64Bits) - typedef - Elf_Verdaux_Impl Elf_Verdaux; + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) + typedef Elf_Verdaux_Impl Elf_Verdaux; Elf_Half vd_version; // Version of this structure (e.g. VER_DEF_CURRENT) Elf_Half vd_flags; // Bitwise flags (VER_DEF_*) Elf_Half vd_ndx; // Version index, used in .gnu.version entries @@ -241,18 +243,18 @@ struct Elf_Verdef_Impl { /// Elf_Verdaux: This is the structure of auxiliary data in the SHT_GNU_verdef /// section (.gnu.version_d). This structure is identical for ELF32 and ELF64. -template +template struct Elf_Verdaux_Impl { - LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, is64Bits) + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) Elf_Word vda_name; // Version name (offset in string table) Elf_Word vda_next; // Offset to next Verdaux entry (in bytes) }; /// Elf_Verneed: This is the structure of entries in the SHT_GNU_verneed /// section (.gnu.version_r). This structure is identical for ELF32 and ELF64. -template +template struct Elf_Verneed_Impl { - LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, is64Bits) + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) Elf_Half vn_version; // Version of this structure (e.g. VER_NEED_CURRENT) Elf_Half vn_cnt; // Number of associated Vernaux entries Elf_Word vn_file; // Library name (string table offset) @@ -262,9 +264,9 @@ struct Elf_Verneed_Impl { /// Elf_Vernaux: This is the structure of auxiliary data in SHT_GNU_verneed /// section (.gnu.version_r). This structure is identical for ELF32 and ELF64. -template +template struct Elf_Vernaux_Impl { - LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, is64Bits) + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) Elf_Word vna_hash; // Hash of dependency name Elf_Half vna_flags; // Bitwise Flags (VER_FLAG_*) Elf_Half vna_other; // Version index, used in .gnu.version entries @@ -274,12 +276,12 @@ struct Elf_Vernaux_Impl { /// Elf_Dyn_Base: This structure matches the form of entries in the dynamic /// table section (.dynamic) look like. -template +template struct Elf_Dyn_Base; -template -struct Elf_Dyn_Base { - LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, false) +template +struct Elf_Dyn_Base > { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) Elf_Sword d_tag; union { Elf_Word d_val; @@ -287,9 +289,9 @@ struct Elf_Dyn_Base { } d_un; }; -template -struct Elf_Dyn_Base { - LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, true) +template +struct Elf_Dyn_Base > { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) Elf_Sxword d_tag; union { Elf_Xword d_val; @@ -298,126 +300,141 @@ struct Elf_Dyn_Base { }; /// Elf_Dyn_Impl: This inherits from Elf_Dyn_Base, adding getters and setters. -template -struct Elf_Dyn_Impl : Elf_Dyn_Base { - using Elf_Dyn_Base::d_tag; - using Elf_Dyn_Base::d_un; +template +struct Elf_Dyn_Impl : Elf_Dyn_Base { + using Elf_Dyn_Base::d_tag; + using Elf_Dyn_Base::d_un; int64_t getTag() const { return d_tag; } uint64_t getVal() const { return d_un.d_val; } uint64_t getPtr() const { return d_un.ptr; } }; -template -class ELFObjectFile; - -// DynRefImpl: Reference to an entry in the dynamic table -// This is an ELF-specific interface. -template -class DynRefImpl { - typedef Elf_Dyn_Impl Elf_Dyn; - typedef ELFObjectFile OwningType; - - DataRefImpl DynPimpl; - const OwningType *OwningObject; - -public: - DynRefImpl() : OwningObject(NULL) { } - - DynRefImpl(DataRefImpl DynP, const OwningType *Owner); - - bool operator==(const DynRefImpl &Other) const; - bool operator <(const DynRefImpl &Other) const; - - error_code getNext(DynRefImpl &Result) const; - int64_t getTag() const; - uint64_t getVal() const; - uint64_t getPtr() const; - - DataRefImpl getRawDataRefImpl() const; -}; - // Elf_Rel: Elf Relocation -template< endianness target_endianness - , std::size_t max_alignment - , bool is64Bits - , bool isRela> +template struct Elf_Rel_Base; -template -struct Elf_Rel_Base { - LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, false) - Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) - Elf_Word r_info; // Symbol table index and type of relocation to apply +template +struct Elf_Rel_Base, false> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) + Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) + Elf_Word r_info; // Symbol table index and type of relocation to apply + + uint32_t getRInfo(bool isMips64EL) const { + assert(!isMips64EL); + return r_info; + } + void setRInfo(uint32_t R) { + r_info = R; + } }; -template -struct Elf_Rel_Base { - LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, true) - Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) - Elf_Xword r_info; // Symbol table index and type of relocation to apply +template +struct Elf_Rel_Base, false> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) + Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) + Elf_Xword r_info; // Symbol table index and type of relocation to apply + + uint64_t getRInfo(bool isMips64EL) const { + uint64_t t = r_info; + if (!isMips64EL) + return t; + // Mips64 little endian has a "special" encoding of r_info. Instead of one + // 64 bit little endian number, it is a little endian 32 bit number followed + // by a 32 bit big endian number. + return (t << 32) | ((t >> 8) & 0xff000000) | ((t >> 24) & 0x00ff0000) | + ((t >> 40) & 0x0000ff00) | ((t >> 56) & 0x000000ff); + } + void setRInfo(uint64_t R) { + // FIXME: Add mips64el support. + r_info = R; + } }; -template -struct Elf_Rel_Base { - LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, false) - Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) - Elf_Word r_info; // Symbol table index and type of relocation to apply - Elf_Sword r_addend; // Compute value for relocatable field by adding this +template +struct Elf_Rel_Base, true> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) + Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) + Elf_Word r_info; // Symbol table index and type of relocation to apply + Elf_Sword r_addend; // Compute value for relocatable field by adding this + + uint32_t getRInfo(bool isMips64EL) const { + assert(!isMips64EL); + return r_info; + } + void setRInfo(uint32_t R) { + r_info = R; + } }; -template -struct Elf_Rel_Base { - LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, true) - Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) - Elf_Xword r_info; // Symbol table index and type of relocation to apply - Elf_Sxword r_addend; // Compute value for relocatable field by adding this. +template +struct Elf_Rel_Base, true> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) + Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) + Elf_Xword r_info; // Symbol table index and type of relocation to apply + Elf_Sxword r_addend; // Compute value for relocatable field by adding this. + + uint64_t getRInfo(bool isMips64EL) const { + // Mips64 little endian has a "special" encoding of r_info. Instead of one + // 64 bit little endian number, it is a little endian 32 bit number followed + // by a 32 bit big endian number. + uint64_t t = r_info; + if (!isMips64EL) + return t; + return (t << 32) | ((t >> 8) & 0xff000000) | ((t >> 24) & 0x00ff0000) | + ((t >> 40) & 0x0000ff00) | ((t >> 56) & 0x000000ff); + } + void setRInfo(uint64_t R) { + // FIXME: Add mips64el support. + r_info = R; + } }; -template< endianness target_endianness - , std::size_t max_alignment - , bool is64Bits - , bool isRela> +template struct Elf_Rel_Impl; -template -struct Elf_Rel_Impl - : Elf_Rel_Base { - using Elf_Rel_Base::r_info; - LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, true) +template +struct Elf_Rel_Impl, isRela> + : Elf_Rel_Base, isRela> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) // These accessors and mutators correspond to the ELF64_R_SYM, ELF64_R_TYPE, // and ELF64_R_INFO macros defined in the ELF specification: - uint64_t getSymbol() const { return (r_info >> 32); } - unsigned char getType() const { - return (unsigned char) (r_info & 0xffffffffL); + uint32_t getSymbol(bool isMips64EL) const { + return (uint32_t) (this->getRInfo(isMips64EL) >> 32); } - void setSymbol(uint64_t s) { setSymbolAndType(s, getType()); } - void setType(unsigned char t) { setSymbolAndType(getSymbol(), t); } - void setSymbolAndType(uint64_t s, unsigned char t) { - r_info = (s << 32) + (t&0xffffffffL); + uint32_t getType(bool isMips64EL) const { + return (uint32_t) (this->getRInfo(isMips64EL) & 0xffffffffL); + } + void setSymbol(uint32_t s) { setSymbolAndType(s, getType()); } + void setType(uint32_t t) { setSymbolAndType(getSymbol(), t); } + void setSymbolAndType(uint32_t s, uint32_t t) { + this->setRInfo(((uint64_t)s << 32) + (t&0xffffffffL)); } }; -template -struct Elf_Rel_Impl - : Elf_Rel_Base { - using Elf_Rel_Base::r_info; - LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, false) +template +struct Elf_Rel_Impl, isRela> + : Elf_Rel_Base, isRela> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) // These accessors and mutators correspond to the ELF32_R_SYM, ELF32_R_TYPE, // and ELF32_R_INFO macros defined in the ELF specification: - uint32_t getSymbol() const { return (r_info >> 8); } - unsigned char getType() const { return (unsigned char) (r_info & 0x0ff); } + uint32_t getSymbol(bool isMips64EL) const { + return this->getRInfo(isMips64EL) >> 8; + } + unsigned char getType(bool isMips64EL) const { + return (unsigned char) (this->getRInfo(isMips64EL) & 0x0ff); + } void setSymbol(uint32_t s) { setSymbolAndType(s, getType()); } void setType(unsigned char t) { setSymbolAndType(getSymbol(), t); } void setSymbolAndType(uint32_t s, unsigned char t) { - r_info = (s << 8) + t; + this->setRInfo((s << 8) + t); } }; -template +template struct Elf_Ehdr_Impl { - LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, is64Bits) + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) unsigned char e_ident[ELF::EI_NIDENT]; // ELF Identification bytes Elf_Half e_type; // Type of file (see ET_*) Elf_Half e_machine; // Required architecture for this file (see EM_*) @@ -440,12 +457,12 @@ struct Elf_Ehdr_Impl { unsigned char getDataEncoding() const { return e_ident[ELF::EI_DATA]; } }; -template +template struct Elf_Phdr_Impl; -template -struct Elf_Phdr_Impl { - LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, false) +template +struct Elf_Phdr_Impl > { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) Elf_Word p_type; // Type of segment Elf_Off p_offset; // FileOffset where segment is located, in bytes Elf_Addr p_vaddr; // Virtual Address of beginning of segment @@ -456,9 +473,9 @@ struct Elf_Phdr_Impl { Elf_Word p_align; // Segment alignment constraint }; -template -struct Elf_Phdr_Impl { - LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, true) +template +struct Elf_Phdr_Impl > { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) Elf_Word p_type; // Type of segment Elf_Word p_flags; // Segment flags Elf_Off p_offset; // FileOffset where segment is located, in bytes @@ -469,72 +486,18 @@ struct Elf_Phdr_Impl { Elf_Xword p_align; // Segment alignment constraint }; -template +template class ELFObjectFile : public ObjectFile { - LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, is64Bits) - - typedef Elf_Ehdr_Impl Elf_Ehdr; - typedef Elf_Shdr_Impl Elf_Shdr; - typedef Elf_Sym_Impl Elf_Sym; - typedef Elf_Dyn_Impl Elf_Dyn; - typedef Elf_Phdr_Impl Elf_Phdr; - typedef - Elf_Rel_Impl Elf_Rel; - typedef - Elf_Rel_Impl Elf_Rela; - typedef - Elf_Verdef_Impl Elf_Verdef; - typedef - Elf_Verdaux_Impl Elf_Verdaux; - typedef - Elf_Verneed_Impl Elf_Verneed; - typedef - Elf_Vernaux_Impl Elf_Vernaux; - typedef - Elf_Versym_Impl Elf_Versym; - typedef DynRefImpl DynRef; - typedef content_iterator dyn_iterator; - -protected: - // This flag is used for classof, to distinguish ELFObjectFile from - // its subclass. If more subclasses will be created, this flag will - // have to become an enum. - bool isDyldELFObject; - -private: - typedef SmallVector Sections_t; - typedef DenseMap IndexMap_t; - typedef DenseMap > RelocMap_t; - - const Elf_Ehdr *Header; - const Elf_Shdr *SectionHeaderTable; - const Elf_Shdr *dot_shstrtab_sec; // Section header string table. - const Elf_Shdr *dot_strtab_sec; // Symbol header string table. - const Elf_Shdr *dot_dynstr_sec; // Dynamic symbol string table. - - // SymbolTableSections[0] always points to the dynamic string table section - // header, or NULL if there is no dynamic string table. - Sections_t SymbolTableSections; - IndexMap_t SymbolTableSectionsIndexMap; - DenseMap ExtendedSymbolTable; - - const Elf_Shdr *dot_dynamic_sec; // .dynamic - const Elf_Shdr *dot_gnu_version_sec; // .gnu.version - const Elf_Shdr *dot_gnu_version_r_sec; // .gnu.version_r - const Elf_Shdr *dot_gnu_version_d_sec; // .gnu.version_d - - // Pointer to SONAME entry in dynamic string table - // This is set the first time getLoadName is called. - mutable const char *dt_soname; + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) public: /// \brief Iterate over constant sized entities. template class ELFEntityIterator { public: - typedef void difference_type; + typedef ptrdiff_t difference_type; typedef EntT value_type; - typedef std::forward_iterator_tag iterator_category; + typedef std::random_access_iterator_tag iterator_category; typedef value_type &reference; typedef value_type *pointer; @@ -574,12 +537,71 @@ public: return Tmp; } + ELFEntityIterator &operator =(const ELFEntityIterator &Other) { + EntitySize = Other.EntitySize; + Current = Other.Current; + return *this; + } + + difference_type operator -(const ELFEntityIterator &Other) const { + assert(EntitySize == Other.EntitySize && + "Subtracting iterators of different EntitiySize!"); + return (Current - Other.Current) / EntitySize; + } + + const char *get() const { return Current; } + private: - const uint64_t EntitySize; + uint64_t EntitySize; const char *Current; }; + typedef Elf_Ehdr_Impl Elf_Ehdr; + typedef Elf_Shdr_Impl Elf_Shdr; + typedef Elf_Sym_Impl Elf_Sym; + typedef Elf_Dyn_Impl Elf_Dyn; + typedef Elf_Phdr_Impl Elf_Phdr; + typedef Elf_Rel_Impl Elf_Rel; + typedef Elf_Rel_Impl Elf_Rela; + typedef Elf_Verdef_Impl Elf_Verdef; + typedef Elf_Verdaux_Impl Elf_Verdaux; + typedef Elf_Verneed_Impl Elf_Verneed; + typedef Elf_Vernaux_Impl Elf_Vernaux; + typedef Elf_Versym_Impl Elf_Versym; + typedef ELFEntityIterator Elf_Dyn_iterator; + typedef ELFEntityIterator Elf_Sym_iterator; + typedef ELFEntityIterator Elf_Rela_Iter; + typedef ELFEntityIterator Elf_Rel_Iter; + +protected: + // This flag is used for classof, to distinguish ELFObjectFile from + // its subclass. If more subclasses will be created, this flag will + // have to become an enum. + bool isDyldELFObject; + +private: + const Elf_Ehdr *Header; + const Elf_Shdr *SectionHeaderTable; + const Elf_Shdr *dot_shstrtab_sec; // Section header string table. + const Elf_Shdr *dot_strtab_sec; // Symbol header string table. + const Elf_Shdr *dot_dynstr_sec; // Dynamic symbol string table. + + int SymbolTableIndex; + int DynamicSymbolTableIndex; + DenseMap ExtendedSymbolTable; + + const Elf_Shdr *dot_dynamic_sec; // .dynamic + const Elf_Shdr *dot_gnu_version_sec; // .gnu.version + const Elf_Shdr *dot_gnu_version_r_sec; // .gnu.version_r + const Elf_Shdr *dot_gnu_version_d_sec; // .gnu.version_d + + // Pointer to SONAME entry in dynamic string table + // This is set the first time getLoadName is called. + mutable const char *dt_soname; + private: + uint64_t getROffset(DataRefImpl Rel) const; + // Records for each version index the corresponding Verdef or Vernaux entry. // This is filled the first time LoadVersionMap() is called. class VersionMapEntry : public PointerIntPair { @@ -606,18 +628,15 @@ private: void LoadVersionNeeds(const Elf_Shdr *ec) const; void LoadVersionMap() const; - /// @brief Map sections to an array of relocation sections that reference - /// them sorted by section index. - RelocMap_t SectionRelocMap; - /// @brief Get the relocation section that contains \a Rel. const Elf_Shdr *getRelSection(DataRefImpl Rel) const { - return getSection(Rel.w.b); + return getSection(Rel.d.a); } +public: bool isRelocationHasAddend(DataRefImpl Rel) const; template - const T *getEntry(uint16_t Section, uint32_t Entry) const; + const T *getEntry(uint32_t Section, uint32_t Entry) const; template const T *getEntry(const Elf_Shdr *Section, uint32_t Entry) const; const Elf_Shdr *getSection(DataRefImpl index) const; @@ -633,8 +652,9 @@ private: void VerifyStrTab(const Elf_Shdr *sh) const; protected: - const Elf_Sym *getSymbol(DataRefImpl Symb) const; // FIXME: Should be private? + const Elf_Sym *getSymbol(DataRefImpl Symb) const; // FIXME: Should be private? void validateSymbol(DataRefImpl Symb) const; + StringRef getRelocationTypeName(uint32_t Type) const; public: error_code getSymbolName(const Elf_Shdr *section, @@ -646,22 +666,22 @@ public: error_code getSymbolVersion(SymbolRef Symb, StringRef &Version, bool &IsDefault) const; uint64_t getSymbolIndex(const Elf_Sym *sym) const; + error_code getRelocationAddend(DataRefImpl Rel, int64_t &Res) const; protected: virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const; virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const; virtual error_code getSymbolFileOffset(DataRefImpl Symb, uint64_t &Res) const; virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const; + virtual error_code getSymbolAlignment(DataRefImpl Symb, uint32_t &Res) const; virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const; virtual error_code getSymbolNMTypeChar(DataRefImpl Symb, char &Res) const; virtual error_code getSymbolFlags(DataRefImpl Symb, uint32_t &Res) const; - virtual error_code getSymbolType(DataRefImpl Symb, SymbolRef::Type &Res) const; + virtual error_code getSymbolType(DataRefImpl Symb, + SymbolRef::Type &Res) const; virtual error_code getSymbolSection(DataRefImpl Symb, section_iterator &Res) const; virtual error_code getSymbolValue(DataRefImpl Symb, uint64_t &Val) const; - friend class DynRefImpl; - virtual error_code getDynNext(DataRefImpl DynData, DynRef &Result) const; - virtual error_code getLibraryNext(DataRefImpl Data, LibraryRef &Result) const; virtual error_code getLibraryPath(DataRefImpl Data, StringRef &Res) const; @@ -683,6 +703,7 @@ protected: bool &Result) const; virtual relocation_iterator getSectionRelBegin(DataRefImpl Sec) const; virtual relocation_iterator getSectionRelEnd(DataRefImpl Sec) const; + virtual section_iterator getRelocatedSection(DataRefImpl Sec) const; virtual error_code getRelocationNext(DataRefImpl Rel, RelocationRef &Res) const; @@ -690,19 +711,23 @@ protected: uint64_t &Res) const; virtual error_code getRelocationOffset(DataRefImpl Rel, uint64_t &Res) const; - virtual error_code getRelocationSymbol(DataRefImpl Rel, - SymbolRef &Res) const; + virtual symbol_iterator getRelocationSymbol(DataRefImpl Rel) const; virtual error_code getRelocationType(DataRefImpl Rel, uint64_t &Res) const; virtual error_code getRelocationTypeName(DataRefImpl Rel, SmallVectorImpl &Result) const; - virtual error_code getRelocationAdditionalInfo(DataRefImpl Rel, - int64_t &Res) const; virtual error_code getRelocationValueString(DataRefImpl Rel, SmallVectorImpl &Result) const; public: ELFObjectFile(MemoryBuffer *Object, error_code &ec); + + bool isMips64EL() const { + return Header->e_machine == ELF::EM_MIPS && + Header->getFileClass() == ELF::ELFCLASS64 && + Header->getDataEncoding() == ELF::ELFDATA2LSB; + } + virtual symbol_iterator begin_symbols() const; virtual symbol_iterator end_symbols() const; @@ -715,11 +740,34 @@ public: virtual library_iterator begin_libraries_needed() const; virtual library_iterator end_libraries_needed() const; - virtual dyn_iterator begin_dynamic_table() const; - virtual dyn_iterator end_dynamic_table() const; + const Elf_Shdr *getDynamicSymbolTableSectionHeader() const { + return getSection(DynamicSymbolTableIndex); + } - typedef ELFEntityIterator Elf_Rela_Iter; - typedef ELFEntityIterator Elf_Rel_Iter; + const Elf_Shdr *getDynamicStringTableSectionHeader() const { + return dot_dynstr_sec; + } + + Elf_Dyn_iterator begin_dynamic_table() const; + /// \param NULLEnd use one past the first DT_NULL entry as the end instead of + /// the section size. + Elf_Dyn_iterator end_dynamic_table(bool NULLEnd = false) const; + + Elf_Sym_iterator begin_elf_dynamic_symbols() const { + const Elf_Shdr *DynSymtab = getDynamicSymbolTableSectionHeader(); + if (DynSymtab) + return Elf_Sym_iterator(DynSymtab->sh_entsize, + (const char *)base() + DynSymtab->sh_offset); + return Elf_Sym_iterator(0, 0); + } + + Elf_Sym_iterator end_elf_dynamic_symbols() const { + const Elf_Shdr *DynSymtab = getDynamicSymbolTableSectionHeader(); + if (DynSymtab) + return Elf_Sym_iterator(DynSymtab->sh_entsize, (const char *)base() + + DynSymtab->sh_offset + DynSymtab->sh_size); + return Elf_Sym_iterator(0, 0); + } Elf_Rela_Iter beginELFRela(const Elf_Shdr *sec) const { return Elf_Rela_Iter(sec->sh_entsize, @@ -767,6 +815,7 @@ public: uint64_t getNumSections() const; uint64_t getStringTableIndex() const; ELF::Elf64_Word getSymbolTableIndex(const Elf_Sym *symb) const; + const Elf_Ehdr *getElfHeader() const; const Elf_Shdr *getSection(const Elf_Sym *symb) const; const Elf_Shdr *getElfSection(section_iterator &It) const; const Elf_Sym *getElfSymbol(symbol_iterator &It) const; @@ -775,16 +824,22 @@ public: // Methods for type inquiry through isa, cast, and dyn_cast bool isDyldType() const { return isDyldELFObject; } static inline bool classof(const Binary *v) { - return v->getType() == getELFType(target_endianness == support::little, - is64Bits); + return v->getType() == getELFType(ELFT::TargetEndianness == support::little, + ELFT::Is64Bits); } }; +// Use an alignment of 2 for the typedefs since that is the worst case for +// ELF files in archives. +typedef ELFObjectFile > ELF32LEObjectFile; +typedef ELFObjectFile > ELF64LEObjectFile; +typedef ELFObjectFile > ELF32BEObjectFile; +typedef ELFObjectFile > ELF64BEObjectFile; + // Iterate through the version definitions, and place each Elf_Verdef // in the VersionMap according to its index. -template -void ELFObjectFile:: - LoadVersionDefs(const Elf_Shdr *sec) const { +template +void ELFObjectFile::LoadVersionDefs(const Elf_Shdr *sec) const { unsigned vd_size = sec->sh_size; // Size of section in bytes unsigned vd_count = sec->sh_info; // Number of Verdef entries const char *sec_start = (const char*)base() + sec->sh_offset; @@ -808,9 +863,8 @@ void ELFObjectFile:: // Iterate through the versions needed section, and place each Elf_Vernaux // in the VersionMap according to its index. -template -void ELFObjectFile:: - LoadVersionNeeds(const Elf_Shdr *sec) const { +template +void ELFObjectFile::LoadVersionNeeds(const Elf_Shdr *sec) const { unsigned vn_size = sec->sh_size; // Size of section in bytes unsigned vn_count = sec->sh_info; // Number of Verneed entries const char *sec_start = (const char*)base() + sec->sh_offset; @@ -841,11 +895,11 @@ void ELFObjectFile:: } } -template -void ELFObjectFile - ::LoadVersionMap() const { +template +void ELFObjectFile::LoadVersionMap() const { // If there is no dynamic symtab or version table, there is nothing to do. - if (SymbolTableSections[0] == NULL || dot_gnu_version_sec == NULL) + if (getDynamicStringTableSectionHeader() == NULL || + dot_gnu_version_sec == NULL) return; // Has the VersionMap already been loaded? @@ -864,11 +918,11 @@ void ELFObjectFile LoadVersionNeeds(dot_gnu_version_r_sec); } -template -void ELFObjectFile - ::validateSymbol(DataRefImpl Symb) const { +template +void ELFObjectFile::validateSymbol(DataRefImpl Symb) const { +#ifndef NDEBUG const Elf_Sym *symb = getSymbol(Symb); - const Elf_Shdr *SymbolTableSection = SymbolTableSections[Symb.d.b]; + const Elf_Shdr *SymbolTableSection = getSection(Symb.d.b); // FIXME: We really need to do proper error handling in the case of an invalid // input file. Because we don't use exceptions, I think we'll just pass // an error object around. @@ -881,70 +935,47 @@ void ELFObjectFile + SymbolTableSection->sh_size))) // FIXME: Proper error handling. report_fatal_error("Symb must point to a valid symbol!"); +#endif } -template -error_code ELFObjectFile - ::getSymbolNext(DataRefImpl Symb, - SymbolRef &Result) const { +template +error_code ELFObjectFile::getSymbolNext(DataRefImpl Symb, + SymbolRef &Result) const { validateSymbol(Symb); - const Elf_Shdr *SymbolTableSection = SymbolTableSections[Symb.d.b]; - ++Symb.d.a; - // Check to see if we are at the end of this symbol table. - if (Symb.d.a >= SymbolTableSection->getEntityCount()) { - // We are at the end. If there are other symbol tables, jump to them. - // If the symbol table is .dynsym, we are iterating dynamic symbols, - // and there is only one table of these. - if (Symb.d.b != 0) { - ++Symb.d.b; - Symb.d.a = 1; // The 0th symbol in ELF is fake. - } - // Otherwise return the terminator. - if (Symb.d.b == 0 || Symb.d.b >= SymbolTableSections.size()) { - Symb.d.a = std::numeric_limits::max(); - Symb.d.b = std::numeric_limits::max(); - } - } - Result = SymbolRef(Symb, this); return object_error::success; } -template -error_code ELFObjectFile - ::getSymbolName(DataRefImpl Symb, - StringRef &Result) const { +template +error_code ELFObjectFile::getSymbolName(DataRefImpl Symb, + StringRef &Result) const { validateSymbol(Symb); const Elf_Sym *symb = getSymbol(Symb); - return getSymbolName(SymbolTableSections[Symb.d.b], symb, Result); + return getSymbolName(getSection(Symb.d.b), symb, Result); } -template -error_code ELFObjectFile - ::getSymbolVersion(SymbolRef SymRef, - StringRef &Version, - bool &IsDefault) const { +template +error_code ELFObjectFile::getSymbolVersion(SymbolRef SymRef, + StringRef &Version, + bool &IsDefault) const { DataRefImpl Symb = SymRef.getRawDataRefImpl(); validateSymbol(Symb); const Elf_Sym *symb = getSymbol(Symb); - return getSymbolVersion(SymbolTableSections[Symb.d.b], symb, - Version, IsDefault); + return getSymbolVersion(getSection(Symb.d.b), symb, Version, IsDefault); } -template -ELF::Elf64_Word ELFObjectFile - ::getSymbolTableIndex(const Elf_Sym *symb) const { +template +ELF::Elf64_Word ELFObjectFile + ::getSymbolTableIndex(const Elf_Sym *symb) const { if (symb->st_shndx == ELF::SHN_XINDEX) return ExtendedSymbolTable.lookup(symb); return symb->st_shndx; } -template -const typename ELFObjectFile - ::Elf_Shdr * -ELFObjectFile - ::getSection(const Elf_Sym *symb) const { +template +const typename ELFObjectFile::Elf_Shdr * +ELFObjectFile::getSection(const Elf_Sym *symb) const { if (symb->st_shndx == ELF::SHN_XINDEX) return getSection(ExtendedSymbolTable.lookup(symb)); if (symb->st_shndx >= ELF::SHN_LORESERVE) @@ -952,38 +983,37 @@ ELFObjectFile return getSection(symb->st_shndx); } -template -const typename ELFObjectFile - ::Elf_Shdr * -ELFObjectFile - ::getElfSection(section_iterator &It) const { +template +const typename ELFObjectFile::Elf_Ehdr * +ELFObjectFile::getElfHeader() const { + return Header; +} + +template +const typename ELFObjectFile::Elf_Shdr * +ELFObjectFile::getElfSection(section_iterator &It) const { llvm::object::DataRefImpl ShdrRef = It->getRawDataRefImpl(); return reinterpret_cast(ShdrRef.p); } -template -const typename ELFObjectFile - ::Elf_Sym * -ELFObjectFile - ::getElfSymbol(symbol_iterator &It) const { +template +const typename ELFObjectFile::Elf_Sym * +ELFObjectFile::getElfSymbol(symbol_iterator &It) const { return getSymbol(It->getRawDataRefImpl()); } -template -const typename ELFObjectFile - ::Elf_Sym * -ELFObjectFile - ::getElfSymbol(uint32_t index) const { +template +const typename ELFObjectFile::Elf_Sym * +ELFObjectFile::getElfSymbol(uint32_t index) const { DataRefImpl SymbolData; SymbolData.d.a = index; - SymbolData.d.b = 1; + SymbolData.d.b = SymbolTableIndex; return getSymbol(SymbolData); } -template -error_code ELFObjectFile - ::getSymbolFileOffset(DataRefImpl Symb, - uint64_t &Result) const { +template +error_code ELFObjectFile::getSymbolFileOffset(DataRefImpl Symb, + uint64_t &Result) const { validateSymbol(Symb); const Elf_Sym *symb = getSymbol(Symb); const Elf_Shdr *Section; @@ -1001,7 +1031,7 @@ error_code ELFObjectFile switch (symb->getType()) { case ELF::STT_SECTION: - Result = Section ? Section->sh_addr : UnknownAddressOrSize; + Result = Section ? Section->sh_offset : UnknownAddressOrSize; return object_error::success; case ELF::STT_FUNC: case ELF::STT_OBJECT: @@ -1015,10 +1045,9 @@ error_code ELFObjectFile } } -template -error_code ELFObjectFile - ::getSymbolAddress(DataRefImpl Symb, - uint64_t &Result) const { +template +error_code ELFObjectFile::getSymbolAddress(DataRefImpl Symb, + uint64_t &Result) const { validateSymbol(Symb); const Elf_Sym *symb = getSymbol(Symb); const Elf_Shdr *Section; @@ -1050,6 +1079,11 @@ error_code ELFObjectFile IsRelocatable = true; } Result = symb->st_value; + + // Clear the ARM/Thumb indicator flag. + if (Header->e_machine == ELF::EM_ARM) + Result &= ~1; + if (IsRelocatable && Section != 0) Result += Section->sh_addr; return object_error::success; @@ -1059,10 +1093,24 @@ error_code ELFObjectFile } } -template -error_code ELFObjectFile - ::getSymbolSize(DataRefImpl Symb, - uint64_t &Result) const { +template +error_code ELFObjectFile::getSymbolAlignment(DataRefImpl Symb, + uint32_t &Res) const { + uint32_t flags; + getSymbolFlags(Symb, flags); + if (flags & SymbolRef::SF_Common) { + uint64_t Value; + getSymbolValue(Symb, Value); + Res = Value; + } else { + Res = 0; + } + return object_error::success; +} + +template +error_code ELFObjectFile::getSymbolSize(DataRefImpl Symb, + uint64_t &Result) const { validateSymbol(Symb); const Elf_Sym *symb = getSymbol(Symb); if (symb->st_size == 0) @@ -1071,10 +1119,9 @@ error_code ELFObjectFile return object_error::success; } -template -error_code ELFObjectFile - ::getSymbolNMTypeChar(DataRefImpl Symb, - char &Result) const { +template +error_code ELFObjectFile::getSymbolNMTypeChar(DataRefImpl Symb, + char &Result) const { validateSymbol(Symb); const Elf_Sym *symb = getSymbol(Symb); const Elf_Shdr *Section = getSection(symb); @@ -1136,10 +1183,9 @@ error_code ELFObjectFile return object_error::success; } -template -error_code ELFObjectFile - ::getSymbolType(DataRefImpl Symb, - SymbolRef::Type &Result) const { +template +error_code ELFObjectFile::getSymbolType(DataRefImpl Symb, + SymbolRef::Type &Result) const { validateSymbol(Symb); const Elf_Sym *symb = getSymbol(Symb); @@ -1168,10 +1214,9 @@ error_code ELFObjectFile return object_error::success; } -template -error_code ELFObjectFile - ::getSymbolFlags(DataRefImpl Symb, - uint32_t &Result) const { +template +error_code ELFObjectFile::getSymbolFlags(DataRefImpl Symb, + uint32_t &Result) const { validateSymbol(Symb); const Elf_Sym *symb = getSymbol(Symb); @@ -1187,7 +1232,8 @@ error_code ELFObjectFile Result |= SymbolRef::SF_Absolute; if (symb->getType() == ELF::STT_FILE || - symb->getType() == ELF::STT_SECTION) + symb->getType() == ELF::STT_SECTION || + Symb == begin_symbols()->getRawDataRefImpl()) Result |= SymbolRef::SF_FormatSpecific; if (getSymbolTableIndex(symb) == ELF::SHN_UNDEF) @@ -1203,10 +1249,9 @@ error_code ELFObjectFile return object_error::success; } -template -error_code ELFObjectFile - ::getSymbolSection(DataRefImpl Symb, - section_iterator &Res) const { +template +error_code ELFObjectFile::getSymbolSection(DataRefImpl Symb, + section_iterator &Res) const { validateSymbol(Symb); const Elf_Sym *symb = getSymbol(Symb); const Elf_Shdr *sec = getSection(symb); @@ -1220,19 +1265,18 @@ error_code ELFObjectFile return object_error::success; } -template -error_code ELFObjectFile - ::getSymbolValue(DataRefImpl Symb, - uint64_t &Val) const { +template +error_code ELFObjectFile::getSymbolValue(DataRefImpl Symb, + uint64_t &Val) const { validateSymbol(Symb); const Elf_Sym *symb = getSymbol(Symb); Val = symb->st_value; return object_error::success; } -template -error_code ELFObjectFile - ::getSectionNext(DataRefImpl Sec, SectionRef &Result) const { +template +error_code ELFObjectFile::getSectionNext(DataRefImpl Sec, + SectionRef &Result) const { const uint8_t *sec = reinterpret_cast(Sec.p); sec += Header->e_shentsize; Sec.p = reinterpret_cast(sec); @@ -1240,65 +1284,58 @@ error_code ELFObjectFile return object_error::success; } -template -error_code ELFObjectFile - ::getSectionName(DataRefImpl Sec, - StringRef &Result) const { +template +error_code ELFObjectFile::getSectionName(DataRefImpl Sec, + StringRef &Result) const { const Elf_Shdr *sec = reinterpret_cast(Sec.p); Result = StringRef(getString(dot_shstrtab_sec, sec->sh_name)); return object_error::success; } -template -error_code ELFObjectFile - ::getSectionAddress(DataRefImpl Sec, - uint64_t &Result) const { +template +error_code ELFObjectFile::getSectionAddress(DataRefImpl Sec, + uint64_t &Result) const { const Elf_Shdr *sec = reinterpret_cast(Sec.p); Result = sec->sh_addr; return object_error::success; } -template -error_code ELFObjectFile - ::getSectionSize(DataRefImpl Sec, - uint64_t &Result) const { +template +error_code ELFObjectFile::getSectionSize(DataRefImpl Sec, + uint64_t &Result) const { const Elf_Shdr *sec = reinterpret_cast(Sec.p); Result = sec->sh_size; return object_error::success; } -template -error_code ELFObjectFile - ::getSectionContents(DataRefImpl Sec, - StringRef &Result) const { +template +error_code ELFObjectFile::getSectionContents(DataRefImpl Sec, + StringRef &Result) const { const Elf_Shdr *sec = reinterpret_cast(Sec.p); const char *start = (const char*)base() + sec->sh_offset; Result = StringRef(start, sec->sh_size); return object_error::success; } -template -error_code ELFObjectFile - ::getSectionContents(const Elf_Shdr *Sec, - StringRef &Result) const { +template +error_code ELFObjectFile::getSectionContents(const Elf_Shdr *Sec, + StringRef &Result) const { const char *start = (const char*)base() + Sec->sh_offset; Result = StringRef(start, Sec->sh_size); return object_error::success; } -template -error_code ELFObjectFile - ::getSectionAlignment(DataRefImpl Sec, - uint64_t &Result) const { +template +error_code ELFObjectFile::getSectionAlignment(DataRefImpl Sec, + uint64_t &Result) const { const Elf_Shdr *sec = reinterpret_cast(Sec.p); Result = sec->sh_addralign; return object_error::success; } -template -error_code ELFObjectFile - ::isSectionText(DataRefImpl Sec, - bool &Result) const { +template +error_code ELFObjectFile::isSectionText(DataRefImpl Sec, + bool &Result) const { const Elf_Shdr *sec = reinterpret_cast(Sec.p); if (sec->sh_flags & ELF::SHF_EXECINSTR) Result = true; @@ -1307,10 +1344,9 @@ error_code ELFObjectFile return object_error::success; } -template -error_code ELFObjectFile - ::isSectionData(DataRefImpl Sec, - bool &Result) const { +template +error_code ELFObjectFile::isSectionData(DataRefImpl Sec, + bool &Result) const { const Elf_Shdr *sec = reinterpret_cast(Sec.p); if (sec->sh_flags & (ELF::SHF_ALLOC | ELF::SHF_WRITE) && sec->sh_type == ELF::SHT_PROGBITS) @@ -1320,10 +1356,9 @@ error_code ELFObjectFile return object_error::success; } -template -error_code ELFObjectFile - ::isSectionBSS(DataRefImpl Sec, - bool &Result) const { +template +error_code ELFObjectFile::isSectionBSS(DataRefImpl Sec, + bool &Result) const { const Elf_Shdr *sec = reinterpret_cast(Sec.p); if (sec->sh_flags & (ELF::SHF_ALLOC | ELF::SHF_WRITE) && sec->sh_type == ELF::SHT_NOBITS) @@ -1333,10 +1368,9 @@ error_code ELFObjectFile return object_error::success; } -template -error_code ELFObjectFile - ::isSectionRequiredForExecution(DataRefImpl Sec, - bool &Result) const { +template +error_code ELFObjectFile::isSectionRequiredForExecution( + DataRefImpl Sec, bool &Result) const { const Elf_Shdr *sec = reinterpret_cast(Sec.p); if (sec->sh_flags & ELF::SHF_ALLOC) Result = true; @@ -1345,10 +1379,9 @@ error_code ELFObjectFile return object_error::success; } -template -error_code ELFObjectFile - ::isSectionVirtual(DataRefImpl Sec, - bool &Result) const { +template +error_code ELFObjectFile::isSectionVirtual(DataRefImpl Sec, + bool &Result) const { const Elf_Shdr *sec = reinterpret_cast(Sec.p); if (sec->sh_type == ELF::SHT_NOBITS) Result = true; @@ -1357,10 +1390,9 @@ error_code ELFObjectFile return object_error::success; } -template -error_code ELFObjectFile - ::isSectionZeroInit(DataRefImpl Sec, - bool &Result) const { +template +error_code ELFObjectFile::isSectionZeroInit(DataRefImpl Sec, + bool &Result) const { const Elf_Shdr *sec = reinterpret_cast(Sec.p); // For ELF, all zero-init sections are virtual (that is, they occupy no space // in the object image) and vice versa. @@ -1368,10 +1400,9 @@ error_code ELFObjectFile return object_error::success; } -template -error_code ELFObjectFile - ::isSectionReadOnlyData(DataRefImpl Sec, - bool &Result) const { +template +error_code ELFObjectFile::isSectionReadOnlyData(DataRefImpl Sec, + bool &Result) const { const Elf_Shdr *sec = reinterpret_cast(Sec.p); if (sec->sh_flags & ELF::SHF_WRITE || sec->sh_flags & ELF::SHF_EXECINSTR) Result = false; @@ -1380,165 +1411,145 @@ error_code ELFObjectFile return object_error::success; } -template -error_code ELFObjectFile - ::sectionContainsSymbol(DataRefImpl Sec, - DataRefImpl Symb, - bool &Result) const { - // FIXME: Unimplemented. - Result = false; +template +error_code ELFObjectFile::sectionContainsSymbol(DataRefImpl Sec, + DataRefImpl Symb, + bool &Result) const { + validateSymbol(Symb); + + const Elf_Shdr *sec = reinterpret_cast(Sec.p); + const Elf_Sym *symb = getSymbol(Symb); + + unsigned shndx = symb->st_shndx; + bool Reserved = shndx >= ELF::SHN_LORESERVE + && shndx <= ELF::SHN_HIRESERVE; + + Result = !Reserved && (sec == getSection(symb->st_shndx)); return object_error::success; } -template -relocation_iterator ELFObjectFile - ::getSectionRelBegin(DataRefImpl Sec) const { +template +relocation_iterator +ELFObjectFile::getSectionRelBegin(DataRefImpl Sec) const { DataRefImpl RelData; - const Elf_Shdr *sec = reinterpret_cast(Sec.p); - typename RelocMap_t::const_iterator ittr = SectionRelocMap.find(sec); - if (sec != 0 && ittr != SectionRelocMap.end()) { - RelData.w.a = getSection(ittr->second[0])->sh_info; - RelData.w.b = ittr->second[0]; - RelData.w.c = 0; - } + uintptr_t SHT = reinterpret_cast(SectionHeaderTable); + RelData.d.a = (Sec.p - SHT) / Header->e_shentsize; + RelData.d.b = 0; return relocation_iterator(RelocationRef(RelData, this)); } -template -relocation_iterator ELFObjectFile - ::getSectionRelEnd(DataRefImpl Sec) const { +template +relocation_iterator +ELFObjectFile::getSectionRelEnd(DataRefImpl Sec) const { DataRefImpl RelData; - const Elf_Shdr *sec = reinterpret_cast(Sec.p); - typename RelocMap_t::const_iterator ittr = SectionRelocMap.find(sec); - if (sec != 0 && ittr != SectionRelocMap.end()) { - // Get the index of the last relocation section for this section. - std::size_t relocsecindex = ittr->second[ittr->second.size() - 1]; - const Elf_Shdr *relocsec = getSection(relocsecindex); - RelData.w.a = relocsec->sh_info; - RelData.w.b = relocsecindex; - RelData.w.c = relocsec->sh_size / relocsec->sh_entsize; - } + uintptr_t SHT = reinterpret_cast(SectionHeaderTable); + const Elf_Shdr *S = reinterpret_cast(Sec.p); + RelData.d.a = (Sec.p - SHT) / Header->e_shentsize; + if (S->sh_type != ELF::SHT_RELA && S->sh_type != ELF::SHT_REL) + RelData.d.b = 0; + else + RelData.d.b = S->sh_size / S->sh_entsize; + return relocation_iterator(RelocationRef(RelData, this)); } +template +section_iterator +ELFObjectFile::getRelocatedSection(DataRefImpl Sec) const { + if (Header->e_type != ELF::ET_REL) + return end_sections(); + + const Elf_Shdr *S = reinterpret_cast(Sec.p); + unsigned sh_type = S->sh_type; + if (sh_type != ELF::SHT_RELA && sh_type != ELF::SHT_REL) + return end_sections(); + + assert(S->sh_info != 0); + const Elf_Shdr *R = getSection(S->sh_info); + DataRefImpl D; + D.p = reinterpret_cast(R); + return section_iterator(SectionRef(D, this)); +} + // Relocations -template -error_code ELFObjectFile - ::getRelocationNext(DataRefImpl Rel, - RelocationRef &Result) const { - ++Rel.w.c; - const Elf_Shdr *relocsec = getSection(Rel.w.b); - if (Rel.w.c >= (relocsec->sh_size / relocsec->sh_entsize)) { - // We have reached the end of the relocations for this section. See if there - // is another relocation section. - typename RelocMap_t::mapped_type relocseclist = - SectionRelocMap.lookup(getSection(Rel.w.a)); - - // Do a binary search for the current reloc section index (which must be - // present). Then get the next one. - typename RelocMap_t::mapped_type::const_iterator loc = - std::lower_bound(relocseclist.begin(), relocseclist.end(), Rel.w.b); - ++loc; - - // If there is no next one, don't do anything. The ++Rel.w.c above sets Rel - // to the end iterator. - if (loc != relocseclist.end()) { - Rel.w.b = *loc; - Rel.w.a = 0; - } - } +template +error_code ELFObjectFile::getRelocationNext(DataRefImpl Rel, + RelocationRef &Result) const { + ++Rel.d.b; Result = RelocationRef(Rel, this); return object_error::success; } -template -error_code ELFObjectFile - ::getRelocationSymbol(DataRefImpl Rel, - SymbolRef &Result) const { +template +symbol_iterator +ELFObjectFile::getRelocationSymbol(DataRefImpl Rel) const { uint32_t symbolIdx; - const Elf_Shdr *sec = getSection(Rel.w.b); + const Elf_Shdr *sec = getRelSection(Rel); switch (sec->sh_type) { default : report_fatal_error("Invalid section type in Rel!"); case ELF::SHT_REL : { - symbolIdx = getRel(Rel)->getSymbol(); + symbolIdx = getRel(Rel)->getSymbol(isMips64EL()); break; } case ELF::SHT_RELA : { - symbolIdx = getRela(Rel)->getSymbol(); + symbolIdx = getRela(Rel)->getSymbol(isMips64EL()); break; } } + if (!symbolIdx) + return end_symbols(); + DataRefImpl SymbolData; - IndexMap_t::const_iterator it = SymbolTableSectionsIndexMap.find(sec->sh_link); - if (it == SymbolTableSectionsIndexMap.end()) - report_fatal_error("Relocation symbol table not found!"); SymbolData.d.a = symbolIdx; - SymbolData.d.b = it->second; - Result = SymbolRef(SymbolData, this); - return object_error::success; + SymbolData.d.b = sec->sh_link; + return symbol_iterator(SymbolRef(SymbolData, this)); } -template -error_code ELFObjectFile - ::getRelocationAddress(DataRefImpl Rel, - uint64_t &Result) const { - uint64_t offset; - const Elf_Shdr *sec = getSection(Rel.w.b); - switch (sec->sh_type) { - default : - report_fatal_error("Invalid section type in Rel!"); - case ELF::SHT_REL : { - offset = getRel(Rel)->r_offset; - break; - } - case ELF::SHT_RELA : { - offset = getRela(Rel)->r_offset; - break; - } - } +template +error_code ELFObjectFile::getRelocationAddress(DataRefImpl Rel, + uint64_t &Result) const { + assert((Header->e_type == ELF::ET_EXEC || Header->e_type == ELF::ET_DYN) && + "Only executable and shared objects files have addresses"); + Result = getROffset(Rel); + return object_error::success; +} - Result = offset; +template +error_code ELFObjectFile::getRelocationOffset(DataRefImpl Rel, + uint64_t &Result) const { + assert(Header->e_type == ELF::ET_REL && + "Only relocatable object files have relocation offsets"); + Result = getROffset(Rel); return object_error::success; } -template -error_code ELFObjectFile - ::getRelocationOffset(DataRefImpl Rel, - uint64_t &Result) const { - uint64_t offset; - const Elf_Shdr *sec = getSection(Rel.w.b); +template +uint64_t ELFObjectFile::getROffset(DataRefImpl Rel) const { + const Elf_Shdr *sec = getRelSection(Rel); switch (sec->sh_type) { - default : - report_fatal_error("Invalid section type in Rel!"); - case ELF::SHT_REL : { - offset = getRel(Rel)->r_offset; - break; - } - case ELF::SHT_RELA : { - offset = getRela(Rel)->r_offset; - break; - } + default: + report_fatal_error("Invalid section type in Rel!"); + case ELF::SHT_REL: + return getRel(Rel)->r_offset; + case ELF::SHT_RELA: + return getRela(Rel)->r_offset; } - - Result = offset - sec->sh_addr; - return object_error::success; } -template -error_code ELFObjectFile - ::getRelocationType(DataRefImpl Rel, - uint64_t &Result) const { - const Elf_Shdr *sec = getSection(Rel.w.b); +template +error_code ELFObjectFile::getRelocationType(DataRefImpl Rel, + uint64_t &Result) const { + const Elf_Shdr *sec = getRelSection(Rel); switch (sec->sh_type) { default : report_fatal_error("Invalid section type in Rel!"); case ELF::SHT_REL : { - Result = getRel(Rel)->getType(); + Result = getRel(Rel)->getType(isMips64EL()); break; } case ELF::SHT_RELA : { - Result = getRela(Rel)->getType(); + Result = getRela(Rel)->getType(isMips64EL()); break; } } @@ -1546,30 +1557,14 @@ error_code ELFObjectFile } #define LLVM_ELF_SWITCH_RELOC_TYPE_NAME(enum) \ - case ELF::enum: res = #enum; break; + case ELF::enum: Res = #enum; break; -template -error_code ELFObjectFile - ::getRelocationTypeName(DataRefImpl Rel, - SmallVectorImpl &Result) const { - const Elf_Shdr *sec = getSection(Rel.w.b); - uint8_t type; - StringRef res; - switch (sec->sh_type) { - default : - return object_error::parse_failed; - case ELF::SHT_REL : { - type = getRel(Rel)->getType(); - break; - } - case ELF::SHT_RELA : { - type = getRela(Rel)->getType(); - break; - } - } +template +StringRef ELFObjectFile::getRelocationTypeName(uint32_t Type) const { + StringRef Res = "Unknown"; switch (Header->e_machine) { case ELF::EM_X86_64: - switch (type) { + switch (Type) { LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_NONE); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_64); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_PC32); @@ -1597,17 +1592,22 @@ error_code ELFObjectFile LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_PC64); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTOFF64); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTPC32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOT64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTPCREL64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTPC64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTPLT64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_PLTOFF64); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_SIZE32); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_SIZE64); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTPC32_TLSDESC); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_TLSDESC_CALL); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_TLSDESC); - default: - res = "Unknown"; + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_IRELATIVE); + default: break; } break; case ELF::EM_386: - switch (type) { + switch (Type) { LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_NONE); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_32); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_PC32); @@ -1648,12 +1648,148 @@ error_code ELFObjectFile LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_DESC_CALL); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_DESC); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_IRELATIVE); - default: - res = "Unknown"; + default: break; + } + break; + case ELF::EM_MIPS: + switch (Type) { + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_NONE); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_REL32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_26); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_HI16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_LO16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_GPREL16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_LITERAL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_GOT16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_PC16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_CALL16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_GPREL32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_UNUSED1); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_UNUSED2); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_SHIFT5); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_SHIFT6); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_GOT_DISP); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_GOT_PAGE); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_GOT_OFST); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_GOT_HI16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_GOT_LO16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_SUB); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_INSERT_A); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_INSERT_B); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_DELETE); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_HIGHER); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_HIGHEST); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_CALL_HI16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_CALL_LO16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_SCN_DISP); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_REL16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_ADD_IMMEDIATE); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_PJUMP); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_RELGOT); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_JALR); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_DTPMOD32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_DTPREL32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_DTPMOD64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_DTPREL64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_GD); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_LDM); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_DTPREL_HI16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_DTPREL_LO16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_GOTTPREL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_TPREL32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_TPREL64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_TPREL_HI16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_TPREL_LO16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_GLOB_DAT); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_COPY); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_JUMP_SLOT); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_NUM); + default: break; + } + break; + case ELF::EM_AARCH64: + switch (Type) { + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_NONE); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_ABS64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_ABS32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_ABS16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_PREL64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_PREL32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_PREL16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_MOVW_UABS_G0); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_MOVW_UABS_G0_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_MOVW_UABS_G1); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_MOVW_UABS_G1_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_MOVW_UABS_G2); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_MOVW_UABS_G2_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_MOVW_UABS_G3); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_MOVW_SABS_G0); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_MOVW_SABS_G1); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_MOVW_SABS_G2); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_LD_PREL_LO19); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_ADR_PREL_LO21); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_ADR_PREL_PG_HI21); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_ADD_ABS_LO12_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_LDST8_ABS_LO12_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TSTBR14); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_CONDBR19); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_JUMP26); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_CALL26); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_LDST16_ABS_LO12_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_LDST32_ABS_LO12_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_LDST64_ABS_LO12_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_LDST128_ABS_LO12_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_ADR_GOT_PAGE); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_LD64_GOT_LO12_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_MOVW_DTPREL_G2); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_MOVW_DTPREL_G1); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_MOVW_DTPREL_G0); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_ADD_DTPREL_HI12); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_ADD_DTPREL_LO12); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_LDST8_DTPREL_LO12); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_LDST16_DTPREL_LO12); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_LDST32_DTPREL_LO12); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_LDST64_DTPREL_LO12); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSIE_MOVW_GOTTPREL_G1); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSIE_LD_GOTTPREL_PREL19); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_MOVW_TPREL_G2); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_MOVW_TPREL_G1); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_MOVW_TPREL_G1_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_MOVW_TPREL_G0); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_MOVW_TPREL_G0_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_ADD_TPREL_HI12); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_ADD_TPREL_LO12); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_ADD_TPREL_LO12_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_LDST8_TPREL_LO12); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_LDST16_TPREL_LO12); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_LDST32_TPREL_LO12); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_LDST64_TPREL_LO12); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSDESC_ADR_PAGE); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSDESC_LD64_LO12_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSDESC_ADD_LO12_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSDESC_CALL); + default: break; } break; case ELF::EM_ARM: - switch (type) { + switch (Type) { LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_NONE); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PC24); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ABS32); @@ -1785,12 +1921,11 @@ error_code ELFObjectFile LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ME_TOO); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_TLS_DESCSEQ16); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_TLS_DESCSEQ32); - default: - res = "Unknown"; + default: break; } break; case ELF::EM_HEXAGON: - switch (type) { + switch (Type) { LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_NONE); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B22_PCREL); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B15_PCREL); @@ -1877,24 +2012,274 @@ error_code ELFObjectFile LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_TPREL_32_6_X); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_TPREL_16_X); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_TPREL_11_X); - default: - res = "Unknown"; + default: break; } break; - default: - res = "Unknown"; + case ELF::EM_PPC: + switch (Type) { + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_NONE); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR24); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR16_LO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR16_HI); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR16_HA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR14); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR14_BRTAKEN); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR14_BRNTAKEN); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_REL24); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_REL14); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_REL14_BRTAKEN); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_REL14_BRNTAKEN); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT16_LO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT16_HI); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT16_HA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_REL32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_TLS); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_DTPMOD32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_TPREL16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_TPREL16_LO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_TPREL16_HI); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_TPREL16_HA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_TPREL32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_DTPREL16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_DTPREL16_LO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_DTPREL16_HI); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_DTPREL16_HA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_DTPREL32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_TLSGD16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_TLSGD16_LO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_TLSGD16_HI); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_TLSGD16_HA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_TLSLD16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_TLSLD16_LO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_TLSLD16_HI); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_TLSLD16_HA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_TPREL16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_TPREL16_LO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_TPREL16_HI); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_TPREL16_HA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_DTPREL16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_DTPREL16_LO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_DTPREL16_HI); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_DTPREL16_HA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_TLSGD); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_TLSLD); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_REL16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_REL16_LO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_REL16_HI); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_REL16_HA); + default: break; + } + break; + case ELF::EM_PPC64: + switch (Type) { + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_NONE); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR24); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_LO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_HI); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_HA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR14); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR14_BRTAKEN); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR14_BRNTAKEN); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL24); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL14); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL14_BRTAKEN); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL14_BRNTAKEN); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT16_LO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT16_HI); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT16_HA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_HIGHER); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_HIGHERA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_HIGHEST); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_HIGHESTA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TOC16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TOC16_LO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TOC16_HI); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TOC16_HA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TOC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_DS); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_LO_DS); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT16_DS); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT16_LO_DS); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TOC16_DS); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TOC16_LO_DS); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TLS); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_DTPMOD64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TPREL16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TPREL16_LO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TPREL16_HI); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TPREL16_HA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TPREL64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_DTPREL16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_DTPREL16_LO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_DTPREL16_HI); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_DTPREL16_HA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_DTPREL64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TLSGD16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TLSGD16_LO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TLSGD16_HI); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TLSGD16_HA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TLSLD16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TLSLD16_LO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TLSLD16_HI); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TLSLD16_HA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TPREL16_DS); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TPREL16_LO_DS); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TPREL16_HI); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TPREL16_HA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_DTPREL16_DS); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_DTPREL16_LO_DS); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_DTPREL16_HI); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_DTPREL16_HA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TPREL16_DS); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TPREL16_LO_DS); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TPREL16_HIGHER); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TPREL16_HIGHERA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TPREL16_HIGHEST); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TPREL16_HIGHESTA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_DTPREL16_DS); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_DTPREL16_LO_DS); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_DTPREL16_HIGHER); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_DTPREL16_HIGHERA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_DTPREL16_HIGHEST); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_DTPREL16_HIGHESTA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TLSGD); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TLSLD); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL16_LO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL16_HI); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL16_HA); + default: break; + } + break; + case ELF::EM_S390: + switch (Type) { + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_NONE); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_8); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_12); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PC32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOT12); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOT32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PLT32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_COPY); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GLOB_DAT); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_JMP_SLOT); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_RELATIVE); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTOFF); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTPC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOT16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PC16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PC16DBL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PLT16DBL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PC32DBL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PLT32DBL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTPCDBL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PC64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOT64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PLT64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTENT); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTOFF16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTOFF64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTPLT12); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTPLT16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTPLT32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTPLT64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTPLTENT); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PLTOFF16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PLTOFF32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PLTOFF64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_LOAD); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_GDCALL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_LDCALL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_GD32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_GD64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_GOTIE12); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_GOTIE32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_GOTIE64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_LDM32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_LDM64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_IE32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_IE64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_IEENT); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_LE32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_LE64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_LDO32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_LDO64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_DTPMOD); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_DTPOFF); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_TPOFF); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_20); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOT20); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTPLT20); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_GOTIE20); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_IRELATIVE); + default: break; + } + break; + default: break; } - Result.append(res.begin(), res.end()); - return object_error::success; + return Res; } #undef LLVM_ELF_SWITCH_RELOC_TYPE_NAME -template -error_code ELFObjectFile - ::getRelocationAdditionalInfo(DataRefImpl Rel, - int64_t &Result) const { - const Elf_Shdr *sec = getSection(Rel.w.b); +template +error_code ELFObjectFile::getRelocationTypeName( + DataRefImpl Rel, SmallVectorImpl &Result) const { + const Elf_Shdr *sec = getRelSection(Rel); + uint32_t type; + switch (sec->sh_type) { + default : + return object_error::parse_failed; + case ELF::SHT_REL : { + type = getRel(Rel)->getType(isMips64EL()); + break; + } + case ELF::SHT_RELA : { + type = getRela(Rel)->getType(isMips64EL()); + break; + } + } + + if (!isMips64EL()) { + StringRef Name = getRelocationTypeName(type); + Result.append(Name.begin(), Name.end()); + } else { + uint8_t Type1 = (type >> 0) & 0xFF; + uint8_t Type2 = (type >> 8) & 0xFF; + uint8_t Type3 = (type >> 16) & 0xFF; + + // Concat all three relocation type names. + StringRef Name = getRelocationTypeName(Type1); + Result.append(Name.begin(), Name.end()); + + Name = getRelocationTypeName(Type2); + Result.append(1, '/'); + Result.append(Name.begin(), Name.end()); + + Name = getRelocationTypeName(Type3); + Result.append(1, '/'); + Result.append(Name.begin(), Name.end()); + } + + return object_error::success; +} + +template +error_code ELFObjectFile::getRelocationAddend( + DataRefImpl Rel, int64_t &Result) const { + const Elf_Shdr *sec = getRelSection(Rel); switch (sec->sh_type) { default : report_fatal_error("Invalid section type in Rel!"); @@ -1909,11 +2294,10 @@ error_code ELFObjectFile } } -template -error_code ELFObjectFile - ::getRelocationValueString(DataRefImpl Rel, - SmallVectorImpl &Result) const { - const Elf_Shdr *sec = getSection(Rel.w.b); +template +error_code ELFObjectFile::getRelocationValueString( + DataRefImpl Rel, SmallVectorImpl &Result) const { + const Elf_Shdr *sec = getRelSection(Rel); uint8_t type; StringRef res; int64_t addend = 0; @@ -1922,14 +2306,14 @@ error_code ELFObjectFile default: return object_error::parse_failed; case ELF::SHT_REL: { - type = getRel(Rel)->getType(); - symbol_index = getRel(Rel)->getSymbol(); + type = getRel(Rel)->getType(isMips64EL()); + symbol_index = getRel(Rel)->getSymbol(isMips64EL()); // TODO: Read implicit addend from section data. break; } case ELF::SHT_RELA: { - type = getRela(Rel)->getType(); - symbol_index = getRela(Rel)->getSymbol(); + type = getRela(Rel)->getType(isMips64EL()); + symbol_index = getRela(Rel)->getSymbol(isMips64EL()); addend = getRela(Rel)->r_addend; break; } @@ -1967,6 +2351,16 @@ error_code ELFObjectFile res = "Unknown"; } break; + case ELF::EM_AARCH64: { + std::string fmtbuf; + raw_string_ostream fmt(fmtbuf); + fmt << symname; + if (addend != 0) + fmt << (addend < 0 ? "" : "+") << addend; + fmt.flush(); + Result.append(fmtbuf.begin(), fmtbuf.end()); + break; + } case ELF::EM_ARM: case ELF::EM_HEXAGON: res = symname; @@ -1980,20 +2374,20 @@ error_code ELFObjectFile } // Verify that the last byte in the string table in a null. -template -void ELFObjectFile - ::VerifyStrTab(const Elf_Shdr *sh) const { +template +void ELFObjectFile::VerifyStrTab(const Elf_Shdr *sh) const { const char *strtab = (const char*)base() + sh->sh_offset; if (strtab[sh->sh_size - 1] != 0) // FIXME: Proper error handling. report_fatal_error("String table must end with a null terminator!"); } -template -ELFObjectFile - ::ELFObjectFile(MemoryBuffer *Object, error_code &ec) - : ObjectFile(getELFType(target_endianness == support::little, is64Bits), - Object, ec) +template +ELFObjectFile::ELFObjectFile(MemoryBuffer *Object, error_code &ec) + : ObjectFile(getELFType( + static_cast(ELFT::TargetEndianness) == support::little, + ELFT::Is64Bits), + Object) , isDyldELFObject(false) , SectionHeaderTable(0) , dot_shstrtab_sec(0) @@ -2036,8 +2430,8 @@ ELFObjectFile const Elf_Shdr* SymbolTableSectionHeaderIndex = 0; const Elf_Shdr* sh = SectionHeaderTable; - // Reserve SymbolTableSections[0] for .dynsym - SymbolTableSections.push_back(NULL); + SymbolTableIndex = -1; + DynamicSymbolTableIndex = -1; for (uint64_t i = 0, e = getNumSections(); i != e; ++i) { switch (sh->sh_type) { @@ -2049,23 +2443,21 @@ ELFObjectFile break; } case ELF::SHT_SYMTAB: { - SymbolTableSectionsIndexMap[i] = SymbolTableSections.size(); - SymbolTableSections.push_back(sh); + if (SymbolTableIndex != -1) + report_fatal_error("More than one SHT_SYMTAB!"); + SymbolTableIndex = i; break; } case ELF::SHT_DYNSYM: { - if (SymbolTableSections[0] != NULL) + if (DynamicSymbolTableIndex != -1) // FIXME: Proper error handling. - report_fatal_error("More than one .dynsym!"); - SymbolTableSectionsIndexMap[i] = 0; - SymbolTableSections[0] = sh; + report_fatal_error("More than one SHT_DYNSYM!"); + DynamicSymbolTableIndex = i; break; } case ELF::SHT_REL: - case ELF::SHT_RELA: { - SectionRelocMap[getSection(sh->sh_info)].push_back(i); + case ELF::SHT_RELA: break; - } case ELF::SHT_DYNAMIC: { if (dot_dynamic_sec != NULL) // FIXME: Proper error handling. @@ -2098,12 +2490,6 @@ ELFObjectFile ++sh; } - // Sort section relocation lists by index. - for (typename RelocMap_t::iterator i = SectionRelocMap.begin(), - e = SectionRelocMap.end(); i != e; ++i) { - std::sort(i->second.begin(), i->second.end()); - } - // Get string table sections. dot_shstrtab_sec = getSection(getStringTableIndex()); if (dot_shstrtab_sec) { @@ -2151,11 +2537,9 @@ ELFObjectFile } // Get the symbol table index in the symtab section given a symbol -template -uint64_t ELFObjectFile - ::getSymbolIndex(const Elf_Sym *Sym) const { - assert(SymbolTableSections.size() == 1 && "Only one symbol table supported!"); - const Elf_Shdr *SymTab = *SymbolTableSections.begin(); +template +uint64_t ELFObjectFile::getSymbolIndex(const Elf_Sym *Sym) const { + const Elf_Shdr *SymTab = getSection(SymbolTableIndex); uintptr_t SymLoc = uintptr_t(Sym); uintptr_t SymTabLoc = uintptr_t(base() + SymTab->sh_offset); assert(SymLoc > SymTabLoc && "Symbol not in symbol table!"); @@ -2165,63 +2549,69 @@ uint64_t ELFObjectFile return SymOffset / SymTab->sh_entsize; } -template -symbol_iterator ELFObjectFile - ::begin_symbols() const { +template +symbol_iterator ELFObjectFile::begin_symbols() const { DataRefImpl SymbolData; - if (SymbolTableSections.size() <= 1) { - SymbolData.d.a = std::numeric_limits::max(); - SymbolData.d.b = std::numeric_limits::max(); + if (SymbolTableIndex == -1) { + SymbolData.d.a = 0; + SymbolData.d.b = 0; } else { - SymbolData.d.a = 1; // The 0th symbol in ELF is fake. - SymbolData.d.b = 1; // The 0th table is .dynsym + SymbolData.d.a = 0; + SymbolData.d.b = SymbolTableIndex; } return symbol_iterator(SymbolRef(SymbolData, this)); } -template -symbol_iterator ELFObjectFile - ::end_symbols() const { +template +symbol_iterator ELFObjectFile::end_symbols() const { DataRefImpl SymbolData; - SymbolData.d.a = std::numeric_limits::max(); - SymbolData.d.b = std::numeric_limits::max(); + if (SymbolTableIndex == -1) { + SymbolData.d.a = 0; + SymbolData.d.b = 0; + } else { + const Elf_Shdr *SymbolTableSection = getSection(SymbolTableIndex); + SymbolData.d.a = SymbolTableSection->getEntityCount(); + SymbolData.d.b = SymbolTableIndex; + } return symbol_iterator(SymbolRef(SymbolData, this)); } -template -symbol_iterator ELFObjectFile - ::begin_dynamic_symbols() const { +template +symbol_iterator ELFObjectFile::begin_dynamic_symbols() const { DataRefImpl SymbolData; - if (SymbolTableSections[0] == NULL) { - SymbolData.d.a = std::numeric_limits::max(); - SymbolData.d.b = std::numeric_limits::max(); + if (DynamicSymbolTableIndex == -1) { + SymbolData.d.a = 0; + SymbolData.d.b = 0; } else { - SymbolData.d.a = 1; // The 0th symbol in ELF is fake. - SymbolData.d.b = 0; // The 0th table is .dynsym + SymbolData.d.a = 0; + SymbolData.d.b = DynamicSymbolTableIndex; } return symbol_iterator(SymbolRef(SymbolData, this)); } -template -symbol_iterator ELFObjectFile - ::end_dynamic_symbols() const { +template +symbol_iterator ELFObjectFile::end_dynamic_symbols() const { DataRefImpl SymbolData; - SymbolData.d.a = std::numeric_limits::max(); - SymbolData.d.b = std::numeric_limits::max(); + if (DynamicSymbolTableIndex == -1) { + SymbolData.d.a = 0; + SymbolData.d.b = 0; + } else { + const Elf_Shdr *SymbolTableSection = getSection(DynamicSymbolTableIndex); + SymbolData.d.a = SymbolTableSection->getEntityCount(); + SymbolData.d.b = DynamicSymbolTableIndex; + } return symbol_iterator(SymbolRef(SymbolData, this)); } -template -section_iterator ELFObjectFile - ::begin_sections() const { +template +section_iterator ELFObjectFile::begin_sections() const { DataRefImpl ret; ret.p = reinterpret_cast(base() + Header->e_shoff); return section_iterator(SectionRef(ret, this)); } -template -section_iterator ELFObjectFile - ::end_sections() const { +template +section_iterator ELFObjectFile::end_sections() const { DataRefImpl ret; ret.p = reinterpret_cast(base() + Header->e_shoff @@ -2229,59 +2619,47 @@ section_iterator ELFObjectFile return section_iterator(SectionRef(ret, this)); } -template -typename ELFObjectFile::dyn_iterator -ELFObjectFile - ::begin_dynamic_table() const { - DataRefImpl DynData; - if (dot_dynamic_sec == NULL || dot_dynamic_sec->sh_size == 0) { - DynData.d.a = std::numeric_limits::max(); - } else { - DynData.d.a = 0; - } - return dyn_iterator(DynRef(DynData, this)); -} - -template -typename ELFObjectFile::dyn_iterator -ELFObjectFile - ::end_dynamic_table() const { - DataRefImpl DynData; - DynData.d.a = std::numeric_limits::max(); - return dyn_iterator(DynRef(DynData, this)); -} - -template -error_code ELFObjectFile - ::getDynNext(DataRefImpl DynData, - DynRef &Result) const { - ++DynData.d.a; - - // Check to see if we are at the end of .dynamic - if (DynData.d.a >= dot_dynamic_sec->getEntityCount()) { - // We are at the end. Return the terminator. - DynData.d.a = std::numeric_limits::max(); +template +typename ELFObjectFile::Elf_Dyn_iterator +ELFObjectFile::begin_dynamic_table() const { + if (dot_dynamic_sec) + return Elf_Dyn_iterator(dot_dynamic_sec->sh_entsize, + (const char *)base() + dot_dynamic_sec->sh_offset); + return Elf_Dyn_iterator(0, 0); +} + +template +typename ELFObjectFile::Elf_Dyn_iterator +ELFObjectFile::end_dynamic_table(bool NULLEnd) const { + if (dot_dynamic_sec) { + Elf_Dyn_iterator Ret(dot_dynamic_sec->sh_entsize, + (const char *)base() + dot_dynamic_sec->sh_offset + + dot_dynamic_sec->sh_size); + + if (NULLEnd) { + Elf_Dyn_iterator Start = begin_dynamic_table(); + while (Start != Ret && Start->getTag() != ELF::DT_NULL) + ++Start; + + // Include the DT_NULL. + if (Start != Ret) + ++Start; + Ret = Start; + } + return Ret; } - - Result = DynRef(DynData, this); - return object_error::success; + return Elf_Dyn_iterator(0, 0); } -template -StringRef -ELFObjectFile::getLoadName() const { +template +StringRef ELFObjectFile::getLoadName() const { if (!dt_soname) { // Find the DT_SONAME entry - dyn_iterator it = begin_dynamic_table(); - dyn_iterator ie = end_dynamic_table(); - error_code ec; - while (it != ie) { - if (it->getTag() == ELF::DT_SONAME) - break; - it.increment(ec); - if (ec) - report_fatal_error("dynamic table iteration failed"); - } + Elf_Dyn_iterator it = begin_dynamic_table(); + Elf_Dyn_iterator ie = end_dynamic_table(); + while (it != ie && it->getTag() != ELF::DT_SONAME) + ++it; + if (it != ie) { if (dot_dynstr_sec == NULL) report_fatal_error("Dynamic string table is missing"); @@ -2293,57 +2671,43 @@ ELFObjectFile::getLoadName() const { return dt_soname; } -template -library_iterator ELFObjectFile - ::begin_libraries_needed() const { +template +library_iterator ELFObjectFile::begin_libraries_needed() const { // Find the first DT_NEEDED entry - dyn_iterator i = begin_dynamic_table(); - dyn_iterator e = end_dynamic_table(); - error_code ec; - while (i != e) { - if (i->getTag() == ELF::DT_NEEDED) - break; - i.increment(ec); - if (ec) - report_fatal_error("dynamic table iteration failed"); - } - // Use the same DataRefImpl format as DynRef. - return library_iterator(LibraryRef(i->getRawDataRefImpl(), this)); + Elf_Dyn_iterator i = begin_dynamic_table(); + Elf_Dyn_iterator e = end_dynamic_table(); + while (i != e && i->getTag() != ELF::DT_NEEDED) + ++i; + + DataRefImpl DRI; + DRI.p = reinterpret_cast(i.get()); + return library_iterator(LibraryRef(DRI, this)); } -template -error_code ELFObjectFile - ::getLibraryNext(DataRefImpl Data, - LibraryRef &Result) const { +template +error_code ELFObjectFile::getLibraryNext(DataRefImpl Data, + LibraryRef &Result) const { // Use the same DataRefImpl format as DynRef. - dyn_iterator i = dyn_iterator(DynRef(Data, this)); - dyn_iterator e = end_dynamic_table(); - - // Skip the current dynamic table entry. - error_code ec; - if (i != e) { - i.increment(ec); - // TODO: proper error handling - if (ec) - report_fatal_error("dynamic table iteration failed"); - } - - // Find the next DT_NEEDED entry. - while (i != e) { - if (i->getTag() == ELF::DT_NEEDED) - break; - i.increment(ec); - if (ec) - report_fatal_error("dynamic table iteration failed"); - } - Result = LibraryRef(i->getRawDataRefImpl(), this); + Elf_Dyn_iterator i = Elf_Dyn_iterator(dot_dynamic_sec->sh_entsize, + reinterpret_cast(Data.p)); + Elf_Dyn_iterator e = end_dynamic_table(); + + // Skip the current dynamic table entry and find the next DT_NEEDED entry. + do + ++i; + while (i != e && i->getTag() != ELF::DT_NEEDED); + + DataRefImpl DRI; + DRI.p = reinterpret_cast(i.get()); + Result = LibraryRef(DRI, this); return object_error::success; } -template -error_code ELFObjectFile - ::getLibraryPath(DataRefImpl Data, StringRef &Res) const { - dyn_iterator i = dyn_iterator(DynRef(Data, this)); +template +error_code ELFObjectFile::getLibraryPath(DataRefImpl Data, + StringRef &Res) const { + Elf_Dyn_iterator i = Elf_Dyn_iterator(dot_dynamic_sec->sh_entsize, + reinterpret_cast(Data.p)); if (i == end_dynamic_table()) report_fatal_error("getLibraryPath() called on iterator end"); @@ -2361,23 +2725,21 @@ error_code ELFObjectFile return object_error::success; } -template -library_iterator ELFObjectFile - ::end_libraries_needed() const { - dyn_iterator e = end_dynamic_table(); - // Use the same DataRefImpl format as DynRef. - return library_iterator(LibraryRef(e->getRawDataRefImpl(), this)); +template +library_iterator ELFObjectFile::end_libraries_needed() const { + Elf_Dyn_iterator e = end_dynamic_table(); + DataRefImpl DRI; + DRI.p = reinterpret_cast(e.get()); + return library_iterator(LibraryRef(DRI, this)); } -template -uint8_t ELFObjectFile - ::getBytesInAddress() const { - return is64Bits ? 8 : 4; +template +uint8_t ELFObjectFile::getBytesInAddress() const { + return ELFT::Is64Bits ? 8 : 4; } -template -StringRef ELFObjectFile - ::getFileFormatName() const { +template +StringRef ELFObjectFile::getFileFormatName() const { switch(Header->e_ident[ELF::EI_CLASS]) { case ELF::ELFCLASS32: switch(Header->e_machine) { @@ -2389,6 +2751,10 @@ StringRef ELFObjectFile return "ELF32-arm"; case ELF::EM_HEXAGON: return "ELF32-hexagon"; + case ELF::EM_MIPS: + return "ELF32-mips"; + case ELF::EM_PPC: + return "ELF32-ppc"; default: return "ELF32-unknown"; } @@ -2398,8 +2764,12 @@ StringRef ELFObjectFile return "ELF64-i386"; case ELF::EM_X86_64: return "ELF64-x86-64"; + case ELF::EM_AARCH64: + return "ELF64-aarch64"; case ELF::EM_PPC64: return "ELF64-ppc64"; + case ELF::EM_S390: + return "ELF64-s390"; default: return "ELF64-unknown"; } @@ -2409,31 +2779,34 @@ StringRef ELFObjectFile } } -template -unsigned ELFObjectFile - ::getArch() const { +template +unsigned ELFObjectFile::getArch() const { switch(Header->e_machine) { case ELF::EM_386: return Triple::x86; case ELF::EM_X86_64: return Triple::x86_64; + case ELF::EM_AARCH64: + return Triple::aarch64; case ELF::EM_ARM: return Triple::arm; case ELF::EM_HEXAGON: return Triple::hexagon; case ELF::EM_MIPS: - return (target_endianness == support::little) ? + return (ELFT::TargetEndianness == support::little) ? Triple::mipsel : Triple::mips; case ELF::EM_PPC64: - return Triple::ppc64; + return (ELFT::TargetEndianness == support::little) ? + Triple::ppc64le : Triple::ppc64; + case ELF::EM_S390: + return Triple::systemz; default: return Triple::UnknownArch; } } -template -uint64_t ELFObjectFile - ::getNumSections() const { +template +uint64_t ELFObjectFile::getNumSections() const { assert(Header && "Header not initialized!"); if (Header->e_shnum == ELF::SHN_UNDEF) { assert(SectionHeaderTable && "SectionHeaderTable not initialized!"); @@ -2442,10 +2815,9 @@ uint64_t ELFObjectFile return Header->e_shnum; } -template +template uint64_t -ELFObjectFile - ::getStringTableIndex() const { +ELFObjectFile::getStringTableIndex() const { if (Header->e_shnum == ELF::SHN_UNDEF) { if (Header->e_shstrndx == ELF::SHN_HIRESERVE) return SectionHeaderTable->sh_link; @@ -2455,62 +2827,44 @@ ELFObjectFile return Header->e_shstrndx; } -template +template template inline const T * -ELFObjectFile - ::getEntry(uint16_t Section, uint32_t Entry) const { +ELFObjectFile::getEntry(uint32_t Section, uint32_t Entry) const { return getEntry(getSection(Section), Entry); } -template +template template inline const T * -ELFObjectFile - ::getEntry(const Elf_Shdr * Section, uint32_t Entry) const { +ELFObjectFile::getEntry(const Elf_Shdr * Section, uint32_t Entry) const { return reinterpret_cast( base() + Section->sh_offset + (Entry * Section->sh_entsize)); } -template -const typename ELFObjectFile - ::Elf_Sym * -ELFObjectFile - ::getSymbol(DataRefImpl Symb) const { - return getEntry(SymbolTableSections[Symb.d.b], Symb.d.a); -} - -template -const typename ELFObjectFile - ::Elf_Dyn * -ELFObjectFile - ::getDyn(DataRefImpl DynData) const { - return getEntry(dot_dynamic_sec, DynData.d.a); +template +const typename ELFObjectFile::Elf_Sym * +ELFObjectFile::getSymbol(DataRefImpl Symb) const { + return getEntry(Symb.d.b, Symb.d.a); } -template -const typename ELFObjectFile - ::Elf_Rel * -ELFObjectFile - ::getRel(DataRefImpl Rel) const { - return getEntry(Rel.w.b, Rel.w.c); +template +const typename ELFObjectFile::Elf_Rel * +ELFObjectFile::getRel(DataRefImpl Rel) const { + return getEntry(Rel.d.a, Rel.d.b); } -template -const typename ELFObjectFile - ::Elf_Rela * -ELFObjectFile - ::getRela(DataRefImpl Rela) const { - return getEntry(Rela.w.b, Rela.w.c); +template +const typename ELFObjectFile::Elf_Rela * +ELFObjectFile::getRela(DataRefImpl Rela) const { + return getEntry(Rela.d.a, Rela.d.b); } -template -const typename ELFObjectFile - ::Elf_Shdr * -ELFObjectFile - ::getSection(DataRefImpl Symb) const { +template +const typename ELFObjectFile::Elf_Shdr * +ELFObjectFile::getSection(DataRefImpl Symb) const { const Elf_Shdr *sec = getSection(Symb.d.b); if (sec->sh_type != ELF::SHT_SYMTAB || sec->sh_type != ELF::SHT_DYNSYM) // FIXME: Proper error handling. @@ -2518,11 +2872,9 @@ ELFObjectFile return sec; } -template -const typename ELFObjectFile - ::Elf_Shdr * -ELFObjectFile - ::getSection(uint32_t index) const { +template +const typename ELFObjectFile::Elf_Shdr * +ELFObjectFile::getSection(uint32_t index) const { if (index == 0) return 0; if (!SectionHeaderTable || index >= getNumSections()) @@ -2534,17 +2886,15 @@ ELFObjectFile + (index * Header->e_shentsize)); } -template -const char *ELFObjectFile - ::getString(uint32_t section, - ELF::Elf32_Word offset) const { +template +const char *ELFObjectFile::getString(uint32_t section, + ELF::Elf32_Word offset) const { return getString(getSection(section), offset); } -template -const char *ELFObjectFile - ::getString(const Elf_Shdr *section, - ELF::Elf32_Word offset) const { +template +const char *ELFObjectFile::getString(const Elf_Shdr *section, + ELF::Elf32_Word offset) const { assert(section && section->sh_type == ELF::SHT_STRTAB && "Invalid section!"); if (offset >= section->sh_size) // FIXME: Proper error handling. @@ -2552,11 +2902,10 @@ const char *ELFObjectFile return (const char *)base() + section->sh_offset + offset; } -template -error_code ELFObjectFile - ::getSymbolName(const Elf_Shdr *section, - const Elf_Sym *symb, - StringRef &Result) const { +template +error_code ELFObjectFile::getSymbolName(const Elf_Shdr *section, + const Elf_Sym *symb, + StringRef &Result) const { if (symb->st_name == 0) { const Elf_Shdr *section = getSection(symb); if (!section) @@ -2566,7 +2915,8 @@ error_code ELFObjectFile return object_error::success; } - if (section == SymbolTableSections[0]) { + if (DynamicSymbolTableIndex != -1 && + section == getSection(DynamicSymbolTableIndex)) { // Symbol is in .dynsym, use .dynstr string table Result = getString(dot_dynstr_sec, symb->st_name); } else { @@ -2576,22 +2926,20 @@ error_code ELFObjectFile return object_error::success; } -template -error_code ELFObjectFile - ::getSectionName(const Elf_Shdr *section, - StringRef &Result) const { +template +error_code ELFObjectFile::getSectionName(const Elf_Shdr *section, + StringRef &Result) const { Result = StringRef(getString(dot_shstrtab_sec, section->sh_name)); return object_error::success; } -template -error_code ELFObjectFile - ::getSymbolVersion(const Elf_Shdr *section, - const Elf_Sym *symb, - StringRef &Version, - bool &IsDefault) const { +template +error_code ELFObjectFile::getSymbolVersion(const Elf_Shdr *section, + const Elf_Sym *symb, + StringRef &Version, + bool &IsDefault) const { // Handle non-dynamic symbols. - if (section != SymbolTableSections[0]) { + if (section != getSection(DynamicSymbolTableIndex)) { // Non-dynamic symbols can have versions in their names // A name of the form 'foo@V1' indicates version 'V1', non-default. // A name of the form 'foo@@V2' indicates version 'V2', default version. @@ -2667,52 +3015,29 @@ error_code ELFObjectFile return object_error::success; } -template -inline DynRefImpl - ::DynRefImpl(DataRefImpl DynP, const OwningType *Owner) - : DynPimpl(DynP) - , OwningObject(Owner) {} - -template -inline bool DynRefImpl - ::operator==(const DynRefImpl &Other) const { - return DynPimpl == Other.DynPimpl; -} - -template -inline bool DynRefImpl - ::operator <(const DynRefImpl &Other) const { - return DynPimpl < Other.DynPimpl; -} - -template -inline error_code DynRefImpl - ::getNext(DynRefImpl &Result) const { - return OwningObject->getDynNext(DynPimpl, Result); -} +/// FIXME: Maybe we should have a base ElfObjectFile that is not a template +/// and make these member functions? +static inline error_code getELFRelocationAddend(const RelocationRef R, + int64_t &Addend) { + const ObjectFile *Obj = R.getObjectFile(); + DataRefImpl DRI = R.getRawDataRefImpl(); + // Little-endian 32-bit + if (const ELF32LEObjectFile *ELFObj = dyn_cast(Obj)) + return ELFObj->getRelocationAddend(DRI, Addend); -template -inline int64_t DynRefImpl - ::getTag() const { - return OwningObject->getDyn(DynPimpl)->d_tag; -} + // Big-endian 32-bit + if (const ELF32BEObjectFile *ELFObj = dyn_cast(Obj)) + return ELFObj->getRelocationAddend(DRI, Addend); -template -inline uint64_t DynRefImpl - ::getVal() const { - return OwningObject->getDyn(DynPimpl)->d_un.d_val; -} + // Little-endian 64-bit + if (const ELF64LEObjectFile *ELFObj = dyn_cast(Obj)) + return ELFObj->getRelocationAddend(DRI, Addend); -template -inline uint64_t DynRefImpl - ::getPtr() const { - return OwningObject->getDyn(DynPimpl)->d_un.d_ptr; -} + // Big-endian 64-bit + if (const ELF64BEObjectFile *ELFObj = dyn_cast(Obj)) + return ELFObj->getRelocationAddend(DRI, Addend); -template -inline DataRefImpl DynRefImpl - ::getRawDataRefImpl() const { - return DynPimpl; + llvm_unreachable("Object passed to getELFRelocationAddend() is not ELF"); } /// This is a generic interface for retrieving GNU symbol version @@ -2722,28 +3047,39 @@ static inline error_code GetELFSymbolVersion(const ObjectFile *Obj, StringRef &Version, bool &IsDefault) { // Little-endian 32-bit - if (const ELFObjectFile *ELFObj = - dyn_cast >(Obj)) + if (const ELF32LEObjectFile *ELFObj = dyn_cast(Obj)) return ELFObj->getSymbolVersion(Sym, Version, IsDefault); // Big-endian 32-bit - if (const ELFObjectFile *ELFObj = - dyn_cast >(Obj)) + if (const ELF32BEObjectFile *ELFObj = dyn_cast(Obj)) return ELFObj->getSymbolVersion(Sym, Version, IsDefault); // Little-endian 64-bit - if (const ELFObjectFile *ELFObj = - dyn_cast >(Obj)) + if (const ELF64LEObjectFile *ELFObj = dyn_cast(Obj)) return ELFObj->getSymbolVersion(Sym, Version, IsDefault); // Big-endian 64-bit - if (const ELFObjectFile *ELFObj = - dyn_cast >(Obj)) + if (const ELF64BEObjectFile *ELFObj = dyn_cast(Obj)) return ELFObj->getSymbolVersion(Sym, Version, IsDefault); llvm_unreachable("Object passed to GetELFSymbolVersion() is not ELF"); } +/// This function returns the hash value for a symbol in the .dynsym section +/// Name of the API remains consistent as specified in the libelf +/// REF : http://www.sco.com/developers/gabi/latest/ch5.dynamic.html#hash +static inline unsigned elf_hash(StringRef &symbolName) { + unsigned h = 0, g; + for (unsigned i = 0, j = symbolName.size(); i < j; i++) { + h = (h << 4) + symbolName[i]; + g = h & 0xf0000000L; + if (g != 0) + h ^= g >> 24; + h &= ~g; + } + return h; +} + } }