summaryrefslogtreecommitdiff
path: root/Libraries/LibELF
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2020-04-11 18:45:17 +0200
committerAndreas Kling <kling@serenityos.org>2020-04-11 18:45:17 +0200
commit5b91d848a7f4bdb0a197acb32e16c6cdf428db83 (patch)
treea098e1a64ba9195bc48dabbdbabc83a658fcaa92 /Libraries/LibELF
parent31d0dbe2a05090b670cfa5005e8e008a15ccc968 (diff)
downloadserenity-5b91d848a7f4bdb0a197acb32e16c6cdf428db83.zip
LibELF: Add a find_symbol() API that finds a Symbol for an address
Also add ELFImage::Symbol::raw_data() to get a StringView containing the entire symbol contents.
Diffstat (limited to 'Libraries/LibELF')
-rw-r--r--Libraries/LibELF/ELFImage.cpp6
-rw-r--r--Libraries/LibELF/ELFImage.h1
-rw-r--r--Libraries/LibELF/ELFLoader.cpp52
-rw-r--r--Libraries/LibELF/ELFLoader.h2
4 files changed, 60 insertions, 1 deletions
diff --git a/Libraries/LibELF/ELFImage.cpp b/Libraries/LibELF/ELFImage.cpp
index 815b272561..a2bff5b2ce 100644
--- a/Libraries/LibELF/ELFImage.cpp
+++ b/Libraries/LibELF/ELFImage.cpp
@@ -414,3 +414,9 @@ bool ELFImage::validate_program_headers(const Elf32_Ehdr& elf_header, size_t fil
}
return true;
}
+
+StringView ELFImage::Symbol::raw_data() const
+{
+ auto& section = this->section();
+ return { section.raw_data() + (value() - section.address()), size() };
+}
diff --git a/Libraries/LibELF/ELFImage.h b/Libraries/LibELF/ELFImage.h
index 2dc0aa857a..61f912079d 100644
--- a/Libraries/LibELF/ELFImage.h
+++ b/Libraries/LibELF/ELFImage.h
@@ -73,6 +73,7 @@ public:
unsigned type() const { return ELF32_ST_TYPE(m_sym.st_info); }
unsigned bind() const { return ELF32_ST_BIND(m_sym.st_info); }
const Section section() const { return m_image.section(section_index()); }
+ StringView raw_data() const;
private:
const ELFImage& m_image;
diff --git a/Libraries/LibELF/ELFLoader.cpp b/Libraries/LibELF/ELFLoader.cpp
index b2952d1ad5..27c5cd0bed 100644
--- a/Libraries/LibELF/ELFLoader.cpp
+++ b/Libraries/LibELF/ELFLoader.cpp
@@ -151,6 +151,56 @@ char* ELFLoader::symbol_ptr(const char* name)
return found_ptr;
}
+#ifndef KERNEL
+Optional<ELFImage::Symbol> ELFLoader::find_symbol(u32 address, u32* out_offset) const
+{
+ if (!m_symbol_count)
+ return {};
+
+ SortedSymbol* sorted_symbols = nullptr;
+#ifdef KERNEL
+ if (!m_sorted_symbols_region) {
+ m_sorted_symbols_region = MM.allocate_kernel_region(PAGE_ROUND_UP(m_symbol_count * sizeof(SortedSymbol)), "Sorted symbols", Kernel::Region::Access::Read | Kernel::Region::Access::Write);
+ sorted_symbols = (SortedSymbol*)m_sorted_symbols_region->vaddr().as_ptr();
+ size_t index = 0;
+ m_image.for_each_symbol([&](auto& symbol) {
+ sorted_symbols[index++] = { symbol.value(), symbol.name() };
+ return IterationDecision::Continue;
+ });
+ quick_sort(sorted_symbols, sorted_symbols + m_symbol_count, [](auto& a, auto& b) {
+ return a.address < b.address;
+ });
+ } else {
+ sorted_symbols = (SortedSymbol*)m_sorted_symbols_region->vaddr().as_ptr();
+ }
+#else
+ if (m_sorted_symbols.is_empty()) {
+ m_sorted_symbols.ensure_capacity(m_symbol_count);
+ m_image.for_each_symbol([this](auto& symbol) {
+ m_sorted_symbols.append({ symbol.value(), symbol.name(), {}, symbol });
+ return IterationDecision::Continue;
+ });
+ quick_sort(m_sorted_symbols, [](auto& a, auto& b) {
+ return a.address < b.address;
+ });
+ }
+ sorted_symbols = m_sorted_symbols.data();
+#endif
+
+ for (size_t i = 0; i < m_symbol_count; ++i) {
+ if (sorted_symbols[i].address > address) {
+ if (i == 0)
+ return {};
+ auto& symbol = sorted_symbols[i - 1];
+ if (out_offset)
+ *out_offset = address - symbol.address;
+ return symbol.symbol;
+ }
+ }
+ return {};
+}
+#endif
+
String ELFLoader::symbolicate(u32 address, u32* out_offset) const
{
if (!m_symbol_count) {
@@ -178,7 +228,7 @@ String ELFLoader::symbolicate(u32 address, u32* out_offset) const
if (m_sorted_symbols.is_empty()) {
m_sorted_symbols.ensure_capacity(m_symbol_count);
m_image.for_each_symbol([this](auto& symbol) {
- m_sorted_symbols.append({ symbol.value(), symbol.name(), {} });
+ m_sorted_symbols.append({ symbol.value(), symbol.name(), {}, {} });
return IterationDecision::Continue;
});
quick_sort(m_sorted_symbols, [](auto& a, auto& b) {
diff --git a/Libraries/LibELF/ELFLoader.h b/Libraries/LibELF/ELFLoader.h
index d2ab9627ac..49fe5ad414 100644
--- a/Libraries/LibELF/ELFLoader.h
+++ b/Libraries/LibELF/ELFLoader.h
@@ -57,6 +57,7 @@ public:
bool has_symbols() const { return m_symbol_count; }
String symbolicate(u32 address, u32* offset = nullptr) const;
+ Optional<ELFImage::Symbol> find_symbol(u32 address, u32* offset = nullptr) const;
private:
bool layout();
@@ -85,6 +86,7 @@ private:
StringView name;
#ifndef KERNEL
String demangled_name;
+ Optional<ELFImage::Symbol> symbol;
#endif
};
#ifdef KERNEL