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" 23e5fd0047SMichael J. Spencer #include "llvm/Support/raw_ostream.h" 24e5fd0047SMichael J. Spencer #include <algorithm> 25b60a18deSMichael J. Spencer #include <limits> 26b60a18deSMichael J. Spencer #include <utility> 27b60a18deSMichael J. Spencer 28b60a18deSMichael J. Spencer using namespace llvm; 29b60a18deSMichael J. Spencer using namespace object; 30b60a18deSMichael J. Spencer 31b60a18deSMichael J. Spencer // Templates to choose Elf_Addr and Elf_Off depending on is64Bits. 32b60a18deSMichael J. Spencer namespace { 33b60a18deSMichael J. Spencer template<support::endianness target_endianness> 34b60a18deSMichael J. Spencer struct ELFDataTypeTypedefHelperCommon { 35b60a18deSMichael J. Spencer typedef support::detail::packed_endian_specific_integral 36b60a18deSMichael J. Spencer <uint16_t, target_endianness, support::aligned> Elf_Half; 37b60a18deSMichael J. Spencer typedef support::detail::packed_endian_specific_integral 38b60a18deSMichael J. Spencer <uint32_t, target_endianness, support::aligned> Elf_Word; 39b60a18deSMichael J. Spencer typedef support::detail::packed_endian_specific_integral 40b60a18deSMichael J. Spencer <int32_t, target_endianness, support::aligned> Elf_Sword; 41b60a18deSMichael J. Spencer typedef support::detail::packed_endian_specific_integral 42b60a18deSMichael J. Spencer <uint64_t, target_endianness, support::aligned> Elf_Xword; 43b60a18deSMichael J. Spencer typedef support::detail::packed_endian_specific_integral 44b60a18deSMichael J. Spencer <int64_t, target_endianness, support::aligned> Elf_Sxword; 45b60a18deSMichael J. Spencer }; 46b60a18deSMichael J. Spencer } 47b60a18deSMichael J. Spencer 48b60a18deSMichael J. Spencer namespace { 49b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 50b60a18deSMichael J. Spencer struct ELFDataTypeTypedefHelper; 51b60a18deSMichael J. Spencer 52b60a18deSMichael J. Spencer /// ELF 32bit types. 53b60a18deSMichael J. Spencer template<support::endianness target_endianness> 54b60a18deSMichael J. Spencer struct ELFDataTypeTypedefHelper<target_endianness, false> 55b60a18deSMichael J. Spencer : ELFDataTypeTypedefHelperCommon<target_endianness> { 56b60a18deSMichael J. Spencer typedef support::detail::packed_endian_specific_integral 57b60a18deSMichael J. Spencer <uint32_t, target_endianness, support::aligned> Elf_Addr; 58b60a18deSMichael J. Spencer typedef support::detail::packed_endian_specific_integral 59b60a18deSMichael J. Spencer <uint32_t, target_endianness, support::aligned> Elf_Off; 60b60a18deSMichael J. Spencer }; 61b60a18deSMichael J. Spencer 62b60a18deSMichael J. Spencer /// ELF 64bit types. 63b60a18deSMichael J. Spencer template<support::endianness target_endianness> 64b60a18deSMichael J. Spencer struct ELFDataTypeTypedefHelper<target_endianness, true> 65b60a18deSMichael J. Spencer : ELFDataTypeTypedefHelperCommon<target_endianness>{ 66b60a18deSMichael J. Spencer typedef support::detail::packed_endian_specific_integral 67b60a18deSMichael J. Spencer <uint64_t, target_endianness, support::aligned> Elf_Addr; 68b60a18deSMichael J. Spencer typedef support::detail::packed_endian_specific_integral 69b60a18deSMichael J. Spencer <uint64_t, target_endianness, support::aligned> Elf_Off; 70b60a18deSMichael J. Spencer }; 71b60a18deSMichael J. Spencer } 72b60a18deSMichael J. Spencer 73b60a18deSMichael J. Spencer // I really don't like doing this, but the alternative is copypasta. 74b60a18deSMichael J. Spencer #define LLVM_ELF_IMPORT_TYPES(target_endianness, is64Bits) \ 75b60a18deSMichael J. Spencer typedef typename \ 76b60a18deSMichael J. Spencer ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Addr Elf_Addr; \ 77b60a18deSMichael J. Spencer typedef typename \ 78b60a18deSMichael J. Spencer ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Off Elf_Off; \ 79b60a18deSMichael J. Spencer typedef typename \ 80b60a18deSMichael J. Spencer ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Half Elf_Half; \ 81b60a18deSMichael J. Spencer typedef typename \ 82b60a18deSMichael J. Spencer ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Word Elf_Word; \ 83b60a18deSMichael J. Spencer typedef typename \ 84b60a18deSMichael J. Spencer ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Sword Elf_Sword; \ 85b60a18deSMichael J. Spencer typedef typename \ 86b60a18deSMichael J. Spencer ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Xword Elf_Xword; \ 87b60a18deSMichael J. Spencer typedef typename \ 88b60a18deSMichael J. Spencer ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Sxword Elf_Sxword; 89b60a18deSMichael J. Spencer 90b60a18deSMichael J. Spencer // Section header. 91b60a18deSMichael J. Spencer namespace { 92b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 93b60a18deSMichael J. Spencer struct Elf_Shdr_Base; 94b60a18deSMichael J. Spencer 95b60a18deSMichael J. Spencer template<support::endianness target_endianness> 96b60a18deSMichael J. Spencer struct Elf_Shdr_Base<target_endianness, false> { 97b60a18deSMichael J. Spencer LLVM_ELF_IMPORT_TYPES(target_endianness, false) 98b60a18deSMichael J. Spencer Elf_Word sh_name; // Section name (index into string table) 99b60a18deSMichael J. Spencer Elf_Word sh_type; // Section type (SHT_*) 100b60a18deSMichael J. Spencer Elf_Word sh_flags; // Section flags (SHF_*) 101b60a18deSMichael J. Spencer Elf_Addr sh_addr; // Address where section is to be loaded 102b60a18deSMichael J. Spencer Elf_Off sh_offset; // File offset of section data, in bytes 103b60a18deSMichael J. Spencer Elf_Word sh_size; // Size of section, in bytes 104b60a18deSMichael J. Spencer Elf_Word sh_link; // Section type-specific header table index link 105b60a18deSMichael J. Spencer Elf_Word sh_info; // Section type-specific extra information 106b60a18deSMichael J. Spencer Elf_Word sh_addralign;// Section address alignment 107b60a18deSMichael J. Spencer Elf_Word sh_entsize; // Size of records contained within the section 108b60a18deSMichael J. Spencer }; 109b60a18deSMichael J. Spencer 110b60a18deSMichael J. Spencer template<support::endianness target_endianness> 111b60a18deSMichael J. Spencer struct Elf_Shdr_Base<target_endianness, true> { 112b60a18deSMichael J. Spencer LLVM_ELF_IMPORT_TYPES(target_endianness, true) 113b60a18deSMichael J. Spencer Elf_Word sh_name; // Section name (index into string table) 114b60a18deSMichael J. Spencer Elf_Word sh_type; // Section type (SHT_*) 115b60a18deSMichael J. Spencer Elf_Xword sh_flags; // Section flags (SHF_*) 116b60a18deSMichael J. Spencer Elf_Addr sh_addr; // Address where section is to be loaded 117b60a18deSMichael J. Spencer Elf_Off sh_offset; // File offset of section data, in bytes 118b60a18deSMichael J. Spencer Elf_Xword sh_size; // Size of section, in bytes 119b60a18deSMichael J. Spencer Elf_Word sh_link; // Section type-specific header table index link 120b60a18deSMichael J. Spencer Elf_Word sh_info; // Section type-specific extra information 121b60a18deSMichael J. Spencer Elf_Xword sh_addralign;// Section address alignment 122b60a18deSMichael J. Spencer Elf_Xword sh_entsize; // Size of records contained within the section 123b60a18deSMichael J. Spencer }; 124b60a18deSMichael J. Spencer 125b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 126b60a18deSMichael J. Spencer struct Elf_Shdr_Impl : Elf_Shdr_Base<target_endianness, is64Bits> { 127b60a18deSMichael J. Spencer using Elf_Shdr_Base<target_endianness, is64Bits>::sh_entsize; 128b60a18deSMichael J. Spencer using Elf_Shdr_Base<target_endianness, is64Bits>::sh_size; 129b60a18deSMichael J. Spencer 130b60a18deSMichael J. Spencer /// @brief Get the number of entities this section contains if it has any. 131b60a18deSMichael J. Spencer unsigned getEntityCount() const { 132b60a18deSMichael J. Spencer if (sh_entsize == 0) 133b60a18deSMichael J. Spencer return 0; 134b60a18deSMichael J. Spencer return sh_size / sh_entsize; 135b60a18deSMichael J. Spencer } 136b60a18deSMichael J. Spencer }; 137b60a18deSMichael J. Spencer } 138b60a18deSMichael J. Spencer 139b60a18deSMichael J. Spencer namespace { 140b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 141b60a18deSMichael J. Spencer struct Elf_Sym_Base; 142b60a18deSMichael J. Spencer 143b60a18deSMichael J. Spencer template<support::endianness target_endianness> 144b60a18deSMichael J. Spencer struct Elf_Sym_Base<target_endianness, false> { 145b60a18deSMichael J. Spencer LLVM_ELF_IMPORT_TYPES(target_endianness, false) 146b60a18deSMichael J. Spencer Elf_Word st_name; // Symbol name (index into string table) 147b60a18deSMichael J. Spencer Elf_Addr st_value; // Value or address associated with the symbol 148b60a18deSMichael J. Spencer Elf_Word st_size; // Size of the symbol 149b60a18deSMichael J. Spencer unsigned char st_info; // Symbol's type and binding attributes 150b60a18deSMichael J. Spencer unsigned char st_other; // Must be zero; reserved 151b60a18deSMichael J. Spencer Elf_Half st_shndx; // Which section (header table index) it's defined in 152b60a18deSMichael J. Spencer }; 153b60a18deSMichael J. Spencer 154b60a18deSMichael J. Spencer template<support::endianness target_endianness> 155b60a18deSMichael J. Spencer struct Elf_Sym_Base<target_endianness, true> { 156b60a18deSMichael J. Spencer LLVM_ELF_IMPORT_TYPES(target_endianness, true) 157b60a18deSMichael J. Spencer Elf_Word st_name; // Symbol name (index into string table) 158b60a18deSMichael J. Spencer unsigned char st_info; // Symbol's type and binding attributes 159b60a18deSMichael J. Spencer unsigned char st_other; // Must be zero; reserved 160b60a18deSMichael J. Spencer Elf_Half st_shndx; // Which section (header table index) it's defined in 161b60a18deSMichael J. Spencer Elf_Addr st_value; // Value or address associated with the symbol 162b60a18deSMichael J. Spencer Elf_Xword st_size; // Size of the symbol 163b60a18deSMichael J. Spencer }; 164b60a18deSMichael J. Spencer 165b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 166b60a18deSMichael J. Spencer struct Elf_Sym_Impl : Elf_Sym_Base<target_endianness, is64Bits> { 167b60a18deSMichael J. Spencer using Elf_Sym_Base<target_endianness, is64Bits>::st_info; 168b60a18deSMichael J. Spencer 169b60a18deSMichael J. Spencer // These accessors and mutators correspond to the ELF32_ST_BIND, 170b60a18deSMichael J. Spencer // ELF32_ST_TYPE, and ELF32_ST_INFO macros defined in the ELF specification: 171b60a18deSMichael J. Spencer unsigned char getBinding() const { return st_info >> 4; } 172b60a18deSMichael J. Spencer unsigned char getType() const { return st_info & 0x0f; } 173b60a18deSMichael J. Spencer void setBinding(unsigned char b) { setBindingAndType(b, getType()); } 174b60a18deSMichael J. Spencer void setType(unsigned char t) { setBindingAndType(getBinding(), t); } 175b60a18deSMichael J. Spencer void setBindingAndType(unsigned char b, unsigned char t) { 176b60a18deSMichael J. Spencer st_info = (b << 4) + (t & 0x0f); 177b60a18deSMichael J. Spencer } 178b60a18deSMichael J. Spencer }; 179b60a18deSMichael J. Spencer } 180b60a18deSMichael J. Spencer 181b60a18deSMichael J. Spencer namespace { 182022ecdf2SBenjamin Kramer template<support::endianness target_endianness, bool is64Bits, bool isRela> 183022ecdf2SBenjamin Kramer struct Elf_Rel_Base; 184022ecdf2SBenjamin Kramer 185022ecdf2SBenjamin Kramer template<support::endianness target_endianness> 186022ecdf2SBenjamin Kramer struct Elf_Rel_Base<target_endianness, false, false> { 187022ecdf2SBenjamin Kramer LLVM_ELF_IMPORT_TYPES(target_endianness, false) 188022ecdf2SBenjamin Kramer Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) 189022ecdf2SBenjamin Kramer Elf_Word r_info; // Symbol table index and type of relocation to apply 190022ecdf2SBenjamin Kramer }; 191022ecdf2SBenjamin Kramer 192022ecdf2SBenjamin Kramer template<support::endianness target_endianness> 193022ecdf2SBenjamin Kramer struct Elf_Rel_Base<target_endianness, true, false> { 194022ecdf2SBenjamin Kramer LLVM_ELF_IMPORT_TYPES(target_endianness, true) 195022ecdf2SBenjamin Kramer Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) 196022ecdf2SBenjamin Kramer Elf_Xword r_info; // Symbol table index and type of relocation to apply 197022ecdf2SBenjamin Kramer }; 198022ecdf2SBenjamin Kramer 199022ecdf2SBenjamin Kramer template<support::endianness target_endianness> 200022ecdf2SBenjamin Kramer struct Elf_Rel_Base<target_endianness, false, true> { 201022ecdf2SBenjamin Kramer LLVM_ELF_IMPORT_TYPES(target_endianness, false) 202022ecdf2SBenjamin Kramer Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) 203022ecdf2SBenjamin Kramer Elf_Word r_info; // Symbol table index and type of relocation to apply 204022ecdf2SBenjamin Kramer Elf_Sword r_addend; // Compute value for relocatable field by adding this 205022ecdf2SBenjamin Kramer }; 206022ecdf2SBenjamin Kramer 207022ecdf2SBenjamin Kramer template<support::endianness target_endianness> 208022ecdf2SBenjamin Kramer struct Elf_Rel_Base<target_endianness, true, true> { 209022ecdf2SBenjamin Kramer LLVM_ELF_IMPORT_TYPES(target_endianness, true) 210022ecdf2SBenjamin Kramer Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) 211022ecdf2SBenjamin Kramer Elf_Xword r_info; // Symbol table index and type of relocation to apply 212022ecdf2SBenjamin Kramer Elf_Sxword r_addend; // Compute value for relocatable field by adding this. 213022ecdf2SBenjamin Kramer }; 214022ecdf2SBenjamin Kramer 215022ecdf2SBenjamin Kramer template<support::endianness target_endianness, bool is64Bits, bool isRela> 216022ecdf2SBenjamin Kramer struct Elf_Rel_Impl; 217022ecdf2SBenjamin Kramer 218022ecdf2SBenjamin Kramer template<support::endianness target_endianness, bool isRela> 219022ecdf2SBenjamin Kramer struct Elf_Rel_Impl<target_endianness, true, isRela> 220022ecdf2SBenjamin Kramer : Elf_Rel_Base<target_endianness, true, isRela> { 221022ecdf2SBenjamin Kramer using Elf_Rel_Base<target_endianness, true, isRela>::r_info; 222022ecdf2SBenjamin Kramer LLVM_ELF_IMPORT_TYPES(target_endianness, true) 223022ecdf2SBenjamin Kramer 224022ecdf2SBenjamin Kramer // These accessors and mutators correspond to the ELF64_R_SYM, ELF64_R_TYPE, 225022ecdf2SBenjamin Kramer // and ELF64_R_INFO macros defined in the ELF specification: 226022ecdf2SBenjamin Kramer uint64_t getSymbol() const { return (r_info >> 32); } 227022ecdf2SBenjamin Kramer unsigned char getType() const { 228022ecdf2SBenjamin Kramer return (unsigned char) (r_info & 0xffffffffL); 229022ecdf2SBenjamin Kramer } 230022ecdf2SBenjamin Kramer void setSymbol(uint64_t s) { setSymbolAndType(s, getType()); } 231022ecdf2SBenjamin Kramer void setType(unsigned char t) { setSymbolAndType(getSymbol(), t); } 232022ecdf2SBenjamin Kramer void setSymbolAndType(uint64_t s, unsigned char t) { 233022ecdf2SBenjamin Kramer r_info = (s << 32) + (t&0xffffffffL); 234022ecdf2SBenjamin Kramer } 235022ecdf2SBenjamin Kramer }; 236022ecdf2SBenjamin Kramer 237022ecdf2SBenjamin Kramer template<support::endianness target_endianness, bool isRela> 238022ecdf2SBenjamin Kramer struct Elf_Rel_Impl<target_endianness, false, isRela> 239022ecdf2SBenjamin Kramer : Elf_Rel_Base<target_endianness, false, isRela> { 240022ecdf2SBenjamin Kramer using Elf_Rel_Base<target_endianness, false, isRela>::r_info; 241022ecdf2SBenjamin Kramer LLVM_ELF_IMPORT_TYPES(target_endianness, false) 242022ecdf2SBenjamin Kramer 243022ecdf2SBenjamin Kramer // These accessors and mutators correspond to the ELF32_R_SYM, ELF32_R_TYPE, 244022ecdf2SBenjamin Kramer // and ELF32_R_INFO macros defined in the ELF specification: 245022ecdf2SBenjamin Kramer uint32_t getSymbol() const { return (r_info >> 8); } 246022ecdf2SBenjamin Kramer unsigned char getType() const { return (unsigned char) (r_info & 0x0ff); } 247022ecdf2SBenjamin Kramer void setSymbol(uint32_t s) { setSymbolAndType(s, getType()); } 248022ecdf2SBenjamin Kramer void setType(unsigned char t) { setSymbolAndType(getSymbol(), t); } 249022ecdf2SBenjamin Kramer void setSymbolAndType(uint32_t s, unsigned char t) { 250022ecdf2SBenjamin Kramer r_info = (s << 8) + t; 251022ecdf2SBenjamin Kramer } 252022ecdf2SBenjamin Kramer }; 253022ecdf2SBenjamin Kramer 254022ecdf2SBenjamin Kramer } 255022ecdf2SBenjamin Kramer 256022ecdf2SBenjamin Kramer namespace { 257b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 258b60a18deSMichael J. Spencer class ELFObjectFile : public ObjectFile { 259b60a18deSMichael J. Spencer LLVM_ELF_IMPORT_TYPES(target_endianness, is64Bits) 260b60a18deSMichael J. Spencer 261b60a18deSMichael J. Spencer typedef Elf_Shdr_Impl<target_endianness, is64Bits> Elf_Shdr; 262b60a18deSMichael J. Spencer typedef Elf_Sym_Impl<target_endianness, is64Bits> Elf_Sym; 263022ecdf2SBenjamin Kramer typedef Elf_Rel_Impl<target_endianness, is64Bits, false> Elf_Rel; 264022ecdf2SBenjamin Kramer typedef Elf_Rel_Impl<target_endianness, is64Bits, true> Elf_Rela; 265b60a18deSMichael J. Spencer 266b60a18deSMichael J. Spencer struct Elf_Ehdr { 267b60a18deSMichael J. Spencer unsigned char e_ident[ELF::EI_NIDENT]; // ELF Identification bytes 268b60a18deSMichael J. Spencer Elf_Half e_type; // Type of file (see ET_*) 269b60a18deSMichael J. Spencer Elf_Half e_machine; // Required architecture for this file (see EM_*) 270b60a18deSMichael J. Spencer Elf_Word e_version; // Must be equal to 1 271b60a18deSMichael J. Spencer Elf_Addr e_entry; // Address to jump to in order to start program 272b60a18deSMichael J. Spencer Elf_Off e_phoff; // Program header table's file offset, in bytes 273b60a18deSMichael J. Spencer Elf_Off e_shoff; // Section header table's file offset, in bytes 274b60a18deSMichael J. Spencer Elf_Word e_flags; // Processor-specific flags 275b60a18deSMichael J. Spencer Elf_Half e_ehsize; // Size of ELF header, in bytes 276b60a18deSMichael J. Spencer Elf_Half e_phentsize;// Size of an entry in the program header table 277b60a18deSMichael J. Spencer Elf_Half e_phnum; // Number of entries in the program header table 278b60a18deSMichael J. Spencer Elf_Half e_shentsize;// Size of an entry in the section header table 279b60a18deSMichael J. Spencer Elf_Half e_shnum; // Number of entries in the section header table 280b60a18deSMichael J. Spencer Elf_Half e_shstrndx; // Section header table index of section name 281b60a18deSMichael J. Spencer // string table 282b60a18deSMichael J. Spencer bool checkMagic() const { 283b60a18deSMichael J. Spencer return (memcmp(e_ident, ELF::ElfMagic, strlen(ELF::ElfMagic))) == 0; 284b60a18deSMichael J. Spencer } 285b60a18deSMichael J. Spencer unsigned char getFileClass() const { return e_ident[ELF::EI_CLASS]; } 286b60a18deSMichael J. Spencer unsigned char getDataEncoding() const { return e_ident[ELF::EI_DATA]; } 287b60a18deSMichael J. Spencer }; 288b60a18deSMichael J. Spencer 289022ecdf2SBenjamin Kramer typedef SmallVector<const Elf_Shdr*, 1> Sections_t; 290022ecdf2SBenjamin Kramer typedef DenseMap<unsigned, unsigned> IndexMap_t; 291e5fd0047SMichael J. Spencer typedef DenseMap<const Elf_Shdr*, SmallVector<uint32_t, 1> > RelocMap_t; 292b60a18deSMichael J. Spencer 293b60a18deSMichael J. Spencer const Elf_Ehdr *Header; 294b60a18deSMichael J. Spencer const Elf_Shdr *SectionHeaderTable; 295b60a18deSMichael J. Spencer const Elf_Shdr *dot_shstrtab_sec; // Section header string table. 296b60a18deSMichael J. Spencer const Elf_Shdr *dot_strtab_sec; // Symbol header string table. 297022ecdf2SBenjamin Kramer Sections_t SymbolTableSections; 298022ecdf2SBenjamin Kramer IndexMap_t SymbolTableSectionsIndexMap; 299d3043965SNick Lewycky DenseMap<const Elf_Sym*, ELF::Elf64_Word> ExtendedSymbolTable; 300e5fd0047SMichael J. Spencer 301e5fd0047SMichael J. Spencer /// @brief Map sections to an array of relocation sections that reference 302e5fd0047SMichael J. Spencer /// them sorted by section index. 303e5fd0047SMichael J. Spencer RelocMap_t SectionRelocMap; 304e5fd0047SMichael J. Spencer 305e5fd0047SMichael J. Spencer /// @brief Get the relocation section that contains \a Rel. 306e5fd0047SMichael J. Spencer const Elf_Shdr *getRelSection(DataRefImpl Rel) const { 307e5fd0047SMichael J. Spencer return getSection(Rel.w.b); 308e5fd0047SMichael J. Spencer } 309b60a18deSMichael J. Spencer 310b60a18deSMichael J. Spencer void validateSymbol(DataRefImpl Symb) const; 311022ecdf2SBenjamin Kramer bool isRelocationHasAddend(DataRefImpl Rel) const; 312022ecdf2SBenjamin Kramer template<typename T> 313e5fd0047SMichael J. Spencer const T *getEntry(uint16_t Section, uint32_t Entry) const; 314e5fd0047SMichael J. Spencer template<typename T> 315e5fd0047SMichael J. Spencer const T *getEntry(const Elf_Shdr *Section, uint32_t Entry) const; 316b60a18deSMichael J. Spencer const Elf_Sym *getSymbol(DataRefImpl Symb) const; 317b60a18deSMichael J. Spencer const Elf_Shdr *getSection(DataRefImpl index) const; 31843f01caeSNick Lewycky const Elf_Shdr *getSection(uint32_t index) const; 319022ecdf2SBenjamin Kramer const Elf_Rel *getRel(DataRefImpl Rel) const; 320022ecdf2SBenjamin Kramer const Elf_Rela *getRela(DataRefImpl Rela) const; 32143f01caeSNick Lewycky const char *getString(uint32_t section, uint32_t offset) const; 322b60a18deSMichael J. Spencer const char *getString(const Elf_Shdr *section, uint32_t offset) const; 323e5fd0047SMichael J. Spencer error_code getSymbolName(const Elf_Sym *Symb, StringRef &Res) const; 324b60a18deSMichael J. Spencer 325b60a18deSMichael J. Spencer protected: 3261d6167fdSMichael J. Spencer virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const; 3271d6167fdSMichael J. Spencer virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const; 328*2631f93fSDanil Malyshev virtual error_code getSymbolFileOffset(DataRefImpl Symb, uint64_t &Res) const; 3291d6167fdSMichael J. Spencer virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const; 3301d6167fdSMichael J. Spencer virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const; 3311d6167fdSMichael J. Spencer virtual error_code getSymbolNMTypeChar(DataRefImpl Symb, char &Res) const; 3321d6167fdSMichael J. Spencer virtual error_code isSymbolInternal(DataRefImpl Symb, bool &Res) const; 33375d1cf33SBenjamin Kramer virtual error_code isSymbolGlobal(DataRefImpl Symb, bool &Res) const; 33401759754SMichael J. Spencer virtual error_code isSymbolWeak(DataRefImpl Symb, bool &Res) const; 335d3946676SMichael J. Spencer virtual error_code getSymbolType(DataRefImpl Symb, SymbolRef::Type &Res) const; 33632173153SMichael J. Spencer virtual error_code isSymbolAbsolute(DataRefImpl Symb, bool &Res) const; 33732173153SMichael J. Spencer virtual error_code getSymbolSection(DataRefImpl Symb, 33832173153SMichael J. Spencer section_iterator &Res) const; 339b60a18deSMichael J. Spencer 3401d6167fdSMichael J. Spencer virtual error_code getSectionNext(DataRefImpl Sec, SectionRef &Res) const; 3411d6167fdSMichael J. Spencer virtual error_code getSectionName(DataRefImpl Sec, StringRef &Res) const; 3421d6167fdSMichael J. Spencer virtual error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const; 3431d6167fdSMichael J. Spencer virtual error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const; 3441d6167fdSMichael J. Spencer virtual error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const; 3457989460aSMichael J. Spencer virtual error_code getSectionAlignment(DataRefImpl Sec, uint64_t &Res) const; 3461d6167fdSMichael J. Spencer virtual error_code isSectionText(DataRefImpl Sec, bool &Res) const; 347800619f2SMichael J. Spencer virtual error_code isSectionData(DataRefImpl Sec, bool &Res) const; 348800619f2SMichael J. Spencer virtual error_code isSectionBSS(DataRefImpl Sec, bool &Res) const; 349f6f3e81cSBenjamin Kramer virtual error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, 350f6f3e81cSBenjamin Kramer bool &Result) const; 351e5fd0047SMichael J. Spencer virtual relocation_iterator getSectionRelBegin(DataRefImpl Sec) const; 352e5fd0047SMichael J. Spencer virtual relocation_iterator getSectionRelEnd(DataRefImpl Sec) const; 353b60a18deSMichael J. Spencer 354022ecdf2SBenjamin Kramer virtual error_code getRelocationNext(DataRefImpl Rel, 355022ecdf2SBenjamin Kramer RelocationRef &Res) const; 356022ecdf2SBenjamin Kramer virtual error_code getRelocationAddress(DataRefImpl Rel, 357022ecdf2SBenjamin Kramer uint64_t &Res) const; 358*2631f93fSDanil Malyshev virtual error_code getRelocationOffset(DataRefImpl Rel, 359*2631f93fSDanil Malyshev uint64_t &Res) const; 360022ecdf2SBenjamin Kramer virtual error_code getRelocationSymbol(DataRefImpl Rel, 361022ecdf2SBenjamin Kramer SymbolRef &Res) const; 362022ecdf2SBenjamin Kramer virtual error_code getRelocationType(DataRefImpl Rel, 3637be76590SOwen Anderson uint64_t &Res) const; 364e5fd0047SMichael J. Spencer virtual error_code getRelocationTypeName(DataRefImpl Rel, 365e5fd0047SMichael J. Spencer SmallVectorImpl<char> &Result) const; 366022ecdf2SBenjamin Kramer virtual error_code getRelocationAdditionalInfo(DataRefImpl Rel, 367022ecdf2SBenjamin Kramer int64_t &Res) const; 368e5fd0047SMichael J. Spencer virtual error_code getRelocationValueString(DataRefImpl Rel, 369e5fd0047SMichael J. Spencer SmallVectorImpl<char> &Result) const; 370022ecdf2SBenjamin Kramer 371b60a18deSMichael J. Spencer public: 372ec29b121SMichael J. Spencer ELFObjectFile(MemoryBuffer *Object, error_code &ec); 373b60a18deSMichael J. Spencer virtual symbol_iterator begin_symbols() const; 374b60a18deSMichael J. Spencer virtual symbol_iterator end_symbols() const; 375b60a18deSMichael J. Spencer virtual section_iterator begin_sections() const; 376b60a18deSMichael J. Spencer virtual section_iterator end_sections() const; 377b60a18deSMichael J. Spencer 378b60a18deSMichael J. Spencer virtual uint8_t getBytesInAddress() const; 379b60a18deSMichael J. Spencer virtual StringRef getFileFormatName() const; 380b60a18deSMichael J. Spencer virtual unsigned getArch() const; 3817adc4370SNick Lewycky 38243f01caeSNick Lewycky uint64_t getNumSections() const; 38343f01caeSNick Lewycky uint64_t getStringTableIndex() const; 384d3043965SNick Lewycky ELF::Elf64_Word getSymbolTableIndex(const Elf_Sym *symb) const; 38543f01caeSNick Lewycky const Elf_Shdr *getSection(const Elf_Sym *symb) const; 3864f91c2f2SMichael J. Spencer 3874f91c2f2SMichael J. Spencer static inline bool classof(const Binary *v) { 3884f91c2f2SMichael J. Spencer return v->getType() == isELF; 3894f91c2f2SMichael J. Spencer } 3904f91c2f2SMichael J. Spencer static inline bool classof(const ELFObjectFile *v) { return true; } 391b60a18deSMichael J. Spencer }; 392b60a18deSMichael J. Spencer } // end namespace 393b60a18deSMichael J. Spencer 394b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 395b60a18deSMichael J. Spencer void ELFObjectFile<target_endianness, is64Bits> 396b60a18deSMichael J. Spencer ::validateSymbol(DataRefImpl Symb) const { 397b60a18deSMichael J. Spencer const Elf_Sym *symb = getSymbol(Symb); 3980324b672SMichael J. Spencer const Elf_Shdr *SymbolTableSection = SymbolTableSections[Symb.d.b]; 399b60a18deSMichael J. Spencer // FIXME: We really need to do proper error handling in the case of an invalid 400b60a18deSMichael J. Spencer // input file. Because we don't use exceptions, I think we'll just pass 401b60a18deSMichael J. Spencer // an error object around. 402b60a18deSMichael J. Spencer if (!( symb 403b60a18deSMichael J. Spencer && SymbolTableSection 404ec29b121SMichael J. Spencer && symb >= (const Elf_Sym*)(base() 405b60a18deSMichael J. Spencer + SymbolTableSection->sh_offset) 406ec29b121SMichael J. Spencer && symb < (const Elf_Sym*)(base() 407b60a18deSMichael J. Spencer + SymbolTableSection->sh_offset 408b60a18deSMichael J. Spencer + SymbolTableSection->sh_size))) 409b60a18deSMichael J. Spencer // FIXME: Proper error handling. 410b60a18deSMichael J. Spencer report_fatal_error("Symb must point to a valid symbol!"); 411b60a18deSMichael J. Spencer } 412b60a18deSMichael J. Spencer 413b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 4141d6167fdSMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits> 4151d6167fdSMichael J. Spencer ::getSymbolNext(DataRefImpl Symb, 4161d6167fdSMichael J. Spencer SymbolRef &Result) const { 417b60a18deSMichael J. Spencer validateSymbol(Symb); 4180324b672SMichael J. Spencer const Elf_Shdr *SymbolTableSection = SymbolTableSections[Symb.d.b]; 419b60a18deSMichael J. Spencer 4200324b672SMichael J. Spencer ++Symb.d.a; 421b60a18deSMichael J. Spencer // Check to see if we are at the end of this symbol table. 4220324b672SMichael J. Spencer if (Symb.d.a >= SymbolTableSection->getEntityCount()) { 423b60a18deSMichael J. Spencer // We are at the end. If there are other symbol tables, jump to them. 4240324b672SMichael J. Spencer ++Symb.d.b; 4250324b672SMichael J. Spencer Symb.d.a = 1; // The 0th symbol in ELF is fake. 426b60a18deSMichael J. Spencer // Otherwise return the terminator. 4270324b672SMichael J. Spencer if (Symb.d.b >= SymbolTableSections.size()) { 4280324b672SMichael J. Spencer Symb.d.a = std::numeric_limits<uint32_t>::max(); 4290324b672SMichael J. Spencer Symb.d.b = std::numeric_limits<uint32_t>::max(); 430b60a18deSMichael J. Spencer } 431b60a18deSMichael J. Spencer } 432b60a18deSMichael J. Spencer 4331d6167fdSMichael J. Spencer Result = SymbolRef(Symb, this); 4341d6167fdSMichael J. Spencer return object_error::success; 435b60a18deSMichael J. Spencer } 436b60a18deSMichael J. Spencer 437b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 4381d6167fdSMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits> 4391d6167fdSMichael J. Spencer ::getSymbolName(DataRefImpl Symb, 4401d6167fdSMichael J. Spencer StringRef &Result) const { 441b60a18deSMichael J. Spencer validateSymbol(Symb); 442b60a18deSMichael J. Spencer const Elf_Sym *symb = getSymbol(Symb); 443e5fd0047SMichael J. Spencer return getSymbolName(symb, Result); 444b60a18deSMichael J. Spencer } 445b60a18deSMichael J. Spencer 446b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 447d3043965SNick Lewycky ELF::Elf64_Word ELFObjectFile<target_endianness, is64Bits> 4487adc4370SNick Lewycky ::getSymbolTableIndex(const Elf_Sym *symb) const { 4497adc4370SNick Lewycky if (symb->st_shndx == ELF::SHN_XINDEX) 4507adc4370SNick Lewycky return ExtendedSymbolTable.lookup(symb); 4517adc4370SNick Lewycky return symb->st_shndx; 4527adc4370SNick Lewycky } 4537adc4370SNick Lewycky 4547adc4370SNick Lewycky template<support::endianness target_endianness, bool is64Bits> 45543f01caeSNick Lewycky const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Shdr * 45643f01caeSNick Lewycky ELFObjectFile<target_endianness, is64Bits> 45743f01caeSNick Lewycky ::getSection(const Elf_Sym *symb) const { 458d3043965SNick Lewycky if (symb->st_shndx == ELF::SHN_XINDEX) 45943f01caeSNick Lewycky return getSection(ExtendedSymbolTable.lookup(symb)); 46043f01caeSNick Lewycky if (symb->st_shndx >= ELF::SHN_LORESERVE) 46143f01caeSNick Lewycky return 0; 46243f01caeSNick Lewycky return getSection(symb->st_shndx); 46343f01caeSNick Lewycky } 46443f01caeSNick Lewycky 46543f01caeSNick Lewycky template<support::endianness target_endianness, bool is64Bits> 4661d6167fdSMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits> 467*2631f93fSDanil Malyshev ::getSymbolFileOffset(DataRefImpl Symb, 468*2631f93fSDanil Malyshev uint64_t &Result) const { 469*2631f93fSDanil Malyshev validateSymbol(Symb); 470*2631f93fSDanil Malyshev const Elf_Sym *symb = getSymbol(Symb); 471*2631f93fSDanil Malyshev const Elf_Shdr *Section; 472*2631f93fSDanil Malyshev switch (getSymbolTableIndex(symb)) { 473*2631f93fSDanil Malyshev case ELF::SHN_COMMON: 474*2631f93fSDanil Malyshev // Undefined symbols have no address yet. 475*2631f93fSDanil Malyshev case ELF::SHN_UNDEF: 476*2631f93fSDanil Malyshev Result = UnknownAddressOrSize; 477*2631f93fSDanil Malyshev return object_error::success; 478*2631f93fSDanil Malyshev case ELF::SHN_ABS: 479*2631f93fSDanil Malyshev Result = symb->st_value; 480*2631f93fSDanil Malyshev return object_error::success; 481*2631f93fSDanil Malyshev default: Section = getSection(symb); 482*2631f93fSDanil Malyshev } 483*2631f93fSDanil Malyshev 484*2631f93fSDanil Malyshev switch (symb->getType()) { 485*2631f93fSDanil Malyshev case ELF::STT_SECTION: 486*2631f93fSDanil Malyshev Result = Section ? Section->sh_addr : UnknownAddressOrSize; 487*2631f93fSDanil Malyshev return object_error::success; 488*2631f93fSDanil Malyshev case ELF::STT_FUNC: 489*2631f93fSDanil Malyshev case ELF::STT_OBJECT: 490*2631f93fSDanil Malyshev case ELF::STT_NOTYPE: 491*2631f93fSDanil Malyshev Result = symb->st_value + 492*2631f93fSDanil Malyshev (Section ? Section->sh_offset - Section->sh_addr : 0); 493*2631f93fSDanil Malyshev return object_error::success; 494*2631f93fSDanil Malyshev default: 495*2631f93fSDanil Malyshev Result = UnknownAddressOrSize; 496*2631f93fSDanil Malyshev return object_error::success; 497*2631f93fSDanil Malyshev } 498*2631f93fSDanil Malyshev } 499*2631f93fSDanil Malyshev 500*2631f93fSDanil Malyshev template<support::endianness target_endianness, bool is64Bits> 501*2631f93fSDanil Malyshev error_code ELFObjectFile<target_endianness, is64Bits> 502*2631f93fSDanil Malyshev ::getSymbolAddress(DataRefImpl Symb, 5031d6167fdSMichael J. Spencer uint64_t &Result) const { 504b60a18deSMichael J. Spencer validateSymbol(Symb); 505b60a18deSMichael J. Spencer const Elf_Sym *symb = getSymbol(Symb); 506b60a18deSMichael J. Spencer const Elf_Shdr *Section; 5077adc4370SNick Lewycky switch (getSymbolTableIndex(symb)) { 508b60a18deSMichael J. Spencer case ELF::SHN_COMMON: 509b60a18deSMichael J. Spencer // Undefined symbols have no address yet. 5101d6167fdSMichael J. Spencer case ELF::SHN_UNDEF: 5111d6167fdSMichael J. Spencer Result = UnknownAddressOrSize; 5121d6167fdSMichael J. Spencer return object_error::success; 5131d6167fdSMichael J. Spencer case ELF::SHN_ABS: 5141d6167fdSMichael J. Spencer Result = symb->st_value; 5151d6167fdSMichael J. Spencer return object_error::success; 51643f01caeSNick Lewycky default: Section = getSection(symb); 517b60a18deSMichael J. Spencer } 518b60a18deSMichael J. Spencer 519b60a18deSMichael J. Spencer switch (symb->getType()) { 5201d6167fdSMichael J. Spencer case ELF::STT_SECTION: 5211d6167fdSMichael J. Spencer Result = Section ? Section->sh_addr : UnknownAddressOrSize; 5221d6167fdSMichael J. Spencer return object_error::success; 523b60a18deSMichael J. Spencer case ELF::STT_FUNC: 524b60a18deSMichael J. Spencer case ELF::STT_OBJECT: 525b60a18deSMichael J. Spencer case ELF::STT_NOTYPE: 5261d6167fdSMichael J. Spencer Result = symb->st_value; 5271d6167fdSMichael J. Spencer return object_error::success; 5281d6167fdSMichael J. Spencer default: 5291d6167fdSMichael J. Spencer Result = UnknownAddressOrSize; 5301d6167fdSMichael J. Spencer return object_error::success; 531b60a18deSMichael J. Spencer } 532b60a18deSMichael J. Spencer } 533b60a18deSMichael J. Spencer 534b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 5351d6167fdSMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits> 5361d6167fdSMichael J. Spencer ::getSymbolSize(DataRefImpl Symb, 5371d6167fdSMichael J. Spencer uint64_t &Result) const { 538b60a18deSMichael J. Spencer validateSymbol(Symb); 539b60a18deSMichael J. Spencer const Elf_Sym *symb = getSymbol(Symb); 540b60a18deSMichael J. Spencer if (symb->st_size == 0) 5411d6167fdSMichael J. Spencer Result = UnknownAddressOrSize; 5421d6167fdSMichael J. Spencer Result = symb->st_size; 5431d6167fdSMichael J. Spencer return object_error::success; 544b60a18deSMichael J. Spencer } 545b60a18deSMichael J. Spencer 546b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 5471d6167fdSMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits> 5481d6167fdSMichael J. Spencer ::getSymbolNMTypeChar(DataRefImpl Symb, 5491d6167fdSMichael J. Spencer char &Result) const { 550b60a18deSMichael J. Spencer validateSymbol(Symb); 551b60a18deSMichael J. Spencer const Elf_Sym *symb = getSymbol(Symb); 55243f01caeSNick Lewycky const Elf_Shdr *Section = getSection(symb); 553b60a18deSMichael J. Spencer 554b60a18deSMichael J. Spencer char ret = '?'; 555b60a18deSMichael J. Spencer 556b60a18deSMichael J. Spencer if (Section) { 557b60a18deSMichael J. Spencer switch (Section->sh_type) { 558b60a18deSMichael J. Spencer case ELF::SHT_PROGBITS: 559b60a18deSMichael J. Spencer case ELF::SHT_DYNAMIC: 560b60a18deSMichael J. Spencer switch (Section->sh_flags) { 561b60a18deSMichael J. Spencer case (ELF::SHF_ALLOC | ELF::SHF_EXECINSTR): 562b60a18deSMichael J. Spencer ret = 't'; break; 563b60a18deSMichael J. Spencer case (ELF::SHF_ALLOC | ELF::SHF_WRITE): 564b60a18deSMichael J. Spencer ret = 'd'; break; 565b60a18deSMichael J. Spencer case ELF::SHF_ALLOC: 566b60a18deSMichael J. Spencer case (ELF::SHF_ALLOC | ELF::SHF_MERGE): 567b60a18deSMichael J. Spencer case (ELF::SHF_ALLOC | ELF::SHF_MERGE | ELF::SHF_STRINGS): 568b60a18deSMichael J. Spencer ret = 'r'; break; 569b60a18deSMichael J. Spencer } 570b60a18deSMichael J. Spencer break; 571b60a18deSMichael J. Spencer case ELF::SHT_NOBITS: ret = 'b'; 572b60a18deSMichael J. Spencer } 573b60a18deSMichael J. Spencer } 574b60a18deSMichael J. Spencer 57543f01caeSNick Lewycky switch (getSymbolTableIndex(symb)) { 576b60a18deSMichael J. Spencer case ELF::SHN_UNDEF: 577b60a18deSMichael J. Spencer if (ret == '?') 578b60a18deSMichael J. Spencer ret = 'U'; 579b60a18deSMichael J. Spencer break; 580b60a18deSMichael J. Spencer case ELF::SHN_ABS: ret = 'a'; break; 581b60a18deSMichael J. Spencer case ELF::SHN_COMMON: ret = 'c'; break; 582b60a18deSMichael J. Spencer } 583b60a18deSMichael J. Spencer 584b60a18deSMichael J. Spencer switch (symb->getBinding()) { 585b60a18deSMichael J. Spencer case ELF::STB_GLOBAL: ret = ::toupper(ret); break; 586b60a18deSMichael J. Spencer case ELF::STB_WEAK: 58743f01caeSNick Lewycky if (getSymbolTableIndex(symb) == ELF::SHN_UNDEF) 588b60a18deSMichael J. Spencer ret = 'w'; 589b60a18deSMichael J. Spencer else 590b60a18deSMichael J. Spencer if (symb->getType() == ELF::STT_OBJECT) 591b60a18deSMichael J. Spencer ret = 'V'; 592b60a18deSMichael J. Spencer else 593b60a18deSMichael J. Spencer ret = 'W'; 594b60a18deSMichael J. Spencer } 595b60a18deSMichael J. Spencer 5961d6167fdSMichael J. Spencer if (ret == '?' && symb->getType() == ELF::STT_SECTION) { 5971d6167fdSMichael J. Spencer StringRef name; 5981d6167fdSMichael J. Spencer if (error_code ec = getSymbolName(Symb, name)) 5991d6167fdSMichael J. Spencer return ec; 6001d6167fdSMichael J. Spencer Result = StringSwitch<char>(name) 601b60a18deSMichael J. Spencer .StartsWith(".debug", 'N') 602022ecdf2SBenjamin Kramer .StartsWith(".note", 'n') 603022ecdf2SBenjamin Kramer .Default('?'); 6041d6167fdSMichael J. Spencer return object_error::success; 6051d6167fdSMichael J. Spencer } 606b60a18deSMichael J. Spencer 6071d6167fdSMichael J. Spencer Result = ret; 6081d6167fdSMichael J. Spencer return object_error::success; 609b60a18deSMichael J. Spencer } 610b60a18deSMichael J. Spencer 611b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 6121d6167fdSMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits> 61375d1cf33SBenjamin Kramer ::getSymbolType(DataRefImpl Symb, 614d3946676SMichael J. Spencer SymbolRef::Type &Result) const { 61575d1cf33SBenjamin Kramer validateSymbol(Symb); 61675d1cf33SBenjamin Kramer const Elf_Sym *symb = getSymbol(Symb); 61775d1cf33SBenjamin Kramer 6187adc4370SNick Lewycky if (getSymbolTableIndex(symb) == ELF::SHN_UNDEF) { 61975d1cf33SBenjamin Kramer Result = SymbolRef::ST_External; 62075d1cf33SBenjamin Kramer return object_error::success; 62175d1cf33SBenjamin Kramer } 62275d1cf33SBenjamin Kramer 62375d1cf33SBenjamin Kramer switch (symb->getType()) { 6241d19f97eSMichael J. Spencer case ELF::STT_SECTION: 6251d19f97eSMichael J. Spencer Result = SymbolRef::ST_Debug; 6261d19f97eSMichael J. Spencer break; 6271d19f97eSMichael J. Spencer case ELF::STT_FILE: 6281d19f97eSMichael J. Spencer Result = SymbolRef::ST_File; 6291d19f97eSMichael J. Spencer break; 63075d1cf33SBenjamin Kramer case ELF::STT_FUNC: 63175d1cf33SBenjamin Kramer Result = SymbolRef::ST_Function; 63275d1cf33SBenjamin Kramer break; 63375d1cf33SBenjamin Kramer case ELF::STT_OBJECT: 63475d1cf33SBenjamin Kramer Result = SymbolRef::ST_Data; 63575d1cf33SBenjamin Kramer break; 63675d1cf33SBenjamin Kramer default: 63775d1cf33SBenjamin Kramer Result = SymbolRef::ST_Other; 63875d1cf33SBenjamin Kramer break; 63975d1cf33SBenjamin Kramer } 64075d1cf33SBenjamin Kramer return object_error::success; 64175d1cf33SBenjamin Kramer } 64275d1cf33SBenjamin Kramer 64375d1cf33SBenjamin Kramer template<support::endianness target_endianness, bool is64Bits> 64475d1cf33SBenjamin Kramer error_code ELFObjectFile<target_endianness, is64Bits> 64575d1cf33SBenjamin Kramer ::isSymbolGlobal(DataRefImpl Symb, 64675d1cf33SBenjamin Kramer bool &Result) const { 64775d1cf33SBenjamin Kramer validateSymbol(Symb); 64875d1cf33SBenjamin Kramer const Elf_Sym *symb = getSymbol(Symb); 64975d1cf33SBenjamin Kramer 65075d1cf33SBenjamin Kramer Result = symb->getBinding() == ELF::STB_GLOBAL; 65175d1cf33SBenjamin Kramer return object_error::success; 65275d1cf33SBenjamin Kramer } 65375d1cf33SBenjamin Kramer 65475d1cf33SBenjamin Kramer template<support::endianness target_endianness, bool is64Bits> 65575d1cf33SBenjamin Kramer error_code ELFObjectFile<target_endianness, is64Bits> 65601759754SMichael J. Spencer ::isSymbolWeak(DataRefImpl Symb, 65701759754SMichael J. Spencer bool &Result) const { 65801759754SMichael J. Spencer validateSymbol(Symb); 65901759754SMichael J. Spencer const Elf_Sym *symb = getSymbol(Symb); 66001759754SMichael J. Spencer 66101759754SMichael J. Spencer Result = symb->getBinding() == ELF::STB_WEAK; 66201759754SMichael J. Spencer return object_error::success; 66301759754SMichael J. Spencer } 66401759754SMichael J. Spencer 66501759754SMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 66601759754SMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits> 66732173153SMichael J. Spencer ::isSymbolAbsolute(DataRefImpl Symb, bool &Res) const { 66832173153SMichael J. Spencer validateSymbol(Symb); 66932173153SMichael J. Spencer const Elf_Sym *symb = getSymbol(Symb); 67032173153SMichael J. Spencer Res = symb->st_shndx == ELF::SHN_ABS; 67132173153SMichael J. Spencer return object_error::success; 67232173153SMichael J. Spencer } 67332173153SMichael J. Spencer 67432173153SMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 67532173153SMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits> 67632173153SMichael J. Spencer ::getSymbolSection(DataRefImpl Symb, 67732173153SMichael J. Spencer section_iterator &Res) const { 67832173153SMichael J. Spencer validateSymbol(Symb); 67932173153SMichael J. Spencer const Elf_Sym *symb = getSymbol(Symb); 68032173153SMichael J. Spencer const Elf_Shdr *sec = getSection(symb); 68132173153SMichael J. Spencer if (!sec) 68232173153SMichael J. Spencer Res = end_sections(); 68332173153SMichael J. Spencer else { 68432173153SMichael J. Spencer DataRefImpl Sec; 68532173153SMichael J. Spencer Sec.p = reinterpret_cast<intptr_t>(sec); 68632173153SMichael J. Spencer Res = section_iterator(SectionRef(Sec, this)); 68732173153SMichael J. Spencer } 68832173153SMichael J. Spencer return object_error::success; 68932173153SMichael J. Spencer } 69032173153SMichael J. Spencer 69132173153SMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 69232173153SMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits> 6931d6167fdSMichael J. Spencer ::isSymbolInternal(DataRefImpl Symb, 6941d6167fdSMichael J. Spencer bool &Result) const { 695b60a18deSMichael J. Spencer validateSymbol(Symb); 696b60a18deSMichael J. Spencer const Elf_Sym *symb = getSymbol(Symb); 697b60a18deSMichael J. Spencer 698b60a18deSMichael J. Spencer if ( symb->getType() == ELF::STT_FILE 699b60a18deSMichael J. Spencer || symb->getType() == ELF::STT_SECTION) 7001d6167fdSMichael J. Spencer Result = true; 7011d6167fdSMichael J. Spencer Result = false; 7021d6167fdSMichael J. Spencer return object_error::success; 703b60a18deSMichael J. Spencer } 704b60a18deSMichael J. Spencer 705b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 7061d6167fdSMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits> 7071d6167fdSMichael J. Spencer ::getSectionNext(DataRefImpl Sec, SectionRef &Result) const { 7080324b672SMichael J. Spencer const uint8_t *sec = reinterpret_cast<const uint8_t *>(Sec.p); 709b60a18deSMichael J. Spencer sec += Header->e_shentsize; 7100324b672SMichael J. Spencer Sec.p = reinterpret_cast<intptr_t>(sec); 7111d6167fdSMichael J. Spencer Result = SectionRef(Sec, this); 7121d6167fdSMichael J. Spencer return object_error::success; 713b60a18deSMichael J. Spencer } 714b60a18deSMichael J. Spencer 715b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 7161d6167fdSMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits> 7171d6167fdSMichael J. Spencer ::getSectionName(DataRefImpl Sec, 7181d6167fdSMichael J. Spencer StringRef &Result) const { 7190324b672SMichael J. Spencer const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); 7201d6167fdSMichael J. Spencer Result = StringRef(getString(dot_shstrtab_sec, sec->sh_name)); 7211d6167fdSMichael J. Spencer return object_error::success; 722b60a18deSMichael J. Spencer } 723b60a18deSMichael J. Spencer 724b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 7251d6167fdSMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits> 7261d6167fdSMichael J. Spencer ::getSectionAddress(DataRefImpl Sec, 7271d6167fdSMichael J. Spencer uint64_t &Result) const { 7280324b672SMichael J. Spencer const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); 7291d6167fdSMichael J. Spencer Result = sec->sh_addr; 7301d6167fdSMichael J. Spencer return object_error::success; 731b60a18deSMichael J. Spencer } 732b60a18deSMichael J. Spencer 733b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 7341d6167fdSMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits> 7351d6167fdSMichael J. Spencer ::getSectionSize(DataRefImpl Sec, 7361d6167fdSMichael J. Spencer uint64_t &Result) const { 7370324b672SMichael J. Spencer const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); 7381d6167fdSMichael J. Spencer Result = sec->sh_size; 7391d6167fdSMichael J. Spencer return object_error::success; 740b60a18deSMichael J. Spencer } 741b60a18deSMichael J. Spencer 742b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 7431d6167fdSMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits> 7441d6167fdSMichael J. Spencer ::getSectionContents(DataRefImpl Sec, 7451d6167fdSMichael J. Spencer StringRef &Result) const { 7460324b672SMichael J. Spencer const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); 7471d6167fdSMichael J. Spencer const char *start = (const char*)base() + sec->sh_offset; 7481d6167fdSMichael J. Spencer Result = StringRef(start, sec->sh_size); 7491d6167fdSMichael J. Spencer return object_error::success; 750b60a18deSMichael J. Spencer } 751b60a18deSMichael J. Spencer 752b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 7531d6167fdSMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits> 7547989460aSMichael J. Spencer ::getSectionAlignment(DataRefImpl Sec, 7557989460aSMichael J. Spencer uint64_t &Result) const { 7567989460aSMichael J. Spencer const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); 7577989460aSMichael J. Spencer Result = sec->sh_addralign; 7587989460aSMichael J. Spencer return object_error::success; 7597989460aSMichael J. Spencer } 7607989460aSMichael J. Spencer 7617989460aSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 7627989460aSMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits> 7631d6167fdSMichael J. Spencer ::isSectionText(DataRefImpl Sec, 7641d6167fdSMichael J. Spencer bool &Result) const { 7650324b672SMichael J. Spencer const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); 766b60a18deSMichael J. Spencer if (sec->sh_flags & ELF::SHF_EXECINSTR) 7671d6167fdSMichael J. Spencer Result = true; 7681d6167fdSMichael J. Spencer else 7691d6167fdSMichael J. Spencer Result = false; 7701d6167fdSMichael J. Spencer return object_error::success; 771b60a18deSMichael J. Spencer } 772b60a18deSMichael J. Spencer 773b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 774f6f3e81cSBenjamin Kramer error_code ELFObjectFile<target_endianness, is64Bits> 775800619f2SMichael J. Spencer ::isSectionData(DataRefImpl Sec, 776800619f2SMichael J. Spencer bool &Result) const { 777800619f2SMichael J. Spencer const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); 778800619f2SMichael J. Spencer if (sec->sh_flags & (ELF::SHF_ALLOC | ELF::SHF_WRITE) 779800619f2SMichael J. Spencer && sec->sh_type == ELF::SHT_PROGBITS) 780800619f2SMichael J. Spencer Result = true; 781800619f2SMichael J. Spencer else 782800619f2SMichael J. Spencer Result = false; 783800619f2SMichael J. Spencer return object_error::success; 784800619f2SMichael J. Spencer } 785800619f2SMichael J. Spencer 786800619f2SMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 787800619f2SMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits> 788800619f2SMichael J. Spencer ::isSectionBSS(DataRefImpl Sec, 789800619f2SMichael J. Spencer bool &Result) const { 790800619f2SMichael J. Spencer const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); 791800619f2SMichael J. Spencer if (sec->sh_flags & (ELF::SHF_ALLOC | ELF::SHF_WRITE) 792800619f2SMichael J. Spencer && sec->sh_type == ELF::SHT_NOBITS) 793800619f2SMichael J. Spencer Result = true; 794800619f2SMichael J. Spencer else 795800619f2SMichael J. Spencer Result = false; 796800619f2SMichael J. Spencer return object_error::success; 797800619f2SMichael J. Spencer } 798800619f2SMichael J. Spencer 799800619f2SMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 800800619f2SMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits> 801f6f3e81cSBenjamin Kramer ::sectionContainsSymbol(DataRefImpl Sec, 802f6f3e81cSBenjamin Kramer DataRefImpl Symb, 803f6f3e81cSBenjamin Kramer bool &Result) const { 804f6f3e81cSBenjamin Kramer // FIXME: Unimplemented. 805f6f3e81cSBenjamin Kramer Result = false; 806f6f3e81cSBenjamin Kramer return object_error::success; 807f6f3e81cSBenjamin Kramer } 808f6f3e81cSBenjamin Kramer 809e5fd0047SMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 810e5fd0047SMichael J. Spencer relocation_iterator ELFObjectFile<target_endianness, is64Bits> 811e5fd0047SMichael J. Spencer ::getSectionRelBegin(DataRefImpl Sec) const { 812e5fd0047SMichael J. Spencer DataRefImpl RelData; 813e5fd0047SMichael J. Spencer memset(&RelData, 0, sizeof(RelData)); 814e5fd0047SMichael J. Spencer const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); 815e5fd0047SMichael J. Spencer typename RelocMap_t::const_iterator ittr = SectionRelocMap.find(sec); 816e5fd0047SMichael J. Spencer if (sec != 0 && ittr != SectionRelocMap.end()) { 817834bd602SMichael J. Spencer RelData.w.a = getSection(ittr->second[0])->sh_info; 818e5fd0047SMichael J. Spencer RelData.w.b = ittr->second[0]; 819e5fd0047SMichael J. Spencer RelData.w.c = 0; 820e5fd0047SMichael J. Spencer } 821e5fd0047SMichael J. Spencer return relocation_iterator(RelocationRef(RelData, this)); 822e5fd0047SMichael J. Spencer } 823e5fd0047SMichael J. Spencer 824e5fd0047SMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 825e5fd0047SMichael J. Spencer relocation_iterator ELFObjectFile<target_endianness, is64Bits> 826e5fd0047SMichael J. Spencer ::getSectionRelEnd(DataRefImpl Sec) const { 827e5fd0047SMichael J. Spencer DataRefImpl RelData; 828e5fd0047SMichael J. Spencer memset(&RelData, 0, sizeof(RelData)); 829e5fd0047SMichael J. Spencer const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); 830e5fd0047SMichael J. Spencer typename RelocMap_t::const_iterator ittr = SectionRelocMap.find(sec); 831e5fd0047SMichael J. Spencer if (sec != 0 && ittr != SectionRelocMap.end()) { 832e5fd0047SMichael J. Spencer // Get the index of the last relocation section for this section. 833e5fd0047SMichael J. Spencer std::size_t relocsecindex = ittr->second[ittr->second.size() - 1]; 834e5fd0047SMichael J. Spencer const Elf_Shdr *relocsec = getSection(relocsecindex); 835834bd602SMichael J. Spencer RelData.w.a = relocsec->sh_info; 836e5fd0047SMichael J. Spencer RelData.w.b = relocsecindex; 837e5fd0047SMichael J. Spencer RelData.w.c = relocsec->sh_size / relocsec->sh_entsize; 838e5fd0047SMichael J. Spencer } 839e5fd0047SMichael J. Spencer return relocation_iterator(RelocationRef(RelData, this)); 840e5fd0047SMichael J. Spencer } 841e5fd0047SMichael J. Spencer 842022ecdf2SBenjamin Kramer // Relocations 843022ecdf2SBenjamin Kramer template<support::endianness target_endianness, bool is64Bits> 844022ecdf2SBenjamin Kramer error_code ELFObjectFile<target_endianness, is64Bits> 845022ecdf2SBenjamin Kramer ::getRelocationNext(DataRefImpl Rel, 846022ecdf2SBenjamin Kramer RelocationRef &Result) const { 847e5fd0047SMichael J. Spencer ++Rel.w.c; 848e5fd0047SMichael J. Spencer const Elf_Shdr *relocsec = getSection(Rel.w.b); 849e5fd0047SMichael J. Spencer if (Rel.w.c >= (relocsec->sh_size / relocsec->sh_entsize)) { 850e5fd0047SMichael J. Spencer // We have reached the end of the relocations for this section. See if there 851e5fd0047SMichael J. Spencer // is another relocation section. 852cfb6cc7bSMichael J. Spencer typename RelocMap_t::mapped_type relocseclist = 853e5fd0047SMichael J. Spencer SectionRelocMap.lookup(getSection(Rel.w.a)); 854022ecdf2SBenjamin Kramer 855e5fd0047SMichael J. Spencer // Do a binary search for the current reloc section index (which must be 856e5fd0047SMichael J. Spencer // present). Then get the next one. 857e5fd0047SMichael J. Spencer typename RelocMap_t::mapped_type::const_iterator loc = 858e5fd0047SMichael J. Spencer std::lower_bound(relocseclist.begin(), relocseclist.end(), Rel.w.b); 859e5fd0047SMichael J. Spencer ++loc; 860e5fd0047SMichael J. Spencer 861e5fd0047SMichael J. Spencer // If there is no next one, don't do anything. The ++Rel.w.c above sets Rel 862e5fd0047SMichael J. Spencer // to the end iterator. 863e5fd0047SMichael J. Spencer if (loc != relocseclist.end()) { 864e5fd0047SMichael J. Spencer Rel.w.b = *loc; 865e5fd0047SMichael J. Spencer Rel.w.a = 0; 866022ecdf2SBenjamin Kramer } 867022ecdf2SBenjamin Kramer } 868022ecdf2SBenjamin Kramer Result = RelocationRef(Rel, this); 869022ecdf2SBenjamin Kramer return object_error::success; 870022ecdf2SBenjamin Kramer } 871022ecdf2SBenjamin Kramer 872022ecdf2SBenjamin Kramer template<support::endianness target_endianness, bool is64Bits> 873022ecdf2SBenjamin Kramer error_code ELFObjectFile<target_endianness, is64Bits> 874022ecdf2SBenjamin Kramer ::getRelocationSymbol(DataRefImpl Rel, 875022ecdf2SBenjamin Kramer SymbolRef &Result) const { 876022ecdf2SBenjamin Kramer uint32_t symbolIdx; 877e5fd0047SMichael J. Spencer const Elf_Shdr *sec = getSection(Rel.w.b); 878022ecdf2SBenjamin Kramer switch (sec->sh_type) { 879022ecdf2SBenjamin Kramer default : 880022ecdf2SBenjamin Kramer report_fatal_error("Invalid section type in Rel!"); 881022ecdf2SBenjamin Kramer case ELF::SHT_REL : { 882022ecdf2SBenjamin Kramer symbolIdx = getRel(Rel)->getSymbol(); 883022ecdf2SBenjamin Kramer break; 884022ecdf2SBenjamin Kramer } 885022ecdf2SBenjamin Kramer case ELF::SHT_RELA : { 886022ecdf2SBenjamin Kramer symbolIdx = getRela(Rel)->getSymbol(); 887022ecdf2SBenjamin Kramer break; 888022ecdf2SBenjamin Kramer } 889022ecdf2SBenjamin Kramer } 890022ecdf2SBenjamin Kramer DataRefImpl SymbolData; 891022ecdf2SBenjamin Kramer IndexMap_t::const_iterator it = SymbolTableSectionsIndexMap.find(sec->sh_link); 892022ecdf2SBenjamin Kramer if (it == SymbolTableSectionsIndexMap.end()) 893022ecdf2SBenjamin Kramer report_fatal_error("Relocation symbol table not found!"); 894022ecdf2SBenjamin Kramer SymbolData.d.a = symbolIdx; 895022ecdf2SBenjamin Kramer SymbolData.d.b = it->second; 896022ecdf2SBenjamin Kramer Result = SymbolRef(SymbolData, this); 897022ecdf2SBenjamin Kramer return object_error::success; 898022ecdf2SBenjamin Kramer } 899022ecdf2SBenjamin Kramer 900022ecdf2SBenjamin Kramer template<support::endianness target_endianness, bool is64Bits> 901022ecdf2SBenjamin Kramer error_code ELFObjectFile<target_endianness, is64Bits> 902022ecdf2SBenjamin Kramer ::getRelocationAddress(DataRefImpl Rel, 903022ecdf2SBenjamin Kramer uint64_t &Result) const { 904022ecdf2SBenjamin Kramer uint64_t offset; 905e5fd0047SMichael J. Spencer const Elf_Shdr *sec = getSection(Rel.w.b); 906022ecdf2SBenjamin Kramer switch (sec->sh_type) { 907022ecdf2SBenjamin Kramer default : 908022ecdf2SBenjamin Kramer report_fatal_error("Invalid section type in Rel!"); 909022ecdf2SBenjamin Kramer case ELF::SHT_REL : { 910022ecdf2SBenjamin Kramer offset = getRel(Rel)->r_offset; 911022ecdf2SBenjamin Kramer break; 912022ecdf2SBenjamin Kramer } 913022ecdf2SBenjamin Kramer case ELF::SHT_RELA : { 914022ecdf2SBenjamin Kramer offset = getRela(Rel)->r_offset; 915022ecdf2SBenjamin Kramer break; 916022ecdf2SBenjamin Kramer } 917022ecdf2SBenjamin Kramer } 918022ecdf2SBenjamin Kramer 919e5fd0047SMichael J. Spencer Result = offset; 920022ecdf2SBenjamin Kramer return object_error::success; 921022ecdf2SBenjamin Kramer } 922022ecdf2SBenjamin Kramer 923022ecdf2SBenjamin Kramer template<support::endianness target_endianness, bool is64Bits> 924022ecdf2SBenjamin Kramer error_code ELFObjectFile<target_endianness, is64Bits> 925*2631f93fSDanil Malyshev ::getRelocationOffset(DataRefImpl Rel, 926*2631f93fSDanil Malyshev uint64_t &Result) const { 927*2631f93fSDanil Malyshev uint64_t offset; 928*2631f93fSDanil Malyshev const Elf_Shdr *sec = getSection(Rel.w.b); 929*2631f93fSDanil Malyshev switch (sec->sh_type) { 930*2631f93fSDanil Malyshev default : 931*2631f93fSDanil Malyshev report_fatal_error("Invalid section type in Rel!"); 932*2631f93fSDanil Malyshev case ELF::SHT_REL : { 933*2631f93fSDanil Malyshev offset = getRel(Rel)->r_offset; 934*2631f93fSDanil Malyshev break; 935*2631f93fSDanil Malyshev } 936*2631f93fSDanil Malyshev case ELF::SHT_RELA : { 937*2631f93fSDanil Malyshev offset = getRela(Rel)->r_offset; 938*2631f93fSDanil Malyshev break; 939*2631f93fSDanil Malyshev } 940*2631f93fSDanil Malyshev } 941*2631f93fSDanil Malyshev 942*2631f93fSDanil Malyshev Result = offset - sec->sh_addr; 943*2631f93fSDanil Malyshev return object_error::success; 944*2631f93fSDanil Malyshev } 945*2631f93fSDanil Malyshev 946*2631f93fSDanil Malyshev template<support::endianness target_endianness, bool is64Bits> 947*2631f93fSDanil Malyshev error_code ELFObjectFile<target_endianness, is64Bits> 948022ecdf2SBenjamin Kramer ::getRelocationType(DataRefImpl Rel, 9497be76590SOwen Anderson uint64_t &Result) const { 950e5fd0047SMichael J. Spencer const Elf_Shdr *sec = getSection(Rel.w.b); 951022ecdf2SBenjamin Kramer switch (sec->sh_type) { 952022ecdf2SBenjamin Kramer default : 953022ecdf2SBenjamin Kramer report_fatal_error("Invalid section type in Rel!"); 954022ecdf2SBenjamin Kramer case ELF::SHT_REL : { 955022ecdf2SBenjamin Kramer Result = getRel(Rel)->getType(); 956022ecdf2SBenjamin Kramer break; 957022ecdf2SBenjamin Kramer } 958022ecdf2SBenjamin Kramer case ELF::SHT_RELA : { 959022ecdf2SBenjamin Kramer Result = getRela(Rel)->getType(); 960022ecdf2SBenjamin Kramer break; 961022ecdf2SBenjamin Kramer } 962022ecdf2SBenjamin Kramer } 963022ecdf2SBenjamin Kramer return object_error::success; 964022ecdf2SBenjamin Kramer } 965022ecdf2SBenjamin Kramer 966e5fd0047SMichael J. Spencer #define LLVM_ELF_SWITCH_RELOC_TYPE_NAME(enum) \ 967e5fd0047SMichael J. Spencer case ELF::enum: res = #enum; break; 968e5fd0047SMichael J. Spencer 969e5fd0047SMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 970e5fd0047SMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits> 971e5fd0047SMichael J. Spencer ::getRelocationTypeName(DataRefImpl Rel, 972e5fd0047SMichael J. Spencer SmallVectorImpl<char> &Result) const { 973e5fd0047SMichael J. Spencer const Elf_Shdr *sec = getSection(Rel.w.b); 974e5fd0047SMichael J. Spencer uint8_t type; 975e5fd0047SMichael J. Spencer StringRef res; 976e5fd0047SMichael J. Spencer switch (sec->sh_type) { 977e5fd0047SMichael J. Spencer default : 978e5fd0047SMichael J. Spencer return object_error::parse_failed; 979e5fd0047SMichael J. Spencer case ELF::SHT_REL : { 980e5fd0047SMichael J. Spencer type = getRel(Rel)->getType(); 981e5fd0047SMichael J. Spencer break; 982e5fd0047SMichael J. Spencer } 983e5fd0047SMichael J. Spencer case ELF::SHT_RELA : { 984e5fd0047SMichael J. Spencer type = getRela(Rel)->getType(); 985e5fd0047SMichael J. Spencer break; 986e5fd0047SMichael J. Spencer } 987e5fd0047SMichael J. Spencer } 988e5fd0047SMichael J. Spencer switch (Header->e_machine) { 989e5fd0047SMichael J. Spencer case ELF::EM_X86_64: 990e5fd0047SMichael J. Spencer switch (type) { 991e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_NONE); 992e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_64); 993e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_PC32); 994e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOT32); 995e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_PLT32); 996e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_COPY); 997e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GLOB_DAT); 998e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_JUMP_SLOT); 999e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_RELATIVE); 1000e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTPCREL); 1001e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_32); 1002e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_32S); 1003e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_16); 1004e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_PC16); 1005e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_8); 1006e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_PC8); 1007e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_DTPMOD64); 1008e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_DTPOFF64); 1009e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_TPOFF64); 1010e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_TLSGD); 1011e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_TLSLD); 1012e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_DTPOFF32); 1013e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTTPOFF); 1014e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_TPOFF32); 1015e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_PC64); 1016e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTOFF64); 1017e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTPC32); 1018e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_SIZE32); 1019e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_SIZE64); 1020e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTPC32_TLSDESC); 1021e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_TLSDESC_CALL); 1022e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_TLSDESC); 1023e5fd0047SMichael J. Spencer default: 1024e5fd0047SMichael J. Spencer res = "Unknown"; 1025e5fd0047SMichael J. Spencer } 1026e5fd0047SMichael J. Spencer break; 1027e5fd0047SMichael J. Spencer case ELF::EM_386: 1028e5fd0047SMichael J. Spencer switch (type) { 1029e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_NONE); 1030e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_32); 1031e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_PC32); 1032e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_GOT32); 1033e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_PLT32); 1034e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_COPY); 1035e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_GLOB_DAT); 1036e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_JUMP_SLOT); 1037e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_RELATIVE); 1038e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_GOTOFF); 1039e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_GOTPC); 1040e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_32PLT); 1041e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_TPOFF); 1042e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_IE); 1043e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_GOTIE); 1044e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LE); 1045e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_GD); 1046e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LDM); 1047e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_16); 1048e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_PC16); 1049e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_8); 1050e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_PC8); 1051e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_GD_32); 1052e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_GD_PUSH); 1053e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_GD_CALL); 1054e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_GD_POP); 1055e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LDM_32); 1056e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LDM_PUSH); 1057e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LDM_CALL); 1058e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LDM_POP); 1059e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LDO_32); 1060e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_IE_32); 1061e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LE_32); 1062e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_DTPMOD32); 1063e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_DTPOFF32); 1064e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_TPOFF32); 1065e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_GOTDESC); 1066e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_DESC_CALL); 1067e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_DESC); 1068e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_IRELATIVE); 1069e5fd0047SMichael J. Spencer default: 1070e5fd0047SMichael J. Spencer res = "Unknown"; 1071e5fd0047SMichael J. Spencer } 1072e5fd0047SMichael J. Spencer break; 1073e5fd0047SMichael J. Spencer default: 1074e5fd0047SMichael J. Spencer res = "Unknown"; 1075e5fd0047SMichael J. Spencer } 1076e5fd0047SMichael J. Spencer Result.append(res.begin(), res.end()); 1077e5fd0047SMichael J. Spencer return object_error::success; 1078e5fd0047SMichael J. Spencer } 1079e5fd0047SMichael J. Spencer 1080e5fd0047SMichael J. Spencer #undef LLVM_ELF_SWITCH_RELOC_TYPE_NAME 1081e5fd0047SMichael J. Spencer 1082022ecdf2SBenjamin Kramer template<support::endianness target_endianness, bool is64Bits> 1083022ecdf2SBenjamin Kramer error_code ELFObjectFile<target_endianness, is64Bits> 1084022ecdf2SBenjamin Kramer ::getRelocationAdditionalInfo(DataRefImpl Rel, 1085022ecdf2SBenjamin Kramer int64_t &Result) const { 1086e5fd0047SMichael J. Spencer const Elf_Shdr *sec = getSection(Rel.w.b); 1087022ecdf2SBenjamin Kramer switch (sec->sh_type) { 1088022ecdf2SBenjamin Kramer default : 1089022ecdf2SBenjamin Kramer report_fatal_error("Invalid section type in Rel!"); 1090022ecdf2SBenjamin Kramer case ELF::SHT_REL : { 1091022ecdf2SBenjamin Kramer Result = 0; 1092022ecdf2SBenjamin Kramer return object_error::success; 1093022ecdf2SBenjamin Kramer } 1094022ecdf2SBenjamin Kramer case ELF::SHT_RELA : { 1095022ecdf2SBenjamin Kramer Result = getRela(Rel)->r_addend; 1096022ecdf2SBenjamin Kramer return object_error::success; 1097022ecdf2SBenjamin Kramer } 1098022ecdf2SBenjamin Kramer } 1099022ecdf2SBenjamin Kramer } 1100022ecdf2SBenjamin Kramer 1101e5fd0047SMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 1102e5fd0047SMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits> 1103e5fd0047SMichael J. Spencer ::getRelocationValueString(DataRefImpl Rel, 1104e5fd0047SMichael J. Spencer SmallVectorImpl<char> &Result) const { 1105e5fd0047SMichael J. Spencer const Elf_Shdr *sec = getSection(Rel.w.b); 1106e5fd0047SMichael J. Spencer uint8_t type; 1107e5fd0047SMichael J. Spencer StringRef res; 1108e5fd0047SMichael J. Spencer int64_t addend = 0; 1109e5fd0047SMichael J. Spencer uint16_t symbol_index = 0; 1110e5fd0047SMichael J. Spencer switch (sec->sh_type) { 1111e5fd0047SMichael J. Spencer default : 1112e5fd0047SMichael J. Spencer return object_error::parse_failed; 1113e5fd0047SMichael J. Spencer case ELF::SHT_REL : { 1114e5fd0047SMichael J. Spencer type = getRel(Rel)->getType(); 1115e5fd0047SMichael J. Spencer symbol_index = getRel(Rel)->getSymbol(); 1116e5fd0047SMichael J. Spencer // TODO: Read implicit addend from section data. 1117e5fd0047SMichael J. Spencer break; 1118e5fd0047SMichael J. Spencer } 1119e5fd0047SMichael J. Spencer case ELF::SHT_RELA : { 1120e5fd0047SMichael J. Spencer type = getRela(Rel)->getType(); 1121e5fd0047SMichael J. Spencer symbol_index = getRela(Rel)->getSymbol(); 1122e5fd0047SMichael J. Spencer addend = getRela(Rel)->r_addend; 1123e5fd0047SMichael J. Spencer break; 1124e5fd0047SMichael J. Spencer } 1125e5fd0047SMichael J. Spencer } 1126e5fd0047SMichael J. Spencer const Elf_Sym *symb = getEntry<Elf_Sym>(sec->sh_link, symbol_index); 1127e5fd0047SMichael J. Spencer StringRef symname; 1128e5fd0047SMichael J. Spencer if (error_code ec = getSymbolName(symb, symname)) 1129e5fd0047SMichael J. Spencer return ec; 1130e5fd0047SMichael J. Spencer switch (Header->e_machine) { 1131e5fd0047SMichael J. Spencer case ELF::EM_X86_64: 1132e5fd0047SMichael J. Spencer switch (type) { 1133e5fd0047SMichael J. Spencer case ELF::R_X86_64_32S: 1134e5fd0047SMichael J. Spencer res = symname; 1135e5fd0047SMichael J. Spencer break; 1136e5fd0047SMichael J. Spencer case ELF::R_X86_64_PC32: { 1137e5fd0047SMichael J. Spencer std::string fmtbuf; 1138e5fd0047SMichael J. Spencer raw_string_ostream fmt(fmtbuf); 1139e5fd0047SMichael J. Spencer fmt << symname << (addend < 0 ? "" : "+") << addend << "-P"; 1140e5fd0047SMichael J. Spencer fmt.flush(); 1141e5fd0047SMichael J. Spencer Result.append(fmtbuf.begin(), fmtbuf.end()); 1142e5fd0047SMichael J. Spencer } 1143e5fd0047SMichael J. Spencer break; 1144e5fd0047SMichael J. Spencer default: 1145e5fd0047SMichael J. Spencer res = "Unknown"; 1146e5fd0047SMichael J. Spencer } 1147e5fd0047SMichael J. Spencer break; 1148e5fd0047SMichael J. Spencer default: 1149e5fd0047SMichael J. Spencer res = "Unknown"; 1150e5fd0047SMichael J. Spencer } 1151e5fd0047SMichael J. Spencer if (Result.empty()) 1152e5fd0047SMichael J. Spencer Result.append(res.begin(), res.end()); 1153e5fd0047SMichael J. Spencer return object_error::success; 1154e5fd0047SMichael J. Spencer } 1155022ecdf2SBenjamin Kramer 1156f6f3e81cSBenjamin Kramer template<support::endianness target_endianness, bool is64Bits> 1157ec29b121SMichael J. Spencer ELFObjectFile<target_endianness, is64Bits>::ELFObjectFile(MemoryBuffer *Object 1158ec29b121SMichael J. Spencer , error_code &ec) 1159ec29b121SMichael J. Spencer : ObjectFile(Binary::isELF, Object, ec) 1160b60a18deSMichael J. Spencer , SectionHeaderTable(0) 1161b60a18deSMichael J. Spencer , dot_shstrtab_sec(0) 1162b60a18deSMichael J. Spencer , dot_strtab_sec(0) { 1163ec29b121SMichael J. Spencer Header = reinterpret_cast<const Elf_Ehdr *>(base()); 1164b60a18deSMichael J. Spencer 1165b60a18deSMichael J. Spencer if (Header->e_shoff == 0) 1166b60a18deSMichael J. Spencer return; 1167b60a18deSMichael J. Spencer 1168b60a18deSMichael J. Spencer SectionHeaderTable = 1169ec29b121SMichael J. Spencer reinterpret_cast<const Elf_Shdr *>(base() + Header->e_shoff); 117043f01caeSNick Lewycky uint64_t SectionTableSize = getNumSections() * Header->e_shentsize; 1171b60a18deSMichael J. Spencer if (!( (const uint8_t *)SectionHeaderTable + SectionTableSize 1172ec29b121SMichael J. Spencer <= base() + Data->getBufferSize())) 1173b60a18deSMichael J. Spencer // FIXME: Proper error handling. 1174b60a18deSMichael J. Spencer report_fatal_error("Section table goes past end of file!"); 1175b60a18deSMichael J. Spencer 117635a90c4bSNick Lewycky 11777adc4370SNick Lewycky // To find the symbol tables we walk the section table to find SHT_SYMTAB. 11787adc4370SNick Lewycky const Elf_Shdr* SymbolTableSectionHeaderIndex = 0; 1179e5fd0047SMichael J. Spencer const Elf_Shdr* sh = reinterpret_cast<const Elf_Shdr*>(SectionHeaderTable); 118043f01caeSNick Lewycky for (uint64_t i = 0, e = getNumSections(); i != e; ++i) { 11817adc4370SNick Lewycky if (sh->sh_type == ELF::SHT_SYMTAB_SHNDX) { 11827adc4370SNick Lewycky if (SymbolTableSectionHeaderIndex) 11837adc4370SNick Lewycky // FIXME: Proper error handling. 11847adc4370SNick Lewycky report_fatal_error("More than one .symtab_shndx!"); 11857adc4370SNick Lewycky SymbolTableSectionHeaderIndex = sh; 11867adc4370SNick Lewycky } 1187b60a18deSMichael J. Spencer if (sh->sh_type == ELF::SHT_SYMTAB) { 1188022ecdf2SBenjamin Kramer SymbolTableSectionsIndexMap[i] = SymbolTableSections.size(); 1189b60a18deSMichael J. Spencer SymbolTableSections.push_back(sh); 1190b60a18deSMichael J. Spencer } 1191022ecdf2SBenjamin Kramer if (sh->sh_type == ELF::SHT_REL || sh->sh_type == ELF::SHT_RELA) { 1192834bd602SMichael J. Spencer SectionRelocMap[getSection(sh->sh_info)].push_back(i); 1193022ecdf2SBenjamin Kramer } 1194022ecdf2SBenjamin Kramer ++sh; 1195b60a18deSMichael J. Spencer } 1196b60a18deSMichael J. Spencer 1197e5fd0047SMichael J. Spencer // Sort section relocation lists by index. 1198e5fd0047SMichael J. Spencer for (typename RelocMap_t::iterator i = SectionRelocMap.begin(), 1199e5fd0047SMichael J. Spencer e = SectionRelocMap.end(); i != e; ++i) { 1200e5fd0047SMichael J. Spencer std::sort(i->second.begin(), i->second.end()); 1201e5fd0047SMichael J. Spencer } 1202e5fd0047SMichael J. Spencer 1203b60a18deSMichael J. Spencer // Get string table sections. 120443f01caeSNick Lewycky dot_shstrtab_sec = getSection(getStringTableIndex()); 1205b60a18deSMichael J. Spencer if (dot_shstrtab_sec) { 1206b60a18deSMichael J. Spencer // Verify that the last byte in the string table in a null. 1207ec29b121SMichael J. Spencer if (((const char*)base() + dot_shstrtab_sec->sh_offset) 1208b60a18deSMichael J. Spencer [dot_shstrtab_sec->sh_size - 1] != 0) 1209b60a18deSMichael J. Spencer // FIXME: Proper error handling. 1210b60a18deSMichael J. Spencer report_fatal_error("String table must end with a null terminator!"); 1211b60a18deSMichael J. Spencer } 1212b60a18deSMichael J. Spencer 1213b60a18deSMichael J. Spencer // Merge this into the above loop. 1214b60a18deSMichael J. Spencer for (const char *i = reinterpret_cast<const char *>(SectionHeaderTable), 121543f01caeSNick Lewycky *e = i + getNumSections() * Header->e_shentsize; 1216b60a18deSMichael J. Spencer i != e; i += Header->e_shentsize) { 1217b60a18deSMichael J. Spencer const Elf_Shdr *sh = reinterpret_cast<const Elf_Shdr*>(i); 1218b60a18deSMichael J. Spencer if (sh->sh_type == ELF::SHT_STRTAB) { 1219b60a18deSMichael J. Spencer StringRef SectionName(getString(dot_shstrtab_sec, sh->sh_name)); 1220b60a18deSMichael J. Spencer if (SectionName == ".strtab") { 1221b60a18deSMichael J. Spencer if (dot_strtab_sec != 0) 1222b60a18deSMichael J. Spencer // FIXME: Proper error handling. 1223b60a18deSMichael J. Spencer report_fatal_error("Already found section named .strtab!"); 1224b60a18deSMichael J. Spencer dot_strtab_sec = sh; 1225ec29b121SMichael J. Spencer const char *dot_strtab = (const char*)base() + sh->sh_offset; 1226b60a18deSMichael J. Spencer if (dot_strtab[sh->sh_size - 1] != 0) 1227b60a18deSMichael J. Spencer // FIXME: Proper error handling. 1228b60a18deSMichael J. Spencer report_fatal_error("String table must end with a null terminator!"); 1229b60a18deSMichael J. Spencer } 1230b60a18deSMichael J. Spencer } 1231b60a18deSMichael J. Spencer } 12327adc4370SNick Lewycky 12337adc4370SNick Lewycky // Build symbol name side-mapping if there is one. 12347adc4370SNick Lewycky if (SymbolTableSectionHeaderIndex) { 12357adc4370SNick Lewycky const Elf_Word *ShndxTable = reinterpret_cast<const Elf_Word*>(base() + 12367adc4370SNick Lewycky SymbolTableSectionHeaderIndex->sh_offset); 12377adc4370SNick Lewycky error_code ec; 12387adc4370SNick Lewycky for (symbol_iterator si = begin_symbols(), 12397adc4370SNick Lewycky se = end_symbols(); si != se; si.increment(ec)) { 12407adc4370SNick Lewycky if (ec) 12417adc4370SNick Lewycky report_fatal_error("Fewer extended symbol table entries than symbols!"); 12427adc4370SNick Lewycky if (*ShndxTable != ELF::SHN_UNDEF) 12437adc4370SNick Lewycky ExtendedSymbolTable[getSymbol(si->getRawDataRefImpl())] = *ShndxTable; 12447adc4370SNick Lewycky ++ShndxTable; 12457adc4370SNick Lewycky } 12467adc4370SNick Lewycky } 1247b60a18deSMichael J. Spencer } 1248b60a18deSMichael J. Spencer 1249b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 1250e5fd0047SMichael J. Spencer symbol_iterator ELFObjectFile<target_endianness, is64Bits> 1251b60a18deSMichael J. Spencer ::begin_symbols() const { 12520324b672SMichael J. Spencer DataRefImpl SymbolData; 1253b60a18deSMichael J. Spencer memset(&SymbolData, 0, sizeof(SymbolData)); 1254b60a18deSMichael J. Spencer if (SymbolTableSections.size() == 0) { 12550324b672SMichael J. Spencer SymbolData.d.a = std::numeric_limits<uint32_t>::max(); 12560324b672SMichael J. Spencer SymbolData.d.b = std::numeric_limits<uint32_t>::max(); 1257b60a18deSMichael J. Spencer } else { 12580324b672SMichael J. Spencer SymbolData.d.a = 1; // The 0th symbol in ELF is fake. 12590324b672SMichael J. Spencer SymbolData.d.b = 0; 1260b60a18deSMichael J. Spencer } 12610324b672SMichael J. Spencer return symbol_iterator(SymbolRef(SymbolData, this)); 1262b60a18deSMichael J. Spencer } 1263b60a18deSMichael J. Spencer 1264b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 1265e5fd0047SMichael J. Spencer symbol_iterator ELFObjectFile<target_endianness, is64Bits> 1266b60a18deSMichael J. Spencer ::end_symbols() const { 12670324b672SMichael J. Spencer DataRefImpl SymbolData; 1268b60a18deSMichael J. Spencer memset(&SymbolData, 0, sizeof(SymbolData)); 12690324b672SMichael J. Spencer SymbolData.d.a = std::numeric_limits<uint32_t>::max(); 12700324b672SMichael J. Spencer SymbolData.d.b = std::numeric_limits<uint32_t>::max(); 12710324b672SMichael J. Spencer return symbol_iterator(SymbolRef(SymbolData, this)); 1272b60a18deSMichael J. Spencer } 1273b60a18deSMichael J. Spencer 1274b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 1275e5fd0047SMichael J. Spencer section_iterator ELFObjectFile<target_endianness, is64Bits> 1276b60a18deSMichael J. Spencer ::begin_sections() const { 12770324b672SMichael J. Spencer DataRefImpl ret; 1278ee066fc4SEric Christopher memset(&ret, 0, sizeof(DataRefImpl)); 1279ec29b121SMichael J. Spencer ret.p = reinterpret_cast<intptr_t>(base() + Header->e_shoff); 12800324b672SMichael J. Spencer return section_iterator(SectionRef(ret, this)); 1281b60a18deSMichael J. Spencer } 1282b60a18deSMichael J. Spencer 1283b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 1284e5fd0047SMichael J. Spencer section_iterator ELFObjectFile<target_endianness, is64Bits> 1285b60a18deSMichael J. Spencer ::end_sections() const { 12860324b672SMichael J. Spencer DataRefImpl ret; 1287ee066fc4SEric Christopher memset(&ret, 0, sizeof(DataRefImpl)); 1288ec29b121SMichael J. Spencer ret.p = reinterpret_cast<intptr_t>(base() 1289b60a18deSMichael J. Spencer + Header->e_shoff 129043f01caeSNick Lewycky + (Header->e_shentsize*getNumSections())); 12910324b672SMichael J. Spencer return section_iterator(SectionRef(ret, this)); 1292b60a18deSMichael J. Spencer } 1293b60a18deSMichael J. Spencer 1294b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 1295b60a18deSMichael J. Spencer uint8_t ELFObjectFile<target_endianness, is64Bits>::getBytesInAddress() const { 12960324b672SMichael J. Spencer return is64Bits ? 8 : 4; 1297b60a18deSMichael J. Spencer } 1298b60a18deSMichael J. Spencer 1299b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 1300b60a18deSMichael J. Spencer StringRef ELFObjectFile<target_endianness, is64Bits> 1301b60a18deSMichael J. Spencer ::getFileFormatName() const { 1302b60a18deSMichael J. Spencer switch(Header->e_ident[ELF::EI_CLASS]) { 1303b60a18deSMichael J. Spencer case ELF::ELFCLASS32: 1304b60a18deSMichael J. Spencer switch(Header->e_machine) { 1305b60a18deSMichael J. Spencer case ELF::EM_386: 1306b60a18deSMichael J. Spencer return "ELF32-i386"; 1307b60a18deSMichael J. Spencer case ELF::EM_X86_64: 1308b60a18deSMichael J. Spencer return "ELF32-x86-64"; 1309022ecdf2SBenjamin Kramer case ELF::EM_ARM: 1310022ecdf2SBenjamin Kramer return "ELF32-arm"; 1311b60a18deSMichael J. Spencer default: 1312b60a18deSMichael J. Spencer return "ELF32-unknown"; 1313b60a18deSMichael J. Spencer } 1314b60a18deSMichael J. Spencer case ELF::ELFCLASS64: 1315b60a18deSMichael J. Spencer switch(Header->e_machine) { 1316b60a18deSMichael J. Spencer case ELF::EM_386: 1317b60a18deSMichael J. Spencer return "ELF64-i386"; 1318b60a18deSMichael J. Spencer case ELF::EM_X86_64: 1319b60a18deSMichael J. Spencer return "ELF64-x86-64"; 1320b60a18deSMichael J. Spencer default: 1321b60a18deSMichael J. Spencer return "ELF64-unknown"; 1322b60a18deSMichael J. Spencer } 1323b60a18deSMichael J. Spencer default: 1324b60a18deSMichael J. Spencer // FIXME: Proper error handling. 1325b60a18deSMichael J. Spencer report_fatal_error("Invalid ELFCLASS!"); 1326b60a18deSMichael J. Spencer } 1327b60a18deSMichael J. Spencer } 1328b60a18deSMichael J. Spencer 1329b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 1330b60a18deSMichael J. Spencer unsigned ELFObjectFile<target_endianness, is64Bits>::getArch() const { 1331b60a18deSMichael J. Spencer switch(Header->e_machine) { 1332b60a18deSMichael J. Spencer case ELF::EM_386: 1333b60a18deSMichael J. Spencer return Triple::x86; 1334b60a18deSMichael J. Spencer case ELF::EM_X86_64: 1335b60a18deSMichael J. Spencer return Triple::x86_64; 1336022ecdf2SBenjamin Kramer case ELF::EM_ARM: 1337022ecdf2SBenjamin Kramer return Triple::arm; 1338b60a18deSMichael J. Spencer default: 1339b60a18deSMichael J. Spencer return Triple::UnknownArch; 1340b60a18deSMichael J. Spencer } 1341b60a18deSMichael J. Spencer } 1342b60a18deSMichael J. Spencer 134343f01caeSNick Lewycky template<support::endianness target_endianness, bool is64Bits> 134443f01caeSNick Lewycky uint64_t ELFObjectFile<target_endianness, is64Bits>::getNumSections() const { 134543f01caeSNick Lewycky if (Header->e_shnum == ELF::SHN_UNDEF) 134643f01caeSNick Lewycky return SectionHeaderTable->sh_size; 134743f01caeSNick Lewycky return Header->e_shnum; 134843f01caeSNick Lewycky } 134943f01caeSNick Lewycky 135043f01caeSNick Lewycky template<support::endianness target_endianness, bool is64Bits> 135143f01caeSNick Lewycky uint64_t 135243f01caeSNick Lewycky ELFObjectFile<target_endianness, is64Bits>::getStringTableIndex() const { 135343f01caeSNick Lewycky if (Header->e_shnum == ELF::SHN_UNDEF) { 135443f01caeSNick Lewycky if (Header->e_shstrndx == ELF::SHN_HIRESERVE) 135543f01caeSNick Lewycky return SectionHeaderTable->sh_link; 135643f01caeSNick Lewycky if (Header->e_shstrndx >= getNumSections()) 135743f01caeSNick Lewycky return 0; 135843f01caeSNick Lewycky } 135943f01caeSNick Lewycky return Header->e_shstrndx; 136043f01caeSNick Lewycky } 136143f01caeSNick Lewycky 1362e5fd0047SMichael J. Spencer 1363b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 1364022ecdf2SBenjamin Kramer template<typename T> 1365022ecdf2SBenjamin Kramer inline const T * 1366e5fd0047SMichael J. Spencer ELFObjectFile<target_endianness, is64Bits>::getEntry(uint16_t Section, 1367e5fd0047SMichael J. Spencer uint32_t Entry) const { 1368e5fd0047SMichael J. Spencer return getEntry<T>(getSection(Section), Entry); 1369e5fd0047SMichael J. Spencer } 1370e5fd0047SMichael J. Spencer 1371e5fd0047SMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 1372e5fd0047SMichael J. Spencer template<typename T> 1373e5fd0047SMichael J. Spencer inline const T * 1374e5fd0047SMichael J. Spencer ELFObjectFile<target_endianness, is64Bits>::getEntry(const Elf_Shdr * Section, 1375e5fd0047SMichael J. Spencer uint32_t Entry) const { 1376022ecdf2SBenjamin Kramer return reinterpret_cast<const T *>( 1377ec29b121SMichael J. Spencer base() 1378e5fd0047SMichael J. Spencer + Section->sh_offset 1379e5fd0047SMichael J. Spencer + (Entry * Section->sh_entsize)); 1380022ecdf2SBenjamin Kramer } 1381022ecdf2SBenjamin Kramer 1382022ecdf2SBenjamin Kramer template<support::endianness target_endianness, bool is64Bits> 1383022ecdf2SBenjamin Kramer const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Sym * 1384022ecdf2SBenjamin Kramer ELFObjectFile<target_endianness, is64Bits>::getSymbol(DataRefImpl Symb) const { 1385e5fd0047SMichael J. Spencer return getEntry<Elf_Sym>(SymbolTableSections[Symb.d.b], Symb.d.a); 1386022ecdf2SBenjamin Kramer } 1387022ecdf2SBenjamin Kramer 1388022ecdf2SBenjamin Kramer template<support::endianness target_endianness, bool is64Bits> 1389022ecdf2SBenjamin Kramer const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Rel * 1390022ecdf2SBenjamin Kramer ELFObjectFile<target_endianness, is64Bits>::getRel(DataRefImpl Rel) const { 1391e5fd0047SMichael J. Spencer return getEntry<Elf_Rel>(Rel.w.b, Rel.w.c); 1392022ecdf2SBenjamin Kramer } 1393022ecdf2SBenjamin Kramer 1394022ecdf2SBenjamin Kramer template<support::endianness target_endianness, bool is64Bits> 1395022ecdf2SBenjamin Kramer const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Rela * 1396022ecdf2SBenjamin Kramer ELFObjectFile<target_endianness, is64Bits>::getRela(DataRefImpl Rela) const { 1397e5fd0047SMichael J. Spencer return getEntry<Elf_Rela>(Rela.w.b, Rela.w.c); 1398b60a18deSMichael J. Spencer } 1399b60a18deSMichael J. Spencer 1400b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 1401b60a18deSMichael J. Spencer const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Shdr * 1402b60a18deSMichael J. Spencer ELFObjectFile<target_endianness, is64Bits>::getSection(DataRefImpl Symb) const { 14030324b672SMichael J. Spencer const Elf_Shdr *sec = getSection(Symb.d.b); 1404e5fd0047SMichael J. Spencer if (sec->sh_type != ELF::SHT_SYMTAB || sec->sh_type != ELF::SHT_DYNSYM) 1405b60a18deSMichael J. Spencer // FIXME: Proper error handling. 1406b60a18deSMichael J. Spencer report_fatal_error("Invalid symbol table section!"); 1407b60a18deSMichael J. Spencer return sec; 1408b60a18deSMichael J. Spencer } 1409b60a18deSMichael J. Spencer 1410b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 1411b60a18deSMichael J. Spencer const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Shdr * 141243f01caeSNick Lewycky ELFObjectFile<target_endianness, is64Bits>::getSection(uint32_t index) const { 141343f01caeSNick Lewycky if (index == 0) 1414b60a18deSMichael J. Spencer return 0; 141543f01caeSNick Lewycky if (!SectionHeaderTable || index >= getNumSections()) 1416b60a18deSMichael J. Spencer // FIXME: Proper error handling. 1417b60a18deSMichael J. Spencer report_fatal_error("Invalid section index!"); 1418b60a18deSMichael J. Spencer 1419b60a18deSMichael J. Spencer return reinterpret_cast<const Elf_Shdr *>( 1420b60a18deSMichael J. Spencer reinterpret_cast<const char *>(SectionHeaderTable) 1421b60a18deSMichael J. Spencer + (index * Header->e_shentsize)); 1422b60a18deSMichael J. Spencer } 1423b60a18deSMichael J. Spencer 1424b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 1425b60a18deSMichael J. Spencer const char *ELFObjectFile<target_endianness, is64Bits> 142643f01caeSNick Lewycky ::getString(uint32_t section, 1427b60a18deSMichael J. Spencer ELF::Elf32_Word offset) const { 1428b60a18deSMichael J. Spencer return getString(getSection(section), offset); 1429b60a18deSMichael J. Spencer } 1430b60a18deSMichael J. Spencer 1431b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 1432b60a18deSMichael J. Spencer const char *ELFObjectFile<target_endianness, is64Bits> 1433b60a18deSMichael J. Spencer ::getString(const Elf_Shdr *section, 1434b60a18deSMichael J. Spencer ELF::Elf32_Word offset) const { 1435b60a18deSMichael J. Spencer assert(section && section->sh_type == ELF::SHT_STRTAB && "Invalid section!"); 1436b60a18deSMichael J. Spencer if (offset >= section->sh_size) 1437b60a18deSMichael J. Spencer // FIXME: Proper error handling. 1438ec29b121SMichael J. Spencer report_fatal_error("Symbol name offset outside of string table!"); 1439ec29b121SMichael J. Spencer return (const char *)base() + section->sh_offset + offset; 1440b60a18deSMichael J. Spencer } 1441b60a18deSMichael J. Spencer 1442e5fd0047SMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 1443e5fd0047SMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits> 1444e5fd0047SMichael J. Spencer ::getSymbolName(const Elf_Sym *symb, 1445e5fd0047SMichael J. Spencer StringRef &Result) const { 1446e5fd0047SMichael J. Spencer if (symb->st_name == 0) { 144743f01caeSNick Lewycky const Elf_Shdr *section = getSection(symb); 1448e5fd0047SMichael J. Spencer if (!section) 1449e5fd0047SMichael J. Spencer Result = ""; 1450e5fd0047SMichael J. Spencer else 1451e5fd0047SMichael J. Spencer Result = getString(dot_shstrtab_sec, section->sh_name); 1452e5fd0047SMichael J. Spencer return object_error::success; 1453e5fd0047SMichael J. Spencer } 1454e5fd0047SMichael J. Spencer 1455e5fd0047SMichael J. Spencer // Use the default symbol table name section. 1456e5fd0047SMichael J. Spencer Result = getString(dot_strtab_sec, symb->st_name); 1457e5fd0047SMichael J. Spencer return object_error::success; 1458e5fd0047SMichael J. Spencer } 1459e5fd0047SMichael J. Spencer 1460b60a18deSMichael J. Spencer // EI_CLASS, EI_DATA. 1461b60a18deSMichael J. Spencer static std::pair<unsigned char, unsigned char> 1462b60a18deSMichael J. Spencer getElfArchType(MemoryBuffer *Object) { 1463b60a18deSMichael J. Spencer if (Object->getBufferSize() < ELF::EI_NIDENT) 1464b60a18deSMichael J. Spencer return std::make_pair((uint8_t)ELF::ELFCLASSNONE,(uint8_t)ELF::ELFDATANONE); 1465b60a18deSMichael J. Spencer return std::make_pair( (uint8_t)Object->getBufferStart()[ELF::EI_CLASS] 1466b60a18deSMichael J. Spencer , (uint8_t)Object->getBufferStart()[ELF::EI_DATA]); 1467b60a18deSMichael J. Spencer } 1468b60a18deSMichael J. Spencer 1469b60a18deSMichael J. Spencer namespace llvm { 1470b60a18deSMichael J. Spencer 1471b60a18deSMichael J. Spencer ObjectFile *ObjectFile::createELFObjectFile(MemoryBuffer *Object) { 1472b60a18deSMichael J. Spencer std::pair<unsigned char, unsigned char> Ident = getElfArchType(Object); 1473ec29b121SMichael J. Spencer error_code ec; 1474b60a18deSMichael J. Spencer if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2LSB) 1475ec29b121SMichael J. Spencer return new ELFObjectFile<support::little, false>(Object, ec); 1476b60a18deSMichael J. Spencer else if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2MSB) 1477ec29b121SMichael J. Spencer return new ELFObjectFile<support::big, false>(Object, ec); 1478b60a18deSMichael J. Spencer else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2LSB) 1479ec29b121SMichael J. Spencer return new ELFObjectFile<support::little, true>(Object, ec); 1480b60a18deSMichael J. Spencer else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2MSB) 1481ec29b121SMichael J. Spencer return new ELFObjectFile<support::big, true>(Object, ec); 1482b60a18deSMichael J. Spencer // FIXME: Proper error handling. 1483b60a18deSMichael J. Spencer report_fatal_error("Not an ELF object file!"); 1484b60a18deSMichael J. Spencer } 1485b60a18deSMichael J. Spencer 1486b60a18deSMichael J. Spencer } // end namespace llvm 1487