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/ELFLoader.cpp | |
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/ELFLoader.cpp')
-rw-r--r-- | Libraries/LibELF/ELFLoader.cpp | 52 |
1 files changed, 51 insertions, 1 deletions
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) { |