diff options
author | Andreas Kling <kling@serenityos.org> | 2020-04-11 18:45:17 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-04-11 18:45:17 +0200 |
commit | 5b91d848a7f4bdb0a197acb32e16c6cdf428db83 (patch) | |
tree | a098e1a64ba9195bc48dabbdbabc83a658fcaa92 /Libraries/LibELF | |
parent | 31d0dbe2a05090b670cfa5005e8e008a15ccc968 (diff) | |
download | serenity-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.cpp | 6 | ||||
-rw-r--r-- | Libraries/LibELF/ELFImage.h | 1 | ||||
-rw-r--r-- | Libraries/LibELF/ELFLoader.cpp | 52 | ||||
-rw-r--r-- | Libraries/LibELF/ELFLoader.h | 2 |
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 |