1b60a18deSMichael J. Spencer //===- ELFObjectFile.cpp - ELF object file implementation -------*- C++ -*-===// 2b60a18deSMichael J. Spencer // 3b60a18deSMichael J. Spencer // The LLVM Compiler Infrastructure 4b60a18deSMichael J. Spencer // 5b60a18deSMichael J. Spencer // This file is distributed under the University of Illinois Open Source 6b60a18deSMichael J. Spencer // License. See LICENSE.TXT for details. 7b60a18deSMichael J. Spencer // 8b60a18deSMichael J. Spencer //===----------------------------------------------------------------------===// 9b60a18deSMichael J. Spencer // 10b60a18deSMichael J. Spencer // This file defines the ELFObjectFile class. 11b60a18deSMichael J. Spencer // 12b60a18deSMichael J. Spencer //===----------------------------------------------------------------------===// 13b60a18deSMichael J. Spencer 14b60a18deSMichael J. Spencer #include "llvm/ADT/SmallVector.h" 15b60a18deSMichael J. Spencer #include "llvm/ADT/StringSwitch.h" 16b60a18deSMichael J. Spencer #include "llvm/ADT/Triple.h" 17b60a18deSMichael J. Spencer #include "llvm/Object/ObjectFile.h" 18b60a18deSMichael J. Spencer #include "llvm/Support/ELF.h" 19b60a18deSMichael J. Spencer #include "llvm/Support/Endian.h" 20b60a18deSMichael J. Spencer #include "llvm/Support/ErrorHandling.h" 21b60a18deSMichael J. Spencer #include "llvm/Support/MemoryBuffer.h" 22b60a18deSMichael J. Spencer #include <limits> 23b60a18deSMichael J. Spencer #include <utility> 24b60a18deSMichael J. Spencer 25b60a18deSMichael J. Spencer using namespace llvm; 26b60a18deSMichael J. Spencer using namespace object; 27b60a18deSMichael J. Spencer 28b60a18deSMichael J. Spencer // Templates to choose Elf_Addr and Elf_Off depending on is64Bits. 29b60a18deSMichael J. Spencer namespace { 30b60a18deSMichael J. Spencer template<support::endianness target_endianness> 31b60a18deSMichael J. Spencer struct ELFDataTypeTypedefHelperCommon { 32b60a18deSMichael J. Spencer typedef support::detail::packed_endian_specific_integral 33b60a18deSMichael J. Spencer <uint16_t, target_endianness, support::aligned> Elf_Half; 34b60a18deSMichael J. Spencer typedef support::detail::packed_endian_specific_integral 35b60a18deSMichael J. Spencer <uint32_t, target_endianness, support::aligned> Elf_Word; 36b60a18deSMichael J. Spencer typedef support::detail::packed_endian_specific_integral 37b60a18deSMichael J. Spencer <int32_t, target_endianness, support::aligned> Elf_Sword; 38b60a18deSMichael J. Spencer typedef support::detail::packed_endian_specific_integral 39b60a18deSMichael J. Spencer <uint64_t, target_endianness, support::aligned> Elf_Xword; 40b60a18deSMichael J. Spencer typedef support::detail::packed_endian_specific_integral 41b60a18deSMichael J. Spencer <int64_t, target_endianness, support::aligned> Elf_Sxword; 42b60a18deSMichael J. Spencer }; 43b60a18deSMichael J. Spencer } 44b60a18deSMichael J. Spencer 45b60a18deSMichael J. Spencer namespace { 46b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 47b60a18deSMichael J. Spencer struct ELFDataTypeTypedefHelper; 48b60a18deSMichael J. Spencer 49b60a18deSMichael J. Spencer /// ELF 32bit types. 50b60a18deSMichael J. Spencer template<support::endianness target_endianness> 51b60a18deSMichael J. Spencer struct ELFDataTypeTypedefHelper<target_endianness, false> 52b60a18deSMichael J. Spencer : ELFDataTypeTypedefHelperCommon<target_endianness> { 53b60a18deSMichael J. Spencer typedef support::detail::packed_endian_specific_integral 54b60a18deSMichael J. Spencer <uint32_t, target_endianness, support::aligned> Elf_Addr; 55b60a18deSMichael J. Spencer typedef support::detail::packed_endian_specific_integral 56b60a18deSMichael J. Spencer <uint32_t, target_endianness, support::aligned> Elf_Off; 57b60a18deSMichael J. Spencer }; 58b60a18deSMichael J. Spencer 59b60a18deSMichael J. Spencer /// ELF 64bit types. 60b60a18deSMichael J. Spencer template<support::endianness target_endianness> 61b60a18deSMichael J. Spencer struct ELFDataTypeTypedefHelper<target_endianness, true> 62b60a18deSMichael J. Spencer : ELFDataTypeTypedefHelperCommon<target_endianness>{ 63b60a18deSMichael J. Spencer typedef support::detail::packed_endian_specific_integral 64b60a18deSMichael J. Spencer <uint64_t, target_endianness, support::aligned> Elf_Addr; 65b60a18deSMichael J. Spencer typedef support::detail::packed_endian_specific_integral 66b60a18deSMichael J. Spencer <uint64_t, target_endianness, support::aligned> Elf_Off; 67b60a18deSMichael J. Spencer }; 68b60a18deSMichael J. Spencer } 69b60a18deSMichael J. Spencer 70b60a18deSMichael J. Spencer // I really don't like doing this, but the alternative is copypasta. 71b60a18deSMichael J. Spencer #define LLVM_ELF_IMPORT_TYPES(target_endianness, is64Bits) \ 72b60a18deSMichael J. Spencer typedef typename \ 73b60a18deSMichael J. Spencer ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Addr Elf_Addr; \ 74b60a18deSMichael J. Spencer typedef typename \ 75b60a18deSMichael J. Spencer ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Off Elf_Off; \ 76b60a18deSMichael J. Spencer typedef typename \ 77b60a18deSMichael J. Spencer ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Half Elf_Half; \ 78b60a18deSMichael J. Spencer typedef typename \ 79b60a18deSMichael J. Spencer ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Word Elf_Word; \ 80b60a18deSMichael J. Spencer typedef typename \ 81b60a18deSMichael J. Spencer ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Sword Elf_Sword; \ 82b60a18deSMichael J. Spencer typedef typename \ 83b60a18deSMichael J. Spencer ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Xword Elf_Xword; \ 84b60a18deSMichael J. Spencer typedef typename \ 85b60a18deSMichael J. Spencer ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Sxword Elf_Sxword; 86b60a18deSMichael J. Spencer 87b60a18deSMichael J. Spencer // Section header. 88b60a18deSMichael J. Spencer namespace { 89b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 90b60a18deSMichael J. Spencer struct Elf_Shdr_Base; 91b60a18deSMichael J. Spencer 92b60a18deSMichael J. Spencer template<support::endianness target_endianness> 93b60a18deSMichael J. Spencer struct Elf_Shdr_Base<target_endianness, false> { 94b60a18deSMichael J. Spencer LLVM_ELF_IMPORT_TYPES(target_endianness, false) 95b60a18deSMichael J. Spencer Elf_Word sh_name; // Section name (index into string table) 96b60a18deSMichael J. Spencer Elf_Word sh_type; // Section type (SHT_*) 97b60a18deSMichael J. Spencer Elf_Word sh_flags; // Section flags (SHF_*) 98b60a18deSMichael J. Spencer Elf_Addr sh_addr; // Address where section is to be loaded 99b60a18deSMichael J. Spencer Elf_Off sh_offset; // File offset of section data, in bytes 100b60a18deSMichael J. Spencer Elf_Word sh_size; // Size of section, in bytes 101b60a18deSMichael J. Spencer Elf_Word sh_link; // Section type-specific header table index link 102b60a18deSMichael J. Spencer Elf_Word sh_info; // Section type-specific extra information 103b60a18deSMichael J. Spencer Elf_Word sh_addralign;// Section address alignment 104b60a18deSMichael J. Spencer Elf_Word sh_entsize; // Size of records contained within the section 105b60a18deSMichael J. Spencer }; 106b60a18deSMichael J. Spencer 107b60a18deSMichael J. Spencer template<support::endianness target_endianness> 108b60a18deSMichael J. Spencer struct Elf_Shdr_Base<target_endianness, true> { 109b60a18deSMichael J. Spencer LLVM_ELF_IMPORT_TYPES(target_endianness, true) 110b60a18deSMichael J. Spencer Elf_Word sh_name; // Section name (index into string table) 111b60a18deSMichael J. Spencer Elf_Word sh_type; // Section type (SHT_*) 112b60a18deSMichael J. Spencer Elf_Xword sh_flags; // Section flags (SHF_*) 113b60a18deSMichael J. Spencer Elf_Addr sh_addr; // Address where section is to be loaded 114b60a18deSMichael J. Spencer Elf_Off sh_offset; // File offset of section data, in bytes 115b60a18deSMichael J. Spencer Elf_Xword sh_size; // Size of section, in bytes 116b60a18deSMichael J. Spencer Elf_Word sh_link; // Section type-specific header table index link 117b60a18deSMichael J. Spencer Elf_Word sh_info; // Section type-specific extra information 118b60a18deSMichael J. Spencer Elf_Xword sh_addralign;// Section address alignment 119b60a18deSMichael J. Spencer Elf_Xword sh_entsize; // Size of records contained within the section 120b60a18deSMichael J. Spencer }; 121b60a18deSMichael J. Spencer 122b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 123b60a18deSMichael J. Spencer struct Elf_Shdr_Impl : Elf_Shdr_Base<target_endianness, is64Bits> { 124b60a18deSMichael J. Spencer using Elf_Shdr_Base<target_endianness, is64Bits>::sh_entsize; 125b60a18deSMichael J. Spencer using Elf_Shdr_Base<target_endianness, is64Bits>::sh_size; 126b60a18deSMichael J. Spencer 127b60a18deSMichael J. Spencer /// @brief Get the number of entities this section contains if it has any. 128b60a18deSMichael J. Spencer unsigned getEntityCount() const { 129b60a18deSMichael J. Spencer if (sh_entsize == 0) 130b60a18deSMichael J. Spencer return 0; 131b60a18deSMichael J. Spencer return sh_size / sh_entsize; 132b60a18deSMichael J. Spencer } 133b60a18deSMichael J. Spencer }; 134b60a18deSMichael J. Spencer } 135b60a18deSMichael J. Spencer 136b60a18deSMichael J. Spencer namespace { 137b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 138b60a18deSMichael J. Spencer struct Elf_Sym_Base; 139b60a18deSMichael J. Spencer 140b60a18deSMichael J. Spencer template<support::endianness target_endianness> 141b60a18deSMichael J. Spencer struct Elf_Sym_Base<target_endianness, false> { 142b60a18deSMichael J. Spencer LLVM_ELF_IMPORT_TYPES(target_endianness, false) 143b60a18deSMichael J. Spencer Elf_Word st_name; // Symbol name (index into string table) 144b60a18deSMichael J. Spencer Elf_Addr st_value; // Value or address associated with the symbol 145b60a18deSMichael J. Spencer Elf_Word st_size; // Size of the symbol 146b60a18deSMichael J. Spencer unsigned char st_info; // Symbol's type and binding attributes 147b60a18deSMichael J. Spencer unsigned char st_other; // Must be zero; reserved 148b60a18deSMichael J. Spencer Elf_Half st_shndx; // Which section (header table index) it's defined in 149b60a18deSMichael J. Spencer }; 150b60a18deSMichael J. Spencer 151b60a18deSMichael J. Spencer template<support::endianness target_endianness> 152b60a18deSMichael J. Spencer struct Elf_Sym_Base<target_endianness, true> { 153b60a18deSMichael J. Spencer LLVM_ELF_IMPORT_TYPES(target_endianness, true) 154b60a18deSMichael J. Spencer Elf_Word st_name; // Symbol name (index into string table) 155b60a18deSMichael J. Spencer unsigned char st_info; // Symbol's type and binding attributes 156b60a18deSMichael J. Spencer unsigned char st_other; // Must be zero; reserved 157b60a18deSMichael J. Spencer Elf_Half st_shndx; // Which section (header table index) it's defined in 158b60a18deSMichael J. Spencer Elf_Addr st_value; // Value or address associated with the symbol 159b60a18deSMichael J. Spencer Elf_Xword st_size; // Size of the symbol 160b60a18deSMichael J. Spencer }; 161b60a18deSMichael J. Spencer 162b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 163b60a18deSMichael J. Spencer struct Elf_Sym_Impl : Elf_Sym_Base<target_endianness, is64Bits> { 164b60a18deSMichael J. Spencer using Elf_Sym_Base<target_endianness, is64Bits>::st_info; 165b60a18deSMichael J. Spencer 166b60a18deSMichael J. Spencer // These accessors and mutators correspond to the ELF32_ST_BIND, 167b60a18deSMichael J. Spencer // ELF32_ST_TYPE, and ELF32_ST_INFO macros defined in the ELF specification: 168b60a18deSMichael J. Spencer unsigned char getBinding() const { return st_info >> 4; } 169b60a18deSMichael J. Spencer unsigned char getType() const { return st_info & 0x0f; } 170b60a18deSMichael J. Spencer void setBinding(unsigned char b) { setBindingAndType(b, getType()); } 171b60a18deSMichael J. Spencer void setType(unsigned char t) { setBindingAndType(getBinding(), t); } 172b60a18deSMichael J. Spencer void setBindingAndType(unsigned char b, unsigned char t) { 173b60a18deSMichael J. Spencer st_info = (b << 4) + (t & 0x0f); 174b60a18deSMichael J. Spencer } 175b60a18deSMichael J. Spencer }; 176b60a18deSMichael J. Spencer } 177b60a18deSMichael J. Spencer 178b60a18deSMichael J. Spencer namespace { 179b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 180b60a18deSMichael J. Spencer class ELFObjectFile : public ObjectFile { 181b60a18deSMichael J. Spencer LLVM_ELF_IMPORT_TYPES(target_endianness, is64Bits) 182b60a18deSMichael J. Spencer 183b60a18deSMichael J. Spencer typedef Elf_Shdr_Impl<target_endianness, is64Bits> Elf_Shdr; 184b60a18deSMichael J. Spencer typedef Elf_Sym_Impl<target_endianness, is64Bits> Elf_Sym; 185b60a18deSMichael J. Spencer 186b60a18deSMichael J. Spencer struct Elf_Ehdr { 187b60a18deSMichael J. Spencer unsigned char e_ident[ELF::EI_NIDENT]; // ELF Identification bytes 188b60a18deSMichael J. Spencer Elf_Half e_type; // Type of file (see ET_*) 189b60a18deSMichael J. Spencer Elf_Half e_machine; // Required architecture for this file (see EM_*) 190b60a18deSMichael J. Spencer Elf_Word e_version; // Must be equal to 1 191b60a18deSMichael J. Spencer Elf_Addr e_entry; // Address to jump to in order to start program 192b60a18deSMichael J. Spencer Elf_Off e_phoff; // Program header table's file offset, in bytes 193b60a18deSMichael J. Spencer Elf_Off e_shoff; // Section header table's file offset, in bytes 194b60a18deSMichael J. Spencer Elf_Word e_flags; // Processor-specific flags 195b60a18deSMichael J. Spencer Elf_Half e_ehsize; // Size of ELF header, in bytes 196b60a18deSMichael J. Spencer Elf_Half e_phentsize;// Size of an entry in the program header table 197b60a18deSMichael J. Spencer Elf_Half e_phnum; // Number of entries in the program header table 198b60a18deSMichael J. Spencer Elf_Half e_shentsize;// Size of an entry in the section header table 199b60a18deSMichael J. Spencer Elf_Half e_shnum; // Number of entries in the section header table 200b60a18deSMichael J. Spencer Elf_Half e_shstrndx; // Section header table index of section name 201b60a18deSMichael J. Spencer // string table 202b60a18deSMichael J. Spencer bool checkMagic() const { 203b60a18deSMichael J. Spencer return (memcmp(e_ident, ELF::ElfMagic, strlen(ELF::ElfMagic))) == 0; 204b60a18deSMichael J. Spencer } 205b60a18deSMichael J. Spencer unsigned char getFileClass() const { return e_ident[ELF::EI_CLASS]; } 206b60a18deSMichael J. Spencer unsigned char getDataEncoding() const { return e_ident[ELF::EI_DATA]; } 207b60a18deSMichael J. Spencer }; 208b60a18deSMichael J. Spencer 209b60a18deSMichael J. Spencer typedef SmallVector<const Elf_Shdr*, 1> SymbolTableSections_t; 210b60a18deSMichael J. Spencer 211b60a18deSMichael J. Spencer const Elf_Ehdr *Header; 212b60a18deSMichael J. Spencer const Elf_Shdr *SectionHeaderTable; 213b60a18deSMichael J. Spencer const Elf_Shdr *dot_shstrtab_sec; // Section header string table. 214b60a18deSMichael J. Spencer const Elf_Shdr *dot_strtab_sec; // Symbol header string table. 215b60a18deSMichael J. Spencer SymbolTableSections_t SymbolTableSections; 216b60a18deSMichael J. Spencer 217b60a18deSMichael J. Spencer void validateSymbol(DataRefImpl Symb) const; 218b60a18deSMichael J. Spencer const Elf_Sym *getSymbol(DataRefImpl Symb) const; 219b60a18deSMichael J. Spencer const Elf_Shdr *getSection(DataRefImpl index) const; 220b60a18deSMichael J. Spencer const Elf_Shdr *getSection(uint16_t index) const; 221b60a18deSMichael J. Spencer const char *getString(uint16_t section, uint32_t offset) const; 222b60a18deSMichael J. Spencer const char *getString(const Elf_Shdr *section, uint32_t offset) const; 223b60a18deSMichael J. Spencer 224b60a18deSMichael J. Spencer protected: 2251d6167fdSMichael J. Spencer virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const; 2261d6167fdSMichael J. Spencer virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const; 2271d6167fdSMichael J. Spencer virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const; 2281d6167fdSMichael J. Spencer virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const; 2291d6167fdSMichael J. Spencer virtual error_code getSymbolNMTypeChar(DataRefImpl Symb, char &Res) const; 2301d6167fdSMichael J. Spencer virtual error_code isSymbolInternal(DataRefImpl Symb, bool &Res) const; 231b60a18deSMichael J. Spencer 2321d6167fdSMichael J. Spencer virtual error_code getSectionNext(DataRefImpl Sec, SectionRef &Res) const; 2331d6167fdSMichael J. Spencer virtual error_code getSectionName(DataRefImpl Sec, StringRef &Res) const; 2341d6167fdSMichael J. Spencer virtual error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const; 2351d6167fdSMichael J. Spencer virtual error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const; 2361d6167fdSMichael J. Spencer virtual error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const; 2371d6167fdSMichael J. Spencer virtual error_code isSectionText(DataRefImpl Sec, bool &Res) const; 238*f6f3e81cSBenjamin Kramer virtual error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, 239*f6f3e81cSBenjamin Kramer bool &Result) const; 240b60a18deSMichael J. Spencer 241b60a18deSMichael J. Spencer public: 242ec29b121SMichael J. Spencer ELFObjectFile(MemoryBuffer *Object, error_code &ec); 243b60a18deSMichael J. Spencer virtual symbol_iterator begin_symbols() const; 244b60a18deSMichael J. Spencer virtual symbol_iterator end_symbols() const; 245b60a18deSMichael J. Spencer virtual section_iterator begin_sections() const; 246b60a18deSMichael J. Spencer virtual section_iterator end_sections() const; 247b60a18deSMichael J. Spencer 248b60a18deSMichael J. Spencer virtual uint8_t getBytesInAddress() const; 249b60a18deSMichael J. Spencer virtual StringRef getFileFormatName() const; 250b60a18deSMichael J. Spencer virtual unsigned getArch() const; 251b60a18deSMichael J. Spencer }; 252b60a18deSMichael J. Spencer } // end namespace 253b60a18deSMichael J. Spencer 254b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 255b60a18deSMichael J. Spencer void ELFObjectFile<target_endianness, is64Bits> 256b60a18deSMichael J. Spencer ::validateSymbol(DataRefImpl Symb) const { 257b60a18deSMichael J. Spencer const Elf_Sym *symb = getSymbol(Symb); 2580324b672SMichael J. Spencer const Elf_Shdr *SymbolTableSection = SymbolTableSections[Symb.d.b]; 259b60a18deSMichael J. Spencer // FIXME: We really need to do proper error handling in the case of an invalid 260b60a18deSMichael J. Spencer // input file. Because we don't use exceptions, I think we'll just pass 261b60a18deSMichael J. Spencer // an error object around. 262b60a18deSMichael J. Spencer if (!( symb 263b60a18deSMichael J. Spencer && SymbolTableSection 264ec29b121SMichael J. Spencer && symb >= (const Elf_Sym*)(base() 265b60a18deSMichael J. Spencer + SymbolTableSection->sh_offset) 266ec29b121SMichael J. Spencer && symb < (const Elf_Sym*)(base() 267b60a18deSMichael J. Spencer + SymbolTableSection->sh_offset 268b60a18deSMichael J. Spencer + SymbolTableSection->sh_size))) 269b60a18deSMichael J. Spencer // FIXME: Proper error handling. 270b60a18deSMichael J. Spencer report_fatal_error("Symb must point to a valid symbol!"); 271b60a18deSMichael J. Spencer } 272b60a18deSMichael J. Spencer 273b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 2741d6167fdSMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits> 2751d6167fdSMichael J. Spencer ::getSymbolNext(DataRefImpl Symb, 2761d6167fdSMichael J. Spencer SymbolRef &Result) const { 277b60a18deSMichael J. Spencer validateSymbol(Symb); 2780324b672SMichael J. Spencer const Elf_Shdr *SymbolTableSection = SymbolTableSections[Symb.d.b]; 279b60a18deSMichael J. Spencer 2800324b672SMichael J. Spencer ++Symb.d.a; 281b60a18deSMichael J. Spencer // Check to see if we are at the end of this symbol table. 2820324b672SMichael J. Spencer if (Symb.d.a >= SymbolTableSection->getEntityCount()) { 283b60a18deSMichael J. Spencer // We are at the end. If there are other symbol tables, jump to them. 2840324b672SMichael J. Spencer ++Symb.d.b; 2850324b672SMichael J. Spencer Symb.d.a = 1; // The 0th symbol in ELF is fake. 286b60a18deSMichael J. Spencer // Otherwise return the terminator. 2870324b672SMichael J. Spencer if (Symb.d.b >= SymbolTableSections.size()) { 2880324b672SMichael J. Spencer Symb.d.a = std::numeric_limits<uint32_t>::max(); 2890324b672SMichael J. Spencer Symb.d.b = std::numeric_limits<uint32_t>::max(); 290b60a18deSMichael J. Spencer } 291b60a18deSMichael J. Spencer } 292b60a18deSMichael J. Spencer 2931d6167fdSMichael J. Spencer Result = SymbolRef(Symb, this); 2941d6167fdSMichael J. Spencer return object_error::success; 295b60a18deSMichael J. Spencer } 296b60a18deSMichael J. Spencer 297b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 2981d6167fdSMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits> 2991d6167fdSMichael J. Spencer ::getSymbolName(DataRefImpl Symb, 3001d6167fdSMichael J. Spencer StringRef &Result) const { 301b60a18deSMichael J. Spencer validateSymbol(Symb); 302b60a18deSMichael J. Spencer const Elf_Sym *symb = getSymbol(Symb); 303b60a18deSMichael J. Spencer if (symb->st_name == 0) { 304b60a18deSMichael J. Spencer const Elf_Shdr *section = getSection(symb->st_shndx); 305b60a18deSMichael J. Spencer if (!section) 3061d6167fdSMichael J. Spencer Result = ""; 3071d6167fdSMichael J. Spencer else 3081d6167fdSMichael J. Spencer Result = getString(dot_shstrtab_sec, section->sh_name); 3091d6167fdSMichael J. Spencer return object_error::success; 310b60a18deSMichael J. Spencer } 311b60a18deSMichael J. Spencer 312b60a18deSMichael J. Spencer // Use the default symbol table name section. 3131d6167fdSMichael J. Spencer Result = getString(dot_strtab_sec, symb->st_name); 3141d6167fdSMichael J. Spencer return object_error::success; 315b60a18deSMichael J. Spencer } 316b60a18deSMichael J. Spencer 317b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 3181d6167fdSMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits> 3191d6167fdSMichael J. Spencer ::getSymbolAddress(DataRefImpl Symb, 3201d6167fdSMichael J. Spencer uint64_t &Result) const { 321b60a18deSMichael J. Spencer validateSymbol(Symb); 322b60a18deSMichael J. Spencer const Elf_Sym *symb = getSymbol(Symb); 323b60a18deSMichael J. Spencer const Elf_Shdr *Section; 324b60a18deSMichael J. Spencer switch (symb->st_shndx) { 325b60a18deSMichael J. Spencer case ELF::SHN_COMMON: 326b60a18deSMichael J. Spencer // Undefined symbols have no address yet. 3271d6167fdSMichael J. Spencer case ELF::SHN_UNDEF: 3281d6167fdSMichael J. Spencer Result = UnknownAddressOrSize; 3291d6167fdSMichael J. Spencer return object_error::success; 3301d6167fdSMichael J. Spencer case ELF::SHN_ABS: 3311d6167fdSMichael J. Spencer Result = symb->st_value; 3321d6167fdSMichael J. Spencer return object_error::success; 333b60a18deSMichael J. Spencer default: Section = getSection(symb->st_shndx); 334b60a18deSMichael J. Spencer } 335b60a18deSMichael J. Spencer 336b60a18deSMichael J. Spencer switch (symb->getType()) { 3371d6167fdSMichael J. Spencer case ELF::STT_SECTION: 3381d6167fdSMichael J. Spencer Result = Section ? Section->sh_addr : UnknownAddressOrSize; 3391d6167fdSMichael J. Spencer return object_error::success; 340b60a18deSMichael J. Spencer case ELF::STT_FUNC: 341b60a18deSMichael J. Spencer case ELF::STT_OBJECT: 342b60a18deSMichael J. Spencer case ELF::STT_NOTYPE: 3431d6167fdSMichael J. Spencer Result = symb->st_value; 3441d6167fdSMichael J. Spencer return object_error::success; 3451d6167fdSMichael J. Spencer default: 3461d6167fdSMichael J. Spencer Result = UnknownAddressOrSize; 3471d6167fdSMichael J. Spencer return object_error::success; 348b60a18deSMichael J. Spencer } 349b60a18deSMichael J. Spencer } 350b60a18deSMichael J. Spencer 351b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 3521d6167fdSMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits> 3531d6167fdSMichael J. Spencer ::getSymbolSize(DataRefImpl Symb, 3541d6167fdSMichael J. Spencer uint64_t &Result) const { 355b60a18deSMichael J. Spencer validateSymbol(Symb); 356b60a18deSMichael J. Spencer const Elf_Sym *symb = getSymbol(Symb); 357b60a18deSMichael J. Spencer if (symb->st_size == 0) 3581d6167fdSMichael J. Spencer Result = UnknownAddressOrSize; 3591d6167fdSMichael J. Spencer Result = symb->st_size; 3601d6167fdSMichael J. Spencer return object_error::success; 361b60a18deSMichael J. Spencer } 362b60a18deSMichael J. Spencer 363b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 3641d6167fdSMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits> 3651d6167fdSMichael J. Spencer ::getSymbolNMTypeChar(DataRefImpl Symb, 3661d6167fdSMichael J. Spencer char &Result) const { 367b60a18deSMichael J. Spencer validateSymbol(Symb); 368b60a18deSMichael J. Spencer const Elf_Sym *symb = getSymbol(Symb); 369b60a18deSMichael J. Spencer const Elf_Shdr *Section = getSection(symb->st_shndx); 370b60a18deSMichael J. Spencer 371b60a18deSMichael J. Spencer char ret = '?'; 372b60a18deSMichael J. Spencer 373b60a18deSMichael J. Spencer if (Section) { 374b60a18deSMichael J. Spencer switch (Section->sh_type) { 375b60a18deSMichael J. Spencer case ELF::SHT_PROGBITS: 376b60a18deSMichael J. Spencer case ELF::SHT_DYNAMIC: 377b60a18deSMichael J. Spencer switch (Section->sh_flags) { 378b60a18deSMichael J. Spencer case (ELF::SHF_ALLOC | ELF::SHF_EXECINSTR): 379b60a18deSMichael J. Spencer ret = 't'; break; 380b60a18deSMichael J. Spencer case (ELF::SHF_ALLOC | ELF::SHF_WRITE): 381b60a18deSMichael J. Spencer ret = 'd'; break; 382b60a18deSMichael J. Spencer case ELF::SHF_ALLOC: 383b60a18deSMichael J. Spencer case (ELF::SHF_ALLOC | ELF::SHF_MERGE): 384b60a18deSMichael J. Spencer case (ELF::SHF_ALLOC | ELF::SHF_MERGE | ELF::SHF_STRINGS): 385b60a18deSMichael J. Spencer ret = 'r'; break; 386b60a18deSMichael J. Spencer } 387b60a18deSMichael J. Spencer break; 388b60a18deSMichael J. Spencer case ELF::SHT_NOBITS: ret = 'b'; 389b60a18deSMichael J. Spencer } 390b60a18deSMichael J. Spencer } 391b60a18deSMichael J. Spencer 392b60a18deSMichael J. Spencer switch (symb->st_shndx) { 393b60a18deSMichael J. Spencer case ELF::SHN_UNDEF: 394b60a18deSMichael J. Spencer if (ret == '?') 395b60a18deSMichael J. Spencer ret = 'U'; 396b60a18deSMichael J. Spencer break; 397b60a18deSMichael J. Spencer case ELF::SHN_ABS: ret = 'a'; break; 398b60a18deSMichael J. Spencer case ELF::SHN_COMMON: ret = 'c'; break; 399b60a18deSMichael J. Spencer } 400b60a18deSMichael J. Spencer 401b60a18deSMichael J. Spencer switch (symb->getBinding()) { 402b60a18deSMichael J. Spencer case ELF::STB_GLOBAL: ret = ::toupper(ret); break; 403b60a18deSMichael J. Spencer case ELF::STB_WEAK: 404b60a18deSMichael J. Spencer if (symb->st_shndx == ELF::SHN_UNDEF) 405b60a18deSMichael J. Spencer ret = 'w'; 406b60a18deSMichael J. Spencer else 407b60a18deSMichael J. Spencer if (symb->getType() == ELF::STT_OBJECT) 408b60a18deSMichael J. Spencer ret = 'V'; 409b60a18deSMichael J. Spencer else 410b60a18deSMichael J. Spencer ret = 'W'; 411b60a18deSMichael J. Spencer } 412b60a18deSMichael J. Spencer 4131d6167fdSMichael J. Spencer if (ret == '?' && symb->getType() == ELF::STT_SECTION) { 4141d6167fdSMichael J. Spencer StringRef name; 4151d6167fdSMichael J. Spencer if (error_code ec = getSymbolName(Symb, name)) 4161d6167fdSMichael J. Spencer return ec; 4171d6167fdSMichael J. Spencer Result = StringSwitch<char>(name) 418b60a18deSMichael J. Spencer .StartsWith(".debug", 'N') 419b60a18deSMichael J. Spencer .StartsWith(".note", 'n'); 4201d6167fdSMichael J. Spencer return object_error::success; 4211d6167fdSMichael J. Spencer } 422b60a18deSMichael J. Spencer 4231d6167fdSMichael J. Spencer Result = ret; 4241d6167fdSMichael J. Spencer return object_error::success; 425b60a18deSMichael J. Spencer } 426b60a18deSMichael J. Spencer 427b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 4281d6167fdSMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits> 4291d6167fdSMichael J. Spencer ::isSymbolInternal(DataRefImpl Symb, 4301d6167fdSMichael J. Spencer bool &Result) const { 431b60a18deSMichael J. Spencer validateSymbol(Symb); 432b60a18deSMichael J. Spencer const Elf_Sym *symb = getSymbol(Symb); 433b60a18deSMichael J. Spencer 434b60a18deSMichael J. Spencer if ( symb->getType() == ELF::STT_FILE 435b60a18deSMichael J. Spencer || symb->getType() == ELF::STT_SECTION) 4361d6167fdSMichael J. Spencer Result = true; 4371d6167fdSMichael J. Spencer Result = false; 4381d6167fdSMichael J. Spencer return object_error::success; 439b60a18deSMichael J. Spencer } 440b60a18deSMichael J. Spencer 441b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 4421d6167fdSMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits> 4431d6167fdSMichael J. Spencer ::getSectionNext(DataRefImpl Sec, SectionRef &Result) const { 4440324b672SMichael J. Spencer const uint8_t *sec = reinterpret_cast<const uint8_t *>(Sec.p); 445b60a18deSMichael J. Spencer sec += Header->e_shentsize; 4460324b672SMichael J. Spencer Sec.p = reinterpret_cast<intptr_t>(sec); 4471d6167fdSMichael J. Spencer Result = SectionRef(Sec, this); 4481d6167fdSMichael J. Spencer return object_error::success; 449b60a18deSMichael J. Spencer } 450b60a18deSMichael J. Spencer 451b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 4521d6167fdSMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits> 4531d6167fdSMichael J. Spencer ::getSectionName(DataRefImpl Sec, 4541d6167fdSMichael J. Spencer StringRef &Result) const { 4550324b672SMichael J. Spencer const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); 4561d6167fdSMichael J. Spencer Result = StringRef(getString(dot_shstrtab_sec, sec->sh_name)); 4571d6167fdSMichael J. Spencer return object_error::success; 458b60a18deSMichael J. Spencer } 459b60a18deSMichael J. Spencer 460b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 4611d6167fdSMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits> 4621d6167fdSMichael J. Spencer ::getSectionAddress(DataRefImpl Sec, 4631d6167fdSMichael J. Spencer uint64_t &Result) const { 4640324b672SMichael J. Spencer const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); 4651d6167fdSMichael J. Spencer Result = sec->sh_addr; 4661d6167fdSMichael J. Spencer return object_error::success; 467b60a18deSMichael J. Spencer } 468b60a18deSMichael J. Spencer 469b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 4701d6167fdSMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits> 4711d6167fdSMichael J. Spencer ::getSectionSize(DataRefImpl Sec, 4721d6167fdSMichael J. Spencer uint64_t &Result) const { 4730324b672SMichael J. Spencer const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); 4741d6167fdSMichael J. Spencer Result = sec->sh_size; 4751d6167fdSMichael J. Spencer return object_error::success; 476b60a18deSMichael J. Spencer } 477b60a18deSMichael J. Spencer 478b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 4791d6167fdSMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits> 4801d6167fdSMichael J. Spencer ::getSectionContents(DataRefImpl Sec, 4811d6167fdSMichael J. Spencer StringRef &Result) const { 4820324b672SMichael J. Spencer const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); 4831d6167fdSMichael J. Spencer const char *start = (const char*)base() + sec->sh_offset; 4841d6167fdSMichael J. Spencer Result = StringRef(start, sec->sh_size); 4851d6167fdSMichael J. Spencer return object_error::success; 486b60a18deSMichael J. Spencer } 487b60a18deSMichael J. Spencer 488b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 4891d6167fdSMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits> 4901d6167fdSMichael J. Spencer ::isSectionText(DataRefImpl Sec, 4911d6167fdSMichael J. Spencer bool &Result) const { 4920324b672SMichael J. Spencer const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); 493b60a18deSMichael J. Spencer if (sec->sh_flags & ELF::SHF_EXECINSTR) 4941d6167fdSMichael J. Spencer Result = true; 4951d6167fdSMichael J. Spencer else 4961d6167fdSMichael J. Spencer Result = false; 4971d6167fdSMichael J. Spencer return object_error::success; 498b60a18deSMichael J. Spencer } 499b60a18deSMichael J. Spencer 500b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 501*f6f3e81cSBenjamin Kramer error_code ELFObjectFile<target_endianness, is64Bits> 502*f6f3e81cSBenjamin Kramer ::sectionContainsSymbol(DataRefImpl Sec, 503*f6f3e81cSBenjamin Kramer DataRefImpl Symb, 504*f6f3e81cSBenjamin Kramer bool &Result) const { 505*f6f3e81cSBenjamin Kramer // FIXME: Unimplemented. 506*f6f3e81cSBenjamin Kramer Result = false; 507*f6f3e81cSBenjamin Kramer return object_error::success; 508*f6f3e81cSBenjamin Kramer } 509*f6f3e81cSBenjamin Kramer 510*f6f3e81cSBenjamin Kramer template<support::endianness target_endianness, bool is64Bits> 511ec29b121SMichael J. Spencer ELFObjectFile<target_endianness, is64Bits>::ELFObjectFile(MemoryBuffer *Object 512ec29b121SMichael J. Spencer , error_code &ec) 513ec29b121SMichael J. Spencer : ObjectFile(Binary::isELF, Object, ec) 514b60a18deSMichael J. Spencer , SectionHeaderTable(0) 515b60a18deSMichael J. Spencer , dot_shstrtab_sec(0) 516b60a18deSMichael J. Spencer , dot_strtab_sec(0) { 517ec29b121SMichael J. Spencer Header = reinterpret_cast<const Elf_Ehdr *>(base()); 518b60a18deSMichael J. Spencer 519b60a18deSMichael J. Spencer if (Header->e_shoff == 0) 520b60a18deSMichael J. Spencer return; 521b60a18deSMichael J. Spencer 522b60a18deSMichael J. Spencer SectionHeaderTable = 523ec29b121SMichael J. Spencer reinterpret_cast<const Elf_Shdr *>(base() + Header->e_shoff); 524b60a18deSMichael J. Spencer uint32_t SectionTableSize = Header->e_shnum * Header->e_shentsize; 525b60a18deSMichael J. Spencer if (!( (const uint8_t *)SectionHeaderTable + SectionTableSize 526ec29b121SMichael J. Spencer <= base() + Data->getBufferSize())) 527b60a18deSMichael J. Spencer // FIXME: Proper error handling. 528b60a18deSMichael J. Spencer report_fatal_error("Section table goes past end of file!"); 529b60a18deSMichael J. Spencer 530b60a18deSMichael J. Spencer 531b60a18deSMichael J. Spencer // To find the symbol tables we walk the section table to find SHT_STMTAB. 532b60a18deSMichael J. Spencer for (const char *i = reinterpret_cast<const char *>(SectionHeaderTable), 533b60a18deSMichael J. Spencer *e = i + Header->e_shnum * Header->e_shentsize; 534b60a18deSMichael J. Spencer i != e; i += Header->e_shentsize) { 535b60a18deSMichael J. Spencer const Elf_Shdr *sh = reinterpret_cast<const Elf_Shdr*>(i); 536b60a18deSMichael J. Spencer if (sh->sh_type == ELF::SHT_SYMTAB) { 537b60a18deSMichael J. Spencer SymbolTableSections.push_back(sh); 538b60a18deSMichael J. Spencer } 539b60a18deSMichael J. Spencer } 540b60a18deSMichael J. Spencer 541b60a18deSMichael J. Spencer // Get string table sections. 542b60a18deSMichael J. Spencer dot_shstrtab_sec = getSection(Header->e_shstrndx); 543b60a18deSMichael J. Spencer if (dot_shstrtab_sec) { 544b60a18deSMichael J. Spencer // Verify that the last byte in the string table in a null. 545ec29b121SMichael J. Spencer if (((const char*)base() + dot_shstrtab_sec->sh_offset) 546b60a18deSMichael J. Spencer [dot_shstrtab_sec->sh_size - 1] != 0) 547b60a18deSMichael J. Spencer // FIXME: Proper error handling. 548b60a18deSMichael J. Spencer report_fatal_error("String table must end with a null terminator!"); 549b60a18deSMichael J. Spencer } 550b60a18deSMichael J. Spencer 551b60a18deSMichael J. Spencer // Merge this into the above loop. 552b60a18deSMichael J. Spencer for (const char *i = reinterpret_cast<const char *>(SectionHeaderTable), 553b60a18deSMichael J. Spencer *e = i + Header->e_shnum * Header->e_shentsize; 554b60a18deSMichael J. Spencer i != e; i += Header->e_shentsize) { 555b60a18deSMichael J. Spencer const Elf_Shdr *sh = reinterpret_cast<const Elf_Shdr*>(i); 556b60a18deSMichael J. Spencer if (sh->sh_type == ELF::SHT_STRTAB) { 557b60a18deSMichael J. Spencer StringRef SectionName(getString(dot_shstrtab_sec, sh->sh_name)); 558b60a18deSMichael J. Spencer if (SectionName == ".strtab") { 559b60a18deSMichael J. Spencer if (dot_strtab_sec != 0) 560b60a18deSMichael J. Spencer // FIXME: Proper error handling. 561b60a18deSMichael J. Spencer report_fatal_error("Already found section named .strtab!"); 562b60a18deSMichael J. Spencer dot_strtab_sec = sh; 563ec29b121SMichael J. Spencer const char *dot_strtab = (const char*)base() + sh->sh_offset; 564b60a18deSMichael J. Spencer if (dot_strtab[sh->sh_size - 1] != 0) 565b60a18deSMichael J. Spencer // FIXME: Proper error handling. 566b60a18deSMichael J. Spencer report_fatal_error("String table must end with a null terminator!"); 567b60a18deSMichael J. Spencer } 568b60a18deSMichael J. Spencer } 569b60a18deSMichael J. Spencer } 570b60a18deSMichael J. Spencer } 571b60a18deSMichael J. Spencer 572b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 573b60a18deSMichael J. Spencer ObjectFile::symbol_iterator ELFObjectFile<target_endianness, is64Bits> 574b60a18deSMichael J. Spencer ::begin_symbols() const { 5750324b672SMichael J. Spencer DataRefImpl SymbolData; 576b60a18deSMichael J. Spencer memset(&SymbolData, 0, sizeof(SymbolData)); 577b60a18deSMichael J. Spencer if (SymbolTableSections.size() == 0) { 5780324b672SMichael J. Spencer SymbolData.d.a = std::numeric_limits<uint32_t>::max(); 5790324b672SMichael J. Spencer SymbolData.d.b = std::numeric_limits<uint32_t>::max(); 580b60a18deSMichael J. Spencer } else { 5810324b672SMichael J. Spencer SymbolData.d.a = 1; // The 0th symbol in ELF is fake. 5820324b672SMichael J. Spencer SymbolData.d.b = 0; 583b60a18deSMichael J. Spencer } 5840324b672SMichael J. Spencer return symbol_iterator(SymbolRef(SymbolData, this)); 585b60a18deSMichael J. Spencer } 586b60a18deSMichael J. Spencer 587b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 588b60a18deSMichael J. Spencer ObjectFile::symbol_iterator ELFObjectFile<target_endianness, is64Bits> 589b60a18deSMichael J. Spencer ::end_symbols() const { 5900324b672SMichael J. Spencer DataRefImpl SymbolData; 591b60a18deSMichael J. Spencer memset(&SymbolData, 0, sizeof(SymbolData)); 5920324b672SMichael J. Spencer SymbolData.d.a = std::numeric_limits<uint32_t>::max(); 5930324b672SMichael J. Spencer SymbolData.d.b = std::numeric_limits<uint32_t>::max(); 5940324b672SMichael J. Spencer return symbol_iterator(SymbolRef(SymbolData, this)); 595b60a18deSMichael J. Spencer } 596b60a18deSMichael J. Spencer 597b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 598b60a18deSMichael J. Spencer ObjectFile::section_iterator ELFObjectFile<target_endianness, is64Bits> 599b60a18deSMichael J. Spencer ::begin_sections() const { 6000324b672SMichael J. Spencer DataRefImpl ret; 601ee066fc4SEric Christopher memset(&ret, 0, sizeof(DataRefImpl)); 602ec29b121SMichael J. Spencer ret.p = reinterpret_cast<intptr_t>(base() + Header->e_shoff); 6030324b672SMichael J. Spencer return section_iterator(SectionRef(ret, this)); 604b60a18deSMichael J. Spencer } 605b60a18deSMichael J. Spencer 606b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 607b60a18deSMichael J. Spencer ObjectFile::section_iterator ELFObjectFile<target_endianness, is64Bits> 608b60a18deSMichael J. Spencer ::end_sections() const { 6090324b672SMichael J. Spencer DataRefImpl ret; 610ee066fc4SEric Christopher memset(&ret, 0, sizeof(DataRefImpl)); 611ec29b121SMichael J. Spencer ret.p = reinterpret_cast<intptr_t>(base() 612b60a18deSMichael J. Spencer + Header->e_shoff 6130324b672SMichael J. Spencer + (Header->e_shentsize * Header->e_shnum)); 6140324b672SMichael J. Spencer return section_iterator(SectionRef(ret, this)); 615b60a18deSMichael J. Spencer } 616b60a18deSMichael J. Spencer 617b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 618b60a18deSMichael J. Spencer uint8_t ELFObjectFile<target_endianness, is64Bits>::getBytesInAddress() const { 6190324b672SMichael J. Spencer return is64Bits ? 8 : 4; 620b60a18deSMichael J. Spencer } 621b60a18deSMichael J. Spencer 622b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 623b60a18deSMichael J. Spencer StringRef ELFObjectFile<target_endianness, is64Bits> 624b60a18deSMichael J. Spencer ::getFileFormatName() const { 625b60a18deSMichael J. Spencer switch(Header->e_ident[ELF::EI_CLASS]) { 626b60a18deSMichael J. Spencer case ELF::ELFCLASS32: 627b60a18deSMichael J. Spencer switch(Header->e_machine) { 628b60a18deSMichael J. Spencer case ELF::EM_386: 629b60a18deSMichael J. Spencer return "ELF32-i386"; 630b60a18deSMichael J. Spencer case ELF::EM_X86_64: 631b60a18deSMichael J. Spencer return "ELF32-x86-64"; 632b60a18deSMichael J. Spencer default: 633b60a18deSMichael J. Spencer return "ELF32-unknown"; 634b60a18deSMichael J. Spencer } 635b60a18deSMichael J. Spencer case ELF::ELFCLASS64: 636b60a18deSMichael J. Spencer switch(Header->e_machine) { 637b60a18deSMichael J. Spencer case ELF::EM_386: 638b60a18deSMichael J. Spencer return "ELF64-i386"; 639b60a18deSMichael J. Spencer case ELF::EM_X86_64: 640b60a18deSMichael J. Spencer return "ELF64-x86-64"; 641b60a18deSMichael J. Spencer default: 642b60a18deSMichael J. Spencer return "ELF64-unknown"; 643b60a18deSMichael J. Spencer } 644b60a18deSMichael J. Spencer default: 645b60a18deSMichael J. Spencer // FIXME: Proper error handling. 646b60a18deSMichael J. Spencer report_fatal_error("Invalid ELFCLASS!"); 647b60a18deSMichael J. Spencer } 648b60a18deSMichael J. Spencer } 649b60a18deSMichael J. Spencer 650b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 651b60a18deSMichael J. Spencer unsigned ELFObjectFile<target_endianness, is64Bits>::getArch() const { 652b60a18deSMichael J. Spencer switch(Header->e_machine) { 653b60a18deSMichael J. Spencer case ELF::EM_386: 654b60a18deSMichael J. Spencer return Triple::x86; 655b60a18deSMichael J. Spencer case ELF::EM_X86_64: 656b60a18deSMichael J. Spencer return Triple::x86_64; 657b60a18deSMichael J. Spencer default: 658b60a18deSMichael J. Spencer return Triple::UnknownArch; 659b60a18deSMichael J. Spencer } 660b60a18deSMichael J. Spencer } 661b60a18deSMichael J. Spencer 662b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 663b60a18deSMichael J. Spencer const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Sym * 664b60a18deSMichael J. Spencer ELFObjectFile<target_endianness, is64Bits>::getSymbol(DataRefImpl Symb) const { 6650324b672SMichael J. Spencer const Elf_Shdr *sec = SymbolTableSections[Symb.d.b]; 666b60a18deSMichael J. Spencer return reinterpret_cast<const Elf_Sym *>( 667ec29b121SMichael J. Spencer base() 668b60a18deSMichael J. Spencer + sec->sh_offset 6690324b672SMichael J. Spencer + (Symb.d.a * sec->sh_entsize)); 670b60a18deSMichael J. Spencer } 671b60a18deSMichael J. Spencer 672b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 673b60a18deSMichael J. Spencer const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Shdr * 674b60a18deSMichael J. Spencer ELFObjectFile<target_endianness, is64Bits>::getSection(DataRefImpl Symb) const { 6750324b672SMichael J. Spencer const Elf_Shdr *sec = getSection(Symb.d.b); 676b60a18deSMichael J. Spencer if (sec->sh_type != ELF::SHT_SYMTAB) 677b60a18deSMichael J. Spencer // FIXME: Proper error handling. 678b60a18deSMichael J. Spencer report_fatal_error("Invalid symbol table section!"); 679b60a18deSMichael J. Spencer return sec; 680b60a18deSMichael J. Spencer } 681b60a18deSMichael J. Spencer 682b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 683b60a18deSMichael J. Spencer const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Shdr * 684b60a18deSMichael J. Spencer ELFObjectFile<target_endianness, is64Bits>::getSection(uint16_t index) const { 685b60a18deSMichael J. Spencer if (index == 0 || index >= ELF::SHN_LORESERVE) 686b60a18deSMichael J. Spencer return 0; 687b60a18deSMichael J. Spencer if (!SectionHeaderTable || index >= Header->e_shnum) 688b60a18deSMichael J. Spencer // FIXME: Proper error handling. 689b60a18deSMichael J. Spencer report_fatal_error("Invalid section index!"); 690b60a18deSMichael J. Spencer 691b60a18deSMichael J. Spencer return reinterpret_cast<const Elf_Shdr *>( 692b60a18deSMichael J. Spencer reinterpret_cast<const char *>(SectionHeaderTable) 693b60a18deSMichael J. Spencer + (index * Header->e_shentsize)); 694b60a18deSMichael J. Spencer } 695b60a18deSMichael J. Spencer 696b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 697b60a18deSMichael J. Spencer const char *ELFObjectFile<target_endianness, is64Bits> 698b60a18deSMichael J. Spencer ::getString(uint16_t section, 699b60a18deSMichael J. Spencer ELF::Elf32_Word offset) const { 700b60a18deSMichael J. Spencer return getString(getSection(section), offset); 701b60a18deSMichael J. Spencer } 702b60a18deSMichael J. Spencer 703b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 704b60a18deSMichael J. Spencer const char *ELFObjectFile<target_endianness, is64Bits> 705b60a18deSMichael J. Spencer ::getString(const Elf_Shdr *section, 706b60a18deSMichael J. Spencer ELF::Elf32_Word offset) const { 707b60a18deSMichael J. Spencer assert(section && section->sh_type == ELF::SHT_STRTAB && "Invalid section!"); 708b60a18deSMichael J. Spencer if (offset >= section->sh_size) 709b60a18deSMichael J. Spencer // FIXME: Proper error handling. 710ec29b121SMichael J. Spencer report_fatal_error("Symbol name offset outside of string table!"); 711ec29b121SMichael J. Spencer return (const char *)base() + section->sh_offset + offset; 712b60a18deSMichael J. Spencer } 713b60a18deSMichael J. Spencer 714b60a18deSMichael J. Spencer // EI_CLASS, EI_DATA. 715b60a18deSMichael J. Spencer static std::pair<unsigned char, unsigned char> 716b60a18deSMichael J. Spencer getElfArchType(MemoryBuffer *Object) { 717b60a18deSMichael J. Spencer if (Object->getBufferSize() < ELF::EI_NIDENT) 718b60a18deSMichael J. Spencer return std::make_pair((uint8_t)ELF::ELFCLASSNONE,(uint8_t)ELF::ELFDATANONE); 719b60a18deSMichael J. Spencer return std::make_pair( (uint8_t)Object->getBufferStart()[ELF::EI_CLASS] 720b60a18deSMichael J. Spencer , (uint8_t)Object->getBufferStart()[ELF::EI_DATA]); 721b60a18deSMichael J. Spencer } 722b60a18deSMichael J. Spencer 723b60a18deSMichael J. Spencer namespace llvm { 724b60a18deSMichael J. Spencer 725b60a18deSMichael J. Spencer ObjectFile *ObjectFile::createELFObjectFile(MemoryBuffer *Object) { 726b60a18deSMichael J. Spencer std::pair<unsigned char, unsigned char> Ident = getElfArchType(Object); 727ec29b121SMichael J. Spencer error_code ec; 728b60a18deSMichael J. Spencer if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2LSB) 729ec29b121SMichael J. Spencer return new ELFObjectFile<support::little, false>(Object, ec); 730b60a18deSMichael J. Spencer else if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2MSB) 731ec29b121SMichael J. Spencer return new ELFObjectFile<support::big, false>(Object, ec); 732b60a18deSMichael J. Spencer else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2LSB) 733ec29b121SMichael J. Spencer return new ELFObjectFile<support::little, true>(Object, ec); 734b60a18deSMichael J. Spencer else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2MSB) 735ec29b121SMichael J. Spencer return new ELFObjectFile<support::big, true>(Object, ec); 736b60a18deSMichael J. Spencer // FIXME: Proper error handling. 737b60a18deSMichael J. Spencer report_fatal_error("Not an ELF object file!"); 738b60a18deSMichael J. Spencer } 739b60a18deSMichael J. Spencer 740b60a18deSMichael J. Spencer } // end namespace llvm 741