12754fe60SDimitry Andric //===- ELFObjectFile.cpp - ELF object file implementation -------*- C++ -*-===// 22754fe60SDimitry Andric // 32754fe60SDimitry Andric // The LLVM Compiler Infrastructure 42754fe60SDimitry Andric // 52754fe60SDimitry Andric // This file is distributed under the University of Illinois Open Source 62754fe60SDimitry Andric // License. See LICENSE.TXT for details. 72754fe60SDimitry Andric // 82754fe60SDimitry Andric //===----------------------------------------------------------------------===// 92754fe60SDimitry Andric // 102754fe60SDimitry Andric // This file defines the ELFObjectFile class. 112754fe60SDimitry Andric // 122754fe60SDimitry Andric //===----------------------------------------------------------------------===// 132754fe60SDimitry Andric 142754fe60SDimitry Andric #include "llvm/ADT/SmallVector.h" 152754fe60SDimitry Andric #include "llvm/ADT/StringSwitch.h" 162754fe60SDimitry Andric #include "llvm/ADT/Triple.h" 172754fe60SDimitry Andric #include "llvm/Object/ObjectFile.h" 182754fe60SDimitry Andric #include "llvm/Support/ELF.h" 192754fe60SDimitry Andric #include "llvm/Support/Endian.h" 202754fe60SDimitry Andric #include "llvm/Support/ErrorHandling.h" 212754fe60SDimitry Andric #include "llvm/Support/MemoryBuffer.h" 222754fe60SDimitry Andric #include <limits> 232754fe60SDimitry Andric #include <utility> 242754fe60SDimitry Andric 252754fe60SDimitry Andric using namespace llvm; 262754fe60SDimitry Andric using namespace object; 272754fe60SDimitry Andric 282754fe60SDimitry Andric // Templates to choose Elf_Addr and Elf_Off depending on is64Bits. 292754fe60SDimitry Andric namespace { 302754fe60SDimitry Andric template<support::endianness target_endianness> 312754fe60SDimitry Andric struct ELFDataTypeTypedefHelperCommon { 322754fe60SDimitry Andric typedef support::detail::packed_endian_specific_integral 332754fe60SDimitry Andric <uint16_t, target_endianness, support::aligned> Elf_Half; 342754fe60SDimitry Andric typedef support::detail::packed_endian_specific_integral 352754fe60SDimitry Andric <uint32_t, target_endianness, support::aligned> Elf_Word; 362754fe60SDimitry Andric typedef support::detail::packed_endian_specific_integral 372754fe60SDimitry Andric <int32_t, target_endianness, support::aligned> Elf_Sword; 382754fe60SDimitry Andric typedef support::detail::packed_endian_specific_integral 392754fe60SDimitry Andric <uint64_t, target_endianness, support::aligned> Elf_Xword; 402754fe60SDimitry Andric typedef support::detail::packed_endian_specific_integral 412754fe60SDimitry Andric <int64_t, target_endianness, support::aligned> Elf_Sxword; 422754fe60SDimitry Andric }; 432754fe60SDimitry Andric } 442754fe60SDimitry Andric 452754fe60SDimitry Andric namespace { 462754fe60SDimitry Andric template<support::endianness target_endianness, bool is64Bits> 472754fe60SDimitry Andric struct ELFDataTypeTypedefHelper; 482754fe60SDimitry Andric 492754fe60SDimitry Andric /// ELF 32bit types. 502754fe60SDimitry Andric template<support::endianness target_endianness> 512754fe60SDimitry Andric struct ELFDataTypeTypedefHelper<target_endianness, false> 522754fe60SDimitry Andric : ELFDataTypeTypedefHelperCommon<target_endianness> { 532754fe60SDimitry Andric typedef support::detail::packed_endian_specific_integral 542754fe60SDimitry Andric <uint32_t, target_endianness, support::aligned> Elf_Addr; 552754fe60SDimitry Andric typedef support::detail::packed_endian_specific_integral 562754fe60SDimitry Andric <uint32_t, target_endianness, support::aligned> Elf_Off; 572754fe60SDimitry Andric }; 582754fe60SDimitry Andric 592754fe60SDimitry Andric /// ELF 64bit types. 602754fe60SDimitry Andric template<support::endianness target_endianness> 612754fe60SDimitry Andric struct ELFDataTypeTypedefHelper<target_endianness, true> 622754fe60SDimitry Andric : ELFDataTypeTypedefHelperCommon<target_endianness>{ 632754fe60SDimitry Andric typedef support::detail::packed_endian_specific_integral 642754fe60SDimitry Andric <uint64_t, target_endianness, support::aligned> Elf_Addr; 652754fe60SDimitry Andric typedef support::detail::packed_endian_specific_integral 662754fe60SDimitry Andric <uint64_t, target_endianness, support::aligned> Elf_Off; 672754fe60SDimitry Andric }; 682754fe60SDimitry Andric } 692754fe60SDimitry Andric 702754fe60SDimitry Andric // I really don't like doing this, but the alternative is copypasta. 712754fe60SDimitry Andric #define LLVM_ELF_IMPORT_TYPES(target_endianness, is64Bits) \ 722754fe60SDimitry Andric typedef typename \ 732754fe60SDimitry Andric ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Addr Elf_Addr; \ 742754fe60SDimitry Andric typedef typename \ 752754fe60SDimitry Andric ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Off Elf_Off; \ 762754fe60SDimitry Andric typedef typename \ 772754fe60SDimitry Andric ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Half Elf_Half; \ 782754fe60SDimitry Andric typedef typename \ 792754fe60SDimitry Andric ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Word Elf_Word; \ 802754fe60SDimitry Andric typedef typename \ 812754fe60SDimitry Andric ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Sword Elf_Sword; \ 822754fe60SDimitry Andric typedef typename \ 832754fe60SDimitry Andric ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Xword Elf_Xword; \ 842754fe60SDimitry Andric typedef typename \ 852754fe60SDimitry Andric ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Sxword Elf_Sxword; 862754fe60SDimitry Andric 872754fe60SDimitry Andric // Section header. 882754fe60SDimitry Andric namespace { 892754fe60SDimitry Andric template<support::endianness target_endianness, bool is64Bits> 902754fe60SDimitry Andric struct Elf_Shdr_Base; 912754fe60SDimitry Andric 922754fe60SDimitry Andric template<support::endianness target_endianness> 932754fe60SDimitry Andric struct Elf_Shdr_Base<target_endianness, false> { 942754fe60SDimitry Andric LLVM_ELF_IMPORT_TYPES(target_endianness, false) 952754fe60SDimitry Andric Elf_Word sh_name; // Section name (index into string table) 962754fe60SDimitry Andric Elf_Word sh_type; // Section type (SHT_*) 972754fe60SDimitry Andric Elf_Word sh_flags; // Section flags (SHF_*) 982754fe60SDimitry Andric Elf_Addr sh_addr; // Address where section is to be loaded 992754fe60SDimitry Andric Elf_Off sh_offset; // File offset of section data, in bytes 1002754fe60SDimitry Andric Elf_Word sh_size; // Size of section, in bytes 1012754fe60SDimitry Andric Elf_Word sh_link; // Section type-specific header table index link 1022754fe60SDimitry Andric Elf_Word sh_info; // Section type-specific extra information 1032754fe60SDimitry Andric Elf_Word sh_addralign;// Section address alignment 1042754fe60SDimitry Andric Elf_Word sh_entsize; // Size of records contained within the section 1052754fe60SDimitry Andric }; 1062754fe60SDimitry Andric 1072754fe60SDimitry Andric template<support::endianness target_endianness> 1082754fe60SDimitry Andric struct Elf_Shdr_Base<target_endianness, true> { 1092754fe60SDimitry Andric LLVM_ELF_IMPORT_TYPES(target_endianness, true) 1102754fe60SDimitry Andric Elf_Word sh_name; // Section name (index into string table) 1112754fe60SDimitry Andric Elf_Word sh_type; // Section type (SHT_*) 1122754fe60SDimitry Andric Elf_Xword sh_flags; // Section flags (SHF_*) 1132754fe60SDimitry Andric Elf_Addr sh_addr; // Address where section is to be loaded 1142754fe60SDimitry Andric Elf_Off sh_offset; // File offset of section data, in bytes 1152754fe60SDimitry Andric Elf_Xword sh_size; // Size of section, in bytes 1162754fe60SDimitry Andric Elf_Word sh_link; // Section type-specific header table index link 1172754fe60SDimitry Andric Elf_Word sh_info; // Section type-specific extra information 1182754fe60SDimitry Andric Elf_Xword sh_addralign;// Section address alignment 1192754fe60SDimitry Andric Elf_Xword sh_entsize; // Size of records contained within the section 1202754fe60SDimitry Andric }; 1212754fe60SDimitry Andric 1222754fe60SDimitry Andric template<support::endianness target_endianness, bool is64Bits> 1232754fe60SDimitry Andric struct Elf_Shdr_Impl : Elf_Shdr_Base<target_endianness, is64Bits> { 1242754fe60SDimitry Andric using Elf_Shdr_Base<target_endianness, is64Bits>::sh_entsize; 1252754fe60SDimitry Andric using Elf_Shdr_Base<target_endianness, is64Bits>::sh_size; 1262754fe60SDimitry Andric 1272754fe60SDimitry Andric /// @brief Get the number of entities this section contains if it has any. 1282754fe60SDimitry Andric unsigned getEntityCount() const { 1292754fe60SDimitry Andric if (sh_entsize == 0) 1302754fe60SDimitry Andric return 0; 1312754fe60SDimitry Andric return sh_size / sh_entsize; 1322754fe60SDimitry Andric } 1332754fe60SDimitry Andric }; 1342754fe60SDimitry Andric } 1352754fe60SDimitry Andric 1362754fe60SDimitry Andric namespace { 1372754fe60SDimitry Andric template<support::endianness target_endianness, bool is64Bits> 1382754fe60SDimitry Andric struct Elf_Sym_Base; 1392754fe60SDimitry Andric 1402754fe60SDimitry Andric template<support::endianness target_endianness> 1412754fe60SDimitry Andric struct Elf_Sym_Base<target_endianness, false> { 1422754fe60SDimitry Andric LLVM_ELF_IMPORT_TYPES(target_endianness, false) 1432754fe60SDimitry Andric Elf_Word st_name; // Symbol name (index into string table) 1442754fe60SDimitry Andric Elf_Addr st_value; // Value or address associated with the symbol 1452754fe60SDimitry Andric Elf_Word st_size; // Size of the symbol 1462754fe60SDimitry Andric unsigned char st_info; // Symbol's type and binding attributes 1472754fe60SDimitry Andric unsigned char st_other; // Must be zero; reserved 1482754fe60SDimitry Andric Elf_Half st_shndx; // Which section (header table index) it's defined in 1492754fe60SDimitry Andric }; 1502754fe60SDimitry Andric 1512754fe60SDimitry Andric template<support::endianness target_endianness> 1522754fe60SDimitry Andric struct Elf_Sym_Base<target_endianness, true> { 1532754fe60SDimitry Andric LLVM_ELF_IMPORT_TYPES(target_endianness, true) 1542754fe60SDimitry Andric Elf_Word st_name; // Symbol name (index into string table) 1552754fe60SDimitry Andric unsigned char st_info; // Symbol's type and binding attributes 1562754fe60SDimitry Andric unsigned char st_other; // Must be zero; reserved 1572754fe60SDimitry Andric Elf_Half st_shndx; // Which section (header table index) it's defined in 1582754fe60SDimitry Andric Elf_Addr st_value; // Value or address associated with the symbol 1592754fe60SDimitry Andric Elf_Xword st_size; // Size of the symbol 1602754fe60SDimitry Andric }; 1612754fe60SDimitry Andric 1622754fe60SDimitry Andric template<support::endianness target_endianness, bool is64Bits> 1632754fe60SDimitry Andric struct Elf_Sym_Impl : Elf_Sym_Base<target_endianness, is64Bits> { 1642754fe60SDimitry Andric using Elf_Sym_Base<target_endianness, is64Bits>::st_info; 1652754fe60SDimitry Andric 1662754fe60SDimitry Andric // These accessors and mutators correspond to the ELF32_ST_BIND, 1672754fe60SDimitry Andric // ELF32_ST_TYPE, and ELF32_ST_INFO macros defined in the ELF specification: 1682754fe60SDimitry Andric unsigned char getBinding() const { return st_info >> 4; } 1692754fe60SDimitry Andric unsigned char getType() const { return st_info & 0x0f; } 1702754fe60SDimitry Andric void setBinding(unsigned char b) { setBindingAndType(b, getType()); } 1712754fe60SDimitry Andric void setType(unsigned char t) { setBindingAndType(getBinding(), t); } 1722754fe60SDimitry Andric void setBindingAndType(unsigned char b, unsigned char t) { 1732754fe60SDimitry Andric st_info = (b << 4) + (t & 0x0f); 1742754fe60SDimitry Andric } 1752754fe60SDimitry Andric }; 1762754fe60SDimitry Andric } 1772754fe60SDimitry Andric 1782754fe60SDimitry Andric namespace { 1792754fe60SDimitry Andric template<support::endianness target_endianness, bool is64Bits> 1802754fe60SDimitry Andric class ELFObjectFile : public ObjectFile { 1812754fe60SDimitry Andric LLVM_ELF_IMPORT_TYPES(target_endianness, is64Bits) 1822754fe60SDimitry Andric 1832754fe60SDimitry Andric typedef Elf_Shdr_Impl<target_endianness, is64Bits> Elf_Shdr; 1842754fe60SDimitry Andric typedef Elf_Sym_Impl<target_endianness, is64Bits> Elf_Sym; 1852754fe60SDimitry Andric 1862754fe60SDimitry Andric struct Elf_Ehdr { 1872754fe60SDimitry Andric unsigned char e_ident[ELF::EI_NIDENT]; // ELF Identification bytes 1882754fe60SDimitry Andric Elf_Half e_type; // Type of file (see ET_*) 1892754fe60SDimitry Andric Elf_Half e_machine; // Required architecture for this file (see EM_*) 1902754fe60SDimitry Andric Elf_Word e_version; // Must be equal to 1 1912754fe60SDimitry Andric Elf_Addr e_entry; // Address to jump to in order to start program 1922754fe60SDimitry Andric Elf_Off e_phoff; // Program header table's file offset, in bytes 1932754fe60SDimitry Andric Elf_Off e_shoff; // Section header table's file offset, in bytes 1942754fe60SDimitry Andric Elf_Word e_flags; // Processor-specific flags 1952754fe60SDimitry Andric Elf_Half e_ehsize; // Size of ELF header, in bytes 1962754fe60SDimitry Andric Elf_Half e_phentsize;// Size of an entry in the program header table 1972754fe60SDimitry Andric Elf_Half e_phnum; // Number of entries in the program header table 1982754fe60SDimitry Andric Elf_Half e_shentsize;// Size of an entry in the section header table 1992754fe60SDimitry Andric Elf_Half e_shnum; // Number of entries in the section header table 2002754fe60SDimitry Andric Elf_Half e_shstrndx; // Section header table index of section name 2012754fe60SDimitry Andric // string table 2022754fe60SDimitry Andric bool checkMagic() const { 2032754fe60SDimitry Andric return (memcmp(e_ident, ELF::ElfMagic, strlen(ELF::ElfMagic))) == 0; 2042754fe60SDimitry Andric } 2052754fe60SDimitry Andric unsigned char getFileClass() const { return e_ident[ELF::EI_CLASS]; } 2062754fe60SDimitry Andric unsigned char getDataEncoding() const { return e_ident[ELF::EI_DATA]; } 2072754fe60SDimitry Andric }; 2082754fe60SDimitry Andric 2092754fe60SDimitry Andric typedef SmallVector<const Elf_Shdr*, 1> SymbolTableSections_t; 2102754fe60SDimitry Andric 2112754fe60SDimitry Andric const Elf_Ehdr *Header; 2122754fe60SDimitry Andric const Elf_Shdr *SectionHeaderTable; 2132754fe60SDimitry Andric const Elf_Shdr *dot_shstrtab_sec; // Section header string table. 2142754fe60SDimitry Andric const Elf_Shdr *dot_strtab_sec; // Symbol header string table. 2152754fe60SDimitry Andric SymbolTableSections_t SymbolTableSections; 2162754fe60SDimitry Andric 2172754fe60SDimitry Andric void validateSymbol(DataRefImpl Symb) const; 2182754fe60SDimitry Andric const Elf_Sym *getSymbol(DataRefImpl Symb) const; 2192754fe60SDimitry Andric const Elf_Shdr *getSection(DataRefImpl index) const; 2202754fe60SDimitry Andric const Elf_Shdr *getSection(uint16_t index) const; 2212754fe60SDimitry Andric const char *getString(uint16_t section, uint32_t offset) const; 2222754fe60SDimitry Andric const char *getString(const Elf_Shdr *section, uint32_t offset) const; 2232754fe60SDimitry Andric 2242754fe60SDimitry Andric protected: 22517a519f9SDimitry Andric virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const; 22617a519f9SDimitry Andric virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const; 22717a519f9SDimitry Andric virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const; 22817a519f9SDimitry Andric virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const; 22917a519f9SDimitry Andric virtual error_code getSymbolNMTypeChar(DataRefImpl Symb, char &Res) const; 23017a519f9SDimitry Andric virtual error_code isSymbolInternal(DataRefImpl Symb, bool &Res) const; 2312754fe60SDimitry Andric 23217a519f9SDimitry Andric virtual error_code getSectionNext(DataRefImpl Sec, SectionRef &Res) const; 23317a519f9SDimitry Andric virtual error_code getSectionName(DataRefImpl Sec, StringRef &Res) const; 23417a519f9SDimitry Andric virtual error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const; 23517a519f9SDimitry Andric virtual error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const; 23617a519f9SDimitry Andric virtual error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const; 23717a519f9SDimitry Andric virtual error_code isSectionText(DataRefImpl Sec, bool &Res) const; 23817a519f9SDimitry Andric virtual error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, 23917a519f9SDimitry Andric bool &Result) const; 2402754fe60SDimitry Andric 2412754fe60SDimitry Andric public: 24217a519f9SDimitry Andric ELFObjectFile(MemoryBuffer *Object, error_code &ec); 2432754fe60SDimitry Andric virtual symbol_iterator begin_symbols() const; 2442754fe60SDimitry Andric virtual symbol_iterator end_symbols() const; 2452754fe60SDimitry Andric virtual section_iterator begin_sections() const; 2462754fe60SDimitry Andric virtual section_iterator end_sections() const; 2472754fe60SDimitry Andric 2482754fe60SDimitry Andric virtual uint8_t getBytesInAddress() const; 2492754fe60SDimitry Andric virtual StringRef getFileFormatName() const; 2502754fe60SDimitry Andric virtual unsigned getArch() const; 2512754fe60SDimitry Andric }; 2522754fe60SDimitry Andric } // end namespace 2532754fe60SDimitry Andric 2542754fe60SDimitry Andric template<support::endianness target_endianness, bool is64Bits> 2552754fe60SDimitry Andric void ELFObjectFile<target_endianness, is64Bits> 2562754fe60SDimitry Andric ::validateSymbol(DataRefImpl Symb) const { 2572754fe60SDimitry Andric const Elf_Sym *symb = getSymbol(Symb); 2582754fe60SDimitry Andric const Elf_Shdr *SymbolTableSection = SymbolTableSections[Symb.d.b]; 2592754fe60SDimitry Andric // FIXME: We really need to do proper error handling in the case of an invalid 2602754fe60SDimitry Andric // input file. Because we don't use exceptions, I think we'll just pass 2612754fe60SDimitry Andric // an error object around. 2622754fe60SDimitry Andric if (!( symb 2632754fe60SDimitry Andric && SymbolTableSection 26417a519f9SDimitry Andric && symb >= (const Elf_Sym*)(base() 2652754fe60SDimitry Andric + SymbolTableSection->sh_offset) 26617a519f9SDimitry Andric && symb < (const Elf_Sym*)(base() 2672754fe60SDimitry Andric + SymbolTableSection->sh_offset 2682754fe60SDimitry Andric + SymbolTableSection->sh_size))) 2692754fe60SDimitry Andric // FIXME: Proper error handling. 2702754fe60SDimitry Andric report_fatal_error("Symb must point to a valid symbol!"); 2712754fe60SDimitry Andric } 2722754fe60SDimitry Andric 2732754fe60SDimitry Andric template<support::endianness target_endianness, bool is64Bits> 27417a519f9SDimitry Andric error_code ELFObjectFile<target_endianness, is64Bits> 27517a519f9SDimitry Andric ::getSymbolNext(DataRefImpl Symb, 27617a519f9SDimitry Andric SymbolRef &Result) const { 2772754fe60SDimitry Andric validateSymbol(Symb); 2782754fe60SDimitry Andric const Elf_Shdr *SymbolTableSection = SymbolTableSections[Symb.d.b]; 2792754fe60SDimitry Andric 2802754fe60SDimitry Andric ++Symb.d.a; 2812754fe60SDimitry Andric // Check to see if we are at the end of this symbol table. 2822754fe60SDimitry Andric if (Symb.d.a >= SymbolTableSection->getEntityCount()) { 2832754fe60SDimitry Andric // We are at the end. If there are other symbol tables, jump to them. 2842754fe60SDimitry Andric ++Symb.d.b; 2852754fe60SDimitry Andric Symb.d.a = 1; // The 0th symbol in ELF is fake. 2862754fe60SDimitry Andric // Otherwise return the terminator. 2872754fe60SDimitry Andric if (Symb.d.b >= SymbolTableSections.size()) { 2882754fe60SDimitry Andric Symb.d.a = std::numeric_limits<uint32_t>::max(); 2892754fe60SDimitry Andric Symb.d.b = std::numeric_limits<uint32_t>::max(); 2902754fe60SDimitry Andric } 2912754fe60SDimitry Andric } 2922754fe60SDimitry Andric 29317a519f9SDimitry Andric Result = SymbolRef(Symb, this); 29417a519f9SDimitry Andric return object_error::success; 2952754fe60SDimitry Andric } 2962754fe60SDimitry Andric 2972754fe60SDimitry Andric template<support::endianness target_endianness, bool is64Bits> 29817a519f9SDimitry Andric error_code ELFObjectFile<target_endianness, is64Bits> 29917a519f9SDimitry Andric ::getSymbolName(DataRefImpl Symb, 30017a519f9SDimitry Andric StringRef &Result) const { 3012754fe60SDimitry Andric validateSymbol(Symb); 3022754fe60SDimitry Andric const Elf_Sym *symb = getSymbol(Symb); 3032754fe60SDimitry Andric if (symb->st_name == 0) { 3042754fe60SDimitry Andric const Elf_Shdr *section = getSection(symb->st_shndx); 3052754fe60SDimitry Andric if (!section) 30617a519f9SDimitry Andric Result = ""; 30717a519f9SDimitry Andric else 30817a519f9SDimitry Andric Result = getString(dot_shstrtab_sec, section->sh_name); 30917a519f9SDimitry Andric return object_error::success; 3102754fe60SDimitry Andric } 3112754fe60SDimitry Andric 3122754fe60SDimitry Andric // Use the default symbol table name section. 31317a519f9SDimitry Andric Result = getString(dot_strtab_sec, symb->st_name); 31417a519f9SDimitry Andric return object_error::success; 3152754fe60SDimitry Andric } 3162754fe60SDimitry Andric 3172754fe60SDimitry Andric template<support::endianness target_endianness, bool is64Bits> 31817a519f9SDimitry Andric error_code ELFObjectFile<target_endianness, is64Bits> 31917a519f9SDimitry Andric ::getSymbolAddress(DataRefImpl Symb, 32017a519f9SDimitry Andric uint64_t &Result) const { 3212754fe60SDimitry Andric validateSymbol(Symb); 3222754fe60SDimitry Andric const Elf_Sym *symb = getSymbol(Symb); 3232754fe60SDimitry Andric const Elf_Shdr *Section; 3242754fe60SDimitry Andric switch (symb->st_shndx) { 3252754fe60SDimitry Andric case ELF::SHN_COMMON: 3262754fe60SDimitry Andric // Undefined symbols have no address yet. 32717a519f9SDimitry Andric case ELF::SHN_UNDEF: 32817a519f9SDimitry Andric Result = UnknownAddressOrSize; 32917a519f9SDimitry Andric return object_error::success; 33017a519f9SDimitry Andric case ELF::SHN_ABS: 33117a519f9SDimitry Andric Result = symb->st_value; 33217a519f9SDimitry Andric return object_error::success; 3332754fe60SDimitry Andric default: Section = getSection(symb->st_shndx); 3342754fe60SDimitry Andric } 3352754fe60SDimitry Andric 3362754fe60SDimitry Andric switch (symb->getType()) { 33717a519f9SDimitry Andric case ELF::STT_SECTION: 33817a519f9SDimitry Andric Result = Section ? Section->sh_addr : UnknownAddressOrSize; 33917a519f9SDimitry Andric return object_error::success; 3402754fe60SDimitry Andric case ELF::STT_FUNC: 3412754fe60SDimitry Andric case ELF::STT_OBJECT: 3422754fe60SDimitry Andric case ELF::STT_NOTYPE: 34317a519f9SDimitry Andric Result = symb->st_value; 34417a519f9SDimitry Andric return object_error::success; 34517a519f9SDimitry Andric default: 34617a519f9SDimitry Andric Result = UnknownAddressOrSize; 34717a519f9SDimitry Andric return object_error::success; 3482754fe60SDimitry Andric } 3492754fe60SDimitry Andric } 3502754fe60SDimitry Andric 3512754fe60SDimitry Andric template<support::endianness target_endianness, bool is64Bits> 35217a519f9SDimitry Andric error_code ELFObjectFile<target_endianness, is64Bits> 35317a519f9SDimitry Andric ::getSymbolSize(DataRefImpl Symb, 35417a519f9SDimitry Andric uint64_t &Result) const { 3552754fe60SDimitry Andric validateSymbol(Symb); 3562754fe60SDimitry Andric const Elf_Sym *symb = getSymbol(Symb); 3572754fe60SDimitry Andric if (symb->st_size == 0) 35817a519f9SDimitry Andric Result = UnknownAddressOrSize; 35917a519f9SDimitry Andric Result = symb->st_size; 36017a519f9SDimitry Andric return object_error::success; 3612754fe60SDimitry Andric } 3622754fe60SDimitry Andric 3632754fe60SDimitry Andric template<support::endianness target_endianness, bool is64Bits> 36417a519f9SDimitry Andric error_code ELFObjectFile<target_endianness, is64Bits> 36517a519f9SDimitry Andric ::getSymbolNMTypeChar(DataRefImpl Symb, 36617a519f9SDimitry Andric char &Result) const { 3672754fe60SDimitry Andric validateSymbol(Symb); 3682754fe60SDimitry Andric const Elf_Sym *symb = getSymbol(Symb); 3692754fe60SDimitry Andric const Elf_Shdr *Section = getSection(symb->st_shndx); 3702754fe60SDimitry Andric 3712754fe60SDimitry Andric char ret = '?'; 3722754fe60SDimitry Andric 3732754fe60SDimitry Andric if (Section) { 3742754fe60SDimitry Andric switch (Section->sh_type) { 3752754fe60SDimitry Andric case ELF::SHT_PROGBITS: 3762754fe60SDimitry Andric case ELF::SHT_DYNAMIC: 3772754fe60SDimitry Andric switch (Section->sh_flags) { 3782754fe60SDimitry Andric case (ELF::SHF_ALLOC | ELF::SHF_EXECINSTR): 3792754fe60SDimitry Andric ret = 't'; break; 3802754fe60SDimitry Andric case (ELF::SHF_ALLOC | ELF::SHF_WRITE): 3812754fe60SDimitry Andric ret = 'd'; break; 3822754fe60SDimitry Andric case ELF::SHF_ALLOC: 3832754fe60SDimitry Andric case (ELF::SHF_ALLOC | ELF::SHF_MERGE): 3842754fe60SDimitry Andric case (ELF::SHF_ALLOC | ELF::SHF_MERGE | ELF::SHF_STRINGS): 3852754fe60SDimitry Andric ret = 'r'; break; 3862754fe60SDimitry Andric } 3872754fe60SDimitry Andric break; 3882754fe60SDimitry Andric case ELF::SHT_NOBITS: ret = 'b'; 3892754fe60SDimitry Andric } 3902754fe60SDimitry Andric } 3912754fe60SDimitry Andric 3922754fe60SDimitry Andric switch (symb->st_shndx) { 3932754fe60SDimitry Andric case ELF::SHN_UNDEF: 3942754fe60SDimitry Andric if (ret == '?') 3952754fe60SDimitry Andric ret = 'U'; 3962754fe60SDimitry Andric break; 3972754fe60SDimitry Andric case ELF::SHN_ABS: ret = 'a'; break; 3982754fe60SDimitry Andric case ELF::SHN_COMMON: ret = 'c'; break; 3992754fe60SDimitry Andric } 4002754fe60SDimitry Andric 4012754fe60SDimitry Andric switch (symb->getBinding()) { 4022754fe60SDimitry Andric case ELF::STB_GLOBAL: ret = ::toupper(ret); break; 4032754fe60SDimitry Andric case ELF::STB_WEAK: 4042754fe60SDimitry Andric if (symb->st_shndx == ELF::SHN_UNDEF) 4052754fe60SDimitry Andric ret = 'w'; 4062754fe60SDimitry Andric else 4072754fe60SDimitry Andric if (symb->getType() == ELF::STT_OBJECT) 4082754fe60SDimitry Andric ret = 'V'; 4092754fe60SDimitry Andric else 4102754fe60SDimitry Andric ret = 'W'; 4112754fe60SDimitry Andric } 4122754fe60SDimitry Andric 41317a519f9SDimitry Andric if (ret == '?' && symb->getType() == ELF::STT_SECTION) { 41417a519f9SDimitry Andric StringRef name; 41517a519f9SDimitry Andric if (error_code ec = getSymbolName(Symb, name)) 41617a519f9SDimitry Andric return ec; 41717a519f9SDimitry Andric Result = StringSwitch<char>(name) 4182754fe60SDimitry Andric .StartsWith(".debug", 'N') 4192754fe60SDimitry Andric .StartsWith(".note", 'n'); 42017a519f9SDimitry Andric return object_error::success; 42117a519f9SDimitry Andric } 4222754fe60SDimitry Andric 42317a519f9SDimitry Andric Result = ret; 42417a519f9SDimitry Andric return object_error::success; 4252754fe60SDimitry Andric } 4262754fe60SDimitry Andric 4272754fe60SDimitry Andric template<support::endianness target_endianness, bool is64Bits> 42817a519f9SDimitry Andric error_code ELFObjectFile<target_endianness, is64Bits> 42917a519f9SDimitry Andric ::isSymbolInternal(DataRefImpl Symb, 43017a519f9SDimitry Andric bool &Result) const { 4312754fe60SDimitry Andric validateSymbol(Symb); 4322754fe60SDimitry Andric const Elf_Sym *symb = getSymbol(Symb); 4332754fe60SDimitry Andric 4342754fe60SDimitry Andric if ( symb->getType() == ELF::STT_FILE 4352754fe60SDimitry Andric || symb->getType() == ELF::STT_SECTION) 43617a519f9SDimitry Andric Result = true; 43717a519f9SDimitry Andric Result = false; 43817a519f9SDimitry Andric return object_error::success; 4392754fe60SDimitry Andric } 4402754fe60SDimitry Andric 4412754fe60SDimitry Andric template<support::endianness target_endianness, bool is64Bits> 44217a519f9SDimitry Andric error_code ELFObjectFile<target_endianness, is64Bits> 44317a519f9SDimitry Andric ::getSectionNext(DataRefImpl Sec, SectionRef &Result) const { 4442754fe60SDimitry Andric const uint8_t *sec = reinterpret_cast<const uint8_t *>(Sec.p); 4452754fe60SDimitry Andric sec += Header->e_shentsize; 4462754fe60SDimitry Andric Sec.p = reinterpret_cast<intptr_t>(sec); 44717a519f9SDimitry Andric Result = SectionRef(Sec, this); 44817a519f9SDimitry Andric return object_error::success; 4492754fe60SDimitry Andric } 4502754fe60SDimitry Andric 4512754fe60SDimitry Andric template<support::endianness target_endianness, bool is64Bits> 45217a519f9SDimitry Andric error_code ELFObjectFile<target_endianness, is64Bits> 45317a519f9SDimitry Andric ::getSectionName(DataRefImpl Sec, 45417a519f9SDimitry Andric StringRef &Result) const { 4552754fe60SDimitry Andric const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); 45617a519f9SDimitry Andric Result = StringRef(getString(dot_shstrtab_sec, sec->sh_name)); 45717a519f9SDimitry Andric return object_error::success; 4582754fe60SDimitry Andric } 4592754fe60SDimitry Andric 4602754fe60SDimitry Andric template<support::endianness target_endianness, bool is64Bits> 46117a519f9SDimitry Andric error_code ELFObjectFile<target_endianness, is64Bits> 46217a519f9SDimitry Andric ::getSectionAddress(DataRefImpl Sec, 46317a519f9SDimitry Andric uint64_t &Result) const { 4642754fe60SDimitry Andric const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); 46517a519f9SDimitry Andric Result = sec->sh_addr; 46617a519f9SDimitry Andric return object_error::success; 4672754fe60SDimitry Andric } 4682754fe60SDimitry Andric 4692754fe60SDimitry Andric template<support::endianness target_endianness, bool is64Bits> 47017a519f9SDimitry Andric error_code ELFObjectFile<target_endianness, is64Bits> 47117a519f9SDimitry Andric ::getSectionSize(DataRefImpl Sec, 47217a519f9SDimitry Andric uint64_t &Result) const { 4732754fe60SDimitry Andric const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); 47417a519f9SDimitry Andric Result = sec->sh_size; 47517a519f9SDimitry Andric return object_error::success; 4762754fe60SDimitry Andric } 4772754fe60SDimitry Andric 4782754fe60SDimitry Andric template<support::endianness target_endianness, bool is64Bits> 47917a519f9SDimitry Andric error_code ELFObjectFile<target_endianness, is64Bits> 48017a519f9SDimitry Andric ::getSectionContents(DataRefImpl Sec, 48117a519f9SDimitry Andric StringRef &Result) const { 4822754fe60SDimitry Andric const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); 48317a519f9SDimitry Andric const char *start = (const char*)base() + sec->sh_offset; 48417a519f9SDimitry Andric Result = StringRef(start, sec->sh_size); 48517a519f9SDimitry Andric return object_error::success; 4862754fe60SDimitry Andric } 4872754fe60SDimitry Andric 4882754fe60SDimitry Andric template<support::endianness target_endianness, bool is64Bits> 48917a519f9SDimitry Andric error_code ELFObjectFile<target_endianness, is64Bits> 49017a519f9SDimitry Andric ::isSectionText(DataRefImpl Sec, 49117a519f9SDimitry Andric bool &Result) const { 4922754fe60SDimitry Andric const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); 4932754fe60SDimitry Andric if (sec->sh_flags & ELF::SHF_EXECINSTR) 49417a519f9SDimitry Andric Result = true; 49517a519f9SDimitry Andric else 49617a519f9SDimitry Andric Result = false; 49717a519f9SDimitry Andric return object_error::success; 4982754fe60SDimitry Andric } 4992754fe60SDimitry Andric 5002754fe60SDimitry Andric template<support::endianness target_endianness, bool is64Bits> 50117a519f9SDimitry Andric error_code ELFObjectFile<target_endianness, is64Bits> 50217a519f9SDimitry Andric ::sectionContainsSymbol(DataRefImpl Sec, 50317a519f9SDimitry Andric DataRefImpl Symb, 50417a519f9SDimitry Andric bool &Result) const { 50517a519f9SDimitry Andric // FIXME: Unimplemented. 50617a519f9SDimitry Andric Result = false; 50717a519f9SDimitry Andric return object_error::success; 50817a519f9SDimitry Andric } 50917a519f9SDimitry Andric 51017a519f9SDimitry Andric template<support::endianness target_endianness, bool is64Bits> 51117a519f9SDimitry Andric ELFObjectFile<target_endianness, is64Bits>::ELFObjectFile(MemoryBuffer *Object 51217a519f9SDimitry Andric , error_code &ec) 51317a519f9SDimitry Andric : ObjectFile(Binary::isELF, Object, ec) 5142754fe60SDimitry Andric , SectionHeaderTable(0) 5152754fe60SDimitry Andric , dot_shstrtab_sec(0) 5162754fe60SDimitry Andric , dot_strtab_sec(0) { 51717a519f9SDimitry Andric Header = reinterpret_cast<const Elf_Ehdr *>(base()); 5182754fe60SDimitry Andric 5192754fe60SDimitry Andric if (Header->e_shoff == 0) 5202754fe60SDimitry Andric return; 5212754fe60SDimitry Andric 5222754fe60SDimitry Andric SectionHeaderTable = 52317a519f9SDimitry Andric reinterpret_cast<const Elf_Shdr *>(base() + Header->e_shoff); 5242754fe60SDimitry Andric uint32_t SectionTableSize = Header->e_shnum * Header->e_shentsize; 5252754fe60SDimitry Andric if (!( (const uint8_t *)SectionHeaderTable + SectionTableSize 52617a519f9SDimitry Andric <= base() + Data->getBufferSize())) 5272754fe60SDimitry Andric // FIXME: Proper error handling. 5282754fe60SDimitry Andric report_fatal_error("Section table goes past end of file!"); 5292754fe60SDimitry Andric 5302754fe60SDimitry Andric 5312754fe60SDimitry Andric // To find the symbol tables we walk the section table to find SHT_STMTAB. 5322754fe60SDimitry Andric for (const char *i = reinterpret_cast<const char *>(SectionHeaderTable), 5332754fe60SDimitry Andric *e = i + Header->e_shnum * Header->e_shentsize; 5342754fe60SDimitry Andric i != e; i += Header->e_shentsize) { 5352754fe60SDimitry Andric const Elf_Shdr *sh = reinterpret_cast<const Elf_Shdr*>(i); 5362754fe60SDimitry Andric if (sh->sh_type == ELF::SHT_SYMTAB) { 5372754fe60SDimitry Andric SymbolTableSections.push_back(sh); 5382754fe60SDimitry Andric } 5392754fe60SDimitry Andric } 5402754fe60SDimitry Andric 5412754fe60SDimitry Andric // Get string table sections. 5422754fe60SDimitry Andric dot_shstrtab_sec = getSection(Header->e_shstrndx); 5432754fe60SDimitry Andric if (dot_shstrtab_sec) { 5442754fe60SDimitry Andric // Verify that the last byte in the string table in a null. 54517a519f9SDimitry Andric if (((const char*)base() + dot_shstrtab_sec->sh_offset) 5462754fe60SDimitry Andric [dot_shstrtab_sec->sh_size - 1] != 0) 5472754fe60SDimitry Andric // FIXME: Proper error handling. 5482754fe60SDimitry Andric report_fatal_error("String table must end with a null terminator!"); 5492754fe60SDimitry Andric } 5502754fe60SDimitry Andric 5512754fe60SDimitry Andric // Merge this into the above loop. 5522754fe60SDimitry Andric for (const char *i = reinterpret_cast<const char *>(SectionHeaderTable), 5532754fe60SDimitry Andric *e = i + Header->e_shnum * Header->e_shentsize; 5542754fe60SDimitry Andric i != e; i += Header->e_shentsize) { 5552754fe60SDimitry Andric const Elf_Shdr *sh = reinterpret_cast<const Elf_Shdr*>(i); 5562754fe60SDimitry Andric if (sh->sh_type == ELF::SHT_STRTAB) { 5572754fe60SDimitry Andric StringRef SectionName(getString(dot_shstrtab_sec, sh->sh_name)); 5582754fe60SDimitry Andric if (SectionName == ".strtab") { 5592754fe60SDimitry Andric if (dot_strtab_sec != 0) 5602754fe60SDimitry Andric // FIXME: Proper error handling. 5612754fe60SDimitry Andric report_fatal_error("Already found section named .strtab!"); 5622754fe60SDimitry Andric dot_strtab_sec = sh; 56317a519f9SDimitry Andric const char *dot_strtab = (const char*)base() + sh->sh_offset; 5642754fe60SDimitry Andric if (dot_strtab[sh->sh_size - 1] != 0) 5652754fe60SDimitry Andric // FIXME: Proper error handling. 5662754fe60SDimitry Andric report_fatal_error("String table must end with a null terminator!"); 5672754fe60SDimitry Andric } 5682754fe60SDimitry Andric } 5692754fe60SDimitry Andric } 5702754fe60SDimitry Andric } 5712754fe60SDimitry Andric 5722754fe60SDimitry Andric template<support::endianness target_endianness, bool is64Bits> 5732754fe60SDimitry Andric ObjectFile::symbol_iterator ELFObjectFile<target_endianness, is64Bits> 5742754fe60SDimitry Andric ::begin_symbols() const { 5752754fe60SDimitry Andric DataRefImpl SymbolData; 5762754fe60SDimitry Andric memset(&SymbolData, 0, sizeof(SymbolData)); 5772754fe60SDimitry Andric if (SymbolTableSections.size() == 0) { 5782754fe60SDimitry Andric SymbolData.d.a = std::numeric_limits<uint32_t>::max(); 5792754fe60SDimitry Andric SymbolData.d.b = std::numeric_limits<uint32_t>::max(); 5802754fe60SDimitry Andric } else { 5812754fe60SDimitry Andric SymbolData.d.a = 1; // The 0th symbol in ELF is fake. 5822754fe60SDimitry Andric SymbolData.d.b = 0; 5832754fe60SDimitry Andric } 5842754fe60SDimitry Andric return symbol_iterator(SymbolRef(SymbolData, this)); 5852754fe60SDimitry Andric } 5862754fe60SDimitry Andric 5872754fe60SDimitry Andric template<support::endianness target_endianness, bool is64Bits> 5882754fe60SDimitry Andric ObjectFile::symbol_iterator ELFObjectFile<target_endianness, is64Bits> 5892754fe60SDimitry Andric ::end_symbols() const { 5902754fe60SDimitry Andric DataRefImpl SymbolData; 5912754fe60SDimitry Andric memset(&SymbolData, 0, sizeof(SymbolData)); 5922754fe60SDimitry Andric SymbolData.d.a = std::numeric_limits<uint32_t>::max(); 5932754fe60SDimitry Andric SymbolData.d.b = std::numeric_limits<uint32_t>::max(); 5942754fe60SDimitry Andric return symbol_iterator(SymbolRef(SymbolData, this)); 5952754fe60SDimitry Andric } 5962754fe60SDimitry Andric 5972754fe60SDimitry Andric template<support::endianness target_endianness, bool is64Bits> 5982754fe60SDimitry Andric ObjectFile::section_iterator ELFObjectFile<target_endianness, is64Bits> 5992754fe60SDimitry Andric ::begin_sections() const { 6002754fe60SDimitry Andric DataRefImpl ret; 6013b0f4066SDimitry Andric memset(&ret, 0, sizeof(DataRefImpl)); 60217a519f9SDimitry Andric ret.p = reinterpret_cast<intptr_t>(base() + Header->e_shoff); 6032754fe60SDimitry Andric return section_iterator(SectionRef(ret, this)); 6042754fe60SDimitry Andric } 6052754fe60SDimitry Andric 6062754fe60SDimitry Andric template<support::endianness target_endianness, bool is64Bits> 6072754fe60SDimitry Andric ObjectFile::section_iterator ELFObjectFile<target_endianness, is64Bits> 6082754fe60SDimitry Andric ::end_sections() const { 6092754fe60SDimitry Andric DataRefImpl ret; 6103b0f4066SDimitry Andric memset(&ret, 0, sizeof(DataRefImpl)); 61117a519f9SDimitry Andric ret.p = reinterpret_cast<intptr_t>(base() 6122754fe60SDimitry Andric + Header->e_shoff 6132754fe60SDimitry Andric + (Header->e_shentsize * Header->e_shnum)); 6142754fe60SDimitry Andric return section_iterator(SectionRef(ret, this)); 6152754fe60SDimitry Andric } 6162754fe60SDimitry Andric 6172754fe60SDimitry Andric template<support::endianness target_endianness, bool is64Bits> 6182754fe60SDimitry Andric uint8_t ELFObjectFile<target_endianness, is64Bits>::getBytesInAddress() const { 6192754fe60SDimitry Andric return is64Bits ? 8 : 4; 6202754fe60SDimitry Andric } 6212754fe60SDimitry Andric 6222754fe60SDimitry Andric template<support::endianness target_endianness, bool is64Bits> 6232754fe60SDimitry Andric StringRef ELFObjectFile<target_endianness, is64Bits> 6242754fe60SDimitry Andric ::getFileFormatName() const { 6252754fe60SDimitry Andric switch(Header->e_ident[ELF::EI_CLASS]) { 6262754fe60SDimitry Andric case ELF::ELFCLASS32: 6272754fe60SDimitry Andric switch(Header->e_machine) { 6282754fe60SDimitry Andric case ELF::EM_386: 6292754fe60SDimitry Andric return "ELF32-i386"; 6302754fe60SDimitry Andric case ELF::EM_X86_64: 6312754fe60SDimitry Andric return "ELF32-x86-64"; 6322754fe60SDimitry Andric default: 6332754fe60SDimitry Andric return "ELF32-unknown"; 6342754fe60SDimitry Andric } 6352754fe60SDimitry Andric case ELF::ELFCLASS64: 6362754fe60SDimitry Andric switch(Header->e_machine) { 6372754fe60SDimitry Andric case ELF::EM_386: 6382754fe60SDimitry Andric return "ELF64-i386"; 6392754fe60SDimitry Andric case ELF::EM_X86_64: 6402754fe60SDimitry Andric return "ELF64-x86-64"; 6412754fe60SDimitry Andric default: 6422754fe60SDimitry Andric return "ELF64-unknown"; 6432754fe60SDimitry Andric } 6442754fe60SDimitry Andric default: 6452754fe60SDimitry Andric // FIXME: Proper error handling. 6462754fe60SDimitry Andric report_fatal_error("Invalid ELFCLASS!"); 6472754fe60SDimitry Andric } 6482754fe60SDimitry Andric } 6492754fe60SDimitry Andric 6502754fe60SDimitry Andric template<support::endianness target_endianness, bool is64Bits> 6512754fe60SDimitry Andric unsigned ELFObjectFile<target_endianness, is64Bits>::getArch() const { 6522754fe60SDimitry Andric switch(Header->e_machine) { 6532754fe60SDimitry Andric case ELF::EM_386: 6542754fe60SDimitry Andric return Triple::x86; 6552754fe60SDimitry Andric case ELF::EM_X86_64: 6562754fe60SDimitry Andric return Triple::x86_64; 6572754fe60SDimitry Andric default: 6582754fe60SDimitry Andric return Triple::UnknownArch; 6592754fe60SDimitry Andric } 6602754fe60SDimitry Andric } 6612754fe60SDimitry Andric 6622754fe60SDimitry Andric template<support::endianness target_endianness, bool is64Bits> 6632754fe60SDimitry Andric const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Sym * 6642754fe60SDimitry Andric ELFObjectFile<target_endianness, is64Bits>::getSymbol(DataRefImpl Symb) const { 6652754fe60SDimitry Andric const Elf_Shdr *sec = SymbolTableSections[Symb.d.b]; 6662754fe60SDimitry Andric return reinterpret_cast<const Elf_Sym *>( 66717a519f9SDimitry Andric base() 6682754fe60SDimitry Andric + sec->sh_offset 6692754fe60SDimitry Andric + (Symb.d.a * sec->sh_entsize)); 6702754fe60SDimitry Andric } 6712754fe60SDimitry Andric 6722754fe60SDimitry Andric template<support::endianness target_endianness, bool is64Bits> 6732754fe60SDimitry Andric const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Shdr * 6742754fe60SDimitry Andric ELFObjectFile<target_endianness, is64Bits>::getSection(DataRefImpl Symb) const { 6752754fe60SDimitry Andric const Elf_Shdr *sec = getSection(Symb.d.b); 6762754fe60SDimitry Andric if (sec->sh_type != ELF::SHT_SYMTAB) 6772754fe60SDimitry Andric // FIXME: Proper error handling. 6782754fe60SDimitry Andric report_fatal_error("Invalid symbol table section!"); 6792754fe60SDimitry Andric return sec; 6802754fe60SDimitry Andric } 6812754fe60SDimitry Andric 6822754fe60SDimitry Andric template<support::endianness target_endianness, bool is64Bits> 6832754fe60SDimitry Andric const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Shdr * 6842754fe60SDimitry Andric ELFObjectFile<target_endianness, is64Bits>::getSection(uint16_t index) const { 6852754fe60SDimitry Andric if (index == 0 || index >= ELF::SHN_LORESERVE) 6862754fe60SDimitry Andric return 0; 6872754fe60SDimitry Andric if (!SectionHeaderTable || index >= Header->e_shnum) 6882754fe60SDimitry Andric // FIXME: Proper error handling. 6892754fe60SDimitry Andric report_fatal_error("Invalid section index!"); 6902754fe60SDimitry Andric 6912754fe60SDimitry Andric return reinterpret_cast<const Elf_Shdr *>( 6922754fe60SDimitry Andric reinterpret_cast<const char *>(SectionHeaderTable) 6932754fe60SDimitry Andric + (index * Header->e_shentsize)); 6942754fe60SDimitry Andric } 6952754fe60SDimitry Andric 6962754fe60SDimitry Andric template<support::endianness target_endianness, bool is64Bits> 6972754fe60SDimitry Andric const char *ELFObjectFile<target_endianness, is64Bits> 6982754fe60SDimitry Andric ::getString(uint16_t section, 6992754fe60SDimitry Andric ELF::Elf32_Word offset) const { 7002754fe60SDimitry Andric return getString(getSection(section), offset); 7012754fe60SDimitry Andric } 7022754fe60SDimitry Andric 7032754fe60SDimitry Andric template<support::endianness target_endianness, bool is64Bits> 7042754fe60SDimitry Andric const char *ELFObjectFile<target_endianness, is64Bits> 7052754fe60SDimitry Andric ::getString(const Elf_Shdr *section, 7062754fe60SDimitry Andric ELF::Elf32_Word offset) const { 7072754fe60SDimitry Andric assert(section && section->sh_type == ELF::SHT_STRTAB && "Invalid section!"); 7082754fe60SDimitry Andric if (offset >= section->sh_size) 7092754fe60SDimitry Andric // FIXME: Proper error handling. 71017a519f9SDimitry Andric report_fatal_error("Symbol name offset outside of string table!"); 71117a519f9SDimitry Andric return (const char *)base() + section->sh_offset + offset; 7122754fe60SDimitry Andric } 7132754fe60SDimitry Andric 7142754fe60SDimitry Andric // EI_CLASS, EI_DATA. 7152754fe60SDimitry Andric static std::pair<unsigned char, unsigned char> 7162754fe60SDimitry Andric getElfArchType(MemoryBuffer *Object) { 7172754fe60SDimitry Andric if (Object->getBufferSize() < ELF::EI_NIDENT) 7182754fe60SDimitry Andric return std::make_pair((uint8_t)ELF::ELFCLASSNONE,(uint8_t)ELF::ELFDATANONE); 7192754fe60SDimitry Andric return std::make_pair( (uint8_t)Object->getBufferStart()[ELF::EI_CLASS] 7202754fe60SDimitry Andric , (uint8_t)Object->getBufferStart()[ELF::EI_DATA]); 7212754fe60SDimitry Andric } 7222754fe60SDimitry Andric 7232754fe60SDimitry Andric namespace llvm { 7242754fe60SDimitry Andric 7252754fe60SDimitry Andric ObjectFile *ObjectFile::createELFObjectFile(MemoryBuffer *Object) { 7262754fe60SDimitry Andric std::pair<unsigned char, unsigned char> Ident = getElfArchType(Object); 72717a519f9SDimitry Andric error_code ec; 7282754fe60SDimitry Andric if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2LSB) 72917a519f9SDimitry Andric return new ELFObjectFile<support::little, false>(Object, ec); 7302754fe60SDimitry Andric else if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2MSB) 73117a519f9SDimitry Andric return new ELFObjectFile<support::big, false>(Object, ec); 7322754fe60SDimitry Andric else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2LSB) 73317a519f9SDimitry Andric return new ELFObjectFile<support::little, true>(Object, ec); 7342754fe60SDimitry Andric else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2MSB) 73517a519f9SDimitry Andric return new ELFObjectFile<support::big, true>(Object, ec); 7362754fe60SDimitry Andric // FIXME: Proper error handling. 7372754fe60SDimitry Andric report_fatal_error("Not an ELF object file!"); 7382754fe60SDimitry Andric } 7392754fe60SDimitry Andric 7402754fe60SDimitry Andric } // end namespace llvm 741