aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Object/ELFObjectFile.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Object/ELFObjectFile.cpp')
-rw-r--r--lib/Object/ELFObjectFile.cpp202
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!");
}