mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 04:27:44 +00:00
Profiler: Cache parsed DWARF debug information in disassembly view
This changes browsing through disassembled functions in Profiler from a painfully sluggish experience into quite a swift one. It's especially true for profiling the kernel, as it has more than 10 megabytes of DWARF data to churn through.
This commit is contained in:
parent
8e1f882ac9
commit
b883652a83
5 changed files with 19 additions and 4 deletions
|
@ -54,7 +54,7 @@ DisassemblyModel::DisassemblyModel(Profile& profile, ProfileNode& node)
|
||||||
, m_node(node)
|
, m_node(node)
|
||||||
{
|
{
|
||||||
FlatPtr base_address = 0;
|
FlatPtr base_address = 0;
|
||||||
OwnPtr<Debug::DebugInfo> debug_info;
|
const Debug::DebugInfo* debug_info;
|
||||||
const ELF::Image* elf;
|
const ELF::Image* elf;
|
||||||
if (auto maybe_kernel_base = Symbolication::kernel_base(); maybe_kernel_base.has_value() && m_node.address() >= *maybe_kernel_base) {
|
if (auto maybe_kernel_base = Symbolication::kernel_base(); maybe_kernel_base.has_value() && m_node.address() >= *maybe_kernel_base) {
|
||||||
if (!g_kernel_debuginfo_object.has_value())
|
if (!g_kernel_debuginfo_object.has_value())
|
||||||
|
@ -63,7 +63,9 @@ DisassemblyModel::DisassemblyModel(Profile& profile, ProfileNode& node)
|
||||||
elf = try_load_kernel_binary();
|
elf = try_load_kernel_binary();
|
||||||
if (elf == nullptr)
|
if (elf == nullptr)
|
||||||
return;
|
return;
|
||||||
debug_info = make<Debug::DebugInfo>(g_kernel_debuginfo_object->elf, String::empty(), base_address);
|
if (g_kernel_debug_info == nullptr)
|
||||||
|
g_kernel_debug_info = make<Debug::DebugInfo>(g_kernel_debuginfo_object->elf, String::empty(), base_address);
|
||||||
|
debug_info = g_kernel_debug_info.ptr();
|
||||||
} else {
|
} else {
|
||||||
auto& process = node.process();
|
auto& process = node.process();
|
||||||
auto library_data = process.library_metadata.library_containing(node.address());
|
auto library_data = process.library_metadata.library_containing(node.address());
|
||||||
|
@ -73,7 +75,7 @@ DisassemblyModel::DisassemblyModel(Profile& profile, ProfileNode& node)
|
||||||
}
|
}
|
||||||
base_address = library_data->base;
|
base_address = library_data->base;
|
||||||
elf = &library_data->object->elf;
|
elf = &library_data->object->elf;
|
||||||
debug_info = make<Debug::DebugInfo>(library_data->object->elf, String::empty(), base_address);
|
debug_info = &library_data->load_debug_info(base_address);
|
||||||
}
|
}
|
||||||
|
|
||||||
VERIFY(elf != nullptr);
|
VERIFY(elf != nullptr);
|
||||||
|
|
|
@ -102,10 +102,17 @@ void LibraryMetadata::handle_mmap(FlatPtr base, size_t size, const String& name)
|
||||||
if (!mapped_object)
|
if (!mapped_object)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_libraries.set(path_string, adopt_own(*new Library { base, size, path_string, mapped_object }));
|
m_libraries.set(path_string, adopt_own(*new Library { base, size, path_string, mapped_object, {} }));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Debug::DebugInfo& LibraryMetadata::Library::load_debug_info(FlatPtr base_address) const
|
||||||
|
{
|
||||||
|
if (debug_info == nullptr)
|
||||||
|
debug_info = make<Debug::DebugInfo>(object->elf, String::empty(), base_address);
|
||||||
|
return *debug_info.ptr();
|
||||||
|
}
|
||||||
|
|
||||||
String LibraryMetadata::Library::symbolicate(FlatPtr ptr, u32* offset) const
|
String LibraryMetadata::Library::symbolicate(FlatPtr ptr, u32* offset) const
|
||||||
{
|
{
|
||||||
if (!object)
|
if (!object)
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include <AK/MappedFile.h>
|
#include <AK/MappedFile.h>
|
||||||
#include <AK/OwnPtr.h>
|
#include <AK/OwnPtr.h>
|
||||||
#include <AK/Vector.h>
|
#include <AK/Vector.h>
|
||||||
|
#include <LibDebug/DebugInfo.h>
|
||||||
#include <LibELF/Image.h>
|
#include <LibELF/Image.h>
|
||||||
|
|
||||||
namespace Profiler {
|
namespace Profiler {
|
||||||
|
@ -29,8 +30,11 @@ public:
|
||||||
size_t size;
|
size_t size;
|
||||||
String name;
|
String name;
|
||||||
MappedObject* object { nullptr };
|
MappedObject* object { nullptr };
|
||||||
|
// This is loaded lazily because we only need it in disassembly view
|
||||||
|
mutable OwnPtr<Debug::DebugInfo> debug_info;
|
||||||
|
|
||||||
String symbolicate(FlatPtr, u32* offset) const;
|
String symbolicate(FlatPtr, u32* offset) const;
|
||||||
|
const Debug::DebugInfo& load_debug_info(FlatPtr base_address) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
void handle_mmap(FlatPtr base, size_t size, const String& name);
|
void handle_mmap(FlatPtr base, size_t size, const String& name);
|
||||||
|
|
|
@ -212,6 +212,7 @@ void Profile::rebuild_tree()
|
||||||
}
|
}
|
||||||
|
|
||||||
Optional<MappedObject> g_kernel_debuginfo_object;
|
Optional<MappedObject> g_kernel_debuginfo_object;
|
||||||
|
OwnPtr<Debug::DebugInfo> g_kernel_debug_info;
|
||||||
|
|
||||||
Result<NonnullOwnPtr<Profile>, String> Profile::load_from_perfcore_file(const StringView& path)
|
Result<NonnullOwnPtr<Profile>, String> Profile::load_from_perfcore_file(const StringView& path)
|
||||||
{
|
{
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
namespace Profiler {
|
namespace Profiler {
|
||||||
|
|
||||||
extern Optional<MappedObject> g_kernel_debuginfo_object;
|
extern Optional<MappedObject> g_kernel_debuginfo_object;
|
||||||
|
extern OwnPtr<Debug::DebugInfo> g_kernel_debug_info;
|
||||||
|
|
||||||
class ProfileNode : public RefCounted<ProfileNode> {
|
class ProfileNode : public RefCounted<ProfileNode> {
|
||||||
public:
|
public:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue