summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2020-04-07 16:41:42 +0200
committerAndreas Kling <kling@serenityos.org>2020-04-07 16:41:42 +0200
commita31ef54a2a97864187bba71618aed5abeaeef70a (patch)
treeb713a1a0e8e73cc4a87253e7aa737f7494955e3e
parent992d8e450c20bb5083cb3279e5f4a19016f6a5c7 (diff)
downloadserenity-a31ef54a2a97864187bba71618aed5abeaeef70a.zip
LibELF: Cache symbol counts + demangled names (userspace only)
To make repeated symbolication requests faster, we now cache the symbol count on ELFLoader instead of looking it up in the image each time. We also cache the demangled versions of names after looking them up the first time. This is a huge speedup for ProfileViewer. :^)
-rw-r--r--Libraries/LibELF/ELFLoader.cpp26
-rw-r--r--Libraries/LibELF/ELFLoader.h7
2 files changed, 24 insertions, 9 deletions
diff --git a/Libraries/LibELF/ELFLoader.cpp b/Libraries/LibELF/ELFLoader.cpp
index e5a30b31fe..b2952d1ad5 100644
--- a/Libraries/LibELF/ELFLoader.cpp
+++ b/Libraries/LibELF/ELFLoader.cpp
@@ -41,6 +41,7 @@
ELFLoader::ELFLoader(const u8* buffer, size_t size)
: m_image(buffer, size)
{
+ m_symbol_count = m_image.symbol_count();
}
ELFLoader::~ELFLoader()
@@ -152,7 +153,7 @@ char* ELFLoader::symbol_ptr(const char* name)
String ELFLoader::symbolicate(u32 address, u32* out_offset) const
{
- if (!m_image.symbol_count()) {
+ if (!m_symbol_count) {
if (out_offset)
*out_offset = 0;
return "??";
@@ -160,14 +161,14 @@ String ELFLoader::symbolicate(u32 address, u32* out_offset) const
SortedSymbol* sorted_symbols = nullptr;
#ifdef KERNEL
if (!m_sorted_symbols_region) {
- m_sorted_symbols_region = MM.allocate_kernel_region(PAGE_ROUND_UP(m_image.symbol_count() * sizeof(SortedSymbol)), "Sorted symbols", Kernel::Region::Access::Read | Kernel::Region::Access::Write);
+ 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_image.symbol_count(), [](auto& a, auto& b) {
+ quick_sort(sorted_symbols, sorted_symbols + m_symbol_count, [](auto& a, auto& b) {
return a.address < b.address;
});
} else {
@@ -175,9 +176,9 @@ String ELFLoader::symbolicate(u32 address, u32* out_offset) const
}
#else
if (m_sorted_symbols.is_empty()) {
- m_sorted_symbols.ensure_capacity(m_image.symbol_count());
+ 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) {
@@ -187,7 +188,7 @@ String ELFLoader::symbolicate(u32 address, u32* out_offset) const
sorted_symbols = m_sorted_symbols.data();
#endif
- for (size_t i = 0; i < m_image.symbol_count(); ++i) {
+ for (size_t i = 0; i < m_symbol_count; ++i) {
if (sorted_symbols[i].address > address) {
if (i == 0) {
if (out_offset)
@@ -195,11 +196,20 @@ String ELFLoader::symbolicate(u32 address, u32* out_offset) const
return "!!";
}
auto& symbol = sorted_symbols[i - 1];
+
+#ifdef KERNEL
+ auto demangled_name = demangle(symbol.name);
+#else
+ auto& demangled_name = symbol.demangled_name;
+ if (demangled_name.is_null())
+ demangled_name = demangle(symbol.name);
+#endif
+
if (out_offset) {
*out_offset = address - symbol.address;
- return demangle(symbol.name);
+ return demangled_name;
}
- return String::format("%s +%u", demangle(symbol.name).characters(), address - symbol.address);
+ return String::format("%s +%u", demangled_name.characters(), address - symbol.address);
}
}
if (out_offset)
diff --git a/Libraries/LibELF/ELFLoader.h b/Libraries/LibELF/ELFLoader.h
index f0e51bc8ea..d2ab9627ac 100644
--- a/Libraries/LibELF/ELFLoader.h
+++ b/Libraries/LibELF/ELFLoader.h
@@ -54,7 +54,7 @@ public:
#endif
char* symbol_ptr(const char* name);
- bool has_symbols() const { return m_image.symbol_count(); }
+ bool has_symbols() const { return m_symbol_count; }
String symbolicate(u32 address, u32* offset = nullptr) const;
@@ -78,9 +78,14 @@ private:
};
ELFImage m_image;
+ size_t m_symbol_count { 0 };
+
struct SortedSymbol {
u32 address;
StringView name;
+#ifndef KERNEL
+ String demangled_name;
+#endif
};
#ifdef KERNEL
mutable OwnPtr<Kernel::Region> m_sorted_symbols_region;