diff --git a/llvm/include/llvm/Object/ELF.h b/llvm/include/llvm/Object/ELF.h index 823491613a04..8afbd451bebe 100644 --- a/llvm/include/llvm/Object/ELF.h +++ b/llvm/include/llvm/Object/ELF.h @@ -7,23 +7,26 @@ // //===----------------------------------------------------------------------===// // -// This file declares the ELFObjectFile template class. +// This file declares the ELFFile template class. // //===----------------------------------------------------------------------===// #ifndef LLVM_OBJECT_ELF_H #define LLVM_OBJECT_ELF_H +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Triple.h" -#include "llvm/Object/ObjectFile.h" +#include "llvm/Object/ELFTypes.h" +#include "llvm/Object/Error.h" #include "llvm/Support/Casting.h" #include "llvm/Support/ELF.h" #include "llvm/Support/Endian.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/ErrorOr.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/raw_ostream.h" #include @@ -33,22 +36,9 @@ namespace llvm { namespace object { -using support::endianness; +StringRef getELFRelocationTypeName(uint32_t Machine, uint32_t Type); -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 - : AlignOf::Alignment}; -}; - -// Subclasses of ELFObjectFile may need this for template instantiation +// Subclasses of ELFFile may need this for template instantiation inline std::pair getElfArchType(MemoryBuffer *Object) { if (Object->getBufferSize() < ELF::EI_NIDENT) @@ -57,442 +47,15 @@ getElfArchType(MemoryBuffer *Object) { (uint8_t) Object->getBufferStart()[ELF::EI_DATA]); } -// Templates to choose Elf_Addr and Elf_Off depending on is64Bits. -template -struct ELFDataTypeTypedefHelperCommon { - typedef support::detail::packed_endian_specific_integral - ::value> Elf_Half; - typedef support::detail::packed_endian_specific_integral - ::value> Elf_Word; - typedef support::detail::packed_endian_specific_integral - ::value> Elf_Sword; - typedef support::detail::packed_endian_specific_integral - ::value> Elf_Xword; - typedef support::detail::packed_endian_specific_integral - ::value> Elf_Sxword; -}; - -template -struct ELFDataTypeTypedefHelper; - -/// ELF 32bit types. -template -struct ELFDataTypeTypedefHelper > - : ELFDataTypeTypedefHelperCommon { - typedef uint32_t value_type; - typedef support::detail::packed_endian_specific_integral - ::value> Elf_Addr; - typedef support::detail::packed_endian_specific_integral - ::value> Elf_Off; -}; - -/// ELF 64bit types. -template -struct ELFDataTypeTypedefHelper > - : ELFDataTypeTypedefHelperCommon { - typedef uint64_t value_type; - typedef support::detail::packed_endian_specific_integral - ::value> Elf_Addr; - typedef support::detail::packed_endian_specific_integral - ::value> Elf_Off; -}; - -// I really don't like doing this, but the alternative is copypasta. -#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(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_*) - Elf_Addr sh_addr; // Address where section is to be loaded - Elf_Off sh_offset; // File offset of section data, in bytes - Elf_Word sh_size; // Size of section, in bytes - Elf_Word sh_link; // Section type-specific header table index link - Elf_Word sh_info; // Section type-specific extra information - Elf_Word sh_addralign;// Section address alignment - Elf_Word sh_entsize; // Size of records contained within the section -}; - -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_*) - Elf_Addr sh_addr; // Address where section is to be loaded - Elf_Off sh_offset; // File offset of section data, in bytes - Elf_Xword sh_size; // Size of section, in bytes - Elf_Word sh_link; // Section type-specific header table index link - Elf_Word sh_info; // Section type-specific extra information - Elf_Xword sh_addralign;// Section address alignment - 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; - - /// @brief Get the number of entities this section contains if it has any. - unsigned getEntityCount() const { - if (sh_entsize == 0) - return 0; - return sh_size / sh_entsize; - } -}; - -template -struct Elf_Sym_Base; - -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 - unsigned char st_info; // Symbol's type and binding attributes - unsigned char st_other; // Must be zero; reserved - Elf_Half st_shndx; // Which section (header table index) it's defined in -}; - -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 - Elf_Half st_shndx; // Which section (header table index) it's defined in - Elf_Addr st_value; // Value or address associated with the symbol - Elf_Xword st_size; // Size of the symbol -}; - -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: - unsigned char getBinding() const { return st_info >> 4; } - unsigned char getType() const { return st_info & 0x0f; } - void setBinding(unsigned char b) { setBindingAndType(b, getType()); } - void setType(unsigned char t) { setBindingAndType(getBinding(), t); } - void setBindingAndType(unsigned char b, unsigned char t) { - st_info = (b << 4) + (t & 0x0f); - } -}; - -/// 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 -struct Elf_Versym_Impl { - LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) - Elf_Half vs_index; // Version index with flags (e.g. VERSYM_HIDDEN) -}; - -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 -struct Elf_Verdef_Impl { - 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 - Elf_Half vd_cnt; // Number of Verdaux entries - Elf_Word vd_hash; // Hash of name - Elf_Word vd_aux; // Offset to the first Verdaux entry (in bytes) - Elf_Word vd_next; // Offset to the next Verdef entry (in bytes) - - /// Get the first Verdaux entry for this Verdef. - const Elf_Verdaux *getAux() const { - return reinterpret_cast((const char*)this + vd_aux); - } -}; - -/// 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 -struct Elf_Verdaux_Impl { - 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 -struct Elf_Verneed_Impl { - 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) - Elf_Word vn_aux; // Offset to first Vernaux entry (in bytes) - Elf_Word vn_next; // Offset to next Verneed entry (in bytes) -}; - -/// 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 -struct Elf_Vernaux_Impl { - 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 - Elf_Word vna_name; // Dependency name - Elf_Word vna_next; // Offset to next Vernaux entry (in bytes) -}; - -/// Elf_Dyn_Base: This structure matches the form of entries in the dynamic -/// table section (.dynamic) look like. -template -struct Elf_Dyn_Base; - -template -struct Elf_Dyn_Base > { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) - Elf_Sword d_tag; - union { - Elf_Word d_val; - Elf_Addr d_ptr; - } d_un; -}; - -template -struct Elf_Dyn_Base > { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) - Elf_Sxword d_tag; - union { - Elf_Xword d_val; - Elf_Addr d_ptr; - } d_un; -}; - -/// 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; - int64_t getTag() const { return d_tag; } - uint64_t getVal() const { return d_un.d_val; } - uint64_t getPtr() const { return d_un.ptr; } -}; - -// Elf_Rel: Elf Relocation -template -struct Elf_Rel_Base; - -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, 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, 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, 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 -struct Elf_Rel_Impl; - -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: - uint32_t getSymbol(bool isMips64EL) const { - return (uint32_t) (this->getRInfo(isMips64EL) >> 32); - } - 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, 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(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) { - this->setRInfo((s << 8) + t); - } -}; - -template -struct Elf_Ehdr_Impl { - 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_*) - Elf_Word e_version; // Must be equal to 1 - Elf_Addr e_entry; // Address to jump to in order to start program - Elf_Off e_phoff; // Program header table's file offset, in bytes - Elf_Off e_shoff; // Section header table's file offset, in bytes - Elf_Word e_flags; // Processor-specific flags - Elf_Half e_ehsize; // Size of ELF header, in bytes - Elf_Half e_phentsize;// Size of an entry in the program header table - Elf_Half e_phnum; // Number of entries in the program header table - Elf_Half e_shentsize;// Size of an entry in the section header table - Elf_Half e_shnum; // Number of entries in the section header table - Elf_Half e_shstrndx; // Section header table index of section name - // string table - bool checkMagic() const { - return (memcmp(e_ident, ELF::ElfMagic, strlen(ELF::ElfMagic))) == 0; - } - unsigned char getFileClass() const { return e_ident[ELF::EI_CLASS]; } - unsigned char getDataEncoding() const { return e_ident[ELF::EI_DATA]; } -}; - -template -struct Elf_Phdr_Impl; - -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 - Elf_Addr p_paddr; // Physical address of beginning of segment (OS-specific) - Elf_Word p_filesz; // Num. of bytes in file image of segment (may be zero) - Elf_Word p_memsz; // Num. of bytes in mem image of segment (may be zero) - Elf_Word p_flags; // Segment flags - Elf_Word p_align; // Segment alignment constraint -}; - -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 - Elf_Addr p_vaddr; // Virtual Address of beginning of segment - Elf_Addr p_paddr; // Physical address of beginning of segment (OS-specific) - Elf_Xword p_filesz; // Num. of bytes in file image of segment (may be zero) - Elf_Xword p_memsz; // Num. of bytes in mem image of segment (may be zero) - Elf_Xword p_align; // Segment alignment constraint -}; - -template -class ELFObjectFile : public ObjectFile { - LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) - +template +class ELFFile { public: + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) + typedef typename conditional::type uintX_t; + /// \brief Iterate over constant sized entities. - template + template class ELFEntityIterator { public: typedef ptrdiff_t difference_type; @@ -503,9 +66,8 @@ public: /// \brief Default construct iterator. ELFEntityIterator() : EntitySize(0), Current(0) {} - ELFEntityIterator(uint64_t EntSize, const char *Start) - : EntitySize(EntSize) - , Current(Start) {} + ELFEntityIterator(uintX_t EntSize, const char *Start) + : EntitySize(EntSize), Current(Start) {} reference operator *() { assert(Current && "Attempted to dereference an invalid iterator!"); @@ -545,14 +107,16 @@ public: difference_type operator -(const ELFEntityIterator &Other) const { assert(EntitySize == Other.EntitySize && - "Subtracting iterators of different EntitiySize!"); + "Subtracting iterators of different EntitySize!"); return (Current - Other.Current) / EntitySize; } const char *get() const { return Current; } + uintX_t getEntSize() const { return EntitySize; } + private: - uint64_t EntitySize; + uintX_t EntitySize; const char *Current; }; @@ -568,40 +132,141 @@ public: 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_Dyn_Iter; typedef ELFEntityIterator Elf_Rela_Iter; typedef ELFEntityIterator Elf_Rel_Iter; + typedef ELFEntityIterator Elf_Shdr_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; + /// \brief Archive files are 2 byte aligned, so we need this for + /// PointerIntPair to work. + template + class ArchivePointerTypeTraits { + public: + static inline const void *getAsVoidPointer(T *P) { return P; } + static inline T *getFromVoidPointer(const void *P) { + return static_cast(P); + } + enum { NumLowBitsAvailable = 1 }; + }; + + class Elf_Sym_Iter { + public: + typedef ptrdiff_t difference_type; + typedef const Elf_Sym value_type; + typedef std::random_access_iterator_tag iterator_category; + typedef value_type &reference; + typedef value_type *pointer; + + /// \brief Default construct iterator. + Elf_Sym_Iter() : EntitySize(0), Current(0, false) {} + Elf_Sym_Iter(uintX_t EntSize, const char *Start, bool IsDynamic) + : EntitySize(EntSize), Current(Start, IsDynamic) {} + + reference operator*() { + assert(Current.getPointer() && + "Attempted to dereference an invalid iterator!"); + return *reinterpret_cast(Current.getPointer()); + } + + pointer operator->() { + assert(Current.getPointer() && + "Attempted to dereference an invalid iterator!"); + return reinterpret_cast(Current.getPointer()); + } + + bool operator==(const Elf_Sym_Iter &Other) { + return Current == Other.Current; + } + + bool operator!=(const Elf_Sym_Iter &Other) { return !(*this == Other); } + + Elf_Sym_Iter &operator++() { + assert(Current.getPointer() && + "Attempted to increment an invalid iterator!"); + Current.setPointer(Current.getPointer() + EntitySize); + return *this; + } + + Elf_Sym_Iter operator++(int) { + Elf_Sym_Iter Tmp = *this; + ++*this; + return Tmp; + } + + Elf_Sym_Iter operator+(difference_type Dist) { + assert(Current.getPointer() && + "Attempted to increment an invalid iterator!"); + Current.setPointer(Current.getPointer() + EntitySize * Dist); + return *this; + } + + Elf_Sym_Iter &operator=(const Elf_Sym_Iter &Other) { + EntitySize = Other.EntitySize; + Current = Other.Current; + return *this; + } + + difference_type operator-(const Elf_Sym_Iter &Other) const { + assert(EntitySize == Other.EntitySize && + "Subtracting iterators of different EntitySize!"); + return (Current.getPointer() - Other.Current.getPointer()) / EntitySize; + } + + const char *get() const { return Current.getPointer(); } + + bool isDynamic() const { return Current.getInt(); } + + uintX_t getEntSize() const { return EntitySize; } + + private: + uintX_t EntitySize; + PointerIntPair > Current; + }; private: + typedef SmallVector Sections_t; + typedef DenseMap IndexMap_t; + + MemoryBuffer *Buf; + + const uint8_t *base() const { + return reinterpret_cast(Buf->getBufferStart()); + } + 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. + const Elf_Shdr *dot_symtab_sec; // Symbol table section. - int SymbolTableIndex; - int DynamicSymbolTableIndex; - DenseMap ExtendedSymbolTable; + const Elf_Shdr *SymbolTableSectionHeaderIndex; + 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 + /// \brief Represents a region described by entries in the .dynamic table. + struct DynRegionInfo { + DynRegionInfo() : Addr(nullptr), Size(0), EntSize(0) {} + /// \brief Address in current address space. + const void *Addr; + /// \brief Size in bytes of the region. + uintX_t Size; + /// \brief Size of each entity in the region. + uintX_t EntSize; + }; + + DynRegionInfo DynamicRegion; + DynRegionInfo DynHashRegion; + DynRegionInfo DynStrRegion; + DynRegionInfo DynSymRegion; + // 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 { @@ -628,99 +293,29 @@ private: void LoadVersionNeeds(const Elf_Shdr *ec) const; void LoadVersionMap() const; - /// @brief Get the relocation section that contains \a Rel. - const Elf_Shdr *getRelSection(DataRefImpl Rel) const { - return getSection(Rel.d.a); - } - public: - bool isRelocationHasAddend(DataRefImpl Rel) const; template 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; - const Elf_Shdr *getSection(uint32_t index) const; - const Elf_Rel *getRel(DataRefImpl Rel) const; - const Elf_Rela *getRela(DataRefImpl Rela) const; + template + const T *getEntry(const Elf_Shdr *Section, uint32_t Entry) const; const char *getString(uint32_t section, uint32_t offset) const; const char *getString(const Elf_Shdr *section, uint32_t offset) const; - error_code getSymbolVersion(const Elf_Shdr *section, - const Elf_Sym *Symb, - StringRef &Version, - bool &IsDefault) const; + const char *getDynamicString(uintX_t Offset) const; + ErrorOr getSymbolVersion(const Elf_Shdr *section, + const Elf_Sym *Symb, + bool &IsDefault) const; void VerifyStrTab(const Elf_Shdr *sh) const; -protected: - const Elf_Sym *getSymbol(DataRefImpl Symb) const; // FIXME: Should be private? - void validateSymbol(DataRefImpl Symb) const; - StringRef getRelocationTypeName(uint32_t Type) const; + StringRef getRelocationTypeName(uint32_t Type) const; + void getRelocationTypeName(uint32_t Type, + SmallVectorImpl &Result) const; -public: - error_code getSymbolName(const Elf_Shdr *section, - const Elf_Sym *Symb, - StringRef &Res) const; - error_code getSectionName(const Elf_Shdr *section, - StringRef &Res) const; - const Elf_Dyn *getDyn(DataRefImpl DynData) const; - 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 getSymbolSection(DataRefImpl Symb, - section_iterator &Res) const; - virtual error_code getSymbolValue(DataRefImpl Symb, uint64_t &Val) const; + /// \brief Get the symbol table section and symbol for a given relocation. + template + std::pair + getRelocationSymbol(const Elf_Shdr *RelSec, const RelT *Rel) const; - virtual error_code getLibraryNext(DataRefImpl Data, LibraryRef &Result) const; - virtual error_code getLibraryPath(DataRefImpl Data, StringRef &Res) const; - - virtual error_code getSectionNext(DataRefImpl Sec, SectionRef &Res) const; - virtual error_code getSectionName(DataRefImpl Sec, StringRef &Res) const; - virtual error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const; - virtual error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const; - virtual error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const; - virtual error_code getSectionAlignment(DataRefImpl Sec, uint64_t &Res) const; - virtual error_code isSectionText(DataRefImpl Sec, bool &Res) const; - virtual error_code isSectionData(DataRefImpl Sec, bool &Res) const; - virtual error_code isSectionBSS(DataRefImpl Sec, bool &Res) const; - virtual error_code isSectionRequiredForExecution(DataRefImpl Sec, - bool &Res) const; - virtual error_code isSectionVirtual(DataRefImpl Sec, bool &Res) const; - virtual error_code isSectionZeroInit(DataRefImpl Sec, bool &Res) const; - virtual error_code isSectionReadOnlyData(DataRefImpl Sec, bool &Res) const; - virtual error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, - 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; - virtual error_code getRelocationAddress(DataRefImpl Rel, - uint64_t &Res) const; - virtual error_code getRelocationOffset(DataRefImpl Rel, - uint64_t &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 getRelocationValueString(DataRefImpl Rel, - SmallVectorImpl &Result) const; - -public: - ELFObjectFile(MemoryBuffer *Object, error_code &ec); + ELFFile(MemoryBuffer *Object, error_code &ec); bool isMips64EL() const { return Header->e_machine == ELF::EM_MIPS && @@ -728,65 +323,51 @@ public: Header->getDataEncoding() == ELF::ELFDATA2LSB; } - virtual symbol_iterator begin_symbols() const; - virtual symbol_iterator end_symbols() const; + Elf_Shdr_Iter begin_sections() const; + Elf_Shdr_Iter end_sections() const; - virtual symbol_iterator begin_dynamic_symbols() const; - virtual symbol_iterator end_dynamic_symbols() const; + Elf_Sym_Iter begin_symbols() const; + Elf_Sym_Iter end_symbols() const; - virtual section_iterator begin_sections() const; - virtual section_iterator end_sections() const; - - virtual library_iterator begin_libraries_needed() const; - virtual library_iterator end_libraries_needed() const; - - const Elf_Shdr *getDynamicSymbolTableSectionHeader() const { - return getSection(DynamicSymbolTableIndex); - } - - const Elf_Shdr *getDynamicStringTableSectionHeader() const { - return dot_dynstr_sec; - } - - Elf_Dyn_iterator begin_dynamic_table() const; + Elf_Dyn_Iter 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_Dyn_Iter 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_Iter begin_dynamic_symbols() const { + if (DynSymRegion.Addr) + return Elf_Sym_Iter(DynSymRegion.EntSize, (const char *)DynSymRegion.Addr, + true); + return Elf_Sym_Iter(0, 0, true); } - 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_Sym_Iter end_dynamic_symbols() const { + if (DynSymRegion.Addr) + return Elf_Sym_Iter(DynSymRegion.EntSize, + (const char *)DynSymRegion.Addr + DynSymRegion.Size, + true); + return Elf_Sym_Iter(0, 0, true); } - Elf_Rela_Iter beginELFRela(const Elf_Shdr *sec) const { + Elf_Rela_Iter begin_rela(const Elf_Shdr *sec) const { return Elf_Rela_Iter(sec->sh_entsize, (const char *)(base() + sec->sh_offset)); } - Elf_Rela_Iter endELFRela(const Elf_Shdr *sec) const { - return Elf_Rela_Iter(sec->sh_entsize, (const char *) - (base() + sec->sh_offset + sec->sh_size)); + Elf_Rela_Iter end_rela(const Elf_Shdr *sec) const { + return Elf_Rela_Iter( + sec->sh_entsize, + (const char *)(base() + sec->sh_offset + sec->sh_size)); } - Elf_Rel_Iter beginELFRel(const Elf_Shdr *sec) const { + Elf_Rel_Iter begin_rel(const Elf_Shdr *sec) const { return Elf_Rel_Iter(sec->sh_entsize, (const char *)(base() + sec->sh_offset)); } - Elf_Rel_Iter endELFRel(const Elf_Shdr *sec) const { - return Elf_Rel_Iter(sec->sh_entsize, (const char *) - (base() + sec->sh_offset + sec->sh_size)); + Elf_Rel_Iter end_rel(const Elf_Shdr *sec) const { + return Elf_Rel_Iter(sec->sh_entsize, + (const char *)(base() + sec->sh_offset + sec->sh_size)); } /// \brief Iterate over program header table. @@ -804,43 +385,42 @@ public: (Header->e_phnum * Header->e_phentsize)); } - virtual uint8_t getBytesInAddress() const; - virtual StringRef getFileFormatName() const; - virtual StringRef getObjectType() const { return "ELF"; } - virtual unsigned getArch() const; - virtual StringRef getLoadName() const; - virtual error_code getSectionContents(const Elf_Shdr *sec, - StringRef &Res) const; - uint64_t getNumSections() const; - uint64_t getStringTableIndex() const; + uintX_t getStringTableIndex() const; ELF::Elf64_Word getSymbolTableIndex(const Elf_Sym *symb) const; - const Elf_Ehdr *getElfHeader() const; + const Elf_Ehdr *getHeader() const { return Header; } 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; - const Elf_Sym *getElfSymbol(uint32_t index) const; + const Elf_Shdr *getSection(uint32_t Index) const; + const Elf_Sym *getSymbol(uint32_t index) const; - // 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(ELFT::TargetEndianness == support::little, - ELFT::Is64Bits); - } + ErrorOr getSymbolName(Elf_Sym_Iter Sym) const; + + /// \brief Get the name of \p Symb. + /// \param SymTab The symbol table section \p Symb is contained in. + /// \param Symb The symbol to get the name of. + /// + /// \p SymTab is used to lookup the string table to use to get the symbol's + /// name. + ErrorOr getSymbolName(const Elf_Shdr *SymTab, + const Elf_Sym *Symb) const; + ErrorOr getSectionName(const Elf_Shdr *Section) const; + uint64_t getSymbolIndex(const Elf_Sym *sym) const; + ErrorOr > getSectionContents(const Elf_Shdr *Sec) const; + StringRef getLoadName() const; }; // 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; +typedef ELFFile > ELF32LEFile; +typedef ELFFile > ELF64LEFile; +typedef ELFFile > ELF32BEFile; +typedef ELFFile > ELF64BEFile; // 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 { - unsigned vd_size = sec->sh_size; // Size of section in bytes +template +void ELFFile::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; const char *sec_end = sec_start + vd_size; @@ -855,7 +435,7 @@ void ELFObjectFile::LoadVersionDefs(const Elf_Shdr *sec) const { report_fatal_error("Unexpected verdef version"); size_t index = vd->vd_ndx & ELF::VERSYM_VERSION; if (index >= VersionMap.size()) - VersionMap.resize(index+1); + VersionMap.resize(index + 1); VersionMap[index] = VersionMapEntry(vd); p += vd->vd_next; } @@ -863,11 +443,11 @@ void ELFObjectFile::LoadVersionDefs(const Elf_Shdr *sec) const { // 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 { - unsigned vn_size = sec->sh_size; // Size of section in bytes +template +void ELFFile::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; + const char *sec_start = (const char *)base() + sec->sh_offset; const char *sec_end = sec_start + vn_size; // The first Verneed entry is at the start of the section. const char *p = sec_start; @@ -887,7 +467,7 @@ void ELFObjectFile::LoadVersionNeeds(const Elf_Shdr *sec) const { const Elf_Vernaux *vna = reinterpret_cast(paux); size_t index = vna->vna_other & ELF::VERSYM_VERSION; if (index >= VersionMap.size()) - VersionMap.resize(index+1); + VersionMap.resize(index + 1); VersionMap[index] = VersionMapEntry(vna); paux += vna->vna_next; } @@ -895,11 +475,10 @@ void ELFObjectFile::LoadVersionNeeds(const Elf_Shdr *sec) const { } } -template -void ELFObjectFile::LoadVersionMap() const { +template +void ELFFile::LoadVersionMap() const { // If there is no dynamic symtab or version table, there is nothing to do. - if (getDynamicStringTableSectionHeader() == NULL || - dot_gnu_version_sec == NULL) + if (DynSymRegion.Addr == NULL || dot_gnu_version_sec == NULL) return; // Has the VersionMap already been loaded? @@ -918,64 +497,16 @@ void ELFObjectFile::LoadVersionMap() const { LoadVersionNeeds(dot_gnu_version_r_sec); } -template -void ELFObjectFile::validateSymbol(DataRefImpl Symb) const { -#ifndef NDEBUG - const Elf_Sym *symb = getSymbol(Symb); - 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. - if (!( symb - && SymbolTableSection - && symb >= (const Elf_Sym*)(base() - + SymbolTableSection->sh_offset) - && symb < (const Elf_Sym*)(base() - + SymbolTableSection->sh_offset - + 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 { - validateSymbol(Symb); - ++Symb.d.a; - Result = SymbolRef(Symb, this); - return object_error::success; -} - -template -error_code ELFObjectFile::getSymbolName(DataRefImpl Symb, - StringRef &Result) const { - validateSymbol(Symb); - const Elf_Sym *symb = getSymbol(Symb); - return getSymbolName(getSection(Symb.d.b), symb, Result); -} - -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(getSection(Symb.d.b), symb, Version, IsDefault); -} - -template -ELF::Elf64_Word ELFObjectFile - ::getSymbolTableIndex(const Elf_Sym *symb) const { +template +ELF::Elf64_Word ELFFile::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 ELFFile::Elf_Shdr * +ELFFile::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) @@ -983,1282 +514,36 @@ ELFObjectFile::getSection(const Elf_Sym *symb) const { return getSection(symb->st_shndx); } -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 { - return getSymbol(It->getRawDataRefImpl()); -} - -template -const typename ELFObjectFile::Elf_Sym * -ELFObjectFile::getElfSymbol(uint32_t index) const { - DataRefImpl SymbolData; - SymbolData.d.a = index; - SymbolData.d.b = SymbolTableIndex; - return getSymbol(SymbolData); -} - -template -error_code ELFObjectFile::getSymbolFileOffset(DataRefImpl Symb, - uint64_t &Result) const { - validateSymbol(Symb); - const Elf_Sym *symb = getSymbol(Symb); - const Elf_Shdr *Section; - switch (getSymbolTableIndex(symb)) { - case ELF::SHN_COMMON: - // Unintialized symbols have no offset in the object file - case ELF::SHN_UNDEF: - Result = UnknownAddressOrSize; - return object_error::success; - case ELF::SHN_ABS: - Result = symb->st_value; - return object_error::success; - default: Section = getSection(symb); - } - - switch (symb->getType()) { - case ELF::STT_SECTION: - Result = Section ? Section->sh_offset : UnknownAddressOrSize; - return object_error::success; - case ELF::STT_FUNC: - case ELF::STT_OBJECT: - case ELF::STT_NOTYPE: - Result = symb->st_value + - (Section ? Section->sh_offset : 0); - return object_error::success; - default: - Result = UnknownAddressOrSize; - return object_error::success; - } -} - -template -error_code ELFObjectFile::getSymbolAddress(DataRefImpl Symb, - uint64_t &Result) const { - validateSymbol(Symb); - const Elf_Sym *symb = getSymbol(Symb); - const Elf_Shdr *Section; - switch (getSymbolTableIndex(symb)) { - case ELF::SHN_COMMON: - case ELF::SHN_UNDEF: - Result = UnknownAddressOrSize; - return object_error::success; - case ELF::SHN_ABS: - Result = symb->st_value; - return object_error::success; - default: Section = getSection(symb); - } - - switch (symb->getType()) { - case ELF::STT_SECTION: - Result = Section ? Section->sh_addr : UnknownAddressOrSize; - return object_error::success; - case ELF::STT_FUNC: - case ELF::STT_OBJECT: - case ELF::STT_NOTYPE: - bool IsRelocatable; - switch(Header->e_type) { - case ELF::ET_EXEC: - case ELF::ET_DYN: - IsRelocatable = false; - break; - default: - 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; - default: - Result = UnknownAddressOrSize; - return object_error::success; - } -} - -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) - Result = UnknownAddressOrSize; - Result = symb->st_size; - return object_error::success; -} - -template -error_code ELFObjectFile::getSymbolNMTypeChar(DataRefImpl Symb, - char &Result) const { - validateSymbol(Symb); - const Elf_Sym *symb = getSymbol(Symb); - const Elf_Shdr *Section = getSection(symb); - - char ret = '?'; - - if (Section) { - switch (Section->sh_type) { - case ELF::SHT_PROGBITS: - case ELF::SHT_DYNAMIC: - switch (Section->sh_flags) { - case (ELF::SHF_ALLOC | ELF::SHF_EXECINSTR): - ret = 't'; break; - case (ELF::SHF_ALLOC | ELF::SHF_WRITE): - ret = 'd'; break; - case ELF::SHF_ALLOC: - case (ELF::SHF_ALLOC | ELF::SHF_MERGE): - case (ELF::SHF_ALLOC | ELF::SHF_MERGE | ELF::SHF_STRINGS): - ret = 'r'; break; - } - break; - case ELF::SHT_NOBITS: ret = 'b'; - } - } - - switch (getSymbolTableIndex(symb)) { - case ELF::SHN_UNDEF: - if (ret == '?') - ret = 'U'; - break; - case ELF::SHN_ABS: ret = 'a'; break; - case ELF::SHN_COMMON: ret = 'c'; break; - } - - switch (symb->getBinding()) { - case ELF::STB_GLOBAL: ret = ::toupper(ret); break; - case ELF::STB_WEAK: - if (getSymbolTableIndex(symb) == ELF::SHN_UNDEF) - ret = 'w'; - else - if (symb->getType() == ELF::STT_OBJECT) - ret = 'V'; - else - ret = 'W'; - } - - if (ret == '?' && symb->getType() == ELF::STT_SECTION) { - StringRef name; - if (error_code ec = getSymbolName(Symb, name)) - return ec; - Result = StringSwitch(name) - .StartsWith(".debug", 'N') - .StartsWith(".note", 'n') - .Default('?'); - return object_error::success; - } - - Result = ret; - return object_error::success; -} - -template -error_code ELFObjectFile::getSymbolType(DataRefImpl Symb, - SymbolRef::Type &Result) const { - validateSymbol(Symb); - const Elf_Sym *symb = getSymbol(Symb); - - switch (symb->getType()) { - case ELF::STT_NOTYPE: - Result = SymbolRef::ST_Unknown; - break; - case ELF::STT_SECTION: - Result = SymbolRef::ST_Debug; - break; - case ELF::STT_FILE: - Result = SymbolRef::ST_File; - break; - case ELF::STT_FUNC: - Result = SymbolRef::ST_Function; - break; - case ELF::STT_OBJECT: - case ELF::STT_COMMON: - case ELF::STT_TLS: - Result = SymbolRef::ST_Data; - break; - default: - Result = SymbolRef::ST_Other; - break; - } - return object_error::success; -} - -template -error_code ELFObjectFile::getSymbolFlags(DataRefImpl Symb, - uint32_t &Result) const { - validateSymbol(Symb); - const Elf_Sym *symb = getSymbol(Symb); - - Result = SymbolRef::SF_None; - - if (symb->getBinding() != ELF::STB_LOCAL) - Result |= SymbolRef::SF_Global; - - if (symb->getBinding() == ELF::STB_WEAK) - Result |= SymbolRef::SF_Weak; - - if (symb->st_shndx == ELF::SHN_ABS) - Result |= SymbolRef::SF_Absolute; - - if (symb->getType() == ELF::STT_FILE || - symb->getType() == ELF::STT_SECTION || - Symb == begin_symbols()->getRawDataRefImpl()) - Result |= SymbolRef::SF_FormatSpecific; - - if (getSymbolTableIndex(symb) == ELF::SHN_UNDEF) - Result |= SymbolRef::SF_Undefined; - - if (symb->getType() == ELF::STT_COMMON || - getSymbolTableIndex(symb) == ELF::SHN_COMMON) - Result |= SymbolRef::SF_Common; - - if (symb->getType() == ELF::STT_TLS) - Result |= SymbolRef::SF_ThreadLocal; - - return object_error::success; -} - -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); - if (!sec) - Res = end_sections(); - else { - DataRefImpl Sec; - Sec.p = reinterpret_cast(sec); - Res = section_iterator(SectionRef(Sec, this)); - } - return object_error::success; -} - -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 { - const uint8_t *sec = reinterpret_cast(Sec.p); - sec += Header->e_shentsize; - Sec.p = reinterpret_cast(sec); - Result = SectionRef(Sec, this); - return object_error::success; -} - -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 { - 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 { - 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 { - 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 { - 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 { - 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 { - const Elf_Shdr *sec = reinterpret_cast(Sec.p); - if (sec->sh_flags & ELF::SHF_EXECINSTR) - Result = true; - else - Result = false; - return object_error::success; -} - -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) - Result = true; - else - Result = false; - return object_error::success; -} - -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) - Result = true; - else - Result = false; - return object_error::success; -} - -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; - else - Result = false; - return object_error::success; -} - -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; - else - Result = false; - return object_error::success; -} - -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. - Result = sec->sh_type == ELF::SHT_NOBITS; - return object_error::success; -} - -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; - else - Result = true; - return object_error::success; -} - -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 { - DataRefImpl RelData; - 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 { - DataRefImpl RelData; - 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 +const typename ELFFile::Elf_Sym * +ELFFile::getSymbol(uint32_t Index) const { + return &*(begin_symbols() + Index); } 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.d.b; - Result = RelocationRef(Rel, this); - return object_error::success; +ErrorOr > +ELFFile::getSectionContents(const Elf_Shdr *Sec) const { + if (Sec->sh_offset + Sec->sh_size > Buf->getBufferSize()) + return object_error::parse_failed; + const uint8_t *Start = base() + Sec->sh_offset; + return ArrayRef(Start, Sec->sh_size); } template -symbol_iterator -ELFObjectFile::getRelocationSymbol(DataRefImpl Rel) const { - uint32_t symbolIdx; - 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(isMips64EL()); - break; - } - case ELF::SHT_RELA : { - symbolIdx = getRela(Rel)->getSymbol(isMips64EL()); - break; - } - } - if (!symbolIdx) - return end_symbols(); - - DataRefImpl SymbolData; - SymbolData.d.a = symbolIdx; - SymbolData.d.b = sec->sh_link; - return symbol_iterator(SymbolRef(SymbolData, this)); +StringRef ELFFile::getRelocationTypeName(uint32_t Type) const { + return getELFRelocationTypeName(Header->e_machine, Type); } -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; -} - -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 -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: - return getRel(Rel)->r_offset; - case ELF::SHT_RELA: - return getRela(Rel)->r_offset; - } -} - -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(isMips64EL()); - break; - } - case ELF::SHT_RELA : { - Result = getRela(Rel)->getType(isMips64EL()); - break; - } - } - return object_error::success; -} - -#define LLVM_ELF_SWITCH_RELOC_TYPE_NAME(enum) \ - case ELF::enum: Res = #enum; break; - -template -StringRef ELFObjectFile::getRelocationTypeName(uint32_t Type) const { - StringRef Res = "Unknown"; - switch (Header->e_machine) { - case ELF::EM_X86_64: - 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); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOT32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_PLT32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_COPY); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GLOB_DAT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_JUMP_SLOT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_RELATIVE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTPCREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_32S); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_PC16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_8); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_PC8); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_DTPMOD64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_DTPOFF64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_TPOFF64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_TLSGD); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_TLSLD); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_DTPOFF32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTTPOFF); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_TPOFF32); - 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); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_IRELATIVE); - default: break; - } - break; - case ELF::EM_386: - 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); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_GOT32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_PLT32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_COPY); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_GLOB_DAT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_JUMP_SLOT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_RELATIVE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_GOTOFF); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_GOTPC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_32PLT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_TPOFF); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_IE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_GOTIE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_GD); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LDM); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_PC16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_8); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_PC8); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_GD_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_GD_PUSH); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_GD_CALL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_GD_POP); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LDM_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LDM_PUSH); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LDM_CALL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LDM_POP); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LDO_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_IE_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LE_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_DTPMOD32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_DTPOFF32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_TPOFF32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_GOTDESC); - 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: 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) { - 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); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_REL32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDR_PC_G0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ABS16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ABS12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_ABS5); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ABS8); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_SBREL32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_CALL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_PC8); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_BREL_ADJ); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_DESC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_SWI8); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_XPC25); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_XPC22); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_DTPMOD32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_DTPOFF32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_TPOFF32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_COPY); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_GLOB_DAT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_JUMP_SLOT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_RELATIVE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_GOTOFF32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_BASE_PREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_GOT_BREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PLT32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_CALL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_JUMP24); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_JUMP24); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_BASE_ABS); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_PCREL_7_0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_PCREL_15_8); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_PCREL_23_15); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDR_SBREL_11_0_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_SBREL_19_12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_SBREL_27_20_CK); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TARGET1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_SBREL31); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_V4BX); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TARGET2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PREL31); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_MOVW_ABS_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_MOVT_ABS); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_MOVW_PREL_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_MOVT_PREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_MOVW_ABS_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_MOVT_ABS); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_MOVW_PREL_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_MOVT_PREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_JUMP19); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_JUMP6); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_ALU_PREL_11_0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_PC12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ABS32_NOI); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_REL32_NOI); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_PC_G0_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_PC_G0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_PC_G1_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_PC_G1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_PC_G2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDR_PC_G1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDR_PC_G2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDRS_PC_G0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDRS_PC_G1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDRS_PC_G2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDC_PC_G0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDC_PC_G1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDC_PC_G2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_SB_G0_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_SB_G0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_SB_G1_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_SB_G1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_SB_G2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDR_SB_G0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDR_SB_G1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDR_SB_G2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDRS_SB_G0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDRS_SB_G1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDRS_SB_G2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDC_SB_G0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDC_SB_G1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDC_SB_G2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_MOVW_BREL_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_MOVT_BREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_MOVW_BREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_MOVW_BREL_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_MOVT_BREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_MOVW_BREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_GOTDESC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_CALL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_DESCSEQ); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_TLS_CALL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PLT32_ABS); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_GOT_ABS); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_GOT_PREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_GOT_BREL12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_GOTOFF12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_GOTRELAX); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_GNU_VTENTRY); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_GNU_VTINHERIT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_JUMP11); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_JUMP8); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_GD32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_LDM32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_LDO32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_IE32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_LE32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_LDO12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_LE12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_IE12GP); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_3); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_4); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_5); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_6); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_7); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_8); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_9); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_10); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_11); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_13); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_14); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_15); - 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: break; - } - break; - case ELF::EM_HEXAGON: - 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); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B7_PCREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_LO16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_HI16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_8); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GPREL16_0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GPREL16_1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GPREL16_2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GPREL16_3); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_HL16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B13_PCREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B9_PCREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B32_PCREL_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_32_6_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B22_PCREL_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B15_PCREL_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B13_PCREL_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B9_PCREL_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B7_PCREL_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_16_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_12_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_11_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_10_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_9_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_8_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_7_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_6_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_32_PCREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_COPY); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GLOB_DAT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_JMP_SLOT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_RELATIVE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_PLT_B22_PCREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOTREL_LO16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOTREL_HI16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOTREL_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOT_LO16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOT_HI16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOT_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOT_16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_DTPMOD_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_DTPREL_LO16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_DTPREL_HI16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_DTPREL_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_DTPREL_16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GD_PLT_B22_PCREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GD_GOT_LO16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GD_GOT_HI16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GD_GOT_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GD_GOT_16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_LO16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_HI16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_GOT_LO16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_GOT_HI16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_GOT_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_GOT_16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_TPREL_LO16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_TPREL_HI16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_TPREL_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_TPREL_16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_6_PCREL_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOTREL_32_6_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOTREL_16_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOTREL_11_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOT_32_6_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOT_16_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOT_11_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_DTPREL_32_6_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_DTPREL_16_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_DTPREL_11_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GD_GOT_32_6_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GD_GOT_16_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GD_GOT_11_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_32_6_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_16_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_GOT_32_6_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_GOT_16_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_GOT_11_X); - 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: break; - } - break; - 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; - } - return Res; -} - -#undef LLVM_ELF_SWITCH_RELOC_TYPE_NAME - -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; - } - } - +template +void ELFFile::getRelocationTypeName(uint32_t Type, + SmallVectorImpl &Result) const { if (!isMips64EL()) { - StringRef Name = getRelocationTypeName(type); + 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; + 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); @@ -2272,135 +557,63 @@ error_code ELFObjectFile::getRelocationTypeName( 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!"); - case ELF::SHT_REL : { - Result = 0; - return object_error::success; - } - case ELF::SHT_RELA : { - Result = getRela(Rel)->r_addend; - return object_error::success; - } - } -} - -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; - uint16_t symbol_index = 0; - switch (sec->sh_type) { - default: - return object_error::parse_failed; - case ELF::SHT_REL: { - 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(isMips64EL()); - symbol_index = getRela(Rel)->getSymbol(isMips64EL()); - addend = getRela(Rel)->r_addend; - break; - } - } - const Elf_Sym *symb = getEntry(sec->sh_link, symbol_index); - StringRef symname; - if (error_code ec = getSymbolName(getSection(sec->sh_link), symb, symname)) - return ec; - switch (Header->e_machine) { - case ELF::EM_X86_64: - switch (type) { - case ELF::R_X86_64_PC8: - case ELF::R_X86_64_PC16: - case ELF::R_X86_64_PC32: { - std::string fmtbuf; - raw_string_ostream fmt(fmtbuf); - fmt << symname << (addend < 0 ? "" : "+") << addend << "-P"; - fmt.flush(); - Result.append(fmtbuf.begin(), fmtbuf.end()); - } - break; - case ELF::R_X86_64_8: - case ELF::R_X86_64_16: - case ELF::R_X86_64_32: - case ELF::R_X86_64_32S: - case ELF::R_X86_64_64: { - std::string fmtbuf; - raw_string_ostream fmt(fmtbuf); - fmt << symname << (addend < 0 ? "" : "+") << addend; - fmt.flush(); - Result.append(fmtbuf.begin(), fmtbuf.end()); - } - break; - default: - 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; - break; - default: - res = "Unknown"; - } - if (Result.empty()) - Result.append(res.begin(), res.end()); - return object_error::success; +template +template +std::pair::Elf_Shdr *, + const typename ELFFile::Elf_Sym *> +ELFFile::getRelocationSymbol(const Elf_Shdr *Sec, const RelT *Rel) const { + if (!Sec->sh_link) + return std::pair(0, 0); + const Elf_Shdr *SymTable = getSection(Sec->sh_link); + return std::make_pair( + SymTable, getEntry(SymTable, Rel->getSymbol(isMips64EL()))); } // Verify that the last byte in the string table in a null. -template -void ELFObjectFile::VerifyStrTab(const Elf_Shdr *sh) const { - const char *strtab = (const char*)base() + sh->sh_offset; +template +void ELFFile::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( - static_cast(ELFT::TargetEndianness) == support::little, - ELFT::Is64Bits), - Object) - , isDyldELFObject(false) - , SectionHeaderTable(0) - , dot_shstrtab_sec(0) - , dot_strtab_sec(0) - , dot_dynstr_sec(0) - , dot_dynamic_sec(0) - , dot_gnu_version_sec(0) - , dot_gnu_version_r_sec(0) - , dot_gnu_version_d_sec(0) - , dt_soname(0) - { +template +uint64_t ELFFile::getNumSections() const { + assert(Header && "Header not initialized!"); + if (Header->e_shnum == ELF::SHN_UNDEF) { + assert(SectionHeaderTable && "SectionHeaderTable not initialized!"); + return SectionHeaderTable->sh_size; + } + return Header->e_shnum; +} - const uint64_t FileSize = Data->getBufferSize(); +template +typename ELFFile::uintX_t ELFFile::getStringTableIndex() const { + if (Header->e_shnum == ELF::SHN_UNDEF) { + if (Header->e_shstrndx == ELF::SHN_HIRESERVE) + return SectionHeaderTable->sh_link; + if (Header->e_shstrndx >= getNumSections()) + return 0; + } + return Header->e_shstrndx; +} + +template +ELFFile::ELFFile(MemoryBuffer *Object, error_code &ec) + : Buf(Object), + SectionHeaderTable(0), + dot_shstrtab_sec(0), + dot_strtab_sec(0), + dot_symtab_sec(0), + SymbolTableSectionHeaderIndex(0), + dot_gnu_version_sec(0), + dot_gnu_version_r_sec(0), + dot_gnu_version_d_sec(0), + dt_soname(0) { + const uint64_t FileSize = Buf->getBufferSize(); if (sizeof(Elf_Ehdr) > FileSize) // FIXME: Proper error handling. @@ -2426,68 +639,64 @@ ELFObjectFile::ELFObjectFile(MemoryBuffer *Object, error_code &ec) // FIXME: Proper error handling. report_fatal_error("Section table goes past end of file!"); - // To find the symbol tables we walk the section table to find SHT_SYMTAB. - const Elf_Shdr* SymbolTableSectionHeaderIndex = 0; - const Elf_Shdr* sh = SectionHeaderTable; + // Scan sections for special sections. - SymbolTableIndex = -1; - DynamicSymbolTableIndex = -1; - - for (uint64_t i = 0, e = getNumSections(); i != e; ++i) { - switch (sh->sh_type) { - case ELF::SHT_SYMTAB_SHNDX: { + for (Elf_Shdr_Iter SecI = begin_sections(), SecE = end_sections(); + SecI != SecE; ++SecI) { + switch (SecI->sh_type) { + case ELF::SHT_SYMTAB_SHNDX: if (SymbolTableSectionHeaderIndex) // FIXME: Proper error handling. report_fatal_error("More than one .symtab_shndx!"); - SymbolTableSectionHeaderIndex = sh; + SymbolTableSectionHeaderIndex = &*SecI; break; - } - case ELF::SHT_SYMTAB: { - if (SymbolTableIndex != -1) - report_fatal_error("More than one SHT_SYMTAB!"); - SymbolTableIndex = i; - break; - } - case ELF::SHT_DYNSYM: { - if (DynamicSymbolTableIndex != -1) + case ELF::SHT_SYMTAB: + if (dot_symtab_sec) // FIXME: Proper error handling. - report_fatal_error("More than one SHT_DYNSYM!"); - DynamicSymbolTableIndex = i; + report_fatal_error("More than one .symtab!"); + dot_symtab_sec = &*SecI; + dot_strtab_sec = getSection(SecI->sh_link); + break; + case ELF::SHT_DYNSYM: { + if (DynSymRegion.Addr) + // FIXME: Proper error handling. + report_fatal_error("More than one .dynsym!"); + DynSymRegion.Addr = base() + SecI->sh_offset; + DynSymRegion.Size = SecI->sh_size; + DynSymRegion.EntSize = SecI->sh_entsize; + const Elf_Shdr *DynStr = getSection(SecI->sh_link); + DynStrRegion.Addr = base() + DynStr->sh_offset; + DynStrRegion.Size = DynStr->sh_size; + DynStrRegion.EntSize = DynStr->sh_entsize; break; } - case ELF::SHT_REL: - case ELF::SHT_RELA: - break; - case ELF::SHT_DYNAMIC: { - if (dot_dynamic_sec != NULL) + case ELF::SHT_DYNAMIC: + if (DynamicRegion.Addr) // FIXME: Proper error handling. report_fatal_error("More than one .dynamic!"); - dot_dynamic_sec = sh; + DynamicRegion.Addr = base() + SecI->sh_offset; + DynamicRegion.Size = SecI->sh_size; + DynamicRegion.EntSize = SecI->sh_entsize; break; - } - case ELF::SHT_GNU_versym: { + case ELF::SHT_GNU_versym: if (dot_gnu_version_sec != NULL) // FIXME: Proper error handling. report_fatal_error("More than one .gnu.version section!"); - dot_gnu_version_sec = sh; + dot_gnu_version_sec = &*SecI; break; - } - case ELF::SHT_GNU_verdef: { + case ELF::SHT_GNU_verdef: if (dot_gnu_version_d_sec != NULL) // FIXME: Proper error handling. report_fatal_error("More than one .gnu.version_d section!"); - dot_gnu_version_d_sec = sh; + dot_gnu_version_d_sec = &*SecI; break; - } - case ELF::SHT_GNU_verneed: { + case ELF::SHT_GNU_verneed: if (dot_gnu_version_r_sec != NULL) // FIXME: Proper error handling. report_fatal_error("More than one .gnu.version_r section!"); - dot_gnu_version_r_sec = sh; + dot_gnu_version_r_sec = &*SecI; break; } - } - ++sh; } // Get string table sections. @@ -2497,173 +706,117 @@ ELFObjectFile::ELFObjectFile(MemoryBuffer *Object, error_code &ec) VerifyStrTab(dot_shstrtab_sec); } - // Merge this into the above loop. - for (const char *i = reinterpret_cast(SectionHeaderTable), - *e = i + getNumSections() * Header->e_shentsize; - i != e; i += Header->e_shentsize) { - const Elf_Shdr *sh = reinterpret_cast(i); - if (sh->sh_type == ELF::SHT_STRTAB) { - StringRef SectionName(getString(dot_shstrtab_sec, sh->sh_name)); - if (SectionName == ".strtab") { - if (dot_strtab_sec != 0) - // FIXME: Proper error handling. - report_fatal_error("Already found section named .strtab!"); - dot_strtab_sec = sh; - VerifyStrTab(dot_strtab_sec); - } else if (SectionName == ".dynstr") { - if (dot_dynstr_sec != 0) - // FIXME: Proper error handling. - report_fatal_error("Already found section named .dynstr!"); - dot_dynstr_sec = sh; - VerifyStrTab(dot_dynstr_sec); - } - } - } - // Build symbol name side-mapping if there is one. if (SymbolTableSectionHeaderIndex) { const Elf_Word *ShndxTable = reinterpret_cast(base() + SymbolTableSectionHeaderIndex->sh_offset); - error_code ec; - for (symbol_iterator si = begin_symbols(), - se = end_symbols(); si != se; si.increment(ec)) { - if (ec) - report_fatal_error("Fewer extended symbol table entries than symbols!"); + for (Elf_Sym_Iter SI = begin_symbols(), SE = end_symbols(); SI != SE; + ++SI) { if (*ShndxTable != ELF::SHN_UNDEF) - ExtendedSymbolTable[getSymbol(si->getRawDataRefImpl())] = *ShndxTable; + ExtendedSymbolTable[&*SI] = *ShndxTable; ++ShndxTable; } } + + // Scan program headers. + for (Elf_Phdr_Iter PhdrI = begin_program_headers(), + PhdrE = end_program_headers(); + PhdrI != PhdrE; ++PhdrI) { + if (PhdrI->p_type == ELF::PT_DYNAMIC) { + DynamicRegion.Addr = base() + PhdrI->p_offset; + DynamicRegion.Size = PhdrI->p_filesz; + DynamicRegion.EntSize = sizeof(Elf_Dyn); + break; + } + } + + ec = error_code::success(); } // Get the symbol table index in the symtab section given a symbol -template -uint64_t ELFObjectFile::getSymbolIndex(const Elf_Sym *Sym) const { - const Elf_Shdr *SymTab = getSection(SymbolTableIndex); +template +uint64_t ELFFile::getSymbolIndex(const Elf_Sym *Sym) const { uintptr_t SymLoc = uintptr_t(Sym); - uintptr_t SymTabLoc = uintptr_t(base() + SymTab->sh_offset); + uintptr_t SymTabLoc = uintptr_t(base() + dot_symtab_sec->sh_offset); assert(SymLoc > SymTabLoc && "Symbol not in symbol table!"); uint64_t SymOffset = SymLoc - SymTabLoc; - assert(SymOffset % SymTab->sh_entsize == 0 && + assert(SymOffset % dot_symtab_sec->sh_entsize == 0 && "Symbol not multiple of symbol size!"); - return SymOffset / SymTab->sh_entsize; + return SymOffset / dot_symtab_sec->sh_entsize; } -template -symbol_iterator ELFObjectFile::begin_symbols() const { - DataRefImpl SymbolData; - if (SymbolTableIndex == -1) { - SymbolData.d.a = 0; - SymbolData.d.b = 0; - } else { - SymbolData.d.a = 0; - SymbolData.d.b = SymbolTableIndex; +template +typename ELFFile::Elf_Shdr_Iter ELFFile::begin_sections() const { + return Elf_Shdr_Iter(Header->e_shentsize, + (const char *)base() + Header->e_shoff); +} + +template +typename ELFFile::Elf_Shdr_Iter ELFFile::end_sections() const { + return Elf_Shdr_Iter(Header->e_shentsize, + (const char *)base() + Header->e_shoff + + (getNumSections() * Header->e_shentsize)); +} + +template +typename ELFFile::Elf_Sym_Iter ELFFile::begin_symbols() const { + if (!dot_symtab_sec) + return Elf_Sym_Iter(0, 0, false); + return Elf_Sym_Iter(dot_symtab_sec->sh_entsize, + (const char *)base() + dot_symtab_sec->sh_offset, false); +} + +template +typename ELFFile::Elf_Sym_Iter ELFFile::end_symbols() const { + if (!dot_symtab_sec) + return Elf_Sym_Iter(0, 0, false); + return Elf_Sym_Iter(dot_symtab_sec->sh_entsize, + (const char *)base() + dot_symtab_sec->sh_offset + + dot_symtab_sec->sh_size, + false); +} + +template +typename ELFFile::Elf_Dyn_Iter +ELFFile::begin_dynamic_table() const { + if (DynamicRegion.Addr) + return Elf_Dyn_Iter(DynamicRegion.EntSize, + (const char *)DynamicRegion.Addr); + return Elf_Dyn_Iter(0, 0); +} + +template +typename ELFFile::Elf_Dyn_Iter +ELFFile::end_dynamic_table(bool NULLEnd) const { + if (!DynamicRegion.Addr) + return Elf_Dyn_Iter(0, 0); + Elf_Dyn_Iter Ret(DynamicRegion.EntSize, + (const char *)DynamicRegion.Addr + DynamicRegion.Size); + + if (NULLEnd) { + Elf_Dyn_Iter Start = begin_dynamic_table(); + while (Start != Ret && Start->getTag() != ELF::DT_NULL) + ++Start; + + // Include the DT_NULL. + if (Start != Ret) + ++Start; + Ret = Start; } - return symbol_iterator(SymbolRef(SymbolData, this)); + return Ret; } -template -symbol_iterator ELFObjectFile::end_symbols() const { - DataRefImpl SymbolData; - 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 { - DataRefImpl SymbolData; - if (DynamicSymbolTableIndex == -1) { - SymbolData.d.a = 0; - SymbolData.d.b = 0; - } else { - SymbolData.d.a = 0; - SymbolData.d.b = DynamicSymbolTableIndex; - } - return symbol_iterator(SymbolRef(SymbolData, this)); -} - -template -symbol_iterator ELFObjectFile::end_dynamic_symbols() const { - DataRefImpl SymbolData; - 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 { - DataRefImpl ret; - ret.p = reinterpret_cast(base() + Header->e_shoff); - return section_iterator(SectionRef(ret, this)); -} - -template -section_iterator ELFObjectFile::end_sections() const { - DataRefImpl ret; - ret.p = reinterpret_cast(base() - + Header->e_shoff - + (Header->e_shentsize*getNumSections())); - return section_iterator(SectionRef(ret, this)); -} - -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; - } - return Elf_Dyn_iterator(0, 0); -} - -template -StringRef ELFObjectFile::getLoadName() const { +template +StringRef ELFFile::getLoadName() const { if (!dt_soname) { // Find the DT_SONAME entry - Elf_Dyn_iterator it = begin_dynamic_table(); - Elf_Dyn_iterator ie = end_dynamic_table(); + Elf_Dyn_Iter it = begin_dynamic_table(); + Elf_Dyn_Iter 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"); - dt_soname = getString(dot_dynstr_sec, it->getVal()); + dt_soname = getDynamicString(it->getVal()); } else { dt_soname = ""; } @@ -2671,210 +824,23 @@ StringRef ELFObjectFile::getLoadName() const { return dt_soname; } -template -library_iterator ELFObjectFile::begin_libraries_needed() const { - // Find the first DT_NEEDED entry - 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 { - // Use the same DataRefImpl format as DynRef. - 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 { - 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"); - - if (i->getTag() != ELF::DT_NEEDED) - report_fatal_error("Invalid library_iterator"); - - // This uses .dynstr to lookup the name of the DT_NEEDED entry. - // THis works as long as DT_STRTAB == .dynstr. This is true most of - // the time, but the specification allows exceptions. - // TODO: This should really use DT_STRTAB instead. Doing this requires - // reading the program headers. - if (dot_dynstr_sec == NULL) - report_fatal_error("Dynamic string table is missing"); - Res = getString(dot_dynstr_sec, i->getVal()); - return object_error::success; -} - -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 ELFT::Is64Bits ? 8 : 4; -} - -template -StringRef ELFObjectFile::getFileFormatName() const { - switch(Header->e_ident[ELF::EI_CLASS]) { - case ELF::ELFCLASS32: - switch(Header->e_machine) { - case ELF::EM_386: - return "ELF32-i386"; - case ELF::EM_X86_64: - return "ELF32-x86-64"; - case ELF::EM_ARM: - 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"; - } - case ELF::ELFCLASS64: - switch(Header->e_machine) { - case ELF::EM_386: - 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"; - } - default: - // FIXME: Proper error handling. - report_fatal_error("Invalid ELFCLASS!"); - } -} - -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 (ELFT::TargetEndianness == support::little) ? - Triple::mipsel : Triple::mips; - case ELF::EM_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 { - assert(Header && "Header not initialized!"); - if (Header->e_shnum == ELF::SHN_UNDEF) { - assert(SectionHeaderTable && "SectionHeaderTable not initialized!"); - return SectionHeaderTable->sh_size; - } - return Header->e_shnum; -} - -template -uint64_t -ELFObjectFile::getStringTableIndex() const { - if (Header->e_shnum == ELF::SHN_UNDEF) { - if (Header->e_shstrndx == ELF::SHN_HIRESERVE) - return SectionHeaderTable->sh_link; - if (Header->e_shstrndx >= getNumSections()) - return 0; - } - return Header->e_shstrndx; -} - -template -template -inline const T * -ELFObjectFile::getEntry(uint32_t Section, uint32_t Entry) const { +template +template +const T *ELFFile::getEntry(uint32_t Section, uint32_t Entry) const { return getEntry(getSection(Section), Entry); } -template -template -inline const T * -ELFObjectFile::getEntry(const Elf_Shdr * Section, uint32_t Entry) const { - return reinterpret_cast( - base() - + Section->sh_offset - + (Entry * Section->sh_entsize)); +template +template +const T *ELFFile::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(Symb.d.b, Symb.d.a); -} - -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.d.a, Rela.d.b); -} - -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. - report_fatal_error("Invalid symbol table section!"); - return sec; -} - -template -const typename ELFObjectFile::Elf_Shdr * -ELFObjectFile::getSection(uint32_t index) const { +template +const typename ELFFile::Elf_Shdr * +ELFFile::getSection(uint32_t index) const { if (index == 0) return 0; if (!SectionHeaderTable || index >= getNumSections()) @@ -2886,15 +852,15 @@ ELFObjectFile::getSection(uint32_t index) const { + (index * Header->e_shentsize)); } -template -const char *ELFObjectFile::getString(uint32_t section, - ELF::Elf32_Word offset) const { +template +const char *ELFFile::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 *ELFFile::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. @@ -2902,56 +868,63 @@ const char *ELFObjectFile::getString(const Elf_Shdr *section, return (const char *)base() + section->sh_offset + offset; } -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) - Result = ""; - else - Result = getString(dot_shstrtab_sec, section->sh_name); - return object_error::success; - } - - if (DynamicSymbolTableIndex != -1 && - section == getSection(DynamicSymbolTableIndex)) { - // Symbol is in .dynsym, use .dynstr string table - Result = getString(dot_dynstr_sec, symb->st_name); - } else { - // Use the default symbol table name section. - Result = getString(dot_strtab_sec, symb->st_name); - } - return object_error::success; +template +const char *ELFFile::getDynamicString(uintX_t Offset) const { + if (!DynStrRegion.Addr || Offset >= DynStrRegion.Size) + return 0; + return (const char *)DynStrRegion.Addr + Offset; } -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 +ErrorOr ELFFile::getSymbolName(Elf_Sym_Iter Sym) const { + if (!Sym.isDynamic()) + return getSymbolName(dot_symtab_sec, &*Sym); + + if (!DynStrRegion.Addr || Sym->st_name >= DynStrRegion.Size) + return object_error::parse_failed; + return StringRef(getDynamicString(Sym->st_name)); } -template -error_code ELFObjectFile::getSymbolVersion(const Elf_Shdr *section, - const Elf_Sym *symb, - StringRef &Version, - bool &IsDefault) const { +template +ErrorOr ELFFile::getSymbolName(const Elf_Shdr *Section, + const Elf_Sym *Symb) const { + if (Symb->st_name == 0) { + const Elf_Shdr *ContainingSec = getSection(Symb); + if (ContainingSec) + return getSectionName(ContainingSec); + } + + const Elf_Shdr *StrTab = getSection(Section->sh_link); + if (Symb->st_name >= StrTab->sh_size) + return object_error::parse_failed; + return StringRef(getString(StrTab, Symb->st_name)); +} + +template +ErrorOr +ELFFile::getSectionName(const Elf_Shdr *Section) const { + if (Section->sh_name >= dot_shstrtab_sec->sh_size) + return object_error::parse_failed; + return StringRef(getString(dot_shstrtab_sec, Section->sh_name)); +} + +template +ErrorOr ELFFile::getSymbolVersion(const Elf_Shdr *section, + const Elf_Sym *symb, + bool &IsDefault) const { // Handle non-dynamic symbols. - if (section != getSection(DynamicSymbolTableIndex)) { + if (section != DynSymRegion.Addr && section != 0) { // 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. - StringRef Name; - error_code ec = getSymbolName(section, symb, Name); - if (ec != object_error::success) - return ec; + ErrorOr SymName = getSymbolName(section, symb); + if (!SymName) + return SymName; + StringRef Name = *SymName; size_t atpos = Name.find('@'); if (atpos == StringRef::npos) { - Version = ""; IsDefault = false; - return object_error::success; + return StringRef(""); } ++atpos; if (atpos < Name.size() && Name[atpos] == '@') { @@ -2960,21 +933,19 @@ error_code ELFObjectFile::getSymbolVersion(const Elf_Shdr *section, } else { IsDefault = false; } - Version = Name.substr(atpos); - return object_error::success; + return Name.substr(atpos); } // This is a dynamic symbol. Look in the GNU symbol version table. if (dot_gnu_version_sec == NULL) { // No version table. - Version = ""; IsDefault = false; - return object_error::success; + return StringRef(""); } // Determine the position in the symbol table of this entry. - const char *sec_start = (const char*)base() + section->sh_offset; - size_t entry_index = ((const char*)symb - sec_start)/section->sh_entsize; + size_t entry_index = ((const char *)symb - (const char *)DynSymRegion.Addr) / + DynSymRegion.EntSize; // Get the corresponding version index entry const Elf_Versym *vs = getEntry(dot_gnu_version_sec, entry_index); @@ -2983,16 +954,14 @@ error_code ELFObjectFile::getSymbolVersion(const Elf_Shdr *section, // Special markers for unversioned symbols. if (version_index == ELF::VER_NDX_LOCAL || version_index == ELF::VER_NDX_GLOBAL) { - Version = ""; IsDefault = false; - return object_error::success; + return StringRef(""); } // Lookup this symbol in the version table LoadVersionMap(); if (version_index >= VersionMap.size() || VersionMap[version_index].isNull()) - report_fatal_error("Symbol has version index without corresponding " - "define or reference entry"); + return object_error::parse_failed; const VersionMapEntry &entry = VersionMap[version_index]; // Get the version name string @@ -3003,7 +972,6 @@ error_code ELFObjectFile::getSymbolVersion(const Elf_Shdr *section, } else { name_offset = entry.getVernaux()->vna_name; } - Version = getString(dot_dynstr_sec, name_offset); // Set IsDefault if (entry.isVerdef()) { @@ -3012,57 +980,9 @@ error_code ELFObjectFile::getSymbolVersion(const Elf_Shdr *section, IsDefault = false; } - return object_error::success; -} - -/// 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); - - // Big-endian 32-bit - if (const ELF32BEObjectFile *ELFObj = dyn_cast(Obj)) - return ELFObj->getRelocationAddend(DRI, Addend); - - // Little-endian 64-bit - if (const ELF64LEObjectFile *ELFObj = dyn_cast(Obj)) - return ELFObj->getRelocationAddend(DRI, Addend); - - // Big-endian 64-bit - if (const ELF64BEObjectFile *ELFObj = dyn_cast(Obj)) - return ELFObj->getRelocationAddend(DRI, Addend); - - llvm_unreachable("Object passed to getELFRelocationAddend() is not ELF"); -} - -/// This is a generic interface for retrieving GNU symbol version -/// information from an ELFObjectFile. -static inline error_code GetELFSymbolVersion(const ObjectFile *Obj, - const SymbolRef &Sym, - StringRef &Version, - bool &IsDefault) { - // Little-endian 32-bit - if (const ELF32LEObjectFile *ELFObj = dyn_cast(Obj)) - return ELFObj->getSymbolVersion(Sym, Version, IsDefault); - - // Big-endian 32-bit - if (const ELF32BEObjectFile *ELFObj = dyn_cast(Obj)) - return ELFObj->getSymbolVersion(Sym, Version, IsDefault); - - // Little-endian 64-bit - if (const ELF64LEObjectFile *ELFObj = dyn_cast(Obj)) - return ELFObj->getSymbolVersion(Sym, Version, IsDefault); - - // Big-endian 64-bit - if (const ELF64BEObjectFile *ELFObj = dyn_cast(Obj)) - return ELFObj->getSymbolVersion(Sym, Version, IsDefault); - - llvm_unreachable("Object passed to GetELFSymbolVersion() is not ELF"); + if (name_offset >= DynStrRegion.Size) + return object_error::parse_failed; + return StringRef(getDynamicString(name_offset)); } /// This function returns the hash value for a symbol in the .dynsym section @@ -3079,8 +999,7 @@ static inline unsigned elf_hash(StringRef &symbolName) { } return h; } - -} -} +} // end namespace object +} // end namespace llvm #endif diff --git a/llvm/include/llvm/Object/ELFObjectFile.h b/llvm/include/llvm/Object/ELFObjectFile.h new file mode 100644 index 000000000000..f0be8abb09fa --- /dev/null +++ b/llvm/include/llvm/Object/ELFObjectFile.h @@ -0,0 +1,1098 @@ +//===- ELFObjectFile.h - ELF object file implementation ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the ELFObjectFile template class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_ELF_OBJECT_FILE_H +#define LLVM_OBJECT_ELF_OBJECT_FILE_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/ADT/Triple.h" +#include "llvm/Object/ELF.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/ELF.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/raw_ostream.h" +#include +#include +#include + +namespace llvm { +namespace object { + +template +class ELFObjectFile : public ObjectFile { +public: + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) + + typedef typename ELFFile::uintX_t uintX_t; + + typedef typename ELFFile::Elf_Sym Elf_Sym; + typedef typename ELFFile::Elf_Shdr Elf_Shdr; + typedef typename ELFFile::Elf_Rel Elf_Rel; + typedef typename ELFFile::Elf_Rela Elf_Rela; + typedef typename ELFFile::Elf_Dyn Elf_Dyn; + + typedef typename ELFFile::Elf_Sym_Iter Elf_Sym_Iter; + typedef typename ELFFile::Elf_Shdr_Iter Elf_Shdr_Iter; + typedef typename ELFFile::Elf_Dyn_Iter Elf_Dyn_Iter; + +protected: + ELFFile EF; + + 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 getSymbolSection(DataRefImpl Symb, + section_iterator &Res) const; + virtual error_code getSymbolValue(DataRefImpl Symb, uint64_t &Val) const; + + virtual error_code getLibraryNext(DataRefImpl Data, LibraryRef &Result) const; + virtual error_code getLibraryPath(DataRefImpl Data, StringRef &Res) const; + + virtual error_code getSectionNext(DataRefImpl Sec, SectionRef &Res) const; + virtual error_code getSectionName(DataRefImpl Sec, StringRef &Res) const; + virtual error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const; + virtual error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const; + virtual error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const; + virtual error_code getSectionAlignment(DataRefImpl Sec, uint64_t &Res) const; + virtual error_code isSectionText(DataRefImpl Sec, bool &Res) const; + virtual error_code isSectionData(DataRefImpl Sec, bool &Res) const; + virtual error_code isSectionBSS(DataRefImpl Sec, bool &Res) const; + virtual error_code isSectionRequiredForExecution(DataRefImpl Sec, + bool &Res) const; + virtual error_code isSectionVirtual(DataRefImpl Sec, bool &Res) const; + virtual error_code isSectionZeroInit(DataRefImpl Sec, bool &Res) const; + virtual error_code isSectionReadOnlyData(DataRefImpl Sec, bool &Res) const; + virtual error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, + 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; + virtual error_code getRelocationAddress(DataRefImpl Rel, uint64_t &Res) const; + virtual error_code getRelocationOffset(DataRefImpl Rel, uint64_t &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 + getRelocationValueString(DataRefImpl Rel, + SmallVectorImpl &Result) const; + +protected: // ELF specific protected members. + const Elf_Sym *getSymbol(DataRefImpl Symb) const; + uint64_t getROffset(DataRefImpl Rel) const; + StringRef getRelocationTypeName(uint32_t Type) const; + + /// \brief Get the relocation section that contains \a Rel. + const Elf_Shdr *getRelSection(DataRefImpl Rel) const { + return EF.getSection(Rel.d.a); + } + + const Elf_Rel *getRel(DataRefImpl Rel) const; + const Elf_Rela *getRela(DataRefImpl Rela) const; + + Elf_Sym_Iter toELFSymIter(DataRefImpl Symb) const { + bool IsDynamic = Symb.p & 1; + if (IsDynamic) + return Elf_Sym_Iter( + EF.begin_dynamic_symbols().getEntSize(), + reinterpret_cast(Symb.p & ~uintptr_t(1)), IsDynamic); + return Elf_Sym_Iter(EF.begin_symbols().getEntSize(), + reinterpret_cast(Symb.p), IsDynamic); + } + + DataRefImpl toDRI(Elf_Sym_Iter Symb) const { + DataRefImpl DRI; + DRI.p = reinterpret_cast(Symb.get()) | Symb.isDynamic(); + return DRI; + } + + Elf_Shdr_Iter toELFShdrIter(DataRefImpl Sec) const { + return Elf_Shdr_Iter(EF.getHeader()->e_shentsize, + reinterpret_cast(Sec.p)); + } + + DataRefImpl toDRI(Elf_Shdr_Iter Sec) const { + DataRefImpl DRI; + DRI.p = reinterpret_cast(Sec.get()); + return DRI; + } + + DataRefImpl toDRI(const Elf_Shdr *Sec) const { + DataRefImpl DRI; + DRI.p = reinterpret_cast(Sec); + return DRI; + } + + Elf_Dyn_Iter toELFDynIter(DataRefImpl Dyn) const { + return Elf_Dyn_Iter(EF.begin_dynamic_table().getEntSize(), + reinterpret_cast(Dyn.p)); + } + + DataRefImpl toDRI(Elf_Dyn_Iter Dyn) const { + DataRefImpl DRI; + DRI.p = reinterpret_cast(Dyn.get()); + return DRI; + } + + // 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; + +public: + ELFObjectFile(MemoryBuffer *Object, error_code &ec); + + virtual symbol_iterator begin_symbols() const; + virtual symbol_iterator end_symbols() const; + + virtual symbol_iterator begin_dynamic_symbols() const; + virtual symbol_iterator end_dynamic_symbols() const; + + virtual section_iterator begin_sections() const; + virtual section_iterator end_sections() const; + + virtual library_iterator begin_libraries_needed() const; + virtual library_iterator end_libraries_needed() const; + + error_code getRelocationAddend(DataRefImpl Rel, int64_t &Res) const; + error_code getSymbolVersion(SymbolRef Symb, StringRef &Version, + bool &IsDefault) const; + + virtual uint8_t getBytesInAddress() const; + virtual StringRef getFileFormatName() const; + virtual StringRef getObjectType() const { return "ELF"; } + virtual unsigned getArch() const; + virtual StringRef getLoadName() const; + + const ELFFile *getELFFile() const { return &EF; } + + bool isDyldType() const { return isDyldELFObject; } + static inline bool classof(const Binary *v) { + 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; + +template +error_code ELFObjectFile::getSymbolNext(DataRefImpl Symb, + SymbolRef &Result) const { + Result = SymbolRef(toDRI(++toELFSymIter(Symb)), this); + return object_error::success; +} + +template +error_code ELFObjectFile::getSymbolName(DataRefImpl Symb, + StringRef &Result) const { + ErrorOr Name = EF.getSymbolName(toELFSymIter(Symb)); + if (!Name) + return Name; + Result = *Name; + return object_error::success; +} + +template +error_code ELFObjectFile::getSymbolVersion(SymbolRef SymRef, + StringRef &Version, + bool &IsDefault) const { + DataRefImpl Symb = SymRef.getRawDataRefImpl(); + const Elf_Sym *symb = getSymbol(Symb); + ErrorOr Ver = + EF.getSymbolVersion(EF.getSection(Symb.d.b), symb, IsDefault); + if (!Ver) + return Ver; + Version = *Ver; + return object_error::success; +} + +template +error_code ELFObjectFile::getSymbolFileOffset(DataRefImpl Symb, + uint64_t &Result) const { + const Elf_Sym *ESym = getSymbol(Symb); + const Elf_Shdr *ESec; + switch (EF.getSymbolTableIndex(ESym)) { + case ELF::SHN_COMMON: + // Unintialized symbols have no offset in the object file + case ELF::SHN_UNDEF: + Result = UnknownAddressOrSize; + return object_error::success; + case ELF::SHN_ABS: + Result = ESym->st_value; + return object_error::success; + default: + ESec = EF.getSection(ESym); + } + + switch (ESym->getType()) { + case ELF::STT_SECTION: + Result = ESec ? ESec->sh_offset : UnknownAddressOrSize; + return object_error::success; + case ELF::STT_FUNC: + case ELF::STT_OBJECT: + case ELF::STT_NOTYPE: + Result = ESym->st_value + (ESec ? ESec->sh_offset : 0); + return object_error::success; + default: + Result = UnknownAddressOrSize; + return object_error::success; + } +} + +template +error_code ELFObjectFile::getSymbolAddress(DataRefImpl Symb, + uint64_t &Result) const { + const Elf_Sym *ESym = getSymbol(Symb); + const Elf_Shdr *ESec; + switch (EF.getSymbolTableIndex(ESym)) { + case ELF::SHN_COMMON: + case ELF::SHN_UNDEF: + Result = UnknownAddressOrSize; + return object_error::success; + case ELF::SHN_ABS: + Result = ESym->st_value; + return object_error::success; + default: + ESec = EF.getSection(ESym); + } + + switch (ESym->getType()) { + case ELF::STT_SECTION: + Result = ESec ? ESec->sh_addr : UnknownAddressOrSize; + return object_error::success; + case ELF::STT_FUNC: + case ELF::STT_OBJECT: + case ELF::STT_NOTYPE: + bool IsRelocatable; + switch (EF.getHeader()->e_type) { + case ELF::ET_EXEC: + case ELF::ET_DYN: + IsRelocatable = false; + break; + default: + IsRelocatable = true; + } + Result = ESym->st_value; + + // Clear the ARM/Thumb indicator flag. + if (EF.getHeader()->e_machine == ELF::EM_ARM) + Result &= ~1; + + if (IsRelocatable && ESec != 0) + Result += ESec->sh_addr; + return object_error::success; + default: + Result = UnknownAddressOrSize; + return object_error::success; + } +} + +template +error_code ELFObjectFile::getSymbolAlignment(DataRefImpl Symb, + uint32_t &Res) const { + Elf_Sym_Iter Sym = toELFSymIter(Symb); + if (Sym->st_shndx == ELF::SHN_COMMON) + Res = Sym->st_value; + else + Res = 0; + return object_error::success; +} + +template +error_code ELFObjectFile::getSymbolSize(DataRefImpl Symb, + uint64_t &Result) const { + Result = toELFSymIter(Symb)->st_size; + return object_error::success; +} + +template +error_code ELFObjectFile::getSymbolNMTypeChar(DataRefImpl Symb, + char &Result) const { + const Elf_Sym *ESym = getSymbol(Symb); + const Elf_Shdr *ESec = EF.getSection(ESym); + + char ret = '?'; + + if (ESec) { + switch (ESec->sh_type) { + case ELF::SHT_PROGBITS: + case ELF::SHT_DYNAMIC: + switch (ESec->sh_flags) { + case (ELF::SHF_ALLOC | ELF::SHF_EXECINSTR): + ret = 't'; + break; + case (ELF::SHF_ALLOC | ELF::SHF_WRITE): + ret = 'd'; + break; + case ELF::SHF_ALLOC: + case (ELF::SHF_ALLOC | ELF::SHF_MERGE): + case (ELF::SHF_ALLOC | ELF::SHF_MERGE | ELF::SHF_STRINGS): + ret = 'r'; + break; + } + break; + case ELF::SHT_NOBITS: + ret = 'b'; + } + } + + switch (EF.getSymbolTableIndex(ESym)) { + case ELF::SHN_UNDEF: + if (ret == '?') + ret = 'U'; + break; + case ELF::SHN_ABS: + ret = 'a'; + break; + case ELF::SHN_COMMON: + ret = 'c'; + break; + } + + switch (ESym->getBinding()) { + case ELF::STB_GLOBAL: + ret = ::toupper(ret); + break; + case ELF::STB_WEAK: + if (EF.getSymbolTableIndex(ESym) == ELF::SHN_UNDEF) + ret = 'w'; + else if (ESym->getType() == ELF::STT_OBJECT) + ret = 'V'; + else + ret = 'W'; + } + + if (ret == '?' && ESym->getType() == ELF::STT_SECTION) { + ErrorOr Name = EF.getSymbolName(toELFSymIter(Symb)); + if (!Name) + return Name; + Result = StringSwitch(*Name) + .StartsWith(".debug", 'N') + .StartsWith(".note", 'n') + .Default('?'); + return object_error::success; + } + + Result = ret; + return object_error::success; +} + +template +error_code ELFObjectFile::getSymbolType(DataRefImpl Symb, + SymbolRef::Type &Result) const { + const Elf_Sym *ESym = getSymbol(Symb); + + switch (ESym->getType()) { + case ELF::STT_NOTYPE: + Result = SymbolRef::ST_Unknown; + break; + case ELF::STT_SECTION: + Result = SymbolRef::ST_Debug; + break; + case ELF::STT_FILE: + Result = SymbolRef::ST_File; + break; + case ELF::STT_FUNC: + Result = SymbolRef::ST_Function; + break; + case ELF::STT_OBJECT: + case ELF::STT_COMMON: + case ELF::STT_TLS: + Result = SymbolRef::ST_Data; + break; + default: + Result = SymbolRef::ST_Other; + break; + } + return object_error::success; +} + +template +error_code ELFObjectFile::getSymbolFlags(DataRefImpl Symb, + uint32_t &Result) const { + const Elf_Sym *ESym = getSymbol(Symb); + + Result = SymbolRef::SF_None; + + if (ESym->getBinding() != ELF::STB_LOCAL) + Result |= SymbolRef::SF_Global; + + if (ESym->getBinding() == ELF::STB_WEAK) + Result |= SymbolRef::SF_Weak; + + if (ESym->st_shndx == ELF::SHN_ABS) + Result |= SymbolRef::SF_Absolute; + + if (ESym->getType() == ELF::STT_FILE || ESym->getType() == ELF::STT_SECTION || + ESym == &*EF.begin_symbols()) + Result |= SymbolRef::SF_FormatSpecific; + + if (EF.getSymbolTableIndex(ESym) == ELF::SHN_UNDEF) + Result |= SymbolRef::SF_Undefined; + + if (ESym->getType() == ELF::STT_COMMON || + EF.getSymbolTableIndex(ESym) == ELF::SHN_COMMON) + Result |= SymbolRef::SF_Common; + + if (ESym->getType() == ELF::STT_TLS) + Result |= SymbolRef::SF_ThreadLocal; + + return object_error::success; +} + +template +error_code ELFObjectFile::getSymbolSection(DataRefImpl Symb, + section_iterator &Res) const { + const Elf_Sym *ESym = getSymbol(Symb); + const Elf_Shdr *ESec = EF.getSection(ESym); + if (!ESec) + Res = end_sections(); + else { + DataRefImpl Sec; + Sec.p = reinterpret_cast(ESec); + Res = section_iterator(SectionRef(Sec, this)); + } + return object_error::success; +} + +template +error_code ELFObjectFile::getSymbolValue(DataRefImpl Symb, + uint64_t &Val) const { + const Elf_Sym *ESym = getSymbol(Symb); + Val = ESym->st_value; + return object_error::success; +} + +template +error_code ELFObjectFile::getSectionNext(DataRefImpl Sec, + SectionRef &Result) const { + Result = SectionRef(toDRI(++toELFShdrIter(Sec)), this); + return object_error::success; +} + +template +error_code ELFObjectFile::getSectionName(DataRefImpl Sec, + StringRef &Result) const { + ErrorOr Name = EF.getSectionName(&*toELFShdrIter(Sec)); + if (!Name) + return Name; + Result = *Name; + return object_error::success; +} + +template +error_code ELFObjectFile::getSectionAddress(DataRefImpl Sec, + uint64_t &Result) const { + Result = toELFShdrIter(Sec)->sh_addr; + return object_error::success; +} + +template +error_code ELFObjectFile::getSectionSize(DataRefImpl Sec, + uint64_t &Result) const { + Result = toELFShdrIter(Sec)->sh_size; + return object_error::success; +} + +template +error_code ELFObjectFile::getSectionContents(DataRefImpl Sec, + StringRef &Result) const { + Elf_Shdr_Iter EShdr = toELFShdrIter(Sec); + Result = StringRef((const char *)base() + EShdr->sh_offset, EShdr->sh_size); + return object_error::success; +} + +template +error_code ELFObjectFile::getSectionAlignment(DataRefImpl Sec, + uint64_t &Result) const { + Result = toELFShdrIter(Sec)->sh_addralign; + return object_error::success; +} + +template +error_code ELFObjectFile::isSectionText(DataRefImpl Sec, + bool &Result) const { + Result = toELFShdrIter(Sec)->sh_flags & ELF::SHF_EXECINSTR; + return object_error::success; +} + +template +error_code ELFObjectFile::isSectionData(DataRefImpl Sec, + bool &Result) const { + Elf_Shdr_Iter EShdr = toELFShdrIter(Sec); + Result = EShdr->sh_flags & (ELF::SHF_ALLOC | ELF::SHF_WRITE) && + EShdr->sh_type == ELF::SHT_PROGBITS; + return object_error::success; +} + +template +error_code ELFObjectFile::isSectionBSS(DataRefImpl Sec, + bool &Result) const { + Elf_Shdr_Iter EShdr = toELFShdrIter(Sec); + Result = EShdr->sh_flags & (ELF::SHF_ALLOC | ELF::SHF_WRITE) && + EShdr->sh_type == ELF::SHT_NOBITS; + return object_error::success; +} + +template +error_code +ELFObjectFile::isSectionRequiredForExecution(DataRefImpl Sec, + bool &Result) const { + Result = toELFShdrIter(Sec)->sh_flags & ELF::SHF_ALLOC; + return object_error::success; +} + +template +error_code ELFObjectFile::isSectionVirtual(DataRefImpl Sec, + bool &Result) const { + Result = toELFShdrIter(Sec)->sh_type & ELF::SHT_NOBITS; + return object_error::success; +} + +template +error_code ELFObjectFile::isSectionZeroInit(DataRefImpl Sec, + bool &Result) const { + Result = toELFShdrIter(Sec)->sh_type & ELF::SHT_NOBITS; + return object_error::success; +} + +template +error_code ELFObjectFile::isSectionReadOnlyData(DataRefImpl Sec, + bool &Result) const { + Elf_Shdr_Iter EShdr = toELFShdrIter(Sec); + Result = !(EShdr->sh_flags & (ELF::SHF_WRITE | ELF::SHF_EXECINSTR)); + return object_error::success; +} + +template +error_code ELFObjectFile::sectionContainsSymbol(DataRefImpl Sec, + DataRefImpl Symb, + bool &Result) const { + Elf_Sym_Iter ESym = toELFSymIter(Symb); + + uintX_t Index = ESym->st_shndx; + bool Reserved = Index >= ELF::SHN_LORESERVE && Index <= ELF::SHN_HIRESERVE; + + Result = !Reserved && (&*toELFShdrIter(Sec) == EF.getSection(ESym->st_shndx)); + return object_error::success; +} + +template +relocation_iterator +ELFObjectFile::getSectionRelBegin(DataRefImpl Sec) const { + DataRefImpl RelData; + uintptr_t SHT = reinterpret_cast(EF.begin_sections().get()); + RelData.d.a = (Sec.p - SHT) / EF.getHeader()->e_shentsize; + RelData.d.b = 0; + return relocation_iterator(RelocationRef(RelData, this)); +} + +template +relocation_iterator +ELFObjectFile::getSectionRelEnd(DataRefImpl Sec) const { + DataRefImpl RelData; + uintptr_t SHT = reinterpret_cast(EF.begin_sections().get()); + const Elf_Shdr *S = reinterpret_cast(Sec.p); + RelData.d.a = (Sec.p - SHT) / EF.getHeader()->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 (EF.getHeader()->e_type != ELF::ET_REL) + return end_sections(); + + Elf_Shdr_Iter EShdr = toELFShdrIter(Sec); + uintX_t Type = EShdr->sh_type; + if (Type != ELF::SHT_REL && Type != ELF::SHT_RELA) + return end_sections(); + + const Elf_Shdr *R = EF.getSection(EShdr->sh_info); + return section_iterator(SectionRef(toDRI(R), this)); +} + +// Relocations +template +error_code ELFObjectFile::getRelocationNext(DataRefImpl Rel, + RelocationRef &Result) const { + ++Rel.d.b; + Result = RelocationRef(Rel, this); + return object_error::success; +} + +template +symbol_iterator +ELFObjectFile::getRelocationSymbol(DataRefImpl Rel) const { + uint32_t symbolIdx; + 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(EF.isMips64EL()); + break; + } + case ELF::SHT_RELA: { + symbolIdx = getRela(Rel)->getSymbol(EF.isMips64EL()); + break; + } + } + if (!symbolIdx) + return end_symbols(); + + const Elf_Shdr *SymSec = EF.getSection(sec->sh_link); + + DataRefImpl SymbolData; + switch (SymSec->sh_type) { + default: + report_fatal_error("Invalid symbol table section type!"); + case ELF::SHT_SYMTAB: + SymbolData = toDRI(EF.begin_symbols() + symbolIdx); + break; + case ELF::SHT_DYNSYM: + SymbolData = toDRI(EF.begin_dynamic_symbols() + symbolIdx); + break; + } + + return symbol_iterator(SymbolRef(SymbolData, this)); +} + +template +error_code ELFObjectFile::getRelocationAddress(DataRefImpl Rel, + uint64_t &Result) const { + Result = getROffset(Rel); + return object_error::success; +} + +template +error_code ELFObjectFile::getRelocationOffset(DataRefImpl Rel, + uint64_t &Result) const { + Result = getROffset(Rel); + return object_error::success; +} + +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: + return getRel(Rel)->r_offset; + case ELF::SHT_RELA: + return getRela(Rel)->r_offset; + } +} + +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(EF.isMips64EL()); + break; + } + case ELF::SHT_RELA: { + Result = getRela(Rel)->getType(EF.isMips64EL()); + break; + } + } + return object_error::success; +} + +template +StringRef ELFObjectFile::getRelocationTypeName(uint32_t Type) const { + return getELFRelocationTypeName(EF.getHeader()->e_machine, Type); +} + +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(EF.isMips64EL()); + break; + } + case ELF::SHT_RELA: { + type = getRela(Rel)->getType(EF.isMips64EL()); + break; + } + } + + EF.getRelocationTypeName(type, Result); + 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!"); + case ELF::SHT_REL: { + Result = 0; + return object_error::success; + } + case ELF::SHT_RELA: { + Result = getRela(Rel)->r_addend; + return object_error::success; + } + } +} + +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; + uint16_t symbol_index = 0; + switch (sec->sh_type) { + default: + return object_error::parse_failed; + case ELF::SHT_REL: { + type = getRel(Rel)->getType(EF.isMips64EL()); + symbol_index = getRel(Rel)->getSymbol(EF.isMips64EL()); + // TODO: Read implicit addend from section data. + break; + } + case ELF::SHT_RELA: { + type = getRela(Rel)->getType(EF.isMips64EL()); + symbol_index = getRela(Rel)->getSymbol(EF.isMips64EL()); + addend = getRela(Rel)->r_addend; + break; + } + } + const Elf_Sym *symb = + EF.template getEntry(sec->sh_link, symbol_index); + ErrorOr SymName = + EF.getSymbolName(EF.getSection(sec->sh_link), symb); + if (!SymName) + return SymName; + switch (EF.getHeader()->e_machine) { + case ELF::EM_X86_64: + switch (type) { + case ELF::R_X86_64_PC8: + case ELF::R_X86_64_PC16: + case ELF::R_X86_64_PC32: { + std::string fmtbuf; + raw_string_ostream fmt(fmtbuf); + fmt << *SymName << (addend < 0 ? "" : "+") << addend << "-P"; + fmt.flush(); + Result.append(fmtbuf.begin(), fmtbuf.end()); + } break; + case ELF::R_X86_64_8: + case ELF::R_X86_64_16: + case ELF::R_X86_64_32: + case ELF::R_X86_64_32S: + case ELF::R_X86_64_64: { + std::string fmtbuf; + raw_string_ostream fmt(fmtbuf); + fmt << *SymName << (addend < 0 ? "" : "+") << addend; + fmt.flush(); + Result.append(fmtbuf.begin(), fmtbuf.end()); + } break; + default: + 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; + break; + default: + res = "Unknown"; + } + if (Result.empty()) + Result.append(res.begin(), res.end()); + return object_error::success; +} + +template +const typename ELFFile::Elf_Sym * +ELFObjectFile::getSymbol(DataRefImpl Symb) const { + return &*toELFSymIter(Symb); +} + +template +const typename ELFObjectFile::Elf_Rel * +ELFObjectFile::getRel(DataRefImpl Rel) const { + return EF.template getEntry(Rel.d.a, Rel.d.b); +} + +template +const typename ELFObjectFile::Elf_Rela * +ELFObjectFile::getRela(DataRefImpl Rela) const { + return EF.template getEntry(Rela.d.a, Rela.d.b); +} + +template +ELFObjectFile::ELFObjectFile(MemoryBuffer *Object, error_code &ec) + : ObjectFile(getELFType(static_cast(ELFT::TargetEndianness) == + support::little, + ELFT::Is64Bits), + Object), + EF(Object, ec) {} + +template +symbol_iterator ELFObjectFile::begin_symbols() const { + return symbol_iterator(SymbolRef(toDRI(EF.begin_symbols()), this)); +} + +template +symbol_iterator ELFObjectFile::end_symbols() const { + return symbol_iterator(SymbolRef(toDRI(EF.end_symbols()), this)); +} + +template +symbol_iterator ELFObjectFile::begin_dynamic_symbols() const { + return symbol_iterator(SymbolRef(toDRI(EF.begin_dynamic_symbols()), this)); +} + +template +symbol_iterator ELFObjectFile::end_dynamic_symbols() const { + return symbol_iterator(SymbolRef(toDRI(EF.end_dynamic_symbols()), this)); +} + +template +section_iterator ELFObjectFile::begin_sections() const { + return section_iterator(SectionRef(toDRI(EF.begin_sections()), this)); +} + +template +section_iterator ELFObjectFile::end_sections() const { + return section_iterator(SectionRef(toDRI(EF.end_sections()), this)); +} + +template +StringRef ELFObjectFile::getLoadName() const { + Elf_Dyn_Iter DI = EF.begin_dynamic_table(); + Elf_Dyn_Iter DE = EF.end_dynamic_table(); + + while (DI != DE && DI->getTag() != ELF::DT_SONAME) + ++DI; + + if (DI != DE) + return EF.getDynamicString(DI->getVal()); + return ""; +} + +template +library_iterator ELFObjectFile::begin_libraries_needed() const { + Elf_Dyn_Iter DI = EF.begin_dynamic_table(); + Elf_Dyn_Iter DE = EF.end_dynamic_table(); + + while (DI != DE && DI->getTag() != ELF::DT_SONAME) + ++DI; + + return library_iterator(LibraryRef(toDRI(DI), this)); +} + +template +error_code ELFObjectFile::getLibraryNext(DataRefImpl Data, + LibraryRef &Result) const { + Elf_Dyn_Iter DI = toELFDynIter(Data); + Elf_Dyn_Iter DE = EF.end_dynamic_table(); + + // Skip to the next DT_NEEDED entry. + do + ++DI; + while (DI != DE && DI->getTag() != ELF::DT_NEEDED); + + Result = LibraryRef(toDRI(DI), this); + return object_error::success; +} + +template +error_code ELFObjectFile::getLibraryPath(DataRefImpl Data, + StringRef &Res) const { + Res = EF.getDynamicString(toELFDynIter(Data)->getVal()); + return object_error::success; +} + +template +library_iterator ELFObjectFile::end_libraries_needed() const { + return library_iterator(LibraryRef(toDRI(EF.end_dynamic_table()), this)); +} + +template +uint8_t ELFObjectFile::getBytesInAddress() const { + return ELFT::Is64Bits ? 8 : 4; +} + +template +StringRef ELFObjectFile::getFileFormatName() const { + switch (EF.getHeader()->e_ident[ELF::EI_CLASS]) { + case ELF::ELFCLASS32: + switch (EF.getHeader()->e_machine) { + case ELF::EM_386: + return "ELF32-i386"; + case ELF::EM_X86_64: + return "ELF32-x86-64"; + case ELF::EM_ARM: + 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"; + } + case ELF::ELFCLASS64: + switch (EF.getHeader()->e_machine) { + case ELF::EM_386: + 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"; + } + default: + // FIXME: Proper error handling. + report_fatal_error("Invalid ELFCLASS!"); + } +} + +template +unsigned ELFObjectFile::getArch() const { + switch (EF.getHeader()->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 (ELFT::TargetEndianness == support::little) ? Triple::mipsel + : Triple::mips; + case ELF::EM_PPC64: + return (ELFT::TargetEndianness == support::little) ? Triple::ppc64le + : Triple::ppc64; + case ELF::EM_S390: + return Triple::systemz; + default: + return Triple::UnknownArch; + } +} + +/// 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); + + // Big-endian 32-bit + if (const ELF32BEObjectFile *ELFObj = dyn_cast(Obj)) + return ELFObj->getRelocationAddend(DRI, Addend); + + // Little-endian 64-bit + if (const ELF64LEObjectFile *ELFObj = dyn_cast(Obj)) + return ELFObj->getRelocationAddend(DRI, Addend); + + // Big-endian 64-bit + if (const ELF64BEObjectFile *ELFObj = dyn_cast(Obj)) + return ELFObj->getRelocationAddend(DRI, Addend); + + llvm_unreachable("Object passed to getELFRelocationAddend() is not ELF"); +} + +/// This is a generic interface for retrieving GNU symbol version +/// information from an ELFObjectFile. +static inline error_code GetELFSymbolVersion(const ObjectFile *Obj, + const SymbolRef &Sym, + StringRef &Version, + bool &IsDefault) { + // Little-endian 32-bit + if (const ELF32LEObjectFile *ELFObj = dyn_cast(Obj)) + return ELFObj->getSymbolVersion(Sym, Version, IsDefault); + + // Big-endian 32-bit + if (const ELF32BEObjectFile *ELFObj = dyn_cast(Obj)) + return ELFObj->getSymbolVersion(Sym, Version, IsDefault); + + // Little-endian 64-bit + if (const ELF64LEObjectFile *ELFObj = dyn_cast(Obj)) + return ELFObj->getSymbolVersion(Sym, Version, IsDefault); + + // Big-endian 64-bit + if (const ELF64BEObjectFile *ELFObj = dyn_cast(Obj)) + return ELFObj->getSymbolVersion(Sym, Version, IsDefault); + + llvm_unreachable("Object passed to GetELFSymbolVersion() is not ELF"); +} +} +} + +#endif diff --git a/llvm/include/llvm/Object/ELFTypes.h b/llvm/include/llvm/Object/ELFTypes.h new file mode 100644 index 000000000000..84b603125a69 --- /dev/null +++ b/llvm/include/llvm/Object/ELFTypes.h @@ -0,0 +1,463 @@ +//===- ELFTypes.h - Endian specific types for ELF ---------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_ELF_TYPES_H +#define LLVM_OBJECT_ELF_TYPES_H + +#include "llvm/Support/AlignOf.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/ELF.h" +#include "llvm/Support/Endian.h" + +namespace llvm { +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 + : AlignOf::Alignment + }; +}; + +// Templates to choose Elf_Addr and Elf_Off depending on is64Bits. +template +struct ELFDataTypeTypedefHelperCommon { + typedef support::detail::packed_endian_specific_integral< + uint16_t, target_endianness, + MaximumAlignment::value> Elf_Half; + typedef support::detail::packed_endian_specific_integral< + uint32_t, target_endianness, + MaximumAlignment::value> Elf_Word; + typedef support::detail::packed_endian_specific_integral< + int32_t, target_endianness, + MaximumAlignment::value> Elf_Sword; + typedef support::detail::packed_endian_specific_integral< + uint64_t, target_endianness, + MaximumAlignment::value> Elf_Xword; + typedef support::detail::packed_endian_specific_integral< + int64_t, target_endianness, + MaximumAlignment::value> Elf_Sxword; +}; + +template struct ELFDataTypeTypedefHelper; + +/// ELF 32bit types. +template +struct ELFDataTypeTypedefHelper > + : ELFDataTypeTypedefHelperCommon { + typedef uint32_t value_type; + typedef support::detail::packed_endian_specific_integral< + value_type, TargetEndianness, + MaximumAlignment::value> Elf_Addr; + typedef support::detail::packed_endian_specific_integral< + value_type, TargetEndianness, + MaximumAlignment::value> Elf_Off; +}; + +/// ELF 64bit types. +template +struct ELFDataTypeTypedefHelper > + : ELFDataTypeTypedefHelperCommon { + typedef uint64_t value_type; + typedef support::detail::packed_endian_specific_integral< + value_type, TargetEndianness, + MaximumAlignment::value> Elf_Addr; + typedef support::detail::packed_endian_specific_integral< + value_type, TargetEndianness, + MaximumAlignment::value> Elf_Off; +}; + +// I really don't like doing this, but the alternative is copypasta. +#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(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_*) + Elf_Addr sh_addr; // Address where section is to be loaded + Elf_Off sh_offset; // File offset of section data, in bytes + Elf_Word sh_size; // Size of section, in bytes + Elf_Word sh_link; // Section type-specific header table index link + Elf_Word sh_info; // Section type-specific extra information + Elf_Word sh_addralign; // Section address alignment + Elf_Word sh_entsize; // Size of records contained within the section +}; + +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_*) + Elf_Addr sh_addr; // Address where section is to be loaded + Elf_Off sh_offset; // File offset of section data, in bytes + Elf_Xword sh_size; // Size of section, in bytes + Elf_Word sh_link; // Section type-specific header table index link + Elf_Word sh_info; // Section type-specific extra information + Elf_Xword sh_addralign; // Section address alignment + 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; + + /// @brief Get the number of entities this section contains if it has any. + unsigned getEntityCount() const { + if (sh_entsize == 0) + return 0; + return sh_size / sh_entsize; + } +}; + +template struct Elf_Sym_Base; + +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 + unsigned char st_info; // Symbol's type and binding attributes + unsigned char st_other; // Must be zero; reserved + Elf_Half st_shndx; // Which section (header table index) it's defined in +}; + +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 + Elf_Half st_shndx; // Which section (header table index) it's defined in + Elf_Addr st_value; // Value or address associated with the symbol + Elf_Xword st_size; // Size of the symbol +}; + +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: + unsigned char getBinding() const { return st_info >> 4; } + unsigned char getType() const { return st_info & 0x0f; } + void setBinding(unsigned char b) { setBindingAndType(b, getType()); } + void setType(unsigned char t) { setBindingAndType(getBinding(), t); } + void setBindingAndType(unsigned char b, unsigned char t) { + st_info = (b << 4) + (t & 0x0f); + } +}; + +/// 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 +struct Elf_Versym_Impl { + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) + Elf_Half vs_index; // Version index with flags (e.g. VERSYM_HIDDEN) +}; + +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 +struct Elf_Verdef_Impl { + 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 + Elf_Half vd_cnt; // Number of Verdaux entries + Elf_Word vd_hash; // Hash of name + Elf_Word vd_aux; // Offset to the first Verdaux entry (in bytes) + Elf_Word vd_next; // Offset to the next Verdef entry (in bytes) + + /// Get the first Verdaux entry for this Verdef. + const Elf_Verdaux *getAux() const { + return reinterpret_cast((const char *)this + vd_aux); + } +}; + +/// 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 +struct Elf_Verdaux_Impl { + 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 +struct Elf_Verneed_Impl { + 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) + Elf_Word vn_aux; // Offset to first Vernaux entry (in bytes) + Elf_Word vn_next; // Offset to next Verneed entry (in bytes) +}; + +/// 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 +struct Elf_Vernaux_Impl { + 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 + Elf_Word vna_name; // Dependency name + Elf_Word vna_next; // Offset to next Vernaux entry (in bytes) +}; + +/// Elf_Dyn_Base: This structure matches the form of entries in the dynamic +/// table section (.dynamic) look like. +template struct Elf_Dyn_Base; + +template +struct Elf_Dyn_Base > { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) + Elf_Sword d_tag; + union { + Elf_Word d_val; + Elf_Addr d_ptr; + } d_un; +}; + +template +struct Elf_Dyn_Base > { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) + Elf_Sxword d_tag; + union { + Elf_Xword d_val; + Elf_Addr d_ptr; + } d_un; +}; + +/// 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; + int64_t getTag() const { return d_tag; } + uint64_t getVal() const { return d_un.d_val; } + uint64_t getPtr() const { return d_un.ptr; } +}; + +// Elf_Rel: Elf Relocation +template struct Elf_Rel_Base; + +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, 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, 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, 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 struct Elf_Rel_Impl; + +template +struct Elf_Rel_Impl, + isRela> : Elf_Rel_Base< + ELFType, 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: + uint32_t getSymbol(bool isMips64EL) const { + return (uint32_t)(this->getRInfo(isMips64EL) >> 32); + } + 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, + isRela> : Elf_Rel_Base< + ELFType, 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(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) { + this->setRInfo((s << 8) + t); + } +}; + +template +struct Elf_Ehdr_Impl { + 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_*) + Elf_Word e_version; // Must be equal to 1 + Elf_Addr e_entry; // Address to jump to in order to start program + Elf_Off e_phoff; // Program header table's file offset, in bytes + Elf_Off e_shoff; // Section header table's file offset, in bytes + Elf_Word e_flags; // Processor-specific flags + Elf_Half e_ehsize; // Size of ELF header, in bytes + Elf_Half e_phentsize; // Size of an entry in the program header table + Elf_Half e_phnum; // Number of entries in the program header table + Elf_Half e_shentsize; // Size of an entry in the section header table + Elf_Half e_shnum; // Number of entries in the section header table + Elf_Half e_shstrndx; // Section header table index of section name + // string table + bool checkMagic() const { + return (memcmp(e_ident, ELF::ElfMagic, strlen(ELF::ElfMagic))) == 0; + } + unsigned char getFileClass() const { return e_ident[ELF::EI_CLASS]; } + unsigned char getDataEncoding() const { return e_ident[ELF::EI_DATA]; } +}; + +template struct Elf_Phdr_Impl; + +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 + Elf_Addr p_paddr; // Physical address of beginning of segment (OS-specific) + Elf_Word p_filesz; // Num. of bytes in file image of segment (may be zero) + Elf_Word p_memsz; // Num. of bytes in mem image of segment (may be zero) + Elf_Word p_flags; // Segment flags + Elf_Word p_align; // Segment alignment constraint +}; + +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 + Elf_Addr p_vaddr; // Virtual Address of beginning of segment + Elf_Addr p_paddr; // Physical address of beginning of segment (OS-specific) + Elf_Xword p_filesz; // Num. of bytes in file image of segment (may be zero) + Elf_Xword p_memsz; // Num. of bytes in mem image of segment (may be zero) + Elf_Xword p_align; // Segment alignment constraint +}; + +} // end namespace object. +} // end namespace llvm. + +#endif diff --git a/llvm/include/llvm/Object/RelocVisitor.h b/llvm/include/llvm/Object/RelocVisitor.h index b1eb4e641c77..97912fe52d81 100644 --- a/llvm/include/llvm/Object/RelocVisitor.h +++ b/llvm/include/llvm/Object/RelocVisitor.h @@ -18,7 +18,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Object/ObjectFile.h" -#include "llvm/Object/ELF.h" +#include "llvm/Object/ELFObjectFile.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ELF.h" #include "llvm/Support/raw_ostream.h" diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp index cd99c3c0f3bb..501959e10d0c 100644 --- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp +++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp @@ -22,7 +22,7 @@ #include "llvm/ADT/Triple.h" #include "llvm/ExecutionEngine/ObjectBuffer.h" #include "llvm/ExecutionEngine/ObjectImage.h" -#include "llvm/Object/ELF.h" +#include "llvm/Object/ELFObjectFile.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/ELF.h" using namespace llvm; @@ -304,7 +304,7 @@ void RuntimeDyldELF::resolveAArch64Relocation(const SectionEntry &Section, } case ELF::R_AARCH64_PREL32: { uint64_t Result = Value + Addend - FinalAddress; - assert(static_cast(Result) >= INT32_MIN && + assert(static_cast(Result) >= INT32_MIN && static_cast(Result) <= UINT32_MAX); *TargetPtr = static_cast(Result & 0xffffffffU); break; @@ -316,7 +316,7 @@ void RuntimeDyldELF::resolveAArch64Relocation(const SectionEntry &Section, uint64_t BranchImm = Value + Addend - FinalAddress; // "Check that -2^27 <= result < 2^27". - assert(-(1LL << 27) <= static_cast(BranchImm) && + assert(-(1LL << 27) <= static_cast(BranchImm) && static_cast(BranchImm) < (1LL << 27)); // AArch64 code is emitted with .rela relocations. The data already in any @@ -341,7 +341,6 @@ void RuntimeDyldELF::resolveAArch64Relocation(const SectionEntry &Section, case ELF::R_AARCH64_MOVW_UABS_G2_NC: { uint64_t Result = Value + Addend; - // AArch64 code is emitted with .rela relocations. The data already in any // bits affected by the relocation on entry is garbage. *TargetPtr &= 0xffe0001fU; diff --git a/llvm/lib/MC/MCObjectSymbolizer.cpp b/llvm/lib/MC/MCObjectSymbolizer.cpp index aa7648e879df..740e8b367290 100644 --- a/llvm/lib/MC/MCObjectSymbolizer.cpp +++ b/llvm/lib/MC/MCObjectSymbolizer.cpp @@ -15,7 +15,7 @@ #include "llvm/MC/MCRelocationInfo.h" #include "llvm/MC/MCSymbol.h" #include "llvm/Object/MachO.h" -#include "llvm/Object/ELF.h" +#include "llvm/Object/ELFObjectFile.h" #include "llvm/Support/raw_ostream.h" #include @@ -96,7 +96,7 @@ MCObjectSymbolizer::MCObjectSymbolizer(MCContext &Ctx, const ELF64LEObjectFile *ELFObj = dyn_cast(Obj); if (ELFObj == 0) break; - if (ELFObj->getElfHeader()->e_type == ELF::ET_REL) { + if (ELFObj->getELFFile()->getHeader()->e_type == ELF::ET_REL) { RI->getOffset(Offset); Offset += StartAddr; } else { diff --git a/llvm/lib/Object/CMakeLists.txt b/llvm/lib/Object/CMakeLists.txt index 2c2cc8e4fb6f..1f07cbba77db 100644 --- a/llvm/lib/Object/CMakeLists.txt +++ b/llvm/lib/Object/CMakeLists.txt @@ -3,6 +3,7 @@ add_llvm_library(LLVMObject Binary.cpp COFFObjectFile.cpp COFFYAML.cpp + ELF.cpp ELFObjectFile.cpp ELFYAML.cpp Error.cpp diff --git a/llvm/lib/Object/ELF.cpp b/llvm/lib/Object/ELF.cpp new file mode 100644 index 000000000000..d9b4462585c0 --- /dev/null +++ b/llvm/lib/Object/ELF.cpp @@ -0,0 +1,623 @@ +//===- ELF.cpp - ELF object file implementation -----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Object/ELF.h" + +namespace llvm { +namespace object { + +#define LLVM_ELF_SWITCH_RELOC_TYPE_NAME(enum) \ + case ELF::enum: \ + return #enum; \ + +StringRef getELFRelocationTypeName(uint32_t Machine, uint32_t Type) { + switch (Machine) { + case ELF::EM_X86_64: + 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); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOT32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_PLT32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_COPY); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GLOB_DAT); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_JUMP_SLOT); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_RELATIVE); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTPCREL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_32S); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_PC16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_8); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_PC8); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_DTPMOD64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_DTPOFF64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_TPOFF64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_TLSGD); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_TLSLD); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_DTPOFF32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTTPOFF); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_TPOFF32); + 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); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_IRELATIVE); + default: + break; + } + break; + case ELF::EM_386: + 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); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_GOT32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_PLT32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_COPY); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_GLOB_DAT); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_JUMP_SLOT); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_RELATIVE); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_GOTOFF); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_GOTPC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_32PLT); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_TPOFF); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_IE); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_GOTIE); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LE); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_GD); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LDM); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_PC16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_8); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_PC8); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_GD_32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_GD_PUSH); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_GD_CALL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_GD_POP); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LDM_32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LDM_PUSH); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LDM_CALL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LDM_POP); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LDO_32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_IE_32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LE_32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_DTPMOD32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_DTPOFF32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_TPOFF32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_GOTDESC); + 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: + 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_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) { + 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); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_REL32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDR_PC_G0); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ABS16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ABS12); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_ABS5); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ABS8); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_SBREL32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_CALL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_PC8); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_BREL_ADJ); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_DESC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_SWI8); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_XPC25); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_XPC22); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_DTPMOD32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_DTPOFF32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_TPOFF32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_COPY); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_GLOB_DAT); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_JUMP_SLOT); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_RELATIVE); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_GOTOFF32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_BASE_PREL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_GOT_BREL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PLT32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_CALL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_JUMP24); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_JUMP24); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_BASE_ABS); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_PCREL_7_0); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_PCREL_15_8); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_PCREL_23_15); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDR_SBREL_11_0_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_SBREL_19_12_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_SBREL_27_20_CK); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TARGET1); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_SBREL31); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_V4BX); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TARGET2); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PREL31); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_MOVW_ABS_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_MOVT_ABS); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_MOVW_PREL_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_MOVT_PREL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_MOVW_ABS_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_MOVT_ABS); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_MOVW_PREL_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_MOVT_PREL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_JUMP19); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_JUMP6); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_ALU_PREL_11_0); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_PC12); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ABS32_NOI); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_REL32_NOI); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_PC_G0_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_PC_G0); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_PC_G1_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_PC_G1); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_PC_G2); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDR_PC_G1); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDR_PC_G2); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDRS_PC_G0); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDRS_PC_G1); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDRS_PC_G2); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDC_PC_G0); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDC_PC_G1); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDC_PC_G2); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_SB_G0_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_SB_G0); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_SB_G1_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_SB_G1); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_SB_G2); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDR_SB_G0); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDR_SB_G1); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDR_SB_G2); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDRS_SB_G0); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDRS_SB_G1); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDRS_SB_G2); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDC_SB_G0); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDC_SB_G1); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDC_SB_G2); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_MOVW_BREL_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_MOVT_BREL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_MOVW_BREL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_MOVW_BREL_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_MOVT_BREL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_MOVW_BREL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_GOTDESC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_CALL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_DESCSEQ); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_TLS_CALL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PLT32_ABS); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_GOT_ABS); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_GOT_PREL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_GOT_BREL12); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_GOTOFF12); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_GOTRELAX); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_GNU_VTENTRY); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_GNU_VTINHERIT); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_JUMP11); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_JUMP8); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_GD32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_LDM32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_LDO32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_IE32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_LE32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_LDO12); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_LE12); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_IE12GP); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_0); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_1); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_2); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_3); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_4); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_5); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_6); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_7); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_8); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_9); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_10); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_11); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_12); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_13); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_14); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_15); + 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: + break; + } + break; + case ELF::EM_HEXAGON: + 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); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B7_PCREL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_LO16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_HI16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_8); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GPREL16_0); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GPREL16_1); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GPREL16_2); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GPREL16_3); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_HL16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B13_PCREL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B9_PCREL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B32_PCREL_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_32_6_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B22_PCREL_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B15_PCREL_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B13_PCREL_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B9_PCREL_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B7_PCREL_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_16_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_12_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_11_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_10_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_9_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_8_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_7_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_6_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_32_PCREL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_COPY); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GLOB_DAT); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_JMP_SLOT); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_RELATIVE); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_PLT_B22_PCREL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOTREL_LO16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOTREL_HI16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOTREL_32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOT_LO16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOT_HI16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOT_32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOT_16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_DTPMOD_32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_DTPREL_LO16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_DTPREL_HI16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_DTPREL_32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_DTPREL_16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GD_PLT_B22_PCREL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GD_GOT_LO16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GD_GOT_HI16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GD_GOT_32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GD_GOT_16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_LO16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_HI16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_GOT_LO16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_GOT_HI16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_GOT_32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_GOT_16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_TPREL_LO16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_TPREL_HI16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_TPREL_32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_TPREL_16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_6_PCREL_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOTREL_32_6_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOTREL_16_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOTREL_11_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOT_32_6_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOT_16_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOT_11_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_DTPREL_32_6_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_DTPREL_16_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_DTPREL_11_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GD_GOT_32_6_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GD_GOT_16_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GD_GOT_11_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_32_6_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_16_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_GOT_32_6_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_GOT_16_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_GOT_11_X); + 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: + break; + } + break; + 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_REL32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_TPREL16_LO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_TPREL16_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_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_HIGHEST); + 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_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_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_TPREL16_LO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TPREL16_HA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_DTPREL16_LO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_DTPREL16_HA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TLSGD16_LO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TLSGD16_HA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TLSLD16_LO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TLSLD16_HA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TPREL16_LO_DS); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TPREL16_HA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TLSGD); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TLSLD); + 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; + } + return "Unknown"; +} + +#undef LLVM_ELF_SWITCH_RELOC_TYPE_NAME + +} // end namespace object +} // end namespace llvm diff --git a/llvm/lib/Object/ELFObjectFile.cpp b/llvm/lib/Object/ELFObjectFile.cpp index 85057fce167d..15bc6be0b46e 100644 --- a/llvm/lib/Object/ELFObjectFile.cpp +++ b/llvm/lib/Object/ELFObjectFile.cpp @@ -11,11 +11,10 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Object/ELF.h" +#include "llvm/Object/ELFObjectFile.h" #include "llvm/Support/MathExtras.h" namespace llvm { - using namespace object; // Creates an in-memory object-file by default: createELFObjectFile(Buffer) diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86ELFRelocationInfo.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86ELFRelocationInfo.cpp index 8f4ab4673d57..a3eb4fbe4936 100644 --- a/llvm/lib/Target/X86/MCTargetDesc/X86ELFRelocationInfo.cpp +++ b/llvm/lib/Target/X86/MCTargetDesc/X86ELFRelocationInfo.cpp @@ -13,7 +13,7 @@ #include "llvm/MC/MCInst.h" #include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCRelocationInfo.h" -#include "llvm/Object/ELF.h" +#include "llvm/Object/ELFObjectFile.h" #include "llvm/Support/ELF.h" using namespace llvm; diff --git a/llvm/test/Object/Inputs/corrupt-version.elf-x86_64 b/llvm/test/Object/Inputs/corrupt-version.elf-x86_64 new file mode 100644 index 000000000000..1241a27a7bb6 Binary files /dev/null and b/llvm/test/Object/Inputs/corrupt-version.elf-x86_64 differ diff --git a/llvm/test/Object/Inputs/corrupt.elf-x86-64 b/llvm/test/Object/Inputs/corrupt.elf-x86-64 new file mode 100644 index 000000000000..8ae5f1759746 Binary files /dev/null and b/llvm/test/Object/Inputs/corrupt.elf-x86-64 differ diff --git a/llvm/test/Object/corrupt.test b/llvm/test/Object/corrupt.test new file mode 100644 index 000000000000..ef72a0979b52 --- /dev/null +++ b/llvm/test/Object/corrupt.test @@ -0,0 +1,24 @@ +// Section name offset overflows section name string table. +RUN: not llvm-readobj %p/Inputs/corrupt.elf-x86-64 -sections \ +RUN: 2>&1 | FileCheck --check-prefix=SECNAME %s + +// Section data offset past end of file. +RUN: not llvm-readobj %p/Inputs/corrupt.elf-x86-64 -sections -section-data \ +RUN: 2>&1 | FileCheck --check-prefix=SECDATA %s + +// Symbol name offset overflows string table. +RUN: not llvm-readobj %p/Inputs/corrupt.elf-x86-64 -symbols \ +RUN: 2>&1 | FileCheck --check-prefix=SYMNAME %s + +// Version index in .gnu.version overflows the version map. +RUN: not llvm-readobj %p/Inputs/corrupt-version.elf-x86_64 -dt \ +RUN: 2>&1 | FileCheck --check-prefix=VER %s + +SECNAME: Error reading file: Invalid data was encountered while parsing the file. + +SECDATA: Error reading file: Invalid data was encountered while parsing the file. +SECDATA: Error reading file: Invalid data was encountered while parsing the file. + +SYMNAME: Error reading file: Invalid data was encountered while parsing the file. + +VER: Error reading file: Invalid data was encountered while parsing the file. diff --git a/llvm/tools/llvm-objdump/ELFDump.cpp b/llvm/tools/llvm-objdump/ELFDump.cpp index ef1f0e9ce357..9c091a410d8f 100644 --- a/llvm/tools/llvm-objdump/ELFDump.cpp +++ b/llvm/tools/llvm-objdump/ELFDump.cpp @@ -13,7 +13,7 @@ //===----------------------------------------------------------------------===// #include "llvm-objdump.h" -#include "llvm/Object/ELF.h" +#include "llvm/Object/ELFObjectFile.h" #include "llvm/Support/Format.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" @@ -21,10 +21,8 @@ using namespace llvm; using namespace llvm::object; -template -void printProgramHeaders( - const ELFObjectFile *o) { - typedef ELFObjectFile ELFO; +template void printProgramHeaders(const ELFFile *o) { + typedef ELFFile ELFO; outs() << "Program Header:\n"; for (typename ELFO::Elf_Phdr_Iter pi = o->begin_program_headers(), pe = o->end_program_headers(); @@ -80,17 +78,17 @@ void printProgramHeaders( void llvm::printELFFileHeader(const object::ObjectFile *Obj) { // Little-endian 32-bit if (const ELF32LEObjectFile *ELFObj = dyn_cast(Obj)) - printProgramHeaders(ELFObj); + printProgramHeaders(ELFObj->getELFFile()); // Big-endian 32-bit if (const ELF32BEObjectFile *ELFObj = dyn_cast(Obj)) - printProgramHeaders(ELFObj); + printProgramHeaders(ELFObj->getELFFile()); // Little-endian 64-bit if (const ELF64LEObjectFile *ELFObj = dyn_cast(Obj)) - printProgramHeaders(ELFObj); + printProgramHeaders(ELFObj->getELFFile()); // Big-endian 64-bit if (const ELF64BEObjectFile *ELFObj = dyn_cast(Obj)) - printProgramHeaders(ELFObj); + printProgramHeaders(ELFObj->getELFFile()); } diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp index 3628c3b63023..e909ef81bb96 100644 --- a/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -18,7 +18,7 @@ #include "StreamWriter.h" #include "llvm/ADT/SmallString.h" -#include "llvm/Object/ELF.h" +#include "llvm/Object/ELFObjectFile.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/Format.h" #include "llvm/Support/MathExtras.h" @@ -28,7 +28,6 @@ using namespace llvm; using namespace llvm::object; using namespace ELF; - #define LLVM_READOBJ_ENUM_CASE(ns, enum) \ case ns::enum: return #enum; @@ -37,9 +36,8 @@ namespace { template class ELFDumper : public ObjDumper { public: - ELFDumper(const ELFObjectFile *Obj, StreamWriter& Writer) - : ObjDumper(Writer) - , Obj(Obj) { } + ELFDumper(const ELFFile *Obj, StreamWriter &Writer) + : ObjDumper(Writer), Obj(Obj) {} virtual void printFileHeaders() LLVM_OVERRIDE; virtual void printSections() LLVM_OVERRIDE; @@ -53,24 +51,32 @@ public: virtual void printProgramHeaders() LLVM_OVERRIDE; private: - typedef ELFObjectFile ELFO; + typedef ELFFile ELFO; typedef typename ELFO::Elf_Shdr Elf_Shdr; typedef typename ELFO::Elf_Sym Elf_Sym; - void printSymbol(symbol_iterator SymI, bool IsDynamic = false); + void printSymbol(typename ELFO::Elf_Sym_Iter Symbol); - void printRelocation(section_iterator SecI, relocation_iterator RelI); + void printRelocations(const Elf_Shdr *Sec); + void printRelocation(const Elf_Shdr *Sec, typename ELFO::Elf_Rela Rel); const ELFO *Obj; }; -} // namespace +template T errorOrDefault(ErrorOr Val, T Default = T()) { + if (!Val) { + error(Val); + return Default; + } + return *Val; +} +} // namespace namespace llvm { template -static error_code createELFDumper(const ELFObjectFile *Obj, +static error_code createELFDumper(const ELFFile *Obj, StreamWriter &Writer, OwningPtr &Result) { Result.reset(new ELFDumper(Obj, Writer)); @@ -82,26 +88,25 @@ error_code createELFDumper(const object::ObjectFile *Obj, OwningPtr &Result) { // Little-endian 32-bit if (const ELF32LEObjectFile *ELFObj = dyn_cast(Obj)) - return createELFDumper(ELFObj, Writer, Result); + return createELFDumper(ELFObj->getELFFile(), Writer, Result); // Big-endian 32-bit if (const ELF32BEObjectFile *ELFObj = dyn_cast(Obj)) - return createELFDumper(ELFObj, Writer, Result); + return createELFDumper(ELFObj->getELFFile(), Writer, Result); // Little-endian 64-bit if (const ELF64LEObjectFile *ELFObj = dyn_cast(Obj)) - return createELFDumper(ELFObj, Writer, Result); + return createELFDumper(ELFObj->getELFFile(), Writer, Result); // Big-endian 64-bit if (const ELF64BEObjectFile *ELFObj = dyn_cast(Obj)) - return createELFDumper(ELFObj, Writer, Result); + return createELFDumper(ELFObj->getELFFile(), Writer, Result); return readobj_error::unsupported_obj_file_format; } } // namespace llvm - static const EnumEntry ElfClass[] = { { "None", ELF::ELFCLASSNONE }, { "32-bit", ELF::ELFCLASS32 }, @@ -322,7 +327,7 @@ static const EnumEntry ElfSymbolTypes[] = { static const char *getElfSectionType(unsigned Arch, unsigned Type) { switch (Arch) { - case Triple::arm: + case ELF::EM_ARM: switch (Type) { LLVM_READOBJ_ENUM_CASE(ELF, SHT_ARM_EXIDX); LLVM_READOBJ_ENUM_CASE(ELF, SHT_ARM_PREEMPTMAP); @@ -330,16 +335,12 @@ static const char *getElfSectionType(unsigned Arch, unsigned Type) { LLVM_READOBJ_ENUM_CASE(ELF, SHT_ARM_DEBUGOVERLAY); LLVM_READOBJ_ENUM_CASE(ELF, SHT_ARM_OVERLAYSECTION); } - case Triple::hexagon: - switch (Type) { - LLVM_READOBJ_ENUM_CASE(ELF, SHT_HEX_ORDERED); - } - case Triple::x86_64: - switch (Type) { - LLVM_READOBJ_ENUM_CASE(ELF, SHT_X86_64_UNWIND); - } - case Triple::mips: - case Triple::mipsel: + case ELF::EM_HEXAGON: + switch (Type) { LLVM_READOBJ_ENUM_CASE(ELF, SHT_HEX_ORDERED); } + case ELF::EM_X86_64: + switch (Type) { LLVM_READOBJ_ENUM_CASE(ELF, SHT_X86_64_UNWIND); } + case ELF::EM_MIPS: + case ELF::EM_MIPS_RS3_LE: switch (Type) { LLVM_READOBJ_ENUM_CASE(ELF, SHT_MIPS_REGINFO); LLVM_READOBJ_ENUM_CASE(ELF, SHT_MIPS_OPTIONS); @@ -416,12 +417,11 @@ static const EnumEntry ElfSegmentFlags[] = { LLVM_READOBJ_ENUM_ENT(ELF, PF_R) }; - template void ELFDumper::printFileHeaders() { error_code EC; - const typename ELFO::Elf_Ehdr *Header = Obj->getElfHeader(); + const typename ELFO::Elf_Ehdr *Header = Obj->getHeader(); { DictScope D(W, "ElfHeader"); @@ -461,24 +461,20 @@ void ELFDumper::printSections() { ListScope SectionsD(W, "Sections"); int SectionIndex = -1; - error_code EC; - for (section_iterator SecI = Obj->begin_sections(), - SecE = Obj->end_sections(); - SecI != SecE; SecI.increment(EC)) { - if (error(EC)) break; - + for (typename ELFO::Elf_Shdr_Iter SecI = Obj->begin_sections(), + SecE = Obj->end_sections(); + SecI != SecE; ++SecI) { ++SectionIndex; - const Elf_Shdr *Section = Obj->getElfSection(SecI); - StringRef Name; - if (error(SecI->getName(Name))) - Name = ""; + const Elf_Shdr *Section = &*SecI; + StringRef Name = errorOrDefault(Obj->getSectionName(Section)); DictScope SectionD(W, "Section"); W.printNumber("Index", SectionIndex); W.printNumber("Name", Name, Section->sh_name); - W.printHex ("Type", getElfSectionType(Obj->getArch(), Section->sh_type), - Section->sh_type); + W.printHex("Type", + getElfSectionType(Obj->getHeader()->e_machine, Section->sh_type), + Section->sh_type); W.printFlags ("Flags", Section->sh_flags, makeArrayRef(ElfSectionFlags)); W.printHex ("Address", Section->sh_addr); W.printHex ("Offset", Section->sh_offset); @@ -490,35 +486,23 @@ void ELFDumper::printSections() { if (opts::SectionRelocations) { ListScope D(W, "Relocations"); - for (relocation_iterator RelI = SecI->begin_relocations(), - RelE = SecI->end_relocations(); - RelI != RelE; RelI.increment(EC)) { - if (error(EC)) break; - - printRelocation(SecI, RelI); - } + printRelocations(Section); } if (opts::SectionSymbols) { ListScope D(W, "Symbols"); - for (symbol_iterator SymI = Obj->begin_symbols(), - SymE = Obj->end_symbols(); - SymI != SymE; SymI.increment(EC)) { - if (error(EC)) break; - - bool Contained = false; - if (SecI->containsSymbol(*SymI, Contained) || !Contained) - continue; - - printSymbol(SymI); + for (typename ELFO::Elf_Sym_Iter SymI = Obj->begin_symbols(), + SymE = Obj->end_symbols(); + SymI != SymE; ++SymI) { + if (Obj->getSection(&*SymI) == Section) + printSymbol(SymI); } } if (opts::SectionData) { - StringRef Data; - if (error(SecI->getContents(Data))) break; - - W.printBinaryBlock("SectionData", Data); + ArrayRef Data = errorOrDefault(Obj->getSectionContents(Section)); + W.printBinaryBlock("SectionData", + StringRef((const char *)Data.data(), Data.size())); } } } @@ -529,70 +513,73 @@ void ELFDumper::printRelocations() { error_code EC; int SectionNumber = -1; - for (section_iterator SecI = Obj->begin_sections(), - SecE = Obj->end_sections(); - SecI != SecE; SecI.increment(EC)) { - if (error(EC)) break; - + for (typename ELFO::Elf_Shdr_Iter SecI = Obj->begin_sections(), + SecE = Obj->end_sections(); + SecI != SecE; ++SecI) { ++SectionNumber; - StringRef Name; - if (error(SecI->getName(Name))) + + if (SecI->sh_type != ELF::SHT_REL && SecI->sh_type != ELF::SHT_RELA) continue; - bool PrintedGroup = false; - for (relocation_iterator RelI = SecI->begin_relocations(), - RelE = SecI->end_relocations(); - RelI != RelE; RelI.increment(EC)) { - if (error(EC)) break; + StringRef Name = errorOrDefault(Obj->getSectionName(&*SecI)); - if (!PrintedGroup) { - W.startLine() << "Section (" << SectionNumber << ") " << Name << " {\n"; - W.indent(); - PrintedGroup = true; - } + W.startLine() << "Section (" << SectionNumber << ") " << Name << " {\n"; + W.indent(); - printRelocation(SecI, RelI); - } + printRelocations(&*SecI); - if (PrintedGroup) { - W.unindent(); - W.startLine() << "}\n"; - } + W.unindent(); + W.startLine() << "}\n"; } } -template -void ELFDumper::printRelocation(section_iterator Sec, - relocation_iterator RelI) { - uint64_t Offset; - uint64_t RelocType; - SmallString<32> RelocName; - int64_t Addend; - StringRef SymbolName; - if (Obj->getElfHeader()->e_type == ELF::ET_REL){ - if (error(RelI->getOffset(Offset))) return; - } else { - if (error(RelI->getAddress(Offset))) return; +template +void ELFDumper::printRelocations(const Elf_Shdr *Sec) { + switch (Sec->sh_type) { + case ELF::SHT_REL: + for (typename ELFO::Elf_Rel_Iter RI = Obj->begin_rel(Sec), + RE = Obj->end_rel(Sec); + RI != RE; ++RI) { + typename ELFO::Elf_Rela Rela; + Rela.r_offset = RI->r_offset; + Rela.r_info = RI->r_info; + Rela.r_addend = 0; + printRelocation(Sec, Rela); + } + break; + case ELF::SHT_RELA: + for (typename ELFO::Elf_Rela_Iter RI = Obj->begin_rela(Sec), + RE = Obj->end_rela(Sec); + RI != RE; ++RI) { + printRelocation(Sec, *RI); + } + break; } - if (error(RelI->getType(RelocType))) return; - if (error(RelI->getTypeName(RelocName))) return; - if (error(getELFRelocationAddend(*RelI, Addend))) return; - symbol_iterator Symbol = RelI->getSymbol(); - if (Symbol != Obj->end_symbols() && error(Symbol->getName(SymbolName))) - return; +} + +template +void ELFDumper::printRelocation(const Elf_Shdr *Sec, + typename ELFO::Elf_Rela Rel) { + SmallString<32> RelocName; + Obj->getRelocationTypeName(Rel.getType(Obj->isMips64EL()), RelocName); + StringRef SymbolName; + std::pair Sym = + Obj->getRelocationSymbol(Sec, &Rel); + if (Sym.first) + SymbolName = errorOrDefault(Obj->getSymbolName(Sym.first, Sym.second)); if (opts::ExpandRelocs) { DictScope Group(W, "Relocation"); - W.printHex("Offset", Offset); - W.printNumber("Type", RelocName, RelocType); + W.printHex("Offset", Rel.r_offset); + W.printNumber("Type", RelocName, (int)Rel.getType(Obj->isMips64EL())); W.printString("Symbol", SymbolName.size() > 0 ? SymbolName : "-"); - W.printHex("Addend", Addend); + W.printHex("Addend", Rel.r_addend); } else { raw_ostream& OS = W.startLine(); - OS << W.hex(Offset) + OS << W.hex(Rel.r_offset) << " " << RelocName << " " << (SymbolName.size() > 0 ? SymbolName : "-") - << " " << W.hex(Addend) + << " " << W.hex(Rel.r_addend) << "\n"; } } @@ -600,12 +587,9 @@ void ELFDumper::printRelocation(section_iterator Sec, template void ELFDumper::printSymbols() { ListScope Group(W, "Symbols"); - - error_code EC; - for (symbol_iterator SymI = Obj->begin_symbols(), SymE = Obj->end_symbols(); - SymI != SymE; SymI.increment(EC)) { - if (error(EC)) break; - + for (typename ELFO::Elf_Sym_Iter SymI = Obj->begin_symbols(), + SymE = Obj->end_symbols(); + SymI != SymE; ++SymI) { printSymbol(SymI); } } @@ -614,41 +598,27 @@ template void ELFDumper::printDynamicSymbols() { ListScope Group(W, "DynamicSymbols"); - error_code EC; - for (symbol_iterator SymI = Obj->begin_dynamic_symbols(), - SymE = Obj->end_dynamic_symbols(); - SymI != SymE; SymI.increment(EC)) { - if (error(EC)) break; - - printSymbol(SymI, true); + for (typename ELFO::Elf_Sym_Iter SymI = Obj->begin_dynamic_symbols(), + SymE = Obj->end_dynamic_symbols(); + SymI != SymE; ++SymI) { + printSymbol(SymI); } } -template -void ELFDumper::printSymbol(symbol_iterator SymI, bool IsDynamic) { - error_code EC; - - const Elf_Sym *Symbol = Obj->getElfSymbol(SymI); - const Elf_Shdr *Section = Obj->getSection(Symbol); - - StringRef SymbolName; - if (SymI->getName(SymbolName)) - SymbolName = ""; - - StringRef SectionName = ""; - if (Section) - Obj->getSectionName(Section, SectionName); - +template +void ELFDumper::printSymbol(typename ELFO::Elf_Sym_Iter Symbol) { + StringRef SymbolName = errorOrDefault(Obj->getSymbolName(Symbol)); + const Elf_Shdr *Sec = Obj->getSection(&*Symbol); + StringRef SectionName = Sec ? errorOrDefault(Obj->getSectionName(Sec)) : ""; std::string FullSymbolName(SymbolName); - if (IsDynamic) { - StringRef Version; + if (Symbol.isDynamic()) { bool IsDefault; - if (error(Obj->getSymbolVersion(*SymI, Version, IsDefault))) - return; - if (!Version.empty()) { + ErrorOr Version = Obj->getSymbolVersion(0, &*Symbol, IsDefault); + if (Version) { FullSymbolName += (IsDefault ? "@@" : "@"); - FullSymbolName += Version; - } + FullSymbolName += *Version; + } else + error(Version); } DictScope D(W, "Symbol"); @@ -706,9 +676,9 @@ static const char *getTypeString(uint64_t Type) { #undef LLVM_READOBJ_TYPE_CASE -template -static void printValue(const ELFObjectFile *O, uint64_t Type, - uint64_t Value, bool Is64, raw_ostream &OS) { +template +static void printValue(const ELFFile *O, uint64_t Type, uint64_t Value, + bool Is64, raw_ostream &OS) { switch (Type) { case DT_PLTREL: if (Value == DT_REL) { @@ -748,12 +718,10 @@ static void printValue(const ELFObjectFile *O, uint64_t Type, OS << Value << " (bytes)"; break; case DT_NEEDED: - OS << "SharedLibrary (" - << O->getString(O->getDynamicStringTableSectionHeader(), Value) << ")"; + OS << "SharedLibrary (" << O->getDynamicString(Value) << ")"; break; case DT_SONAME: - OS << "LibrarySoname (" - << O->getString(O->getDynamicStringTableSectionHeader(), Value) << ")"; + OS << "LibrarySoname (" << O->getDynamicString(Value) << ")"; break; } } @@ -765,9 +733,8 @@ void ELFDumper::printUnwindInfo() { template void ELFDumper::printDynamicTable() { - typedef typename ELFO::Elf_Dyn_iterator EDI; - EDI Start = Obj->begin_dynamic_table(), - End = Obj->end_dynamic_table(true); + typedef typename ELFO::Elf_Dyn_Iter EDI; + EDI Start = Obj->begin_dynamic_table(), End = Obj->end_dynamic_table(true); if (Start == End) return; @@ -776,7 +743,7 @@ void ELFDumper::printDynamicTable() { raw_ostream &OS = W.getOStream(); W.startLine() << "DynamicSection [ (" << Total << " entries)\n"; - bool Is64 = Obj->getBytesInAddress() == 8; + bool Is64 = ELFT::Is64Bits; W.startLine() << " Tag" << (Is64 ? " " : " ") << "Type" @@ -793,38 +760,25 @@ void ELFDumper::printDynamicTable() { W.startLine() << "]\n"; } -static bool compareLibraryName(const LibraryRef &L, const LibraryRef &R) { - StringRef LPath, RPath; - L.getPath(LPath); - R.getPath(RPath); - return LPath < RPath; -} - template void ELFDumper::printNeededLibraries() { ListScope D(W, "NeededLibraries"); error_code EC; - typedef std::vector LibsTy; + typedef std::vector LibsTy; LibsTy Libs; - for (library_iterator I = Obj->begin_libraries_needed(), - E = Obj->end_libraries_needed(); - I != E; I.increment(EC)) { - if (EC) - report_fatal_error("Needed libraries iteration failed"); + for (typename ELFO::Elf_Dyn_Iter DynI = Obj->begin_dynamic_table(), + DynE = Obj->end_dynamic_table(); + DynI != DynE; ++DynI) + if (DynI->d_tag == ELF::DT_NEEDED) + Libs.push_back(Obj->getDynamicString(DynI->d_un.d_val)); - Libs.push_back(*I); - } + std::stable_sort(Libs.begin(), Libs.end()); - std::sort(Libs.begin(), Libs.end(), &compareLibraryName); - - for (LibsTy::const_iterator I = Libs.begin(), E = Libs.end(); - I != E; ++I) { - StringRef Path; - I->getPath(Path); - outs() << " " << Path << "\n"; + for (LibsTy::const_iterator I = Libs.begin(), E = Libs.end(); I != E; ++I) { + outs() << " " << *I << "\n"; } } diff --git a/llvm/tools/llvm-readobj/llvm-readobj.cpp b/llvm/tools/llvm-readobj/llvm-readobj.cpp index 2e95b6b5518f..0e092c0cda2e 100644 --- a/llvm/tools/llvm-readobj/llvm-readobj.cpp +++ b/llvm/tools/llvm-readobj/llvm-readobj.cpp @@ -1,4 +1,4 @@ -//===- llvm-readobj.cpp - Dump contents of an Object File -----------------===// +//===- llvm-readobj.cpp - Dump contents of an Object File -----------------===// // // The LLVM Compiler Infrastructure // @@ -130,12 +130,15 @@ namespace opts { cl::desc("Expand each shown relocation to multiple lines")); } // namespace opts +static int ReturnValue = EXIT_SUCCESS; + namespace llvm { bool error(error_code EC) { if (!EC) return false; + ReturnValue = EXIT_FAILURE; outs() << "\nError reading file: " << EC.message() << ".\n"; outs().flush(); return true; @@ -157,6 +160,7 @@ static void reportError(StringRef Input, error_code EC) { errs() << Input << ": " << EC.message() << "\n"; errs().flush(); + ReturnValue = EXIT_FAILURE; } static void reportError(StringRef Input, StringRef Message) { @@ -164,6 +168,7 @@ static void reportError(StringRef Input, StringRef Message) { Input = ""; errs() << Input << ": " << Message << "\n"; + ReturnValue = EXIT_FAILURE; } /// @brief Creates an format-specific object file dumper. @@ -289,5 +294,5 @@ int main(int argc, const char *argv[]) { std::for_each(opts::InputFilenames.begin(), opts::InputFilenames.end(), dumpInput); - return 0; + return ReturnValue; } diff --git a/llvm/tools/yaml2obj/yaml2elf.cpp b/llvm/tools/yaml2obj/yaml2elf.cpp index 61252a4a28d3..d3b25ecf09bf 100644 --- a/llvm/tools/yaml2obj/yaml2elf.cpp +++ b/llvm/tools/yaml2obj/yaml2elf.cpp @@ -13,7 +13,7 @@ //===----------------------------------------------------------------------===// #include "yaml2obj.h" -#include "llvm/Object/ELF.h" +#include "llvm/Object/ELFObjectFile.h" #include "llvm/Object/ELFYAML.h" #include "llvm/Support/ELF.h" #include "llvm/Support/MemoryBuffer.h" @@ -157,7 +157,7 @@ class ELFState { unsigned DotStrtabSecNo; /// \brief The accumulated contents of all sections so far. ContiguousBlobAccumulator &SectionContentAccum; - typedef typename object::ELFObjectFile::Elf_Ehdr Elf_Ehdr; + typedef typename object::ELFFile::Elf_Ehdr Elf_Ehdr; /// \brief The ELF file header. Elf_Ehdr &Header; @@ -185,9 +185,9 @@ public: template static void addSymbols(const std::vector &Symbols, ELFState &State, - std::vector::Elf_Sym> &Syms, + std::vector::Elf_Sym> &Syms, unsigned SymbolBinding) { - typedef typename object::ELFObjectFile::Elf_Sym Elf_Sym; + typedef typename object::ELFFile::Elf_Sym Elf_Sym; for (unsigned i = 0, e = Symbols.size(); i != e; ++i) { const ELFYAML::Symbol &Sym = Symbols[i]; Elf_Sym Symbol; @@ -211,11 +211,12 @@ addSymbols(const std::vector &Symbols, ELFState &State, } template -static void handleSymtabSectionHeader( - const ELFYAML::LocalGlobalWeakSymbols &Symbols, ELFState &State, - typename object::ELFObjectFile::Elf_Shdr &SHeader) { +static void +handleSymtabSectionHeader(const ELFYAML::LocalGlobalWeakSymbols &Symbols, + ELFState &State, + typename object::ELFFile::Elf_Shdr &SHeader) { - typedef typename object::ELFObjectFile::Elf_Sym Elf_Sym; + typedef typename object::ELFFile::Elf_Sym Elf_Sym; SHeader.sh_type = ELF::SHT_SYMTAB; SHeader.sh_link = State.getDotStrTabSecNo(); // One greater than symbol table index of the last local symbol. @@ -241,8 +242,8 @@ static void handleSymtabSectionHeader( template static int writeELF(raw_ostream &OS, const ELFYAML::Object &Doc) { using namespace llvm::ELF; - typedef typename object::ELFObjectFile::Elf_Ehdr Elf_Ehdr; - typedef typename object::ELFObjectFile::Elf_Shdr Elf_Shdr; + typedef typename object::ELFFile::Elf_Ehdr Elf_Ehdr; + typedef typename object::ELFFile::Elf_Shdr Elf_Shdr; const ELFYAML::FileHeader &Hdr = Doc.Header;