mirror of
https://github.com/SerenityOS/serenity
synced 2024-09-06 17:06:31 +00:00
Tidy up ELFLoader.
This commit is contained in:
parent
422b5403e5
commit
b5c5286ee1
|
@ -4,7 +4,7 @@
|
||||||
ELFImage::ELFImage(ByteBuffer&& buffer)
|
ELFImage::ELFImage(ByteBuffer&& buffer)
|
||||||
: m_buffer(buffer)
|
: m_buffer(buffer)
|
||||||
{
|
{
|
||||||
m_isValid = parse();
|
m_valid = parse();
|
||||||
}
|
}
|
||||||
|
|
||||||
ELFImage::~ELFImage()
|
ELFImage::~ELFImage()
|
||||||
|
@ -23,7 +23,7 @@ static const char* objectFileTypeToString(Elf32_Half type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* ELFImage::sectionIndexToString(unsigned index)
|
const char* ELFImage::section_index_to_string(unsigned index)
|
||||||
{
|
{
|
||||||
if (index == SHN_UNDEF)
|
if (index == SHN_UNDEF)
|
||||||
return "Undefined";
|
return "Undefined";
|
||||||
|
@ -32,17 +32,17 @@ const char* ELFImage::sectionIndexToString(unsigned index)
|
||||||
return section(index).name();
|
return section(index).name();
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned ELFImage::symbolCount() const
|
unsigned ELFImage::symbol_count() const
|
||||||
{
|
{
|
||||||
return section(m_symbolTableSectionIndex).entryCount();
|
return section(m_symbol_table_section_index).entry_count();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ELFImage::dump()
|
void ELFImage::dump()
|
||||||
{
|
{
|
||||||
kprintf("ELFImage{%p} {\n", this);
|
kprintf("ELFImage{%p} {\n", this);
|
||||||
kprintf(" isValid: %u\n", isValid());
|
kprintf(" isValid: %u\n", is_valid());
|
||||||
|
|
||||||
if (!isValid()) {
|
if (!is_valid()) {
|
||||||
kprintf("}\n");
|
kprintf("}\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -65,12 +65,12 @@ void ELFImage::dump()
|
||||||
kprintf(" }\n");
|
kprintf(" }\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
kprintf("Symbol count: %u (table is %u)\n", symbolCount(), m_symbolTableSectionIndex);
|
kprintf("Symbol count: %u (table is %u)\n", symbol_count(), m_symbol_table_section_index);
|
||||||
for (unsigned i = 1; i < symbolCount(); ++i) {
|
for (unsigned i = 1; i < symbol_count(); ++i) {
|
||||||
auto& sym = symbol(i);
|
auto& sym = symbol(i);
|
||||||
kprintf("Symbol @%u:\n", i);
|
kprintf("Symbol @%u:\n", i);
|
||||||
kprintf(" Name: %s\n", sym.name());
|
kprintf(" Name: %s\n", sym.name());
|
||||||
kprintf(" In section: %s\n", sectionIndexToString(sym.sectionIndex()));
|
kprintf(" In section: %s\n", section_index_to_string(sym.section_index()));
|
||||||
kprintf(" Value: %x\n", sym.value());
|
kprintf(" Value: %x\n", sym.value());
|
||||||
kprintf(" Size: %u\n", sym.size());
|
kprintf(" Size: %u\n", sym.size());
|
||||||
}
|
}
|
||||||
|
@ -78,7 +78,7 @@ void ELFImage::dump()
|
||||||
kprintf("}\n");
|
kprintf("}\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned ELFImage::sectionCount() const
|
unsigned ELFImage::section_count() const
|
||||||
{
|
{
|
||||||
return header().e_shnum;
|
return header().e_shnum;
|
||||||
}
|
}
|
||||||
|
@ -95,43 +95,43 @@ bool ELFImage::parse()
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// First locate the string tables.
|
// First locate the string tables.
|
||||||
for (unsigned i = 0; i < sectionCount(); ++i) {
|
for (unsigned i = 0; i < section_count(); ++i) {
|
||||||
auto& sh = sectionHeader(i);
|
auto& sh = section_header(i);
|
||||||
if (sh.sh_type == SHT_SYMTAB) {
|
if (sh.sh_type == SHT_SYMTAB) {
|
||||||
ASSERT(!m_symbolTableSectionIndex);
|
ASSERT(!m_symbol_table_section_index);
|
||||||
m_symbolTableSectionIndex = 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) {
|
||||||
ASSERT(!m_stringTableSectionIndex);
|
ASSERT(!m_string_table_section_index);
|
||||||
m_stringTableSectionIndex = i;
|
m_string_table_section_index = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then create a name-to-index map.
|
// Then create a name-to-index map.
|
||||||
for (unsigned i = 0; i < sectionCount(); ++i) {
|
for (unsigned i = 0; i < section_count(); ++i) {
|
||||||
auto& section = this->section(i);
|
auto& section = this->section(i);
|
||||||
m_sections.set(section.name(), move(i));
|
m_sections.set(section.name(), move(i));
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* ELFImage::sectionHeaderTableString(unsigned offset) const
|
const char* ELFImage::section_header_table_string(unsigned offset) const
|
||||||
{
|
{
|
||||||
auto& sh = sectionHeader(header().e_shstrndx);
|
auto& sh = section_header(header().e_shstrndx);
|
||||||
if (sh.sh_type != SHT_STRTAB)
|
if (sh.sh_type != SHT_STRTAB)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
return rawData(sh.sh_offset + offset);
|
return raw_data(sh.sh_offset + offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* ELFImage::tableString(unsigned offset) const
|
const char* ELFImage::table_string(unsigned offset) const
|
||||||
{
|
{
|
||||||
auto& sh = sectionHeader(m_stringTableSectionIndex);
|
auto& sh = section_header(m_string_table_section_index);
|
||||||
if (sh.sh_type != SHT_STRTAB)
|
if (sh.sh_type != SHT_STRTAB)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
return rawData(sh.sh_offset + offset);
|
return raw_data(sh.sh_offset + offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* ELFImage::rawData(unsigned offset) const
|
const char* ELFImage::raw_data(unsigned offset) const
|
||||||
{
|
{
|
||||||
#ifdef SERENITY
|
#ifdef SERENITY
|
||||||
return reinterpret_cast<const char*>(m_buffer.pointer()) + offset;
|
return reinterpret_cast<const char*>(m_buffer.pointer()) + offset;
|
||||||
|
@ -142,31 +142,31 @@ const char* ELFImage::rawData(unsigned offset) const
|
||||||
|
|
||||||
const Elf32_Ehdr& ELFImage::header() const
|
const Elf32_Ehdr& ELFImage::header() const
|
||||||
{
|
{
|
||||||
return *reinterpret_cast<const Elf32_Ehdr*>(rawData(0));
|
return *reinterpret_cast<const Elf32_Ehdr*>(raw_data(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
const Elf32_Phdr& ELFImage::program_header_internal(unsigned index) const
|
const Elf32_Phdr& ELFImage::program_header_internal(unsigned index) const
|
||||||
{
|
{
|
||||||
ASSERT(index < header().e_phnum);
|
ASSERT(index < header().e_phnum);
|
||||||
return *reinterpret_cast<const Elf32_Phdr*>(rawData(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& ELFImage::sectionHeader(unsigned index) const
|
const Elf32_Shdr& ELFImage::section_header(unsigned index) const
|
||||||
{
|
{
|
||||||
ASSERT(index < header().e_shnum);
|
ASSERT(index < header().e_shnum);
|
||||||
return *reinterpret_cast<const Elf32_Shdr*>(rawData(header().e_shoff + (index * sizeof(Elf32_Shdr))));
|
return *reinterpret_cast<const Elf32_Shdr*>(raw_data(header().e_shoff + (index * sizeof(Elf32_Shdr))));
|
||||||
}
|
}
|
||||||
|
|
||||||
const ELFImage::Symbol ELFImage::symbol(unsigned index) const
|
const ELFImage::Symbol ELFImage::symbol(unsigned index) const
|
||||||
{
|
{
|
||||||
ASSERT(index < symbolCount());
|
ASSERT(index < symbol_count());
|
||||||
auto* rawSyms = reinterpret_cast<const Elf32_Sym*>(rawData(section(m_symbolTableSectionIndex).offset()));
|
auto* rawSyms = reinterpret_cast<const Elf32_Sym*>(raw_data(section(m_symbol_table_section_index).offset()));
|
||||||
return Symbol(*this, index, rawSyms[index]);
|
return Symbol(*this, index, rawSyms[index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
const ELFImage::Section ELFImage::section(unsigned index) const
|
const ELFImage::Section ELFImage::section(unsigned index) const
|
||||||
{
|
{
|
||||||
ASSERT(index < sectionCount());
|
ASSERT(index < section_count());
|
||||||
return Section(*this, index);
|
return Section(*this, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,8 +178,8 @@ const ELFImage::ProgramHeader ELFImage::program_header(unsigned index) const
|
||||||
|
|
||||||
const ELFImage::Relocation ELFImage::RelocationSection::relocation(unsigned index) const
|
const ELFImage::Relocation ELFImage::RelocationSection::relocation(unsigned index) const
|
||||||
{
|
{
|
||||||
ASSERT(index < relocationCount());
|
ASSERT(index < relocation_count());
|
||||||
auto* rels = reinterpret_cast<const Elf32_Rel*>(m_image.rawData(offset()));
|
auto* rels = reinterpret_cast<const Elf32_Rel*>(m_image.raw_data(offset()));
|
||||||
return Relocation(m_image, rels[index]);
|
return Relocation(m_image, rels[index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ public:
|
||||||
explicit ELFImage(ByteBuffer&&);
|
explicit ELFImage(ByteBuffer&&);
|
||||||
~ELFImage();
|
~ELFImage();
|
||||||
void dump();
|
void dump();
|
||||||
bool isValid() const { return m_isValid; }
|
bool is_valid() const { return m_valid; }
|
||||||
bool parse();
|
bool parse();
|
||||||
|
|
||||||
class Section;
|
class Section;
|
||||||
|
@ -30,13 +30,13 @@ public:
|
||||||
|
|
||||||
~Symbol() { }
|
~Symbol() { }
|
||||||
|
|
||||||
const char* name() const { return m_image.tableString(m_sym.st_name); }
|
const char* name() const { return m_image.table_string(m_sym.st_name); }
|
||||||
unsigned sectionIndex() const { return m_sym.st_shndx; }
|
unsigned section_index() const { return m_sym.st_shndx; }
|
||||||
unsigned value() const { return m_sym.st_value; }
|
unsigned value() const { return m_sym.st_value; }
|
||||||
unsigned size() const { return m_sym.st_size; }
|
unsigned size() const { return m_sym.st_size; }
|
||||||
unsigned index() const { return m_index; }
|
unsigned index() const { return m_index; }
|
||||||
unsigned type() const { return ELF32_ST_TYPE(m_sym.st_info); }
|
unsigned type() const { return ELF32_ST_TYPE(m_sym.st_info); }
|
||||||
const Section section() const { return m_image.section(sectionIndex()); }
|
const Section section() const { return m_image.section(section_index()); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const ELFImage& m_image;
|
const ELFImage& m_image;
|
||||||
|
@ -73,39 +73,39 @@ public:
|
||||||
public:
|
public:
|
||||||
Section(const ELFImage& image, unsigned sectionIndex)
|
Section(const ELFImage& image, unsigned sectionIndex)
|
||||||
: m_image(image)
|
: m_image(image)
|
||||||
, m_sectionHeader(image.sectionHeader(sectionIndex))
|
, m_section_header(image.section_header(sectionIndex))
|
||||||
, m_sectionIndex(sectionIndex)
|
, m_section_index(sectionIndex)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
~Section() { }
|
~Section() { }
|
||||||
|
|
||||||
const char* name() const { return m_image.sectionHeaderTableString(m_sectionHeader.sh_name); }
|
const char* name() const { return m_image.section_header_table_string(m_section_header.sh_name); }
|
||||||
unsigned type() const { return m_sectionHeader.sh_type; }
|
unsigned type() const { return m_section_header.sh_type; }
|
||||||
unsigned offset() const { return m_sectionHeader.sh_offset; }
|
unsigned offset() const { return m_section_header.sh_offset; }
|
||||||
unsigned size() const { return m_sectionHeader.sh_size; }
|
unsigned size() const { return m_section_header.sh_size; }
|
||||||
unsigned entrySize() const { return m_sectionHeader.sh_entsize; }
|
unsigned entry_size() const { return m_section_header.sh_entsize; }
|
||||||
unsigned entryCount() const { return size() / entrySize(); }
|
unsigned entry_count() const { return size() / entry_size(); }
|
||||||
dword address() const { return m_sectionHeader.sh_addr; }
|
dword address() const { return m_section_header.sh_addr; }
|
||||||
const char* rawData() const { return m_image.rawData(m_sectionHeader.sh_offset); }
|
const char* raw_data() const { return m_image.raw_data(m_section_header.sh_offset); }
|
||||||
bool isUndefined() const { return m_sectionIndex == SHN_UNDEF; }
|
bool is_undefined() const { return m_section_index == SHN_UNDEF; }
|
||||||
const RelocationSection relocations() const;
|
const RelocationSection relocations() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend class RelocationSection;
|
friend class RelocationSection;
|
||||||
const ELFImage& m_image;
|
const ELFImage& m_image;
|
||||||
const Elf32_Shdr& m_sectionHeader;
|
const Elf32_Shdr& m_section_header;
|
||||||
unsigned m_sectionIndex;
|
unsigned m_section_index;
|
||||||
};
|
};
|
||||||
|
|
||||||
class RelocationSection : public Section {
|
class RelocationSection : public Section {
|
||||||
public:
|
public:
|
||||||
RelocationSection(const Section& section)
|
RelocationSection(const Section& section)
|
||||||
: Section(section.m_image, section.m_sectionIndex)
|
: Section(section.m_image, section.m_section_index)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
unsigned relocationCount() const { return entryCount(); }
|
unsigned relocation_count() const { return entry_count(); }
|
||||||
const Relocation relocation(unsigned index) const;
|
const Relocation relocation(unsigned index) const;
|
||||||
template<typename F> void forEachRelocation(F) const;
|
template<typename F> void for_each_relocation(F) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Relocation {
|
class Relocation {
|
||||||
|
@ -120,66 +120,62 @@ public:
|
||||||
|
|
||||||
unsigned offset() const { return m_rel.r_offset; }
|
unsigned offset() const { return m_rel.r_offset; }
|
||||||
unsigned type() const { return ELF32_R_TYPE(m_rel.r_info); }
|
unsigned type() const { return ELF32_R_TYPE(m_rel.r_info); }
|
||||||
unsigned symbolIndex() const { return ELF32_R_SYM(m_rel.r_info); }
|
unsigned symbol_index() const { return ELF32_R_SYM(m_rel.r_info); }
|
||||||
const Symbol symbol() const { return m_image.symbol(symbolIndex()); }
|
const Symbol symbol() const { return m_image.symbol(symbol_index()); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const ELFImage& m_image;
|
const ELFImage& m_image;
|
||||||
const Elf32_Rel& m_rel;
|
const Elf32_Rel& m_rel;
|
||||||
};
|
};
|
||||||
|
|
||||||
unsigned symbolCount() const;
|
unsigned symbol_count() const;
|
||||||
unsigned sectionCount() const;
|
unsigned section_count() const;
|
||||||
unsigned program_header_count() const;
|
unsigned program_header_count() const;
|
||||||
|
|
||||||
const Symbol symbol(unsigned) const;
|
const Symbol symbol(unsigned) const;
|
||||||
const Section section(unsigned) const;
|
const Section section(unsigned) const;
|
||||||
const ProgramHeader program_header(unsigned const) const;
|
const ProgramHeader program_header(unsigned const) const;
|
||||||
|
|
||||||
template<typename F> void forEachSection(F) const;
|
template<typename F> void for_each_section(F) const;
|
||||||
template<typename F> void forEachSectionOfType(unsigned, F) const;
|
template<typename F> void for_each_section_of_type(unsigned, F) const;
|
||||||
template<typename F> void forEachSymbol(F) const;
|
template<typename F> void for_each_symbol(F) const;
|
||||||
template<typename F> void for_each_program_header(F) const;
|
template<typename F> void for_each_program_header(F) const;
|
||||||
|
|
||||||
// NOTE: Returns section(0) if section with name is not found.
|
// NOTE: Returns section(0) if section with name is not found.
|
||||||
// FIXME: I don't love this API.
|
// FIXME: I don't love this API.
|
||||||
const Section lookupSection(const char* name) const;
|
const Section lookupSection(const char* name) const;
|
||||||
|
|
||||||
bool isExecutable() const { return header().e_type == ET_EXEC; }
|
bool is_executable() const { return header().e_type == ET_EXEC; }
|
||||||
bool isRelocatable() const { return header().e_type == ET_REL; }
|
bool is_relocatable() const { return header().e_type == ET_REL; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool parseHeader();
|
bool parseHeader();
|
||||||
const char* rawData(unsigned offset) const;
|
const char* raw_data(unsigned offset) const;
|
||||||
const Elf32_Ehdr& header() const;
|
const Elf32_Ehdr& header() const;
|
||||||
const Elf32_Shdr& sectionHeader(unsigned) const;
|
const Elf32_Shdr& section_header(unsigned) const;
|
||||||
const Elf32_Phdr& program_header_internal(unsigned) const;
|
const Elf32_Phdr& program_header_internal(unsigned) const;
|
||||||
const char* tableString(unsigned offset) const;
|
const char* table_string(unsigned offset) const;
|
||||||
const char* sectionHeaderTableString(unsigned offset) const;
|
const char* section_header_table_string(unsigned offset) const;
|
||||||
const char* sectionIndexToString(unsigned index);
|
const char* section_index_to_string(unsigned index);
|
||||||
|
|
||||||
#ifdef SERENITY
|
|
||||||
ByteBuffer m_buffer;
|
ByteBuffer m_buffer;
|
||||||
#else
|
|
||||||
MappedFile m_file;
|
|
||||||
#endif
|
|
||||||
HashMap<String, unsigned> m_sections;
|
HashMap<String, unsigned> m_sections;
|
||||||
bool m_isValid { false };
|
bool m_valid { false };
|
||||||
unsigned m_symbolTableSectionIndex { 0 };
|
unsigned m_symbol_table_section_index { 0 };
|
||||||
unsigned m_stringTableSectionIndex { 0 };
|
unsigned m_string_table_section_index { 0 };
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename F>
|
template<typename F>
|
||||||
inline void ELFImage::forEachSection(F func) const
|
inline void ELFImage::for_each_section(F func) const
|
||||||
{
|
{
|
||||||
for (unsigned i = 0; i < sectionCount(); ++i)
|
for (unsigned i = 0; i < section_count(); ++i)
|
||||||
func(section(i));
|
func(section(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename F>
|
template<typename F>
|
||||||
inline void ELFImage::forEachSectionOfType(unsigned type, F func) const
|
inline void ELFImage::for_each_section_of_type(unsigned type, F func) const
|
||||||
{
|
{
|
||||||
for (unsigned i = 0; i < sectionCount(); ++i) {
|
for (unsigned i = 0; i < section_count(); ++i) {
|
||||||
auto& section = this->section(i);
|
auto& section = this->section(i);
|
||||||
if (section.type() == type) {
|
if (section.type() == type) {
|
||||||
if (!func(section))
|
if (!func(section))
|
||||||
|
@ -189,18 +185,18 @@ inline void ELFImage::forEachSectionOfType(unsigned type, F func) const
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename F>
|
template<typename F>
|
||||||
inline void ELFImage::RelocationSection::forEachRelocation(F func) const
|
inline void ELFImage::RelocationSection::for_each_relocation(F func) const
|
||||||
{
|
{
|
||||||
for (unsigned i = 0; i < relocationCount(); ++i) {
|
for (unsigned i = 0; i < relocation_count(); ++i) {
|
||||||
if (!func(relocation(i)))
|
if (!func(relocation(i)))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename F>
|
template<typename F>
|
||||||
inline void ELFImage::forEachSymbol(F func) const
|
inline void ELFImage::for_each_symbol(F func) const
|
||||||
{
|
{
|
||||||
for (unsigned i = 0; i < symbolCount(); ++i) {
|
for (unsigned i = 0; i < symbol_count(); ++i) {
|
||||||
if (!func(symbol(i)))
|
if (!func(symbol(i)))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -209,7 +205,6 @@ inline void ELFImage::forEachSymbol(F func) const
|
||||||
template<typename F>
|
template<typename F>
|
||||||
inline void ELFImage::for_each_program_header(F func) const
|
inline void ELFImage::for_each_program_header(F func) const
|
||||||
{
|
{
|
||||||
for (unsigned i = 0; i < program_header_count(); ++i) {
|
for (unsigned i = 0; i < program_header_count(); ++i)
|
||||||
func(program_header(i));
|
func(program_header(i));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,8 +4,8 @@
|
||||||
//#define ELFLOADER_DEBUG
|
//#define ELFLOADER_DEBUG
|
||||||
|
|
||||||
ELFLoader::ELFLoader(ByteBuffer&& buffer)
|
ELFLoader::ELFLoader(ByteBuffer&& buffer)
|
||||||
|
: m_image(move(buffer))
|
||||||
{
|
{
|
||||||
m_image = make<ELFImage>(move(buffer));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ELFLoader::~ELFLoader()
|
ELFLoader::~ELFLoader()
|
||||||
|
@ -15,15 +15,15 @@ ELFLoader::~ELFLoader()
|
||||||
bool ELFLoader::load()
|
bool ELFLoader::load()
|
||||||
{
|
{
|
||||||
#ifdef ELFLOADER_DEBUG
|
#ifdef ELFLOADER_DEBUG
|
||||||
m_image->dump();
|
m_image.dump();
|
||||||
#endif
|
#endif
|
||||||
if (!m_image->isValid())
|
if (!m_image.is_valid())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!layout())
|
if (!layout())
|
||||||
return false;
|
return false;
|
||||||
exportSymbols();
|
export_symbols();
|
||||||
if (!performRelocations())
|
if (!perform_relocations())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -36,7 +36,7 @@ bool ELFLoader::layout()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool failed = false;
|
bool failed = false;
|
||||||
m_image->for_each_program_header([&] (const ELFImage::ProgramHeader& program_header) {
|
m_image.for_each_program_header([&] (const ELFImage::ProgramHeader& program_header) {
|
||||||
if (program_header.type() != PT_LOAD)
|
if (program_header.type() != PT_LOAD)
|
||||||
return;
|
return;
|
||||||
#ifdef ELFLOADER_DEBUG
|
#ifdef ELFLOADER_DEBUG
|
||||||
|
@ -45,7 +45,7 @@ bool ELFLoader::layout()
|
||||||
allocate_section(program_header.laddr(), program_header.size_in_memory(), program_header.alignment(), program_header.is_readable(), program_header.is_writable());
|
allocate_section(program_header.laddr(), program_header.size_in_memory(), program_header.alignment(), program_header.is_readable(), program_header.is_writable());
|
||||||
});
|
});
|
||||||
|
|
||||||
m_image->forEachSectionOfType(SHT_PROGBITS, [this, &failed] (const ELFImage::Section& section) {
|
m_image.for_each_section_of_type(SHT_PROGBITS, [this, &failed] (const ELFImage::Section& section) {
|
||||||
#ifdef ELFLOADER_DEBUG
|
#ifdef ELFLOADER_DEBUG
|
||||||
kprintf("ELFLoader: Copying progbits section: %s\n", section.name());
|
kprintf("ELFLoader: Copying progbits section: %s\n", section.name());
|
||||||
#endif
|
#endif
|
||||||
|
@ -58,11 +58,11 @@ bool ELFLoader::layout()
|
||||||
#endif
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
memcpy(ptr, section.rawData(), section.size());
|
memcpy(ptr, section.raw_data(), section.size());
|
||||||
m_sections.set(section.name(), move(ptr));
|
m_sections.set(section.name(), move(ptr));
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
m_image->forEachSectionOfType(SHT_NOBITS, [this, &failed] (const ELFImage::Section& section) {
|
m_image.for_each_section_of_type(SHT_NOBITS, [this, &failed] (const ELFImage::Section& section) {
|
||||||
#ifdef ELFLOADER_DEBUG
|
#ifdef ELFLOADER_DEBUG
|
||||||
kprintf("ELFLoader: Copying nobits section: %s\n", section.name());
|
kprintf("ELFLoader: Copying nobits section: %s\n", section.name());
|
||||||
#endif
|
#endif
|
||||||
|
@ -83,17 +83,17 @@ bool ELFLoader::layout()
|
||||||
|
|
||||||
void* ELFLoader::lookup(const ELFImage::Symbol& symbol)
|
void* ELFLoader::lookup(const ELFImage::Symbol& symbol)
|
||||||
{
|
{
|
||||||
if (symbol.section().isUndefined())
|
if (symbol.section().is_undefined())
|
||||||
return symbol_ptr(symbol.name());
|
return symbol_ptr(symbol.name());
|
||||||
return areaForSection(symbol.section()) + symbol.value();
|
return area_for_section(symbol.section()) + symbol.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
char* ELFLoader::areaForSection(const ELFImage::Section& section)
|
char* ELFLoader::area_for_section(const ELFImage::Section& section)
|
||||||
{
|
{
|
||||||
return areaForSectionName(section.name());
|
return area_for_section_name(section.name());
|
||||||
}
|
}
|
||||||
|
|
||||||
char* ELFLoader::areaForSectionName(const char* name)
|
char* ELFLoader::area_for_section_name(const char* name)
|
||||||
{
|
{
|
||||||
if (auto it = m_sections.find(name); it != m_sections.end())
|
if (auto it = m_sections.find(name); it != m_sections.end())
|
||||||
return (*it).value;
|
return (*it).value;
|
||||||
|
@ -101,7 +101,7 @@ char* ELFLoader::areaForSectionName(const char* name)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ELFLoader::performRelocations()
|
bool ELFLoader::perform_relocations()
|
||||||
{
|
{
|
||||||
#ifdef ELFLOADER_DEBUG
|
#ifdef ELFLOADER_DEBUG
|
||||||
kprintf("ELFLoader: Performing relocations\n");
|
kprintf("ELFLoader: Performing relocations\n");
|
||||||
|
@ -109,34 +109,34 @@ bool ELFLoader::performRelocations()
|
||||||
|
|
||||||
bool failed = false;
|
bool failed = false;
|
||||||
|
|
||||||
m_image->forEachSectionOfType(SHT_PROGBITS, [this, &failed] (const ELFImage::Section& section) -> bool {
|
m_image.for_each_section_of_type(SHT_PROGBITS, [this, &failed] (const ELFImage::Section& section) -> bool {
|
||||||
auto& relocations = section.relocations();
|
auto& relocations = section.relocations();
|
||||||
if (relocations.isUndefined())
|
if (relocations.is_undefined())
|
||||||
return true;
|
return true;
|
||||||
relocations.forEachRelocation([this, section, &failed] (const ELFImage::Relocation& relocation) {
|
relocations.for_each_relocation([this, section, &failed] (const ELFImage::Relocation& relocation) {
|
||||||
auto symbol = relocation.symbol();
|
auto symbol = relocation.symbol();
|
||||||
auto& patchPtr = *reinterpret_cast<ptrdiff_t*>(areaForSection(section) + relocation.offset());
|
auto& patch_ptr = *reinterpret_cast<ptrdiff_t*>(area_for_section(section) + relocation.offset());
|
||||||
|
|
||||||
switch (relocation.type()) {
|
switch (relocation.type()) {
|
||||||
case R_386_PC32: {
|
case R_386_PC32: {
|
||||||
char* targetPtr = (char*)lookup(symbol);
|
char* target_ptr = (char*)lookup(symbol);
|
||||||
if (!targetPtr) {
|
if (!target_ptr) {
|
||||||
kprintf("ELFLoader: unresolved symbol '%s'\n", symbol.name());
|
kprintf("ELFLoader: unresolved symbol '%s'\n", symbol.name());
|
||||||
failed = true;
|
failed = true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ptrdiff_t relativeOffset = (char*)targetPtr - ((char*)&patchPtr + 4);
|
ptrdiff_t relativeOffset = (char*)target_ptr - ((char*)&patch_ptr + 4);
|
||||||
#ifdef ELFLOADER_DEBUG
|
#ifdef ELFLOADER_DEBUG
|
||||||
kprintf("ELFLoader: Relocate PC32: offset=%x, symbol=%u(%s) value=%x target=%p, offset=%d\n",
|
kprintf("ELFLoader: Relocate PC32: offset=%x, symbol=%u(%s) value=%x target=%p, offset=%d\n",
|
||||||
relocation.offset(),
|
relocation.offset(),
|
||||||
symbol.index(),
|
symbol.index(),
|
||||||
symbol.name(),
|
symbol.name(),
|
||||||
symbol.value(),
|
symbol.value(),
|
||||||
targetPtr,
|
target_ptr,
|
||||||
relativeOffset
|
relativeOffset
|
||||||
);
|
);
|
||||||
#endif
|
#endif
|
||||||
patchPtr = relativeOffset;
|
patch_ptr = relativeOffset;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case R_386_32: {
|
case R_386_32: {
|
||||||
|
@ -148,8 +148,8 @@ bool ELFLoader::performRelocations()
|
||||||
symbol.section().name()
|
symbol.section().name()
|
||||||
);
|
);
|
||||||
#endif
|
#endif
|
||||||
char* targetPtr = areaForSection(symbol.section()) + symbol.value();
|
char* target_ptr = area_for_section(symbol.section()) + symbol.value();
|
||||||
patchPtr += (ptrdiff_t)targetPtr;
|
patch_ptr += (ptrdiff_t)target_ptr;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -163,18 +163,18 @@ bool ELFLoader::performRelocations()
|
||||||
return !failed;
|
return !failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ELFLoader::exportSymbols()
|
void ELFLoader::export_symbols()
|
||||||
{
|
{
|
||||||
m_image->forEachSymbol([&] (const ELFImage::Symbol symbol) {
|
m_image.for_each_symbol([&] (const ELFImage::Symbol symbol) {
|
||||||
#ifdef ELFLOADER_DEBUG
|
#ifdef ELFLOADER_DEBUG
|
||||||
kprintf("symbol: %u, type=%u, name=%s, section=%u\n", symbol.index(), symbol.type(), symbol.name(), symbol.sectionIndex());
|
kprintf("symbol: %u, type=%u, name=%s, section=%u\n", symbol.index(), symbol.type(), symbol.name(), symbol.sectionIndex());
|
||||||
#endif
|
#endif
|
||||||
if (symbol.type() == STT_FUNC) {
|
if (symbol.type() == STT_FUNC) {
|
||||||
char* ptr;
|
char* ptr;
|
||||||
if (m_image->isExecutable())
|
if (m_image.is_executable())
|
||||||
ptr = (char*)symbol.value();
|
ptr = (char*)symbol.value();
|
||||||
else if (m_image->isRelocatable())
|
else if (m_image.is_relocatable())
|
||||||
ptr = areaForSection(symbol.section()) + symbol.value();
|
ptr = area_for_section(symbol.section()) + symbol.value();
|
||||||
else
|
else
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
add_symbol(symbol.name(), ptr, symbol.size());
|
add_symbol(symbol.name(), ptr, symbol.size());
|
||||||
|
|
|
@ -19,11 +19,11 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool layout();
|
bool layout();
|
||||||
bool performRelocations();
|
bool perform_relocations();
|
||||||
void exportSymbols();
|
void export_symbols();
|
||||||
void* lookup(const ELFImage::Symbol&);
|
void* lookup(const ELFImage::Symbol&);
|
||||||
char* areaForSection(const ELFImage::Section&);
|
char* area_for_section(const ELFImage::Section&);
|
||||||
char* areaForSectionName(const char*);
|
char* area_for_section_name(const char*);
|
||||||
|
|
||||||
struct PtrAndSize {
|
struct PtrAndSize {
|
||||||
PtrAndSize() { }
|
PtrAndSize() { }
|
||||||
|
@ -36,8 +36,9 @@ private:
|
||||||
char* ptr { nullptr };
|
char* ptr { nullptr };
|
||||||
unsigned size { 0 };
|
unsigned size { 0 };
|
||||||
};
|
};
|
||||||
|
ELFImage m_image;
|
||||||
|
|
||||||
HashMap<String, PtrAndSize> m_symbols;
|
HashMap<String, PtrAndSize> m_symbols;
|
||||||
HashMap<String, char*> m_sections;
|
HashMap<String, char*> m_sections;
|
||||||
OwnPtr<ELFImage> m_image;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ void __assertion_failed(const char* msg, const char* file, unsigned line, const
|
||||||
{
|
{
|
||||||
fprintf(stderr, "ASSERTION FAILED: %s\n%s:%u in %s\n", msg, file, line, func);
|
fprintf(stderr, "ASSERTION FAILED: %s\n%s:%u in %s\n", msg, file, line, func);
|
||||||
abort();
|
abort();
|
||||||
|
for (;;);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue