diff options
Diffstat (limited to 'lib/Object/ELFObjectFile.cpp')
-rw-r--r-- | lib/Object/ELFObjectFile.cpp | 1720 |
1 files changed, 25 insertions, 1695 deletions
diff --git a/lib/Object/ELFObjectFile.cpp b/lib/Object/ELFObjectFile.cpp index 1b29cf682f..ab5f8108af 100644 --- a/lib/Object/ELFObjectFile.cpp +++ b/lib/Object/ELFObjectFile.cpp @@ -7,1714 +7,44 @@ // //===----------------------------------------------------------------------===// // -// This file defines the ELFObjectFile and DyldELFObject classes. +// Part of the ELFObjectFile class implementation. // //===----------------------------------------------------------------------===// -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringSwitch.h" -#include "llvm/ADT/Triple.h" -#include "llvm/ADT/DenseMap.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 <algorithm> -#include <limits> -#include <utility> +#include "llvm/Object/ELF.h" -using namespace llvm; -using namespace object; - -// Templates to choose Elf_Addr and Elf_Off depending on is64Bits. -namespace { -template<support::endianness target_endianness> -struct ELFDataTypeTypedefHelperCommon { - typedef support::detail::packed_endian_specific_integral - <uint16_t, target_endianness, support::aligned> Elf_Half; - typedef support::detail::packed_endian_specific_integral - <uint32_t, target_endianness, support::aligned> Elf_Word; - typedef support::detail::packed_endian_specific_integral - <int32_t, target_endianness, support::aligned> Elf_Sword; - typedef support::detail::packed_endian_specific_integral - <uint64_t, target_endianness, support::aligned> Elf_Xword; - typedef support::detail::packed_endian_specific_integral - <int64_t, target_endianness, support::aligned> Elf_Sxword; -}; -} - -namespace { -template<support::endianness target_endianness, bool is64Bits> -struct ELFDataTypeTypedefHelper; - -/// ELF 32bit types. -template<support::endianness target_endianness> -struct ELFDataTypeTypedefHelper<target_endianness, false> - : ELFDataTypeTypedefHelperCommon<target_endianness> { - typedef uint32_t value_type; - typedef support::detail::packed_endian_specific_integral - <value_type, target_endianness, support::aligned> Elf_Addr; - typedef support::detail::packed_endian_specific_integral - <value_type, target_endianness, support::aligned> Elf_Off; -}; - -/// ELF 64bit types. -template<support::endianness target_endianness> -struct ELFDataTypeTypedefHelper<target_endianness, true> - : ELFDataTypeTypedefHelperCommon<target_endianness>{ - typedef uint64_t value_type; - typedef support::detail::packed_endian_specific_integral - <value_type, target_endianness, support::aligned> Elf_Addr; - typedef support::detail::packed_endian_specific_integral - <value_type, target_endianness, support::aligned> Elf_Off; -}; -} - -// I really don't like doing this, but the alternative is copypasta. -#define LLVM_ELF_IMPORT_TYPES(target_endianness, is64Bits) \ -typedef typename \ - ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Addr Elf_Addr; \ -typedef typename \ - ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Off Elf_Off; \ -typedef typename \ - ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Half Elf_Half; \ -typedef typename \ - ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Word Elf_Word; \ -typedef typename \ - ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Sword Elf_Sword; \ -typedef typename \ - ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Xword Elf_Xword; \ -typedef typename \ - ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Sxword Elf_Sxword; - - // Section header. -namespace { -template<support::endianness target_endianness, bool is64Bits> -struct Elf_Shdr_Base; - -template<support::endianness target_endianness> -struct Elf_Shdr_Base<target_endianness, false> { - LLVM_ELF_IMPORT_TYPES(target_endianness, 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<support::endianness target_endianness> -struct Elf_Shdr_Base<target_endianness, true> { - LLVM_ELF_IMPORT_TYPES(target_endianness, 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<support::endianness target_endianness, bool is64Bits> -struct Elf_Shdr_Impl : Elf_Shdr_Base<target_endianness, is64Bits> { - using Elf_Shdr_Base<target_endianness, is64Bits>::sh_entsize; - using Elf_Shdr_Base<target_endianness, is64Bits>::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; - } -}; -} - -namespace { -template<support::endianness target_endianness, bool is64Bits> -struct Elf_Sym_Base; - -template<support::endianness target_endianness> -struct Elf_Sym_Base<target_endianness, false> { - LLVM_ELF_IMPORT_TYPES(target_endianness, 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<support::endianness target_endianness> -struct Elf_Sym_Base<target_endianness, true> { - LLVM_ELF_IMPORT_TYPES(target_endianness, 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<support::endianness target_endianness, bool is64Bits> -struct Elf_Sym_Impl : Elf_Sym_Base<target_endianness, is64Bits> { - using Elf_Sym_Base<target_endianness, is64Bits>::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); - } -}; -} - -namespace { -template<support::endianness target_endianness, bool is64Bits, bool isRela> -struct Elf_Rel_Base; - -template<support::endianness target_endianness> -struct Elf_Rel_Base<target_endianness, false, false> { - LLVM_ELF_IMPORT_TYPES(target_endianness, false) - Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) - Elf_Word r_info; // Symbol table index and type of relocation to apply -}; - -template<support::endianness target_endianness> -struct Elf_Rel_Base<target_endianness, true, false> { - LLVM_ELF_IMPORT_TYPES(target_endianness, true) - Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) - Elf_Xword r_info; // Symbol table index and type of relocation to apply -}; - -template<support::endianness target_endianness> -struct Elf_Rel_Base<target_endianness, false, true> { - LLVM_ELF_IMPORT_TYPES(target_endianness, false) - Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) - Elf_Word r_info; // Symbol table index and type of relocation to apply - Elf_Sword r_addend; // Compute value for relocatable field by adding this -}; - -template<support::endianness target_endianness> -struct Elf_Rel_Base<target_endianness, true, true> { - LLVM_ELF_IMPORT_TYPES(target_endianness, true) - Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) - Elf_Xword r_info; // Symbol table index and type of relocation to apply - Elf_Sxword r_addend; // Compute value for relocatable field by adding this. -}; - -template<support::endianness target_endianness, bool is64Bits, bool isRela> -struct Elf_Rel_Impl; - -template<support::endianness target_endianness, bool isRela> -struct Elf_Rel_Impl<target_endianness, true, isRela> - : Elf_Rel_Base<target_endianness, true, isRela> { - using Elf_Rel_Base<target_endianness, true, isRela>::r_info; - LLVM_ELF_IMPORT_TYPES(target_endianness, true) - - // These accessors and mutators correspond to the ELF64_R_SYM, ELF64_R_TYPE, - // and ELF64_R_INFO macros defined in the ELF specification: - uint64_t getSymbol() const { return (r_info >> 32); } - unsigned char getType() const { - return (unsigned char) (r_info & 0xffffffffL); - } - void setSymbol(uint64_t s) { setSymbolAndType(s, getType()); } - void setType(unsigned char t) { setSymbolAndType(getSymbol(), t); } - void setSymbolAndType(uint64_t s, unsigned char t) { - r_info = (s << 32) + (t&0xffffffffL); - } -}; - -template<support::endianness target_endianness, bool isRela> -struct Elf_Rel_Impl<target_endianness, false, isRela> - : Elf_Rel_Base<target_endianness, false, isRela> { - using Elf_Rel_Base<target_endianness, false, isRela>::r_info; - LLVM_ELF_IMPORT_TYPES(target_endianness, false) - - // These accessors and mutators correspond to the ELF32_R_SYM, ELF32_R_TYPE, - // and ELF32_R_INFO macros defined in the ELF specification: - uint32_t getSymbol() const { return (r_info >> 8); } - unsigned char getType() const { return (unsigned char) (r_info & 0x0ff); } - void setSymbol(uint32_t s) { setSymbolAndType(s, getType()); } - void setType(unsigned char t) { setSymbolAndType(getSymbol(), t); } - void setSymbolAndType(uint32_t s, unsigned char t) { - r_info = (s << 8) + t; - } -}; +namespace llvm { -} +using namespace object; namespace { -template<support::endianness target_endianness, bool is64Bits> -class ELFObjectFile : public ObjectFile { - LLVM_ELF_IMPORT_TYPES(target_endianness, is64Bits) - - typedef Elf_Shdr_Impl<target_endianness, is64Bits> Elf_Shdr; - typedef Elf_Sym_Impl<target_endianness, is64Bits> Elf_Sym; - typedef Elf_Rel_Impl<target_endianness, is64Bits, false> Elf_Rel; - typedef Elf_Rel_Impl<target_endianness, is64Bits, true> Elf_Rela; - -protected: - struct Elf_Ehdr { - 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]; } - }; - // This flag is used for classof, to distinguish ELFObjectFile from - // its subclass. If more subclasses will be created, this flag will - // have to become an enum. - bool isDyldELFObject; - -private: - typedef SmallVector<const Elf_Shdr*, 1> Sections_t; - typedef DenseMap<unsigned, unsigned> IndexMap_t; - typedef DenseMap<const Elf_Shdr*, SmallVector<uint32_t, 1> > RelocMap_t; - - const Elf_Ehdr *Header; - const Elf_Shdr *SectionHeaderTable; - const Elf_Shdr *dot_shstrtab_sec; // Section header string table. - const Elf_Shdr *dot_strtab_sec; // Symbol header string table. - Sections_t SymbolTableSections; - IndexMap_t SymbolTableSectionsIndexMap; - DenseMap<const Elf_Sym*, ELF::Elf64_Word> ExtendedSymbolTable; - - /// @brief Map sections to an array of relocation sections that reference - /// them sorted by section index. - RelocMap_t SectionRelocMap; - - /// @brief Get the relocation section that contains \a Rel. - const Elf_Shdr *getRelSection(DataRefImpl Rel) const { - return getSection(Rel.w.b); - } - - bool isRelocationHasAddend(DataRefImpl Rel) const; - template<typename T> - const T *getEntry(uint16_t Section, uint32_t Entry) const; - template<typename T> - 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; - const char *getString(uint32_t section, uint32_t offset) const; - const char *getString(const Elf_Shdr *section, uint32_t offset) const; - error_code getSymbolName(const Elf_Sym *Symb, StringRef &Res) const; - -protected: - const Elf_Sym *getSymbol(DataRefImpl Symb) const; // FIXME: Should be private? - void validateSymbol(DataRefImpl Symb) 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 getSymbolSize(DataRefImpl Symb, uint64_t &Res) const; - virtual error_code getSymbolNMTypeChar(DataRefImpl Symb, char &Res) const; - virtual error_code isSymbolInternal(DataRefImpl Symb, bool &Res) const; - virtual error_code isSymbolGlobal(DataRefImpl Symb, bool &Res) const; - virtual error_code isSymbolWeak(DataRefImpl Symb, bool &Res) const; - virtual error_code getSymbolType(DataRefImpl Symb, SymbolRef::Type &Res) const; - virtual error_code isSymbolAbsolute(DataRefImpl Symb, bool &Res) const; - virtual error_code getSymbolSection(DataRefImpl Symb, - section_iterator &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 sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, - bool &Result) const; - virtual relocation_iterator getSectionRelBegin(DataRefImpl Sec) const; - virtual relocation_iterator getSectionRelEnd(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 error_code getRelocationSymbol(DataRefImpl Rel, - SymbolRef &Res) const; - virtual error_code getRelocationType(DataRefImpl Rel, - uint64_t &Res) const; - virtual error_code getRelocationTypeName(DataRefImpl Rel, - SmallVectorImpl<char> &Result) const; - virtual error_code getRelocationAdditionalInfo(DataRefImpl Rel, - int64_t &Res) const; - virtual error_code getRelocationValueString(DataRefImpl Rel, - SmallVectorImpl<char> &Result) const; - -public: - ELFObjectFile(MemoryBuffer *Object, error_code &ec); - virtual symbol_iterator begin_symbols() const; - virtual symbol_iterator end_symbols() const; - virtual section_iterator begin_sections() const; - virtual section_iterator end_sections() const; - - virtual uint8_t getBytesInAddress() const; - virtual StringRef getFileFormatName() const; - virtual unsigned getArch() const; - - uint64_t getNumSections() const; - uint64_t getStringTableIndex() const; - ELF::Elf64_Word getSymbolTableIndex(const Elf_Sym *symb) const; - const Elf_Shdr *getSection(const Elf_Sym *symb) 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() == Binary::isELF; - } - static inline bool classof(const ELFObjectFile *v) { return true; } -}; -} // end namespace - -template<support::endianness target_endianness, bool is64Bits> -void ELFObjectFile<target_endianness, is64Bits> - ::validateSymbol(DataRefImpl Symb) const { - const Elf_Sym *symb = getSymbol(Symb); - const Elf_Shdr *SymbolTableSection = SymbolTableSections[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!"); -} - -template<support::endianness target_endianness, bool is64Bits> -error_code ELFObjectFile<target_endianness, is64Bits> - ::getSymbolNext(DataRefImpl Symb, - SymbolRef &Result) const { - validateSymbol(Symb); - const Elf_Shdr *SymbolTableSection = SymbolTableSections[Symb.d.b]; - - ++Symb.d.a; - // Check to see if we are at the end of this symbol table. - if (Symb.d.a >= SymbolTableSection->getEntityCount()) { - // We are at the end. If there are other symbol tables, jump to them. - ++Symb.d.b; - Symb.d.a = 1; // The 0th symbol in ELF is fake. - // Otherwise return the terminator. - if (Symb.d.b >= SymbolTableSections.size()) { - Symb.d.a = std::numeric_limits<uint32_t>::max(); - Symb.d.b = std::numeric_limits<uint32_t>::max(); - } - } - - Result = SymbolRef(Symb, this); - return object_error::success; -} - -template<support::endianness target_endianness, bool is64Bits> -error_code ELFObjectFile<target_endianness, is64Bits> - ::getSymbolName(DataRefImpl Symb, - StringRef &Result) const { - validateSymbol(Symb); - const Elf_Sym *symb = getSymbol(Symb); - return getSymbolName(symb, Result); -} - -template<support::endianness target_endianness, bool is64Bits> -ELF::Elf64_Word ELFObjectFile<target_endianness, is64Bits> - ::getSymbolTableIndex(const Elf_Sym *symb) const { - if (symb->st_shndx == ELF::SHN_XINDEX) - return ExtendedSymbolTable.lookup(symb); - return symb->st_shndx; -} - -template<support::endianness target_endianness, bool is64Bits> -const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Shdr * -ELFObjectFile<target_endianness, is64Bits> - ::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) - return 0; - return getSection(symb->st_shndx); -} - -template<support::endianness target_endianness, bool is64Bits> -error_code ELFObjectFile<target_endianness, is64Bits> - ::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_addr : 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<support::endianness target_endianness, bool is64Bits> -error_code ELFObjectFile<target_endianness, is64Bits> - ::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: - Result = symb->st_value + (Section ? Section->sh_addr : 0); - return object_error::success; - default: - Result = UnknownAddressOrSize; - return object_error::success; - } -} - -template<support::endianness target_endianness, bool is64Bits> -error_code ELFObjectFile<target_endianness, is64Bits> - ::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<support::endianness target_endianness, bool is64Bits> -error_code ELFObjectFile<target_endianness, is64Bits> - ::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<char>(name) - .StartsWith(".debug", 'N') - .StartsWith(".note", 'n') - .Default('?'); - return object_error::success; - } - - Result = ret; - return object_error::success; -} - -template<support::endianness target_endianness, bool is64Bits> -error_code ELFObjectFile<target_endianness, is64Bits> - ::getSymbolType(DataRefImpl Symb, - SymbolRef::Type &Result) const { - validateSymbol(Symb); - const Elf_Sym *symb = getSymbol(Symb); - - if (getSymbolTableIndex(symb) == ELF::SHN_UNDEF) { - Result = SymbolRef::ST_External; - return object_error::success; - } - - switch (symb->getType()) { - 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: - Result = SymbolRef::ST_Data; - break; - default: - Result = SymbolRef::ST_Other; - break; - } - return object_error::success; -} - -template<support::endianness target_endianness, bool is64Bits> -error_code ELFObjectFile<target_endianness, is64Bits> - ::isSymbolGlobal(DataRefImpl Symb, - bool &Result) const { - validateSymbol(Symb); - const Elf_Sym *symb = getSymbol(Symb); - - Result = symb->getBinding() == ELF::STB_GLOBAL; - return object_error::success; -} - -template<support::endianness target_endianness, bool is64Bits> -error_code ELFObjectFile<target_endianness, is64Bits> - ::isSymbolWeak(DataRefImpl Symb, - bool &Result) const { - validateSymbol(Symb); - const Elf_Sym *symb = getSymbol(Symb); - - Result = symb->getBinding() == ELF::STB_WEAK; - return object_error::success; -} - -template<support::endianness target_endianness, bool is64Bits> -error_code ELFObjectFile<target_endianness, is64Bits> - ::isSymbolAbsolute(DataRefImpl Symb, bool &Res) const { - validateSymbol(Symb); - const Elf_Sym *symb = getSymbol(Symb); - Res = symb->st_shndx == ELF::SHN_ABS; - return object_error::success; -} - -template<support::endianness target_endianness, bool is64Bits> -error_code ELFObjectFile<target_endianness, is64Bits> - ::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<intptr_t>(sec); - Res = section_iterator(SectionRef(Sec, this)); - } - return object_error::success; -} - -template<support::endianness target_endianness, bool is64Bits> -error_code ELFObjectFile<target_endianness, is64Bits> - ::isSymbolInternal(DataRefImpl Symb, - bool &Result) const { - validateSymbol(Symb); - const Elf_Sym *symb = getSymbol(Symb); - - if ( symb->getType() == ELF::STT_FILE - || symb->getType() == ELF::STT_SECTION) - Result = true; - Result = false; - return object_error::success; -} - -template<support::endianness target_endianness, bool is64Bits> -error_code ELFObjectFile<target_endianness, is64Bits> - ::getSectionNext(DataRefImpl Sec, SectionRef &Result) const { - const uint8_t *sec = reinterpret_cast<const uint8_t *>(Sec.p); - sec += Header->e_shentsize; - Sec.p = reinterpret_cast<intptr_t>(sec); - Result = SectionRef(Sec, this); - return object_error::success; -} - -template<support::endianness target_endianness, bool is64Bits> -error_code ELFObjectFile<target_endianness, is64Bits> - ::getSectionName(DataRefImpl Sec, - StringRef &Result) const { - const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); - Result = StringRef(getString(dot_shstrtab_sec, sec->sh_name)); - return object_error::success; -} - -template<support::endianness target_endianness, bool is64Bits> -error_code ELFObjectFile<target_endianness, is64Bits> - ::getSectionAddress(DataRefImpl Sec, - uint64_t &Result) const { - const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); - Result = sec->sh_addr; - return object_error::success; -} - -template<support::endianness target_endianness, bool is64Bits> -error_code ELFObjectFile<target_endianness, is64Bits> - ::getSectionSize(DataRefImpl Sec, - uint64_t &Result) const { - const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); - Result = sec->sh_size; - return object_error::success; -} - -template<support::endianness target_endianness, bool is64Bits> -error_code ELFObjectFile<target_endianness, is64Bits> - ::getSectionContents(DataRefImpl Sec, - StringRef &Result) const { - const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); - const char *start = (const char*)base() + sec->sh_offset; - Result = StringRef(start, sec->sh_size); - return object_error::success; -} - -template<support::endianness target_endianness, bool is64Bits> -error_code ELFObjectFile<target_endianness, is64Bits> - ::getSectionAlignment(DataRefImpl Sec, - uint64_t &Result) const { - const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); - Result = sec->sh_addralign; - return object_error::success; -} - -template<support::endianness target_endianness, bool is64Bits> -error_code ELFObjectFile<target_endianness, is64Bits> - ::isSectionText(DataRefImpl Sec, - bool &Result) const { - const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); - if (sec->sh_flags & ELF::SHF_EXECINSTR) - Result = true; - else - Result = false; - return object_error::success; -} - -template<support::endianness target_endianness, bool is64Bits> -error_code ELFObjectFile<target_endianness, is64Bits> - ::isSectionData(DataRefImpl Sec, - bool &Result) const { - const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(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<support::endianness target_endianness, bool is64Bits> -error_code ELFObjectFile<target_endianness, is64Bits> - ::isSectionBSS(DataRefImpl Sec, - bool &Result) const { - const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(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<support::endianness target_endianness, bool is64Bits> -error_code ELFObjectFile<target_endianness, is64Bits> - ::sectionContainsSymbol(DataRefImpl Sec, - DataRefImpl Symb, - bool &Result) const { - // FIXME: Unimplemented. - Result = false; - return object_error::success; -} - -template<support::endianness target_endianness, bool is64Bits> -relocation_iterator ELFObjectFile<target_endianness, is64Bits> - ::getSectionRelBegin(DataRefImpl Sec) const { - DataRefImpl RelData; - memset(&RelData, 0, sizeof(RelData)); - const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); - typename RelocMap_t::const_iterator ittr = SectionRelocMap.find(sec); - if (sec != 0 && ittr != SectionRelocMap.end()) { - RelData.w.a = getSection(ittr->second[0])->sh_info; - RelData.w.b = ittr->second[0]; - RelData.w.c = 0; + std::pair<unsigned char, unsigned char> + getElfArchType(MemoryBuffer *Object) { + if (Object->getBufferSize() < ELF::EI_NIDENT) + return std::make_pair((uint8_t)ELF::ELFCLASSNONE,(uint8_t)ELF::ELFDATANONE); + return std::make_pair( (uint8_t)Object->getBufferStart()[ELF::EI_CLASS] + , (uint8_t)Object->getBufferStart()[ELF::EI_DATA]); } - return relocation_iterator(RelocationRef(RelData, this)); } -template<support::endianness target_endianness, bool is64Bits> -relocation_iterator ELFObjectFile<target_endianness, is64Bits> - ::getSectionRelEnd(DataRefImpl Sec) const { - DataRefImpl RelData; - memset(&RelData, 0, sizeof(RelData)); - const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); - typename RelocMap_t::const_iterator ittr = SectionRelocMap.find(sec); - if (sec != 0 && ittr != SectionRelocMap.end()) { - // Get the index of the last relocation section for this section. - std::size_t relocsecindex = ittr->second[ittr->second.size() - 1]; - const Elf_Shdr *relocsec = getSection(relocsecindex); - RelData.w.a = relocsec->sh_info; - RelData.w.b = relocsecindex; - RelData.w.c = relocsec->sh_size / relocsec->sh_entsize; - } - return relocation_iterator(RelocationRef(RelData, this)); -} - -// Relocations -template<support::endianness target_endianness, bool is64Bits> -error_code ELFObjectFile<target_endianness, is64Bits> - ::getRelocationNext(DataRefImpl Rel, - RelocationRef &Result) const { - ++Rel.w.c; - const Elf_Shdr *relocsec = getSection(Rel.w.b); - if (Rel.w.c >= (relocsec->sh_size / relocsec->sh_entsize)) { - // We have reached the end of the relocations for this section. See if there - // is another relocation section. - typename RelocMap_t::mapped_type relocseclist = - SectionRelocMap.lookup(getSection(Rel.w.a)); - - // Do a binary search for the current reloc section index (which must be - // present). Then get the next one. - typename RelocMap_t::mapped_type::const_iterator loc = - std::lower_bound(relocseclist.begin(), relocseclist.end(), Rel.w.b); - ++loc; - - // If there is no next one, don't do anything. The ++Rel.w.c above sets Rel - // to the end iterator. - if (loc != relocseclist.end()) { - Rel.w.b = *loc; - Rel.w.a = 0; - } - } - Result = RelocationRef(Rel, this); - return object_error::success; -} - -template<support::endianness target_endianness, bool is64Bits> -error_code ELFObjectFile<target_endianness, is64Bits> - ::getRelocationSymbol(DataRefImpl Rel, - SymbolRef &Result) const { - uint32_t symbolIdx; - const Elf_Shdr *sec = getSection(Rel.w.b); - switch (sec->sh_type) { - default : - report_fatal_error("Invalid section type in Rel!"); - case ELF::SHT_REL : { - symbolIdx = getRel(Rel)->getSymbol(); - break; - } - case ELF::SHT_RELA : { - symbolIdx = getRela(Rel)->getSymbol(); - break; - } - } - DataRefImpl SymbolData; - IndexMap_t::const_iterator it = SymbolTableSectionsIndexMap.find(sec->sh_link); - if (it == SymbolTableSectionsIndexMap.end()) - report_fatal_error("Relocation symbol table not found!"); - SymbolData.d.a = symbolIdx; - SymbolData.d.b = it->second; - Result = SymbolRef(SymbolData, this); - return object_error::success; -} - -template<support::endianness target_endianness, bool is64Bits> -error_code ELFObjectFile<target_endianness, is64Bits> - ::getRelocationAddress(DataRefImpl Rel, - uint64_t &Result) const { - uint64_t offset; - const Elf_Shdr *sec = getSection(Rel.w.b); - switch (sec->sh_type) { - default : - report_fatal_error("Invalid section type |