From 71d92cef1712b02f0f2085d6b5f10a78cfd07d79 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Sun, 20 Dec 2020 15:45:39 +0100 Subject: [PATCH] UserspaceEmulator: Add lazy caching of debug info for shared libraries Keep the debug symbols for shared libraries in memory after we opened them the first time. This dramatically speeds up symbolication of backtraces when running dynamically linked programs in UE. --- DevTools/UserspaceEmulator/Emulator.cpp | 27 +++++++++++++++---------- DevTools/UserspaceEmulator/Emulator.h | 9 +++++++++ 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/DevTools/UserspaceEmulator/Emulator.cpp b/DevTools/UserspaceEmulator/Emulator.cpp index f60b265d3a..5103ce1502 100644 --- a/DevTools/UserspaceEmulator/Emulator.cpp +++ b/DevTools/UserspaceEmulator/Emulator.cpp @@ -302,24 +302,29 @@ String Emulator::create_backtrace_line(FlatPtr address) String lib_name = region->name().substring(0, separator_index.value()); String lib_path = lib_name; if (region->name().contains(".so")) - lib_path = String::format("/usr/lib/%s", lib_path.characters()); + lib_path = String::formatted("/usr/lib/{}", lib_path); - auto mapped_file = make(lib_path); - if (!mapped_file->is_valid()) - return minimal; + if (!m_dynamic_library_cache.contains(lib_path)) { + MappedFile mapped_file { lib_path }; + if (!mapped_file.is_valid()) + return minimal; - auto loader = ELF::Loader::create((const u8*)mapped_file->data(), mapped_file->size()); - String symbol = loader->symbolicate(address - region->base()); + auto loader = ELF::Loader::create((const u8*)mapped_file.data(), mapped_file.size()); + auto debug_info = make(loader); + m_dynamic_library_cache.set(lib_path, CachedELF { move(mapped_file), move(loader), move(debug_info) }); + } + + auto it = m_dynamic_library_cache.find(lib_path); + auto& loader = *it->value.elf_loader; + String symbol = loader.symbolicate(address - region->base()); auto line_without_source_info = String::format("=={%d}== %p [%s]: %s", getpid(), address, lib_name.characters(), symbol.characters()); - auto debug_info = make(loader); - auto source_position = debug_info->get_source_position(address - region->base()); + auto source_position = it->value.debug_info->get_source_position(address - region->base()); if (source_position.has_value()) return String::format("=={%d}== %p [%s]: %s (\033[34;1m%s\033[0m:%u)", getpid(), address, lib_name.characters(), symbol.characters(), LexicalPath(source_position.value().file_path).basename().characters(), source_position.value().line_number); - else { - return line_without_source_info; - } + + return line_without_source_info; } void Emulator::dump_backtrace(const Vector& backtrace) diff --git a/DevTools/UserspaceEmulator/Emulator.h b/DevTools/UserspaceEmulator/Emulator.h index 67e8943817..aa43fdf2f1 100644 --- a/DevTools/UserspaceEmulator/Emulator.h +++ b/DevTools/UserspaceEmulator/Emulator.h @@ -30,6 +30,7 @@ #include "Report.h" #include "SoftCPU.h" #include "SoftMMU.h" +#include #include #include #include @@ -200,6 +201,14 @@ private: FlatPtr m_signal_trampoline { 0 }; Optional m_loader_text_base; Optional m_loader_text_size; + + struct CachedELF { + MappedFile mapped_file; + NonnullRefPtr elf_loader; + OwnPtr debug_info; + }; + + HashMap m_dynamic_library_cache; }; ALWAYS_INLINE bool Emulator::is_in_malloc_or_free() const