diff --git a/Userland/DevTools/Profiler/DisassemblyModel.cpp b/Userland/DevTools/Profiler/DisassemblyModel.cpp index b058df61525..10d29b8cf11 100644 --- a/Userland/DevTools/Profiler/DisassemblyModel.cpp +++ b/Userland/DevTools/Profiler/DisassemblyModel.cpp @@ -74,7 +74,7 @@ DisassemblyModel::DisassemblyModel(Profile& profile, ProfileNode& node) dbgln("no library data"); return; } - elf = &library_data->elf; + elf = &library_data->object->elf; base_address = library_data->base; } diff --git a/Userland/DevTools/Profiler/Profile.cpp b/Userland/DevTools/Profiler/Profile.cpp index 893f02a0e54..1f61b1c3e36 100644 --- a/Userland/DevTools/Profiler/Profile.cpp +++ b/Userland/DevTools/Profiler/Profile.cpp @@ -316,7 +316,11 @@ Result, String> Profile::load_from_perfcore_file(const St library_metadata = it->library_metadata.ptr(); if (auto* library = library_metadata ? library_metadata->library_containing(ptr) : nullptr) { object_name = library->name; - symbol = library->elf.symbolicate(ptr - library->base, &offset); + if (library->object) { + symbol = library->object->elf.symbolicate(ptr - library->base, &offset); + } else { + symbol = "??"; + } } else { symbol = "??"; } @@ -401,6 +405,32 @@ GUI::Model* Profile::disassembly_model() return m_disassembly_model; } +HashMap> g_mapped_object_cache; + +static MappedObject* get_or_create_mapped_object(const String& path) +{ + if (auto it = g_mapped_object_cache.find(path); it != g_mapped_object_cache.end()) + return it->value.ptr(); + + auto file_or_error = MappedFile::map(path); + if (file_or_error.is_error()) { + g_mapped_object_cache.set(path, {}); + return nullptr; + } + auto elf = ELF::Image(file_or_error.value()->bytes()); + if (!elf.is_valid()) { + g_mapped_object_cache.set(path, {}); + return nullptr; + } + auto new_mapped_object = adopt_own(*new MappedObject { + .file = file_or_error.release_value(), + .elf = move(elf), + }); + auto* ptr = new_mapped_object.ptr(); + g_mapped_object_cache.set(path, move(new_mapped_object)); + return ptr; +} + LibraryMetadata::LibraryMetadata(JsonArray regions) : m_regions(move(regions)) { @@ -421,16 +451,11 @@ LibraryMetadata::LibraryMetadata(JsonArray regions) if (name.contains(".so")) path = String::formatted("/usr/lib/{}", path); - auto file_or_error = MappedFile::map(path); - if (file_or_error.is_error()) { - m_libraries.set(name, {}); + auto* mapped_object = get_or_create_mapped_object(path); + if (!mapped_object) continue; - } - auto elf = ELF::Image(file_or_error.value()->bytes()); - if (!elf.is_valid()) - continue; - auto library = adopt_own(*new Library { base, size, name, file_or_error.release_value(), move(elf) }); - m_libraries.set(name, move(library)); + + m_libraries.set(name, adopt_own(*new Library { base, size, name, mapped_object })); } } diff --git a/Userland/DevTools/Profiler/Profile.h b/Userland/DevTools/Profiler/Profile.h index efacf40c2f6..63728410379 100644 --- a/Userland/DevTools/Profiler/Profile.h +++ b/Userland/DevTools/Profiler/Profile.h @@ -44,6 +44,13 @@ class Profile; class ProfileModel; class SamplesModel; +struct MappedObject { + NonnullRefPtr file; + ELF::Image elf; +}; + +extern HashMap> g_mapped_object_cache; + class LibraryMetadata { public: explicit LibraryMetadata(JsonArray regions); @@ -52,8 +59,7 @@ public: FlatPtr base; size_t size; String name; - NonnullRefPtr file; - ELF::Image elf; + MappedObject* object { nullptr }; }; const Library* library_containing(FlatPtr) const;