mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 01:27:43 +00:00
HackStudio: Update variables view based on the selected backtrace frame
This commit is contained in:
parent
1fb62df02a
commit
2acce56ac1
5 changed files with 36 additions and 15 deletions
|
@ -27,9 +27,9 @@
|
||||||
#include "BacktraceModel.h"
|
#include "BacktraceModel.h"
|
||||||
#include "Debugger.h"
|
#include "Debugger.h"
|
||||||
|
|
||||||
RefPtr<BacktraceModel> BacktraceModel::create(const PtraceRegisters& regs)
|
NonnullRefPtr<BacktraceModel> BacktraceModel::create(const DebugSession& debug_session, const PtraceRegisters& regs)
|
||||||
{
|
{
|
||||||
return adopt(*new BacktraceModel(create_backtrace(regs)));
|
return adopt(*new BacktraceModel(create_backtrace(debug_session, regs)));
|
||||||
}
|
}
|
||||||
|
|
||||||
GUI::Variant BacktraceModel::data(const GUI::ModelIndex& index, Role role) const
|
GUI::Variant BacktraceModel::data(const GUI::ModelIndex& index, Role role) const
|
||||||
|
@ -41,20 +41,19 @@ GUI::Variant BacktraceModel::data(const GUI::ModelIndex& index, Role role) const
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector<BacktraceModel::FrameInfo> BacktraceModel::create_backtrace(const PtraceRegisters& regs)
|
Vector<BacktraceModel::FrameInfo> BacktraceModel::create_backtrace(const DebugSession& debug_session, const PtraceRegisters& regs)
|
||||||
{
|
{
|
||||||
u32 current_ebp = regs.ebp;
|
u32 current_ebp = regs.ebp;
|
||||||
u32 current_instruction = regs.eip;
|
u32 current_instruction = regs.eip;
|
||||||
Vector<BacktraceModel::FrameInfo> frames;
|
Vector<BacktraceModel::FrameInfo> frames;
|
||||||
do {
|
do {
|
||||||
const auto& debug_info = Debugger::the().session()->debug_info();
|
String name = debug_session.debug_info().name_of_containing_function(current_instruction);
|
||||||
String name = debug_info.name_of_containing_function(current_instruction);
|
|
||||||
if (name.is_null()) {
|
if (name.is_null()) {
|
||||||
dbg() << "BacktraceModel: couldn't find containing function for address: " << (void*)current_instruction;
|
dbg() << "BacktraceModel: couldn't find containing function for address: " << (void*)current_instruction;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
frames.append({ name, current_instruction });
|
frames.append({ name, current_instruction, current_ebp });
|
||||||
current_instruction = Debugger::the().session()->peek(reinterpret_cast<u32*>(current_ebp + 4)).value();
|
current_instruction = Debugger::the().session()->peek(reinterpret_cast<u32*>(current_ebp + 4)).value();
|
||||||
current_ebp = Debugger::the().session()->peek(reinterpret_cast<u32*>(current_ebp)).value();
|
current_ebp = Debugger::the().session()->peek(reinterpret_cast<u32*>(current_ebp)).value();
|
||||||
} while (current_ebp);
|
} while (current_ebp);
|
||||||
|
|
|
@ -30,9 +30,11 @@
|
||||||
#include <LibGUI/Model.h>
|
#include <LibGUI/Model.h>
|
||||||
#include <sys/arch/i386/regs.h>
|
#include <sys/arch/i386/regs.h>
|
||||||
|
|
||||||
|
class DebugSession;
|
||||||
|
|
||||||
class BacktraceModel final : public GUI::Model {
|
class BacktraceModel final : public GUI::Model {
|
||||||
public:
|
public:
|
||||||
static RefPtr<BacktraceModel> create(const PtraceRegisters& regs);
|
static NonnullRefPtr<BacktraceModel> create(const DebugSession&, const PtraceRegisters& regs);
|
||||||
|
|
||||||
virtual int row_count(const GUI::ModelIndex& = GUI::ModelIndex()) const override { return m_frames.size(); }
|
virtual int row_count(const GUI::ModelIndex& = GUI::ModelIndex()) const override { return m_frames.size(); }
|
||||||
virtual int column_count(const GUI::ModelIndex& = GUI::ModelIndex()) const override { return 1; }
|
virtual int column_count(const GUI::ModelIndex& = GUI::ModelIndex()) const override { return 1; }
|
||||||
|
@ -47,18 +49,21 @@ public:
|
||||||
virtual void update() override {}
|
virtual void update() override {}
|
||||||
virtual GUI::ModelIndex index(int row, int column = 0, const GUI::ModelIndex& = GUI::ModelIndex()) const override { return create_index(row, column, &m_frames.at(row)); }
|
virtual GUI::ModelIndex index(int row, int column = 0, const GUI::ModelIndex& = GUI::ModelIndex()) const override { return create_index(row, column, &m_frames.at(row)); }
|
||||||
|
|
||||||
private:
|
|
||||||
struct FrameInfo {
|
struct FrameInfo {
|
||||||
String function_name;
|
String function_name;
|
||||||
u32 address_in_frame;
|
u32 instruction_address;
|
||||||
|
u32 frame_base;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const Vector<FrameInfo>& frames() const { return m_frames; }
|
||||||
|
|
||||||
|
private:
|
||||||
explicit BacktraceModel(Vector<FrameInfo>&& frames)
|
explicit BacktraceModel(Vector<FrameInfo>&& frames)
|
||||||
: m_frames(move(frames))
|
: m_frames(move(frames))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
static Vector<FrameInfo> create_backtrace(const PtraceRegisters&);
|
static Vector<FrameInfo> create_backtrace(const DebugSession&, const PtraceRegisters&);
|
||||||
|
|
||||||
Vector<FrameInfo> m_frames;
|
Vector<FrameInfo> m_frames;
|
||||||
};
|
};
|
||||||
|
|
|
@ -43,10 +43,25 @@ DebugInfoWidget::DebugInfoWidget()
|
||||||
m_variables_view = splitter.add<GUI::TreeView>();
|
m_variables_view = splitter.add<GUI::TreeView>();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DebugInfoWidget::update_state(const PtraceRegisters& regs)
|
void DebugInfoWidget::update_state(const DebugSession& debug_session, const PtraceRegisters& regs)
|
||||||
{
|
{
|
||||||
m_variables_view->set_model(VariablesModel::create(regs));
|
m_variables_view->set_model(VariablesModel::create(regs));
|
||||||
m_backtrace_view->set_model(BacktraceModel::create(regs));
|
m_backtrace_view->set_model(BacktraceModel::create(debug_session, regs));
|
||||||
|
m_backtrace_view->selection().set(m_backtrace_view->model()->index(0));
|
||||||
|
|
||||||
|
m_backtrace_view->on_selection
|
||||||
|
= [this](auto& index) {
|
||||||
|
auto& model = static_cast<BacktraceModel&>(*m_backtrace_view->model());
|
||||||
|
|
||||||
|
// Note: The recontruction of the register set here is obviously incomplete.
|
||||||
|
// We currently only reconstruct eip & ebp. Ideally would also reconstruct the other registers somehow.
|
||||||
|
// (Other registers may be needed to get the values of variables who are not stored on the stack)
|
||||||
|
PtraceRegisters frame_regs {};
|
||||||
|
frame_regs.eip = model.frames()[index.row()].instruction_address;
|
||||||
|
frame_regs.ebp = model.frames()[index.row()].frame_base;
|
||||||
|
|
||||||
|
m_variables_view->set_model(VariablesModel::create(frame_regs));
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void DebugInfoWidget::program_stopped()
|
void DebugInfoWidget::program_stopped()
|
||||||
|
|
|
@ -38,7 +38,7 @@ class DebugInfoWidget final : public GUI::Widget {
|
||||||
public:
|
public:
|
||||||
virtual ~DebugInfoWidget() override {}
|
virtual ~DebugInfoWidget() override {}
|
||||||
|
|
||||||
void update_state(const PtraceRegisters&);
|
void update_state(const DebugSession&, const PtraceRegisters&);
|
||||||
void program_stopped();
|
void program_stopped();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -608,14 +608,16 @@ int main(int argc, char** argv)
|
||||||
[&](const PtraceRegisters& regs) {
|
[&](const PtraceRegisters& regs) {
|
||||||
dbg() << "Program stopped";
|
dbg() << "Program stopped";
|
||||||
|
|
||||||
auto source_position = Debugger::the().session()->debug_info().get_source_position(regs.eip);
|
ASSERT(Debugger::the().session());
|
||||||
|
const auto& debug_session = *Debugger::the().session();
|
||||||
|
auto source_position = debug_session.debug_info().get_source_position(regs.eip);
|
||||||
if (!source_position.has_value()) {
|
if (!source_position.has_value()) {
|
||||||
dbg() << "Could not find source position for address: " << (void*)regs.eip;
|
dbg() << "Could not find source position for address: " << (void*)regs.eip;
|
||||||
return Debugger::HasControlPassedToUser::No;
|
return Debugger::HasControlPassedToUser::No;
|
||||||
}
|
}
|
||||||
current_editor_in_execution = get_editor_of_file(source_position.value().file_path);
|
current_editor_in_execution = get_editor_of_file(source_position.value().file_path);
|
||||||
current_editor_in_execution->editor().set_execution_position(source_position.value().line_number - 1);
|
current_editor_in_execution->editor().set_execution_position(source_position.value().line_number - 1);
|
||||||
debug_info_widget.update_state(regs);
|
debug_info_widget.update_state(debug_session, regs);
|
||||||
continue_action->set_enabled(true);
|
continue_action->set_enabled(true);
|
||||||
single_step_action->set_enabled(true);
|
single_step_action->set_enabled(true);
|
||||||
reveal_action_tab(debug_info_widget);
|
reveal_action_tab(debug_info_widget);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue