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 // 10*c3c80f09SEli Bendersky // This file defines the ELFObjectFile and DyldELFObject classes. 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" 19*c3c80f09SEli Bendersky #include "llvm/Support/Casting.h" 20b60a18deSMichael J. Spencer #include "llvm/Support/ELF.h" 21b60a18deSMichael J. Spencer #include "llvm/Support/Endian.h" 22b60a18deSMichael J. Spencer #include "llvm/Support/ErrorHandling.h" 23b60a18deSMichael J. Spencer #include "llvm/Support/MemoryBuffer.h" 24e5fd0047SMichael J. Spencer #include "llvm/Support/raw_ostream.h" 25e5fd0047SMichael J. Spencer #include <algorithm> 26b60a18deSMichael J. Spencer #include <limits> 27b60a18deSMichael J. Spencer #include <utility> 28b60a18deSMichael J. Spencer 29b60a18deSMichael J. Spencer using namespace llvm; 30b60a18deSMichael J. Spencer using namespace object; 31b60a18deSMichael J. Spencer 32b60a18deSMichael J. Spencer // Templates to choose Elf_Addr and Elf_Off depending on is64Bits. 33b60a18deSMichael J. Spencer namespace { 34b60a18deSMichael J. Spencer template<support::endianness target_endianness> 35b60a18deSMichael J. Spencer struct ELFDataTypeTypedefHelperCommon { 36b60a18deSMichael J. Spencer typedef support::detail::packed_endian_specific_integral 37b60a18deSMichael J. Spencer <uint16_t, target_endianness, support::aligned> Elf_Half; 38b60a18deSMichael J. Spencer typedef support::detail::packed_endian_specific_integral 39b60a18deSMichael J. Spencer <uint32_t, target_endianness, support::aligned> Elf_Word; 40b60a18deSMichael J. Spencer typedef support::detail::packed_endian_specific_integral 41b60a18deSMichael J. Spencer <int32_t, target_endianness, support::aligned> Elf_Sword; 42b60a18deSMichael J. Spencer typedef support::detail::packed_endian_specific_integral 43b60a18deSMichael J. Spencer <uint64_t, target_endianness, support::aligned> Elf_Xword; 44b60a18deSMichael J. Spencer typedef support::detail::packed_endian_specific_integral 45b60a18deSMichael J. Spencer <int64_t, target_endianness, support::aligned> Elf_Sxword; 46b60a18deSMichael J. Spencer }; 47b60a18deSMichael J. Spencer } 48b60a18deSMichael J. Spencer 49b60a18deSMichael J. Spencer namespace { 50b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 51b60a18deSMichael J. Spencer struct ELFDataTypeTypedefHelper; 52b60a18deSMichael J. Spencer 53b60a18deSMichael J. Spencer /// ELF 32bit types. 54b60a18deSMichael J. Spencer template<support::endianness target_endianness> 55b60a18deSMichael J. Spencer struct ELFDataTypeTypedefHelper<target_endianness, false> 56b60a18deSMichael J. Spencer : ELFDataTypeTypedefHelperCommon<target_endianness> { 57*c3c80f09SEli Bendersky typedef uint32_t value_type; 58b60a18deSMichael J. Spencer typedef support::detail::packed_endian_specific_integral 59*c3c80f09SEli Bendersky <value_type, target_endianness, support::aligned> Elf_Addr; 60b60a18deSMichael J. Spencer typedef support::detail::packed_endian_specific_integral 61*c3c80f09SEli Bendersky <value_type, target_endianness, support::aligned> Elf_Off; 62b60a18deSMichael J. Spencer }; 63b60a18deSMichael J. Spencer 64b60a18deSMichael J. Spencer /// ELF 64bit types. 65b60a18deSMichael J. Spencer template<support::endianness target_endianness> 66b60a18deSMichael J. Spencer struct ELFDataTypeTypedefHelper<target_endianness, true> 67b60a18deSMichael J. Spencer : ELFDataTypeTypedefHelperCommon<target_endianness>{ 68*c3c80f09SEli Bendersky typedef uint64_t value_type; 69b60a18deSMichael J. Spencer typedef support::detail::packed_endian_specific_integral 70*c3c80f09SEli Bendersky <value_type, target_endianness, support::aligned> Elf_Addr; 71b60a18deSMichael J. Spencer typedef support::detail::packed_endian_specific_integral 72*c3c80f09SEli Bendersky <value_type, target_endianness, support::aligned> Elf_Off; 73b60a18deSMichael J. Spencer }; 74b60a18deSMichael J. Spencer } 75b60a18deSMichael J. Spencer 76b60a18deSMichael J. Spencer // I really don't like doing this, but the alternative is copypasta. 77b60a18deSMichael J. Spencer #define LLVM_ELF_IMPORT_TYPES(target_endianness, is64Bits) \ 78b60a18deSMichael J. Spencer typedef typename \ 79b60a18deSMichael J. Spencer ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Addr Elf_Addr; \ 80b60a18deSMichael J. Spencer typedef typename \ 81b60a18deSMichael J. Spencer ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Off Elf_Off; \ 82b60a18deSMichael J. Spencer typedef typename \ 83b60a18deSMichael J. Spencer ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Half Elf_Half; \ 84b60a18deSMichael J. Spencer typedef typename \ 85b60a18deSMichael J. Spencer ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Word Elf_Word; \ 86b60a18deSMichael J. Spencer typedef typename \ 87b60a18deSMichael J. Spencer ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Sword Elf_Sword; \ 88b60a18deSMichael J. Spencer typedef typename \ 89b60a18deSMichael J. Spencer ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Xword Elf_Xword; \ 90b60a18deSMichael J. Spencer typedef typename \ 91b60a18deSMichael J. Spencer ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Sxword Elf_Sxword; 92b60a18deSMichael J. Spencer 93b60a18deSMichael J. Spencer // Section header. 94b60a18deSMichael J. Spencer namespace { 95b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 96b60a18deSMichael J. Spencer struct Elf_Shdr_Base; 97b60a18deSMichael J. Spencer 98b60a18deSMichael J. Spencer template<support::endianness target_endianness> 99b60a18deSMichael J. Spencer struct Elf_Shdr_Base<target_endianness, false> { 100b60a18deSMichael J. Spencer LLVM_ELF_IMPORT_TYPES(target_endianness, false) 101b60a18deSMichael J. Spencer Elf_Word sh_name; // Section name (index into string table) 102b60a18deSMichael J. Spencer Elf_Word sh_type; // Section type (SHT_*) 103b60a18deSMichael J. Spencer Elf_Word sh_flags; // Section flags (SHF_*) 104b60a18deSMichael J. Spencer Elf_Addr sh_addr; // Address where section is to be loaded 105b60a18deSMichael J. Spencer Elf_Off sh_offset; // File offset of section data, in bytes 106b60a18deSMichael J. Spencer Elf_Word sh_size; // Size of section, in bytes 107b60a18deSMichael J. Spencer Elf_Word sh_link; // Section type-specific header table index link 108b60a18deSMichael J. Spencer Elf_Word sh_info; // Section type-specific extra information 109b60a18deSMichael J. Spencer Elf_Word sh_addralign;// Section address alignment 110b60a18deSMichael J. Spencer Elf_Word sh_entsize; // Size of records contained within the section 111b60a18deSMichael J. Spencer }; 112b60a18deSMichael J. Spencer 113b60a18deSMichael J. Spencer template<support::endianness target_endianness> 114b60a18deSMichael J. Spencer struct Elf_Shdr_Base<target_endianness, true> { 115b60a18deSMichael J. Spencer LLVM_ELF_IMPORT_TYPES(target_endianness, true) 116b60a18deSMichael J. Spencer Elf_Word sh_name; // Section name (index into string table) 117b60a18deSMichael J. Spencer Elf_Word sh_type; // Section type (SHT_*) 118b60a18deSMichael J. Spencer Elf_Xword sh_flags; // Section flags (SHF_*) 119b60a18deSMichael J. Spencer Elf_Addr sh_addr; // Address where section is to be loaded 120b60a18deSMichael J. Spencer Elf_Off sh_offset; // File offset of section data, in bytes 121b60a18deSMichael J. Spencer Elf_Xword sh_size; // Size of section, in bytes 122b60a18deSMichael J. Spencer Elf_Word sh_link; // Section type-specific header table index link 123b60a18deSMichael J. Spencer Elf_Word sh_info; // Section type-specific extra information 124b60a18deSMichael J. Spencer Elf_Xword sh_addralign;// Section address alignment 125b60a18deSMichael J. Spencer Elf_Xword sh_entsize; // Size of records contained within the section 126b60a18deSMichael J. Spencer }; 127b60a18deSMichael J. Spencer 128b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 129b60a18deSMichael J. Spencer struct Elf_Shdr_Impl : Elf_Shdr_Base<target_endianness, is64Bits> { 130b60a18deSMichael J. Spencer using Elf_Shdr_Base<target_endianness, is64Bits>::sh_entsize; 131b60a18deSMichael J. Spencer using Elf_Shdr_Base<target_endianness, is64Bits>::sh_size; 132b60a18deSMichael J. Spencer 133b60a18deSMichael J. Spencer /// @brief Get the number of entities this section contains if it has any. 134b60a18deSMichael J. Spencer unsigned getEntityCount() const { 135b60a18deSMichael J. Spencer if (sh_entsize == 0) 136b60a18deSMichael J. Spencer return 0; 137b60a18deSMichael J. Spencer return sh_size / sh_entsize; 138b60a18deSMichael J. Spencer } 139b60a18deSMichael J. Spencer }; 140b60a18deSMichael J. Spencer } 141b60a18deSMichael J. Spencer 142b60a18deSMichael J. Spencer namespace { 143b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 144b60a18deSMichael J. Spencer struct Elf_Sym_Base; 145b60a18deSMichael J. Spencer 146b60a18deSMichael J. Spencer template<support::endianness target_endianness> 147b60a18deSMichael J. Spencer struct Elf_Sym_Base<target_endianness, false> { 148b60a18deSMichael J. Spencer LLVM_ELF_IMPORT_TYPES(target_endianness, false) 149b60a18deSMichael J. Spencer Elf_Word st_name; // Symbol name (index into string table) 150b60a18deSMichael J. Spencer Elf_Addr st_value; // Value or address associated with the symbol 151b60a18deSMichael J. Spencer Elf_Word st_size; // Size of the symbol 152b60a18deSMichael J. Spencer unsigned char st_info; // Symbol's type and binding attributes 153b60a18deSMichael J. Spencer unsigned char st_other; // Must be zero; reserved 154b60a18deSMichael J. Spencer Elf_Half st_shndx; // Which section (header table index) it's defined in 155b60a18deSMichael J. Spencer }; 156b60a18deSMichael J. Spencer 157b60a18deSMichael J. Spencer template<support::endianness target_endianness> 158b60a18deSMichael J. Spencer struct Elf_Sym_Base<target_endianness, true> { 159b60a18deSMichael J. Spencer LLVM_ELF_IMPORT_TYPES(target_endianness, true) 160b60a18deSMichael J. Spencer Elf_Word st_name; // Symbol name (index into string table) 161b60a18deSMichael J. Spencer unsigned char st_info; // Symbol's type and binding attributes 162b60a18deSMichael J. Spencer unsigned char st_other; // Must be zero; reserved 163b60a18deSMichael J. Spencer Elf_Half st_shndx; // Which section (header table index) it's defined in 164b60a18deSMichael J. Spencer Elf_Addr st_value; // Value or address associated with the symbol 165b60a18deSMichael J. Spencer Elf_Xword st_size; // Size of the symbol 166b60a18deSMichael J. Spencer }; 167b60a18deSMichael J. Spencer 168b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 169b60a18deSMichael J. Spencer struct Elf_Sym_Impl : Elf_Sym_Base<target_endianness, is64Bits> { 170b60a18deSMichael J. Spencer using Elf_Sym_Base<target_endianness, is64Bits>::st_info; 171b60a18deSMichael J. Spencer 172b60a18deSMichael J. Spencer // These accessors and mutators correspond to the ELF32_ST_BIND, 173b60a18deSMichael J. Spencer // ELF32_ST_TYPE, and ELF32_ST_INFO macros defined in the ELF specification: 174b60a18deSMichael J. Spencer unsigned char getBinding() const { return st_info >> 4; } 175b60a18deSMichael J. Spencer unsigned char getType() const { return st_info & 0x0f; } 176b60a18deSMichael J. Spencer void setBinding(unsigned char b) { setBindingAndType(b, getType()); } 177b60a18deSMichael J. Spencer void setType(unsigned char t) { setBindingAndType(getBinding(), t); } 178b60a18deSMichael J. Spencer void setBindingAndType(unsigned char b, unsigned char t) { 179b60a18deSMichael J. Spencer st_info = (b << 4) + (t & 0x0f); 180b60a18deSMichael J. Spencer } 181b60a18deSMichael J. Spencer }; 182b60a18deSMichael J. Spencer } 183b60a18deSMichael J. Spencer 184b60a18deSMichael J. Spencer namespace { 185022ecdf2SBenjamin Kramer template<support::endianness target_endianness, bool is64Bits, bool isRela> 186022ecdf2SBenjamin Kramer struct Elf_Rel_Base; 187022ecdf2SBenjamin Kramer 188022ecdf2SBenjamin Kramer template<support::endianness target_endianness> 189022ecdf2SBenjamin Kramer struct Elf_Rel_Base<target_endianness, false, false> { 190022ecdf2SBenjamin Kramer LLVM_ELF_IMPORT_TYPES(target_endianness, false) 191022ecdf2SBenjamin Kramer Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) 192022ecdf2SBenjamin Kramer Elf_Word r_info; // Symbol table index and type of relocation to apply 193022ecdf2SBenjamin Kramer }; 194022ecdf2SBenjamin Kramer 195022ecdf2SBenjamin Kramer template<support::endianness target_endianness> 196022ecdf2SBenjamin Kramer struct Elf_Rel_Base<target_endianness, true, false> { 197022ecdf2SBenjamin Kramer LLVM_ELF_IMPORT_TYPES(target_endianness, true) 198022ecdf2SBenjamin Kramer Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) 199022ecdf2SBenjamin Kramer Elf_Xword r_info; // Symbol table index and type of relocation to apply 200022ecdf2SBenjamin Kramer }; 201022ecdf2SBenjamin Kramer 202022ecdf2SBenjamin Kramer template<support::endianness target_endianness> 203022ecdf2SBenjamin Kramer struct Elf_Rel_Base<target_endianness, false, true> { 204022ecdf2SBenjamin Kramer LLVM_ELF_IMPORT_TYPES(target_endianness, false) 205022ecdf2SBenjamin Kramer Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) 206022ecdf2SBenjamin Kramer Elf_Word r_info; // Symbol table index and type of relocation to apply 207022ecdf2SBenjamin Kramer Elf_Sword r_addend; // Compute value for relocatable field by adding this 208022ecdf2SBenjamin Kramer }; 209022ecdf2SBenjamin Kramer 210022ecdf2SBenjamin Kramer template<support::endianness target_endianness> 211022ecdf2SBenjamin Kramer struct Elf_Rel_Base<target_endianness, true, true> { 212022ecdf2SBenjamin Kramer LLVM_ELF_IMPORT_TYPES(target_endianness, true) 213022ecdf2SBenjamin Kramer Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) 214022ecdf2SBenjamin Kramer Elf_Xword r_info; // Symbol table index and type of relocation to apply 215022ecdf2SBenjamin Kramer Elf_Sxword r_addend; // Compute value for relocatable field by adding this. 216022ecdf2SBenjamin Kramer }; 217022ecdf2SBenjamin Kramer 218022ecdf2SBenjamin Kramer template<support::endianness target_endianness, bool is64Bits, bool isRela> 219022ecdf2SBenjamin Kramer struct Elf_Rel_Impl; 220022ecdf2SBenjamin Kramer 221022ecdf2SBenjamin Kramer template<support::endianness target_endianness, bool isRela> 222022ecdf2SBenjamin Kramer struct Elf_Rel_Impl<target_endianness, true, isRela> 223022ecdf2SBenjamin Kramer : Elf_Rel_Base<target_endianness, true, isRela> { 224022ecdf2SBenjamin Kramer using Elf_Rel_Base<target_endianness, true, isRela>::r_info; 225022ecdf2SBenjamin Kramer LLVM_ELF_IMPORT_TYPES(target_endianness, true) 226022ecdf2SBenjamin Kramer 227022ecdf2SBenjamin Kramer // These accessors and mutators correspond to the ELF64_R_SYM, ELF64_R_TYPE, 228022ecdf2SBenjamin Kramer // and ELF64_R_INFO macros defined in the ELF specification: 229022ecdf2SBenjamin Kramer uint64_t getSymbol() const { return (r_info >> 32); } 230022ecdf2SBenjamin Kramer unsigned char getType() const { 231022ecdf2SBenjamin Kramer return (unsigned char) (r_info & 0xffffffffL); 232022ecdf2SBenjamin Kramer } 233022ecdf2SBenjamin Kramer void setSymbol(uint64_t s) { setSymbolAndType(s, getType()); } 234022ecdf2SBenjamin Kramer void setType(unsigned char t) { setSymbolAndType(getSymbol(), t); } 235022ecdf2SBenjamin Kramer void setSymbolAndType(uint64_t s, unsigned char t) { 236022ecdf2SBenjamin Kramer r_info = (s << 32) + (t&0xffffffffL); 237022ecdf2SBenjamin Kramer } 238022ecdf2SBenjamin Kramer }; 239022ecdf2SBenjamin Kramer 240022ecdf2SBenjamin Kramer template<support::endianness target_endianness, bool isRela> 241022ecdf2SBenjamin Kramer struct Elf_Rel_Impl<target_endianness, false, isRela> 242022ecdf2SBenjamin Kramer : Elf_Rel_Base<target_endianness, false, isRela> { 243022ecdf2SBenjamin Kramer using Elf_Rel_Base<target_endianness, false, isRela>::r_info; 244022ecdf2SBenjamin Kramer LLVM_ELF_IMPORT_TYPES(target_endianness, false) 245022ecdf2SBenjamin Kramer 246022ecdf2SBenjamin Kramer // These accessors and mutators correspond to the ELF32_R_SYM, ELF32_R_TYPE, 247022ecdf2SBenjamin Kramer // and ELF32_R_INFO macros defined in the ELF specification: 248022ecdf2SBenjamin Kramer uint32_t getSymbol() const { return (r_info >> 8); } 249022ecdf2SBenjamin Kramer unsigned char getType() const { return (unsigned char) (r_info & 0x0ff); } 250022ecdf2SBenjamin Kramer void setSymbol(uint32_t s) { setSymbolAndType(s, getType()); } 251022ecdf2SBenjamin Kramer void setType(unsigned char t) { setSymbolAndType(getSymbol(), t); } 252022ecdf2SBenjamin Kramer void setSymbolAndType(uint32_t s, unsigned char t) { 253022ecdf2SBenjamin Kramer r_info = (s << 8) + t; 254022ecdf2SBenjamin Kramer } 255022ecdf2SBenjamin Kramer }; 256022ecdf2SBenjamin Kramer 257022ecdf2SBenjamin Kramer } 258022ecdf2SBenjamin Kramer 259022ecdf2SBenjamin Kramer namespace { 260b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 261b60a18deSMichael J. Spencer class ELFObjectFile : public ObjectFile { 262b60a18deSMichael J. Spencer LLVM_ELF_IMPORT_TYPES(target_endianness, is64Bits) 263b60a18deSMichael J. Spencer 264b60a18deSMichael J. Spencer typedef Elf_Shdr_Impl<target_endianness, is64Bits> Elf_Shdr; 265b60a18deSMichael J. Spencer typedef Elf_Sym_Impl<target_endianness, is64Bits> Elf_Sym; 266022ecdf2SBenjamin Kramer typedef Elf_Rel_Impl<target_endianness, is64Bits, false> Elf_Rel; 267022ecdf2SBenjamin Kramer typedef Elf_Rel_Impl<target_endianness, is64Bits, true> Elf_Rela; 268b60a18deSMichael J. Spencer 269*c3c80f09SEli Bendersky protected: 270b60a18deSMichael J. Spencer struct Elf_Ehdr { 271b60a18deSMichael J. Spencer unsigned char e_ident[ELF::EI_NIDENT]; // ELF Identification bytes 272b60a18deSMichael J. Spencer Elf_Half e_type; // Type of file (see ET_*) 273b60a18deSMichael J. Spencer Elf_Half e_machine; // Required architecture for this file (see EM_*) 274b60a18deSMichael J. Spencer Elf_Word e_version; // Must be equal to 1 275b60a18deSMichael J. Spencer Elf_Addr e_entry; // Address to jump to in order to start program 276b60a18deSMichael J. Spencer Elf_Off e_phoff; // Program header table's file offset, in bytes 277b60a18deSMichael J. Spencer Elf_Off e_shoff; // Section header table's file offset, in bytes 278b60a18deSMichael J. Spencer Elf_Word e_flags; // Processor-specific flags 279b60a18deSMichael J. Spencer Elf_Half e_ehsize; // Size of ELF header, in bytes 280b60a18deSMichael J. Spencer Elf_Half e_phentsize;// Size of an entry in the program header table 281b60a18deSMichael J. Spencer Elf_Half e_phnum; // Number of entries in the program header table 282b60a18deSMichael J. Spencer Elf_Half e_shentsize;// Size of an entry in the section header table 283b60a18deSMichael J. Spencer Elf_Half e_shnum; // Number of entries in the section header table 284b60a18deSMichael J. Spencer Elf_Half e_shstrndx; // Section header table index of section name 285b60a18deSMichael J. Spencer // string table 286b60a18deSMichael J. Spencer bool checkMagic() const { 287b60a18deSMichael J. Spencer return (memcmp(e_ident, ELF::ElfMagic, strlen(ELF::ElfMagic))) == 0; 288b60a18deSMichael J. Spencer } 289b60a18deSMichael J. Spencer unsigned char getFileClass() const { return e_ident[ELF::EI_CLASS]; } 290b60a18deSMichael J. Spencer unsigned char getDataEncoding() const { return e_ident[ELF::EI_DATA]; } 291b60a18deSMichael J. Spencer }; 292*c3c80f09SEli Bendersky // This flag is used for classof, to distinguish ELFObjectFile from 293*c3c80f09SEli Bendersky // its subclass. If more subclasses will be created, this flag will 294*c3c80f09SEli Bendersky // have to become an enum. 295*c3c80f09SEli Bendersky bool isDyldELFObject; 296b60a18deSMichael J. Spencer 297*c3c80f09SEli Bendersky private: 298022ecdf2SBenjamin Kramer typedef SmallVector<const Elf_Shdr*, 1> Sections_t; 299022ecdf2SBenjamin Kramer typedef DenseMap<unsigned, unsigned> IndexMap_t; 300e5fd0047SMichael J. Spencer typedef DenseMap<const Elf_Shdr*, SmallVector<uint32_t, 1> > RelocMap_t; 301b60a18deSMichael J. Spencer 302b60a18deSMichael J. Spencer const Elf_Ehdr *Header; 303b60a18deSMichael J. Spencer const Elf_Shdr *SectionHeaderTable; 304b60a18deSMichael J. Spencer const Elf_Shdr *dot_shstrtab_sec; // Section header string table. 305b60a18deSMichael J. Spencer const Elf_Shdr *dot_strtab_sec; // Symbol header string table. 306022ecdf2SBenjamin Kramer Sections_t SymbolTableSections; 307022ecdf2SBenjamin Kramer IndexMap_t SymbolTableSectionsIndexMap; 308d3043965SNick Lewycky DenseMap<const Elf_Sym*, ELF::Elf64_Word> ExtendedSymbolTable; 309e5fd0047SMichael J. Spencer 310e5fd0047SMichael J. Spencer /// @brief Map sections to an array of relocation sections that reference 311e5fd0047SMichael J. Spencer /// them sorted by section index. 312e5fd0047SMichael J. Spencer RelocMap_t SectionRelocMap; 313e5fd0047SMichael J. Spencer 314e5fd0047SMichael J. Spencer /// @brief Get the relocation section that contains \a Rel. 315e5fd0047SMichael J. Spencer const Elf_Shdr *getRelSection(DataRefImpl Rel) const { 316e5fd0047SMichael J. Spencer return getSection(Rel.w.b); 317e5fd0047SMichael J. Spencer } 318b60a18deSMichael J. Spencer 319022ecdf2SBenjamin Kramer bool isRelocationHasAddend(DataRefImpl Rel) const; 320022ecdf2SBenjamin Kramer template<typename T> 321e5fd0047SMichael J. Spencer const T *getEntry(uint16_t Section, uint32_t Entry) const; 322e5fd0047SMichael J. Spencer template<typename T> 323e5fd0047SMichael J. Spencer const T *getEntry(const Elf_Shdr *Section, uint32_t Entry) const; 324b60a18deSMichael J. Spencer const Elf_Shdr *getSection(DataRefImpl index) const; 32543f01caeSNick Lewycky const Elf_Shdr *getSection(uint32_t index) const; 326022ecdf2SBenjamin Kramer const Elf_Rel *getRel(DataRefImpl Rel) const; 327022ecdf2SBenjamin Kramer const Elf_Rela *getRela(DataRefImpl Rela) const; 32843f01caeSNick Lewycky const char *getString(uint32_t section, uint32_t offset) const; 329b60a18deSMichael J. Spencer const char *getString(const Elf_Shdr *section, uint32_t offset) const; 330e5fd0047SMichael J. Spencer error_code getSymbolName(const Elf_Sym *Symb, StringRef &Res) const; 331b60a18deSMichael J. Spencer 332b60a18deSMichael J. Spencer protected: 333*c3c80f09SEli Bendersky const Elf_Sym *getSymbol(DataRefImpl Symb) const; // FIXME: Should be private? 334*c3c80f09SEli Bendersky void validateSymbol(DataRefImpl Symb) const; 335*c3c80f09SEli Bendersky 336*c3c80f09SEli Bendersky protected: 3371d6167fdSMichael J. Spencer virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const; 3381d6167fdSMichael J. Spencer virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const; 339cbe72fc9SDanil Malyshev virtual error_code getSymbolFileOffset(DataRefImpl Symb, uint64_t &Res) const; 3401d6167fdSMichael J. Spencer virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const; 3411d6167fdSMichael J. Spencer virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const; 3421d6167fdSMichael J. Spencer virtual error_code getSymbolNMTypeChar(DataRefImpl Symb, char &Res) const; 3431d6167fdSMichael J. Spencer virtual error_code isSymbolInternal(DataRefImpl Symb, bool &Res) const; 34475d1cf33SBenjamin Kramer virtual error_code isSymbolGlobal(DataRefImpl Symb, bool &Res) const; 34501759754SMichael J. Spencer virtual error_code isSymbolWeak(DataRefImpl Symb, bool &Res) const; 346d3946676SMichael J. Spencer virtual error_code getSymbolType(DataRefImpl Symb, SymbolRef::Type &Res) const; 34732173153SMichael J. Spencer virtual error_code isSymbolAbsolute(DataRefImpl Symb, bool &Res) const; 34832173153SMichael J. Spencer virtual error_code getSymbolSection(DataRefImpl Symb, 34932173153SMichael J. Spencer section_iterator &Res) const; 350b60a18deSMichael J. Spencer 3511d6167fdSMichael J. Spencer virtual error_code getSectionNext(DataRefImpl Sec, SectionRef &Res) const; 3521d6167fdSMichael J. Spencer virtual error_code getSectionName(DataRefImpl Sec, StringRef &Res) const; 3531d6167fdSMichael J. Spencer virtual error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const; 3541d6167fdSMichael J. Spencer virtual error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const; 3551d6167fdSMichael J. Spencer virtual error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const; 3567989460aSMichael J. Spencer virtual error_code getSectionAlignment(DataRefImpl Sec, uint64_t &Res) const; 3571d6167fdSMichael J. Spencer virtual error_code isSectionText(DataRefImpl Sec, bool &Res) const; 358800619f2SMichael J. Spencer virtual error_code isSectionData(DataRefImpl Sec, bool &Res) const; 359800619f2SMichael J. Spencer virtual error_code isSectionBSS(DataRefImpl Sec, bool &Res) const; 360f6f3e81cSBenjamin Kramer virtual error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, 361f6f3e81cSBenjamin Kramer bool &Result) const; 362e5fd0047SMichael J. Spencer virtual relocation_iterator getSectionRelBegin(DataRefImpl Sec) const; 363e5fd0047SMichael J. Spencer virtual relocation_iterator getSectionRelEnd(DataRefImpl Sec) const; 364b60a18deSMichael J. Spencer 365022ecdf2SBenjamin Kramer virtual error_code getRelocationNext(DataRefImpl Rel, 366022ecdf2SBenjamin Kramer RelocationRef &Res) const; 367022ecdf2SBenjamin Kramer virtual error_code getRelocationAddress(DataRefImpl Rel, 368022ecdf2SBenjamin Kramer uint64_t &Res) const; 369cbe72fc9SDanil Malyshev virtual error_code getRelocationOffset(DataRefImpl Rel, 370cbe72fc9SDanil Malyshev uint64_t &Res) const; 371022ecdf2SBenjamin Kramer virtual error_code getRelocationSymbol(DataRefImpl Rel, 372022ecdf2SBenjamin Kramer SymbolRef &Res) const; 373022ecdf2SBenjamin Kramer virtual error_code getRelocationType(DataRefImpl Rel, 3747be76590SOwen Anderson uint64_t &Res) const; 375e5fd0047SMichael J. Spencer virtual error_code getRelocationTypeName(DataRefImpl Rel, 376e5fd0047SMichael J. Spencer SmallVectorImpl<char> &Result) const; 377022ecdf2SBenjamin Kramer virtual error_code getRelocationAdditionalInfo(DataRefImpl Rel, 378022ecdf2SBenjamin Kramer int64_t &Res) const; 379e5fd0047SMichael J. Spencer virtual error_code getRelocationValueString(DataRefImpl Rel, 380e5fd0047SMichael J. Spencer SmallVectorImpl<char> &Result) const; 381022ecdf2SBenjamin Kramer 382b60a18deSMichael J. Spencer public: 383ec29b121SMichael J. Spencer ELFObjectFile(MemoryBuffer *Object, error_code &ec); 384b60a18deSMichael J. Spencer virtual symbol_iterator begin_symbols() const; 385b60a18deSMichael J. Spencer virtual symbol_iterator end_symbols() const; 386b60a18deSMichael J. Spencer virtual section_iterator begin_sections() const; 387b60a18deSMichael J. Spencer virtual section_iterator end_sections() const; 388b60a18deSMichael J. Spencer 389b60a18deSMichael J. Spencer virtual uint8_t getBytesInAddress() const; 390b60a18deSMichael J. Spencer virtual StringRef getFileFormatName() const; 391b60a18deSMichael J. Spencer virtual unsigned getArch() const; 3927adc4370SNick Lewycky 39343f01caeSNick Lewycky uint64_t getNumSections() const; 39443f01caeSNick Lewycky uint64_t getStringTableIndex() const; 395d3043965SNick Lewycky ELF::Elf64_Word getSymbolTableIndex(const Elf_Sym *symb) const; 39643f01caeSNick Lewycky const Elf_Shdr *getSection(const Elf_Sym *symb) const; 3974f91c2f2SMichael J. Spencer 398*c3c80f09SEli Bendersky // Methods for type inquiry through isa, cast, and dyn_cast 399*c3c80f09SEli Bendersky bool isDyldType() const { return isDyldELFObject; } 4004f91c2f2SMichael J. Spencer static inline bool classof(const Binary *v) { 401*c3c80f09SEli Bendersky return v->getType() == Binary::isELF; 4024f91c2f2SMichael J. Spencer } 4034f91c2f2SMichael J. Spencer static inline bool classof(const ELFObjectFile *v) { return true; } 404b60a18deSMichael J. Spencer }; 405b60a18deSMichael J. Spencer } // end namespace 406b60a18deSMichael J. Spencer 407b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 408b60a18deSMichael J. Spencer void ELFObjectFile<target_endianness, is64Bits> 409b60a18deSMichael J. Spencer ::validateSymbol(DataRefImpl Symb) const { 410b60a18deSMichael J. Spencer const Elf_Sym *symb = getSymbol(Symb); 4110324b672SMichael J. Spencer const Elf_Shdr *SymbolTableSection = SymbolTableSections[Symb.d.b]; 412b60a18deSMichael J. Spencer // FIXME: We really need to do proper error handling in the case of an invalid 413b60a18deSMichael J. Spencer // input file. Because we don't use exceptions, I think we'll just pass 414b60a18deSMichael J. Spencer // an error object around. 415b60a18deSMichael J. Spencer if (!( symb 416b60a18deSMichael J. Spencer && SymbolTableSection 417ec29b121SMichael J. Spencer && symb >= (const Elf_Sym*)(base() 418b60a18deSMichael J. Spencer + SymbolTableSection->sh_offset) 419ec29b121SMichael J. Spencer && symb < (const Elf_Sym*)(base() 420b60a18deSMichael J. Spencer + SymbolTableSection->sh_offset 421b60a18deSMichael J. Spencer + SymbolTableSection->sh_size))) 422b60a18deSMichael J. Spencer // FIXME: Proper error handling. 423b60a18deSMichael J. Spencer report_fatal_error("Symb must point to a valid symbol!"); 424b60a18deSMichael J. Spencer } 425b60a18deSMichael J. Spencer 426b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 4271d6167fdSMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits> 4281d6167fdSMichael J. Spencer ::getSymbolNext(DataRefImpl Symb, 4291d6167fdSMichael J. Spencer SymbolRef &Result) const { 430b60a18deSMichael J. Spencer validateSymbol(Symb); 4310324b672SMichael J. Spencer const Elf_Shdr *SymbolTableSection = SymbolTableSections[Symb.d.b]; 432b60a18deSMichael J. Spencer 4330324b672SMichael J. Spencer ++Symb.d.a; 434b60a18deSMichael J. Spencer // Check to see if we are at the end of this symbol table. 4350324b672SMichael J. Spencer if (Symb.d.a >= SymbolTableSection->getEntityCount()) { 436b60a18deSMichael J. Spencer // We are at the end. If there are other symbol tables, jump to them. 4370324b672SMichael J. Spencer ++Symb.d.b; 4380324b672SMichael J. Spencer Symb.d.a = 1; // The 0th symbol in ELF is fake. 439b60a18deSMichael J. Spencer // Otherwise return the terminator. 4400324b672SMichael J. Spencer if (Symb.d.b >= SymbolTableSections.size()) { 4410324b672SMichael J. Spencer Symb.d.a = std::numeric_limits<uint32_t>::max(); 4420324b672SMichael J. Spencer Symb.d.b = std::numeric_limits<uint32_t>::max(); 443b60a18deSMichael J. Spencer } 444b60a18deSMichael J. Spencer } 445b60a18deSMichael J. Spencer 4461d6167fdSMichael J. Spencer Result = SymbolRef(Symb, this); 4471d6167fdSMichael J. Spencer return object_error::success; 448b60a18deSMichael J. Spencer } 449b60a18deSMichael J. Spencer 450b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 4511d6167fdSMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits> 4521d6167fdSMichael J. Spencer ::getSymbolName(DataRefImpl Symb, 4531d6167fdSMichael J. Spencer StringRef &Result) const { 454b60a18deSMichael J. Spencer validateSymbol(Symb); 455b60a18deSMichael J. Spencer const Elf_Sym *symb = getSymbol(Symb); 456e5fd0047SMichael J. Spencer return getSymbolName(symb, Result); 457b60a18deSMichael J. Spencer } 458b60a18deSMichael J. Spencer 459b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 460d3043965SNick Lewycky ELF::Elf64_Word ELFObjectFile<target_endianness, is64Bits> 4617adc4370SNick Lewycky ::getSymbolTableIndex(const Elf_Sym *symb) const { 4627adc4370SNick Lewycky if (symb->st_shndx == ELF::SHN_XINDEX) 4637adc4370SNick Lewycky return ExtendedSymbolTable.lookup(symb); 4647adc4370SNick Lewycky return symb->st_shndx; 4657adc4370SNick Lewycky } 4667adc4370SNick Lewycky 4677adc4370SNick Lewycky template<support::endianness target_endianness, bool is64Bits> 46843f01caeSNick Lewycky const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Shdr * 46943f01caeSNick Lewycky ELFObjectFile<target_endianness, is64Bits> 47043f01caeSNick Lewycky ::getSection(const Elf_Sym *symb) const { 471d3043965SNick Lewycky if (symb->st_shndx == ELF::SHN_XINDEX) 47243f01caeSNick Lewycky return getSection(ExtendedSymbolTable.lookup(symb)); 47343f01caeSNick Lewycky if (symb->st_shndx >= ELF::SHN_LORESERVE) 47443f01caeSNick Lewycky return 0; 47543f01caeSNick Lewycky return getSection(symb->st_shndx); 47643f01caeSNick Lewycky } 47743f01caeSNick Lewycky 47843f01caeSNick Lewycky template<support::endianness target_endianness, bool is64Bits> 4791d6167fdSMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits> 480cbe72fc9SDanil Malyshev ::getSymbolFileOffset(DataRefImpl Symb, 481cbe72fc9SDanil Malyshev uint64_t &Result) const { 482cbe72fc9SDanil Malyshev validateSymbol(Symb); 483cbe72fc9SDanil Malyshev const Elf_Sym *symb = getSymbol(Symb); 484cbe72fc9SDanil Malyshev const Elf_Shdr *Section; 485cbe72fc9SDanil Malyshev switch (getSymbolTableIndex(symb)) { 486cbe72fc9SDanil Malyshev case ELF::SHN_COMMON: 487*c3c80f09SEli Bendersky // Unintialized symbols have no offset in the object file 488cbe72fc9SDanil Malyshev case ELF::SHN_UNDEF: 489cbe72fc9SDanil Malyshev Result = UnknownAddressOrSize; 490cbe72fc9SDanil Malyshev return object_error::success; 491cbe72fc9SDanil Malyshev case ELF::SHN_ABS: 492cbe72fc9SDanil Malyshev Result = symb->st_value; 493cbe72fc9SDanil Malyshev return object_error::success; 494cbe72fc9SDanil Malyshev default: Section = getSection(symb); 495cbe72fc9SDanil Malyshev } 496cbe72fc9SDanil Malyshev 497cbe72fc9SDanil Malyshev switch (symb->getType()) { 498cbe72fc9SDanil Malyshev case ELF::STT_SECTION: 499cbe72fc9SDanil Malyshev Result = Section ? Section->sh_addr : UnknownAddressOrSize; 500cbe72fc9SDanil Malyshev return object_error::success; 501cbe72fc9SDanil Malyshev case ELF::STT_FUNC: 502cbe72fc9SDanil Malyshev case ELF::STT_OBJECT: 503cbe72fc9SDanil Malyshev case ELF::STT_NOTYPE: 504cbe72fc9SDanil Malyshev Result = symb->st_value + 505*c3c80f09SEli Bendersky (Section ? Section->sh_offset : 0); 506cbe72fc9SDanil Malyshev return object_error::success; 507cbe72fc9SDanil Malyshev default: 508cbe72fc9SDanil Malyshev Result = UnknownAddressOrSize; 509cbe72fc9SDanil Malyshev return object_error::success; 510cbe72fc9SDanil Malyshev } 511cbe72fc9SDanil Malyshev } 512cbe72fc9SDanil Malyshev 513cbe72fc9SDanil Malyshev template<support::endianness target_endianness, bool is64Bits> 514cbe72fc9SDanil Malyshev error_code ELFObjectFile<target_endianness, is64Bits> 515cbe72fc9SDanil Malyshev ::getSymbolAddress(DataRefImpl Symb, 5162631f93fSDanil Malyshev uint64_t &Result) const { 5172631f93fSDanil Malyshev validateSymbol(Symb); 5182631f93fSDanil Malyshev const Elf_Sym *symb = getSymbol(Symb); 5192631f93fSDanil Malyshev const Elf_Shdr *Section; 5202631f93fSDanil Malyshev switch (getSymbolTableIndex(symb)) { 5212631f93fSDanil Malyshev case ELF::SHN_COMMON: 5222631f93fSDanil Malyshev case ELF::SHN_UNDEF: 5232631f93fSDanil Malyshev Result = UnknownAddressOrSize; 5242631f93fSDanil Malyshev return object_error::success; 5252631f93fSDanil Malyshev case ELF::SHN_ABS: 5262631f93fSDanil Malyshev Result = symb->st_value; 5272631f93fSDanil Malyshev return object_error::success; 5282631f93fSDanil Malyshev default: Section = getSection(symb); 5292631f93fSDanil Malyshev } 5302631f93fSDanil Malyshev 5312631f93fSDanil Malyshev switch (symb->getType()) { 5322631f93fSDanil Malyshev case ELF::STT_SECTION: 5332631f93fSDanil Malyshev Result = Section ? Section->sh_addr : UnknownAddressOrSize; 5342631f93fSDanil Malyshev return object_error::success; 5352631f93fSDanil Malyshev case ELF::STT_FUNC: 5362631f93fSDanil Malyshev case ELF::STT_OBJECT: 5372631f93fSDanil Malyshev case ELF::STT_NOTYPE: 538*c3c80f09SEli Bendersky Result = symb->st_value + (Section ? Section->sh_addr : 0); 5392631f93fSDanil Malyshev return object_error::success; 5402631f93fSDanil Malyshev default: 5412631f93fSDanil Malyshev Result = UnknownAddressOrSize; 5422631f93fSDanil Malyshev return object_error::success; 5432631f93fSDanil Malyshev } 5442631f93fSDanil Malyshev } 5452631f93fSDanil Malyshev 5462631f93fSDanil Malyshev template<support::endianness target_endianness, bool is64Bits> 5472631f93fSDanil Malyshev error_code ELFObjectFile<target_endianness, is64Bits> 5481d6167fdSMichael J. Spencer ::getSymbolSize(DataRefImpl Symb, 5491d6167fdSMichael J. Spencer uint64_t &Result) const { 550b60a18deSMichael J. Spencer validateSymbol(Symb); 551b60a18deSMichael J. Spencer const Elf_Sym *symb = getSymbol(Symb); 552b60a18deSMichael J. Spencer if (symb->st_size == 0) 5531d6167fdSMichael J. Spencer Result = UnknownAddressOrSize; 5541d6167fdSMichael J. Spencer Result = symb->st_size; 5551d6167fdSMichael J. Spencer return object_error::success; 556b60a18deSMichael J. Spencer } 557b60a18deSMichael J. Spencer 558b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 5591d6167fdSMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits> 5601d6167fdSMichael J. Spencer ::getSymbolNMTypeChar(DataRefImpl Symb, 5611d6167fdSMichael J. Spencer char &Result) const { 562b60a18deSMichael J. Spencer validateSymbol(Symb); 563b60a18deSMichael J. Spencer const Elf_Sym *symb = getSymbol(Symb); 56443f01caeSNick Lewycky const Elf_Shdr *Section = getSection(symb); 565b60a18deSMichael J. Spencer 566b60a18deSMichael J. Spencer char ret = '?'; 567b60a18deSMichael J. Spencer 568b60a18deSMichael J. Spencer if (Section) { 569b60a18deSMichael J. Spencer switch (Section->sh_type) { 570b60a18deSMichael J. Spencer case ELF::SHT_PROGBITS: 571b60a18deSMichael J. Spencer case ELF::SHT_DYNAMIC: 572b60a18deSMichael J. Spencer switch (Section->sh_flags) { 573b60a18deSMichael J. Spencer case (ELF::SHF_ALLOC | ELF::SHF_EXECINSTR): 574b60a18deSMichael J. Spencer ret = 't'; break; 575b60a18deSMichael J. Spencer case (ELF::SHF_ALLOC | ELF::SHF_WRITE): 576b60a18deSMichael J. Spencer ret = 'd'; break; 577b60a18deSMichael J. Spencer case ELF::SHF_ALLOC: 578b60a18deSMichael J. Spencer case (ELF::SHF_ALLOC | ELF::SHF_MERGE): 579b60a18deSMichael J. Spencer case (ELF::SHF_ALLOC | ELF::SHF_MERGE | ELF::SHF_STRINGS): 580b60a18deSMichael J. Spencer ret = 'r'; break; 581b60a18deSMichael J. Spencer } 582b60a18deSMichael J. Spencer break; 583b60a18deSMichael J. Spencer case ELF::SHT_NOBITS: ret = 'b'; 584b60a18deSMichael J. Spencer } 585b60a18deSMichael J. Spencer } 586b60a18deSMichael J. Spencer 58743f01caeSNick Lewycky switch (getSymbolTableIndex(symb)) { 588b60a18deSMichael J. Spencer case ELF::SHN_UNDEF: 589b60a18deSMichael J. Spencer if (ret == '?') 590b60a18deSMichael J. Spencer ret = 'U'; 591b60a18deSMichael J. Spencer break; 592b60a18deSMichael J. Spencer case ELF::SHN_ABS: ret = 'a'; break; 593b60a18deSMichael J. Spencer case ELF::SHN_COMMON: ret = 'c'; break; 594b60a18deSMichael J. Spencer } 595b60a18deSMichael J. Spencer 596b60a18deSMichael J. Spencer switch (symb->getBinding()) { 597b60a18deSMichael J. Spencer case ELF::STB_GLOBAL: ret = ::toupper(ret); break; 598b60a18deSMichael J. Spencer case ELF::STB_WEAK: 59943f01caeSNick Lewycky if (getSymbolTableIndex(symb) == ELF::SHN_UNDEF) 600b60a18deSMichael J. Spencer ret = 'w'; 601b60a18deSMichael J. Spencer else 602b60a18deSMichael J. Spencer if (symb->getType() == ELF::STT_OBJECT) 603b60a18deSMichael J. Spencer ret = 'V'; 604b60a18deSMichael J. Spencer else 605b60a18deSMichael J. Spencer ret = 'W'; 606b60a18deSMichael J. Spencer } 607b60a18deSMichael J. Spencer 6081d6167fdSMichael J. Spencer if (ret == '?' && symb->getType() == ELF::STT_SECTION) { 6091d6167fdSMichael J. Spencer StringRef name; 6101d6167fdSMichael J. Spencer if (error_code ec = getSymbolName(Symb, name)) 6111d6167fdSMichael J. Spencer return ec; 6121d6167fdSMichael J. Spencer Result = StringSwitch<char>(name) 613b60a18deSMichael J. Spencer .StartsWith(".debug", 'N') 614022ecdf2SBenjamin Kramer .StartsWith(".note", 'n') 615022ecdf2SBenjamin Kramer .Default('?'); 6161d6167fdSMichael J. Spencer return object_error::success; 6171d6167fdSMichael J. Spencer } 618b60a18deSMichael J. Spencer 6191d6167fdSMichael J. Spencer Result = ret; 6201d6167fdSMichael J. Spencer return object_error::success; 621b60a18deSMichael J. Spencer } 622b60a18deSMichael J. Spencer 623b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 6241d6167fdSMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits> 62575d1cf33SBenjamin Kramer ::getSymbolType(DataRefImpl Symb, 626d3946676SMichael J. Spencer SymbolRef::Type &Result) const { 62775d1cf33SBenjamin Kramer validateSymbol(Symb); 62875d1cf33SBenjamin Kramer const Elf_Sym *symb = getSymbol(Symb); 62975d1cf33SBenjamin Kramer 6307adc4370SNick Lewycky if (getSymbolTableIndex(symb) == ELF::SHN_UNDEF) { 63175d1cf33SBenjamin Kramer Result = SymbolRef::ST_External; 63275d1cf33SBenjamin Kramer return object_error::success; 63375d1cf33SBenjamin Kramer } 63475d1cf33SBenjamin Kramer 63575d1cf33SBenjamin Kramer switch (symb->getType()) { 6361d19f97eSMichael J. Spencer case ELF::STT_SECTION: 6371d19f97eSMichael J. Spencer Result = SymbolRef::ST_Debug; 6381d19f97eSMichael J. Spencer break; 6391d19f97eSMichael J. Spencer case ELF::STT_FILE: 6401d19f97eSMichael J. Spencer Result = SymbolRef::ST_File; 6411d19f97eSMichael J. Spencer break; 64275d1cf33SBenjamin Kramer case ELF::STT_FUNC: 64375d1cf33SBenjamin Kramer Result = SymbolRef::ST_Function; 64475d1cf33SBenjamin Kramer break; 64575d1cf33SBenjamin Kramer case ELF::STT_OBJECT: 64675d1cf33SBenjamin Kramer Result = SymbolRef::ST_Data; 64775d1cf33SBenjamin Kramer break; 64875d1cf33SBenjamin Kramer default: 64975d1cf33SBenjamin Kramer Result = SymbolRef::ST_Other; 65075d1cf33SBenjamin Kramer break; 65175d1cf33SBenjamin Kramer } 65275d1cf33SBenjamin Kramer return object_error::success; 65375d1cf33SBenjamin Kramer } 65475d1cf33SBenjamin Kramer 65575d1cf33SBenjamin Kramer template<support::endianness target_endianness, bool is64Bits> 65675d1cf33SBenjamin Kramer error_code ELFObjectFile<target_endianness, is64Bits> 65775d1cf33SBenjamin Kramer ::isSymbolGlobal(DataRefImpl Symb, 65875d1cf33SBenjamin Kramer bool &Result) const { 65975d1cf33SBenjamin Kramer validateSymbol(Symb); 66075d1cf33SBenjamin Kramer const Elf_Sym *symb = getSymbol(Symb); 66175d1cf33SBenjamin Kramer 66275d1cf33SBenjamin Kramer Result = symb->getBinding() == ELF::STB_GLOBAL; 66375d1cf33SBenjamin Kramer return object_error::success; 66475d1cf33SBenjamin Kramer } 66575d1cf33SBenjamin Kramer 66675d1cf33SBenjamin Kramer template<support::endianness target_endianness, bool is64Bits> 66775d1cf33SBenjamin Kramer error_code ELFObjectFile<target_endianness, is64Bits> 66801759754SMichael J. Spencer ::isSymbolWeak(DataRefImpl Symb, 66901759754SMichael J. Spencer bool &Result) const { 67001759754SMichael J. Spencer validateSymbol(Symb); 67101759754SMichael J. Spencer const Elf_Sym *symb = getSymbol(Symb); 67201759754SMichael J. Spencer 67301759754SMichael J. Spencer Result = symb->getBinding() == ELF::STB_WEAK; 67401759754SMichael J. Spencer return object_error::success; 67501759754SMichael J. Spencer } 67601759754SMichael J. Spencer 67701759754SMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 67801759754SMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits> 67932173153SMichael J. Spencer ::isSymbolAbsolute(DataRefImpl Symb, bool &Res) const { 68032173153SMichael J. Spencer validateSymbol(Symb); 68132173153SMichael J. Spencer const Elf_Sym *symb = getSymbol(Symb); 68232173153SMichael J. Spencer Res = symb->st_shndx == ELF::SHN_ABS; 68332173153SMichael J. Spencer return object_error::success; 68432173153SMichael J. Spencer } 68532173153SMichael J. Spencer 68632173153SMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 68732173153SMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits> 68832173153SMichael J. Spencer ::getSymbolSection(DataRefImpl Symb, 68932173153SMichael J. Spencer section_iterator &Res) const { 69032173153SMichael J. Spencer validateSymbol(Symb); 69132173153SMichael J. Spencer const Elf_Sym *symb = getSymbol(Symb); 69232173153SMichael J. Spencer const Elf_Shdr *sec = getSection(symb); 69332173153SMichael J. Spencer if (!sec) 69432173153SMichael J. Spencer Res = end_sections(); 69532173153SMichael J. Spencer else { 69632173153SMichael J. Spencer DataRefImpl Sec; 69732173153SMichael J. Spencer Sec.p = reinterpret_cast<intptr_t>(sec); 69832173153SMichael J. Spencer Res = section_iterator(SectionRef(Sec, this)); 69932173153SMichael J. Spencer } 70032173153SMichael J. Spencer return object_error::success; 70132173153SMichael J. Spencer } 70232173153SMichael J. Spencer 70332173153SMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 70432173153SMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits> 7051d6167fdSMichael J. Spencer ::isSymbolInternal(DataRefImpl Symb, 7061d6167fdSMichael J. Spencer bool &Result) const { 707b60a18deSMichael J. Spencer validateSymbol(Symb); 708b60a18deSMichael J. Spencer const Elf_Sym *symb = getSymbol(Symb); 709b60a18deSMichael J. Spencer 710b60a18deSMichael J. Spencer if ( symb->getType() == ELF::STT_FILE 711b60a18deSMichael J. Spencer || symb->getType() == ELF::STT_SECTION) 7121d6167fdSMichael J. Spencer Result = true; 7131d6167fdSMichael J. Spencer Result = false; 7141d6167fdSMichael J. Spencer return object_error::success; 715b60a18deSMichael J. Spencer } 716b60a18deSMichael J. Spencer 717b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 7181d6167fdSMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits> 7191d6167fdSMichael J. Spencer ::getSectionNext(DataRefImpl Sec, SectionRef &Result) const { 7200324b672SMichael J. Spencer const uint8_t *sec = reinterpret_cast<const uint8_t *>(Sec.p); 721b60a18deSMichael J. Spencer sec += Header->e_shentsize; 7220324b672SMichael J. Spencer Sec.p = reinterpret_cast<intptr_t>(sec); 7231d6167fdSMichael J. Spencer Result = SectionRef(Sec, this); 7241d6167fdSMichael J. Spencer return object_error::success; 725b60a18deSMichael J. Spencer } 726b60a18deSMichael J. Spencer 727b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 7281d6167fdSMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits> 7291d6167fdSMichael J. Spencer ::getSectionName(DataRefImpl Sec, 7301d6167fdSMichael J. Spencer StringRef &Result) const { 7310324b672SMichael J. Spencer const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); 7321d6167fdSMichael J. Spencer Result = StringRef(getString(dot_shstrtab_sec, sec->sh_name)); 7331d6167fdSMichael J. Spencer return object_error::success; 734b60a18deSMichael J. Spencer } 735b60a18deSMichael J. Spencer 736b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 7371d6167fdSMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits> 7381d6167fdSMichael J. Spencer ::getSectionAddress(DataRefImpl Sec, 7391d6167fdSMichael J. Spencer uint64_t &Result) const { 7400324b672SMichael J. Spencer const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); 7411d6167fdSMichael J. Spencer Result = sec->sh_addr; 7421d6167fdSMichael J. Spencer return object_error::success; 743b60a18deSMichael J. Spencer } 744b60a18deSMichael J. Spencer 745b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 7461d6167fdSMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits> 7471d6167fdSMichael J. Spencer ::getSectionSize(DataRefImpl Sec, 7481d6167fdSMichael J. Spencer uint64_t &Result) const { 7490324b672SMichael J. Spencer const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); 7501d6167fdSMichael J. Spencer Result = sec->sh_size; 7511d6167fdSMichael J. Spencer return object_error::success; 752b60a18deSMichael J. Spencer } 753b60a18deSMichael J. Spencer 754b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 7551d6167fdSMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits> 7561d6167fdSMichael J. Spencer ::getSectionContents(DataRefImpl Sec, 7571d6167fdSMichael J. Spencer StringRef &Result) const { 7580324b672SMichael J. Spencer const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); 7591d6167fdSMichael J. Spencer const char *start = (const char*)base() + sec->sh_offset; 7601d6167fdSMichael J. Spencer Result = StringRef(start, sec->sh_size); 7611d6167fdSMichael J. Spencer return object_error::success; 762b60a18deSMichael J. Spencer } 763b60a18deSMichael J. Spencer 764b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 7651d6167fdSMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits> 7667989460aSMichael J. Spencer ::getSectionAlignment(DataRefImpl Sec, 7677989460aSMichael J. Spencer uint64_t &Result) const { 7687989460aSMichael J. Spencer const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); 7697989460aSMichael J. Spencer Result = sec->sh_addralign; 7707989460aSMichael J. Spencer return object_error::success; 7717989460aSMichael J. Spencer } 7727989460aSMichael J. Spencer 7737989460aSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 7747989460aSMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits> 7751d6167fdSMichael J. Spencer ::isSectionText(DataRefImpl Sec, 7761d6167fdSMichael J. Spencer bool &Result) const { 7770324b672SMichael J. Spencer const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); 778b60a18deSMichael J. Spencer if (sec->sh_flags & ELF::SHF_EXECINSTR) 7791d6167fdSMichael J. Spencer Result = true; 7801d6167fdSMichael J. Spencer else 7811d6167fdSMichael J. Spencer Result = false; 7821d6167fdSMichael J. Spencer return object_error::success; 783b60a18deSMichael J. Spencer } 784b60a18deSMichael J. Spencer 785b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 786f6f3e81cSBenjamin Kramer error_code ELFObjectFile<target_endianness, is64Bits> 787800619f2SMichael J. Spencer ::isSectionData(DataRefImpl Sec, 788800619f2SMichael J. Spencer bool &Result) const { 789800619f2SMichael J. Spencer const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); 790800619f2SMichael J. Spencer if (sec->sh_flags & (ELF::SHF_ALLOC | ELF::SHF_WRITE) 791800619f2SMichael J. Spencer && sec->sh_type == ELF::SHT_PROGBITS) 792800619f2SMichael J. Spencer Result = true; 793800619f2SMichael J. Spencer else 794800619f2SMichael J. Spencer Result = false; 795800619f2SMichael J. Spencer return object_error::success; 796800619f2SMichael J. Spencer } 797800619f2SMichael J. Spencer 798800619f2SMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 799800619f2SMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits> 800800619f2SMichael J. Spencer ::isSectionBSS(DataRefImpl Sec, 801800619f2SMichael J. Spencer bool &Result) const { 802800619f2SMichael J. Spencer const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); 803800619f2SMichael J. Spencer if (sec->sh_flags & (ELF::SHF_ALLOC | ELF::SHF_WRITE) 804800619f2SMichael J. Spencer && sec->sh_type == ELF::SHT_NOBITS) 805800619f2SMichael J. Spencer Result = true; 806800619f2SMichael J. Spencer else 807800619f2SMichael J. Spencer Result = false; 808800619f2SMichael J. Spencer return object_error::success; 809800619f2SMichael J. Spencer } 810800619f2SMichael J. Spencer 811800619f2SMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 812800619f2SMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits> 813f6f3e81cSBenjamin Kramer ::sectionContainsSymbol(DataRefImpl Sec, 814f6f3e81cSBenjamin Kramer DataRefImpl Symb, 815f6f3e81cSBenjamin Kramer bool &Result) const { 816f6f3e81cSBenjamin Kramer // FIXME: Unimplemented. 817f6f3e81cSBenjamin Kramer Result = false; 818f6f3e81cSBenjamin Kramer return object_error::success; 819f6f3e81cSBenjamin Kramer } 820f6f3e81cSBenjamin Kramer 821e5fd0047SMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 822e5fd0047SMichael J. Spencer relocation_iterator ELFObjectFile<target_endianness, is64Bits> 823e5fd0047SMichael J. Spencer ::getSectionRelBegin(DataRefImpl Sec) const { 824e5fd0047SMichael J. Spencer DataRefImpl RelData; 825e5fd0047SMichael J. Spencer memset(&RelData, 0, sizeof(RelData)); 826e5fd0047SMichael J. Spencer const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); 827e5fd0047SMichael J. Spencer typename RelocMap_t::const_iterator ittr = SectionRelocMap.find(sec); 828e5fd0047SMichael J. Spencer if (sec != 0 && ittr != SectionRelocMap.end()) { 829834bd602SMichael J. Spencer RelData.w.a = getSection(ittr->second[0])->sh_info; 830e5fd0047SMichael J. Spencer RelData.w.b = ittr->second[0]; 831e5fd0047SMichael J. Spencer RelData.w.c = 0; 832e5fd0047SMichael J. Spencer } 833e5fd0047SMichael J. Spencer return relocation_iterator(RelocationRef(RelData, this)); 834e5fd0047SMichael J. Spencer } 835e5fd0047SMichael J. Spencer 836e5fd0047SMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 837e5fd0047SMichael J. Spencer relocation_iterator ELFObjectFile<target_endianness, is64Bits> 838e5fd0047SMichael J. Spencer ::getSectionRelEnd(DataRefImpl Sec) const { 839e5fd0047SMichael J. Spencer DataRefImpl RelData; 840e5fd0047SMichael J. Spencer memset(&RelData, 0, sizeof(RelData)); 841e5fd0047SMichael J. Spencer const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); 842e5fd0047SMichael J. Spencer typename RelocMap_t::const_iterator ittr = SectionRelocMap.find(sec); 843e5fd0047SMichael J. Spencer if (sec != 0 && ittr != SectionRelocMap.end()) { 844e5fd0047SMichael J. Spencer // Get the index of the last relocation section for this section. 845e5fd0047SMichael J. Spencer std::size_t relocsecindex = ittr->second[ittr->second.size() - 1]; 846e5fd0047SMichael J. Spencer const Elf_Shdr *relocsec = getSection(relocsecindex); 847834bd602SMichael J. Spencer RelData.w.a = relocsec->sh_info; 848e5fd0047SMichael J. Spencer RelData.w.b = relocsecindex; 849e5fd0047SMichael J. Spencer RelData.w.c = relocsec->sh_size / relocsec->sh_entsize; 850e5fd0047SMichael J. Spencer } 851e5fd0047SMichael J. Spencer return relocation_iterator(RelocationRef(RelData, this)); 852e5fd0047SMichael J. Spencer } 853e5fd0047SMichael J. Spencer 854022ecdf2SBenjamin Kramer // Relocations 855022ecdf2SBenjamin Kramer template<support::endianness target_endianness, bool is64Bits> 856022ecdf2SBenjamin Kramer error_code ELFObjectFile<target_endianness, is64Bits> 857022ecdf2SBenjamin Kramer ::getRelocationNext(DataRefImpl Rel, 858022ecdf2SBenjamin Kramer RelocationRef &Result) const { 859e5fd0047SMichael J. Spencer ++Rel.w.c; 860e5fd0047SMichael J. Spencer const Elf_Shdr *relocsec = getSection(Rel.w.b); 861e5fd0047SMichael J. Spencer if (Rel.w.c >= (relocsec->sh_size / relocsec->sh_entsize)) { 862e5fd0047SMichael J. Spencer // We have reached the end of the relocations for this section. See if there 863e5fd0047SMichael J. Spencer // is another relocation section. 864cfb6cc7bSMichael J. Spencer typename RelocMap_t::mapped_type relocseclist = 865e5fd0047SMichael J. Spencer SectionRelocMap.lookup(getSection(Rel.w.a)); 866022ecdf2SBenjamin Kramer 867e5fd0047SMichael J. Spencer // Do a binary search for the current reloc section index (which must be 868e5fd0047SMichael J. Spencer // present). Then get the next one. 869e5fd0047SMichael J. Spencer typename RelocMap_t::mapped_type::const_iterator loc = 870e5fd0047SMichael J. Spencer std::lower_bound(relocseclist.begin(), relocseclist.end(), Rel.w.b); 871e5fd0047SMichael J. Spencer ++loc; 872e5fd0047SMichael J. Spencer 873e5fd0047SMichael J. Spencer // If there is no next one, don't do anything. The ++Rel.w.c above sets Rel 874e5fd0047SMichael J. Spencer // to the end iterator. 875e5fd0047SMichael J. Spencer if (loc != relocseclist.end()) { 876e5fd0047SMichael J. Spencer Rel.w.b = *loc; 877e5fd0047SMichael J. Spencer Rel.w.a = 0; 878022ecdf2SBenjamin Kramer } 879022ecdf2SBenjamin Kramer } 880022ecdf2SBenjamin Kramer Result = RelocationRef(Rel, this); 881022ecdf2SBenjamin Kramer return object_error::success; 882022ecdf2SBenjamin Kramer } 883022ecdf2SBenjamin Kramer 884022ecdf2SBenjamin Kramer template<support::endianness target_endianness, bool is64Bits> 885022ecdf2SBenjamin Kramer error_code ELFObjectFile<target_endianness, is64Bits> 886022ecdf2SBenjamin Kramer ::getRelocationSymbol(DataRefImpl Rel, 887022ecdf2SBenjamin Kramer SymbolRef &Result) const { 888022ecdf2SBenjamin Kramer uint32_t symbolIdx; 889e5fd0047SMichael J. Spencer const Elf_Shdr *sec = getSection(Rel.w.b); 890022ecdf2SBenjamin Kramer switch (sec->sh_type) { 891022ecdf2SBenjamin Kramer default : 892022ecdf2SBenjamin Kramer report_fatal_error("Invalid section type in Rel!"); 893022ecdf2SBenjamin Kramer case ELF::SHT_REL : { 894022ecdf2SBenjamin Kramer symbolIdx = getRel(Rel)->getSymbol(); 895022ecdf2SBenjamin Kramer break; 896022ecdf2SBenjamin Kramer } 897022ecdf2SBenjamin Kramer case ELF::SHT_RELA : { 898022ecdf2SBenjamin Kramer symbolIdx = getRela(Rel)->getSymbol(); 899022ecdf2SBenjamin Kramer break; 900022ecdf2SBenjamin Kramer } 901022ecdf2SBenjamin Kramer } 902022ecdf2SBenjamin Kramer DataRefImpl SymbolData; 903022ecdf2SBenjamin Kramer IndexMap_t::const_iterator it = SymbolTableSectionsIndexMap.find(sec->sh_link); 904022ecdf2SBenjamin Kramer if (it == SymbolTableSectionsIndexMap.end()) 905022ecdf2SBenjamin Kramer report_fatal_error("Relocation symbol table not found!"); 906022ecdf2SBenjamin Kramer SymbolData.d.a = symbolIdx; 907022ecdf2SBenjamin Kramer SymbolData.d.b = it->second; 908022ecdf2SBenjamin Kramer Result = SymbolRef(SymbolData, this); 909022ecdf2SBenjamin Kramer return object_error::success; 910022ecdf2SBenjamin Kramer } 911022ecdf2SBenjamin Kramer 912022ecdf2SBenjamin Kramer template<support::endianness target_endianness, bool is64Bits> 913022ecdf2SBenjamin Kramer error_code ELFObjectFile<target_endianness, is64Bits> 914022ecdf2SBenjamin Kramer ::getRelocationAddress(DataRefImpl Rel, 915022ecdf2SBenjamin Kramer uint64_t &Result) const { 916022ecdf2SBenjamin Kramer uint64_t offset; 917e5fd0047SMichael J. Spencer const Elf_Shdr *sec = getSection(Rel.w.b); 918022ecdf2SBenjamin Kramer switch (sec->sh_type) { 919022ecdf2SBenjamin Kramer default : 920022ecdf2SBenjamin Kramer report_fatal_error("Invalid section type in Rel!"); 921022ecdf2SBenjamin Kramer case ELF::SHT_REL : { 922022ecdf2SBenjamin Kramer offset = getRel(Rel)->r_offset; 923022ecdf2SBenjamin Kramer break; 924022ecdf2SBenjamin Kramer } 925022ecdf2SBenjamin Kramer case ELF::SHT_RELA : { 926022ecdf2SBenjamin Kramer offset = getRela(Rel)->r_offset; 927022ecdf2SBenjamin Kramer break; 928022ecdf2SBenjamin Kramer } 929022ecdf2SBenjamin Kramer } 930022ecdf2SBenjamin Kramer 931e5fd0047SMichael J. Spencer Result = offset; 932022ecdf2SBenjamin Kramer return object_error::success; 933022ecdf2SBenjamin Kramer } 934022ecdf2SBenjamin Kramer 935022ecdf2SBenjamin Kramer template<support::endianness target_endianness, bool is64Bits> 936022ecdf2SBenjamin Kramer error_code ELFObjectFile<target_endianness, is64Bits> 937cbe72fc9SDanil Malyshev ::getRelocationOffset(DataRefImpl Rel, 938cbe72fc9SDanil Malyshev uint64_t &Result) const { 939cbe72fc9SDanil Malyshev uint64_t offset; 940cbe72fc9SDanil Malyshev const Elf_Shdr *sec = getSection(Rel.w.b); 941cbe72fc9SDanil Malyshev switch (sec->sh_type) { 942cbe72fc9SDanil Malyshev default : 943cbe72fc9SDanil Malyshev report_fatal_error("Invalid section type in Rel!"); 944cbe72fc9SDanil Malyshev case ELF::SHT_REL : { 945cbe72fc9SDanil Malyshev offset = getRel(Rel)->r_offset; 946cbe72fc9SDanil Malyshev break; 947cbe72fc9SDanil Malyshev } 948cbe72fc9SDanil Malyshev case ELF::SHT_RELA : { 949cbe72fc9SDanil Malyshev offset = getRela(Rel)->r_offset; 950cbe72fc9SDanil Malyshev break; 951cbe72fc9SDanil Malyshev } 952cbe72fc9SDanil Malyshev } 953cbe72fc9SDanil Malyshev 954cbe72fc9SDanil Malyshev Result = offset - sec->sh_addr; 955cbe72fc9SDanil Malyshev return object_error::success; 956cbe72fc9SDanil Malyshev } 957cbe72fc9SDanil Malyshev 958cbe72fc9SDanil Malyshev template<support::endianness target_endianness, bool is64Bits> 959cbe72fc9SDanil Malyshev error_code ELFObjectFile<target_endianness, is64Bits> 960022ecdf2SBenjamin Kramer ::getRelocationType(DataRefImpl Rel, 9617be76590SOwen Anderson uint64_t &Result) const { 962e5fd0047SMichael J. Spencer const Elf_Shdr *sec = getSection(Rel.w.b); 963022ecdf2SBenjamin Kramer switch (sec->sh_type) { 964022ecdf2SBenjamin Kramer default : 965022ecdf2SBenjamin Kramer report_fatal_error("Invalid section type in Rel!"); 966022ecdf2SBenjamin Kramer case ELF::SHT_REL : { 967022ecdf2SBenjamin Kramer Result = getRel(Rel)->getType(); 968022ecdf2SBenjamin Kramer break; 969022ecdf2SBenjamin Kramer } 970022ecdf2SBenjamin Kramer case ELF::SHT_RELA : { 971022ecdf2SBenjamin Kramer Result = getRela(Rel)->getType(); 972022ecdf2SBenjamin Kramer break; 973022ecdf2SBenjamin Kramer } 974022ecdf2SBenjamin Kramer } 975022ecdf2SBenjamin Kramer return object_error::success; 976022ecdf2SBenjamin Kramer } 977022ecdf2SBenjamin Kramer 978e5fd0047SMichael J. Spencer #define LLVM_ELF_SWITCH_RELOC_TYPE_NAME(enum) \ 979e5fd0047SMichael J. Spencer case ELF::enum: res = #enum; break; 980e5fd0047SMichael J. Spencer 981e5fd0047SMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 982e5fd0047SMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits> 983e5fd0047SMichael J. Spencer ::getRelocationTypeName(DataRefImpl Rel, 984e5fd0047SMichael J. Spencer SmallVectorImpl<char> &Result) const { 985e5fd0047SMichael J. Spencer const Elf_Shdr *sec = getSection(Rel.w.b); 986e5fd0047SMichael J. Spencer uint8_t type; 987e5fd0047SMichael J. Spencer StringRef res; 988e5fd0047SMichael J. Spencer switch (sec->sh_type) { 989e5fd0047SMichael J. Spencer default : 990e5fd0047SMichael J. Spencer return object_error::parse_failed; 991e5fd0047SMichael J. Spencer case ELF::SHT_REL : { 992e5fd0047SMichael J. Spencer type = getRel(Rel)->getType(); 993e5fd0047SMichael J. Spencer break; 994e5fd0047SMichael J. Spencer } 995e5fd0047SMichael J. Spencer case ELF::SHT_RELA : { 996e5fd0047SMichael J. Spencer type = getRela(Rel)->getType(); 997e5fd0047SMichael J. Spencer break; 998e5fd0047SMichael J. Spencer } 999e5fd0047SMichael J. Spencer } 1000e5fd0047SMichael J. Spencer switch (Header->e_machine) { 1001e5fd0047SMichael J. Spencer case ELF::EM_X86_64: 1002e5fd0047SMichael J. Spencer switch (type) { 1003e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_NONE); 1004e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_64); 1005e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_PC32); 1006e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOT32); 1007e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_PLT32); 1008e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_COPY); 1009e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GLOB_DAT); 1010e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_JUMP_SLOT); 1011e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_RELATIVE); 1012e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTPCREL); 1013e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_32); 1014e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_32S); 1015e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_16); 1016e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_PC16); 1017e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_8); 1018e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_PC8); 1019e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_DTPMOD64); 1020e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_DTPOFF64); 1021e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_TPOFF64); 1022e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_TLSGD); 1023e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_TLSLD); 1024e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_DTPOFF32); 1025e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTTPOFF); 1026e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_TPOFF32); 1027e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_PC64); 1028e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTOFF64); 1029e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTPC32); 1030e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_SIZE32); 1031e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_SIZE64); 1032e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTPC32_TLSDESC); 1033e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_TLSDESC_CALL); 1034e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_TLSDESC); 1035e5fd0047SMichael J. Spencer default: 1036e5fd0047SMichael J. Spencer res = "Unknown"; 1037e5fd0047SMichael J. Spencer } 1038e5fd0047SMichael J. Spencer break; 1039e5fd0047SMichael J. Spencer case ELF::EM_386: 1040e5fd0047SMichael J. Spencer switch (type) { 1041e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_NONE); 1042e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_32); 1043e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_PC32); 1044e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_GOT32); 1045e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_PLT32); 1046e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_COPY); 1047e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_GLOB_DAT); 1048e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_JUMP_SLOT); 1049e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_RELATIVE); 1050e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_GOTOFF); 1051e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_GOTPC); 1052e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_32PLT); 1053e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_TPOFF); 1054e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_IE); 1055e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_GOTIE); 1056e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LE); 1057e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_GD); 1058e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LDM); 1059e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_16); 1060e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_PC16); 1061e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_8); 1062e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_PC8); 1063e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_GD_32); 1064e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_GD_PUSH); 1065e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_GD_CALL); 1066e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_GD_POP); 1067e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LDM_32); 1068e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LDM_PUSH); 1069e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LDM_CALL); 1070e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LDM_POP); 1071e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LDO_32); 1072e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_IE_32); 1073e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LE_32); 1074e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_DTPMOD32); 1075e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_DTPOFF32); 1076e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_TPOFF32); 1077e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_GOTDESC); 1078e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_DESC_CALL); 1079e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_DESC); 1080e5fd0047SMichael J. Spencer LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_IRELATIVE); 1081e5fd0047SMichael J. Spencer default: 1082e5fd0047SMichael J. Spencer res = "Unknown"; 1083e5fd0047SMichael J. Spencer } 1084e5fd0047SMichael J. Spencer break; 1085e5fd0047SMichael J. Spencer default: 1086e5fd0047SMichael J. Spencer res = "Unknown"; 1087e5fd0047SMichael J. Spencer } 1088e5fd0047SMichael J. Spencer Result.append(res.begin(), res.end()); 1089e5fd0047SMichael J. Spencer return object_error::success; 1090e5fd0047SMichael J. Spencer } 1091e5fd0047SMichael J. Spencer 1092e5fd0047SMichael J. Spencer #undef LLVM_ELF_SWITCH_RELOC_TYPE_NAME 1093e5fd0047SMichael J. Spencer 1094022ecdf2SBenjamin Kramer template<support::endianness target_endianness, bool is64Bits> 1095022ecdf2SBenjamin Kramer error_code ELFObjectFile<target_endianness, is64Bits> 1096022ecdf2SBenjamin Kramer ::getRelocationAdditionalInfo(DataRefImpl Rel, 1097022ecdf2SBenjamin Kramer int64_t &Result) const { 1098e5fd0047SMichael J. Spencer const Elf_Shdr *sec = getSection(Rel.w.b); 1099022ecdf2SBenjamin Kramer switch (sec->sh_type) { 1100022ecdf2SBenjamin Kramer default : 1101022ecdf2SBenjamin Kramer report_fatal_error("Invalid section type in Rel!"); 1102022ecdf2SBenjamin Kramer case ELF::SHT_REL : { 1103022ecdf2SBenjamin Kramer Result = 0; 1104022ecdf2SBenjamin Kramer return object_error::success; 1105022ecdf2SBenjamin Kramer } 1106022ecdf2SBenjamin Kramer case ELF::SHT_RELA : { 1107022ecdf2SBenjamin Kramer Result = getRela(Rel)->r_addend; 1108022ecdf2SBenjamin Kramer return object_error::success; 1109022ecdf2SBenjamin Kramer } 1110022ecdf2SBenjamin Kramer } 1111022ecdf2SBenjamin Kramer } 1112022ecdf2SBenjamin Kramer 1113e5fd0047SMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 1114e5fd0047SMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits> 1115e5fd0047SMichael J. Spencer ::getRelocationValueString(DataRefImpl Rel, 1116e5fd0047SMichael J. Spencer SmallVectorImpl<char> &Result) const { 1117e5fd0047SMichael J. Spencer const Elf_Shdr *sec = getSection(Rel.w.b); 1118e5fd0047SMichael J. Spencer uint8_t type; 1119e5fd0047SMichael J. Spencer StringRef res; 1120e5fd0047SMichael J. Spencer int64_t addend = 0; 1121e5fd0047SMichael J. Spencer uint16_t symbol_index = 0; 1122e5fd0047SMichael J. Spencer switch (sec->sh_type) { 1123e5fd0047SMichael J. Spencer default : 1124e5fd0047SMichael J. Spencer return object_error::parse_failed; 1125e5fd0047SMichael J. Spencer case ELF::SHT_REL : { 1126e5fd0047SMichael J. Spencer type = getRel(Rel)->getType(); 1127e5fd0047SMichael J. Spencer symbol_index = getRel(Rel)->getSymbol(); 1128e5fd0047SMichael J. Spencer // TODO: Read implicit addend from section data. 1129e5fd0047SMichael J. Spencer break; 1130e5fd0047SMichael J. Spencer } 1131e5fd0047SMichael J. Spencer case ELF::SHT_RELA : { 1132e5fd0047SMichael J. Spencer type = getRela(Rel)->getType(); 1133e5fd0047SMichael J. Spencer symbol_index = getRela(Rel)->getSymbol(); 1134e5fd0047SMichael J. Spencer addend = getRela(Rel)->r_addend; 1135e5fd0047SMichael J. Spencer break; 1136e5fd0047SMichael J. Spencer } 1137e5fd0047SMichael J. Spencer } 1138e5fd0047SMichael J. Spencer const Elf_Sym *symb = getEntry<Elf_Sym>(sec->sh_link, symbol_index); 1139e5fd0047SMichael J. Spencer StringRef symname; 1140e5fd0047SMichael J. Spencer if (error_code ec = getSymbolName(symb, symname)) 1141e5fd0047SMichael J. Spencer return ec; 1142e5fd0047SMichael J. Spencer switch (Header->e_machine) { 1143e5fd0047SMichael J. Spencer case ELF::EM_X86_64: 1144e5fd0047SMichael J. Spencer switch (type) { 1145e5fd0047SMichael J. Spencer case ELF::R_X86_64_32S: 1146e5fd0047SMichael J. Spencer res = symname; 1147e5fd0047SMichael J. Spencer break; 1148e5fd0047SMichael J. Spencer case ELF::R_X86_64_PC32: { 1149e5fd0047SMichael J. Spencer std::string fmtbuf; 1150e5fd0047SMichael J. Spencer raw_string_ostream fmt(fmtbuf); 1151e5fd0047SMichael J. Spencer fmt << symname << (addend < 0 ? "" : "+") << addend << "-P"; 1152e5fd0047SMichael J. Spencer fmt.flush(); 1153e5fd0047SMichael J. Spencer Result.append(fmtbuf.begin(), fmtbuf.end()); 1154e5fd0047SMichael J. Spencer } 1155e5fd0047SMichael J. Spencer break; 1156e5fd0047SMichael J. Spencer default: 1157e5fd0047SMichael J. Spencer res = "Unknown"; 1158e5fd0047SMichael J. Spencer } 1159e5fd0047SMichael J. Spencer break; 1160e5fd0047SMichael J. Spencer default: 1161e5fd0047SMichael J. Spencer res = "Unknown"; 1162e5fd0047SMichael J. Spencer } 1163e5fd0047SMichael J. Spencer if (Result.empty()) 1164e5fd0047SMichael J. Spencer Result.append(res.begin(), res.end()); 1165e5fd0047SMichael J. Spencer return object_error::success; 1166e5fd0047SMichael J. Spencer } 1167022ecdf2SBenjamin Kramer 1168f6f3e81cSBenjamin Kramer template<support::endianness target_endianness, bool is64Bits> 1169ec29b121SMichael J. Spencer ELFObjectFile<target_endianness, is64Bits>::ELFObjectFile(MemoryBuffer *Object 1170ec29b121SMichael J. Spencer , error_code &ec) 1171ec29b121SMichael J. Spencer : ObjectFile(Binary::isELF, Object, ec) 1172*c3c80f09SEli Bendersky , isDyldELFObject(false) 1173b60a18deSMichael J. Spencer , SectionHeaderTable(0) 1174b60a18deSMichael J. Spencer , dot_shstrtab_sec(0) 1175b60a18deSMichael J. Spencer , dot_strtab_sec(0) { 1176ec29b121SMichael J. Spencer Header = reinterpret_cast<const Elf_Ehdr *>(base()); 1177b60a18deSMichael J. Spencer 1178b60a18deSMichael J. Spencer if (Header->e_shoff == 0) 1179b60a18deSMichael J. Spencer return; 1180b60a18deSMichael J. Spencer 1181b60a18deSMichael J. Spencer SectionHeaderTable = 1182ec29b121SMichael J. Spencer reinterpret_cast<const Elf_Shdr *>(base() + Header->e_shoff); 118343f01caeSNick Lewycky uint64_t SectionTableSize = getNumSections() * Header->e_shentsize; 1184*c3c80f09SEli Bendersky 1185*c3c80f09SEli Bendersky if ((const uint8_t *)SectionHeaderTable + SectionTableSize 1186*c3c80f09SEli Bendersky > base() + Data->getBufferSize()) { 1187b60a18deSMichael J. Spencer // FIXME: Proper error handling. 1188b60a18deSMichael J. Spencer report_fatal_error("Section table goes past end of file!"); 1189*c3c80f09SEli Bendersky } 1190b60a18deSMichael J. Spencer 119135a90c4bSNick Lewycky 11927adc4370SNick Lewycky // To find the symbol tables we walk the section table to find SHT_SYMTAB. 11937adc4370SNick Lewycky const Elf_Shdr* SymbolTableSectionHeaderIndex = 0; 1194e5fd0047SMichael J. Spencer const Elf_Shdr* sh = reinterpret_cast<const Elf_Shdr*>(SectionHeaderTable); 119543f01caeSNick Lewycky for (uint64_t i = 0, e = getNumSections(); i != e; ++i) { 11967adc4370SNick Lewycky if (sh->sh_type == ELF::SHT_SYMTAB_SHNDX) { 11977adc4370SNick Lewycky if (SymbolTableSectionHeaderIndex) 11987adc4370SNick Lewycky // FIXME: Proper error handling. 11997adc4370SNick Lewycky report_fatal_error("More than one .symtab_shndx!"); 12007adc4370SNick Lewycky SymbolTableSectionHeaderIndex = sh; 12017adc4370SNick Lewycky } 1202b60a18deSMichael J. Spencer if (sh->sh_type == ELF::SHT_SYMTAB) { 1203022ecdf2SBenjamin Kramer SymbolTableSectionsIndexMap[i] = SymbolTableSections.size(); 1204b60a18deSMichael J. Spencer SymbolTableSections.push_back(sh); 1205b60a18deSMichael J. Spencer } 1206022ecdf2SBenjamin Kramer if (sh->sh_type == ELF::SHT_REL || sh->sh_type == ELF::SHT_RELA) { 1207834bd602SMichael J. Spencer SectionRelocMap[getSection(sh->sh_info)].push_back(i); 1208022ecdf2SBenjamin Kramer } 1209022ecdf2SBenjamin Kramer ++sh; 1210b60a18deSMichael J. Spencer } 1211b60a18deSMichael J. Spencer 1212e5fd0047SMichael J. Spencer // Sort section relocation lists by index. 1213e5fd0047SMichael J. Spencer for (typename RelocMap_t::iterator i = SectionRelocMap.begin(), 1214e5fd0047SMichael J. Spencer e = SectionRelocMap.end(); i != e; ++i) { 1215e5fd0047SMichael J. Spencer std::sort(i->second.begin(), i->second.end()); 1216e5fd0047SMichael J. Spencer } 1217e5fd0047SMichael J. Spencer 1218b60a18deSMichael J. Spencer // Get string table sections. 121943f01caeSNick Lewycky dot_shstrtab_sec = getSection(getStringTableIndex()); 1220b60a18deSMichael J. Spencer if (dot_shstrtab_sec) { 1221b60a18deSMichael J. Spencer // Verify that the last byte in the string table in a null. 1222ec29b121SMichael J. Spencer if (((const char*)base() + dot_shstrtab_sec->sh_offset) 1223b60a18deSMichael J. Spencer [dot_shstrtab_sec->sh_size - 1] != 0) 1224b60a18deSMichael J. Spencer // FIXME: Proper error handling. 1225b60a18deSMichael J. Spencer report_fatal_error("String table must end with a null terminator!"); 1226b60a18deSMichael J. Spencer } 1227b60a18deSMichael J. Spencer 1228b60a18deSMichael J. Spencer // Merge this into the above loop. 1229b60a18deSMichael J. Spencer for (const char *i = reinterpret_cast<const char *>(SectionHeaderTable), 123043f01caeSNick Lewycky *e = i + getNumSections() * Header->e_shentsize; 1231b60a18deSMichael J. Spencer i != e; i += Header->e_shentsize) { 1232b60a18deSMichael J. Spencer const Elf_Shdr *sh = reinterpret_cast<const Elf_Shdr*>(i); 1233b60a18deSMichael J. Spencer if (sh->sh_type == ELF::SHT_STRTAB) { 1234b60a18deSMichael J. Spencer StringRef SectionName(getString(dot_shstrtab_sec, sh->sh_name)); 1235b60a18deSMichael J. Spencer if (SectionName == ".strtab") { 1236b60a18deSMichael J. Spencer if (dot_strtab_sec != 0) 1237b60a18deSMichael J. Spencer // FIXME: Proper error handling. 1238b60a18deSMichael J. Spencer report_fatal_error("Already found section named .strtab!"); 1239b60a18deSMichael J. Spencer dot_strtab_sec = sh; 1240ec29b121SMichael J. Spencer const char *dot_strtab = (const char*)base() + sh->sh_offset; 1241b60a18deSMichael J. Spencer if (dot_strtab[sh->sh_size - 1] != 0) 1242b60a18deSMichael J. Spencer // FIXME: Proper error handling. 1243b60a18deSMichael J. Spencer report_fatal_error("String table must end with a null terminator!"); 1244b60a18deSMichael J. Spencer } 1245b60a18deSMichael J. Spencer } 1246b60a18deSMichael J. Spencer } 12477adc4370SNick Lewycky 12487adc4370SNick Lewycky // Build symbol name side-mapping if there is one. 12497adc4370SNick Lewycky if (SymbolTableSectionHeaderIndex) { 12507adc4370SNick Lewycky const Elf_Word *ShndxTable = reinterpret_cast<const Elf_Word*>(base() + 12517adc4370SNick Lewycky SymbolTableSectionHeaderIndex->sh_offset); 12527adc4370SNick Lewycky error_code ec; 12537adc4370SNick Lewycky for (symbol_iterator si = begin_symbols(), 12547adc4370SNick Lewycky se = end_symbols(); si != se; si.increment(ec)) { 12557adc4370SNick Lewycky if (ec) 12567adc4370SNick Lewycky report_fatal_error("Fewer extended symbol table entries than symbols!"); 12577adc4370SNick Lewycky if (*ShndxTable != ELF::SHN_UNDEF) 12587adc4370SNick Lewycky ExtendedSymbolTable[getSymbol(si->getRawDataRefImpl())] = *ShndxTable; 12597adc4370SNick Lewycky ++ShndxTable; 12607adc4370SNick Lewycky } 12617adc4370SNick Lewycky } 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 ::begin_symbols() const { 12670324b672SMichael J. Spencer DataRefImpl SymbolData; 1268b60a18deSMichael J. Spencer memset(&SymbolData, 0, sizeof(SymbolData)); 1269b60a18deSMichael J. Spencer if (SymbolTableSections.size() == 0) { 12700324b672SMichael J. Spencer SymbolData.d.a = std::numeric_limits<uint32_t>::max(); 12710324b672SMichael J. Spencer SymbolData.d.b = std::numeric_limits<uint32_t>::max(); 1272b60a18deSMichael J. Spencer } else { 12730324b672SMichael J. Spencer SymbolData.d.a = 1; // The 0th symbol in ELF is fake. 12740324b672SMichael J. Spencer SymbolData.d.b = 0; 1275b60a18deSMichael J. Spencer } 12760324b672SMichael J. Spencer return symbol_iterator(SymbolRef(SymbolData, this)); 1277b60a18deSMichael J. Spencer } 1278b60a18deSMichael J. Spencer 1279b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 1280e5fd0047SMichael J. Spencer symbol_iterator ELFObjectFile<target_endianness, is64Bits> 1281b60a18deSMichael J. Spencer ::end_symbols() const { 12820324b672SMichael J. Spencer DataRefImpl SymbolData; 1283b60a18deSMichael J. Spencer memset(&SymbolData, 0, sizeof(SymbolData)); 12840324b672SMichael J. Spencer SymbolData.d.a = std::numeric_limits<uint32_t>::max(); 12850324b672SMichael J. Spencer SymbolData.d.b = std::numeric_limits<uint32_t>::max(); 12860324b672SMichael J. Spencer return symbol_iterator(SymbolRef(SymbolData, this)); 1287b60a18deSMichael J. Spencer } 1288b60a18deSMichael J. Spencer 1289b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 1290e5fd0047SMichael J. Spencer section_iterator ELFObjectFile<target_endianness, is64Bits> 1291b60a18deSMichael J. Spencer ::begin_sections() const { 12920324b672SMichael J. Spencer DataRefImpl ret; 1293ee066fc4SEric Christopher memset(&ret, 0, sizeof(DataRefImpl)); 1294ec29b121SMichael J. Spencer ret.p = reinterpret_cast<intptr_t>(base() + Header->e_shoff); 12950324b672SMichael J. Spencer return section_iterator(SectionRef(ret, this)); 1296b60a18deSMichael J. Spencer } 1297b60a18deSMichael J. Spencer 1298b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 1299e5fd0047SMichael J. Spencer section_iterator ELFObjectFile<target_endianness, is64Bits> 1300b60a18deSMichael J. Spencer ::end_sections() const { 13010324b672SMichael J. Spencer DataRefImpl ret; 1302ee066fc4SEric Christopher memset(&ret, 0, sizeof(DataRefImpl)); 1303ec29b121SMichael J. Spencer ret.p = reinterpret_cast<intptr_t>(base() 1304b60a18deSMichael J. Spencer + Header->e_shoff 130543f01caeSNick Lewycky + (Header->e_shentsize*getNumSections())); 13060324b672SMichael J. Spencer return section_iterator(SectionRef(ret, this)); 1307b60a18deSMichael J. Spencer } 1308b60a18deSMichael J. Spencer 1309b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 1310b60a18deSMichael J. Spencer uint8_t ELFObjectFile<target_endianness, is64Bits>::getBytesInAddress() const { 13110324b672SMichael J. Spencer return is64Bits ? 8 : 4; 1312b60a18deSMichael J. Spencer } 1313b60a18deSMichael J. Spencer 1314b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 1315b60a18deSMichael J. Spencer StringRef ELFObjectFile<target_endianness, is64Bits> 1316b60a18deSMichael J. Spencer ::getFileFormatName() const { 1317b60a18deSMichael J. Spencer switch(Header->e_ident[ELF::EI_CLASS]) { 1318b60a18deSMichael J. Spencer case ELF::ELFCLASS32: 1319b60a18deSMichael J. Spencer switch(Header->e_machine) { 1320b60a18deSMichael J. Spencer case ELF::EM_386: 1321b60a18deSMichael J. Spencer return "ELF32-i386"; 1322b60a18deSMichael J. Spencer case ELF::EM_X86_64: 1323b60a18deSMichael J. Spencer return "ELF32-x86-64"; 1324022ecdf2SBenjamin Kramer case ELF::EM_ARM: 1325022ecdf2SBenjamin Kramer return "ELF32-arm"; 1326b60a18deSMichael J. Spencer default: 1327b60a18deSMichael J. Spencer return "ELF32-unknown"; 1328b60a18deSMichael J. Spencer } 1329b60a18deSMichael J. Spencer case ELF::ELFCLASS64: 1330b60a18deSMichael J. Spencer switch(Header->e_machine) { 1331b60a18deSMichael J. Spencer case ELF::EM_386: 1332b60a18deSMichael J. Spencer return "ELF64-i386"; 1333b60a18deSMichael J. Spencer case ELF::EM_X86_64: 1334b60a18deSMichael J. Spencer return "ELF64-x86-64"; 1335b60a18deSMichael J. Spencer default: 1336b60a18deSMichael J. Spencer return "ELF64-unknown"; 1337b60a18deSMichael J. Spencer } 1338b60a18deSMichael J. Spencer default: 1339b60a18deSMichael J. Spencer // FIXME: Proper error handling. 1340b60a18deSMichael J. Spencer report_fatal_error("Invalid ELFCLASS!"); 1341b60a18deSMichael J. Spencer } 1342b60a18deSMichael J. Spencer } 1343b60a18deSMichael J. Spencer 1344b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 1345b60a18deSMichael J. Spencer unsigned ELFObjectFile<target_endianness, is64Bits>::getArch() const { 1346b60a18deSMichael J. Spencer switch(Header->e_machine) { 1347b60a18deSMichael J. Spencer case ELF::EM_386: 1348b60a18deSMichael J. Spencer return Triple::x86; 1349b60a18deSMichael J. Spencer case ELF::EM_X86_64: 1350b60a18deSMichael J. Spencer return Triple::x86_64; 1351022ecdf2SBenjamin Kramer case ELF::EM_ARM: 1352022ecdf2SBenjamin Kramer return Triple::arm; 1353b60a18deSMichael J. Spencer default: 1354b60a18deSMichael J. Spencer return Triple::UnknownArch; 1355b60a18deSMichael J. Spencer } 1356b60a18deSMichael J. Spencer } 1357b60a18deSMichael J. Spencer 135843f01caeSNick Lewycky template<support::endianness target_endianness, bool is64Bits> 135943f01caeSNick Lewycky uint64_t ELFObjectFile<target_endianness, is64Bits>::getNumSections() const { 136043f01caeSNick Lewycky if (Header->e_shnum == ELF::SHN_UNDEF) 136143f01caeSNick Lewycky return SectionHeaderTable->sh_size; 136243f01caeSNick Lewycky return Header->e_shnum; 136343f01caeSNick Lewycky } 136443f01caeSNick Lewycky 136543f01caeSNick Lewycky template<support::endianness target_endianness, bool is64Bits> 136643f01caeSNick Lewycky uint64_t 136743f01caeSNick Lewycky ELFObjectFile<target_endianness, is64Bits>::getStringTableIndex() const { 136843f01caeSNick Lewycky if (Header->e_shnum == ELF::SHN_UNDEF) { 136943f01caeSNick Lewycky if (Header->e_shstrndx == ELF::SHN_HIRESERVE) 137043f01caeSNick Lewycky return SectionHeaderTable->sh_link; 137143f01caeSNick Lewycky if (Header->e_shstrndx >= getNumSections()) 137243f01caeSNick Lewycky return 0; 137343f01caeSNick Lewycky } 137443f01caeSNick Lewycky return Header->e_shstrndx; 137543f01caeSNick Lewycky } 137643f01caeSNick Lewycky 1377e5fd0047SMichael J. Spencer 1378b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 1379022ecdf2SBenjamin Kramer template<typename T> 1380022ecdf2SBenjamin Kramer inline const T * 1381e5fd0047SMichael J. Spencer ELFObjectFile<target_endianness, is64Bits>::getEntry(uint16_t Section, 1382e5fd0047SMichael J. Spencer uint32_t Entry) const { 1383e5fd0047SMichael J. Spencer return getEntry<T>(getSection(Section), Entry); 1384e5fd0047SMichael J. Spencer } 1385e5fd0047SMichael J. Spencer 1386e5fd0047SMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 1387e5fd0047SMichael J. Spencer template<typename T> 1388e5fd0047SMichael J. Spencer inline const T * 1389e5fd0047SMichael J. Spencer ELFObjectFile<target_endianness, is64Bits>::getEntry(const Elf_Shdr * Section, 1390e5fd0047SMichael J. Spencer uint32_t Entry) const { 1391022ecdf2SBenjamin Kramer return reinterpret_cast<const T *>( 1392ec29b121SMichael J. Spencer base() 1393e5fd0047SMichael J. Spencer + Section->sh_offset 1394e5fd0047SMichael J. Spencer + (Entry * Section->sh_entsize)); 1395022ecdf2SBenjamin Kramer } 1396022ecdf2SBenjamin Kramer 1397022ecdf2SBenjamin Kramer template<support::endianness target_endianness, bool is64Bits> 1398022ecdf2SBenjamin Kramer const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Sym * 1399022ecdf2SBenjamin Kramer ELFObjectFile<target_endianness, is64Bits>::getSymbol(DataRefImpl Symb) const { 1400e5fd0047SMichael J. Spencer return getEntry<Elf_Sym>(SymbolTableSections[Symb.d.b], Symb.d.a); 1401022ecdf2SBenjamin Kramer } 1402022ecdf2SBenjamin Kramer 1403022ecdf2SBenjamin Kramer template<support::endianness target_endianness, bool is64Bits> 1404022ecdf2SBenjamin Kramer const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Rel * 1405022ecdf2SBenjamin Kramer ELFObjectFile<target_endianness, is64Bits>::getRel(DataRefImpl Rel) const { 1406e5fd0047SMichael J. Spencer return getEntry<Elf_Rel>(Rel.w.b, Rel.w.c); 1407022ecdf2SBenjamin Kramer } 1408022ecdf2SBenjamin Kramer 1409022ecdf2SBenjamin Kramer template<support::endianness target_endianness, bool is64Bits> 1410022ecdf2SBenjamin Kramer const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Rela * 1411022ecdf2SBenjamin Kramer ELFObjectFile<target_endianness, is64Bits>::getRela(DataRefImpl Rela) const { 1412e5fd0047SMichael J. Spencer return getEntry<Elf_Rela>(Rela.w.b, Rela.w.c); 1413b60a18deSMichael J. Spencer } 1414b60a18deSMichael J. Spencer 1415b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 1416b60a18deSMichael J. Spencer const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Shdr * 1417b60a18deSMichael J. Spencer ELFObjectFile<target_endianness, is64Bits>::getSection(DataRefImpl Symb) const { 14180324b672SMichael J. Spencer const Elf_Shdr *sec = getSection(Symb.d.b); 1419e5fd0047SMichael J. Spencer if (sec->sh_type != ELF::SHT_SYMTAB || sec->sh_type != ELF::SHT_DYNSYM) 1420b60a18deSMichael J. Spencer // FIXME: Proper error handling. 1421b60a18deSMichael J. Spencer report_fatal_error("Invalid symbol table section!"); 1422b60a18deSMichael J. Spencer return sec; 1423b60a18deSMichael J. Spencer } 1424b60a18deSMichael J. Spencer 1425b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 1426b60a18deSMichael J. Spencer const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Shdr * 142743f01caeSNick Lewycky ELFObjectFile<target_endianness, is64Bits>::getSection(uint32_t index) const { 142843f01caeSNick Lewycky if (index == 0) 1429b60a18deSMichael J. Spencer return 0; 143043f01caeSNick Lewycky if (!SectionHeaderTable || index >= getNumSections()) 1431b60a18deSMichael J. Spencer // FIXME: Proper error handling. 1432b60a18deSMichael J. Spencer report_fatal_error("Invalid section index!"); 1433b60a18deSMichael J. Spencer 1434b60a18deSMichael J. Spencer return reinterpret_cast<const Elf_Shdr *>( 1435b60a18deSMichael J. Spencer reinterpret_cast<const char *>(SectionHeaderTable) 1436b60a18deSMichael J. Spencer + (index * Header->e_shentsize)); 1437b60a18deSMichael J. Spencer } 1438b60a18deSMichael J. Spencer 1439b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 1440b60a18deSMichael J. Spencer const char *ELFObjectFile<target_endianness, is64Bits> 144143f01caeSNick Lewycky ::getString(uint32_t section, 1442b60a18deSMichael J. Spencer ELF::Elf32_Word offset) const { 1443b60a18deSMichael J. Spencer return getString(getSection(section), offset); 1444b60a18deSMichael J. Spencer } 1445b60a18deSMichael J. Spencer 1446b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 1447b60a18deSMichael J. Spencer const char *ELFObjectFile<target_endianness, is64Bits> 1448b60a18deSMichael J. Spencer ::getString(const Elf_Shdr *section, 1449b60a18deSMichael J. Spencer ELF::Elf32_Word offset) const { 1450b60a18deSMichael J. Spencer assert(section && section->sh_type == ELF::SHT_STRTAB && "Invalid section!"); 1451b60a18deSMichael J. Spencer if (offset >= section->sh_size) 1452b60a18deSMichael J. Spencer // FIXME: Proper error handling. 1453ec29b121SMichael J. Spencer report_fatal_error("Symbol name offset outside of string table!"); 1454ec29b121SMichael J. Spencer return (const char *)base() + section->sh_offset + offset; 1455b60a18deSMichael J. Spencer } 1456b60a18deSMichael J. Spencer 1457e5fd0047SMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 1458e5fd0047SMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits> 1459e5fd0047SMichael J. Spencer ::getSymbolName(const Elf_Sym *symb, 1460e5fd0047SMichael J. Spencer StringRef &Result) const { 1461e5fd0047SMichael J. Spencer if (symb->st_name == 0) { 146243f01caeSNick Lewycky const Elf_Shdr *section = getSection(symb); 1463e5fd0047SMichael J. Spencer if (!section) 1464e5fd0047SMichael J. Spencer Result = ""; 1465e5fd0047SMichael J. Spencer else 1466e5fd0047SMichael J. Spencer Result = getString(dot_shstrtab_sec, section->sh_name); 1467e5fd0047SMichael J. Spencer return object_error::success; 1468e5fd0047SMichael J. Spencer } 1469e5fd0047SMichael J. Spencer 1470e5fd0047SMichael J. Spencer // Use the default symbol table name section. 1471e5fd0047SMichael J. Spencer Result = getString(dot_strtab_sec, symb->st_name); 1472e5fd0047SMichael J. Spencer return object_error::success; 1473e5fd0047SMichael J. Spencer } 1474e5fd0047SMichael J. Spencer 1475b60a18deSMichael J. Spencer // EI_CLASS, EI_DATA. 1476b60a18deSMichael J. Spencer static std::pair<unsigned char, unsigned char> 1477b60a18deSMichael J. Spencer getElfArchType(MemoryBuffer *Object) { 1478b60a18deSMichael J. Spencer if (Object->getBufferSize() < ELF::EI_NIDENT) 1479b60a18deSMichael J. Spencer return std::make_pair((uint8_t)ELF::ELFCLASSNONE,(uint8_t)ELF::ELFDATANONE); 1480b60a18deSMichael J. Spencer return std::make_pair( (uint8_t)Object->getBufferStart()[ELF::EI_CLASS] 1481b60a18deSMichael J. Spencer , (uint8_t)Object->getBufferStart()[ELF::EI_DATA]); 1482b60a18deSMichael J. Spencer } 1483b60a18deSMichael J. Spencer 1484*c3c80f09SEli Bendersky 1485*c3c80f09SEli Bendersky namespace { 1486*c3c80f09SEli Bendersky template<support::endianness target_endianness, bool is64Bits> 1487*c3c80f09SEli Bendersky class DyldELFObject : public ELFObjectFile<target_endianness, is64Bits> { 1488*c3c80f09SEli Bendersky LLVM_ELF_IMPORT_TYPES(target_endianness, is64Bits) 1489*c3c80f09SEli Bendersky 1490*c3c80f09SEli Bendersky typedef Elf_Shdr_Impl<target_endianness, is64Bits> Elf_Shdr; 1491*c3c80f09SEli Bendersky typedef Elf_Sym_Impl<target_endianness, is64Bits> Elf_Sym; 1492*c3c80f09SEli Bendersky typedef Elf_Rel_Impl<target_endianness, is64Bits, false> Elf_Rel; 1493*c3c80f09SEli Bendersky typedef Elf_Rel_Impl<target_endianness, is64Bits, true> Elf_Rela; 1494*c3c80f09SEli Bendersky 1495*c3c80f09SEli Bendersky typedef typename ELFObjectFile<target_endianness, is64Bits>:: 1496*c3c80f09SEli Bendersky Elf_Ehdr Elf_Ehdr; 1497*c3c80f09SEli Bendersky Elf_Ehdr *Header; 1498*c3c80f09SEli Bendersky 1499*c3c80f09SEli Bendersky // Update section headers according to the current location in memory 1500*c3c80f09SEli Bendersky virtual void rebaseObject(std::vector<uint8_t*> *MemoryMap); 1501*c3c80f09SEli Bendersky // Record memory addresses for cleanup 1502*c3c80f09SEli Bendersky virtual void saveAddress(std::vector<uint8_t*> *MemoryMap, uint8_t *addr); 1503*c3c80f09SEli Bendersky 1504*c3c80f09SEli Bendersky protected: 1505*c3c80f09SEli Bendersky virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const; 1506*c3c80f09SEli Bendersky 1507*c3c80f09SEli Bendersky public: 1508*c3c80f09SEli Bendersky DyldELFObject(MemoryBuffer *Object, std::vector<uint8_t*> *MemoryMap, 1509*c3c80f09SEli Bendersky error_code &ec); 1510*c3c80f09SEli Bendersky 1511*c3c80f09SEli Bendersky // Methods for type inquiry through isa, cast, and dyn_cast 1512*c3c80f09SEli Bendersky static inline bool classof(const Binary *v) { 1513*c3c80f09SEli Bendersky return (isa<ELFObjectFile<target_endianness, is64Bits> >(v) 1514*c3c80f09SEli Bendersky && classof(cast<ELFObjectFile<target_endianness, is64Bits> >(v))); 1515*c3c80f09SEli Bendersky } 1516*c3c80f09SEli Bendersky static inline bool classof( 1517*c3c80f09SEli Bendersky const ELFObjectFile<target_endianness, is64Bits> *v) { 1518*c3c80f09SEli Bendersky return v->isDyldType(); 1519*c3c80f09SEli Bendersky } 1520*c3c80f09SEli Bendersky static inline bool classof(const DyldELFObject *v) { 1521*c3c80f09SEli Bendersky return true; 1522*c3c80f09SEli Bendersky } 1523*c3c80f09SEli Bendersky }; 1524*c3c80f09SEli Bendersky } // end anonymous namespace 1525*c3c80f09SEli Bendersky 1526*c3c80f09SEli Bendersky template<support::endianness target_endianness, bool is64Bits> 1527*c3c80f09SEli Bendersky DyldELFObject<target_endianness, is64Bits>::DyldELFObject(MemoryBuffer *Object, 1528*c3c80f09SEli Bendersky std::vector<uint8_t*> *MemoryMap, error_code &ec) 1529*c3c80f09SEli Bendersky : ELFObjectFile<target_endianness, is64Bits>(Object, ec) 1530*c3c80f09SEli Bendersky , Header(0) { 1531*c3c80f09SEli Bendersky this->isDyldELFObject = true; 1532*c3c80f09SEli Bendersky Header = const_cast<Elf_Ehdr *>( 1533*c3c80f09SEli Bendersky reinterpret_cast<const Elf_Ehdr *>(this->base())); 1534*c3c80f09SEli Bendersky if (Header->e_shoff == 0) 1535*c3c80f09SEli Bendersky return; 1536*c3c80f09SEli Bendersky 1537*c3c80f09SEli Bendersky // Mark the image as a dynamic shared library 1538*c3c80f09SEli Bendersky Header->e_type = ELF::ET_DYN; 1539*c3c80f09SEli Bendersky 1540*c3c80f09SEli Bendersky rebaseObject(MemoryMap); 1541*c3c80f09SEli Bendersky } 1542*c3c80f09SEli Bendersky 1543*c3c80f09SEli Bendersky // Walk through the ELF headers, updating virtual addresses to reflect where 1544*c3c80f09SEli Bendersky // the object is currently loaded in memory 1545*c3c80f09SEli Bendersky template<support::endianness target_endianness, bool is64Bits> 1546*c3c80f09SEli Bendersky void DyldELFObject<target_endianness, is64Bits>::rebaseObject( 1547*c3c80f09SEli Bendersky std::vector<uint8_t*> *MemoryMap) { 1548*c3c80f09SEli Bendersky typedef typename ELFDataTypeTypedefHelper< 1549*c3c80f09SEli Bendersky target_endianness, is64Bits>::value_type addr_type; 1550*c3c80f09SEli Bendersky 1551*c3c80f09SEli Bendersky uint8_t *base_p = const_cast<uint8_t *>(this->base()); 1552*c3c80f09SEli Bendersky Elf_Shdr *sectionTable = 1553*c3c80f09SEli Bendersky reinterpret_cast<Elf_Shdr *>(base_p + Header->e_shoff); 1554*c3c80f09SEli Bendersky uint64_t numSections = this->getNumSections(); 1555*c3c80f09SEli Bendersky 1556*c3c80f09SEli Bendersky // Allocate memory space for NOBITS sections (such as .bss), which only exist 1557*c3c80f09SEli Bendersky // in memory, but don't occupy space in the object file. 1558*c3c80f09SEli Bendersky // Update the address in the section headers to reflect this allocation. 1559*c3c80f09SEli Bendersky for (uint64_t index = 0; index < numSections; index++) { 1560*c3c80f09SEli Bendersky Elf_Shdr *sec = reinterpret_cast<Elf_Shdr *>( 1561*c3c80f09SEli Bendersky reinterpret_cast<char *>(sectionTable) + index * Header->e_shentsize); 1562*c3c80f09SEli Bendersky 1563*c3c80f09SEli Bendersky // Only update sections that are meant to be present in program memory 1564*c3c80f09SEli Bendersky if (sec->sh_flags & ELF::SHF_ALLOC) { 1565*c3c80f09SEli Bendersky uint8_t *addr = base_p + sec->sh_offset; 1566*c3c80f09SEli Bendersky if (sec->sh_type == ELF::SHT_NOBITS) { 1567*c3c80f09SEli Bendersky addr = static_cast<uint8_t *>(calloc(sec->sh_size, 1)); 1568*c3c80f09SEli Bendersky saveAddress(MemoryMap, addr); 1569*c3c80f09SEli Bendersky } 1570*c3c80f09SEli Bendersky else { 1571*c3c80f09SEli Bendersky // FIXME: Currently memory with RWX permissions is allocated. In the 1572*c3c80f09SEli Bendersky // future, make sure that permissions are as necessary 1573*c3c80f09SEli Bendersky if (sec->sh_flags & ELF::SHF_WRITE) { 1574*c3c80f09SEli Bendersky // see FIXME above 1575*c3c80f09SEli Bendersky } 1576*c3c80f09SEli Bendersky if (sec->sh_flags & ELF::SHF_EXECINSTR) { 1577*c3c80f09SEli Bendersky // see FIXME above 1578*c3c80f09SEli Bendersky } 1579*c3c80f09SEli Bendersky } 1580*c3c80f09SEli Bendersky assert(sizeof(addr_type) == sizeof(intptr_t) && 1581*c3c80f09SEli Bendersky "Cross-architecture ELF dy-load is not supported!"); 1582*c3c80f09SEli Bendersky sec->sh_addr = static_cast<addr_type>(intptr_t(addr)); 1583*c3c80f09SEli Bendersky } 1584*c3c80f09SEli Bendersky } 1585*c3c80f09SEli Bendersky 1586*c3c80f09SEli Bendersky // Now allocate actual space for COMMON symbols, which also don't occupy 1587*c3c80f09SEli Bendersky // space in the object file. 1588*c3c80f09SEli Bendersky // We want to allocate space for all COMMON symbols at once, so the flow is: 1589*c3c80f09SEli Bendersky // 1. Go over all symbols, find those that are in COMMON. For each such 1590*c3c80f09SEli Bendersky // symbol, record its size and the value field in its symbol header in a 1591*c3c80f09SEli Bendersky // special vector. 1592*c3c80f09SEli Bendersky // 2. Allocate memory for all COMMON symbols in one fell swoop. 1593*c3c80f09SEli Bendersky // 3. Using the recorded information from (1), update the address fields in 1594*c3c80f09SEli Bendersky // the symbol headers of the COMMON symbols to reflect their allocated 1595*c3c80f09SEli Bendersky // address. 1596*c3c80f09SEli Bendersky uint64_t TotalSize = 0; 1597*c3c80f09SEli Bendersky std::vector<std::pair<Elf_Addr *, uint64_t> > SymbAddrInfo; 1598*c3c80f09SEli Bendersky error_code ec = object_error::success; 1599*c3c80f09SEli Bendersky for (symbol_iterator si = this->begin_symbols(), 1600*c3c80f09SEli Bendersky se = this->end_symbols(); si != se; si.increment(ec)) { 1601*c3c80f09SEli Bendersky uint64_t Size = 0; 1602*c3c80f09SEli Bendersky ec = si->getSize(Size); 1603*c3c80f09SEli Bendersky Elf_Sym* symb = const_cast<Elf_Sym*>( 1604*c3c80f09SEli Bendersky this->getSymbol(si->getRawDataRefImpl())); 1605*c3c80f09SEli Bendersky if (ec == object_error::success && 1606*c3c80f09SEli Bendersky this->getSymbolTableIndex(symb) == ELF::SHN_COMMON && Size > 0) { 1607*c3c80f09SEli Bendersky SymbAddrInfo.push_back(std::make_pair(&(symb->st_value), Size)); 1608*c3c80f09SEli Bendersky TotalSize += Size; 1609*c3c80f09SEli Bendersky } 1610*c3c80f09SEli Bendersky } 1611*c3c80f09SEli Bendersky 1612*c3c80f09SEli Bendersky uint8_t* SectionPtr = (uint8_t *)calloc(TotalSize, 1); 1613*c3c80f09SEli Bendersky saveAddress(MemoryMap, SectionPtr); 1614*c3c80f09SEli Bendersky 1615*c3c80f09SEli Bendersky typedef typename std::vector<std::pair<Elf_Addr *, uint64_t> >::iterator 1616*c3c80f09SEli Bendersky AddrInfoIterator; 1617*c3c80f09SEli Bendersky AddrInfoIterator EndIter = SymbAddrInfo.end(); 1618*c3c80f09SEli Bendersky for (AddrInfoIterator AddrIter = SymbAddrInfo.begin(); 1619*c3c80f09SEli Bendersky AddrIter != EndIter; ++AddrIter) { 1620*c3c80f09SEli Bendersky assert(sizeof(addr_type) == sizeof(intptr_t) && 1621*c3c80f09SEli Bendersky "Cross-architecture ELF dy-load is not supported!"); 1622*c3c80f09SEli Bendersky *(AddrIter->first) = static_cast<addr_type>(intptr_t(SectionPtr)); 1623*c3c80f09SEli Bendersky SectionPtr += AddrIter->second; 1624*c3c80f09SEli Bendersky } 1625*c3c80f09SEli Bendersky } 1626*c3c80f09SEli Bendersky 1627*c3c80f09SEli Bendersky // Record memory addresses for callers 1628*c3c80f09SEli Bendersky template<support::endianness target_endianness, bool is64Bits> 1629*c3c80f09SEli Bendersky void DyldELFObject<target_endianness, is64Bits>::saveAddress( 1630*c3c80f09SEli Bendersky std::vector<uint8_t*> *MemoryMap, uint8_t* addr) { 1631*c3c80f09SEli Bendersky if (MemoryMap) 1632*c3c80f09SEli Bendersky MemoryMap->push_back(addr); 1633*c3c80f09SEli Bendersky else 1634*c3c80f09SEli Bendersky errs() << "WARNING: Memory leak - cannot record memory for ELF dyld."; 1635*c3c80f09SEli Bendersky } 1636*c3c80f09SEli Bendersky 1637*c3c80f09SEli Bendersky template<support::endianness target_endianness, bool is64Bits> 1638*c3c80f09SEli Bendersky error_code DyldELFObject<target_endianness, is64Bits>::getSymbolAddress( 1639*c3c80f09SEli Bendersky DataRefImpl Symb, uint64_t &Result) const { 1640*c3c80f09SEli Bendersky this->validateSymbol(Symb); 1641*c3c80f09SEli Bendersky const Elf_Sym *symb = this->getSymbol(Symb); 1642*c3c80f09SEli Bendersky if (this->getSymbolTableIndex(symb) == ELF::SHN_COMMON) { 1643*c3c80f09SEli Bendersky Result = symb->st_value; 1644*c3c80f09SEli Bendersky return object_error::success; 1645*c3c80f09SEli Bendersky } 1646*c3c80f09SEli Bendersky else { 1647*c3c80f09SEli Bendersky return ELFObjectFile<target_endianness, is64Bits>::getSymbolAddress( 1648*c3c80f09SEli Bendersky Symb, Result); 1649*c3c80f09SEli Bendersky } 1650*c3c80f09SEli Bendersky } 1651*c3c80f09SEli Bendersky 1652b60a18deSMichael J. Spencer namespace llvm { 1653b60a18deSMichael J. Spencer 1654*c3c80f09SEli Bendersky // Creates an in-memory object-file by default: createELFObjectFile(Buffer) 1655*c3c80f09SEli Bendersky // Set doDyld to true to create a live (executable/debug-worthy) image 1656*c3c80f09SEli Bendersky // If doDyld is true, any memory allocated for non-resident sections and 1657*c3c80f09SEli Bendersky // symbols is recorded in MemoryMap. 1658*c3c80f09SEli Bendersky ObjectFile *ObjectFile::createELFObjectFile(MemoryBuffer *Object, 1659*c3c80f09SEli Bendersky bool doDyld, std::vector<uint8_t *> *MemoryMap) { 1660b60a18deSMichael J. Spencer std::pair<unsigned char, unsigned char> Ident = getElfArchType(Object); 1661ec29b121SMichael J. Spencer error_code ec; 1662*c3c80f09SEli Bendersky 1663*c3c80f09SEli Bendersky if (doDyld) { 1664*c3c80f09SEli Bendersky if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2LSB) 1665*c3c80f09SEli Bendersky return new DyldELFObject<support::little, false>(Object, MemoryMap, ec); 1666*c3c80f09SEli Bendersky else if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2MSB) 1667*c3c80f09SEli Bendersky return new DyldELFObject<support::big, false>(Object, MemoryMap, ec); 1668*c3c80f09SEli Bendersky else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2MSB) 1669*c3c80f09SEli Bendersky return new DyldELFObject<support::big, true>(Object, MemoryMap, ec); 1670*c3c80f09SEli Bendersky else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2LSB) { 1671*c3c80f09SEli Bendersky DyldELFObject<support::little, true> *result = 1672*c3c80f09SEli Bendersky new DyldELFObject<support::little, true>(Object, MemoryMap, ec); 1673*c3c80f09SEli Bendersky 1674*c3c80f09SEli Bendersky // Unit testing for type inquiry 1675*c3c80f09SEli Bendersky bool isBinary = isa<Binary>(result); 1676*c3c80f09SEli Bendersky bool isDyld = isa<DyldELFObject<support::little, true> >(result); 1677*c3c80f09SEli Bendersky bool isFile = isa<ELFObjectFile<support::little, true> >(result); 1678*c3c80f09SEli Bendersky assert(isBinary && isDyld && isFile && 1679*c3c80f09SEli Bendersky "Type inquiry failed for ELF object!"); 1680*c3c80f09SEli Bendersky return result; 1681*c3c80f09SEli Bendersky } 1682*c3c80f09SEli Bendersky } 1683*c3c80f09SEli Bendersky 1684b60a18deSMichael J. Spencer if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2LSB) 1685ec29b121SMichael J. Spencer return new ELFObjectFile<support::little, false>(Object, ec); 1686b60a18deSMichael J. Spencer else if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2MSB) 1687ec29b121SMichael J. Spencer return new ELFObjectFile<support::big, false>(Object, ec); 1688b60a18deSMichael J. Spencer else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2MSB) 1689ec29b121SMichael J. Spencer return new ELFObjectFile<support::big, true>(Object, ec); 1690*c3c80f09SEli Bendersky else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2LSB) { 1691*c3c80f09SEli Bendersky ELFObjectFile<support::little, true> *result = 1692*c3c80f09SEli Bendersky new ELFObjectFile<support::little, true>(Object, ec); 1693*c3c80f09SEli Bendersky 1694*c3c80f09SEli Bendersky // Unit testing for type inquiry 1695*c3c80f09SEli Bendersky bool isBinary = isa<Binary>(result); 1696*c3c80f09SEli Bendersky bool isDyld = isa<DyldELFObject<support::little, true> >(result); 1697*c3c80f09SEli Bendersky bool isFile = isa<ELFObjectFile<support::little, true> >(result); 1698*c3c80f09SEli Bendersky assert(isBinary && isFile && !isDyld && 1699*c3c80f09SEli Bendersky "Type inquiry failed for ELF object!"); 1700*c3c80f09SEli Bendersky return result; 1701*c3c80f09SEli Bendersky } 1702*c3c80f09SEli Bendersky 1703*c3c80f09SEli Bendersky report_fatal_error("Buffer is not an ELF object file!"); 1704b60a18deSMichael J. Spencer } 1705b60a18deSMichael J. Spencer 1706b60a18deSMichael J. Spencer } // end namespace llvm 1707