|
@@ -32,11 +32,12 @@
|
|
|
|
|
|
namespace ELF {
|
|
namespace ELF {
|
|
|
|
|
|
-Image::Image(const u8* buffer, size_t size)
|
|
|
|
|
|
+Image::Image(const u8* buffer, size_t size, bool verbose_logging)
|
|
: m_buffer(buffer)
|
|
: m_buffer(buffer)
|
|
, m_size(size)
|
|
, m_size(size)
|
|
|
|
+ , m_verbose_logging(verbose_logging)
|
|
{
|
|
{
|
|
- m_valid = parse();
|
|
|
|
|
|
+ parse();
|
|
}
|
|
}
|
|
|
|
|
|
Image::~Image()
|
|
Image::~Image()
|
|
@@ -63,6 +64,7 @@ static const char* object_file_type_to_string(Elf32_Half type)
|
|
|
|
|
|
StringView Image::section_index_to_string(unsigned index) const
|
|
StringView Image::section_index_to_string(unsigned index) const
|
|
{
|
|
{
|
|
|
|
+ ASSERT(m_valid);
|
|
if (index == SHN_UNDEF)
|
|
if (index == SHN_UNDEF)
|
|
return "Undefined";
|
|
return "Undefined";
|
|
if (index >= SHN_LORESERVE)
|
|
if (index >= SHN_LORESERVE)
|
|
@@ -72,6 +74,7 @@ StringView Image::section_index_to_string(unsigned index) const
|
|
|
|
|
|
unsigned Image::symbol_count() const
|
|
unsigned Image::symbol_count() const
|
|
{
|
|
{
|
|
|
|
+ ASSERT(m_valid);
|
|
return section(m_symbol_table_section_index).entry_count();
|
|
return section(m_symbol_table_section_index).entry_count();
|
|
}
|
|
}
|
|
|
|
|
|
@@ -130,26 +133,32 @@ void Image::dump() const
|
|
|
|
|
|
unsigned Image::section_count() const
|
|
unsigned Image::section_count() const
|
|
{
|
|
{
|
|
|
|
+ ASSERT(m_valid);
|
|
return header().e_shnum;
|
|
return header().e_shnum;
|
|
}
|
|
}
|
|
|
|
|
|
unsigned Image::program_header_count() const
|
|
unsigned Image::program_header_count() const
|
|
{
|
|
{
|
|
|
|
+ ASSERT(m_valid);
|
|
return header().e_phnum;
|
|
return header().e_phnum;
|
|
}
|
|
}
|
|
|
|
|
|
bool Image::parse()
|
|
bool Image::parse()
|
|
{
|
|
{
|
|
- if (!validate_elf_header(header(), m_size)) {
|
|
|
|
- dbgputstr("Image::parse(): ELF Header not valid\n");
|
|
|
|
- return false;
|
|
|
|
|
|
+ if (m_size < sizeof(Elf32_Ehdr) || !validate_elf_header(header(), m_size, m_verbose_logging)) {
|
|
|
|
+ if (m_verbose_logging)
|
|
|
|
+ dbgputstr("Image::parse(): ELF Header not valid\n");
|
|
|
|
+ return m_valid = false;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ m_valid = true;
|
|
|
|
+
|
|
// First locate the string tables.
|
|
// First locate the string tables.
|
|
for (unsigned i = 0; i < section_count(); ++i) {
|
|
for (unsigned i = 0; i < section_count(); ++i) {
|
|
auto& sh = section_header(i);
|
|
auto& sh = section_header(i);
|
|
if (sh.sh_type == SHT_SYMTAB) {
|
|
if (sh.sh_type == SHT_SYMTAB) {
|
|
- ASSERT(!m_symbol_table_section_index || m_symbol_table_section_index == i);
|
|
|
|
|
|
+ if (m_symbol_table_section_index && m_symbol_table_section_index != i)
|
|
|
|
+ return m_valid = false;
|
|
m_symbol_table_section_index = i;
|
|
m_symbol_table_section_index = i;
|
|
}
|
|
}
|
|
if (sh.sh_type == SHT_STRTAB && i != header().e_shstrndx) {
|
|
if (sh.sh_type == SHT_STRTAB && i != header().e_shstrndx) {
|
|
@@ -164,17 +173,19 @@ bool Image::parse()
|
|
m_sections.set(section.name(), move(i));
|
|
m_sections.set(section.name(), move(i));
|
|
}
|
|
}
|
|
|
|
|
|
- return true;
|
|
|
|
|
|
+ return m_valid;
|
|
}
|
|
}
|
|
|
|
|
|
StringView Image::table_string(unsigned table_index, unsigned offset) const
|
|
StringView Image::table_string(unsigned table_index, unsigned offset) const
|
|
{
|
|
{
|
|
|
|
+ ASSERT(m_valid);
|
|
auto& sh = section_header(table_index);
|
|
auto& sh = section_header(table_index);
|
|
if (sh.sh_type != SHT_STRTAB)
|
|
if (sh.sh_type != SHT_STRTAB)
|
|
return nullptr;
|
|
return nullptr;
|
|
size_t computed_offset = sh.sh_offset + offset;
|
|
size_t computed_offset = sh.sh_offset + offset;
|
|
if (computed_offset >= m_size) {
|
|
if (computed_offset >= m_size) {
|
|
- dbgprintf("SHENANIGANS! Image::table_string() computed offset outside image.\n");
|
|
|
|
|
|
+ if (m_verbose_logging)
|
|
|
|
+ dbgprintf("SHENANIGANS! Image::table_string() computed offset outside image.\n");
|
|
return {};
|
|
return {};
|
|
}
|
|
}
|
|
size_t max_length = m_size - computed_offset;
|
|
size_t max_length = m_size - computed_offset;
|
|
@@ -184,38 +195,45 @@ StringView Image::table_string(unsigned table_index, unsigned offset) const
|
|
|
|
|
|
StringView Image::section_header_table_string(unsigned offset) const
|
|
StringView Image::section_header_table_string(unsigned offset) const
|
|
{
|
|
{
|
|
|
|
+ ASSERT(m_valid);
|
|
return table_string(header().e_shstrndx, offset);
|
|
return table_string(header().e_shstrndx, offset);
|
|
}
|
|
}
|
|
|
|
|
|
StringView Image::table_string(unsigned offset) const
|
|
StringView Image::table_string(unsigned offset) const
|
|
{
|
|
{
|
|
|
|
+ ASSERT(m_valid);
|
|
return table_string(m_string_table_section_index, offset);
|
|
return table_string(m_string_table_section_index, offset);
|
|
}
|
|
}
|
|
|
|
|
|
const char* Image::raw_data(unsigned offset) const
|
|
const char* Image::raw_data(unsigned offset) const
|
|
{
|
|
{
|
|
|
|
+ ASSERT(offset < m_size); // Callers must check indices into raw_data()'s result are also in bounds.
|
|
return reinterpret_cast<const char*>(m_buffer) + offset;
|
|
return reinterpret_cast<const char*>(m_buffer) + offset;
|
|
}
|
|
}
|
|
|
|
|
|
const Elf32_Ehdr& Image::header() const
|
|
const Elf32_Ehdr& Image::header() const
|
|
{
|
|
{
|
|
|
|
+ ASSERT(m_size >= sizeof(Elf32_Ehdr));
|
|
return *reinterpret_cast<const Elf32_Ehdr*>(raw_data(0));
|
|
return *reinterpret_cast<const Elf32_Ehdr*>(raw_data(0));
|
|
}
|
|
}
|
|
|
|
|
|
const Elf32_Phdr& Image::program_header_internal(unsigned index) const
|
|
const Elf32_Phdr& Image::program_header_internal(unsigned index) const
|
|
{
|
|
{
|
|
|
|
+ ASSERT(m_valid);
|
|
ASSERT(index < header().e_phnum);
|
|
ASSERT(index < header().e_phnum);
|
|
return *reinterpret_cast<const Elf32_Phdr*>(raw_data(header().e_phoff + (index * sizeof(Elf32_Phdr))));
|
|
return *reinterpret_cast<const Elf32_Phdr*>(raw_data(header().e_phoff + (index * sizeof(Elf32_Phdr))));
|
|
}
|
|
}
|
|
|
|
|
|
const Elf32_Shdr& Image::section_header(unsigned index) const
|
|
const Elf32_Shdr& Image::section_header(unsigned index) const
|
|
{
|
|
{
|
|
|
|
+ ASSERT(m_valid);
|
|
ASSERT(index < header().e_shnum);
|
|
ASSERT(index < header().e_shnum);
|
|
return *reinterpret_cast<const Elf32_Shdr*>(raw_data(header().e_shoff + (index * header().e_shentsize)));
|
|
return *reinterpret_cast<const Elf32_Shdr*>(raw_data(header().e_shoff + (index * header().e_shentsize)));
|
|
}
|
|
}
|
|
|
|
|
|
const Image::Symbol Image::symbol(unsigned index) const
|
|
const Image::Symbol Image::symbol(unsigned index) const
|
|
{
|
|
{
|
|
|
|
+ ASSERT(m_valid);
|
|
ASSERT(index < symbol_count());
|
|
ASSERT(index < symbol_count());
|
|
auto* raw_syms = reinterpret_cast<const Elf32_Sym*>(raw_data(section(m_symbol_table_section_index).offset()));
|
|
auto* raw_syms = reinterpret_cast<const Elf32_Sym*>(raw_data(section(m_symbol_table_section_index).offset()));
|
|
return Symbol(*this, index, raw_syms[index]);
|
|
return Symbol(*this, index, raw_syms[index]);
|
|
@@ -223,12 +241,14 @@ const Image::Symbol Image::symbol(unsigned index) const
|
|
|
|
|
|
const Image::Section Image::section(unsigned index) const
|
|
const Image::Section Image::section(unsigned index) const
|
|
{
|
|
{
|
|
|
|
+ ASSERT(m_valid);
|
|
ASSERT(index < section_count());
|
|
ASSERT(index < section_count());
|
|
return Section(*this, index);
|
|
return Section(*this, index);
|
|
}
|
|
}
|
|
|
|
|
|
const Image::ProgramHeader Image::program_header(unsigned index) const
|
|
const Image::ProgramHeader Image::program_header(unsigned index) const
|
|
{
|
|
{
|
|
|
|
+ ASSERT(m_valid);
|
|
ASSERT(index < program_header_count());
|
|
ASSERT(index < program_header_count());
|
|
return ProgramHeader(*this, index);
|
|
return ProgramHeader(*this, index);
|
|
}
|
|
}
|
|
@@ -258,6 +278,7 @@ const Image::RelocationSection Image::Section::relocations() const
|
|
|
|
|
|
const Image::Section Image::lookup_section(const String& name) const
|
|
const Image::Section Image::lookup_section(const String& name) const
|
|
{
|
|
{
|
|
|
|
+ ASSERT(m_valid);
|
|
if (auto it = m_sections.find(name); it != m_sections.end())
|
|
if (auto it = m_sections.find(name); it != m_sections.end())
|
|
return section((*it).value);
|
|
return section((*it).value);
|
|
return section(0);
|
|
return section(0);
|