mirror of
https://github.com/RGBCube/serenity
synced 2025-05-21 10:55: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:
parent
c4437e19bd
commit
5d3b452897
2 changed files with 31 additions and 1 deletions
|
@ -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 {};
|
||||||
|
|
|
@ -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
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue