mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-11 01:06:01 +03:00
HackStudio: Add a registers view for the current function in debug mode
This commit is contained in:
parent
3ddc42fdf1
commit
916e5e8cb3
Notes:
sideshowbarker
2024-07-19 03:11:42 +09:00
Author: https://github.com/Lubrsi Commit: https://github.com/SerenityOS/serenity/commit/916e5e8cb31 Pull-request: https://github.com/SerenityOS/serenity/pull/3290
@ -5,6 +5,7 @@ set(SOURCES
|
|||||||
Debugger/DebugInfoWidget.cpp
|
Debugger/DebugInfoWidget.cpp
|
||||||
Debugger/DisassemblyModel.cpp
|
Debugger/DisassemblyModel.cpp
|
||||||
Debugger/DisassemblyWidget.cpp
|
Debugger/DisassemblyWidget.cpp
|
||||||
|
Debugger/RegistersModel.cpp
|
||||||
Debugger/VariablesModel.cpp
|
Debugger/VariablesModel.cpp
|
||||||
Editor.cpp
|
Editor.cpp
|
||||||
EditorWrapper.cpp
|
EditorWrapper.cpp
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
#include "DebugInfoWidget.h"
|
#include "DebugInfoWidget.h"
|
||||||
#include "BacktraceModel.h"
|
#include "BacktraceModel.h"
|
||||||
#include "Debugger.h"
|
#include "Debugger.h"
|
||||||
|
#include "RegistersModel.h"
|
||||||
#include "VariablesModel.h"
|
#include "VariablesModel.h"
|
||||||
#include <AK/StringBuilder.h>
|
#include <AK/StringBuilder.h>
|
||||||
#include <LibGUI/Action.h>
|
#include <LibGUI/Action.h>
|
||||||
@ -37,6 +38,7 @@
|
|||||||
#include <LibGUI/Menu.h>
|
#include <LibGUI/Menu.h>
|
||||||
#include <LibGUI/Model.h>
|
#include <LibGUI/Model.h>
|
||||||
#include <LibGUI/Splitter.h>
|
#include <LibGUI/Splitter.h>
|
||||||
|
#include <LibGUI/TabWidget.h>
|
||||||
#include <LibGUI/TreeView.h>
|
#include <LibGUI/TreeView.h>
|
||||||
|
|
||||||
namespace HackStudio {
|
namespace HackStudio {
|
||||||
@ -90,7 +92,10 @@ DebugInfoWidget::DebugInfoWidget()
|
|||||||
|
|
||||||
auto& splitter = bottom_box.add<GUI::HorizontalSplitter>();
|
auto& splitter = bottom_box.add<GUI::HorizontalSplitter>();
|
||||||
m_backtrace_view = splitter.add<GUI::ListView>();
|
m_backtrace_view = splitter.add<GUI::ListView>();
|
||||||
m_variables_view = splitter.add<GUI::TreeView>();
|
auto& variables_tab_widget = splitter.add<GUI::TabWidget>();
|
||||||
|
variables_tab_widget.set_tab_position(GUI::TabWidget::TabPosition::Bottom);
|
||||||
|
variables_tab_widget.add_widget("Variables", build_variables_tab());
|
||||||
|
variables_tab_widget.add_widget("Registers", build_registers_tab());
|
||||||
|
|
||||||
m_backtrace_view->on_selection = [this](auto& index) {
|
m_backtrace_view->on_selection = [this](auto& index) {
|
||||||
auto& model = static_cast<BacktraceModel&>(*m_backtrace_view->model());
|
auto& model = static_cast<BacktraceModel&>(*m_backtrace_view->model());
|
||||||
@ -104,13 +109,14 @@ DebugInfoWidget::DebugInfoWidget()
|
|||||||
|
|
||||||
m_variables_view->set_model(VariablesModel::create(frame_regs));
|
m_variables_view->set_model(VariablesModel::create(frame_regs));
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
auto edit_variable_action = GUI::Action::create("Change value", [&](auto&) {
|
NonnullRefPtr<GUI::Widget> DebugInfoWidget::build_variables_tab()
|
||||||
m_variables_view->on_activation(m_variables_view->selection().first());
|
{
|
||||||
});
|
auto variables_widget = GUI::Widget::construct();
|
||||||
|
variables_widget->set_layout<GUI::HorizontalBoxLayout>();
|
||||||
|
|
||||||
m_variable_context_menu = GUI::Menu::construct();
|
m_variables_view = variables_widget->add<GUI::TreeView>();
|
||||||
m_variable_context_menu->add_action(edit_variable_action);
|
|
||||||
|
|
||||||
auto is_valid_index = [](auto& index) {
|
auto is_valid_index = [](auto& index) {
|
||||||
if (!index.is_valid())
|
if (!index.is_valid())
|
||||||
@ -137,12 +143,32 @@ DebugInfoWidget::DebugInfoWidget()
|
|||||||
model.set_variable_value(index, value, window());
|
model.set_variable_value(index, value, window());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
auto edit_variable_action = GUI::Action::create("Change value", [&](auto&) {
|
||||||
|
m_variables_view->on_activation(m_variables_view->selection().first());
|
||||||
|
});
|
||||||
|
|
||||||
|
m_variable_context_menu = GUI::Menu::construct();
|
||||||
|
m_variable_context_menu->add_action(edit_variable_action);
|
||||||
|
|
||||||
|
return variables_widget;
|
||||||
|
}
|
||||||
|
|
||||||
|
NonnullRefPtr<GUI::Widget> DebugInfoWidget::build_registers_tab()
|
||||||
|
{
|
||||||
|
auto registers_widget = GUI::Widget::construct();
|
||||||
|
registers_widget->set_layout<GUI::HorizontalBoxLayout>();
|
||||||
|
|
||||||
|
m_registers_view = registers_widget->add<GUI::TableView>();
|
||||||
|
|
||||||
|
return registers_widget;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DebugInfoWidget::update_state(const Debug::DebugSession& debug_session, const PtraceRegisters& regs)
|
void DebugInfoWidget::update_state(const Debug::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(debug_session, regs));
|
m_backtrace_view->set_model(BacktraceModel::create(debug_session, regs));
|
||||||
|
m_registers_view->set_model(RegistersModel::create(regs));
|
||||||
auto selected_index = m_backtrace_view->model()->index(0);
|
auto selected_index = m_backtrace_view->model()->index(0);
|
||||||
if (!selected_index.is_valid()) {
|
if (!selected_index.is_valid()) {
|
||||||
dbg() << "Warning: DebugInfoWidget: backtrace selected index is invalid";
|
dbg() << "Warning: DebugInfoWidget: backtrace selected index is invalid";
|
||||||
@ -154,6 +180,8 @@ void DebugInfoWidget::update_state(const Debug::DebugSession& debug_session, con
|
|||||||
void DebugInfoWidget::program_stopped()
|
void DebugInfoWidget::program_stopped()
|
||||||
{
|
{
|
||||||
m_variables_view->set_model({});
|
m_variables_view->set_model({});
|
||||||
|
m_backtrace_view->set_model({});
|
||||||
|
m_registers_view->set_model({});
|
||||||
}
|
}
|
||||||
|
|
||||||
void DebugInfoWidget::set_debug_actions_enabled(bool enabled)
|
void DebugInfoWidget::set_debug_actions_enabled(bool enabled)
|
||||||
@ -163,4 +191,5 @@ void DebugInfoWidget::set_debug_actions_enabled(bool enabled)
|
|||||||
m_step_in_action->set_enabled(enabled);
|
m_step_in_action->set_enabled(enabled);
|
||||||
m_step_out_action->set_enabled(enabled);
|
m_step_out_action->set_enabled(enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
#include <LibGUI/Action.h>
|
#include <LibGUI/Action.h>
|
||||||
#include <LibGUI/ListView.h>
|
#include <LibGUI/ListView.h>
|
||||||
#include <LibGUI/Model.h>
|
#include <LibGUI/Model.h>
|
||||||
|
#include <LibGUI/TableView.h>
|
||||||
#include <LibGUI/ToolBar.h>
|
#include <LibGUI/ToolBar.h>
|
||||||
#include <LibGUI/ToolBarContainer.h>
|
#include <LibGUI/ToolBarContainer.h>
|
||||||
#include <LibGUI/Widget.h>
|
#include <LibGUI/Widget.h>
|
||||||
@ -51,7 +52,11 @@ private:
|
|||||||
explicit DebugInfoWidget();
|
explicit DebugInfoWidget();
|
||||||
void init_toolbar();
|
void init_toolbar();
|
||||||
|
|
||||||
|
NonnullRefPtr<GUI::Widget> build_variables_tab();
|
||||||
|
NonnullRefPtr<GUI::Widget> build_registers_tab();
|
||||||
|
|
||||||
RefPtr<GUI::TreeView> m_variables_view;
|
RefPtr<GUI::TreeView> m_variables_view;
|
||||||
|
RefPtr<GUI::TableView> m_registers_view;
|
||||||
RefPtr<GUI::ListView> m_backtrace_view;
|
RefPtr<GUI::ListView> m_backtrace_view;
|
||||||
RefPtr<GUI::Menu> m_variable_context_menu;
|
RefPtr<GUI::Menu> m_variable_context_menu;
|
||||||
RefPtr<GUI::ToolBar> m_toolbar;
|
RefPtr<GUI::ToolBar> m_toolbar;
|
||||||
|
92
DevTools/HackStudio/Debugger/RegistersModel.cpp
Normal file
92
DevTools/HackStudio/Debugger/RegistersModel.cpp
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020, Luke Wilde <luke.wilde@live.co.uk>
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "RegistersModel.h"
|
||||||
|
|
||||||
|
namespace HackStudio {
|
||||||
|
|
||||||
|
RegistersModel::RegistersModel(const PtraceRegisters& regs)
|
||||||
|
{
|
||||||
|
m_registers.append({ "eax", regs.eax });
|
||||||
|
m_registers.append({ "ebx", regs.ebx });
|
||||||
|
m_registers.append({ "ecx", regs.ecx });
|
||||||
|
m_registers.append({ "edx", regs.edx });
|
||||||
|
m_registers.append({ "esp", regs.esp });
|
||||||
|
m_registers.append({ "ebp", regs.ebp });
|
||||||
|
m_registers.append({ "esi", regs.esi });
|
||||||
|
m_registers.append({ "edi", regs.edi });
|
||||||
|
m_registers.append({ "eip", regs.eip });
|
||||||
|
m_registers.append({ "eflags", regs.eflags });
|
||||||
|
m_registers.append({ "cs", regs.cs });
|
||||||
|
m_registers.append({ "ss", regs.ss });
|
||||||
|
m_registers.append({ "ds", regs.ds });
|
||||||
|
m_registers.append({ "es", regs.es });
|
||||||
|
m_registers.append({ "fs", regs.fs });
|
||||||
|
m_registers.append({ "gs", regs.gs });
|
||||||
|
}
|
||||||
|
|
||||||
|
RegistersModel::~RegistersModel()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int RegistersModel::row_count(const GUI::ModelIndex&) const
|
||||||
|
{
|
||||||
|
return m_registers.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
String RegistersModel::column_name(int column) const
|
||||||
|
{
|
||||||
|
switch (column) {
|
||||||
|
case Column::Register:
|
||||||
|
return "Register";
|
||||||
|
case Column::Value:
|
||||||
|
return "Value";
|
||||||
|
default:
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GUI::Variant RegistersModel::data(const GUI::ModelIndex& index, GUI::ModelRole role) const
|
||||||
|
{
|
||||||
|
auto& reg = m_registers[index.row()];
|
||||||
|
|
||||||
|
if (role == GUI::ModelRole::Display) {
|
||||||
|
if (index.column() == Column::Register)
|
||||||
|
return reg.name;
|
||||||
|
if (index.column() == Column::Value)
|
||||||
|
return String::format("%#08x", reg.value);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegistersModel::update()
|
||||||
|
{
|
||||||
|
did_update();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
67
DevTools/HackStudio/Debugger/RegistersModel.h
Normal file
67
DevTools/HackStudio/Debugger/RegistersModel.h
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020, Luke Wilde <luke.wilde@live.co.uk>
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <AK/Vector.h>
|
||||||
|
#include <LibGUI/Model.h>
|
||||||
|
#include <sys/arch/i386/regs.h>
|
||||||
|
|
||||||
|
namespace HackStudio {
|
||||||
|
|
||||||
|
struct RegisterData {
|
||||||
|
String name;
|
||||||
|
u32 value;
|
||||||
|
};
|
||||||
|
|
||||||
|
class RegistersModel final : public GUI::Model {
|
||||||
|
public:
|
||||||
|
static RefPtr<RegistersModel> create(const PtraceRegisters& regs)
|
||||||
|
{
|
||||||
|
return adopt(*new RegistersModel(regs));
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Column {
|
||||||
|
Register,
|
||||||
|
Value,
|
||||||
|
__Count
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual ~RegistersModel() override;
|
||||||
|
|
||||||
|
virtual int row_count(const GUI::ModelIndex& = GUI::ModelIndex()) const override;
|
||||||
|
virtual int column_count(const GUI::ModelIndex& = GUI::ModelIndex()) const override { return Column::__Count; }
|
||||||
|
virtual String column_name(int) const override;
|
||||||
|
virtual GUI::Variant data(const GUI::ModelIndex&, GUI::ModelRole) const override;
|
||||||
|
virtual void update() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
explicit RegistersModel(const PtraceRegisters& regs);
|
||||||
|
|
||||||
|
Vector<RegisterData> m_registers;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user