1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-21 18:45:07 +00:00

Profiler: Display source location information in the disassembly view

With this, we can now have some amount of source-level profiling
information :^)
This commit is contained in:
Ali Mohammad Pur 2021-08-06 00:37:20 +04:30 committed by Andreas Kling
parent c4437e19bd
commit 5d3b452897
2 changed files with 31 additions and 1 deletions

View file

@ -7,6 +7,7 @@
#include "DisassemblyModel.h" #include "DisassemblyModel.h"
#include "Profile.h" #include "Profile.h"
#include <AK/MappedFile.h> #include <AK/MappedFile.h>
#include <LibDebug/DebugInfo.h>
#include <LibELF/Image.h> #include <LibELF/Image.h>
#include <LibGUI/Painter.h> #include <LibGUI/Painter.h>
#include <LibSymbolication/Symbolication.h> #include <LibSymbolication/Symbolication.h>
@ -75,6 +76,7 @@ DisassemblyModel::DisassemblyModel(Profile& profile, ProfileNode& node)
X86::ELFSymbolProvider symbol_provider(*elf); X86::ELFSymbolProvider symbol_provider(*elf);
X86::SimpleInstructionStream stream((const u8*)view.characters_without_null_termination(), view.length()); X86::SimpleInstructionStream stream((const u8*)view.characters_without_null_termination(), view.length());
X86::Disassembler disassembler(stream); X86::Disassembler disassembler(stream);
Debug::DebugInfo debug_info { *elf, {}, base_address };
size_t offset_into_symbol = 0; size_t offset_into_symbol = 0;
for (;;) { for (;;) {
@ -89,7 +91,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); 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; 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 }); 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(); offset_into_symbol += insn.value().length();
} }
@ -115,6 +117,8 @@ String DisassemblyModel::column_name(int column) const
return "Insn Bytes"; return "Insn Bytes";
case Column::Disassembly: case Column::Disassembly:
return "Disassembly"; return "Disassembly";
case Column::SourceLocation:
return "Source Location";
default: default:
VERIFY_NOT_REACHED(); VERIFY_NOT_REACHED();
return {}; return {};
@ -164,8 +168,10 @@ GUI::Variant DisassemblyModel::data(const GUI::ModelIndex& index, GUI::ModelRole
return ((float)insn.event_count / (float)m_node.event_count()) * 100.0f; return ((float)insn.event_count / (float)m_node.event_count()) * 100.0f;
return insn.event_count; return insn.event_count;
} }
if (index.column() == Column::Address) if (index.column() == Column::Address)
return String::formatted("{:p}", insn.address); return String::formatted("{:p}", insn.address);
if (index.column() == Column::InstructionBytes) { if (index.column() == Column::InstructionBytes) {
StringBuilder builder; StringBuilder builder;
for (auto ch : insn.bytes) { for (auto ch : insn.bytes) {
@ -173,8 +179,29 @@ GUI::Variant DisassemblyModel::data(const GUI::ModelIndex& index, GUI::ModelRole
} }
return builder.to_string(); return builder.to_string();
} }
if (index.column() == Column::Disassembly) if (index.column() == Column::Disassembly)
return insn.disassembly; return insn.disassembly;
if (index.column() == Column::SourceLocation) {
StringBuilder builder;
auto first = true;
for (auto& entry : insn.source_position_with_inlines.inline_chain) {
if (first)
first = false;
else
builder.append(" => ");
builder.appendff("{}:{}", entry.file_path, entry.line_number);
}
if (insn.source_position_with_inlines.source_position.has_value()) {
if (!first)
builder.append(" => ");
auto& entry = insn.source_position_with_inlines.source_position.value();
builder.appendff("{}:{}", entry.file_path, entry.line_number);
}
return builder.build();
}
return {}; return {};
} }
return {}; return {};

View file

@ -6,6 +6,7 @@
#pragma once #pragma once
#include <LibDebug/DebugInfo.h>
#include <LibGUI/Model.h> #include <LibGUI/Model.h>
#include <LibX86/Instruction.h> #include <LibX86/Instruction.h>
@ -21,6 +22,7 @@ struct InstructionData {
FlatPtr address { 0 }; FlatPtr address { 0 };
u32 event_count { 0 }; u32 event_count { 0 };
float percent { 0 }; float percent { 0 };
Debug::DebugInfo::SourcePositionWithInlines source_position_with_inlines;
}; };
class DisassemblyModel final : public GUI::Model { class DisassemblyModel final : public GUI::Model {
@ -35,6 +37,7 @@ public:
SampleCount, SampleCount,
InstructionBytes, InstructionBytes,
Disassembly, Disassembly,
SourceLocation,
__Count __Count
}; };