summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Kling <awesomekling@gmail.com>2019-06-27 10:49:49 +0200
committerAndreas Kling <awesomekling@gmail.com>2019-06-27 10:49:49 +0200
commitf83263a72b49568592389b49cc4095ca0a934ffc (patch)
treef264a2cf286ccbb9aed7e2c1b66c7c7531f107de
parent7a3f59ae3fc29e144c0bd937aa0581cf53bfa629 (diff)
downloadserenity-f83263a72b49568592389b49cc4095ca0a934ffc.zip
Kernel: Use a raw VM region for sorting ELF symbols instead of a Vector.
This avoids putting pressure on kmalloc() during backtrace symbolication. Since we dump backtrace for every process that exits, this is actually a decent performance improvement for things like GCC that chain a lot of processes together.
-rw-r--r--AK/ELF/ELFLoader.cpp30
-rw-r--r--AK/ELF/ELFLoader.h12
2 files changed, 36 insertions, 6 deletions
diff --git a/AK/ELF/ELFLoader.cpp b/AK/ELF/ELFLoader.cpp
index 895108b90c..6bc84f65b4 100644
--- a/AK/ELF/ELFLoader.cpp
+++ b/AK/ELF/ELFLoader.cpp
@@ -2,6 +2,10 @@
#include <AK/QuickSort.h>
#include <AK/kstdio.h>
+#ifdef KERNEL
+#include <Kernel/VM/MemoryManager.h>
+#endif
+
//#define ELFLOADER_DEBUG
ELFLoader::ELFLoader(const byte* buffer)
@@ -79,6 +83,24 @@ char* ELFLoader::symbol_ptr(const char* name)
String ELFLoader::symbolicate(dword address) 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");
+ sorted_symbols = (SortedSymbol*)m_sorted_symbols_region->vaddr().as_ptr();
+ dbgprintf("sorted_symbols: %p\n", sorted_symbols);
+ 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) {
+ 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_image.symbol_count());
m_image.for_each_symbol([this](auto& symbol) {
@@ -89,12 +111,14 @@ String ELFLoader::symbolicate(dword address) const
return a.address < b.address;
});
}
+ sorted_symbols = m_sorted_symbols.data();
+#endif
- for (int i = 0; i < m_sorted_symbols.size(); ++i) {
- if (m_sorted_symbols[i].address > address) {
+ for (size_t i = 0; i < m_image.symbol_count(); ++i) {
+ if (sorted_symbols[i].address > address) {
if (i == 0)
return "!!";
- auto& symbol = m_sorted_symbols[i - 1];
+ auto& symbol = sorted_symbols[i - 1];
return String::format("%s +%u", symbol.name, address - symbol.address);
}
}
diff --git a/AK/ELF/ELFLoader.h b/AK/ELF/ELFLoader.h
index e3c3ab4098..3803726a29 100644
--- a/AK/ELF/ELFLoader.h
+++ b/AK/ELF/ELFLoader.h
@@ -4,11 +4,13 @@
#include <AK/HashMap.h>
#include <AK/OwnPtr.h>
#include <AK/Vector.h>
-#if defined(KERNEL)
-# include <Kernel/VirtualAddress.h>
-#endif
#include <AK/ELF/ELFImage.h>
+#ifdef KERNEL
+#include <Kernel/VirtualAddress.h>
+class Region;
+#endif
+
class ELFLoader {
public:
explicit ELFLoader(const byte*);
@@ -50,5 +52,9 @@ private:
dword address;
const char* name;
};
+#ifdef KERNEL
+ mutable RefPtr<Region> m_sorted_symbols_region;
+#else
mutable Vector<SortedSymbol> m_sorted_symbols;
+#endif
};