summaryrefslogtreecommitdiff
path: root/Libraries/LibELF
diff options
context:
space:
mode:
Diffstat (limited to 'Libraries/LibELF')
-rw-r--r--Libraries/LibELF/ELFImage.cpp44
-rw-r--r--Libraries/LibELF/ELFImage.h51
-rw-r--r--Libraries/LibELF/exec_elf.h3
3 files changed, 94 insertions, 4 deletions
diff --git a/Libraries/LibELF/ELFImage.cpp b/Libraries/LibELF/ELFImage.cpp
index dedfea994c..51d14ba459 100644
--- a/Libraries/LibELF/ELFImage.cpp
+++ b/Libraries/LibELF/ELFImage.cpp
@@ -106,14 +106,21 @@ bool ELFImage::parse()
for (unsigned i = 0; i < section_count(); ++i) {
auto& sh = section_header(i);
if (sh.sh_type == SHT_SYMTAB) {
- ASSERT(!m_symbol_table_section_index);
+ ASSERT(!m_symbol_table_section_index || m_symbol_table_section_index == i);
m_symbol_table_section_index = i;
}
if (sh.sh_type == SHT_STRTAB && i != header().e_shstrndx) {
- ASSERT(!m_string_table_section_index);
+ ASSERT(!m_string_table_section_index || m_string_table_section_index == i);
m_string_table_section_index = i;
}
}
+
+ // Then create a name-to-index map.
+ for (unsigned i = 0; i < section_count(); ++i) {
+ auto& section = this->section(i);
+ m_sections.set(section.name(), move(i));
+ }
+
return true;
}
@@ -173,3 +180,36 @@ const ELFImage::ProgramHeader ELFImage::program_header(unsigned index) const
ASSERT(index < program_header_count());
return ProgramHeader(*this, index);
}
+
+const ELFImage::Relocation ELFImage::RelocationSection::relocation(unsigned index) const
+{
+ ASSERT(index < relocation_count());
+ auto* rels = reinterpret_cast<const Elf32_Rel*>(m_image.raw_data(offset()));
+ return Relocation(m_image, rels[index]);
+}
+
+const ELFImage::RelocationSection ELFImage::Section::relocations() const
+{
+ // FIXME: This is ugly.
+ char relocation_sectionName[128];
+ sprintf(relocation_sectionName, ".rel%s", name());
+
+#ifdef ELFIMAGE_DEBUG
+ kprintf("looking for '%s'\n", relocation_sectionName);
+#endif
+ auto relocation_section = m_image.lookup_section(relocation_sectionName);
+ if (relocation_section.type() != SHT_REL)
+ return static_cast<const RelocationSection>(m_image.section(0));
+
+#ifdef ELFIMAGE_DEBUG
+ kprintf("Found relocations for %s in %s\n", name(), relocation_section.name());
+#endif
+ return static_cast<const RelocationSection>(relocation_section);
+}
+
+const ELFImage::Section ELFImage::lookup_section(const char* name) const
+{
+ if (auto it = m_sections.find(name); it != m_sections.end())
+ return section((*it).value);
+ return section(0);
+}
diff --git a/Libraries/LibELF/ELFImage.h b/Libraries/LibELF/ELFImage.h
index 143b4005e7..9ad48a50dc 100644
--- a/Libraries/LibELF/ELFImage.h
+++ b/Libraries/LibELF/ELFImage.h
@@ -1,8 +1,8 @@
#pragma once
-#include <AK/String.h>
#include <AK/HashMap.h>
#include <AK/OwnPtr.h>
+#include <AK/String.h>
#include <Kernel/VM/VirtualAddress.h>
#include <LibELF/exec_elf.h>
@@ -92,6 +92,7 @@ public:
u32 address() const { return m_section_header.sh_addr; }
const char* raw_data() const { return m_image.raw_data(m_section_header.sh_offset); }
bool is_undefined() const { return m_section_index == SHN_UNDEF; }
+ const RelocationSection relocations() const;
u32 flags() const { return m_section_header.sh_flags; }
bool is_writable() const { return flags() & SHF_WRITE; }
bool is_executable() const { return flags() & PF_X; }
@@ -103,6 +104,38 @@ public:
unsigned m_section_index;
};
+ class RelocationSection : public Section {
+ public:
+ RelocationSection(const Section& section)
+ : Section(section.m_image, section.m_section_index)
+ {
+ }
+ unsigned relocation_count() const { return entry_count(); }
+ const Relocation relocation(unsigned index) const;
+ template<typename F>
+ void for_each_relocation(F) const;
+ };
+
+ class Relocation {
+ public:
+ Relocation(const ELFImage& image, const Elf32_Rel& rel)
+ : m_image(image)
+ , m_rel(rel)
+ {
+ }
+
+ ~Relocation() {}
+
+ unsigned offset() const { return m_rel.r_offset; }
+ unsigned type() const { return ELF32_R_TYPE(m_rel.r_info); }
+ unsigned symbol_index() const { return ELF32_R_SYM(m_rel.r_info); }
+ const Symbol symbol() const { return m_image.symbol(symbol_index()); }
+
+ private:
+ const ELFImage& m_image;
+ const Elf32_Rel& m_rel;
+ };
+
unsigned symbol_count() const;
unsigned section_count() const;
unsigned program_header_count() const;
@@ -120,6 +153,10 @@ public:
template<typename F>
void for_each_program_header(F) const;
+ // NOTE: Returns section(0) if section with name is not found.
+ // FIXME: I don't love this API.
+ const Section lookup_section(const char* name) const;
+
bool is_executable() const { return header().e_type == ET_EXEC; }
bool is_relocatable() const { return header().e_type == ET_REL; }
@@ -136,6 +173,7 @@ private:
const char* section_index_to_string(unsigned index) const;
const u8* m_buffer { nullptr };
+ HashMap<String, unsigned> m_sections;
bool m_valid { false };
unsigned m_symbol_table_section_index { 0 };
unsigned m_string_table_section_index { 0 };
@@ -154,13 +192,22 @@ inline void ELFImage::for_each_section_of_type(unsigned type, F func) const
for (unsigned i = 0; i < section_count(); ++i) {
auto& section = this->section(i);
if (section.type() == type) {
- if (!func(section))
+ if (func(section) == IterationDecision::Break)
break;
}
}
}
template<typename F>
+inline void ELFImage::RelocationSection::for_each_relocation(F func) const
+{
+ for (unsigned i = 0; i < relocation_count(); ++i) {
+ if (func(relocation(i)) == IterationDecision::Break)
+ break;
+ }
+}
+
+template<typename F>
inline void ELFImage::for_each_symbol(F func) const
{
for (unsigned i = 0; i < symbol_count(); ++i) {
diff --git a/Libraries/LibELF/exec_elf.h b/Libraries/LibELF/exec_elf.h
index 90dca3a6e3..2be5076801 100644
--- a/Libraries/LibELF/exec_elf.h
+++ b/Libraries/LibELF/exec_elf.h
@@ -775,4 +775,7 @@ struct elf_args {
#define ELF_TARG_VER 1 /* The ver for which this code is intended */
+#define R_386_32 1
+#define R_386_PC32 2
+
#endif /* _SYS_EXEC_ELF_H_ */