X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FObject%2FELFObjectFile.cpp;h=8ccb2538ac78d06abb8a13b194f1e4eeb4b1357a;hb=ec8aeb0bc1648fdc81b838ab8e35ee06c44519c3;hp=1c4dceaa35f59c33bdd685625882c4d3f1e6f195;hpb=69aec36f9b3129ba6eb83d64cde31c3d86d6d39a;p=oota-llvm.git diff --git a/lib/Object/ELFObjectFile.cpp b/lib/Object/ELFObjectFile.cpp index 1c4dceaa35f..8ccb2538ac7 100644 --- a/lib/Object/ELFObjectFile.cpp +++ b/lib/Object/ELFObjectFile.cpp @@ -7,684 +7,75 @@ // //===----------------------------------------------------------------------===// // -// This file defines the ELFObjectFile class. +// Part of the ELFObjectFile class implementation. // //===----------------------------------------------------------------------===// -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringSwitch.h" -#include "llvm/ADT/Triple.h" -#include "llvm/Object/ObjectFile.h" -#include "llvm/Support/ELF.h" -#include "llvm/Support/Endian.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/MemoryBuffer.h" -#include -#include +#include "llvm/Object/ELFObjectFile.h" +#include "llvm/Support/MathExtras.h" -using namespace llvm; +namespace llvm { using namespace object; -// Templates to choose Elf_Addr and Elf_Off depending on is64Bits. -namespace { -template -struct ELFDataTypeTypedefHelperCommon { - typedef support::detail::packed_endian_specific_integral - Elf_Half; - typedef support::detail::packed_endian_specific_integral - Elf_Word; - typedef support::detail::packed_endian_specific_integral - Elf_Sword; - typedef support::detail::packed_endian_specific_integral - Elf_Xword; - typedef support::detail::packed_endian_specific_integral - Elf_Sxword; -}; -} - -namespace { -template -struct ELFDataTypeTypedefHelper; - -/// ELF 32bit types. -template -struct ELFDataTypeTypedefHelper - : ELFDataTypeTypedefHelperCommon { - typedef support::detail::packed_endian_specific_integral - Elf_Addr; - typedef support::detail::packed_endian_specific_integral - Elf_Off; -}; - -/// ELF 64bit types. -template -struct ELFDataTypeTypedefHelper - : ELFDataTypeTypedefHelperCommon{ - typedef support::detail::packed_endian_specific_integral - Elf_Addr; - typedef support::detail::packed_endian_specific_integral - Elf_Off; -}; -} - -// I really don't like doing this, but the alternative is copypasta. -#define LLVM_ELF_IMPORT_TYPES(target_endianness, is64Bits) \ -typedef typename \ - ELFDataTypeTypedefHelper::Elf_Addr Elf_Addr; \ -typedef typename \ - ELFDataTypeTypedefHelper::Elf_Off Elf_Off; \ -typedef typename \ - ELFDataTypeTypedefHelper::Elf_Half Elf_Half; \ -typedef typename \ - ELFDataTypeTypedefHelper::Elf_Word Elf_Word; \ -typedef typename \ - ELFDataTypeTypedefHelper::Elf_Sword Elf_Sword; \ -typedef typename \ - ELFDataTypeTypedefHelper::Elf_Xword Elf_Xword; \ -typedef typename \ - ELFDataTypeTypedefHelper::Elf_Sxword Elf_Sxword; - - // Section header. -namespace { -template -struct Elf_Shdr_Base; - -template -struct Elf_Shdr_Base { - LLVM_ELF_IMPORT_TYPES(target_endianness, false) - Elf_Word sh_name; // Section name (index into string table) - Elf_Word sh_type; // Section type (SHT_*) - Elf_Word sh_flags; // Section flags (SHF_*) - Elf_Addr sh_addr; // Address where section is to be loaded - Elf_Off sh_offset; // File offset of section data, in bytes - Elf_Word sh_size; // Size of section, in bytes - Elf_Word sh_link; // Section type-specific header table index link - Elf_Word sh_info; // Section type-specific extra information - Elf_Word sh_addralign;// Section address alignment - Elf_Word sh_entsize; // Size of records contained within the section -}; - -template -struct Elf_Shdr_Base { - LLVM_ELF_IMPORT_TYPES(target_endianness, true) - Elf_Word sh_name; // Section name (index into string table) - Elf_Word sh_type; // Section type (SHT_*) - Elf_Xword sh_flags; // Section flags (SHF_*) - Elf_Addr sh_addr; // Address where section is to be loaded - Elf_Off sh_offset; // File offset of section data, in bytes - Elf_Xword sh_size; // Size of section, in bytes - Elf_Word sh_link; // Section type-specific header table index link - Elf_Word sh_info; // Section type-specific extra information - Elf_Xword sh_addralign;// Section address alignment - Elf_Xword sh_entsize; // Size of records contained within the section -}; - -template -struct Elf_Shdr_Impl : Elf_Shdr_Base { - using Elf_Shdr_Base::sh_entsize; - using Elf_Shdr_Base::sh_size; - - /// @brief Get the number of entities this section contains if it has any. - unsigned getEntityCount() const { - if (sh_entsize == 0) - return 0; - return sh_size / sh_entsize; - } -}; -} - -namespace { -template -struct Elf_Sym_Base; - -template -struct Elf_Sym_Base { - LLVM_ELF_IMPORT_TYPES(target_endianness, false) - Elf_Word st_name; // Symbol name (index into string table) - Elf_Addr st_value; // Value or address associated with the symbol - Elf_Word st_size; // Size of the symbol - unsigned char st_info; // Symbol's type and binding attributes - unsigned char st_other; // Must be zero; reserved - Elf_Half st_shndx; // Which section (header table index) it's defined in -}; - -template -struct Elf_Sym_Base { - LLVM_ELF_IMPORT_TYPES(target_endianness, true) - Elf_Word st_name; // Symbol name (index into string table) - unsigned char st_info; // Symbol's type and binding attributes - unsigned char st_other; // Must be zero; reserved - Elf_Half st_shndx; // Which section (header table index) it's defined in - Elf_Addr st_value; // Value or address associated with the symbol - Elf_Xword st_size; // Size of the symbol -}; - -template -struct Elf_Sym_Impl : Elf_Sym_Base { - using Elf_Sym_Base::st_info; - - // These accessors and mutators correspond to the ELF32_ST_BIND, - // ELF32_ST_TYPE, and ELF32_ST_INFO macros defined in the ELF specification: - unsigned char getBinding() const { return st_info >> 4; } - unsigned char getType() const { return st_info & 0x0f; } - void setBinding(unsigned char b) { setBindingAndType(b, getType()); } - void setType(unsigned char t) { setBindingAndType(getBinding(), t); } - void setBindingAndType(unsigned char b, unsigned char t) { - st_info = (b << 4) + (t & 0x0f); - } -}; -} - -namespace { -template -class ELFObjectFile : public ObjectFile { - LLVM_ELF_IMPORT_TYPES(target_endianness, is64Bits) - - typedef Elf_Shdr_Impl Elf_Shdr; - typedef Elf_Sym_Impl Elf_Sym; - - struct Elf_Ehdr { - unsigned char e_ident[ELF::EI_NIDENT]; // ELF Identification bytes - Elf_Half e_type; // Type of file (see ET_*) - Elf_Half e_machine; // Required architecture for this file (see EM_*) - Elf_Word e_version; // Must be equal to 1 - Elf_Addr e_entry; // Address to jump to in order to start program - Elf_Off e_phoff; // Program header table's file offset, in bytes - Elf_Off e_shoff; // Section header table's file offset, in bytes - Elf_Word e_flags; // Processor-specific flags - Elf_Half e_ehsize; // Size of ELF header, in bytes - Elf_Half e_phentsize;// Size of an entry in the program header table - Elf_Half e_phnum; // Number of entries in the program header table - Elf_Half e_shentsize;// Size of an entry in the section header table - Elf_Half e_shnum; // Number of entries in the section header table - Elf_Half e_shstrndx; // Section header table index of section name - // string table - bool checkMagic() const { - return (memcmp(e_ident, ELF::ElfMagic, strlen(ELF::ElfMagic))) == 0; - } - unsigned char getFileClass() const { return e_ident[ELF::EI_CLASS]; } - unsigned char getDataEncoding() const { return e_ident[ELF::EI_DATA]; } - }; - - typedef SmallVector SymbolTableSections_t; - - const Elf_Ehdr *Header; - const Elf_Shdr *SectionHeaderTable; - const Elf_Shdr *dot_shstrtab_sec; // Section header string table. - const Elf_Shdr *dot_strtab_sec; // Symbol header string table. - SymbolTableSections_t SymbolTableSections; - - void validateSymbol(DataRefImpl Symb) const; - const Elf_Sym *getSymbol(DataRefImpl Symb) const; - const Elf_Shdr *getSection(DataRefImpl index) const; - const Elf_Shdr *getSection(uint16_t index) const; - const char *getString(uint16_t section, uint32_t offset) const; - const char *getString(const Elf_Shdr *section, uint32_t offset) const; - -protected: - virtual SymbolRef getSymbolNext(DataRefImpl Symb) const; - virtual StringRef getSymbolName(DataRefImpl Symb) const; - virtual uint64_t getSymbolAddress(DataRefImpl Symb) const; - virtual uint64_t getSymbolSize(DataRefImpl Symb) const; - virtual char getSymbolNMTypeChar(DataRefImpl Symb) const; - virtual bool isSymbolInternal(DataRefImpl Symb) const; - - virtual SectionRef getSectionNext(DataRefImpl Sec) const; - virtual StringRef getSectionName(DataRefImpl Sec) const; - virtual uint64_t getSectionAddress(DataRefImpl Sec) const; - virtual uint64_t getSectionSize(DataRefImpl Sec) const; - virtual StringRef getSectionContents(DataRefImpl Sec) const; - virtual bool isSectionText(DataRefImpl Sec) const; - -public: - ELFObjectFile(MemoryBuffer *Object, error_code &ec); - virtual symbol_iterator begin_symbols() const; - virtual symbol_iterator end_symbols() const; - virtual section_iterator begin_sections() const; - virtual section_iterator end_sections() const; - - virtual uint8_t getBytesInAddress() const; - virtual StringRef getFileFormatName() const; - virtual unsigned getArch() const; -}; -} // end namespace - -template -void ELFObjectFile - ::validateSymbol(DataRefImpl Symb) const { - const Elf_Sym *symb = getSymbol(Symb); - const Elf_Shdr *SymbolTableSection = SymbolTableSections[Symb.d.b]; - // FIXME: We really need to do proper error handling in the case of an invalid - // input file. Because we don't use exceptions, I think we'll just pass - // an error object around. - if (!( symb - && SymbolTableSection - && symb >= (const Elf_Sym*)(base() - + SymbolTableSection->sh_offset) - && symb < (const Elf_Sym*)(base() - + SymbolTableSection->sh_offset - + SymbolTableSection->sh_size))) - // FIXME: Proper error handling. - report_fatal_error("Symb must point to a valid symbol!"); -} - -template -SymbolRef ELFObjectFile - ::getSymbolNext(DataRefImpl Symb) const { - validateSymbol(Symb); - const Elf_Shdr *SymbolTableSection = SymbolTableSections[Symb.d.b]; - - ++Symb.d.a; - // Check to see if we are at the end of this symbol table. - if (Symb.d.a >= SymbolTableSection->getEntityCount()) { - // We are at the end. If there are other symbol tables, jump to them. - ++Symb.d.b; - Symb.d.a = 1; // The 0th symbol in ELF is fake. - // Otherwise return the terminator. - if (Symb.d.b >= SymbolTableSections.size()) { - Symb.d.a = std::numeric_limits::max(); - Symb.d.b = std::numeric_limits::max(); - } - } - - return SymbolRef(Symb, this); -} - -template -StringRef ELFObjectFile - ::getSymbolName(DataRefImpl Symb) const { - validateSymbol(Symb); - const Elf_Sym *symb = getSymbol(Symb); - if (symb->st_name == 0) { - const Elf_Shdr *section = getSection(symb->st_shndx); - if (!section) - return ""; - return getString(dot_shstrtab_sec, section->sh_name); - } - - // Use the default symbol table name section. - return getString(dot_strtab_sec, symb->st_name); -} - -template -uint64_t ELFObjectFile - ::getSymbolAddress(DataRefImpl Symb) const { - validateSymbol(Symb); - const Elf_Sym *symb = getSymbol(Symb); - const Elf_Shdr *Section; - switch (symb->st_shndx) { - case ELF::SHN_COMMON: - // Undefined symbols have no address yet. - case ELF::SHN_UNDEF: return UnknownAddressOrSize; - case ELF::SHN_ABS: return symb->st_value; - default: Section = getSection(symb->st_shndx); - } - - switch (symb->getType()) { - case ELF::STT_SECTION: return Section ? Section->sh_addr - : UnknownAddressOrSize; - case ELF::STT_FUNC: - case ELF::STT_OBJECT: - case ELF::STT_NOTYPE: - return symb->st_value; - default: return UnknownAddressOrSize; - } -} - -template -uint64_t ELFObjectFile - ::getSymbolSize(DataRefImpl Symb) const { - validateSymbol(Symb); - const Elf_Sym *symb = getSymbol(Symb); - if (symb->st_size == 0) - return UnknownAddressOrSize; - return symb->st_size; -} - -template -char ELFObjectFile - ::getSymbolNMTypeChar(DataRefImpl Symb) const { - validateSymbol(Symb); - const Elf_Sym *symb = getSymbol(Symb); - const Elf_Shdr *Section = getSection(symb->st_shndx); - - char ret = '?'; - - if (Section) { - switch (Section->sh_type) { - case ELF::SHT_PROGBITS: - case ELF::SHT_DYNAMIC: - switch (Section->sh_flags) { - case (ELF::SHF_ALLOC | ELF::SHF_EXECINSTR): - ret = 't'; break; - case (ELF::SHF_ALLOC | ELF::SHF_WRITE): - ret = 'd'; break; - case ELF::SHF_ALLOC: - case (ELF::SHF_ALLOC | ELF::SHF_MERGE): - case (ELF::SHF_ALLOC | ELF::SHF_MERGE | ELF::SHF_STRINGS): - ret = 'r'; break; - } - break; - case ELF::SHT_NOBITS: ret = 'b'; - } - } - - switch (symb->st_shndx) { - case ELF::SHN_UNDEF: - if (ret == '?') - ret = 'U'; - break; - case ELF::SHN_ABS: ret = 'a'; break; - case ELF::SHN_COMMON: ret = 'c'; break; - } - - switch (symb->getBinding()) { - case ELF::STB_GLOBAL: ret = ::toupper(ret); break; - case ELF::STB_WEAK: - if (symb->st_shndx == ELF::SHN_UNDEF) - ret = 'w'; +ELFObjectFileBase::ELFObjectFileBase(unsigned int Type, MemoryBufferRef Source) + : ObjectFile(Type, Source) {} + +ErrorOr> +ObjectFile::createELFObjectFile(MemoryBufferRef Obj) { + std::pair Ident = + getElfArchType(Obj.getBuffer()); + std::size_t MaxAlignment = + 1ULL << countTrailingZeros(uintptr_t(Obj.getBufferStart())); + + std::error_code EC; + std::unique_ptr R; + if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2LSB) +#if !LLVM_IS_UNALIGNED_ACCESS_FAST + if (MaxAlignment >= 4) + R.reset(new ELFObjectFile>(Obj, EC)); else - if (symb->getType() == ELF::STT_OBJECT) - ret = 'V'; - else - ret = 'W'; - } - - if (ret == '?' && symb->getType() == ELF::STT_SECTION) - return StringSwitch(getSymbolName(Symb)) - .StartsWith(".debug", 'N') - .StartsWith(".note", 'n'); - - return ret; -} - -template -bool ELFObjectFile - ::isSymbolInternal(DataRefImpl Symb) const { - validateSymbol(Symb); - const Elf_Sym *symb = getSymbol(Symb); - - if ( symb->getType() == ELF::STT_FILE - || symb->getType() == ELF::STT_SECTION) - return true; - return false; -} - -template -SectionRef ELFObjectFile - ::getSectionNext(DataRefImpl Sec) const { - const uint8_t *sec = reinterpret_cast(Sec.p); - sec += Header->e_shentsize; - Sec.p = reinterpret_cast(sec); - return SectionRef(Sec, this); -} - -template -StringRef ELFObjectFile - ::getSectionName(DataRefImpl Sec) const { - const Elf_Shdr *sec = reinterpret_cast(Sec.p); - return StringRef(getString(dot_shstrtab_sec, sec->sh_name)); -} - -template -uint64_t ELFObjectFile - ::getSectionAddress(DataRefImpl Sec) const { - const Elf_Shdr *sec = reinterpret_cast(Sec.p); - return sec->sh_addr; -} - -template -uint64_t ELFObjectFile - ::getSectionSize(DataRefImpl Sec) const { - const Elf_Shdr *sec = reinterpret_cast(Sec.p); - return sec->sh_size; -} - -template -StringRef ELFObjectFile - ::getSectionContents(DataRefImpl Sec) const { - const Elf_Shdr *sec = reinterpret_cast(Sec.p); - const char *start = (char*)base() + sec->sh_offset; - return StringRef(start, sec->sh_size); -} - -template -bool ELFObjectFile - ::isSectionText(DataRefImpl Sec) const { - const Elf_Shdr *sec = reinterpret_cast(Sec.p); - if (sec->sh_flags & ELF::SHF_EXECINSTR) - return true; - return false; -} - -template -ELFObjectFile::ELFObjectFile(MemoryBuffer *Object - , error_code &ec) - : ObjectFile(Binary::isELF, Object, ec) - , SectionHeaderTable(0) - , dot_shstrtab_sec(0) - , dot_strtab_sec(0) { - Header = reinterpret_cast(base()); - - if (Header->e_shoff == 0) - return; - - SectionHeaderTable = - reinterpret_cast(base() + Header->e_shoff); - uint32_t SectionTableSize = Header->e_shnum * Header->e_shentsize; - if (!( (const uint8_t *)SectionHeaderTable + SectionTableSize - <= base() + Data->getBufferSize())) - // FIXME: Proper error handling. - report_fatal_error("Section table goes past end of file!"); - - - // To find the symbol tables we walk the section table to find SHT_STMTAB. - for (const char *i = reinterpret_cast(SectionHeaderTable), - *e = i + Header->e_shnum * Header->e_shentsize; - i != e; i += Header->e_shentsize) { - const Elf_Shdr *sh = reinterpret_cast(i); - if (sh->sh_type == ELF::SHT_SYMTAB) { - SymbolTableSections.push_back(sh); - } - } - - // Get string table sections. - dot_shstrtab_sec = getSection(Header->e_shstrndx); - if (dot_shstrtab_sec) { - // Verify that the last byte in the string table in a null. - if (((const char*)base() + dot_shstrtab_sec->sh_offset) - [dot_shstrtab_sec->sh_size - 1] != 0) - // FIXME: Proper error handling. - report_fatal_error("String table must end with a null terminator!"); - } - - // Merge this into the above loop. - for (const char *i = reinterpret_cast(SectionHeaderTable), - *e = i + Header->e_shnum * Header->e_shentsize; - i != e; i += Header->e_shentsize) { - const Elf_Shdr *sh = reinterpret_cast(i); - if (sh->sh_type == ELF::SHT_STRTAB) { - StringRef SectionName(getString(dot_shstrtab_sec, sh->sh_name)); - if (SectionName == ".strtab") { - if (dot_strtab_sec != 0) - // FIXME: Proper error handling. - report_fatal_error("Already found section named .strtab!"); - dot_strtab_sec = sh; - const char *dot_strtab = (const char*)base() + sh->sh_offset; - if (dot_strtab[sh->sh_size - 1] != 0) - // FIXME: Proper error handling. - report_fatal_error("String table must end with a null terminator!"); - } - } - } -} - -template -ObjectFile::symbol_iterator ELFObjectFile - ::begin_symbols() const { - DataRefImpl SymbolData; - memset(&SymbolData, 0, sizeof(SymbolData)); - if (SymbolTableSections.size() == 0) { - SymbolData.d.a = std::numeric_limits::max(); - SymbolData.d.b = std::numeric_limits::max(); - } else { - SymbolData.d.a = 1; // The 0th symbol in ELF is fake. - SymbolData.d.b = 0; - } - return symbol_iterator(SymbolRef(SymbolData, this)); -} - -template -ObjectFile::symbol_iterator ELFObjectFile - ::end_symbols() const { - DataRefImpl SymbolData; - memset(&SymbolData, 0, sizeof(SymbolData)); - SymbolData.d.a = std::numeric_limits::max(); - SymbolData.d.b = std::numeric_limits::max(); - return symbol_iterator(SymbolRef(SymbolData, this)); -} - -template -ObjectFile::section_iterator ELFObjectFile - ::begin_sections() const { - DataRefImpl ret; - memset(&ret, 0, sizeof(DataRefImpl)); - ret.p = reinterpret_cast(base() + Header->e_shoff); - return section_iterator(SectionRef(ret, this)); -} - -template -ObjectFile::section_iterator ELFObjectFile - ::end_sections() const { - DataRefImpl ret; - memset(&ret, 0, sizeof(DataRefImpl)); - ret.p = reinterpret_cast(base() - + Header->e_shoff - + (Header->e_shentsize * Header->e_shnum)); - return section_iterator(SectionRef(ret, this)); -} - -template -uint8_t ELFObjectFile::getBytesInAddress() const { - return is64Bits ? 8 : 4; -} - -template -StringRef ELFObjectFile - ::getFileFormatName() const { - switch(Header->e_ident[ELF::EI_CLASS]) { - case ELF::ELFCLASS32: - switch(Header->e_machine) { - case ELF::EM_386: - return "ELF32-i386"; - case ELF::EM_X86_64: - return "ELF32-x86-64"; - default: - return "ELF32-unknown"; - } - case ELF::ELFCLASS64: - switch(Header->e_machine) { - case ELF::EM_386: - return "ELF64-i386"; - case ELF::EM_X86_64: - return "ELF64-x86-64"; - default: - return "ELF64-unknown"; - } - default: - // FIXME: Proper error handling. - report_fatal_error("Invalid ELFCLASS!"); - } -} - -template -unsigned ELFObjectFile::getArch() const { - switch(Header->e_machine) { - case ELF::EM_386: - return Triple::x86; - case ELF::EM_X86_64: - return Triple::x86_64; - default: - return Triple::UnknownArch; +#endif + if (MaxAlignment >= 2) + R.reset(new ELFObjectFile>(Obj, EC)); + else + return object_error::parse_failed; + else if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2MSB) +#if !LLVM_IS_UNALIGNED_ACCESS_FAST + if (MaxAlignment >= 4) + R.reset(new ELFObjectFile>(Obj, EC)); + else +#endif + if (MaxAlignment >= 2) + R.reset(new ELFObjectFile>(Obj, EC)); + else + return object_error::parse_failed; + else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2MSB) +#if !LLVM_IS_UNALIGNED_ACCESS_FAST + if (MaxAlignment >= 8) + R.reset(new ELFObjectFile>(Obj, EC)); + else +#endif + if (MaxAlignment >= 2) + R.reset(new ELFObjectFile>(Obj, EC)); + else + return object_error::parse_failed; + else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2LSB) { +#if !LLVM_IS_UNALIGNED_ACCESS_FAST + if (MaxAlignment >= 8) + R.reset(new ELFObjectFile>(Obj, EC)); + else +#endif + if (MaxAlignment >= 2) + R.reset(new ELFObjectFile>(Obj, EC)); + else + return object_error::parse_failed; } -} + else + llvm_unreachable("Buffer is not an ELF object file!"); -template -const typename ELFObjectFile::Elf_Sym * -ELFObjectFile::getSymbol(DataRefImpl Symb) const { - const Elf_Shdr *sec = SymbolTableSections[Symb.d.b]; - return reinterpret_cast( - base() - + sec->sh_offset - + (Symb.d.a * sec->sh_entsize)); + if (EC) + return EC; + return std::move(R); } -template -const typename ELFObjectFile::Elf_Shdr * -ELFObjectFile::getSection(DataRefImpl Symb) const { - const Elf_Shdr *sec = getSection(Symb.d.b); - if (sec->sh_type != ELF::SHT_SYMTAB) - // FIXME: Proper error handling. - report_fatal_error("Invalid symbol table section!"); - return sec; -} - -template -const typename ELFObjectFile::Elf_Shdr * -ELFObjectFile::getSection(uint16_t index) const { - if (index == 0 || index >= ELF::SHN_LORESERVE) - return 0; - if (!SectionHeaderTable || index >= Header->e_shnum) - // FIXME: Proper error handling. - report_fatal_error("Invalid section index!"); - - return reinterpret_cast( - reinterpret_cast(SectionHeaderTable) - + (index * Header->e_shentsize)); -} - -template -const char *ELFObjectFile - ::getString(uint16_t section, - ELF::Elf32_Word offset) const { - return getString(getSection(section), offset); -} - -template -const char *ELFObjectFile - ::getString(const Elf_Shdr *section, - ELF::Elf32_Word offset) const { - assert(section && section->sh_type == ELF::SHT_STRTAB && "Invalid section!"); - if (offset >= section->sh_size) - // FIXME: Proper error handling. - report_fatal_error("Symbol name offset outside of string table!"); - return (const char *)base() + section->sh_offset + offset; -} - -// EI_CLASS, EI_DATA. -static std::pair -getElfArchType(MemoryBuffer *Object) { - if (Object->getBufferSize() < ELF::EI_NIDENT) - return std::make_pair((uint8_t)ELF::ELFCLASSNONE,(uint8_t)ELF::ELFDATANONE); - return std::make_pair( (uint8_t)Object->getBufferStart()[ELF::EI_CLASS] - , (uint8_t)Object->getBufferStart()[ELF::EI_DATA]); -} - -namespace llvm { - - ObjectFile *ObjectFile::createELFObjectFile(MemoryBuffer *Object) { - std::pair Ident = getElfArchType(Object); - error_code ec; - if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2LSB) - return new ELFObjectFile(Object, ec); - else if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2MSB) - return new ELFObjectFile(Object, ec); - else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2LSB) - return new ELFObjectFile(Object, ec); - else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2MSB) - return new ELFObjectFile(Object, ec); - // FIXME: Proper error handling. - report_fatal_error("Not an ELF object file!"); - } - } // end namespace llvm