From 8e1f882ac938c813e497a866498b8da31a956ccd Mon Sep 17 00:00:00 2001 From: Daniel Bertalan Date: Tue, 26 Oct 2021 18:17:49 +0200 Subject: [PATCH] Profiler: Load the actual kernel binary for disassembly /boot/Kernel.debug only contains the symbol table and DWARF debug information, and has its `.text` and other PT_LOAD segments stripped out. When we try to parse its data as instructions, we get a crash from within LibX86. We now load the actual /boot/Kernel binary when we want to disassemble kernel functions. --- .../DevTools/Profiler/DisassemblyModel.cpp | 34 +++++++++++++++---- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/Userland/DevTools/Profiler/DisassemblyModel.cpp b/Userland/DevTools/Profiler/DisassemblyModel.cpp index 85af3dffa8..3fe4da9c20 100644 --- a/Userland/DevTools/Profiler/DisassemblyModel.cpp +++ b/Userland/DevTools/Profiler/DisassemblyModel.cpp @@ -34,17 +34,36 @@ static Color color_for_percent(int percent) return heat_gradient().get_pixel(percent, 0); } +static Optional s_kernel_binary; + +static ELF::Image* try_load_kernel_binary() +{ + if (s_kernel_binary.has_value()) + return &s_kernel_binary->elf; + auto kernel_binary_or_error = MappedFile::map("/boot/Kernel"); + if (!kernel_binary_or_error.is_error()) { + auto kernel_binary = kernel_binary_or_error.release_value(); + s_kernel_binary = { { kernel_binary, ELF::Image(kernel_binary->bytes()) } }; + return &s_kernel_binary->elf; + } + return nullptr; +} + DisassemblyModel::DisassemblyModel(Profile& profile, ProfileNode& node) : m_profile(profile) , m_node(node) { - const ELF::Image* elf; FlatPtr base_address = 0; + OwnPtr debug_info; + const ELF::Image* elf; 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()) return; - elf = &g_kernel_debuginfo_object->elf; - base_address = maybe_kernel_base.value(); + base_address = maybe_kernel_base.release_value(); + elf = try_load_kernel_binary(); + if (elf == nullptr) + return; + debug_info = make(g_kernel_debuginfo_object->elf, String::empty(), base_address); } else { auto& process = node.process(); auto library_data = process.library_metadata.library_containing(node.address()); @@ -52,16 +71,17 @@ DisassemblyModel::DisassemblyModel(Profile& profile, ProfileNode& node) dbgln("no library data for address {:p}", node.address()); return; } - elf = &library_data->object->elf; base_address = library_data->base; + elf = &library_data->object->elf; + debug_info = make(library_data->object->elf, String::empty(), base_address); } VERIFY(elf != nullptr); + VERIFY(debug_info != nullptr); FlatPtr function_address = node.address() - base_address; auto is_function_address = false; - Debug::DebugInfo debug_info { *elf, {}, base_address }; - auto function = debug_info.get_containing_function(function_address); + auto function = debug_info->get_containing_function(function_address); if (function.has_value()) { if (function_address == function->address_low) is_function_address = true; @@ -107,7 +127,7 @@ DisassemblyModel::DisassemblyModel(Profile& profile, ProfileNode& node) u32 samples_at_this_instruction = m_node.events_per_address().get(address_in_profiled_program).value_or(0); float percent = ((float)samples_at_this_instruction / (float)m_node.event_count()) * 100.0f; - m_instructions.append({ insn.value(), disassembly, instruction_bytes, address_in_profiled_program, samples_at_this_instruction, percent, debug_info.get_source_position_with_inlines(address_in_profiled_program - base_address) }); + m_instructions.append({ insn.value(), disassembly, instruction_bytes, address_in_profiled_program, samples_at_this_instruction, percent, debug_info->get_source_position_with_inlines(address_in_profiled_program - base_address) }); offset_into_symbol += insn.value().length(); }