mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 07:07:34 +00:00
LibELF: Use binary search when looking up symbols :^)
For whatever reason, symbolication was doing an O(n) walk of all the symbols, despite having sorted them beforehand. Changing this to a binary_search() makes symbolication noticeably faster and improves Profiler startup time.
This commit is contained in:
parent
ef09f9c825
commit
b31602367e
2 changed files with 49 additions and 56 deletions
|
@ -4,6 +4,7 @@
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <AK/BinarySearch.h>
|
||||||
#include <AK/Debug.h>
|
#include <AK/Debug.h>
|
||||||
#include <AK/Demangle.h>
|
#include <AK/Demangle.h>
|
||||||
#include <AK/Memory.h>
|
#include <AK/Memory.h>
|
||||||
|
@ -309,36 +310,45 @@ Optional<Image::Symbol> Image::find_demangled_function(const String& name) const
|
||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Image::SortedSymbol* Image::find_sorted_symbol(FlatPtr address) const
|
||||||
|
{
|
||||||
|
if (m_sorted_symbols.is_empty())
|
||||||
|
sort_symbols();
|
||||||
|
|
||||||
|
size_t index = 0;
|
||||||
|
binary_search(m_sorted_symbols, nullptr, &index, [&address](auto, auto& candidate) {
|
||||||
|
return address - candidate.address;
|
||||||
|
});
|
||||||
|
// FIXME: The error path here feels strange, index == 0 means error but what about symbol #0?
|
||||||
|
if (index == 0)
|
||||||
|
return nullptr;
|
||||||
|
return &m_sorted_symbols[index];
|
||||||
|
}
|
||||||
|
|
||||||
Optional<Image::Symbol> Image::find_symbol(u32 address, u32* out_offset) const
|
Optional<Image::Symbol> Image::find_symbol(u32 address, u32* out_offset) const
|
||||||
{
|
{
|
||||||
auto symbol_count = this->symbol_count();
|
auto symbol_count = this->symbol_count();
|
||||||
if (!symbol_count)
|
if (!symbol_count)
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
SortedSymbol* sorted_symbols = nullptr;
|
auto* symbol = find_sorted_symbol(address);
|
||||||
if (m_sorted_symbols.is_empty()) {
|
if (!symbol)
|
||||||
m_sorted_symbols.ensure_capacity(symbol_count);
|
return {};
|
||||||
for_each_symbol([this](const auto& symbol) {
|
if (out_offset)
|
||||||
m_sorted_symbols.append({ symbol.value(), symbol.name(), {}, symbol });
|
*out_offset = address - symbol->address;
|
||||||
return IterationDecision::Continue;
|
return symbol->symbol;
|
||||||
});
|
}
|
||||||
quick_sort(m_sorted_symbols, [](auto& a, auto& b) {
|
|
||||||
return a.address < b.address;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
sorted_symbols = m_sorted_symbols.data();
|
|
||||||
|
|
||||||
for (size_t i = 0; i < symbol_count; ++i) {
|
NEVER_INLINE void Image::sort_symbols() const
|
||||||
if (sorted_symbols[i].address > address) {
|
{
|
||||||
if (i == 0)
|
m_sorted_symbols.ensure_capacity(symbol_count());
|
||||||
return {};
|
for_each_symbol([this](const auto& symbol) {
|
||||||
auto& symbol = sorted_symbols[i - 1];
|
m_sorted_symbols.append({ symbol.value(), symbol.name(), {}, symbol });
|
||||||
if (out_offset)
|
return IterationDecision::Continue;
|
||||||
*out_offset = address - symbol.address;
|
});
|
||||||
return symbol.symbol;
|
quick_sort(m_sorted_symbols, [](auto& a, auto& b) {
|
||||||
}
|
return a.address < b.address;
|
||||||
}
|
});
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String Image::symbolicate(u32 address, u32* out_offset) const
|
String Image::symbolicate(u32 address, u32* out_offset) const
|
||||||
|
@ -349,43 +359,23 @@ String Image::symbolicate(u32 address, u32* out_offset) const
|
||||||
*out_offset = 0;
|
*out_offset = 0;
|
||||||
return "??";
|
return "??";
|
||||||
}
|
}
|
||||||
SortedSymbol* sorted_symbols = nullptr;
|
|
||||||
if (m_sorted_symbols.is_empty()) {
|
auto* symbol = find_sorted_symbol(address);
|
||||||
m_sorted_symbols.ensure_capacity(symbol_count);
|
if (!symbol) {
|
||||||
for_each_symbol([this](const auto& symbol) {
|
if (out_offset)
|
||||||
m_sorted_symbols.append({ symbol.value(), symbol.name(), {}, symbol });
|
*out_offset = 0;
|
||||||
return IterationDecision::Continue;
|
return "??";
|
||||||
});
|
|
||||||
quick_sort(m_sorted_symbols, [](auto& a, auto& b) {
|
|
||||||
return a.address < b.address;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
sorted_symbols = m_sorted_symbols.data();
|
|
||||||
|
|
||||||
for (size_t i = 0; i < symbol_count; ++i) {
|
auto& demangled_name = symbol->demangled_name;
|
||||||
if (sorted_symbols[i].address > address) {
|
if (demangled_name.is_null())
|
||||||
if (i == 0) {
|
demangled_name = demangle(symbol->name);
|
||||||
if (out_offset)
|
|
||||||
*out_offset = 0;
|
|
||||||
return "!!";
|
|
||||||
}
|
|
||||||
auto& symbol = sorted_symbols[i - 1];
|
|
||||||
|
|
||||||
auto& demangled_name = symbol.demangled_name;
|
if (out_offset) {
|
||||||
if (demangled_name.is_null()) {
|
*out_offset = address - symbol->address;
|
||||||
demangled_name = demangle(symbol.name);
|
return demangled_name;
|
||||||
}
|
|
||||||
|
|
||||||
if (out_offset) {
|
|
||||||
*out_offset = address - symbol.address;
|
|
||||||
return demangled_name;
|
|
||||||
}
|
|
||||||
return String::formatted("{} +{:#x}", demangled_name, address - symbol.address);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (out_offset)
|
return String::formatted("{} +{:#x}", demangled_name, address - symbol->address);
|
||||||
*out_offset = 0;
|
|
||||||
return "??";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // end namespace ELF
|
} // end namespace ELF
|
||||||
|
|
|
@ -216,6 +216,9 @@ private:
|
||||||
Optional<Image::Symbol> symbol;
|
Optional<Image::Symbol> symbol;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void sort_symbols() const;
|
||||||
|
SortedSymbol* find_sorted_symbol(FlatPtr) const;
|
||||||
|
|
||||||
mutable Vector<SortedSymbol> m_sorted_symbols;
|
mutable Vector<SortedSymbol> m_sorted_symbols;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue