mirror of
https://github.com/RGBCube/serenity
synced 2025-07-28 09:37:44 +00:00
HackStudio: Add option to inspect Coredump
This adds a --coredump <file> option to Hack Studio. When used, Hack Studio will open the coredump and allow the user to inspect it in the Debug tab.
This commit is contained in:
parent
ce726fe027
commit
8316eb7306
8 changed files with 72 additions and 19 deletions
|
@ -50,5 +50,5 @@ set(SOURCES
|
|||
)
|
||||
|
||||
serenity_app(HackStudio ICON app-hack-studio)
|
||||
target_link_libraries(HackStudio LibWeb LibMarkdown LibGUI LibCpp LibGfx LibCore LibVT LibDebug LibX86 LibDiff LibShell LibSymbolication LibRegex LibSQL)
|
||||
target_link_libraries(HackStudio LibWeb LibMarkdown LibGUI LibCpp LibGfx LibCore LibVT LibDebug LibX86 LibDiff LibShell LibSymbolication LibRegex LibSQL LibCoredump)
|
||||
add_dependencies(HackStudio CppLanguageServer)
|
||||
|
|
|
@ -76,10 +76,16 @@ DebugInfoWidget::DebugInfoWidget()
|
|||
// 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.set_ip(model.frames()[index.row()].instruction_address);
|
||||
frame_regs.set_bp(model.frames()[index.row()].frame_base);
|
||||
auto backtrace_frame = model.frames()[index.row()];
|
||||
frame_regs.set_ip(backtrace_frame.instruction_address);
|
||||
frame_regs.set_bp(backtrace_frame.frame_base);
|
||||
|
||||
m_variables_view->set_model(VariablesModel::create(frame_regs));
|
||||
m_variables_view->set_model(VariablesModel::create(static_cast<VariablesModel&>(*m_variables_view->model()).inspector(), frame_regs));
|
||||
if (on_backtrace_frame_selection && backtrace_frame.m_source_position.has_value()) {
|
||||
on_backtrace_frame_selection(*backtrace_frame.m_source_position);
|
||||
} else {
|
||||
dbgln("no source position info");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -149,9 +155,9 @@ NonnullRefPtr<GUI::Widget> DebugInfoWidget::build_registers_tab()
|
|||
return registers_widget;
|
||||
}
|
||||
|
||||
void DebugInfoWidget::update_state(const Debug::ProcessInspector& inspector, const PtraceRegisters& regs)
|
||||
void DebugInfoWidget::update_state(Debug::ProcessInspector& inspector, const PtraceRegisters& regs)
|
||||
{
|
||||
m_variables_view->set_model(VariablesModel::create(regs));
|
||||
m_variables_view->set_model(VariablesModel::create(inspector, regs));
|
||||
m_backtrace_view->set_model(BacktraceModel::create(inspector, regs));
|
||||
if (m_registers_view->model()) {
|
||||
auto& previous_registers = static_cast<RegistersModel*>(m_registers_view->model())->raw_registers();
|
||||
|
|
|
@ -26,10 +26,12 @@ class DebugInfoWidget final : public GUI::Widget {
|
|||
public:
|
||||
virtual ~DebugInfoWidget() override { }
|
||||
|
||||
void update_state(Debug::ProcessInspector const&, PtraceRegisters const&);
|
||||
void update_state(Debug::ProcessInspector&, PtraceRegisters const&);
|
||||
void program_stopped();
|
||||
void set_debug_actions_enabled(bool enabled);
|
||||
|
||||
Function<void(Debug::DebugInfo::SourcePosition const&)> on_backtrace_frame_selection;
|
||||
|
||||
private:
|
||||
explicit DebugInfoWidget();
|
||||
void init_toolbar();
|
||||
|
|
|
@ -78,7 +78,7 @@
|
|||
|
||||
namespace HackStudio {
|
||||
|
||||
HackStudioWidget::HackStudioWidget(const String& path_to_project)
|
||||
HackStudioWidget::HackStudioWidget(String path_to_project)
|
||||
: m_editor_font(read_editor_font_from_config())
|
||||
{
|
||||
set_fill_with_background_color(true);
|
||||
|
@ -207,7 +207,7 @@ void HackStudioWidget::open_project(const String& root_path)
|
|||
m_project_tree_view->set_model(m_project->model());
|
||||
m_project_tree_view->update();
|
||||
}
|
||||
if (m_git_widget) {
|
||||
if (m_git_widget && m_git_widget->initialized()) {
|
||||
m_git_widget->change_repo(LexicalPath(root_path));
|
||||
m_git_widget->refresh();
|
||||
}
|
||||
|
@ -855,8 +855,9 @@ void HackStudioWidget::initialize_debugger()
|
|||
String HackStudioWidget::get_full_path_of_serenity_source(const String& file)
|
||||
{
|
||||
auto path_parts = LexicalPath(file).parts();
|
||||
VERIFY(path_parts[0] == "..");
|
||||
path_parts.remove(0);
|
||||
while (!path_parts.is_empty() && path_parts[0] == "..") {
|
||||
path_parts.remove(0);
|
||||
}
|
||||
StringBuilder relative_path_builder;
|
||||
relative_path_builder.join("/", path_parts);
|
||||
constexpr char SERENITY_LIBS_PREFIX[] = "/usr/src/serenity";
|
||||
|
@ -864,12 +865,20 @@ String HackStudioWidget::get_full_path_of_serenity_source(const String& file)
|
|||
return String::formatted("{}/{}", serenity_sources_base, relative_path_builder.to_string());
|
||||
}
|
||||
|
||||
String HackStudioWidget::get_absolute_path(const String& path) const
|
||||
{
|
||||
// TODO: We can probably do a more specific condition here, something like
|
||||
// "if (file.starts_with("../Libraries/") || file.starts_with("../AK/"))"
|
||||
if (path.starts_with("..")) {
|
||||
return get_full_path_of_serenity_source(path);
|
||||
}
|
||||
return m_project->to_absolute_path(path);
|
||||
}
|
||||
|
||||
RefPtr<EditorWrapper> HackStudioWidget::get_editor_of_file(const String& filename)
|
||||
{
|
||||
String file_path = filename;
|
||||
|
||||
// TODO: We can probably do a more specific condition here, something like
|
||||
// "if (file.starts_with("../Libraries/") || file.starts_with("../AK/"))"
|
||||
if (filename.starts_with("../")) {
|
||||
file_path = get_full_path_of_serenity_source(filename);
|
||||
}
|
||||
|
@ -1060,6 +1069,11 @@ void HackStudioWidget::create_action_tab(GUI::Widget& parent)
|
|||
m_todo_entries_widget = m_action_tab_widget->add_tab<ToDoEntriesWidget>("TODO");
|
||||
m_terminal_wrapper = m_action_tab_widget->add_tab<TerminalWrapper>("Build", false);
|
||||
m_debug_info_widget = m_action_tab_widget->add_tab<DebugInfoWidget>("Debug");
|
||||
|
||||
m_debug_info_widget->on_backtrace_frame_selection = [this](Debug::DebugInfo::SourcePosition const& source_position) {
|
||||
open_file(get_absolute_path(source_position.file_path), source_position.line_number - 1);
|
||||
};
|
||||
|
||||
m_disassembly_widget = m_action_tab_widget->add_tab<DisassemblyWidget>("Disassembly");
|
||||
m_git_widget = m_action_tab_widget->add_tab<GitWidget>("Git", LexicalPath(m_project->root_path()));
|
||||
m_git_widget->set_view_diff_callback([this](const auto& original_content, const auto& diff) {
|
||||
|
@ -1452,4 +1466,20 @@ void HackStudioWidget::change_editor_font(RefPtr<Gfx::Font> font)
|
|||
Config::write_i32("HackStudio", "EditorFont", "Size", m_editor_font->presentation_size());
|
||||
}
|
||||
|
||||
void HackStudioWidget::open_coredump(String const& coredump_path)
|
||||
{
|
||||
open_project("/usr/src/serenity");
|
||||
m_mode = Mode::Coredump;
|
||||
|
||||
m_coredump_inspector = Coredump::Inspector::create(coredump_path, [this](float progress) {
|
||||
window()->set_progress(progress * 100);
|
||||
});
|
||||
window()->set_progress(0);
|
||||
|
||||
if (m_coredump_inspector) {
|
||||
m_debug_info_widget->update_state(*m_coredump_inspector, m_coredump_inspector->get_registers());
|
||||
reveal_action_tab(*m_debug_info_widget);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "ProjectFile.h"
|
||||
#include "TerminalWrapper.h"
|
||||
#include "ToDoEntriesWidget.h"
|
||||
#include <LibCoredump/Inspector.h>
|
||||
#include <LibGUI/ActionGroup.h>
|
||||
#include <LibGUI/Scrollbar.h>
|
||||
#include <LibGUI/Splitter.h>
|
||||
|
@ -62,11 +63,19 @@ public:
|
|||
};
|
||||
ContinueDecision warn_unsaved_changes(const String& prompt);
|
||||
|
||||
enum class Mode {
|
||||
Code,
|
||||
Coredump
|
||||
};
|
||||
|
||||
void open_coredump(String const& coredump_path);
|
||||
|
||||
private:
|
||||
static String get_full_path_of_serenity_source(const String& file);
|
||||
String get_absolute_path(String const&) const;
|
||||
Vector<String> selected_file_paths() const;
|
||||
|
||||
HackStudioWidget(const String& path_to_project);
|
||||
HackStudioWidget(String path_to_project);
|
||||
void open_project(const String& root_path);
|
||||
|
||||
enum class EditMode {
|
||||
|
@ -215,5 +224,8 @@ private:
|
|||
RefPtr<GUI::Action> m_no_wrapping_action;
|
||||
RefPtr<GUI::Action> m_wrap_anywhere_action;
|
||||
RefPtr<GUI::Action> m_wrap_at_words_action;
|
||||
|
||||
Mode m_mode { Mode::Code };
|
||||
OwnPtr<Coredump::Inspector> m_coredump_inspector;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@ NonnullRefPtr<ProjectFile> Project::create_file(const String& path) const
|
|||
return ProjectFile::construct_with_name(full_path);
|
||||
}
|
||||
|
||||
String Project::to_absolute_path(const String& path) const
|
||||
String Project::to_absolute_path(String const& path) const
|
||||
{
|
||||
if (LexicalPath { path }.is_absolute()) {
|
||||
return path;
|
||||
|
|
|
@ -29,12 +29,11 @@ public:
|
|||
NonnullRefPtr<ProjectFile> create_file(const String& path) const;
|
||||
|
||||
void for_each_text_file(Function<void(const ProjectFile&)>) const;
|
||||
String to_absolute_path(String const&) const;
|
||||
|
||||
private:
|
||||
explicit Project(const String& root_path);
|
||||
|
||||
String to_absolute_path(const String&) const;
|
||||
|
||||
RefPtr<GUI::FileSystemModel> m_model;
|
||||
|
||||
String m_root_path;
|
||||
|
|
|
@ -52,14 +52,16 @@ int main(int argc, char** argv)
|
|||
}
|
||||
|
||||
const char* path_argument = nullptr;
|
||||
bool mode_coredump = false;
|
||||
Core::ArgsParser args_parser;
|
||||
args_parser.add_positional_argument(path_argument, "Path to a workspace or a file", "path", Core::ArgsParser::Required::No);
|
||||
args_parser.add_option(mode_coredump, "Inspect a coredump in HackStudio", "coredump", 'c');
|
||||
args_parser.parse(argc, argv);
|
||||
|
||||
auto argument_absolute_path = Core::File::real_path_for(path_argument);
|
||||
|
||||
auto project_path = argument_absolute_path;
|
||||
if (argument_absolute_path.is_null())
|
||||
if (argument_absolute_path.is_null() || mode_coredump)
|
||||
project_path = Core::File::real_path_for(".");
|
||||
|
||||
s_hack_studio_widget = window->set_main_widget<HackStudioWidget>(project_path);
|
||||
|
@ -76,9 +78,11 @@ int main(int argc, char** argv)
|
|||
};
|
||||
|
||||
window->show();
|
||||
|
||||
s_hack_studio_widget->update_actions();
|
||||
|
||||
if (mode_coredump)
|
||||
s_hack_studio_widget->open_coredump(argument_absolute_path);
|
||||
|
||||
return app->exec();
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue