1*b60a18deSMichael J. Spencer //===- ELFObjectFile.cpp - ELF object file implementation -------*- C++ -*-===// 2*b60a18deSMichael J. Spencer // 3*b60a18deSMichael J. Spencer // The LLVM Compiler Infrastructure 4*b60a18deSMichael J. Spencer // 5*b60a18deSMichael J. Spencer // This file is distributed under the University of Illinois Open Source 6*b60a18deSMichael J. Spencer // License. See LICENSE.TXT for details. 7*b60a18deSMichael J. Spencer // 8*b60a18deSMichael J. Spencer //===----------------------------------------------------------------------===// 9*b60a18deSMichael J. Spencer // 10*b60a18deSMichael J. Spencer // This file defines the ELFObjectFile class. 11*b60a18deSMichael J. Spencer // 12*b60a18deSMichael J. Spencer //===----------------------------------------------------------------------===// 13*b60a18deSMichael J. Spencer 14*b60a18deSMichael J. Spencer #include "llvm/ADT/SmallVector.h" 15*b60a18deSMichael J. Spencer #include "llvm/ADT/StringSwitch.h" 16*b60a18deSMichael J. Spencer #include "llvm/ADT/Triple.h" 17*b60a18deSMichael J. Spencer #include "llvm/Object/ObjectFile.h" 18*b60a18deSMichael J. Spencer #include "llvm/Support/ELF.h" 19*b60a18deSMichael J. Spencer #include "llvm/Support/Endian.h" 20*b60a18deSMichael J. Spencer #include "llvm/Support/ErrorHandling.h" 21*b60a18deSMichael J. Spencer #include "llvm/Support/MemoryBuffer.h" 22*b60a18deSMichael J. Spencer #include <limits> 23*b60a18deSMichael J. Spencer #include <utility> 24*b60a18deSMichael J. Spencer 25*b60a18deSMichael J. Spencer using namespace llvm; 26*b60a18deSMichael J. Spencer using namespace object; 27*b60a18deSMichael J. Spencer 28*b60a18deSMichael J. Spencer // Templates to choose Elf_Addr and Elf_Off depending on is64Bits. 29*b60a18deSMichael J. Spencer namespace { 30*b60a18deSMichael J. Spencer template<support::endianness target_endianness> 31*b60a18deSMichael J. Spencer struct ELFDataTypeTypedefHelperCommon { 32*b60a18deSMichael J. Spencer typedef support::detail::packed_endian_specific_integral 33*b60a18deSMichael J. Spencer <uint16_t, target_endianness, support::aligned> Elf_Half; 34*b60a18deSMichael J. Spencer typedef support::detail::packed_endian_specific_integral 35*b60a18deSMichael J. Spencer <uint32_t, target_endianness, support::aligned> Elf_Word; 36*b60a18deSMichael J. Spencer typedef support::detail::packed_endian_specific_integral 37*b60a18deSMichael J. Spencer <int32_t, target_endianness, support::aligned> Elf_Sword; 38*b60a18deSMichael J. Spencer typedef support::detail::packed_endian_specific_integral 39*b60a18deSMichael J. Spencer <uint64_t, target_endianness, support::aligned> Elf_Xword; 40*b60a18deSMichael J. Spencer typedef support::detail::packed_endian_specific_integral 41*b60a18deSMichael J. Spencer <int64_t, target_endianness, support::aligned> Elf_Sxword; 42*b60a18deSMichael J. Spencer }; 43*b60a18deSMichael J. Spencer } 44*b60a18deSMichael J. Spencer 45*b60a18deSMichael J. Spencer namespace { 46*b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 47*b60a18deSMichael J. Spencer struct ELFDataTypeTypedefHelper; 48*b60a18deSMichael J. Spencer 49*b60a18deSMichael J. Spencer /// ELF 32bit types. 50*b60a18deSMichael J. Spencer template<support::endianness target_endianness> 51*b60a18deSMichael J. Spencer struct ELFDataTypeTypedefHelper<target_endianness, false> 52*b60a18deSMichael J. Spencer : ELFDataTypeTypedefHelperCommon<target_endianness> { 53*b60a18deSMichael J. Spencer typedef support::detail::packed_endian_specific_integral 54*b60a18deSMichael J. Spencer <uint32_t, target_endianness, support::aligned> Elf_Addr; 55*b60a18deSMichael J. Spencer typedef support::detail::packed_endian_specific_integral 56*b60a18deSMichael J. Spencer <uint32_t, target_endianness, support::aligned> Elf_Off; 57*b60a18deSMichael J. Spencer }; 58*b60a18deSMichael J. Spencer 59*b60a18deSMichael J. Spencer /// ELF 64bit types. 60*b60a18deSMichael J. Spencer template<support::endianness target_endianness> 61*b60a18deSMichael J. Spencer struct ELFDataTypeTypedefHelper<target_endianness, true> 62*b60a18deSMichael J. Spencer : ELFDataTypeTypedefHelperCommon<target_endianness>{ 63*b60a18deSMichael J. Spencer typedef support::detail::packed_endian_specific_integral 64*b60a18deSMichael J. Spencer <uint64_t, target_endianness, support::aligned> Elf_Addr; 65*b60a18deSMichael J. Spencer typedef support::detail::packed_endian_specific_integral 66*b60a18deSMichael J. Spencer <uint64_t, target_endianness, support::aligned> Elf_Off; 67*b60a18deSMichael J. Spencer }; 68*b60a18deSMichael J. Spencer } 69*b60a18deSMichael J. Spencer 70*b60a18deSMichael J. Spencer // I really don't like doing this, but the alternative is copypasta. 71*b60a18deSMichael J. Spencer #define LLVM_ELF_IMPORT_TYPES(target_endianness, is64Bits) \ 72*b60a18deSMichael J. Spencer typedef typename \ 73*b60a18deSMichael J. Spencer ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Addr Elf_Addr; \ 74*b60a18deSMichael J. Spencer typedef typename \ 75*b60a18deSMichael J. Spencer ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Off Elf_Off; \ 76*b60a18deSMichael J. Spencer typedef typename \ 77*b60a18deSMichael J. Spencer ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Half Elf_Half; \ 78*b60a18deSMichael J. Spencer typedef typename \ 79*b60a18deSMichael J. Spencer ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Word Elf_Word; \ 80*b60a18deSMichael J. Spencer typedef typename \ 81*b60a18deSMichael J. Spencer ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Sword Elf_Sword; \ 82*b60a18deSMichael J. Spencer typedef typename \ 83*b60a18deSMichael J. Spencer ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Xword Elf_Xword; \ 84*b60a18deSMichael J. Spencer typedef typename \ 85*b60a18deSMichael J. Spencer ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Sxword Elf_Sxword; 86*b60a18deSMichael J. Spencer 87*b60a18deSMichael J. Spencer // Section header. 88*b60a18deSMichael J. Spencer namespace { 89*b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 90*b60a18deSMichael J. Spencer struct Elf_Shdr_Base; 91*b60a18deSMichael J. Spencer 92*b60a18deSMichael J. Spencer template<support::endianness target_endianness> 93*b60a18deSMichael J. Spencer struct Elf_Shdr_Base<target_endianness, false> { 94*b60a18deSMichael J. Spencer LLVM_ELF_IMPORT_TYPES(target_endianness, false) 95*b60a18deSMichael J. Spencer Elf_Word sh_name; // Section name (index into string table) 96*b60a18deSMichael J. Spencer Elf_Word sh_type; // Section type (SHT_*) 97*b60a18deSMichael J. Spencer Elf_Word sh_flags; // Section flags (SHF_*) 98*b60a18deSMichael J. Spencer Elf_Addr sh_addr; // Address where section is to be loaded 99*b60a18deSMichael J. Spencer Elf_Off sh_offset; // File offset of section data, in bytes 100*b60a18deSMichael J. Spencer Elf_Word sh_size; // Size of section, in bytes 101*b60a18deSMichael J. Spencer Elf_Word sh_link; // Section type-specific header table index link 102*b60a18deSMichael J. Spencer Elf_Word sh_info; // Section type-specific extra information 103*b60a18deSMichael J. Spencer Elf_Word sh_addralign;// Section address alignment 104*b60a18deSMichael J. Spencer Elf_Word sh_entsize; // Size of records contained within the section 105*b60a18deSMichael J. Spencer }; 106*b60a18deSMichael J. Spencer 107*b60a18deSMichael J. Spencer template<support::endianness target_endianness> 108*b60a18deSMichael J. Spencer struct Elf_Shdr_Base<target_endianness, true> { 109*b60a18deSMichael J. Spencer LLVM_ELF_IMPORT_TYPES(target_endianness, true) 110*b60a18deSMichael J. Spencer Elf_Word sh_name; // Section name (index into string table) 111*b60a18deSMichael J. Spencer Elf_Word sh_type; // Section type (SHT_*) 112*b60a18deSMichael J. Spencer Elf_Xword sh_flags; // Section flags (SHF_*) 113*b60a18deSMichael J. Spencer Elf_Addr sh_addr; // Address where section is to be loaded 114*b60a18deSMichael J. Spencer Elf_Off sh_offset; // File offset of section data, in bytes 115*b60a18deSMichael J. Spencer Elf_Xword sh_size; // Size of section, in bytes 116*b60a18deSMichael J. Spencer Elf_Word sh_link; // Section type-specific header table index link 117*b60a18deSMichael J. Spencer Elf_Word sh_info; // Section type-specific extra information 118*b60a18deSMichael J. Spencer Elf_Xword sh_addralign;// Section address alignment 119*b60a18deSMichael J. Spencer Elf_Xword sh_entsize; // Size of records contained within the section 120*b60a18deSMichael J. Spencer }; 121*b60a18deSMichael J. Spencer 122*b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 123*b60a18deSMichael J. Spencer struct Elf_Shdr_Impl : Elf_Shdr_Base<target_endianness, is64Bits> { 124*b60a18deSMichael J. Spencer using Elf_Shdr_Base<target_endianness, is64Bits>::sh_entsize; 125*b60a18deSMichael J. Spencer using Elf_Shdr_Base<target_endianness, is64Bits>::sh_size; 126*b60a18deSMichael J. Spencer 127*b60a18deSMichael J. Spencer /// @brief Get the number of entities this section contains if it has any. 128*b60a18deSMichael J. Spencer unsigned getEntityCount() const { 129*b60a18deSMichael J. Spencer if (sh_entsize == 0) 130*b60a18deSMichael J. Spencer return 0; 131*b60a18deSMichael J. Spencer else 132*b60a18deSMichael J. Spencer return sh_size / sh_entsize; 133*b60a18deSMichael J. Spencer } 134*b60a18deSMichael J. Spencer }; 135*b60a18deSMichael J. Spencer } 136*b60a18deSMichael J. Spencer 137*b60a18deSMichael J. Spencer namespace { 138*b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 139*b60a18deSMichael J. Spencer struct Elf_Sym_Base; 140*b60a18deSMichael J. Spencer 141*b60a18deSMichael J. Spencer template<support::endianness target_endianness> 142*b60a18deSMichael J. Spencer struct Elf_Sym_Base<target_endianness, false> { 143*b60a18deSMichael J. Spencer LLVM_ELF_IMPORT_TYPES(target_endianness, false) 144*b60a18deSMichael J. Spencer Elf_Word st_name; // Symbol name (index into string table) 145*b60a18deSMichael J. Spencer Elf_Addr st_value; // Value or address associated with the symbol 146*b60a18deSMichael J. Spencer Elf_Word st_size; // Size of the symbol 147*b60a18deSMichael J. Spencer unsigned char st_info; // Symbol's type and binding attributes 148*b60a18deSMichael J. Spencer unsigned char st_other; // Must be zero; reserved 149*b60a18deSMichael J. Spencer Elf_Half st_shndx; // Which section (header table index) it's defined in 150*b60a18deSMichael J. Spencer }; 151*b60a18deSMichael J. Spencer 152*b60a18deSMichael J. Spencer template<support::endianness target_endianness> 153*b60a18deSMichael J. Spencer struct Elf_Sym_Base<target_endianness, true> { 154*b60a18deSMichael J. Spencer LLVM_ELF_IMPORT_TYPES(target_endianness, true) 155*b60a18deSMichael J. Spencer Elf_Word st_name; // Symbol name (index into string table) 156*b60a18deSMichael J. Spencer unsigned char st_info; // Symbol's type and binding attributes 157*b60a18deSMichael J. Spencer unsigned char st_other; // Must be zero; reserved 158*b60a18deSMichael J. Spencer Elf_Half st_shndx; // Which section (header table index) it's defined in 159*b60a18deSMichael J. Spencer Elf_Addr st_value; // Value or address associated with the symbol 160*b60a18deSMichael J. Spencer Elf_Xword st_size; // Size of the symbol 161*b60a18deSMichael J. Spencer }; 162*b60a18deSMichael J. Spencer 163*b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 164*b60a18deSMichael J. Spencer struct Elf_Sym_Impl : Elf_Sym_Base<target_endianness, is64Bits> { 165*b60a18deSMichael J. Spencer using Elf_Sym_Base<target_endianness, is64Bits>::st_info; 166*b60a18deSMichael J. Spencer 167*b60a18deSMichael J. Spencer // These accessors and mutators correspond to the ELF32_ST_BIND, 168*b60a18deSMichael J. Spencer // ELF32_ST_TYPE, and ELF32_ST_INFO macros defined in the ELF specification: 169*b60a18deSMichael J. Spencer unsigned char getBinding() const { return st_info >> 4; } 170*b60a18deSMichael J. Spencer unsigned char getType() const { return st_info & 0x0f; } 171*b60a18deSMichael J. Spencer void setBinding(unsigned char b) { setBindingAndType(b, getType()); } 172*b60a18deSMichael J. Spencer void setType(unsigned char t) { setBindingAndType(getBinding(), t); } 173*b60a18deSMichael J. Spencer void setBindingAndType(unsigned char b, unsigned char t) { 174*b60a18deSMichael J. Spencer st_info = (b << 4) + (t & 0x0f); 175*b60a18deSMichael J. Spencer } 176*b60a18deSMichael J. Spencer }; 177*b60a18deSMichael J. Spencer } 178*b60a18deSMichael J. Spencer 179*b60a18deSMichael J. Spencer namespace { 180*b60a18deSMichael J. Spencer struct ELFDataRefImpl { 181*b60a18deSMichael J. Spencer uint32_t SymbolIndex; 182*b60a18deSMichael J. Spencer uint16_t SymbolTableSectionIndex; 183*b60a18deSMichael J. Spencer uint16_t Unused; 184*b60a18deSMichael J. Spencer }; 185*b60a18deSMichael J. Spencer } 186*b60a18deSMichael J. Spencer 187*b60a18deSMichael J. Spencer namespace { 188*b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 189*b60a18deSMichael J. Spencer class ELFObjectFile : public ObjectFile { 190*b60a18deSMichael J. Spencer LLVM_ELF_IMPORT_TYPES(target_endianness, is64Bits) 191*b60a18deSMichael J. Spencer 192*b60a18deSMichael J. Spencer typedef Elf_Shdr_Impl<target_endianness, is64Bits> Elf_Shdr; 193*b60a18deSMichael J. Spencer typedef Elf_Sym_Impl<target_endianness, is64Bits> Elf_Sym; 194*b60a18deSMichael J. Spencer 195*b60a18deSMichael J. Spencer struct Elf_Ehdr { 196*b60a18deSMichael J. Spencer unsigned char e_ident[ELF::EI_NIDENT]; // ELF Identification bytes 197*b60a18deSMichael J. Spencer Elf_Half e_type; // Type of file (see ET_*) 198*b60a18deSMichael J. Spencer Elf_Half e_machine; // Required architecture for this file (see EM_*) 199*b60a18deSMichael J. Spencer Elf_Word e_version; // Must be equal to 1 200*b60a18deSMichael J. Spencer Elf_Addr e_entry; // Address to jump to in order to start program 201*b60a18deSMichael J. Spencer Elf_Off e_phoff; // Program header table's file offset, in bytes 202*b60a18deSMichael J. Spencer Elf_Off e_shoff; // Section header table's file offset, in bytes 203*b60a18deSMichael J. Spencer Elf_Word e_flags; // Processor-specific flags 204*b60a18deSMichael J. Spencer Elf_Half e_ehsize; // Size of ELF header, in bytes 205*b60a18deSMichael J. Spencer Elf_Half e_phentsize;// Size of an entry in the program header table 206*b60a18deSMichael J. Spencer Elf_Half e_phnum; // Number of entries in the program header table 207*b60a18deSMichael J. Spencer Elf_Half e_shentsize;// Size of an entry in the section header table 208*b60a18deSMichael J. Spencer Elf_Half e_shnum; // Number of entries in the section header table 209*b60a18deSMichael J. Spencer Elf_Half e_shstrndx; // Section header table index of section name 210*b60a18deSMichael J. Spencer // string table 211*b60a18deSMichael J. Spencer bool checkMagic() const { 212*b60a18deSMichael J. Spencer return (memcmp(e_ident, ELF::ElfMagic, strlen(ELF::ElfMagic))) == 0; 213*b60a18deSMichael J. Spencer } 214*b60a18deSMichael J. Spencer unsigned char getFileClass() const { return e_ident[ELF::EI_CLASS]; } 215*b60a18deSMichael J. Spencer unsigned char getDataEncoding() const { return e_ident[ELF::EI_DATA]; } 216*b60a18deSMichael J. Spencer }; 217*b60a18deSMichael J. Spencer 218*b60a18deSMichael J. Spencer typedef SmallVector<const Elf_Shdr*, 1> SymbolTableSections_t; 219*b60a18deSMichael J. Spencer 220*b60a18deSMichael J. Spencer const Elf_Ehdr *Header; 221*b60a18deSMichael J. Spencer const Elf_Shdr *SectionHeaderTable; 222*b60a18deSMichael J. Spencer const Elf_Shdr *dot_shstrtab_sec; // Section header string table. 223*b60a18deSMichael J. Spencer const Elf_Shdr *dot_strtab_sec; // Symbol header string table. 224*b60a18deSMichael J. Spencer SymbolTableSections_t SymbolTableSections; 225*b60a18deSMichael J. Spencer 226*b60a18deSMichael J. Spencer void validateSymbol(DataRefImpl Symb) const; 227*b60a18deSMichael J. Spencer const Elf_Sym *getSymbol(DataRefImpl Symb) const; 228*b60a18deSMichael J. Spencer const Elf_Shdr *getSection(DataRefImpl index) const; 229*b60a18deSMichael J. Spencer const Elf_Shdr *getSection(uint16_t index) const; 230*b60a18deSMichael J. Spencer const char *getString(uint16_t section, uint32_t offset) const; 231*b60a18deSMichael J. Spencer const char *getString(const Elf_Shdr *section, uint32_t offset) const; 232*b60a18deSMichael J. Spencer 233*b60a18deSMichael J. Spencer protected: 234*b60a18deSMichael J. Spencer virtual SymbolRef getSymbolNext(DataRefImpl Symb) const; 235*b60a18deSMichael J. Spencer virtual StringRef getSymbolName(DataRefImpl Symb) const; 236*b60a18deSMichael J. Spencer virtual uint64_t getSymbolAddress(DataRefImpl Symb) const; 237*b60a18deSMichael J. Spencer virtual uint64_t getSymbolSize(DataRefImpl Symb) const; 238*b60a18deSMichael J. Spencer virtual char getSymbolNMTypeChar(DataRefImpl Symb) const; 239*b60a18deSMichael J. Spencer virtual bool isSymbolInternal(DataRefImpl Symb) const; 240*b60a18deSMichael J. Spencer 241*b60a18deSMichael J. Spencer virtual SectionRef getSectionNext(DataRefImpl Sec) const; 242*b60a18deSMichael J. Spencer virtual StringRef getSectionName(DataRefImpl Sec) const; 243*b60a18deSMichael J. Spencer virtual uint64_t getSectionAddress(DataRefImpl Sec) const; 244*b60a18deSMichael J. Spencer virtual uint64_t getSectionSize(DataRefImpl Sec) const; 245*b60a18deSMichael J. Spencer virtual StringRef getSectionContents(DataRefImpl Sec) const; 246*b60a18deSMichael J. Spencer virtual bool isSectionText(DataRefImpl Sec) const; 247*b60a18deSMichael J. Spencer 248*b60a18deSMichael J. Spencer public: 249*b60a18deSMichael J. Spencer ELFObjectFile(MemoryBuffer *Object); 250*b60a18deSMichael J. Spencer virtual symbol_iterator begin_symbols() const; 251*b60a18deSMichael J. Spencer virtual symbol_iterator end_symbols() const; 252*b60a18deSMichael J. Spencer virtual section_iterator begin_sections() const; 253*b60a18deSMichael J. Spencer virtual section_iterator end_sections() const; 254*b60a18deSMichael J. Spencer 255*b60a18deSMichael J. Spencer virtual uint8_t getBytesInAddress() const; 256*b60a18deSMichael J. Spencer virtual StringRef getFileFormatName() const; 257*b60a18deSMichael J. Spencer virtual unsigned getArch() const; 258*b60a18deSMichael J. Spencer }; 259*b60a18deSMichael J. Spencer } // end namespace 260*b60a18deSMichael J. Spencer 261*b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 262*b60a18deSMichael J. Spencer void ELFObjectFile<target_endianness, is64Bits> 263*b60a18deSMichael J. Spencer ::validateSymbol(DataRefImpl Symb) const { 264*b60a18deSMichael J. Spencer const ELFDataRefImpl SymbolData = *reinterpret_cast<ELFDataRefImpl *>(&Symb); 265*b60a18deSMichael J. Spencer const Elf_Sym *symb = getSymbol(Symb); 266*b60a18deSMichael J. Spencer const Elf_Shdr *SymbolTableSection = 267*b60a18deSMichael J. Spencer SymbolTableSections[SymbolData.SymbolTableSectionIndex]; 268*b60a18deSMichael J. Spencer // FIXME: We really need to do proper error handling in the case of an invalid 269*b60a18deSMichael J. Spencer // input file. Because we don't use exceptions, I think we'll just pass 270*b60a18deSMichael J. Spencer // an error object around. 271*b60a18deSMichael J. Spencer if (!( symb 272*b60a18deSMichael J. Spencer && SymbolTableSection 273*b60a18deSMichael J. Spencer && symb >= (const Elf_Sym*)(base 274*b60a18deSMichael J. Spencer + SymbolTableSection->sh_offset) 275*b60a18deSMichael J. Spencer && symb < (const Elf_Sym*)(base 276*b60a18deSMichael J. Spencer + SymbolTableSection->sh_offset 277*b60a18deSMichael J. Spencer + SymbolTableSection->sh_size))) 278*b60a18deSMichael J. Spencer // FIXME: Proper error handling. 279*b60a18deSMichael J. Spencer report_fatal_error("Symb must point to a valid symbol!"); 280*b60a18deSMichael J. Spencer } 281*b60a18deSMichael J. Spencer 282*b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 283*b60a18deSMichael J. Spencer SymbolRef ELFObjectFile<target_endianness, is64Bits> 284*b60a18deSMichael J. Spencer ::getSymbolNext(DataRefImpl Symb) const { 285*b60a18deSMichael J. Spencer validateSymbol(Symb); 286*b60a18deSMichael J. Spencer ELFDataRefImpl &SymbolData = *reinterpret_cast<ELFDataRefImpl *>(&Symb); 287*b60a18deSMichael J. Spencer const Elf_Shdr *SymbolTableSection = 288*b60a18deSMichael J. Spencer SymbolTableSections[SymbolData.SymbolTableSectionIndex]; 289*b60a18deSMichael J. Spencer 290*b60a18deSMichael J. Spencer ++SymbolData.SymbolIndex; 291*b60a18deSMichael J. Spencer // Check to see if we are at the end of this symbol table. 292*b60a18deSMichael J. Spencer if (SymbolData.SymbolIndex >= SymbolTableSection->getEntityCount()) { 293*b60a18deSMichael J. Spencer // We are at the end. If there are other symbol tables, jump to them. 294*b60a18deSMichael J. Spencer ++SymbolData.SymbolTableSectionIndex; 295*b60a18deSMichael J. Spencer SymbolData.SymbolIndex = 1; // The 0th symbol in ELF is fake. 296*b60a18deSMichael J. Spencer // Otherwise return the terminator. 297*b60a18deSMichael J. Spencer if (SymbolData.SymbolTableSectionIndex >= SymbolTableSections.size()) { 298*b60a18deSMichael J. Spencer SymbolData.SymbolIndex = std::numeric_limits<uint32_t>::max(); 299*b60a18deSMichael J. Spencer SymbolData.SymbolTableSectionIndex = std::numeric_limits<uint32_t>::max(); 300*b60a18deSMichael J. Spencer } 301*b60a18deSMichael J. Spencer } 302*b60a18deSMichael J. Spencer 303*b60a18deSMichael J. Spencer return SymbolRef(Symb, this); 304*b60a18deSMichael J. Spencer } 305*b60a18deSMichael J. Spencer 306*b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 307*b60a18deSMichael J. Spencer StringRef ELFObjectFile<target_endianness, is64Bits> 308*b60a18deSMichael J. Spencer ::getSymbolName(DataRefImpl Symb) const { 309*b60a18deSMichael J. Spencer validateSymbol(Symb); 310*b60a18deSMichael J. Spencer const Elf_Sym *symb = getSymbol(Symb); 311*b60a18deSMichael J. Spencer if (symb->st_name == 0) { 312*b60a18deSMichael J. Spencer const Elf_Shdr *section = getSection(symb->st_shndx); 313*b60a18deSMichael J. Spencer if (!section) 314*b60a18deSMichael J. Spencer return ""; 315*b60a18deSMichael J. Spencer return getString(dot_shstrtab_sec, section->sh_name); 316*b60a18deSMichael J. Spencer } 317*b60a18deSMichael J. Spencer 318*b60a18deSMichael J. Spencer // Use the default symbol table name section. 319*b60a18deSMichael J. Spencer return getString(dot_strtab_sec, symb->st_name); 320*b60a18deSMichael J. Spencer } 321*b60a18deSMichael J. Spencer 322*b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 323*b60a18deSMichael J. Spencer uint64_t ELFObjectFile<target_endianness, is64Bits> 324*b60a18deSMichael J. Spencer ::getSymbolAddress(DataRefImpl Symb) const { 325*b60a18deSMichael J. Spencer validateSymbol(Symb); 326*b60a18deSMichael J. Spencer const Elf_Sym *symb = getSymbol(Symb); 327*b60a18deSMichael J. Spencer const Elf_Shdr *Section; 328*b60a18deSMichael J. Spencer switch (symb->st_shndx) { 329*b60a18deSMichael J. Spencer case ELF::SHN_COMMON: 330*b60a18deSMichael J. Spencer // Undefined symbols have no address yet. 331*b60a18deSMichael J. Spencer case ELF::SHN_UNDEF: return UnknownAddressOrSize; 332*b60a18deSMichael J. Spencer case ELF::SHN_ABS: return symb->st_value; 333*b60a18deSMichael J. Spencer default: Section = getSection(symb->st_shndx); 334*b60a18deSMichael J. Spencer } 335*b60a18deSMichael J. Spencer 336*b60a18deSMichael J. Spencer switch (symb->getType()) { 337*b60a18deSMichael J. Spencer case ELF::STT_SECTION: return Section ? Section->sh_addr 338*b60a18deSMichael J. Spencer : UnknownAddressOrSize; 339*b60a18deSMichael J. Spencer case ELF::STT_FUNC: 340*b60a18deSMichael J. Spencer case ELF::STT_OBJECT: 341*b60a18deSMichael J. Spencer case ELF::STT_NOTYPE: 342*b60a18deSMichael J. Spencer return symb->st_value; 343*b60a18deSMichael J. Spencer default: return UnknownAddressOrSize; 344*b60a18deSMichael J. Spencer } 345*b60a18deSMichael J. Spencer } 346*b60a18deSMichael J. Spencer 347*b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 348*b60a18deSMichael J. Spencer uint64_t ELFObjectFile<target_endianness, is64Bits> 349*b60a18deSMichael J. Spencer ::getSymbolSize(DataRefImpl Symb) const { 350*b60a18deSMichael J. Spencer validateSymbol(Symb); 351*b60a18deSMichael J. Spencer const Elf_Sym *symb = getSymbol(Symb); 352*b60a18deSMichael J. Spencer if (symb->st_size == 0) 353*b60a18deSMichael J. Spencer return UnknownAddressOrSize; 354*b60a18deSMichael J. Spencer return symb->st_size; 355*b60a18deSMichael J. Spencer } 356*b60a18deSMichael J. Spencer 357*b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 358*b60a18deSMichael J. Spencer char ELFObjectFile<target_endianness, is64Bits> 359*b60a18deSMichael J. Spencer ::getSymbolNMTypeChar(DataRefImpl Symb) const { 360*b60a18deSMichael J. Spencer validateSymbol(Symb); 361*b60a18deSMichael J. Spencer const Elf_Sym *symb = getSymbol(Symb); 362*b60a18deSMichael J. Spencer const Elf_Shdr *Section = getSection(symb->st_shndx); 363*b60a18deSMichael J. Spencer 364*b60a18deSMichael J. Spencer char ret = '?'; 365*b60a18deSMichael J. Spencer 366*b60a18deSMichael J. Spencer if (Section) { 367*b60a18deSMichael J. Spencer switch (Section->sh_type) { 368*b60a18deSMichael J. Spencer case ELF::SHT_PROGBITS: 369*b60a18deSMichael J. Spencer case ELF::SHT_DYNAMIC: 370*b60a18deSMichael J. Spencer switch (Section->sh_flags) { 371*b60a18deSMichael J. Spencer case (ELF::SHF_ALLOC | ELF::SHF_EXECINSTR): 372*b60a18deSMichael J. Spencer ret = 't'; break; 373*b60a18deSMichael J. Spencer case (ELF::SHF_ALLOC | ELF::SHF_WRITE): 374*b60a18deSMichael J. Spencer ret = 'd'; break; 375*b60a18deSMichael J. Spencer case ELF::SHF_ALLOC: 376*b60a18deSMichael J. Spencer case (ELF::SHF_ALLOC | ELF::SHF_MERGE): 377*b60a18deSMichael J. Spencer case (ELF::SHF_ALLOC | ELF::SHF_MERGE | ELF::SHF_STRINGS): 378*b60a18deSMichael J. Spencer ret = 'r'; break; 379*b60a18deSMichael J. Spencer } 380*b60a18deSMichael J. Spencer break; 381*b60a18deSMichael J. Spencer case ELF::SHT_NOBITS: ret = 'b'; 382*b60a18deSMichael J. Spencer } 383*b60a18deSMichael J. Spencer } 384*b60a18deSMichael J. Spencer 385*b60a18deSMichael J. Spencer switch (symb->st_shndx) { 386*b60a18deSMichael J. Spencer case ELF::SHN_UNDEF: 387*b60a18deSMichael J. Spencer if (ret == '?') 388*b60a18deSMichael J. Spencer ret = 'U'; 389*b60a18deSMichael J. Spencer break; 390*b60a18deSMichael J. Spencer case ELF::SHN_ABS: ret = 'a'; break; 391*b60a18deSMichael J. Spencer case ELF::SHN_COMMON: ret = 'c'; break; 392*b60a18deSMichael J. Spencer } 393*b60a18deSMichael J. Spencer 394*b60a18deSMichael J. Spencer switch (symb->getBinding()) { 395*b60a18deSMichael J. Spencer case ELF::STB_GLOBAL: ret = ::toupper(ret); break; 396*b60a18deSMichael J. Spencer case ELF::STB_WEAK: 397*b60a18deSMichael J. Spencer if (symb->st_shndx == ELF::SHN_UNDEF) 398*b60a18deSMichael J. Spencer ret = 'w'; 399*b60a18deSMichael J. Spencer else 400*b60a18deSMichael J. Spencer if (symb->getType() == ELF::STT_OBJECT) 401*b60a18deSMichael J. Spencer ret = 'V'; 402*b60a18deSMichael J. Spencer else 403*b60a18deSMichael J. Spencer ret = 'W'; 404*b60a18deSMichael J. Spencer } 405*b60a18deSMichael J. Spencer 406*b60a18deSMichael J. Spencer if (ret == '?' && symb->getType() == ELF::STT_SECTION) 407*b60a18deSMichael J. Spencer return StringSwitch<char>(getSymbolName(Symb)) 408*b60a18deSMichael J. Spencer .StartsWith(".debug", 'N') 409*b60a18deSMichael J. Spencer .StartsWith(".note", 'n'); 410*b60a18deSMichael J. Spencer 411*b60a18deSMichael J. Spencer return ret; 412*b60a18deSMichael J. Spencer } 413*b60a18deSMichael J. Spencer 414*b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 415*b60a18deSMichael J. Spencer bool ELFObjectFile<target_endianness, is64Bits> 416*b60a18deSMichael J. Spencer ::isSymbolInternal(DataRefImpl Symb) const { 417*b60a18deSMichael J. Spencer validateSymbol(Symb); 418*b60a18deSMichael J. Spencer const Elf_Sym *symb = getSymbol(Symb); 419*b60a18deSMichael J. Spencer 420*b60a18deSMichael J. Spencer if ( symb->getType() == ELF::STT_FILE 421*b60a18deSMichael J. Spencer || symb->getType() == ELF::STT_SECTION) 422*b60a18deSMichael J. Spencer return true; 423*b60a18deSMichael J. Spencer return false; 424*b60a18deSMichael J. Spencer } 425*b60a18deSMichael J. Spencer 426*b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 427*b60a18deSMichael J. Spencer SectionRef ELFObjectFile<target_endianness, is64Bits> 428*b60a18deSMichael J. Spencer ::getSectionNext(DataRefImpl Sec) const { 429*b60a18deSMichael J. Spencer const uint8_t *sec = *reinterpret_cast<const uint8_t **>(&Sec); 430*b60a18deSMichael J. Spencer sec += Header->e_shentsize; 431*b60a18deSMichael J. Spencer return SectionRef(DataRefImpl(sec), this); 432*b60a18deSMichael J. Spencer } 433*b60a18deSMichael J. Spencer 434*b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 435*b60a18deSMichael J. Spencer StringRef ELFObjectFile<target_endianness, is64Bits> 436*b60a18deSMichael J. Spencer ::getSectionName(DataRefImpl Sec) const { 437*b60a18deSMichael J. Spencer const Elf_Shdr *sec = 438*b60a18deSMichael J. Spencer *reinterpret_cast<const Elf_Shdr **>(&Sec); 439*b60a18deSMichael J. Spencer return StringRef(getString(dot_shstrtab_sec, sec->sh_name)); 440*b60a18deSMichael J. Spencer } 441*b60a18deSMichael J. Spencer 442*b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 443*b60a18deSMichael J. Spencer uint64_t ELFObjectFile<target_endianness, is64Bits> 444*b60a18deSMichael J. Spencer ::getSectionAddress(DataRefImpl Sec) const { 445*b60a18deSMichael J. Spencer const Elf_Shdr *sec = 446*b60a18deSMichael J. Spencer *reinterpret_cast<const Elf_Shdr **>(&Sec); 447*b60a18deSMichael J. Spencer return sec->sh_addr; 448*b60a18deSMichael J. Spencer } 449*b60a18deSMichael J. Spencer 450*b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 451*b60a18deSMichael J. Spencer uint64_t ELFObjectFile<target_endianness, is64Bits> 452*b60a18deSMichael J. Spencer ::getSectionSize(DataRefImpl Sec) const { 453*b60a18deSMichael J. Spencer const Elf_Shdr *sec = 454*b60a18deSMichael J. Spencer *reinterpret_cast<const Elf_Shdr **>(&Sec); 455*b60a18deSMichael J. Spencer return sec->sh_size; 456*b60a18deSMichael J. Spencer } 457*b60a18deSMichael J. Spencer 458*b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 459*b60a18deSMichael J. Spencer StringRef ELFObjectFile<target_endianness, is64Bits> 460*b60a18deSMichael J. Spencer ::getSectionContents(DataRefImpl Sec) const { 461*b60a18deSMichael J. Spencer const Elf_Shdr *sec = 462*b60a18deSMichael J. Spencer *reinterpret_cast<const Elf_Shdr **>(&Sec); 463*b60a18deSMichael J. Spencer const char *start = (char*)base + sec->sh_offset; 464*b60a18deSMichael J. Spencer return StringRef(start, sec->sh_size); 465*b60a18deSMichael J. Spencer } 466*b60a18deSMichael J. Spencer 467*b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 468*b60a18deSMichael J. Spencer bool ELFObjectFile<target_endianness, is64Bits> 469*b60a18deSMichael J. Spencer ::isSectionText(DataRefImpl Sec) const { 470*b60a18deSMichael J. Spencer const Elf_Shdr *sec = 471*b60a18deSMichael J. Spencer *reinterpret_cast<const Elf_Shdr **>(&Sec); 472*b60a18deSMichael J. Spencer if (sec->sh_flags & ELF::SHF_EXECINSTR) 473*b60a18deSMichael J. Spencer return true; 474*b60a18deSMichael J. Spencer return false; 475*b60a18deSMichael J. Spencer } 476*b60a18deSMichael J. Spencer 477*b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 478*b60a18deSMichael J. Spencer ELFObjectFile<target_endianness, is64Bits>::ELFObjectFile(MemoryBuffer *Object) 479*b60a18deSMichael J. Spencer : ObjectFile(Object) 480*b60a18deSMichael J. Spencer , SectionHeaderTable(0) 481*b60a18deSMichael J. Spencer , dot_shstrtab_sec(0) 482*b60a18deSMichael J. Spencer , dot_strtab_sec(0) { 483*b60a18deSMichael J. Spencer Header = reinterpret_cast<const Elf_Ehdr *>(base); 484*b60a18deSMichael J. Spencer 485*b60a18deSMichael J. Spencer if (Header->e_shoff == 0) 486*b60a18deSMichael J. Spencer return; 487*b60a18deSMichael J. Spencer 488*b60a18deSMichael J. Spencer SectionHeaderTable = 489*b60a18deSMichael J. Spencer reinterpret_cast<const Elf_Shdr *>(base + Header->e_shoff); 490*b60a18deSMichael J. Spencer uint32_t SectionTableSize = Header->e_shnum * Header->e_shentsize; 491*b60a18deSMichael J. Spencer if (!( (const uint8_t *)SectionHeaderTable + SectionTableSize 492*b60a18deSMichael J. Spencer <= base + MapFile->getBufferSize())) 493*b60a18deSMichael J. Spencer // FIXME: Proper error handling. 494*b60a18deSMichael J. Spencer report_fatal_error("Section table goes past end of file!"); 495*b60a18deSMichael J. Spencer 496*b60a18deSMichael J. Spencer 497*b60a18deSMichael J. Spencer // To find the symbol tables we walk the section table to find SHT_STMTAB. 498*b60a18deSMichael J. Spencer for (const char *i = reinterpret_cast<const char *>(SectionHeaderTable), 499*b60a18deSMichael J. Spencer *e = i + Header->e_shnum * Header->e_shentsize; 500*b60a18deSMichael J. Spencer i != e; i += Header->e_shentsize) { 501*b60a18deSMichael J. Spencer const Elf_Shdr *sh = reinterpret_cast<const Elf_Shdr*>(i); 502*b60a18deSMichael J. Spencer if (sh->sh_type == ELF::SHT_SYMTAB) { 503*b60a18deSMichael J. Spencer SymbolTableSections.push_back(sh); 504*b60a18deSMichael J. Spencer } 505*b60a18deSMichael J. Spencer } 506*b60a18deSMichael J. Spencer 507*b60a18deSMichael J. Spencer // Get string table sections. 508*b60a18deSMichael J. Spencer dot_shstrtab_sec = getSection(Header->e_shstrndx); 509*b60a18deSMichael J. Spencer if (dot_shstrtab_sec) { 510*b60a18deSMichael J. Spencer // Verify that the last byte in the string table in a null. 511*b60a18deSMichael J. Spencer if (((const char*)base + dot_shstrtab_sec->sh_offset) 512*b60a18deSMichael J. Spencer [dot_shstrtab_sec->sh_size - 1] != 0) 513*b60a18deSMichael J. Spencer // FIXME: Proper error handling. 514*b60a18deSMichael J. Spencer report_fatal_error("String table must end with a null terminator!"); 515*b60a18deSMichael J. Spencer } 516*b60a18deSMichael J. Spencer 517*b60a18deSMichael J. Spencer // Merge this into the above loop. 518*b60a18deSMichael J. Spencer for (const char *i = reinterpret_cast<const char *>(SectionHeaderTable), 519*b60a18deSMichael J. Spencer *e = i + Header->e_shnum * Header->e_shentsize; 520*b60a18deSMichael J. Spencer i != e; i += Header->e_shentsize) { 521*b60a18deSMichael J. Spencer const Elf_Shdr *sh = reinterpret_cast<const Elf_Shdr*>(i); 522*b60a18deSMichael J. Spencer if (sh->sh_type == ELF::SHT_STRTAB) { 523*b60a18deSMichael J. Spencer StringRef SectionName(getString(dot_shstrtab_sec, sh->sh_name)); 524*b60a18deSMichael J. Spencer if (SectionName == ".strtab") { 525*b60a18deSMichael J. Spencer if (dot_strtab_sec != 0) 526*b60a18deSMichael J. Spencer // FIXME: Proper error handling. 527*b60a18deSMichael J. Spencer report_fatal_error("Already found section named .strtab!"); 528*b60a18deSMichael J. Spencer dot_strtab_sec = sh; 529*b60a18deSMichael J. Spencer const char *dot_strtab = (const char*)base + sh->sh_offset; 530*b60a18deSMichael J. Spencer if (dot_strtab[sh->sh_size - 1] != 0) 531*b60a18deSMichael J. Spencer // FIXME: Proper error handling. 532*b60a18deSMichael J. Spencer report_fatal_error("String table must end with a null terminator!"); 533*b60a18deSMichael J. Spencer } 534*b60a18deSMichael J. Spencer } 535*b60a18deSMichael J. Spencer } 536*b60a18deSMichael J. Spencer } 537*b60a18deSMichael J. Spencer 538*b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 539*b60a18deSMichael J. Spencer ObjectFile::symbol_iterator ELFObjectFile<target_endianness, is64Bits> 540*b60a18deSMichael J. Spencer ::begin_symbols() const { 541*b60a18deSMichael J. Spencer ELFDataRefImpl SymbolData; 542*b60a18deSMichael J. Spencer memset(&SymbolData, 0, sizeof(SymbolData)); 543*b60a18deSMichael J. Spencer if (SymbolTableSections.size() == 0) { 544*b60a18deSMichael J. Spencer SymbolData.SymbolIndex = std::numeric_limits<uint32_t>::max(); 545*b60a18deSMichael J. Spencer SymbolData.SymbolTableSectionIndex = std::numeric_limits<uint32_t>::max(); 546*b60a18deSMichael J. Spencer } else { 547*b60a18deSMichael J. Spencer SymbolData.SymbolIndex = 1; // The 0th symbol in ELF is fake. 548*b60a18deSMichael J. Spencer SymbolData.SymbolTableSectionIndex = 0; 549*b60a18deSMichael J. Spencer } 550*b60a18deSMichael J. Spencer return symbol_iterator( 551*b60a18deSMichael J. Spencer SymbolRef(DataRefImpl(*reinterpret_cast<DataRefImpl*>(&SymbolData)), this)); 552*b60a18deSMichael J. Spencer } 553*b60a18deSMichael J. Spencer 554*b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 555*b60a18deSMichael J. Spencer ObjectFile::symbol_iterator ELFObjectFile<target_endianness, is64Bits> 556*b60a18deSMichael J. Spencer ::end_symbols() const { 557*b60a18deSMichael J. Spencer ELFDataRefImpl SymbolData; 558*b60a18deSMichael J. Spencer memset(&SymbolData, 0, sizeof(SymbolData)); 559*b60a18deSMichael J. Spencer SymbolData.SymbolIndex = std::numeric_limits<uint32_t>::max(); 560*b60a18deSMichael J. Spencer SymbolData.SymbolTableSectionIndex = std::numeric_limits<uint32_t>::max(); 561*b60a18deSMichael J. Spencer return symbol_iterator( 562*b60a18deSMichael J. Spencer SymbolRef(DataRefImpl(*reinterpret_cast<DataRefImpl*>(&SymbolData)), this)); 563*b60a18deSMichael J. Spencer } 564*b60a18deSMichael J. Spencer 565*b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 566*b60a18deSMichael J. Spencer ObjectFile::section_iterator ELFObjectFile<target_endianness, is64Bits> 567*b60a18deSMichael J. Spencer ::begin_sections() const { 568*b60a18deSMichael J. Spencer return section_iterator( 569*b60a18deSMichael J. Spencer SectionRef(DataRefImpl(base + Header->e_shoff), this)); 570*b60a18deSMichael J. Spencer } 571*b60a18deSMichael J. Spencer 572*b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 573*b60a18deSMichael J. Spencer ObjectFile::section_iterator ELFObjectFile<target_endianness, is64Bits> 574*b60a18deSMichael J. Spencer ::end_sections() const { 575*b60a18deSMichael J. Spencer return section_iterator( 576*b60a18deSMichael J. Spencer SectionRef(DataRefImpl(base 577*b60a18deSMichael J. Spencer + Header->e_shoff 578*b60a18deSMichael J. Spencer + (Header->e_shentsize * Header->e_shnum)), this)); 579*b60a18deSMichael J. Spencer } 580*b60a18deSMichael J. Spencer 581*b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 582*b60a18deSMichael J. Spencer uint8_t ELFObjectFile<target_endianness, is64Bits>::getBytesInAddress() const { 583*b60a18deSMichael J. Spencer return 4; 584*b60a18deSMichael J. Spencer } 585*b60a18deSMichael J. Spencer 586*b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 587*b60a18deSMichael J. Spencer StringRef ELFObjectFile<target_endianness, is64Bits> 588*b60a18deSMichael J. Spencer ::getFileFormatName() const { 589*b60a18deSMichael J. Spencer switch(Header->e_ident[ELF::EI_CLASS]) { 590*b60a18deSMichael J. Spencer case ELF::ELFCLASS32: 591*b60a18deSMichael J. Spencer switch(Header->e_machine) { 592*b60a18deSMichael J. Spencer case ELF::EM_386: 593*b60a18deSMichael J. Spencer return "ELF32-i386"; 594*b60a18deSMichael J. Spencer case ELF::EM_X86_64: 595*b60a18deSMichael J. Spencer return "ELF32-x86-64"; 596*b60a18deSMichael J. Spencer default: 597*b60a18deSMichael J. Spencer return "ELF32-unknown"; 598*b60a18deSMichael J. Spencer } 599*b60a18deSMichael J. Spencer case ELF::ELFCLASS64: 600*b60a18deSMichael J. Spencer switch(Header->e_machine) { 601*b60a18deSMichael J. Spencer case ELF::EM_386: 602*b60a18deSMichael J. Spencer return "ELF64-i386"; 603*b60a18deSMichael J. Spencer case ELF::EM_X86_64: 604*b60a18deSMichael J. Spencer return "ELF64-x86-64"; 605*b60a18deSMichael J. Spencer default: 606*b60a18deSMichael J. Spencer return "ELF64-unknown"; 607*b60a18deSMichael J. Spencer } 608*b60a18deSMichael J. Spencer default: 609*b60a18deSMichael J. Spencer // FIXME: Proper error handling. 610*b60a18deSMichael J. Spencer report_fatal_error("Invalid ELFCLASS!"); 611*b60a18deSMichael J. Spencer } 612*b60a18deSMichael J. Spencer } 613*b60a18deSMichael J. Spencer 614*b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 615*b60a18deSMichael J. Spencer unsigned ELFObjectFile<target_endianness, is64Bits>::getArch() const { 616*b60a18deSMichael J. Spencer switch(Header->e_machine) { 617*b60a18deSMichael J. Spencer case ELF::EM_386: 618*b60a18deSMichael J. Spencer return Triple::x86; 619*b60a18deSMichael J. Spencer case ELF::EM_X86_64: 620*b60a18deSMichael J. Spencer return Triple::x86_64; 621*b60a18deSMichael J. Spencer default: 622*b60a18deSMichael J. Spencer return Triple::UnknownArch; 623*b60a18deSMichael J. Spencer } 624*b60a18deSMichael J. Spencer } 625*b60a18deSMichael J. Spencer 626*b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 627*b60a18deSMichael J. Spencer const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Sym * 628*b60a18deSMichael J. Spencer ELFObjectFile<target_endianness, is64Bits>::getSymbol(DataRefImpl Symb) const { 629*b60a18deSMichael J. Spencer const ELFDataRefImpl SymbolData = *reinterpret_cast<ELFDataRefImpl *>(&Symb); 630*b60a18deSMichael J. Spencer const Elf_Shdr *sec = 631*b60a18deSMichael J. Spencer SymbolTableSections[SymbolData.SymbolTableSectionIndex]; 632*b60a18deSMichael J. Spencer return reinterpret_cast<const Elf_Sym *>( 633*b60a18deSMichael J. Spencer base 634*b60a18deSMichael J. Spencer + sec->sh_offset 635*b60a18deSMichael J. Spencer + (SymbolData.SymbolIndex * sec->sh_entsize)); 636*b60a18deSMichael J. Spencer } 637*b60a18deSMichael J. Spencer 638*b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 639*b60a18deSMichael J. Spencer const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Shdr * 640*b60a18deSMichael J. Spencer ELFObjectFile<target_endianness, is64Bits>::getSection(DataRefImpl Symb) const { 641*b60a18deSMichael J. Spencer const ELFDataRefImpl SymbolData = *reinterpret_cast<ELFDataRefImpl *>(&Symb); 642*b60a18deSMichael J. Spencer const Elf_Shdr *sec = getSection(SymbolData.SymbolTableSectionIndex); 643*b60a18deSMichael J. Spencer if (sec->sh_type != ELF::SHT_SYMTAB) 644*b60a18deSMichael J. Spencer // FIXME: Proper error handling. 645*b60a18deSMichael J. Spencer report_fatal_error("Invalid symbol table section!"); 646*b60a18deSMichael J. Spencer return sec; 647*b60a18deSMichael J. Spencer } 648*b60a18deSMichael J. Spencer 649*b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 650*b60a18deSMichael J. Spencer const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Shdr * 651*b60a18deSMichael J. Spencer ELFObjectFile<target_endianness, is64Bits>::getSection(uint16_t index) const { 652*b60a18deSMichael J. Spencer if (index == 0 || index >= ELF::SHN_LORESERVE) 653*b60a18deSMichael J. Spencer return 0; 654*b60a18deSMichael J. Spencer if (!SectionHeaderTable || index >= Header->e_shnum) 655*b60a18deSMichael J. Spencer // FIXME: Proper error handling. 656*b60a18deSMichael J. Spencer report_fatal_error("Invalid section index!"); 657*b60a18deSMichael J. Spencer 658*b60a18deSMichael J. Spencer return reinterpret_cast<const Elf_Shdr *>( 659*b60a18deSMichael J. Spencer reinterpret_cast<const char *>(SectionHeaderTable) 660*b60a18deSMichael J. Spencer + (index * Header->e_shentsize)); 661*b60a18deSMichael J. Spencer } 662*b60a18deSMichael J. Spencer 663*b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 664*b60a18deSMichael J. Spencer const char *ELFObjectFile<target_endianness, is64Bits> 665*b60a18deSMichael J. Spencer ::getString(uint16_t section, 666*b60a18deSMichael J. Spencer ELF::Elf32_Word offset) const { 667*b60a18deSMichael J. Spencer return getString(getSection(section), offset); 668*b60a18deSMichael J. Spencer } 669*b60a18deSMichael J. Spencer 670*b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits> 671*b60a18deSMichael J. Spencer const char *ELFObjectFile<target_endianness, is64Bits> 672*b60a18deSMichael J. Spencer ::getString(const Elf_Shdr *section, 673*b60a18deSMichael J. Spencer ELF::Elf32_Word offset) const { 674*b60a18deSMichael J. Spencer assert(section && section->sh_type == ELF::SHT_STRTAB && "Invalid section!"); 675*b60a18deSMichael J. Spencer if (offset >= section->sh_size) 676*b60a18deSMichael J. Spencer // FIXME: Proper error handling. 677*b60a18deSMichael J. Spencer report_fatal_error("Sybol name offset outside of string table!"); 678*b60a18deSMichael J. Spencer return (const char *)base + section->sh_offset + offset; 679*b60a18deSMichael J. Spencer } 680*b60a18deSMichael J. Spencer 681*b60a18deSMichael J. Spencer // EI_CLASS, EI_DATA. 682*b60a18deSMichael J. Spencer static std::pair<unsigned char, unsigned char> 683*b60a18deSMichael J. Spencer getElfArchType(MemoryBuffer *Object) { 684*b60a18deSMichael J. Spencer if (Object->getBufferSize() < ELF::EI_NIDENT) 685*b60a18deSMichael J. Spencer return std::make_pair((uint8_t)ELF::ELFCLASSNONE,(uint8_t)ELF::ELFDATANONE); 686*b60a18deSMichael J. Spencer return std::make_pair( (uint8_t)Object->getBufferStart()[ELF::EI_CLASS] 687*b60a18deSMichael J. Spencer , (uint8_t)Object->getBufferStart()[ELF::EI_DATA]); 688*b60a18deSMichael J. Spencer } 689*b60a18deSMichael J. Spencer 690*b60a18deSMichael J. Spencer namespace llvm { 691*b60a18deSMichael J. Spencer 692*b60a18deSMichael J. Spencer ObjectFile *ObjectFile::createELFObjectFile(MemoryBuffer *Object) { 693*b60a18deSMichael J. Spencer std::pair<unsigned char, unsigned char> Ident = getElfArchType(Object); 694*b60a18deSMichael J. Spencer if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2LSB) 695*b60a18deSMichael J. Spencer return new ELFObjectFile<support::little, false>(Object); 696*b60a18deSMichael J. Spencer else if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2MSB) 697*b60a18deSMichael J. Spencer return new ELFObjectFile<support::big, false>(Object); 698*b60a18deSMichael J. Spencer else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2LSB) 699*b60a18deSMichael J. Spencer return new ELFObjectFile<support::little, true>(Object); 700*b60a18deSMichael J. Spencer else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2MSB) 701*b60a18deSMichael J. Spencer return new ELFObjectFile<support::big, true>(Object); 702*b60a18deSMichael J. Spencer // FIXME: Proper error handling. 703*b60a18deSMichael J. Spencer report_fatal_error("Not an ELF object file!"); 704*b60a18deSMichael J. Spencer } 705*b60a18deSMichael J. Spencer 706*b60a18deSMichael J. Spencer } // end namespace llvm 707