diff options
Diffstat (limited to 'lib/Object/ELFObjectFile.cpp')
-rw-r--r-- | lib/Object/ELFObjectFile.cpp | 202 |
1 files changed, 121 insertions, 81 deletions
diff --git a/lib/Object/ELFObjectFile.cpp b/lib/Object/ELFObjectFile.cpp index d2a2726..edf9824 100644 --- a/lib/Object/ELFObjectFile.cpp +++ b/lib/Object/ELFObjectFile.cpp @@ -222,22 +222,22 @@ class ELFObjectFile : public ObjectFile { 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; + virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const; + virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const; + virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const; + virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const; + virtual error_code getSymbolNMTypeChar(DataRefImpl Symb, char &Res) const; + virtual error_code isSymbolInternal(DataRefImpl Symb, bool &Res) const; + + virtual error_code getSectionNext(DataRefImpl Sec, SectionRef &Res) const; + virtual error_code getSectionName(DataRefImpl Sec, StringRef &Res) const; + virtual error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const; + virtual error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const; + virtual error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const; + virtual error_code isSectionText(DataRefImpl Sec, bool &Res) const; public: - ELFObjectFile(MemoryBuffer *Object); + ELFObjectFile(MemoryBuffer *Object, error_code &ec); virtual symbol_iterator begin_symbols() const; virtual symbol_iterator end_symbols() const; virtual section_iterator begin_sections() const; @@ -259,9 +259,9 @@ void ELFObjectFile<target_endianness, is64Bits> // an error object around. if (!( symb && SymbolTableSection - && symb >= (const Elf_Sym*)(base + && symb >= (const Elf_Sym*)(base() + SymbolTableSection->sh_offset) - && symb < (const Elf_Sym*)(base + && symb < (const Elf_Sym*)(base() + SymbolTableSection->sh_offset + SymbolTableSection->sh_size))) // FIXME: Proper error handling. @@ -269,8 +269,9 @@ void ELFObjectFile<target_endianness, is64Bits> } template<support::endianness target_endianness, bool is64Bits> -SymbolRef ELFObjectFile<target_endianness, is64Bits> - ::getSymbolNext(DataRefImpl Symb) const { +error_code ELFObjectFile<target_endianness, is64Bits> + ::getSymbolNext(DataRefImpl Symb, + SymbolRef &Result) const { validateSymbol(Symb); const Elf_Shdr *SymbolTableSection = SymbolTableSections[Symb.d.b]; @@ -287,63 +288,80 @@ SymbolRef ELFObjectFile<target_endianness, is64Bits> } } - return SymbolRef(Symb, this); + Result = SymbolRef(Symb, this); + return object_error::success; } template<support::endianness target_endianness, bool is64Bits> -StringRef ELFObjectFile<target_endianness, is64Bits> - ::getSymbolName(DataRefImpl Symb) const { +error_code ELFObjectFile<target_endianness, is64Bits> + ::getSymbolName(DataRefImpl Symb, + StringRef &Result) 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); + Result = ""; + else + Result = getString(dot_shstrtab_sec, section->sh_name); + return object_error::success; } // Use the default symbol table name section. - return getString(dot_strtab_sec, symb->st_name); + Result = getString(dot_strtab_sec, symb->st_name); + return object_error::success; } template<support::endianness target_endianness, bool is64Bits> -uint64_t ELFObjectFile<target_endianness, is64Bits> - ::getSymbolAddress(DataRefImpl Symb) const { +error_code ELFObjectFile<target_endianness, is64Bits> + ::getSymbolAddress(DataRefImpl Symb, + uint64_t &Result) 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; + case ELF::SHN_UNDEF: + Result = UnknownAddressOrSize; + return object_error::success; + case ELF::SHN_ABS: + Result = symb->st_value; + return object_error::success; default: Section = getSection(symb->st_shndx); } switch (symb->getType()) { - case ELF::STT_SECTION: return Section ? Section->sh_addr - : UnknownAddressOrSize; + case ELF::STT_SECTION: + Result = Section ? Section->sh_addr : UnknownAddressOrSize; + return object_error::success; case ELF::STT_FUNC: case ELF::STT_OBJECT: case ELF::STT_NOTYPE: - return symb->st_value; - default: return UnknownAddressOrSize; + Result = symb->st_value; + return object_error::success; + default: + Result = UnknownAddressOrSize; + return object_error::success; } } template<support::endianness target_endianness, bool is64Bits> -uint64_t ELFObjectFile<target_endianness, is64Bits> - ::getSymbolSize(DataRefImpl Symb) const { +error_code ELFObjectFile<target_endianness, is64Bits> + ::getSymbolSize(DataRefImpl Symb, + uint64_t &Result) const { validateSymbol(Symb); const Elf_Sym *symb = getSymbol(Symb); if (symb->st_size == 0) - return UnknownAddressOrSize; - return symb->st_size; + Result = UnknownAddressOrSize; + Result = symb->st_size; + return object_error::success; } template<support::endianness target_endianness, bool is64Bits> -char ELFObjectFile<target_endianness, is64Bits> - ::getSymbolNMTypeChar(DataRefImpl Symb) const { +error_code ELFObjectFile<target_endianness, is64Bits> + ::getSymbolNMTypeChar(DataRefImpl Symb, + char &Result) const { validateSymbol(Symb); const Elf_Sym *symb = getSymbol(Symb); const Elf_Shdr *Section = getSection(symb->st_shndx); @@ -390,89 +408,110 @@ char ELFObjectFile<target_endianness, is64Bits> ret = 'W'; } - if (ret == '?' && symb->getType() == ELF::STT_SECTION) - return StringSwitch<char>(getSymbolName(Symb)) + if (ret == '?' && symb->getType() == ELF::STT_SECTION) { + StringRef name; + if (error_code ec = getSymbolName(Symb, name)) + return ec; + Result = StringSwitch<char>(name) .StartsWith(".debug", 'N') .StartsWith(".note", 'n'); + return object_error::success; + } - return ret; + Result = ret; + return object_error::success; } template<support::endianness target_endianness, bool is64Bits> -bool ELFObjectFile<target_endianness, is64Bits> - ::isSymbolInternal(DataRefImpl Symb) const { +error_code ELFObjectFile<target_endianness, is64Bits> + ::isSymbolInternal(DataRefImpl Symb, + bool &Result) const { validateSymbol(Symb); const Elf_Sym *symb = getSymbol(Symb); if ( symb->getType() == ELF::STT_FILE || symb->getType() == ELF::STT_SECTION) - return true; - return false; + Result = true; + Result = false; + return object_error::success; } template<support::endianness target_endianness, bool is64Bits> -SectionRef ELFObjectFile<target_endianness, is64Bits> - ::getSectionNext(DataRefImpl Sec) const { +error_code ELFObjectFile<target_endianness, is64Bits> + ::getSectionNext(DataRefImpl Sec, SectionRef &Result) const { const uint8_t *sec = reinterpret_cast<const uint8_t *>(Sec.p); sec += Header->e_shentsize; Sec.p = reinterpret_cast<intptr_t>(sec); - return SectionRef(Sec, this); + Result = SectionRef(Sec, this); + return object_error::success; } template<support::endianness target_endianness, bool is64Bits> -StringRef ELFObjectFile<target_endianness, is64Bits> - ::getSectionName(DataRefImpl Sec) const { +error_code ELFObjectFile<target_endianness, is64Bits> + ::getSectionName(DataRefImpl Sec, + StringRef &Result) const { const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); - return StringRef(getString(dot_shstrtab_sec, sec->sh_name)); + Result = StringRef(getString(dot_shstrtab_sec, sec->sh_name)); + return object_error::success; } template<support::endianness target_endianness, bool is64Bits> -uint64_t ELFObjectFile<target_endianness, is64Bits> - ::getSectionAddress(DataRefImpl Sec) const { +error_code ELFObjectFile<target_endianness, is64Bits> + ::getSectionAddress(DataRefImpl Sec, + uint64_t &Result) const { const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); - return sec->sh_addr; + Result = sec->sh_addr; + return object_error::success; } template<support::endianness target_endianness, bool is64Bits> -uint64_t ELFObjectFile<target_endianness, is64Bits> - ::getSectionSize(DataRefImpl Sec) const { +error_code ELFObjectFile<target_endianness, is64Bits> + ::getSectionSize(DataRefImpl Sec, + uint64_t &Result) const { const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); - return sec->sh_size; + Result = sec->sh_size; + return object_error::success; } template<support::endianness target_endianness, bool is64Bits> -StringRef ELFObjectFile<target_endianness, is64Bits> - ::getSectionContents(DataRefImpl Sec) const { +error_code ELFObjectFile<target_endianness, is64Bits> + ::getSectionContents(DataRefImpl Sec, + StringRef &Result) const { const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); - const char *start = (char*)base + sec->sh_offset; - return StringRef(start, sec->sh_size); + const char *start = (const char*)base() + sec->sh_offset; + Result = StringRef(start, sec->sh_size); + return object_error::success; } template<support::endianness target_endianness, bool is64Bits> -bool ELFObjectFile<target_endianness, is64Bits> - ::isSectionText(DataRefImpl Sec) const { +error_code ELFObjectFile<target_endianness, is64Bits> + ::isSectionText(DataRefImpl Sec, + bool &Result) const { const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); if (sec->sh_flags & ELF::SHF_EXECINSTR) - return true; - return false; + Result = true; + else + Result = false; + return object_error::success; } template<support::endianness target_endianness, bool is64Bits> -ELFObjectFile<target_endianness, is64Bits>::ELFObjectFile(MemoryBuffer *Object) - : ObjectFile(Object) +ELFObjectFile<target_endianness, is64Bits>::ELFObjectFile(MemoryBuffer *Object + , error_code &ec) + : ObjectFile(Binary::isELF, Object, ec) , SectionHeaderTable(0) , dot_shstrtab_sec(0) , dot_strtab_sec(0) { - Header = reinterpret_cast<const Elf_Ehdr *>(base); + Header = reinterpret_cast<const Elf_Ehdr *>(base()); if (Header->e_shoff == 0) return; SectionHeaderTable = - reinterpret_cast<const Elf_Shdr *>(base + Header->e_shoff); + reinterpret_cast<const Elf_Shdr *>(base() + Header->e_shoff); uint32_t SectionTableSize = Header->e_shnum * Header->e_shentsize; if (!( (const uint8_t *)SectionHeaderTable + SectionTableSize - <= base + MapFile->getBufferSize())) + <= base() + Data->getBufferSize())) // FIXME: Proper error handling. report_fatal_error("Section table goes past end of file!"); @@ -491,7 +530,7 @@ ELFObjectFile<target_endianness, is64Bits>::ELFObjectFile(MemoryBuffer *Object) 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) + 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!"); @@ -509,7 +548,7 @@ ELFObjectFile<target_endianness, is64Bits>::ELFObjectFile(MemoryBuffer *Object) // 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; + 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!"); @@ -548,7 +587,7 @@ ObjectFile::section_iterator ELFObjectFile<target_endianness, is64Bits> ::begin_sections() const { DataRefImpl ret; memset(&ret, 0, sizeof(DataRefImpl)); - ret.p = reinterpret_cast<intptr_t>(base + Header->e_shoff); + ret.p = reinterpret_cast<intptr_t>(base() + Header->e_shoff); return section_iterator(SectionRef(ret, this)); } @@ -557,7 +596,7 @@ ObjectFile::section_iterator ELFObjectFile<target_endianness, is64Bits> ::end_sections() const { DataRefImpl ret; memset(&ret, 0, sizeof(DataRefImpl)); - ret.p = reinterpret_cast<intptr_t>(base + ret.p = reinterpret_cast<intptr_t>(base() + Header->e_shoff + (Header->e_shentsize * Header->e_shnum)); return section_iterator(SectionRef(ret, this)); @@ -613,7 +652,7 @@ const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Sym * ELFObjectFile<target_endianness, is64Bits>::getSymbol(DataRefImpl Symb) const { const Elf_Shdr *sec = SymbolTableSections[Symb.d.b]; return reinterpret_cast<const Elf_Sym *>( - base + base() + sec->sh_offset + (Symb.d.a * sec->sh_entsize)); } @@ -656,8 +695,8 @@ const char *ELFObjectFile<target_endianness, is64Bits> assert(section && section->sh_type == ELF::SHT_STRTAB && "Invalid section!"); if (offset >= section->sh_size) // FIXME: Proper error handling. - report_fatal_error("Sybol name offset outside of string table!"); - return (const char *)base + section->sh_offset + offset; + report_fatal_error("Symbol name offset outside of string table!"); + return (const char *)base() + section->sh_offset + offset; } // EI_CLASS, EI_DATA. @@ -673,14 +712,15 @@ namespace llvm { ObjectFile *ObjectFile::createELFObjectFile(MemoryBuffer *Object) { std::pair<unsigned char, unsigned char> Ident = getElfArchType(Object); + error_code ec; if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2LSB) - return new ELFObjectFile<support::little, false>(Object); + return new ELFObjectFile<support::little, false>(Object, ec); else if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2MSB) - return new ELFObjectFile<support::big, false>(Object); + return new ELFObjectFile<support::big, false>(Object, ec); else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2LSB) - return new ELFObjectFile<support::little, true>(Object); + return new ELFObjectFile<support::little, true>(Object, ec); else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2MSB) - return new ELFObjectFile<support::big, true>(Object); + return new ELFObjectFile<support::big, true>(Object, ec); // FIXME: Proper error handling. report_fatal_error("Not an ELF object file!"); } |