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" 17022ecdf2SBenjamin Kramer #include "llvm/ADT/DenseMap.h" 18b60a18deSMichael J. Spencer #include "llvm/Object/ObjectFile.h" 19b60a18deSMichael J. Spencer #include "llvm/Support/ELF.h" 20b60a18deSMichael J. Spencer #include "llvm/Support/Endian.h" 21b60a18deSMichael J. Spencer #include "llvm/Support/ErrorHandling.h" 22b60a18deSMichael J. Spencer #include "llvm/Support/MemoryBuffer.h" 23b60a18deSMichael J. Spencer #include <limits> 24b60a18deSMichael J. Spencer #include <utility> 25b60a18deSMichael J. Spencer 26b60a18deSMichael J. Spencer using namespace llvm; 27b60a18deSMichael J. Spencer using namespace object; 28b60a18deSMichael J. Spencer 29b60a18deSMichael J. Spencer // Templates to choose Elf_Addr and Elf_Off depending on is64Bits. 30b60a18deSMichael J. Spencer namespace { 31b60a18deSMichael J. Spencer template<support::endianness target_endianness> 32b60a18deSMichael J. Spencer struct ELFDataTypeTypedefHelperCommon { 33b60a18deSMichael J. Spencer typedef support::detail::packed_endian_specific_integral 34b60a18deSMichael J. Spencer <uint16_t, target_endianness, support::aligned> Elf_Half; 35b60a18deSMichael J. Spencer typedef support::detail::packed_endian_specific_integral 36b60a18deSMichael J. Spencer <uint32_t, target_endianness, support::aligned> Elf_Word; 37b60a18deSMichael J. Spencer typedef support::detail::packed_endian_specific_integral 38b60a18deSMichael J. Spencer <int32_t, target_endianness, support::aligned> Elf_Sword; 39b60a18deSMichael J. Spencer typedef support::detail::packed_endian_specific_integral 40b60a18deSMichael J. Spencer <uint64_t, target_endianness, support::aligned> Elf_Xword; 41b60a18deSMichael J. Spencer typedef support::detail::packed_endian_specific_integral 42b60a18deSMichael J. Spencer <int64_t, target_endianness, support::aligned> Elf_Sxword; 43b60a18deSMichael J. Spencer }; 44b60a18deSMichael J. Spencer } 45b60a18deSMichael J. Spencer 46b60a18deSMichael J. Spencer namespace { 47b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 48b60a18deSMichael J. Spencer struct ELFDataTypeTypedefHelper; 49b60a18deSMichael J. Spencer 50b60a18deSMichael J. Spencer /// ELF 32bit types. 51b60a18deSMichael J. Spencer template<support::endianness target_endianness> 52b60a18deSMichael J. Spencer struct ELFDataTypeTypedefHelper<target_endianness, false> 53b60a18deSMichael J. Spencer : ELFDataTypeTypedefHelperCommon<target_endianness> { 54b60a18deSMichael J. Spencer typedef support::detail::packed_endian_specific_integral 55b60a18deSMichael J. Spencer <uint32_t, target_endianness, support::aligned> Elf_Addr; 56b60a18deSMichael J. Spencer typedef support::detail::packed_endian_specific_integral 57b60a18deSMichael J. Spencer <uint32_t, target_endianness, support::aligned> Elf_Off; 58b60a18deSMichael J. Spencer }; 59b60a18deSMichael J. Spencer 60b60a18deSMichael J. Spencer /// ELF 64bit types. 61b60a18deSMichael J. Spencer template<support::endianness target_endianness> 62b60a18deSMichael J. Spencer struct ELFDataTypeTypedefHelper<target_endianness, true> 63b60a18deSMichael J. Spencer : ELFDataTypeTypedefHelperCommon<target_endianness>{ 64b60a18deSMichael J. Spencer typedef support::detail::packed_endian_specific_integral 65b60a18deSMichael J. Spencer <uint64_t, target_endianness, support::aligned> Elf_Addr; 66b60a18deSMichael J. Spencer typedef support::detail::packed_endian_specific_integral 67b60a18deSMichael J. Spencer <uint64_t, target_endianness, support::aligned> Elf_Off; 68b60a18deSMichael J. Spencer }; 69b60a18deSMichael J. Spencer } 70b60a18deSMichael J. Spencer 71b60a18deSMichael J. Spencer // I really don't like doing this, but the alternative is copypasta. 72b60a18deSMichael J. Spencer #define LLVM_ELF_IMPORT_TYPES(target_endianness, is64Bits) \ 73b60a18deSMichael J. Spencer typedef typename \ 74b60a18deSMichael J. Spencer ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Addr Elf_Addr; \ 75b60a18deSMichael J. Spencer typedef typename \ 76b60a18deSMichael J. Spencer ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Off Elf_Off; \ 77b60a18deSMichael J. Spencer typedef typename \ 78b60a18deSMichael J. Spencer ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Half Elf_Half; \ 79b60a18deSMichael J. Spencer typedef typename \ 80b60a18deSMichael J. Spencer ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Word Elf_Word; \ 81b60a18deSMichael J. Spencer typedef typename \ 82b60a18deSMichael J. Spencer ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Sword Elf_Sword; \ 83b60a18deSMichael J. Spencer typedef typename \ 84b60a18deSMichael J. Spencer ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Xword Elf_Xword; \ 85b60a18deSMichael J. Spencer typedef typename \ 86b60a18deSMichael J. Spencer ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Sxword Elf_Sxword; 87b60a18deSMichael J. Spencer 88b60a18deSMichael J. Spencer // Section header. 89b60a18deSMichael J. Spencer namespace { 90b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 91b60a18deSMichael J. Spencer struct Elf_Shdr_Base; 92b60a18deSMichael J. Spencer 93b60a18deSMichael J. Spencer template<support::endianness target_endianness> 94b60a18deSMichael J. Spencer struct Elf_Shdr_Base<target_endianness, false> { 95b60a18deSMichael J. Spencer LLVM_ELF_IMPORT_TYPES(target_endianness, false) 96b60a18deSMichael J. Spencer Elf_Word sh_name; // Section name (index into string table) 97b60a18deSMichael J. Spencer Elf_Word sh_type; // Section type (SHT_*) 98b60a18deSMichael J. Spencer Elf_Word sh_flags; // Section flags (SHF_*) 99b60a18deSMichael J. Spencer Elf_Addr sh_addr; // Address where section is to be loaded 100b60a18deSMichael J. Spencer Elf_Off sh_offset; // File offset of section data, in bytes 101b60a18deSMichael J. Spencer Elf_Word sh_size; // Size of section, in bytes 102b60a18deSMichael J. Spencer Elf_Word sh_link; // Section type-specific header table index link 103b60a18deSMichael J. Spencer Elf_Word sh_info; // Section type-specific extra information 104b60a18deSMichael J. Spencer Elf_Word sh_addralign;// Section address alignment 105b60a18deSMichael J. Spencer Elf_Word sh_entsize; // Size of records contained within the section 106b60a18deSMichael J. Spencer }; 107b60a18deSMichael J. Spencer 108b60a18deSMichael J. Spencer template<support::endianness target_endianness> 109b60a18deSMichael J. Spencer struct Elf_Shdr_Base<target_endianness, true> { 110b60a18deSMichael J. Spencer LLVM_ELF_IMPORT_TYPES(target_endianness, true) 111b60a18deSMichael J. Spencer Elf_Word sh_name; // Section name (index into string table) 112b60a18deSMichael J. Spencer Elf_Word sh_type; // Section type (SHT_*) 113b60a18deSMichael J. Spencer Elf_Xword sh_flags; // Section flags (SHF_*) 114b60a18deSMichael J. Spencer Elf_Addr sh_addr; // Address where section is to be loaded 115b60a18deSMichael J. Spencer Elf_Off sh_offset; // File offset of section data, in bytes 116b60a18deSMichael J. Spencer Elf_Xword sh_size; // Size of section, in bytes 117b60a18deSMichael J. Spencer Elf_Word sh_link; // Section type-specific header table index link 118b60a18deSMichael J. Spencer Elf_Word sh_info; // Section type-specific extra information 119b60a18deSMichael J. Spencer Elf_Xword sh_addralign;// Section address alignment 120b60a18deSMichael J. Spencer Elf_Xword sh_entsize; // Size of records contained within the section 121b60a18deSMichael J. Spencer }; 122b60a18deSMichael J. Spencer 123b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 124b60a18deSMichael J. Spencer struct Elf_Shdr_Impl : Elf_Shdr_Base<target_endianness, is64Bits> { 125b60a18deSMichael J. Spencer using Elf_Shdr_Base<target_endianness, is64Bits>::sh_entsize; 126b60a18deSMichael J. Spencer using Elf_Shdr_Base<target_endianness, is64Bits>::sh_size; 127b60a18deSMichael J. Spencer 128b60a18deSMichael J. Spencer /// @brief Get the number of entities this section contains if it has any. 129b60a18deSMichael J. Spencer unsigned getEntityCount() const { 130b60a18deSMichael J. Spencer if (sh_entsize == 0) 131b60a18deSMichael J. Spencer return 0; 132b60a18deSMichael J. Spencer return sh_size / sh_entsize; 133b60a18deSMichael J. Spencer } 134b60a18deSMichael J. Spencer }; 135b60a18deSMichael J. Spencer } 136b60a18deSMichael J. Spencer 137b60a18deSMichael J. Spencer namespace { 138b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 139b60a18deSMichael J. Spencer struct Elf_Sym_Base; 140b60a18deSMichael J. Spencer 141b60a18deSMichael J. Spencer template<support::endianness target_endianness> 142b60a18deSMichael J. Spencer struct Elf_Sym_Base<target_endianness, false> { 143b60a18deSMichael J. Spencer LLVM_ELF_IMPORT_TYPES(target_endianness, false) 144b60a18deSMichael J. Spencer Elf_Word st_name; // Symbol name (index into string table) 145b60a18deSMichael J. Spencer Elf_Addr st_value; // Value or address associated with the symbol 146b60a18deSMichael J. Spencer Elf_Word st_size; // Size of the symbol 147b60a18deSMichael J. Spencer unsigned char st_info; // Symbol's type and binding attributes 148b60a18deSMichael J. Spencer unsigned char st_other; // Must be zero; reserved 149b60a18deSMichael J. Spencer Elf_Half st_shndx; // Which section (header table index) it's defined in 150b60a18deSMichael J. Spencer }; 151b60a18deSMichael J. Spencer 152b60a18deSMichael J. Spencer template<support::endianness target_endianness> 153b60a18deSMichael J. Spencer struct Elf_Sym_Base<target_endianness, true> { 154b60a18deSMichael J. Spencer LLVM_ELF_IMPORT_TYPES(target_endianness, true) 155b60a18deSMichael J. Spencer Elf_Word st_name; // Symbol name (index into string table) 156b60a18deSMichael J. Spencer unsigned char st_info; // Symbol's type and binding attributes 157b60a18deSMichael J. Spencer unsigned char st_other; // Must be zero; reserved 158b60a18deSMichael J. Spencer Elf_Half st_shndx; // Which section (header table index) it's defined in 159b60a18deSMichael J. Spencer Elf_Addr st_value; // Value or address associated with the symbol 160b60a18deSMichael J. Spencer Elf_Xword st_size; // Size of the symbol 161b60a18deSMichael J. Spencer }; 162b60a18deSMichael J. Spencer 163b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 164b60a18deSMichael J. Spencer struct Elf_Sym_Impl : Elf_Sym_Base<target_endianness, is64Bits> { 165b60a18deSMichael J. Spencer using Elf_Sym_Base<target_endianness, is64Bits>::st_info; 166b60a18deSMichael J. Spencer 167b60a18deSMichael J. Spencer // These accessors and mutators correspond to the ELF32_ST_BIND, 168b60a18deSMichael J. Spencer // ELF32_ST_TYPE, and ELF32_ST_INFO macros defined in the ELF specification: 169b60a18deSMichael J. Spencer unsigned char getBinding() const { return st_info >> 4; } 170b60a18deSMichael J. Spencer unsigned char getType() const { return st_info & 0x0f; } 171b60a18deSMichael J. Spencer void setBinding(unsigned char b) { setBindingAndType(b, getType()); } 172b60a18deSMichael J. Spencer void setType(unsigned char t) { setBindingAndType(getBinding(), t); } 173b60a18deSMichael J. Spencer void setBindingAndType(unsigned char b, unsigned char t) { 174b60a18deSMichael J. Spencer st_info = (b << 4) + (t & 0x0f); 175b60a18deSMichael J. Spencer } 176b60a18deSMichael J. Spencer }; 177b60a18deSMichael J. Spencer } 178b60a18deSMichael J. Spencer 179b60a18deSMichael J. Spencer namespace { 180022ecdf2SBenjamin Kramer template<support::endianness target_endianness, bool is64Bits, bool isRela> 181022ecdf2SBenjamin Kramer struct Elf_Rel_Base; 182022ecdf2SBenjamin Kramer 183022ecdf2SBenjamin Kramer template<support::endianness target_endianness> 184022ecdf2SBenjamin Kramer struct Elf_Rel_Base<target_endianness, false, false> { 185022ecdf2SBenjamin Kramer LLVM_ELF_IMPORT_TYPES(target_endianness, false) 186022ecdf2SBenjamin Kramer Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) 187022ecdf2SBenjamin Kramer Elf_Word r_info; // Symbol table index and type of relocation to apply 188022ecdf2SBenjamin Kramer }; 189022ecdf2SBenjamin Kramer 190022ecdf2SBenjamin Kramer template<support::endianness target_endianness> 191022ecdf2SBenjamin Kramer struct Elf_Rel_Base<target_endianness, true, false> { 192022ecdf2SBenjamin Kramer LLVM_ELF_IMPORT_TYPES(target_endianness, true) 193022ecdf2SBenjamin Kramer Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) 194022ecdf2SBenjamin Kramer Elf_Xword r_info; // Symbol table index and type of relocation to apply 195022ecdf2SBenjamin Kramer }; 196022ecdf2SBenjamin Kramer 197022ecdf2SBenjamin Kramer template<support::endianness target_endianness> 198022ecdf2SBenjamin Kramer struct Elf_Rel_Base<target_endianness, false, true> { 199022ecdf2SBenjamin Kramer LLVM_ELF_IMPORT_TYPES(target_endianness, false) 200022ecdf2SBenjamin Kramer Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) 201022ecdf2SBenjamin Kramer Elf_Word r_info; // Symbol table index and type of relocation to apply 202022ecdf2SBenjamin Kramer Elf_Sword r_addend; // Compute value for relocatable field by adding this 203022ecdf2SBenjamin Kramer }; 204022ecdf2SBenjamin Kramer 205022ecdf2SBenjamin Kramer template<support::endianness target_endianness> 206022ecdf2SBenjamin Kramer struct Elf_Rel_Base<target_endianness, true, true> { 207022ecdf2SBenjamin Kramer LLVM_ELF_IMPORT_TYPES(target_endianness, true) 208022ecdf2SBenjamin Kramer Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) 209022ecdf2SBenjamin Kramer Elf_Xword r_info; // Symbol table index and type of relocation to apply 210022ecdf2SBenjamin Kramer Elf_Sxword r_addend; // Compute value for relocatable field by adding this. 211022ecdf2SBenjamin Kramer }; 212022ecdf2SBenjamin Kramer 213022ecdf2SBenjamin Kramer template<support::endianness target_endianness, bool is64Bits, bool isRela> 214022ecdf2SBenjamin Kramer struct Elf_Rel_Impl; 215022ecdf2SBenjamin Kramer 216022ecdf2SBenjamin Kramer template<support::endianness target_endianness, bool isRela> 217022ecdf2SBenjamin Kramer struct Elf_Rel_Impl<target_endianness, true, isRela> 218022ecdf2SBenjamin Kramer : Elf_Rel_Base<target_endianness, true, isRela> { 219022ecdf2SBenjamin Kramer using Elf_Rel_Base<target_endianness, true, isRela>::r_info; 220022ecdf2SBenjamin Kramer LLVM_ELF_IMPORT_TYPES(target_endianness, true) 221022ecdf2SBenjamin Kramer 222022ecdf2SBenjamin Kramer // These accessors and mutators correspond to the ELF64_R_SYM, ELF64_R_TYPE, 223022ecdf2SBenjamin Kramer // and ELF64_R_INFO macros defined in the ELF specification: 224022ecdf2SBenjamin Kramer uint64_t getSymbol() const { return (r_info >> 32); } 225022ecdf2SBenjamin Kramer unsigned char getType() const { 226022ecdf2SBenjamin Kramer return (unsigned char) (r_info & 0xffffffffL); 227022ecdf2SBenjamin Kramer } 228022ecdf2SBenjamin Kramer void setSymbol(uint64_t s) { setSymbolAndType(s, getType()); } 229022ecdf2SBenjamin Kramer void setType(unsigned char t) { setSymbolAndType(getSymbol(), t); } 230022ecdf2SBenjamin Kramer void setSymbolAndType(uint64_t s, unsigned char t) { 231022ecdf2SBenjamin Kramer r_info = (s << 32) + (t&0xffffffffL); 232022ecdf2SBenjamin Kramer } 233022ecdf2SBenjamin Kramer }; 234022ecdf2SBenjamin Kramer 235022ecdf2SBenjamin Kramer template<support::endianness target_endianness, bool isRela> 236022ecdf2SBenjamin Kramer struct Elf_Rel_Impl<target_endianness, false, isRela> 237022ecdf2SBenjamin Kramer : Elf_Rel_Base<target_endianness, false, isRela> { 238022ecdf2SBenjamin Kramer using Elf_Rel_Base<target_endianness, false, isRela>::r_info; 239022ecdf2SBenjamin Kramer LLVM_ELF_IMPORT_TYPES(target_endianness, false) 240022ecdf2SBenjamin Kramer 241022ecdf2SBenjamin Kramer // These accessors and mutators correspond to the ELF32_R_SYM, ELF32_R_TYPE, 242022ecdf2SBenjamin Kramer // and ELF32_R_INFO macros defined in the ELF specification: 243022ecdf2SBenjamin Kramer uint32_t getSymbol() const { return (r_info >> 8); } 244022ecdf2SBenjamin Kramer unsigned char getType() const { return (unsigned char) (r_info & 0x0ff); } 245022ecdf2SBenjamin Kramer void setSymbol(uint32_t s) { setSymbolAndType(s, getType()); } 246022ecdf2SBenjamin Kramer void setType(unsigned char t) { setSymbolAndType(getSymbol(), t); } 247022ecdf2SBenjamin Kramer void setSymbolAndType(uint32_t s, unsigned char t) { 248022ecdf2SBenjamin Kramer r_info = (s << 8) + t; 249022ecdf2SBenjamin Kramer } 250022ecdf2SBenjamin Kramer }; 251022ecdf2SBenjamin Kramer 252022ecdf2SBenjamin Kramer } 253022ecdf2SBenjamin Kramer 254022ecdf2SBenjamin Kramer namespace { 255b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 256b60a18deSMichael J. Spencer class ELFObjectFile : public ObjectFile { 257b60a18deSMichael J. Spencer LLVM_ELF_IMPORT_TYPES(target_endianness, is64Bits) 258b60a18deSMichael J. Spencer 259b60a18deSMichael J. Spencer typedef Elf_Shdr_Impl<target_endianness, is64Bits> Elf_Shdr; 260b60a18deSMichael J. Spencer typedef Elf_Sym_Impl<target_endianness, is64Bits> Elf_Sym; 261022ecdf2SBenjamin Kramer typedef Elf_Rel_Impl<target_endianness, is64Bits, false> Elf_Rel; 262022ecdf2SBenjamin Kramer typedef Elf_Rel_Impl<target_endianness, is64Bits, true> Elf_Rela; 263b60a18deSMichael J. Spencer 264b60a18deSMichael J. Spencer struct Elf_Ehdr { 265b60a18deSMichael J. Spencer unsigned char e_ident[ELF::EI_NIDENT]; // ELF Identification bytes 266b60a18deSMichael J. Spencer Elf_Half e_type; // Type of file (see ET_*) 267b60a18deSMichael J. Spencer Elf_Half e_machine; // Required architecture for this file (see EM_*) 268b60a18deSMichael J. Spencer Elf_Word e_version; // Must be equal to 1 269b60a18deSMichael J. Spencer Elf_Addr e_entry; // Address to jump to in order to start program 270b60a18deSMichael J. Spencer Elf_Off e_phoff; // Program header table's file offset, in bytes 271b60a18deSMichael J. Spencer Elf_Off e_shoff; // Section header table's file offset, in bytes 272b60a18deSMichael J. Spencer Elf_Word e_flags; // Processor-specific flags 273b60a18deSMichael J. Spencer Elf_Half e_ehsize; // Size of ELF header, in bytes 274b60a18deSMichael J. Spencer Elf_Half e_phentsize;// Size of an entry in the program header table 275b60a18deSMichael J. Spencer Elf_Half e_phnum; // Number of entries in the program header table 276b60a18deSMichael J. Spencer Elf_Half e_shentsize;// Size of an entry in the section header table 277b60a18deSMichael J. Spencer Elf_Half e_shnum; // Number of entries in the section header table 278b60a18deSMichael J. Spencer Elf_Half e_shstrndx; // Section header table index of section name 279b60a18deSMichael J. Spencer // string table 280b60a18deSMichael J. Spencer bool checkMagic() const { 281b60a18deSMichael J. Spencer return (memcmp(e_ident, ELF::ElfMagic, strlen(ELF::ElfMagic))) == 0; 282b60a18deSMichael J. Spencer } 283b60a18deSMichael J. Spencer unsigned char getFileClass() const { return e_ident[ELF::EI_CLASS]; } 284b60a18deSMichael J. Spencer unsigned char getDataEncoding() const { return e_ident[ELF::EI_DATA]; } 285b60a18deSMichael J. Spencer }; 286b60a18deSMichael J. Spencer 287022ecdf2SBenjamin Kramer typedef SmallVector<const Elf_Shdr*, 1> Sections_t; 288022ecdf2SBenjamin Kramer typedef DenseMap<unsigned, unsigned> IndexMap_t; 289b60a18deSMichael J. Spencer 290b60a18deSMichael J. Spencer const Elf_Ehdr *Header; 291b60a18deSMichael J. Spencer const Elf_Shdr *SectionHeaderTable; 292b60a18deSMichael J. Spencer const Elf_Shdr *dot_shstrtab_sec; // Section header string table. 293b60a18deSMichael J. Spencer const Elf_Shdr *dot_strtab_sec; // Symbol header string table. 294022ecdf2SBenjamin Kramer Sections_t SymbolTableSections; 295022ecdf2SBenjamin Kramer IndexMap_t SymbolTableSectionsIndexMap; 296022ecdf2SBenjamin Kramer Sections_t RelocationTableSections; 297b60a18deSMichael J. Spencer 298b60a18deSMichael J. Spencer void validateSymbol(DataRefImpl Symb) const; 299022ecdf2SBenjamin Kramer bool isRelocationHasAddend(DataRefImpl Rel) const; 300022ecdf2SBenjamin Kramer template<typename T> 301022ecdf2SBenjamin Kramer const T *getEntry(DataRefImpl Entry, Sections_t Sections) const; 302b60a18deSMichael J. Spencer const Elf_Sym *getSymbol(DataRefImpl Symb) const; 303b60a18deSMichael J. Spencer const Elf_Shdr *getSection(DataRefImpl index) const; 304b60a18deSMichael J. Spencer const Elf_Shdr *getSection(uint16_t index) const; 305022ecdf2SBenjamin Kramer const Elf_Rel *getRel(DataRefImpl Rel) const; 306022ecdf2SBenjamin Kramer const Elf_Rela *getRela(DataRefImpl Rela) const; 307b60a18deSMichael J. Spencer const char *getString(uint16_t section, uint32_t offset) const; 308b60a18deSMichael J. Spencer const char *getString(const Elf_Shdr *section, uint32_t offset) const; 309b60a18deSMichael J. Spencer 310b60a18deSMichael J. Spencer protected: 3111d6167fdSMichael J. Spencer virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const; 3121d6167fdSMichael J. Spencer virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const; 31375d1cf33SBenjamin Kramer virtual error_code getSymbolOffset(DataRefImpl Symb, uint64_t &Res) const; 3141d6167fdSMichael J. Spencer virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const; 3151d6167fdSMichael J. Spencer virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const; 3161d6167fdSMichael J. Spencer virtual error_code getSymbolNMTypeChar(DataRefImpl Symb, char &Res) const; 3171d6167fdSMichael J. Spencer virtual error_code isSymbolInternal(DataRefImpl Symb, bool &Res) const; 31875d1cf33SBenjamin Kramer virtual error_code isSymbolGlobal(DataRefImpl Symb, bool &Res) const; 31975d1cf33SBenjamin Kramer virtual error_code getSymbolType(DataRefImpl Symb, SymbolRef::SymbolType &Res) const; 320b60a18deSMichael J. Spencer 3211d6167fdSMichael J. Spencer virtual error_code getSectionNext(DataRefImpl Sec, SectionRef &Res) const; 3221d6167fdSMichael J. Spencer virtual error_code getSectionName(DataRefImpl Sec, StringRef &Res) const; 3231d6167fdSMichael J. Spencer virtual error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const; 3241d6167fdSMichael J. Spencer virtual error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const; 3251d6167fdSMichael J. Spencer virtual error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const; 3261d6167fdSMichael J. Spencer virtual error_code isSectionText(DataRefImpl Sec, bool &Res) const; 327*800619f2SMichael J. Spencer virtual error_code isSectionData(DataRefImpl Sec, bool &Res) const; 328*800619f2SMichael J. Spencer virtual error_code isSectionBSS(DataRefImpl Sec, bool &Res) const; 329f6f3e81cSBenjamin Kramer virtual error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, 330f6f3e81cSBenjamin Kramer bool &Result) const; 331b60a18deSMichael J. Spencer 332022ecdf2SBenjamin Kramer virtual error_code getRelocationNext(DataRefImpl Rel, 333022ecdf2SBenjamin Kramer RelocationRef &Res) const; 334022ecdf2SBenjamin Kramer virtual error_code getRelocationAddress(DataRefImpl Rel, 335022ecdf2SBenjamin Kramer uint64_t &Res) const; 336022ecdf2SBenjamin Kramer virtual error_code getRelocationSymbol(DataRefImpl Rel, 337022ecdf2SBenjamin Kramer SymbolRef &Res) const; 338022ecdf2SBenjamin Kramer virtual error_code getRelocationType(DataRefImpl Rel, 339022ecdf2SBenjamin Kramer uint32_t &Res) const; 340022ecdf2SBenjamin Kramer virtual error_code getRelocationAdditionalInfo(DataRefImpl Rel, 341022ecdf2SBenjamin Kramer int64_t &Res) const; 342022ecdf2SBenjamin Kramer 343b60a18deSMichael J. Spencer public: 344ec29b121SMichael J. Spencer ELFObjectFile(MemoryBuffer *Object, error_code &ec); 345b60a18deSMichael J. Spencer virtual symbol_iterator begin_symbols() const; 346b60a18deSMichael J. Spencer virtual symbol_iterator end_symbols() const; 347b60a18deSMichael J. Spencer virtual section_iterator begin_sections() const; 348b60a18deSMichael J. Spencer virtual section_iterator end_sections() const; 349022ecdf2SBenjamin Kramer virtual relocation_iterator begin_relocations() const; 350022ecdf2SBenjamin Kramer virtual relocation_iterator end_relocations() const; 351b60a18deSMichael J. Spencer 352b60a18deSMichael J. Spencer virtual uint8_t getBytesInAddress() const; 353b60a18deSMichael J. Spencer virtual StringRef getFileFormatName() const; 354b60a18deSMichael J. Spencer virtual unsigned getArch() const; 355b60a18deSMichael J. Spencer }; 356b60a18deSMichael J. Spencer } // end namespace 357b60a18deSMichael J. Spencer 358b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 359b60a18deSMichael J. Spencer void ELFObjectFile<target_endianness, is64Bits> 360b60a18deSMichael J. Spencer ::validateSymbol(DataRefImpl Symb) const { 361b60a18deSMichael J. Spencer const Elf_Sym *symb = getSymbol(Symb); 3620324b672SMichael J. Spencer const Elf_Shdr *SymbolTableSection = SymbolTableSections[Symb.d.b]; 363b60a18deSMichael J. Spencer // FIXME: We really need to do proper error handling in the case of an invalid 364b60a18deSMichael J. Spencer // input file. Because we don't use exceptions, I think we'll just pass 365b60a18deSMichael J. Spencer // an error object around. 366b60a18deSMichael J. Spencer if (!( symb 367b60a18deSMichael J. Spencer && SymbolTableSection 368ec29b121SMichael J. Spencer && symb >= (const Elf_Sym*)(base() 369b60a18deSMichael J. Spencer + SymbolTableSection->sh_offset) 370ec29b121SMichael J. Spencer && symb < (const Elf_Sym*)(base() 371b60a18deSMichael J. Spencer + SymbolTableSection->sh_offset 372b60a18deSMichael J. Spencer + SymbolTableSection->sh_size))) 373b60a18deSMichael J. Spencer // FIXME: Proper error handling. 374b60a18deSMichael J. Spencer report_fatal_error("Symb must point to a valid symbol!"); 375b60a18deSMichael J. Spencer } 376b60a18deSMichael J. Spencer 377b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 3781d6167fdSMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits> 3791d6167fdSMichael J. Spencer ::getSymbolNext(DataRefImpl Symb, 3801d6167fdSMichael J. Spencer SymbolRef &Result) const { 381b60a18deSMichael J. Spencer validateSymbol(Symb); 3820324b672SMichael J. Spencer const Elf_Shdr *SymbolTableSection = SymbolTableSections[Symb.d.b]; 383b60a18deSMichael J. Spencer 3840324b672SMichael J. Spencer ++Symb.d.a; 385b60a18deSMichael J. Spencer // Check to see if we are at the end of this symbol table. 3860324b672SMichael J. Spencer if (Symb.d.a >= SymbolTableSection->getEntityCount()) { 387b60a18deSMichael J. Spencer // We are at the end. If there are other symbol tables, jump to them. 3880324b672SMichael J. Spencer ++Symb.d.b; 3890324b672SMichael J. Spencer Symb.d.a = 1; // The 0th symbol in ELF is fake. 390b60a18deSMichael J. Spencer // Otherwise return the terminator. 3910324b672SMichael J. Spencer if (Symb.d.b >= SymbolTableSections.size()) { 3920324b672SMichael J. Spencer Symb.d.a = std::numeric_limits<uint32_t>::max(); 3930324b672SMichael J. Spencer Symb.d.b = std::numeric_limits<uint32_t>::max(); 394b60a18deSMichael J. Spencer } 395b60a18deSMichael J. Spencer } 396b60a18deSMichael J. Spencer 3971d6167fdSMichael J. Spencer Result = SymbolRef(Symb, this); 3981d6167fdSMichael J. Spencer return object_error::success; 399b60a18deSMichael J. Spencer } 400b60a18deSMichael J. Spencer 401b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 4021d6167fdSMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits> 4031d6167fdSMichael J. Spencer ::getSymbolName(DataRefImpl Symb, 4041d6167fdSMichael J. Spencer StringRef &Result) const { 405b60a18deSMichael J. Spencer validateSymbol(Symb); 406b60a18deSMichael J. Spencer const Elf_Sym *symb = getSymbol(Symb); 407b60a18deSMichael J. Spencer if (symb->st_name == 0) { 408b60a18deSMichael J. Spencer const Elf_Shdr *section = getSection(symb->st_shndx); 409b60a18deSMichael J. Spencer if (!section) 4101d6167fdSMichael J. Spencer Result = ""; 4111d6167fdSMichael J. Spencer else 4121d6167fdSMichael J. Spencer Result = getString(dot_shstrtab_sec, section->sh_name); 4131d6167fdSMichael J. Spencer return object_error::success; 414b60a18deSMichael J. Spencer } 415b60a18deSMichael J. Spencer 416b60a18deSMichael J. Spencer // Use the default symbol table name section. 4171d6167fdSMichael J. Spencer Result = getString(dot_strtab_sec, symb->st_name); 4181d6167fdSMichael J. Spencer return object_error::success; 419b60a18deSMichael J. Spencer } 420b60a18deSMichael J. Spencer 421b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 4221d6167fdSMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits> 42375d1cf33SBenjamin Kramer ::getSymbolOffset(DataRefImpl Symb, 4241d6167fdSMichael J. Spencer uint64_t &Result) const { 425b60a18deSMichael J. Spencer validateSymbol(Symb); 426b60a18deSMichael J. Spencer const Elf_Sym *symb = getSymbol(Symb); 427b60a18deSMichael J. Spencer const Elf_Shdr *Section; 428b60a18deSMichael J. Spencer switch (symb->st_shndx) { 429b60a18deSMichael J. Spencer case ELF::SHN_COMMON: 430b60a18deSMichael J. Spencer // Undefined symbols have no address yet. 4311d6167fdSMichael J. Spencer case ELF::SHN_UNDEF: 4321d6167fdSMichael J. Spencer Result = UnknownAddressOrSize; 4331d6167fdSMichael J. Spencer return object_error::success; 4341d6167fdSMichael J. Spencer case ELF::SHN_ABS: 4351d6167fdSMichael J. Spencer Result = symb->st_value; 4361d6167fdSMichael J. Spencer return object_error::success; 437b60a18deSMichael J. Spencer default: Section = getSection(symb->st_shndx); 438b60a18deSMichael J. Spencer } 439b60a18deSMichael J. Spencer 440b60a18deSMichael J. Spencer switch (symb->getType()) { 4411d6167fdSMichael J. Spencer case ELF::STT_SECTION: 4421d6167fdSMichael J. Spencer Result = Section ? Section->sh_addr : UnknownAddressOrSize; 4431d6167fdSMichael J. Spencer return object_error::success; 444b60a18deSMichael J. Spencer case ELF::STT_FUNC: 445b60a18deSMichael J. Spencer case ELF::STT_OBJECT: 446b60a18deSMichael J. Spencer case ELF::STT_NOTYPE: 4471d6167fdSMichael J. Spencer Result = symb->st_value; 4481d6167fdSMichael J. Spencer return object_error::success; 4491d6167fdSMichael J. Spencer default: 4501d6167fdSMichael J. Spencer Result = UnknownAddressOrSize; 4511d6167fdSMichael J. Spencer return object_error::success; 452b60a18deSMichael J. Spencer } 453b60a18deSMichael J. Spencer } 454b60a18deSMichael J. Spencer 455b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 4561d6167fdSMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits> 45775d1cf33SBenjamin Kramer ::getSymbolAddress(DataRefImpl Symb, 45875d1cf33SBenjamin Kramer uint64_t &Result) const { 45975d1cf33SBenjamin Kramer validateSymbol(Symb); 46075d1cf33SBenjamin Kramer const Elf_Sym *symb = getSymbol(Symb); 46175d1cf33SBenjamin Kramer const Elf_Shdr *Section; 46275d1cf33SBenjamin Kramer switch (symb->st_shndx) { 46375d1cf33SBenjamin Kramer case ELF::SHN_COMMON: // Fall through. 46475d1cf33SBenjamin Kramer // Undefined symbols have no address yet. 46575d1cf33SBenjamin Kramer case ELF::SHN_UNDEF: 46675d1cf33SBenjamin Kramer Result = UnknownAddressOrSize; 46775d1cf33SBenjamin Kramer return object_error::success; 46875d1cf33SBenjamin Kramer case ELF::SHN_ABS: 46975d1cf33SBenjamin Kramer Result = reinterpret_cast<uintptr_t>(base()+symb->st_value); 47075d1cf33SBenjamin Kramer return object_error::success; 47175d1cf33SBenjamin Kramer default: Section = getSection(symb->st_shndx); 47275d1cf33SBenjamin Kramer } 47375d1cf33SBenjamin Kramer const uint8_t* addr = base(); 47475d1cf33SBenjamin Kramer if (Section) 47575d1cf33SBenjamin Kramer addr += Section->sh_offset; 47675d1cf33SBenjamin Kramer switch (symb->getType()) { 47775d1cf33SBenjamin Kramer case ELF::STT_SECTION: 47875d1cf33SBenjamin Kramer Result = reinterpret_cast<uintptr_t>(addr); 47975d1cf33SBenjamin Kramer return object_error::success; 48075d1cf33SBenjamin Kramer case ELF::STT_FUNC: // Fall through. 48175d1cf33SBenjamin Kramer case ELF::STT_OBJECT: // Fall through. 48275d1cf33SBenjamin Kramer case ELF::STT_NOTYPE: 48375d1cf33SBenjamin Kramer addr += symb->st_value; 48475d1cf33SBenjamin Kramer Result = reinterpret_cast<uintptr_t>(addr); 48575d1cf33SBenjamin Kramer return object_error::success; 48675d1cf33SBenjamin Kramer default: 48775d1cf33SBenjamin Kramer Result = UnknownAddressOrSize; 48875d1cf33SBenjamin Kramer return object_error::success; 48975d1cf33SBenjamin Kramer } 49075d1cf33SBenjamin Kramer } 49175d1cf33SBenjamin Kramer 49275d1cf33SBenjamin Kramer template<support::endianness target_endianness, bool is64Bits> 49375d1cf33SBenjamin Kramer error_code ELFObjectFile<target_endianness, is64Bits> 4941d6167fdSMichael J. Spencer ::getSymbolSize(DataRefImpl Symb, 4951d6167fdSMichael J. Spencer uint64_t &Result) const { 496b60a18deSMichael J. Spencer validateSymbol(Symb); 497b60a18deSMichael J. Spencer const Elf_Sym *symb = getSymbol(Symb); 498b60a18deSMichael J. Spencer if (symb->st_size == 0) 4991d6167fdSMichael J. Spencer Result = UnknownAddressOrSize; 5001d6167fdSMichael J. Spencer Result = symb->st_size; 5011d6167fdSMichael J. Spencer return object_error::success; 502b60a18deSMichael J. Spencer } 503b60a18deSMichael J. Spencer 504b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 5051d6167fdSMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits> 5061d6167fdSMichael J. Spencer ::getSymbolNMTypeChar(DataRefImpl Symb, 5071d6167fdSMichael J. Spencer char &Result) const { 508b60a18deSMichael J. Spencer validateSymbol(Symb); 509b60a18deSMichael J. Spencer const Elf_Sym *symb = getSymbol(Symb); 510b60a18deSMichael J. Spencer const Elf_Shdr *Section = getSection(symb->st_shndx); 511b60a18deSMichael J. Spencer 512b60a18deSMichael J. Spencer char ret = '?'; 513b60a18deSMichael J. Spencer 514b60a18deSMichael J. Spencer if (Section) { 515b60a18deSMichael J. Spencer switch (Section->sh_type) { 516b60a18deSMichael J. Spencer case ELF::SHT_PROGBITS: 517b60a18deSMichael J. Spencer case ELF::SHT_DYNAMIC: 518b60a18deSMichael J. Spencer switch (Section->sh_flags) { 519b60a18deSMichael J. Spencer case (ELF::SHF_ALLOC | ELF::SHF_EXECINSTR): 520b60a18deSMichael J. Spencer ret = 't'; break; 521b60a18deSMichael J. Spencer case (ELF::SHF_ALLOC | ELF::SHF_WRITE): 522b60a18deSMichael J. Spencer ret = 'd'; break; 523b60a18deSMichael J. Spencer case ELF::SHF_ALLOC: 524b60a18deSMichael J. Spencer case (ELF::SHF_ALLOC | ELF::SHF_MERGE): 525b60a18deSMichael J. Spencer case (ELF::SHF_ALLOC | ELF::SHF_MERGE | ELF::SHF_STRINGS): 526b60a18deSMichael J. Spencer ret = 'r'; break; 527b60a18deSMichael J. Spencer } 528b60a18deSMichael J. Spencer break; 529b60a18deSMichael J. Spencer case ELF::SHT_NOBITS: ret = 'b'; 530b60a18deSMichael J. Spencer } 531b60a18deSMichael J. Spencer } 532b60a18deSMichael J. Spencer 533b60a18deSMichael J. Spencer switch (symb->st_shndx) { 534b60a18deSMichael J. Spencer case ELF::SHN_UNDEF: 535b60a18deSMichael J. Spencer if (ret == '?') 536b60a18deSMichael J. Spencer ret = 'U'; 537b60a18deSMichael J. Spencer break; 538b60a18deSMichael J. Spencer case ELF::SHN_ABS: ret = 'a'; break; 539b60a18deSMichael J. Spencer case ELF::SHN_COMMON: ret = 'c'; break; 540b60a18deSMichael J. Spencer } 541b60a18deSMichael J. Spencer 542b60a18deSMichael J. Spencer switch (symb->getBinding()) { 543b60a18deSMichael J. Spencer case ELF::STB_GLOBAL: ret = ::toupper(ret); break; 544b60a18deSMichael J. Spencer case ELF::STB_WEAK: 545b60a18deSMichael J. Spencer if (symb->st_shndx == ELF::SHN_UNDEF) 546b60a18deSMichael J. Spencer ret = 'w'; 547b60a18deSMichael J. Spencer else 548b60a18deSMichael J. Spencer if (symb->getType() == ELF::STT_OBJECT) 549b60a18deSMichael J. Spencer ret = 'V'; 550b60a18deSMichael J. Spencer else 551b60a18deSMichael J. Spencer ret = 'W'; 552b60a18deSMichael J. Spencer } 553b60a18deSMichael J. Spencer 5541d6167fdSMichael J. Spencer if (ret == '?' && symb->getType() == ELF::STT_SECTION) { 5551d6167fdSMichael J. Spencer StringRef name; 5561d6167fdSMichael J. Spencer if (error_code ec = getSymbolName(Symb, name)) 5571d6167fdSMichael J. Spencer return ec; 5581d6167fdSMichael J. Spencer Result = StringSwitch<char>(name) 559b60a18deSMichael J. Spencer .StartsWith(".debug", 'N') 560022ecdf2SBenjamin Kramer .StartsWith(".note", 'n') 561022ecdf2SBenjamin Kramer .Default('?'); 5621d6167fdSMichael J. Spencer return object_error::success; 5631d6167fdSMichael J. Spencer } 564b60a18deSMichael J. Spencer 5651d6167fdSMichael J. Spencer Result = ret; 5661d6167fdSMichael J. Spencer return object_error::success; 567b60a18deSMichael J. Spencer } 568b60a18deSMichael J. Spencer 569b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 5701d6167fdSMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits> 57175d1cf33SBenjamin Kramer ::getSymbolType(DataRefImpl Symb, 57275d1cf33SBenjamin Kramer SymbolRef::SymbolType &Result) const { 57375d1cf33SBenjamin Kramer validateSymbol(Symb); 57475d1cf33SBenjamin Kramer const Elf_Sym *symb = getSymbol(Symb); 57575d1cf33SBenjamin Kramer 57675d1cf33SBenjamin Kramer if (symb->st_shndx == ELF::SHN_UNDEF) { 57775d1cf33SBenjamin Kramer Result = SymbolRef::ST_External; 57875d1cf33SBenjamin Kramer return object_error::success; 57975d1cf33SBenjamin Kramer } 58075d1cf33SBenjamin Kramer 58175d1cf33SBenjamin Kramer switch (symb->getType()) { 58275d1cf33SBenjamin Kramer case ELF::STT_FUNC: 58375d1cf33SBenjamin Kramer Result = SymbolRef::ST_Function; 58475d1cf33SBenjamin Kramer break; 58575d1cf33SBenjamin Kramer case ELF::STT_OBJECT: 58675d1cf33SBenjamin Kramer Result = SymbolRef::ST_Data; 58775d1cf33SBenjamin Kramer break; 58875d1cf33SBenjamin Kramer default: 58975d1cf33SBenjamin Kramer Result = SymbolRef::ST_Other; 59075d1cf33SBenjamin Kramer break; 59175d1cf33SBenjamin Kramer } 59275d1cf33SBenjamin Kramer return object_error::success; 59375d1cf33SBenjamin Kramer } 59475d1cf33SBenjamin Kramer 59575d1cf33SBenjamin Kramer template<support::endianness target_endianness, bool is64Bits> 59675d1cf33SBenjamin Kramer error_code ELFObjectFile<target_endianness, is64Bits> 59775d1cf33SBenjamin Kramer ::isSymbolGlobal(DataRefImpl Symb, 59875d1cf33SBenjamin Kramer bool &Result) const { 59975d1cf33SBenjamin Kramer validateSymbol(Symb); 60075d1cf33SBenjamin Kramer const Elf_Sym *symb = getSymbol(Symb); 60175d1cf33SBenjamin Kramer 60275d1cf33SBenjamin Kramer Result = symb->getBinding() == ELF::STB_GLOBAL; 60375d1cf33SBenjamin Kramer return object_error::success; 60475d1cf33SBenjamin Kramer } 60575d1cf33SBenjamin Kramer 60675d1cf33SBenjamin Kramer template<support::endianness target_endianness, bool is64Bits> 60775d1cf33SBenjamin Kramer error_code ELFObjectFile<target_endianness, is64Bits> 6081d6167fdSMichael J. Spencer ::isSymbolInternal(DataRefImpl Symb, 6091d6167fdSMichael J. Spencer bool &Result) const { 610b60a18deSMichael J. Spencer validateSymbol(Symb); 611b60a18deSMichael J. Spencer const Elf_Sym *symb = getSymbol(Symb); 612b60a18deSMichael J. Spencer 613b60a18deSMichael J. Spencer if ( symb->getType() == ELF::STT_FILE 614b60a18deSMichael J. Spencer || symb->getType() == ELF::STT_SECTION) 6151d6167fdSMichael J. Spencer Result = true; 6161d6167fdSMichael J. Spencer Result = false; 6171d6167fdSMichael J. Spencer return object_error::success; 618b60a18deSMichael J. Spencer } 619b60a18deSMichael J. Spencer 620b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 6211d6167fdSMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits> 6221d6167fdSMichael J. Spencer ::getSectionNext(DataRefImpl Sec, SectionRef &Result) const { 6230324b672SMichael J. Spencer const uint8_t *sec = reinterpret_cast<const uint8_t *>(Sec.p); 624b60a18deSMichael J. Spencer sec += Header->e_shentsize; 6250324b672SMichael J. Spencer Sec.p = reinterpret_cast<intptr_t>(sec); 6261d6167fdSMichael J. Spencer Result = SectionRef(Sec, this); 6271d6167fdSMichael J. Spencer return object_error::success; 628b60a18deSMichael J. Spencer } 629b60a18deSMichael J. Spencer 630b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 6311d6167fdSMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits> 6321d6167fdSMichael J. Spencer ::getSectionName(DataRefImpl Sec, 6331d6167fdSMichael J. Spencer StringRef &Result) const { 6340324b672SMichael J. Spencer const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); 6351d6167fdSMichael J. Spencer Result = StringRef(getString(dot_shstrtab_sec, sec->sh_name)); 6361d6167fdSMichael J. Spencer return object_error::success; 637b60a18deSMichael J. Spencer } 638b60a18deSMichael J. Spencer 639b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 6401d6167fdSMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits> 6411d6167fdSMichael J. Spencer ::getSectionAddress(DataRefImpl Sec, 6421d6167fdSMichael J. Spencer uint64_t &Result) const { 6430324b672SMichael J. Spencer const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); 6441d6167fdSMichael J. Spencer Result = sec->sh_addr; 6451d6167fdSMichael J. Spencer return object_error::success; 646b60a18deSMichael J. Spencer } 647b60a18deSMichael J. Spencer 648b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 6491d6167fdSMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits> 6501d6167fdSMichael J. Spencer ::getSectionSize(DataRefImpl Sec, 6511d6167fdSMichael J. Spencer uint64_t &Result) const { 6520324b672SMichael J. Spencer const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); 6531d6167fdSMichael J. Spencer Result = sec->sh_size; 6541d6167fdSMichael J. Spencer return object_error::success; 655b60a18deSMichael J. Spencer } 656b60a18deSMichael J. Spencer 657b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 6581d6167fdSMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits> 6591d6167fdSMichael J. Spencer ::getSectionContents(DataRefImpl Sec, 6601d6167fdSMichael J. Spencer StringRef &Result) const { 6610324b672SMichael J. Spencer const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); 6621d6167fdSMichael J. Spencer const char *start = (const char*)base() + sec->sh_offset; 6631d6167fdSMichael J. Spencer Result = StringRef(start, sec->sh_size); 6641d6167fdSMichael J. Spencer return object_error::success; 665b60a18deSMichael J. Spencer } 666b60a18deSMichael J. Spencer 667b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 6681d6167fdSMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits> 6691d6167fdSMichael J. Spencer ::isSectionText(DataRefImpl Sec, 6701d6167fdSMichael J. Spencer bool &Result) const { 6710324b672SMichael J. Spencer const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); 672b60a18deSMichael J. Spencer if (sec->sh_flags & ELF::SHF_EXECINSTR) 6731d6167fdSMichael J. Spencer Result = true; 6741d6167fdSMichael J. Spencer else 6751d6167fdSMichael J. Spencer Result = false; 6761d6167fdSMichael J. Spencer return object_error::success; 677b60a18deSMichael J. Spencer } 678b60a18deSMichael J. Spencer 679b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 680f6f3e81cSBenjamin Kramer error_code ELFObjectFile<target_endianness, is64Bits> 681*800619f2SMichael J. Spencer ::isSectionData(DataRefImpl Sec, 682*800619f2SMichael J. Spencer bool &Result) const { 683*800619f2SMichael J. Spencer const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); 684*800619f2SMichael J. Spencer if (sec->sh_flags & (ELF::SHF_ALLOC | ELF::SHF_WRITE) 685*800619f2SMichael J. Spencer && sec->sh_type == ELF::SHT_PROGBITS) 686*800619f2SMichael J. Spencer Result = true; 687*800619f2SMichael J. Spencer else 688*800619f2SMichael J. Spencer Result = false; 689*800619f2SMichael J. Spencer return object_error::success; 690*800619f2SMichael J. Spencer } 691*800619f2SMichael J. Spencer 692*800619f2SMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 693*800619f2SMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits> 694*800619f2SMichael J. Spencer ::isSectionBSS(DataRefImpl Sec, 695*800619f2SMichael J. Spencer bool &Result) const { 696*800619f2SMichael J. Spencer const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); 697*800619f2SMichael J. Spencer if (sec->sh_flags & (ELF::SHF_ALLOC | ELF::SHF_WRITE) 698*800619f2SMichael J. Spencer && sec->sh_type == ELF::SHT_NOBITS) 699*800619f2SMichael J. Spencer Result = true; 700*800619f2SMichael J. Spencer else 701*800619f2SMichael J. Spencer Result = false; 702*800619f2SMichael J. Spencer return object_error::success; 703*800619f2SMichael J. Spencer } 704*800619f2SMichael J. Spencer 705*800619f2SMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 706*800619f2SMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits> 707f6f3e81cSBenjamin Kramer ::sectionContainsSymbol(DataRefImpl Sec, 708f6f3e81cSBenjamin Kramer DataRefImpl Symb, 709f6f3e81cSBenjamin Kramer bool &Result) const { 710f6f3e81cSBenjamin Kramer // FIXME: Unimplemented. 711f6f3e81cSBenjamin Kramer Result = false; 712f6f3e81cSBenjamin Kramer return object_error::success; 713f6f3e81cSBenjamin Kramer } 714f6f3e81cSBenjamin Kramer 715022ecdf2SBenjamin Kramer // Relocations 716022ecdf2SBenjamin Kramer template<support::endianness target_endianness, bool is64Bits> 717022ecdf2SBenjamin Kramer error_code ELFObjectFile<target_endianness, is64Bits> 718022ecdf2SBenjamin Kramer ::getRelocationNext(DataRefImpl Rel, 719022ecdf2SBenjamin Kramer RelocationRef &Result) const { 720022ecdf2SBenjamin Kramer const Elf_Shdr *RelocationTableSection = RelocationTableSections[Rel.d.b]; 721022ecdf2SBenjamin Kramer 722022ecdf2SBenjamin Kramer // Check to see if we are at the end of this relocation table. 723022ecdf2SBenjamin Kramer if (++Rel.d.a >= RelocationTableSection->getEntityCount()) { 724022ecdf2SBenjamin Kramer // We are at the end. If there are other relocation tables, jump to them. 725022ecdf2SBenjamin Kramer Rel.d.a = 0; 726022ecdf2SBenjamin Kramer // Otherwise return the terminator. 727022ecdf2SBenjamin Kramer if (++Rel.d.b >= SymbolTableSections.size()) { 728022ecdf2SBenjamin Kramer Rel.d.a = std::numeric_limits<uint32_t>::max(); 729022ecdf2SBenjamin Kramer Rel.d.b = std::numeric_limits<uint32_t>::max(); 730022ecdf2SBenjamin Kramer } 731022ecdf2SBenjamin Kramer } 732022ecdf2SBenjamin Kramer 733022ecdf2SBenjamin Kramer Result = RelocationRef(Rel, this); 734022ecdf2SBenjamin Kramer return object_error::success; 735022ecdf2SBenjamin Kramer } 736022ecdf2SBenjamin Kramer 737022ecdf2SBenjamin Kramer template<support::endianness target_endianness, bool is64Bits> 738022ecdf2SBenjamin Kramer error_code ELFObjectFile<target_endianness, is64Bits> 739022ecdf2SBenjamin Kramer ::getRelocationSymbol(DataRefImpl Rel, 740022ecdf2SBenjamin Kramer SymbolRef &Result) const { 741022ecdf2SBenjamin Kramer uint32_t symbolIdx; 742022ecdf2SBenjamin Kramer const Elf_Shdr *sec = RelocationTableSections[Rel.d.b]; 743022ecdf2SBenjamin Kramer switch (sec->sh_type) { 744022ecdf2SBenjamin Kramer default : 745022ecdf2SBenjamin Kramer report_fatal_error("Invalid section type in Rel!"); 746022ecdf2SBenjamin Kramer case ELF::SHT_REL : { 747022ecdf2SBenjamin Kramer symbolIdx = getRel(Rel)->getSymbol(); 748022ecdf2SBenjamin Kramer break; 749022ecdf2SBenjamin Kramer } 750022ecdf2SBenjamin Kramer case ELF::SHT_RELA : { 751022ecdf2SBenjamin Kramer symbolIdx = getRela(Rel)->getSymbol(); 752022ecdf2SBenjamin Kramer break; 753022ecdf2SBenjamin Kramer } 754022ecdf2SBenjamin Kramer } 755022ecdf2SBenjamin Kramer DataRefImpl SymbolData; 756022ecdf2SBenjamin Kramer IndexMap_t::const_iterator it = SymbolTableSectionsIndexMap.find(sec->sh_link); 757022ecdf2SBenjamin Kramer if (it == SymbolTableSectionsIndexMap.end()) 758022ecdf2SBenjamin Kramer report_fatal_error("Relocation symbol table not found!"); 759022ecdf2SBenjamin Kramer SymbolData.d.a = symbolIdx; 760022ecdf2SBenjamin Kramer SymbolData.d.b = it->second; 761022ecdf2SBenjamin Kramer Result = SymbolRef(SymbolData, this); 762022ecdf2SBenjamin Kramer return object_error::success; 763022ecdf2SBenjamin Kramer } 764022ecdf2SBenjamin Kramer 765022ecdf2SBenjamin Kramer template<support::endianness target_endianness, bool is64Bits> 766022ecdf2SBenjamin Kramer error_code ELFObjectFile<target_endianness, is64Bits> 767022ecdf2SBenjamin Kramer ::getRelocationAddress(DataRefImpl Rel, 768022ecdf2SBenjamin Kramer uint64_t &Result) const { 769022ecdf2SBenjamin Kramer uint64_t offset; 770022ecdf2SBenjamin Kramer const Elf_Shdr *sec = RelocationTableSections[Rel.d.b]; 771022ecdf2SBenjamin Kramer switch (sec->sh_type) { 772022ecdf2SBenjamin Kramer default : 773022ecdf2SBenjamin Kramer report_fatal_error("Invalid section type in Rel!"); 774022ecdf2SBenjamin Kramer case ELF::SHT_REL : { 775022ecdf2SBenjamin Kramer offset = getRel(Rel)->r_offset; 776022ecdf2SBenjamin Kramer break; 777022ecdf2SBenjamin Kramer } 778022ecdf2SBenjamin Kramer case ELF::SHT_RELA : { 779022ecdf2SBenjamin Kramer offset = getRela(Rel)->r_offset; 780022ecdf2SBenjamin Kramer break; 781022ecdf2SBenjamin Kramer } 782022ecdf2SBenjamin Kramer } 783022ecdf2SBenjamin Kramer 784022ecdf2SBenjamin Kramer const Elf_Shdr *secAddr = getSection(sec->sh_info); 785022ecdf2SBenjamin Kramer Result = offset + reinterpret_cast<uintptr_t>(base() + secAddr->sh_offset); 786022ecdf2SBenjamin Kramer return object_error::success; 787022ecdf2SBenjamin Kramer } 788022ecdf2SBenjamin Kramer 789022ecdf2SBenjamin Kramer template<support::endianness target_endianness, bool is64Bits> 790022ecdf2SBenjamin Kramer error_code ELFObjectFile<target_endianness, is64Bits> 791022ecdf2SBenjamin Kramer ::getRelocationType(DataRefImpl Rel, 792022ecdf2SBenjamin Kramer uint32_t &Result) const { 793022ecdf2SBenjamin Kramer const Elf_Shdr *sec = RelocationTableSections[Rel.d.b]; 794022ecdf2SBenjamin Kramer switch (sec->sh_type) { 795022ecdf2SBenjamin Kramer default : 796022ecdf2SBenjamin Kramer report_fatal_error("Invalid section type in Rel!"); 797022ecdf2SBenjamin Kramer case ELF::SHT_REL : { 798022ecdf2SBenjamin Kramer Result = getRel(Rel)->getType(); 799022ecdf2SBenjamin Kramer break; 800022ecdf2SBenjamin Kramer } 801022ecdf2SBenjamin Kramer case ELF::SHT_RELA : { 802022ecdf2SBenjamin Kramer Result = getRela(Rel)->getType(); 803022ecdf2SBenjamin Kramer break; 804022ecdf2SBenjamin Kramer } 805022ecdf2SBenjamin Kramer } 806022ecdf2SBenjamin Kramer return object_error::success; 807022ecdf2SBenjamin Kramer } 808022ecdf2SBenjamin Kramer 809022ecdf2SBenjamin Kramer template<support::endianness target_endianness, bool is64Bits> 810022ecdf2SBenjamin Kramer error_code ELFObjectFile<target_endianness, is64Bits> 811022ecdf2SBenjamin Kramer ::getRelocationAdditionalInfo(DataRefImpl Rel, 812022ecdf2SBenjamin Kramer int64_t &Result) const { 813022ecdf2SBenjamin Kramer const Elf_Shdr *sec = RelocationTableSections[Rel.d.b]; 814022ecdf2SBenjamin Kramer switch (sec->sh_type) { 815022ecdf2SBenjamin Kramer default : 816022ecdf2SBenjamin Kramer report_fatal_error("Invalid section type in Rel!"); 817022ecdf2SBenjamin Kramer case ELF::SHT_REL : { 818022ecdf2SBenjamin Kramer Result = 0; 819022ecdf2SBenjamin Kramer return object_error::success; 820022ecdf2SBenjamin Kramer } 821022ecdf2SBenjamin Kramer case ELF::SHT_RELA : { 822022ecdf2SBenjamin Kramer Result = getRela(Rel)->r_addend; 823022ecdf2SBenjamin Kramer return object_error::success; 824022ecdf2SBenjamin Kramer } 825022ecdf2SBenjamin Kramer } 826022ecdf2SBenjamin Kramer } 827022ecdf2SBenjamin Kramer 828022ecdf2SBenjamin Kramer 829022ecdf2SBenjamin Kramer 830f6f3e81cSBenjamin Kramer template<support::endianness target_endianness, bool is64Bits> 831ec29b121SMichael J. Spencer ELFObjectFile<target_endianness, is64Bits>::ELFObjectFile(MemoryBuffer *Object 832ec29b121SMichael J. Spencer , error_code &ec) 833ec29b121SMichael J. Spencer : ObjectFile(Binary::isELF, Object, ec) 834b60a18deSMichael J. Spencer , SectionHeaderTable(0) 835b60a18deSMichael J. Spencer , dot_shstrtab_sec(0) 836b60a18deSMichael J. Spencer , dot_strtab_sec(0) { 837ec29b121SMichael J. Spencer Header = reinterpret_cast<const Elf_Ehdr *>(base()); 838b60a18deSMichael J. Spencer 839b60a18deSMichael J. Spencer if (Header->e_shoff == 0) 840b60a18deSMichael J. Spencer return; 841b60a18deSMichael J. Spencer 842b60a18deSMichael J. Spencer SectionHeaderTable = 843ec29b121SMichael J. Spencer reinterpret_cast<const Elf_Shdr *>(base() + Header->e_shoff); 844b60a18deSMichael J. Spencer uint32_t SectionTableSize = Header->e_shnum * Header->e_shentsize; 845b60a18deSMichael J. Spencer if (!( (const uint8_t *)SectionHeaderTable + SectionTableSize 846ec29b121SMichael J. Spencer <= base() + Data->getBufferSize())) 847b60a18deSMichael J. Spencer // FIXME: Proper error handling. 848b60a18deSMichael J. Spencer report_fatal_error("Section table goes past end of file!"); 849b60a18deSMichael J. Spencer 850b60a18deSMichael J. Spencer 851b60a18deSMichael J. Spencer // To find the symbol tables we walk the section table to find SHT_STMTAB. 852022ecdf2SBenjamin Kramer const Elf_Shdr* sh = 853022ecdf2SBenjamin Kramer reinterpret_cast<const Elf_Shdr*>(SectionHeaderTable); 854022ecdf2SBenjamin Kramer for (unsigned i = 0; i < Header->e_shnum; ++i) { 855b60a18deSMichael J. Spencer if (sh->sh_type == ELF::SHT_SYMTAB) { 856022ecdf2SBenjamin Kramer SymbolTableSectionsIndexMap[i] = SymbolTableSections.size(); 857b60a18deSMichael J. Spencer SymbolTableSections.push_back(sh); 858b60a18deSMichael J. Spencer } 859022ecdf2SBenjamin Kramer if (sh->sh_type == ELF::SHT_REL || sh->sh_type == ELF::SHT_RELA) { 860022ecdf2SBenjamin Kramer RelocationTableSections.push_back(sh); 861022ecdf2SBenjamin Kramer } 862022ecdf2SBenjamin Kramer ++sh; 863b60a18deSMichael J. Spencer } 864b60a18deSMichael J. Spencer 865b60a18deSMichael J. Spencer // Get string table sections. 866b60a18deSMichael J. Spencer dot_shstrtab_sec = getSection(Header->e_shstrndx); 867b60a18deSMichael J. Spencer if (dot_shstrtab_sec) { 868b60a18deSMichael J. Spencer // Verify that the last byte in the string table in a null. 869ec29b121SMichael J. Spencer if (((const char*)base() + dot_shstrtab_sec->sh_offset) 870b60a18deSMichael J. Spencer [dot_shstrtab_sec->sh_size - 1] != 0) 871b60a18deSMichael J. Spencer // FIXME: Proper error handling. 872b60a18deSMichael J. Spencer report_fatal_error("String table must end with a null terminator!"); 873b60a18deSMichael J. Spencer } 874b60a18deSMichael J. Spencer 875b60a18deSMichael J. Spencer // Merge this into the above loop. 876b60a18deSMichael J. Spencer for (const char *i = reinterpret_cast<const char *>(SectionHeaderTable), 877b60a18deSMichael J. Spencer *e = i + Header->e_shnum * Header->e_shentsize; 878b60a18deSMichael J. Spencer i != e; i += Header->e_shentsize) { 879b60a18deSMichael J. Spencer const Elf_Shdr *sh = reinterpret_cast<const Elf_Shdr*>(i); 880b60a18deSMichael J. Spencer if (sh->sh_type == ELF::SHT_STRTAB) { 881b60a18deSMichael J. Spencer StringRef SectionName(getString(dot_shstrtab_sec, sh->sh_name)); 882b60a18deSMichael J. Spencer if (SectionName == ".strtab") { 883b60a18deSMichael J. Spencer if (dot_strtab_sec != 0) 884b60a18deSMichael J. Spencer // FIXME: Proper error handling. 885b60a18deSMichael J. Spencer report_fatal_error("Already found section named .strtab!"); 886b60a18deSMichael J. Spencer dot_strtab_sec = sh; 887ec29b121SMichael J. Spencer const char *dot_strtab = (const char*)base() + sh->sh_offset; 888b60a18deSMichael J. Spencer if (dot_strtab[sh->sh_size - 1] != 0) 889b60a18deSMichael J. Spencer // FIXME: Proper error handling. 890b60a18deSMichael J. Spencer report_fatal_error("String table must end with a null terminator!"); 891b60a18deSMichael J. Spencer } 892b60a18deSMichael J. Spencer } 893b60a18deSMichael J. Spencer } 894b60a18deSMichael J. Spencer } 895b60a18deSMichael J. Spencer 896b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 897b60a18deSMichael J. Spencer ObjectFile::symbol_iterator ELFObjectFile<target_endianness, is64Bits> 898b60a18deSMichael J. Spencer ::begin_symbols() const { 8990324b672SMichael J. Spencer DataRefImpl SymbolData; 900b60a18deSMichael J. Spencer memset(&SymbolData, 0, sizeof(SymbolData)); 901b60a18deSMichael J. Spencer if (SymbolTableSections.size() == 0) { 9020324b672SMichael J. Spencer SymbolData.d.a = std::numeric_limits<uint32_t>::max(); 9030324b672SMichael J. Spencer SymbolData.d.b = std::numeric_limits<uint32_t>::max(); 904b60a18deSMichael J. Spencer } else { 9050324b672SMichael J. Spencer SymbolData.d.a = 1; // The 0th symbol in ELF is fake. 9060324b672SMichael J. Spencer SymbolData.d.b = 0; 907b60a18deSMichael J. Spencer } 9080324b672SMichael J. Spencer return symbol_iterator(SymbolRef(SymbolData, this)); 909b60a18deSMichael J. Spencer } 910b60a18deSMichael J. Spencer 911b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 912b60a18deSMichael J. Spencer ObjectFile::symbol_iterator ELFObjectFile<target_endianness, is64Bits> 913b60a18deSMichael J. Spencer ::end_symbols() const { 9140324b672SMichael J. Spencer DataRefImpl SymbolData; 915b60a18deSMichael J. Spencer memset(&SymbolData, 0, sizeof(SymbolData)); 9160324b672SMichael J. Spencer SymbolData.d.a = std::numeric_limits<uint32_t>::max(); 9170324b672SMichael J. Spencer SymbolData.d.b = std::numeric_limits<uint32_t>::max(); 9180324b672SMichael J. Spencer return symbol_iterator(SymbolRef(SymbolData, this)); 919b60a18deSMichael J. Spencer } 920b60a18deSMichael J. Spencer 921b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 922b60a18deSMichael J. Spencer ObjectFile::section_iterator ELFObjectFile<target_endianness, is64Bits> 923b60a18deSMichael J. Spencer ::begin_sections() const { 9240324b672SMichael J. Spencer DataRefImpl ret; 925ee066fc4SEric Christopher memset(&ret, 0, sizeof(DataRefImpl)); 926ec29b121SMichael J. Spencer ret.p = reinterpret_cast<intptr_t>(base() + Header->e_shoff); 9270324b672SMichael J. Spencer return section_iterator(SectionRef(ret, this)); 928b60a18deSMichael J. Spencer } 929b60a18deSMichael J. Spencer 930b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 931b60a18deSMichael J. Spencer ObjectFile::section_iterator ELFObjectFile<target_endianness, is64Bits> 932b60a18deSMichael J. Spencer ::end_sections() const { 9330324b672SMichael J. Spencer DataRefImpl ret; 934ee066fc4SEric Christopher memset(&ret, 0, sizeof(DataRefImpl)); 935ec29b121SMichael J. Spencer ret.p = reinterpret_cast<intptr_t>(base() 936b60a18deSMichael J. Spencer + Header->e_shoff 9370324b672SMichael J. Spencer + (Header->e_shentsize * Header->e_shnum)); 9380324b672SMichael J. Spencer return section_iterator(SectionRef(ret, this)); 939b60a18deSMichael J. Spencer } 940b60a18deSMichael J. Spencer 941b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 942022ecdf2SBenjamin Kramer ObjectFile::relocation_iterator ELFObjectFile<target_endianness, is64Bits> 943022ecdf2SBenjamin Kramer ::begin_relocations() const { 944022ecdf2SBenjamin Kramer DataRefImpl RelData; 945022ecdf2SBenjamin Kramer memset(&RelData, 0, sizeof(RelData)); 946022ecdf2SBenjamin Kramer if (RelocationTableSections.size() == 0) { 947022ecdf2SBenjamin Kramer RelData.d.a = std::numeric_limits<uint32_t>::max(); 948022ecdf2SBenjamin Kramer RelData.d.b = std::numeric_limits<uint32_t>::max(); 949022ecdf2SBenjamin Kramer } else { 950022ecdf2SBenjamin Kramer RelData.d.a = 0; 951022ecdf2SBenjamin Kramer RelData.d.b = 0; 952022ecdf2SBenjamin Kramer } 953022ecdf2SBenjamin Kramer return relocation_iterator(RelocationRef(RelData, this)); 954022ecdf2SBenjamin Kramer } 955022ecdf2SBenjamin Kramer 956022ecdf2SBenjamin Kramer template<support::endianness target_endianness, bool is64Bits> 957022ecdf2SBenjamin Kramer ObjectFile::relocation_iterator ELFObjectFile<target_endianness, is64Bits> 958022ecdf2SBenjamin Kramer ::end_relocations() const { 959022ecdf2SBenjamin Kramer DataRefImpl RelData; 960022ecdf2SBenjamin Kramer memset(&RelData, 0, sizeof(RelData)); 961022ecdf2SBenjamin Kramer RelData.d.a = std::numeric_limits<uint32_t>::max(); 962022ecdf2SBenjamin Kramer RelData.d.b = std::numeric_limits<uint32_t>::max(); 963022ecdf2SBenjamin Kramer return relocation_iterator(RelocationRef(RelData, this)); 964022ecdf2SBenjamin Kramer } 965022ecdf2SBenjamin Kramer 966022ecdf2SBenjamin Kramer template<support::endianness target_endianness, bool is64Bits> 967b60a18deSMichael J. Spencer uint8_t ELFObjectFile<target_endianness, is64Bits>::getBytesInAddress() const { 9680324b672SMichael J. Spencer return is64Bits ? 8 : 4; 969b60a18deSMichael J. Spencer } 970b60a18deSMichael J. Spencer 971b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 972b60a18deSMichael J. Spencer StringRef ELFObjectFile<target_endianness, is64Bits> 973b60a18deSMichael J. Spencer ::getFileFormatName() const { 974b60a18deSMichael J. Spencer switch(Header->e_ident[ELF::EI_CLASS]) { 975b60a18deSMichael J. Spencer case ELF::ELFCLASS32: 976b60a18deSMichael J. Spencer switch(Header->e_machine) { 977b60a18deSMichael J. Spencer case ELF::EM_386: 978b60a18deSMichael J. Spencer return "ELF32-i386"; 979b60a18deSMichael J. Spencer case ELF::EM_X86_64: 980b60a18deSMichael J. Spencer return "ELF32-x86-64"; 981022ecdf2SBenjamin Kramer case ELF::EM_ARM: 982022ecdf2SBenjamin Kramer return "ELF32-arm"; 983b60a18deSMichael J. Spencer default: 984b60a18deSMichael J. Spencer return "ELF32-unknown"; 985b60a18deSMichael J. Spencer } 986b60a18deSMichael J. Spencer case ELF::ELFCLASS64: 987b60a18deSMichael J. Spencer switch(Header->e_machine) { 988b60a18deSMichael J. Spencer case ELF::EM_386: 989b60a18deSMichael J. Spencer return "ELF64-i386"; 990b60a18deSMichael J. Spencer case ELF::EM_X86_64: 991b60a18deSMichael J. Spencer return "ELF64-x86-64"; 992b60a18deSMichael J. Spencer default: 993b60a18deSMichael J. Spencer return "ELF64-unknown"; 994b60a18deSMichael J. Spencer } 995b60a18deSMichael J. Spencer default: 996b60a18deSMichael J. Spencer // FIXME: Proper error handling. 997b60a18deSMichael J. Spencer report_fatal_error("Invalid ELFCLASS!"); 998b60a18deSMichael J. Spencer } 999b60a18deSMichael J. Spencer } 1000b60a18deSMichael J. Spencer 1001b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 1002b60a18deSMichael J. Spencer unsigned ELFObjectFile<target_endianness, is64Bits>::getArch() const { 1003b60a18deSMichael J. Spencer switch(Header->e_machine) { 1004b60a18deSMichael J. Spencer case ELF::EM_386: 1005b60a18deSMichael J. Spencer return Triple::x86; 1006b60a18deSMichael J. Spencer case ELF::EM_X86_64: 1007b60a18deSMichael J. Spencer return Triple::x86_64; 1008022ecdf2SBenjamin Kramer case ELF::EM_ARM: 1009022ecdf2SBenjamin Kramer return Triple::arm; 1010b60a18deSMichael J. Spencer default: 1011b60a18deSMichael J. Spencer return Triple::UnknownArch; 1012b60a18deSMichael J. Spencer } 1013b60a18deSMichael J. Spencer } 1014b60a18deSMichael J. Spencer 1015b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 1016022ecdf2SBenjamin Kramer template<typename T> 1017022ecdf2SBenjamin Kramer inline const T * 1018022ecdf2SBenjamin Kramer ELFObjectFile<target_endianness, is64Bits>::getEntry(DataRefImpl Entry, 1019022ecdf2SBenjamin Kramer Sections_t Sections) const { 1020022ecdf2SBenjamin Kramer const Elf_Shdr *sec = Sections[Entry.d.b]; 1021022ecdf2SBenjamin Kramer return reinterpret_cast<const T *>( 1022ec29b121SMichael J. Spencer base() 1023b60a18deSMichael J. Spencer + sec->sh_offset 1024022ecdf2SBenjamin Kramer + (Entry.d.a * sec->sh_entsize)); 1025022ecdf2SBenjamin Kramer } 1026022ecdf2SBenjamin Kramer 1027022ecdf2SBenjamin Kramer template<support::endianness target_endianness, bool is64Bits> 1028022ecdf2SBenjamin Kramer const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Sym * 1029022ecdf2SBenjamin Kramer ELFObjectFile<target_endianness, is64Bits>::getSymbol(DataRefImpl Symb) const { 1030022ecdf2SBenjamin Kramer return getEntry<Elf_Sym>(Symb, SymbolTableSections); 1031022ecdf2SBenjamin Kramer } 1032022ecdf2SBenjamin Kramer 1033022ecdf2SBenjamin Kramer template<support::endianness target_endianness, bool is64Bits> 1034022ecdf2SBenjamin Kramer const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Rel * 1035022ecdf2SBenjamin Kramer ELFObjectFile<target_endianness, is64Bits>::getRel(DataRefImpl Rel) const { 1036022ecdf2SBenjamin Kramer return getEntry<Elf_Rel>(Rel, RelocationTableSections); 1037022ecdf2SBenjamin Kramer } 1038022ecdf2SBenjamin Kramer 1039022ecdf2SBenjamin Kramer template<support::endianness target_endianness, bool is64Bits> 1040022ecdf2SBenjamin Kramer const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Rela * 1041022ecdf2SBenjamin Kramer ELFObjectFile<target_endianness, is64Bits>::getRela(DataRefImpl Rela) const { 1042022ecdf2SBenjamin Kramer return getEntry<Elf_Rela>(Rela, RelocationTableSections); 1043b60a18deSMichael J. Spencer } 1044b60a18deSMichael J. Spencer 1045b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 1046b60a18deSMichael J. Spencer const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Shdr * 1047b60a18deSMichael J. Spencer ELFObjectFile<target_endianness, is64Bits>::getSection(DataRefImpl Symb) const { 10480324b672SMichael J. Spencer const Elf_Shdr *sec = getSection(Symb.d.b); 1049b60a18deSMichael J. Spencer if (sec->sh_type != ELF::SHT_SYMTAB) 1050b60a18deSMichael J. Spencer // FIXME: Proper error handling. 1051b60a18deSMichael J. Spencer report_fatal_error("Invalid symbol table section!"); 1052b60a18deSMichael J. Spencer return sec; 1053b60a18deSMichael J. Spencer } 1054b60a18deSMichael J. Spencer 1055b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 1056b60a18deSMichael J. Spencer const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Shdr * 1057b60a18deSMichael J. Spencer ELFObjectFile<target_endianness, is64Bits>::getSection(uint16_t index) const { 1058b60a18deSMichael J. Spencer if (index == 0 || index >= ELF::SHN_LORESERVE) 1059b60a18deSMichael J. Spencer return 0; 1060b60a18deSMichael J. Spencer if (!SectionHeaderTable || index >= Header->e_shnum) 1061b60a18deSMichael J. Spencer // FIXME: Proper error handling. 1062b60a18deSMichael J. Spencer report_fatal_error("Invalid section index!"); 1063b60a18deSMichael J. Spencer 1064b60a18deSMichael J. Spencer return reinterpret_cast<const Elf_Shdr *>( 1065b60a18deSMichael J. Spencer reinterpret_cast<const char *>(SectionHeaderTable) 1066b60a18deSMichael J. Spencer + (index * Header->e_shentsize)); 1067b60a18deSMichael J. Spencer } 1068b60a18deSMichael J. Spencer 1069b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 1070b60a18deSMichael J. Spencer const char *ELFObjectFile<target_endianness, is64Bits> 1071b60a18deSMichael J. Spencer ::getString(uint16_t section, 1072b60a18deSMichael J. Spencer ELF::Elf32_Word offset) const { 1073b60a18deSMichael J. Spencer return getString(getSection(section), offset); 1074b60a18deSMichael J. Spencer } 1075b60a18deSMichael J. Spencer 1076b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 1077b60a18deSMichael J. Spencer const char *ELFObjectFile<target_endianness, is64Bits> 1078b60a18deSMichael J. Spencer ::getString(const Elf_Shdr *section, 1079b60a18deSMichael J. Spencer ELF::Elf32_Word offset) const { 1080b60a18deSMichael J. Spencer assert(section && section->sh_type == ELF::SHT_STRTAB && "Invalid section!"); 1081b60a18deSMichael J. Spencer if (offset >= section->sh_size) 1082b60a18deSMichael J. Spencer // FIXME: Proper error handling. 1083ec29b121SMichael J. Spencer report_fatal_error("Symbol name offset outside of string table!"); 1084ec29b121SMichael J. Spencer return (const char *)base() + section->sh_offset + offset; 1085b60a18deSMichael J. Spencer } 1086b60a18deSMichael J. Spencer 1087b60a18deSMichael J. Spencer // EI_CLASS, EI_DATA. 1088b60a18deSMichael J. Spencer static std::pair<unsigned char, unsigned char> 1089b60a18deSMichael J. Spencer getElfArchType(MemoryBuffer *Object) { 1090b60a18deSMichael J. Spencer if (Object->getBufferSize() < ELF::EI_NIDENT) 1091b60a18deSMichael J. Spencer return std::make_pair((uint8_t)ELF::ELFCLASSNONE,(uint8_t)ELF::ELFDATANONE); 1092b60a18deSMichael J. Spencer return std::make_pair( (uint8_t)Object->getBufferStart()[ELF::EI_CLASS] 1093b60a18deSMichael J. Spencer , (uint8_t)Object->getBufferStart()[ELF::EI_DATA]); 1094b60a18deSMichael J. Spencer } 1095b60a18deSMichael J. Spencer 1096b60a18deSMichael J. Spencer namespace llvm { 1097b60a18deSMichael J. Spencer 1098b60a18deSMichael J. Spencer ObjectFile *ObjectFile::createELFObjectFile(MemoryBuffer *Object) { 1099b60a18deSMichael J. Spencer std::pair<unsigned char, unsigned char> Ident = getElfArchType(Object); 1100ec29b121SMichael J. Spencer error_code ec; 1101b60a18deSMichael J. Spencer if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2LSB) 1102ec29b121SMichael J. Spencer return new ELFObjectFile<support::little, false>(Object, ec); 1103b60a18deSMichael J. Spencer else if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2MSB) 1104ec29b121SMichael J. Spencer return new ELFObjectFile<support::big, false>(Object, ec); 1105b60a18deSMichael J. Spencer else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2LSB) 1106ec29b121SMichael J. Spencer return new ELFObjectFile<support::little, true>(Object, ec); 1107b60a18deSMichael J. Spencer else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2MSB) 1108ec29b121SMichael J. Spencer return new ELFObjectFile<support::big, true>(Object, ec); 1109b60a18deSMichael J. Spencer // FIXME: Proper error handling. 1110b60a18deSMichael J. Spencer report_fatal_error("Not an ELF object file!"); 1111b60a18deSMichael J. Spencer } 1112b60a18deSMichael J. Spencer 1113b60a18deSMichael J. Spencer } // end namespace llvm 1114