mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-06-04 01:12:56 +00:00
LibDebug: Move everything into the "Debug" namespace
This commit is contained in:
parent
b58ca7cf3d
commit
694b86a4bf
Notes:
sideshowbarker
2024-07-19 03:11:50 +09:00
Author: https://github.com/Lubrsi
Commit: 694b86a4bf
Pull-request: https://github.com/SerenityOS/serenity/pull/3290
31 changed files with 115 additions and 85 deletions
|
@ -46,7 +46,7 @@
|
||||||
|
|
||||||
RefPtr<Line::Editor> editor;
|
RefPtr<Line::Editor> editor;
|
||||||
|
|
||||||
OwnPtr<DebugSession> g_debug_session;
|
OwnPtr<Debug::DebugSession> g_debug_session;
|
||||||
|
|
||||||
static void handle_sigint(int)
|
static void handle_sigint(int)
|
||||||
{
|
{
|
||||||
|
@ -186,7 +186,7 @@ int main(int argc, char** argv)
|
||||||
"program", Core::ArgsParser::Required::Yes);
|
"program", Core::ArgsParser::Required::Yes);
|
||||||
args_parser.parse(argc, argv);
|
args_parser.parse(argc, argv);
|
||||||
|
|
||||||
auto result = DebugSession::exec_and_attach(command);
|
auto result = Debug::DebugSession::exec_and_attach(command);
|
||||||
if (!result) {
|
if (!result) {
|
||||||
fprintf(stderr, "Failed to start debugging session for: \"%s\"\n", command);
|
fprintf(stderr, "Failed to start debugging session for: \"%s\"\n", command);
|
||||||
exit(1);
|
exit(1);
|
||||||
|
@ -201,13 +201,13 @@ int main(int argc, char** argv)
|
||||||
bool rc = g_debug_session->insert_breakpoint(g_debug_session->elf().entry().as_ptr());
|
bool rc = g_debug_session->insert_breakpoint(g_debug_session->elf().entry().as_ptr());
|
||||||
ASSERT(rc);
|
ASSERT(rc);
|
||||||
|
|
||||||
DebugInfo::SourcePosition previous_source_position;
|
Debug::DebugInfo::SourcePosition previous_source_position;
|
||||||
bool in_step_line = false;
|
bool in_step_line = false;
|
||||||
|
|
||||||
g_debug_session->run([&](DebugSession::DebugBreakReason reason, Optional<PtraceRegisters> optional_regs) {
|
g_debug_session->run([&](Debug::DebugSession::DebugBreakReason reason, Optional<PtraceRegisters> optional_regs) {
|
||||||
if (reason == DebugSession::DebugBreakReason::Exited) {
|
if (reason == Debug::DebugSession::DebugBreakReason::Exited) {
|
||||||
printf("Program exited.\n");
|
printf("Program exited.\n");
|
||||||
return DebugSession::DebugDecision::Detach;
|
return Debug::DebugSession::DebugDecision::Detach;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT(optional_regs.has_value());
|
ASSERT(optional_regs.has_value());
|
||||||
|
@ -223,7 +223,7 @@ int main(int argc, char** argv)
|
||||||
printf("No source information for current instruction! stoppoing.\n");
|
printf("No source information for current instruction! stoppoing.\n");
|
||||||
in_step_line = false;
|
in_step_line = false;
|
||||||
} else {
|
} else {
|
||||||
return DebugSession::DebugDecision::SingleStep;
|
return Debug::DebugSession::DebugDecision::SingleStep;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -240,25 +240,25 @@ int main(int argc, char** argv)
|
||||||
auto command_result = editor->get_line("(sdb) ");
|
auto command_result = editor->get_line("(sdb) ");
|
||||||
|
|
||||||
if (command_result.is_error())
|
if (command_result.is_error())
|
||||||
return DebugSession::DebugDecision::Detach;
|
return Debug::DebugSession::DebugDecision::Detach;
|
||||||
|
|
||||||
auto& command = command_result.value();
|
auto& command = command_result.value();
|
||||||
|
|
||||||
bool success = false;
|
bool success = false;
|
||||||
Optional<DebugSession::DebugDecision> decision;
|
Optional<Debug::DebugSession::DebugDecision> decision;
|
||||||
|
|
||||||
if (command.is_empty() && !editor->history().is_empty()) {
|
if (command.is_empty() && !editor->history().is_empty()) {
|
||||||
command = editor->history().last();
|
command = editor->history().last();
|
||||||
}
|
}
|
||||||
if (command == "cont") {
|
if (command == "cont") {
|
||||||
decision = DebugSession::DebugDecision::Continue;
|
decision = Debug::DebugSession::DebugDecision::Continue;
|
||||||
success = true;
|
success = true;
|
||||||
} else if (command == "si") {
|
} else if (command == "si") {
|
||||||
decision = DebugSession::DebugDecision::SingleStep;
|
decision = Debug::DebugSession::DebugDecision::SingleStep;
|
||||||
success = true;
|
success = true;
|
||||||
} else if (command == "sl") {
|
} else if (command == "sl") {
|
||||||
if (source_position.has_value()) {
|
if (source_position.has_value()) {
|
||||||
decision = DebugSession::DebugDecision::SingleStep;
|
decision = Debug::DebugSession::DebugDecision::SingleStep;
|
||||||
in_step_line = true;
|
in_step_line = true;
|
||||||
success = true;
|
success = true;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
|
|
||||||
namespace HackStudio {
|
namespace HackStudio {
|
||||||
|
|
||||||
NonnullRefPtr<BacktraceModel> BacktraceModel::create(const DebugSession& debug_session, const PtraceRegisters& regs)
|
NonnullRefPtr<BacktraceModel> BacktraceModel::create(const Debug::DebugSession& debug_session, const PtraceRegisters& regs)
|
||||||
{
|
{
|
||||||
return adopt(*new BacktraceModel(create_backtrace(debug_session, regs)));
|
return adopt(*new BacktraceModel(create_backtrace(debug_session, regs)));
|
||||||
}
|
}
|
||||||
|
@ -51,7 +51,7 @@ GUI::ModelIndex BacktraceModel::index(int row, int column, const GUI::ModelIndex
|
||||||
return create_index(row, column, &m_frames.at(row));
|
return create_index(row, column, &m_frames.at(row));
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector<BacktraceModel::FrameInfo> BacktraceModel::create_backtrace(const DebugSession& debug_session, const PtraceRegisters& regs)
|
Vector<BacktraceModel::FrameInfo> BacktraceModel::create_backtrace(const Debug::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;
|
||||||
|
@ -64,7 +64,7 @@ Vector<BacktraceModel::FrameInfo> BacktraceModel::create_backtrace(const DebugSe
|
||||||
}
|
}
|
||||||
|
|
||||||
frames.append({ name, current_instruction, current_ebp });
|
frames.append({ name, current_instruction, current_ebp });
|
||||||
auto frame_info = StackFrameUtils::get_info(*Debugger::the().session(), current_ebp);
|
auto frame_info = Debug::StackFrameUtils::get_info(*Debugger::the().session(), current_ebp);
|
||||||
ASSERT(frame_info.has_value());
|
ASSERT(frame_info.has_value());
|
||||||
current_instruction = frame_info.value().return_address;
|
current_instruction = frame_info.value().return_address;
|
||||||
current_ebp = frame_info.value().next_ebp;
|
current_ebp = frame_info.value().next_ebp;
|
||||||
|
|
|
@ -31,13 +31,17 @@
|
||||||
#include <LibGUI/Model.h>
|
#include <LibGUI/Model.h>
|
||||||
#include <sys/arch/i386/regs.h>
|
#include <sys/arch/i386/regs.h>
|
||||||
|
|
||||||
|
namespace Debug {
|
||||||
|
|
||||||
class DebugSession;
|
class DebugSession;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
namespace HackStudio {
|
namespace HackStudio {
|
||||||
|
|
||||||
class BacktraceModel final : public GUI::Model {
|
class BacktraceModel final : public GUI::Model {
|
||||||
public:
|
public:
|
||||||
static NonnullRefPtr<BacktraceModel> create(const DebugSession&, const PtraceRegisters& regs);
|
static NonnullRefPtr<BacktraceModel> create(const Debug::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; }
|
||||||
|
@ -66,7 +70,7 @@ private:
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
static Vector<FrameInfo> create_backtrace(const DebugSession&, const PtraceRegisters&);
|
static Vector<FrameInfo> create_backtrace(const Debug::DebugSession&, const PtraceRegisters&);
|
||||||
|
|
||||||
Vector<FrameInfo> m_frames;
|
Vector<FrameInfo> m_frames;
|
||||||
};
|
};
|
||||||
|
|
|
@ -115,8 +115,8 @@ DebugInfoWidget::DebugInfoWidget()
|
||||||
auto is_valid_index = [](auto& index) {
|
auto is_valid_index = [](auto& index) {
|
||||||
if (!index.is_valid())
|
if (!index.is_valid())
|
||||||
return false;
|
return false;
|
||||||
auto* variable = static_cast<const DebugInfo::VariableInfo*>(index.internal_data());
|
auto* variable = static_cast<const Debug::DebugInfo::VariableInfo*>(index.internal_data());
|
||||||
if (variable->location_type != DebugInfo::VariableInfo::LocationType::Address)
|
if (variable->location_type != Debug::DebugInfo::VariableInfo::LocationType::Address)
|
||||||
return false;
|
return false;
|
||||||
return variable->is_enum_type() || variable->type_name.is_one_of("int", "bool");
|
return variable->is_enum_type() || variable->type_name.is_one_of("int", "bool");
|
||||||
};
|
};
|
||||||
|
@ -139,7 +139,7 @@ DebugInfoWidget::DebugInfoWidget()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void DebugInfoWidget::update_state(const 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));
|
||||||
|
|
|
@ -43,7 +43,7 @@ class DebugInfoWidget final : public GUI::Widget {
|
||||||
public:
|
public:
|
||||||
virtual ~DebugInfoWidget() override {}
|
virtual ~DebugInfoWidget() override {}
|
||||||
|
|
||||||
void update_state(const DebugSession&, const PtraceRegisters&);
|
void update_state(const Debug::DebugSession&, const PtraceRegisters&);
|
||||||
void program_stopped();
|
void program_stopped();
|
||||||
void set_debug_actions_enabled(bool enabled);
|
void set_debug_actions_enabled(bool enabled);
|
||||||
|
|
||||||
|
|
|
@ -69,7 +69,7 @@ void Debugger::on_breakpoint_change(const String& file, size_t line, BreakpointC
|
||||||
if (change_type == BreakpointChange::Added) {
|
if (change_type == BreakpointChange::Added) {
|
||||||
Debugger::the().m_breakpoints.append(position);
|
Debugger::the().m_breakpoints.append(position);
|
||||||
} else {
|
} else {
|
||||||
Debugger::the().m_breakpoints.remove_all_matching([&](DebugInfo::SourcePosition val) { return val == position; });
|
Debugger::the().m_breakpoints.remove_all_matching([&](Debug::DebugInfo::SourcePosition val) { return val == position; });
|
||||||
}
|
}
|
||||||
|
|
||||||
auto session = Debugger::the().session();
|
auto session = Debugger::the().session();
|
||||||
|
@ -94,7 +94,7 @@ void Debugger::on_breakpoint_change(const String& file, size_t line, BreakpointC
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DebugInfo::SourcePosition Debugger::create_source_position(const String& file, size_t line)
|
Debug::DebugInfo::SourcePosition Debugger::create_source_position(const String& file, size_t line)
|
||||||
{
|
{
|
||||||
if (!file.starts_with('/') && !file.starts_with("./"))
|
if (!file.starts_with('/') && !file.starts_with("./"))
|
||||||
return { String::format("./%s", file.characters()), line + 1 };
|
return { String::format("./%s", file.characters()), line + 1 };
|
||||||
|
@ -109,7 +109,7 @@ int Debugger::start_static()
|
||||||
|
|
||||||
void Debugger::start()
|
void Debugger::start()
|
||||||
{
|
{
|
||||||
m_debug_session = DebugSession::exec_and_attach(m_executable_path);
|
m_debug_session = Debug::DebugSession::exec_and_attach(m_executable_path);
|
||||||
ASSERT(!!m_debug_session);
|
ASSERT(!!m_debug_session);
|
||||||
|
|
||||||
for (const auto& breakpoint : m_breakpoints) {
|
for (const auto& breakpoint : m_breakpoints) {
|
||||||
|
@ -130,11 +130,11 @@ int Debugger::debugger_loop()
|
||||||
{
|
{
|
||||||
ASSERT(m_debug_session);
|
ASSERT(m_debug_session);
|
||||||
|
|
||||||
m_debug_session->run([&](DebugSession::DebugBreakReason reason, Optional<PtraceRegisters> optional_regs) {
|
m_debug_session->run([&](Debug::DebugSession::DebugBreakReason reason, Optional<PtraceRegisters> optional_regs) {
|
||||||
if (reason == DebugSession::DebugBreakReason::Exited) {
|
if (reason == Debug::DebugSession::DebugBreakReason::Exited) {
|
||||||
dbg() << "Program exited";
|
dbg() << "Program exited";
|
||||||
m_on_exit_callback();
|
m_on_exit_callback();
|
||||||
return DebugSession::DebugDecision::Detach;
|
return Debug::DebugSession::DebugDecision::Detach;
|
||||||
}
|
}
|
||||||
remove_temporary_breakpoints();
|
remove_temporary_breakpoints();
|
||||||
ASSERT(optional_regs.has_value());
|
ASSERT(optional_regs.has_value());
|
||||||
|
@ -146,7 +146,7 @@ int Debugger::debugger_loop()
|
||||||
if (m_state.should_stop_single_stepping(source_position.value())) {
|
if (m_state.should_stop_single_stepping(source_position.value())) {
|
||||||
m_state.set_normal();
|
m_state.set_normal();
|
||||||
} else {
|
} else {
|
||||||
return DebugSession::DebugDecision::SingleStep;
|
return Debug::DebugSession::DebugDecision::SingleStep;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,18 +165,18 @@ int Debugger::debugger_loop()
|
||||||
switch (m_continue_type) {
|
switch (m_continue_type) {
|
||||||
case ContinueType::Continue:
|
case ContinueType::Continue:
|
||||||
m_state.set_normal();
|
m_state.set_normal();
|
||||||
return DebugSession::DebugDecision::Continue;
|
return Debug::DebugSession::DebugDecision::Continue;
|
||||||
case ContinueType::SourceSingleStep:
|
case ContinueType::SourceSingleStep:
|
||||||
m_state.set_single_stepping(source_position.value());
|
m_state.set_single_stepping(source_position.value());
|
||||||
return DebugSession::DebugDecision::SingleStep;
|
return Debug::DebugSession::DebugDecision::SingleStep;
|
||||||
case ContinueType::SourceStepOut:
|
case ContinueType::SourceStepOut:
|
||||||
m_state.set_stepping_out();
|
m_state.set_stepping_out();
|
||||||
do_step_out(regs);
|
do_step_out(regs);
|
||||||
return DebugSession::DebugDecision::Continue;
|
return Debug::DebugSession::DebugDecision::Continue;
|
||||||
case ContinueType::SourceStepOver:
|
case ContinueType::SourceStepOver:
|
||||||
m_state.set_stepping_over();
|
m_state.set_stepping_over();
|
||||||
do_step_over(regs);
|
do_step_over(regs);
|
||||||
return DebugSession::DebugDecision::Continue;
|
return Debug::DebugSession::DebugDecision::Continue;
|
||||||
}
|
}
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
});
|
});
|
||||||
|
@ -190,13 +190,13 @@ void Debugger::DebuggingState::set_normal()
|
||||||
m_original_source_position.clear();
|
m_original_source_position.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Debugger::DebuggingState::set_single_stepping(DebugInfo::SourcePosition original_source_position)
|
void Debugger::DebuggingState::set_single_stepping(Debug::DebugInfo::SourcePosition original_source_position)
|
||||||
{
|
{
|
||||||
m_state = State::SingleStepping;
|
m_state = State::SingleStepping;
|
||||||
m_original_source_position = original_source_position;
|
m_original_source_position = original_source_position;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Debugger::DebuggingState::should_stop_single_stepping(const DebugInfo::SourcePosition& current_source_position) const
|
bool Debugger::DebuggingState::should_stop_single_stepping(const Debug::DebugInfo::SourcePosition& current_source_position) const
|
||||||
{
|
{
|
||||||
ASSERT(m_state == State::SingleStepping);
|
ASSERT(m_state == State::SingleStepping);
|
||||||
return m_original_source_position.value() != current_source_position;
|
return m_original_source_position.value() != current_source_position;
|
||||||
|
@ -244,7 +244,7 @@ void Debugger::do_step_over(const PtraceRegisters& regs)
|
||||||
|
|
||||||
void Debugger::insert_temporary_breakpoint_at_return_address(const PtraceRegisters& regs)
|
void Debugger::insert_temporary_breakpoint_at_return_address(const PtraceRegisters& regs)
|
||||||
{
|
{
|
||||||
auto frame_info = StackFrameUtils::get_info(*m_debug_session, regs.ebp);
|
auto frame_info = Debug::StackFrameUtils::get_info(*m_debug_session, regs.ebp);
|
||||||
ASSERT(frame_info.has_value());
|
ASSERT(frame_info.has_value());
|
||||||
u32 return_address = frame_info.value().return_address;
|
u32 return_address = frame_info.value().return_address;
|
||||||
insert_temporary_breakpoint(return_address);
|
insert_temporary_breakpoint(return_address);
|
||||||
|
|
|
@ -55,7 +55,7 @@ public:
|
||||||
|
|
||||||
void set_executable_path(const String& path) { m_executable_path = path; }
|
void set_executable_path(const String& path) { m_executable_path = path; }
|
||||||
|
|
||||||
DebugSession* session() { return m_debug_session.ptr(); }
|
Debug::DebugSession* session() { return m_debug_session.ptr(); }
|
||||||
|
|
||||||
// Thread entry point
|
// Thread entry point
|
||||||
static int start_static();
|
static int start_static();
|
||||||
|
@ -85,18 +85,18 @@ private:
|
||||||
State get() const { return m_state; }
|
State get() const { return m_state; }
|
||||||
|
|
||||||
void set_normal();
|
void set_normal();
|
||||||
void set_single_stepping(DebugInfo::SourcePosition original_source_position);
|
void set_single_stepping(Debug::DebugInfo::SourcePosition original_source_position);
|
||||||
void set_stepping_out() { m_state = State::SteppingOut; }
|
void set_stepping_out() { m_state = State::SteppingOut; }
|
||||||
void set_stepping_over() { m_state = State::SteppingOver; }
|
void set_stepping_over() { m_state = State::SteppingOver; }
|
||||||
|
|
||||||
bool should_stop_single_stepping(const DebugInfo::SourcePosition& current_source_position) const;
|
bool should_stop_single_stepping(const Debug::DebugInfo::SourcePosition& current_source_position) const;
|
||||||
void clear_temporary_breakpoints();
|
void clear_temporary_breakpoints();
|
||||||
void add_temporary_breakpoint(u32 address);
|
void add_temporary_breakpoint(u32 address);
|
||||||
const Vector<u32>& temporary_breakpoints() const { return m_addresses_of_temporary_breakpoints; }
|
const Vector<u32>& temporary_breakpoints() const { return m_addresses_of_temporary_breakpoints; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
State m_state { Normal };
|
State m_state { Normal };
|
||||||
Optional<DebugInfo::SourcePosition> m_original_source_position; // The source position at which we started the current single step
|
Optional<Debug::DebugInfo::SourcePosition> m_original_source_position; // The source position at which we started the current single step
|
||||||
Vector<u32> m_addresses_of_temporary_breakpoints;
|
Vector<u32> m_addresses_of_temporary_breakpoints;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -105,7 +105,7 @@ private:
|
||||||
Function<void()> on_continue_callback,
|
Function<void()> on_continue_callback,
|
||||||
Function<void()> on_exit_callback);
|
Function<void()> on_exit_callback);
|
||||||
|
|
||||||
static DebugInfo::SourcePosition create_source_position(const String& file, size_t line);
|
static Debug::DebugInfo::SourcePosition create_source_position(const String& file, size_t line);
|
||||||
|
|
||||||
void start();
|
void start();
|
||||||
int debugger_loop();
|
int debugger_loop();
|
||||||
|
@ -116,13 +116,13 @@ private:
|
||||||
void insert_temporary_breakpoint(FlatPtr address);
|
void insert_temporary_breakpoint(FlatPtr address);
|
||||||
void insert_temporary_breakpoint_at_return_address(const PtraceRegisters&);
|
void insert_temporary_breakpoint_at_return_address(const PtraceRegisters&);
|
||||||
|
|
||||||
OwnPtr<DebugSession> m_debug_session;
|
OwnPtr<Debug::DebugSession> m_debug_session;
|
||||||
DebuggingState m_state;
|
DebuggingState m_state;
|
||||||
|
|
||||||
pthread_mutex_t m_continue_mutex {};
|
pthread_mutex_t m_continue_mutex {};
|
||||||
pthread_cond_t m_continue_cond {};
|
pthread_cond_t m_continue_cond {};
|
||||||
|
|
||||||
Vector<DebugInfo::SourcePosition> m_breakpoints;
|
Vector<Debug::DebugInfo::SourcePosition> m_breakpoints;
|
||||||
|
|
||||||
String m_executable_path;
|
String m_executable_path;
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@ GUI::ModelIndex VariablesModel::index(int row, int column, const GUI::ModelIndex
|
||||||
{
|
{
|
||||||
if (!parent_index.is_valid())
|
if (!parent_index.is_valid())
|
||||||
return create_index(row, column, &m_variables[row]);
|
return create_index(row, column, &m_variables[row]);
|
||||||
auto* parent = static_cast<const DebugInfo::VariableInfo*>(parent_index.internal_data());
|
auto* parent = static_cast<const Debug::DebugInfo::VariableInfo*>(parent_index.internal_data());
|
||||||
auto* child = &parent->members[row];
|
auto* child = &parent->members[row];
|
||||||
return create_index(row, column, child);
|
return create_index(row, column, child);
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,7 @@ GUI::ModelIndex VariablesModel::parent_index(const GUI::ModelIndex& index) const
|
||||||
{
|
{
|
||||||
if (!index.is_valid())
|
if (!index.is_valid())
|
||||||
return {};
|
return {};
|
||||||
auto* child = static_cast<const DebugInfo::VariableInfo*>(index.internal_data());
|
auto* child = static_cast<const Debug::DebugInfo::VariableInfo*>(index.internal_data());
|
||||||
auto* parent = child->parent;
|
auto* parent = child->parent;
|
||||||
if (parent == nullptr)
|
if (parent == nullptr)
|
||||||
return {};
|
return {};
|
||||||
|
@ -55,7 +55,7 @@ GUI::ModelIndex VariablesModel::parent_index(const GUI::ModelIndex& index) const
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
for (size_t row = 0; row < parent->parent->members.size(); row++) {
|
for (size_t row = 0; row < parent->parent->members.size(); row++) {
|
||||||
DebugInfo::VariableInfo* child_at_row = parent->parent->members.ptr_at(row).ptr();
|
Debug::DebugInfo::VariableInfo* child_at_row = parent->parent->members.ptr_at(row).ptr();
|
||||||
if (child_at_row == parent)
|
if (child_at_row == parent)
|
||||||
return create_index(row, 0, parent);
|
return create_index(row, 0, parent);
|
||||||
}
|
}
|
||||||
|
@ -66,13 +66,13 @@ int VariablesModel::row_count(const GUI::ModelIndex& index) const
|
||||||
{
|
{
|
||||||
if (!index.is_valid())
|
if (!index.is_valid())
|
||||||
return m_variables.size();
|
return m_variables.size();
|
||||||
auto* node = static_cast<const DebugInfo::VariableInfo*>(index.internal_data());
|
auto* node = static_cast<const Debug::DebugInfo::VariableInfo*>(index.internal_data());
|
||||||
return node->members.size();
|
return node->members.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
static String variable_value_as_string(const DebugInfo::VariableInfo& variable)
|
static String variable_value_as_string(const Debug::DebugInfo::VariableInfo& variable)
|
||||||
{
|
{
|
||||||
if (variable.location_type != DebugInfo::VariableInfo::LocationType::Address)
|
if (variable.location_type != Debug::DebugInfo::VariableInfo::LocationType::Address)
|
||||||
return "N/A";
|
return "N/A";
|
||||||
|
|
||||||
auto variable_address = variable.location_data.address;
|
auto variable_address = variable.location_data.address;
|
||||||
|
@ -108,7 +108,7 @@ static String variable_value_as_string(const DebugInfo::VariableInfo& variable)
|
||||||
return String::format("type: %s @ %08x, ", variable.type_name.characters(), variable_address);
|
return String::format("type: %s @ %08x, ", variable.type_name.characters(), variable_address);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Optional<u32> string_to_variable_value(const StringView& string_value, const DebugInfo::VariableInfo& variable)
|
static Optional<u32> string_to_variable_value(const StringView& string_value, const Debug::DebugInfo::VariableInfo& variable)
|
||||||
{
|
{
|
||||||
if (variable.is_enum_type()) {
|
if (variable.is_enum_type()) {
|
||||||
auto prefix_string = String::format("%s::", variable.type_name.characters());
|
auto prefix_string = String::format("%s::", variable.type_name.characters());
|
||||||
|
@ -145,7 +145,7 @@ static Optional<u32> string_to_variable_value(const StringView& string_value, co
|
||||||
|
|
||||||
void VariablesModel::set_variable_value(const GUI::ModelIndex& index, const StringView& string_value, GUI::Window* parent_window)
|
void VariablesModel::set_variable_value(const GUI::ModelIndex& index, const StringView& string_value, GUI::Window* parent_window)
|
||||||
{
|
{
|
||||||
auto variable = static_cast<const DebugInfo::VariableInfo*>(index.internal_data());
|
auto variable = static_cast<const Debug::DebugInfo::VariableInfo*>(index.internal_data());
|
||||||
|
|
||||||
auto value = string_to_variable_value(string_value, *variable);
|
auto value = string_to_variable_value(string_value, *variable);
|
||||||
|
|
||||||
|
@ -163,7 +163,7 @@ void VariablesModel::set_variable_value(const GUI::ModelIndex& index, const Stri
|
||||||
|
|
||||||
GUI::Variant VariablesModel::data(const GUI::ModelIndex& index, GUI::ModelRole role) const
|
GUI::Variant VariablesModel::data(const GUI::ModelIndex& index, GUI::ModelRole role) const
|
||||||
{
|
{
|
||||||
auto* variable = static_cast<const DebugInfo::VariableInfo*>(index.internal_data());
|
auto* variable = static_cast<const Debug::DebugInfo::VariableInfo*>(index.internal_data());
|
||||||
switch (role) {
|
switch (role) {
|
||||||
case GUI::ModelRole::Display: {
|
case GUI::ModelRole::Display: {
|
||||||
auto value_as_string = variable_value_as_string(*variable);
|
auto value_as_string = variable_value_as_string(*variable);
|
||||||
|
|
|
@ -48,13 +48,13 @@ public:
|
||||||
virtual GUI::ModelIndex index(int row, int column = 0, const GUI::ModelIndex& = GUI::ModelIndex()) const override;
|
virtual GUI::ModelIndex index(int row, int column = 0, const GUI::ModelIndex& = GUI::ModelIndex()) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit VariablesModel(NonnullOwnPtrVector<DebugInfo::VariableInfo>&& variables, const PtraceRegisters& regs)
|
explicit VariablesModel(NonnullOwnPtrVector<Debug::DebugInfo::VariableInfo>&& variables, const PtraceRegisters& regs)
|
||||||
: m_variables(move(variables))
|
: m_variables(move(variables))
|
||||||
, m_regs(regs)
|
, m_regs(regs)
|
||||||
{
|
{
|
||||||
m_variable_icon.set_bitmap_for_size(16, Gfx::Bitmap::load_from_file("/res/icons/16x16/inspector-object.png"));
|
m_variable_icon.set_bitmap_for_size(16, Gfx::Bitmap::load_from_file("/res/icons/16x16/inspector-object.png"));
|
||||||
}
|
}
|
||||||
NonnullOwnPtrVector<DebugInfo::VariableInfo> m_variables;
|
NonnullOwnPtrVector<Debug::DebugInfo::VariableInfo> m_variables;
|
||||||
PtraceRegisters m_regs;
|
PtraceRegisters m_regs;
|
||||||
|
|
||||||
GUI::Icon m_variable_icon;
|
GUI::Icon m_variable_icon;
|
||||||
|
|
|
@ -154,7 +154,7 @@ bool Emulator::load_elf()
|
||||||
m_free_symbol_start = free_symbol.value().value();
|
m_free_symbol_start = free_symbol.value().value();
|
||||||
m_free_symbol_end = m_free_symbol_start + free_symbol.value().size();
|
m_free_symbol_end = m_free_symbol_start + free_symbol.value().size();
|
||||||
|
|
||||||
m_debug_info = make<DebugInfo>(m_elf);
|
m_debug_info = make<Debug::DebugInfo>(m_elf);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -64,7 +64,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NonnullRefPtr<ELF::Loader> m_elf;
|
NonnullRefPtr<ELF::Loader> m_elf;
|
||||||
OwnPtr<DebugInfo> m_debug_info;
|
OwnPtr<Debug::DebugInfo> m_debug_info;
|
||||||
|
|
||||||
SoftMMU m_mmu;
|
SoftMMU m_mmu;
|
||||||
SoftCPU m_cpu;
|
SoftCPU m_cpu;
|
||||||
|
|
|
@ -33,6 +33,8 @@
|
||||||
|
|
||||||
//#define DEBUG_SPAM
|
//#define DEBUG_SPAM
|
||||||
|
|
||||||
|
namespace Debug {
|
||||||
|
|
||||||
DebugInfo::DebugInfo(NonnullRefPtr<const ELF::Loader> elf)
|
DebugInfo::DebugInfo(NonnullRefPtr<const ELF::Loader> elf)
|
||||||
: m_elf(elf)
|
: m_elf(elf)
|
||||||
, m_dwarf_info(Dwarf::DwarfInfo::create(m_elf))
|
, m_dwarf_info(Dwarf::DwarfInfo::create(m_elf))
|
||||||
|
@ -107,9 +109,9 @@ void DebugInfo::prepare_lines()
|
||||||
auto buffer = section.wrapping_byte_buffer();
|
auto buffer = section.wrapping_byte_buffer();
|
||||||
InputMemoryStream stream { buffer };
|
InputMemoryStream stream { buffer };
|
||||||
|
|
||||||
Vector<LineProgram::LineInfo> all_lines;
|
Vector<Dwarf::LineProgram::LineInfo> all_lines;
|
||||||
while (!stream.eof()) {
|
while (!stream.eof()) {
|
||||||
LineProgram program(stream);
|
Dwarf::LineProgram program(stream);
|
||||||
all_lines.append(program.lines());
|
all_lines.append(program.lines());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -331,7 +333,9 @@ Vector<DebugInfo::SourcePosition> DebugInfo::source_lines_in_scope(const Variabl
|
||||||
return source_lines;
|
return source_lines;
|
||||||
}
|
}
|
||||||
|
|
||||||
DebugInfo::SourcePosition DebugInfo::SourcePosition::from_line_info(const LineProgram::LineInfo& line)
|
DebugInfo::SourcePosition DebugInfo::SourcePosition::from_line_info(const Dwarf::LineProgram::LineInfo& line)
|
||||||
{
|
{
|
||||||
return { line.file, line.line, line.address };
|
return { line.file, line.line, line.address };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -36,6 +36,8 @@
|
||||||
#include <LibELF/Loader.h>
|
#include <LibELF/Loader.h>
|
||||||
#include <sys/arch/i386/regs.h>
|
#include <sys/arch/i386/regs.h>
|
||||||
|
|
||||||
|
namespace Debug {
|
||||||
|
|
||||||
class DebugInfo {
|
class DebugInfo {
|
||||||
public:
|
public:
|
||||||
explicit DebugInfo(NonnullRefPtr<const ELF::Loader> elf);
|
explicit DebugInfo(NonnullRefPtr<const ELF::Loader> elf);
|
||||||
|
@ -48,7 +50,7 @@ public:
|
||||||
bool operator==(const SourcePosition& other) const { return file_path == other.file_path && line_number == other.line_number; }
|
bool operator==(const SourcePosition& other) const { return file_path == other.file_path && line_number == other.line_number; }
|
||||||
bool operator!=(const SourcePosition& other) const { return !(*this == other); }
|
bool operator!=(const SourcePosition& other) const { return !(*this == other); }
|
||||||
|
|
||||||
static SourcePosition from_line_info(const LineProgram::LineInfo&);
|
static SourcePosition from_line_info(const Dwarf::LineProgram::LineInfo&);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct VariableInfo {
|
struct VariableInfo {
|
||||||
|
@ -119,5 +121,7 @@ private:
|
||||||
NonnullRefPtr<Dwarf::DwarfInfo> m_dwarf_info;
|
NonnullRefPtr<Dwarf::DwarfInfo> m_dwarf_info;
|
||||||
|
|
||||||
Vector<VariablesScope> m_scopes;
|
Vector<VariablesScope> m_scopes;
|
||||||
Vector<LineProgram::LineInfo> m_sorted_lines;
|
Vector<Dwarf::LineProgram::LineInfo> m_sorted_lines;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -28,6 +28,8 @@
|
||||||
#include <AK/Optional.h>
|
#include <AK/Optional.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
namespace Debug {
|
||||||
|
|
||||||
DebugSession::DebugSession(int pid)
|
DebugSession::DebugSession(int pid)
|
||||||
: m_debugee_pid(pid)
|
: m_debugee_pid(pid)
|
||||||
, m_executable(initialize_executable_mapped_file(pid))
|
, m_executable(initialize_executable_mapped_file(pid))
|
||||||
|
@ -263,3 +265,5 @@ void* DebugSession::single_step()
|
||||||
set_registers(regs);
|
set_registers(regs);
|
||||||
return (void*)regs.eip;
|
return (void*)regs.eip;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -42,6 +42,8 @@
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
namespace Debug {
|
||||||
|
|
||||||
class DebugSession {
|
class DebugSession {
|
||||||
public:
|
public:
|
||||||
static OwnPtr<DebugSession> exec_and_attach(const String& command);
|
static OwnPtr<DebugSession> exec_and_attach(const String& command);
|
||||||
|
@ -243,3 +245,5 @@ void DebugSession::run(Callback callback)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
|
|
||||||
#include <AK/Stream.h>
|
#include <AK/Stream.h>
|
||||||
|
|
||||||
namespace Dwarf {
|
namespace Debug::Dwarf {
|
||||||
|
|
||||||
AbbreviationsMap::AbbreviationsMap(const DwarfInfo& dwarf_info, u32 offset)
|
AbbreviationsMap::AbbreviationsMap(const DwarfInfo& dwarf_info, u32 offset)
|
||||||
: m_dwarf_info(dwarf_info)
|
: m_dwarf_info(dwarf_info)
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
#include <AK/Optional.h>
|
#include <AK/Optional.h>
|
||||||
#include <AK/Types.h>
|
#include <AK/Types.h>
|
||||||
|
|
||||||
namespace Dwarf {
|
namespace Debug::Dwarf {
|
||||||
|
|
||||||
class DwarfInfo;
|
class DwarfInfo;
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
#include "CompilationUnit.h"
|
#include "CompilationUnit.h"
|
||||||
#include "DIE.h"
|
#include "DIE.h"
|
||||||
|
|
||||||
namespace Dwarf {
|
namespace Debug::Dwarf {
|
||||||
|
|
||||||
CompilationUnit::CompilationUnit(const DwarfInfo& dwarf_info, u32 offset, const CompilationUnitHeader& header)
|
CompilationUnit::CompilationUnit(const DwarfInfo& dwarf_info, u32 offset, const CompilationUnitHeader& header)
|
||||||
: m_dwarf_info(dwarf_info)
|
: m_dwarf_info(dwarf_info)
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
#include "AbbreviationsMap.h"
|
#include "AbbreviationsMap.h"
|
||||||
#include <AK/Types.h>
|
#include <AK/Types.h>
|
||||||
|
|
||||||
namespace Dwarf {
|
namespace Debug::Dwarf {
|
||||||
|
|
||||||
class DwarfInfo;
|
class DwarfInfo;
|
||||||
class DIE;
|
class DIE;
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
#include <AK/ByteBuffer.h>
|
#include <AK/ByteBuffer.h>
|
||||||
#include <AK/Stream.h>
|
#include <AK/Stream.h>
|
||||||
|
|
||||||
namespace Dwarf {
|
namespace Debug::Dwarf {
|
||||||
|
|
||||||
DIE::DIE(const CompilationUnit& unit, u32 offset)
|
DIE::DIE(const CompilationUnit& unit, u32 offset)
|
||||||
: m_compilation_unit(unit)
|
: m_compilation_unit(unit)
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
#include <AK/Optional.h>
|
#include <AK/Optional.h>
|
||||||
#include <AK/Types.h>
|
#include <AK/Types.h>
|
||||||
|
|
||||||
namespace Dwarf {
|
namespace Debug::Dwarf {
|
||||||
|
|
||||||
class CompilationUnit;
|
class CompilationUnit;
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
|
|
||||||
#include <AK/Stream.h>
|
#include <AK/Stream.h>
|
||||||
|
|
||||||
namespace Dwarf {
|
namespace Debug::Dwarf {
|
||||||
|
|
||||||
DwarfInfo::DwarfInfo(NonnullRefPtr<const ELF::Loader> elf)
|
DwarfInfo::DwarfInfo(NonnullRefPtr<const ELF::Loader> elf)
|
||||||
: m_elf(elf)
|
: m_elf(elf)
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
#include <AK/String.h>
|
#include <AK/String.h>
|
||||||
#include <LibELF/Loader.h>
|
#include <LibELF/Loader.h>
|
||||||
|
|
||||||
namespace Dwarf {
|
namespace Debug::Dwarf {
|
||||||
|
|
||||||
class DwarfInfo : public RefCounted<DwarfInfo> {
|
class DwarfInfo : public RefCounted<DwarfInfo> {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
|
|
||||||
#include <AK/Types.h>
|
#include <AK/Types.h>
|
||||||
|
|
||||||
namespace Dwarf {
|
namespace Debug::Dwarf {
|
||||||
|
|
||||||
struct [[gnu::packed]] CompilationUnitHeader
|
struct [[gnu::packed]] CompilationUnitHeader
|
||||||
{
|
{
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
|
|
||||||
#include <sys/arch/i386/regs.h>
|
#include <sys/arch/i386/regs.h>
|
||||||
|
|
||||||
namespace Dwarf::Expression {
|
namespace Debug::Dwarf::Expression {
|
||||||
|
|
||||||
Value evaluate(ReadonlyBytes bytes, const PtraceRegisters& regs)
|
Value evaluate(ReadonlyBytes bytes, const PtraceRegisters& regs)
|
||||||
{
|
{
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
|
|
||||||
class PtraceRegisters;
|
class PtraceRegisters;
|
||||||
|
|
||||||
namespace Dwarf::Expression {
|
namespace Debug::Dwarf::Expression {
|
||||||
|
|
||||||
enum class Type {
|
enum class Type {
|
||||||
None,
|
None,
|
||||||
|
|
|
@ -30,6 +30,8 @@
|
||||||
|
|
||||||
//#define DWARF_DEBUG
|
//#define DWARF_DEBUG
|
||||||
|
|
||||||
|
namespace Debug::Dwarf {
|
||||||
|
|
||||||
LineProgram::LineProgram(InputMemoryStream& stream)
|
LineProgram::LineProgram(InputMemoryStream& stream)
|
||||||
: m_stream(stream)
|
: m_stream(stream)
|
||||||
{
|
{
|
||||||
|
@ -252,3 +254,5 @@ void LineProgram::run_program()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -30,6 +30,8 @@
|
||||||
#include <AK/String.h>
|
#include <AK/String.h>
|
||||||
#include <AK/Vector.h>
|
#include <AK/Vector.h>
|
||||||
|
|
||||||
|
namespace Debug::Dwarf {
|
||||||
|
|
||||||
class LineProgram {
|
class LineProgram {
|
||||||
public:
|
public:
|
||||||
explicit LineProgram(InputMemoryStream& stream);
|
explicit LineProgram(InputMemoryStream& stream);
|
||||||
|
@ -55,8 +57,7 @@ private:
|
||||||
void handle_standard_opcode(u8 opcode);
|
void handle_standard_opcode(u8 opcode);
|
||||||
void handle_sepcial_opcode(u8 opcode);
|
void handle_sepcial_opcode(u8 opcode);
|
||||||
|
|
||||||
struct [[gnu::packed]] UnitHeader32
|
struct [[gnu::packed]] UnitHeader32 {
|
||||||
{
|
|
||||||
u32 length;
|
u32 length;
|
||||||
u16 version;
|
u16 version;
|
||||||
u32 header_length;
|
u32 header_length;
|
||||||
|
@ -113,3 +114,5 @@ private:
|
||||||
|
|
||||||
Vector<LineInfo> m_lines;
|
Vector<LineInfo> m_lines;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -26,7 +26,8 @@
|
||||||
|
|
||||||
#include "StackFrameUtils.h"
|
#include "StackFrameUtils.h"
|
||||||
|
|
||||||
namespace StackFrameUtils {
|
namespace Debug::StackFrameUtils {
|
||||||
|
|
||||||
Optional<StackFrameInfo> get_info(const DebugSession& session, FlatPtr current_ebp)
|
Optional<StackFrameInfo> get_info(const DebugSession& session, FlatPtr current_ebp)
|
||||||
{
|
{
|
||||||
auto return_address = session.peek(reinterpret_cast<u32*>(current_ebp + sizeof(FlatPtr)));
|
auto return_address = session.peek(reinterpret_cast<u32*>(current_ebp + sizeof(FlatPtr)));
|
||||||
|
@ -37,4 +38,5 @@ Optional<StackFrameInfo> get_info(const DebugSession& session, FlatPtr current_e
|
||||||
StackFrameInfo info = { return_address.value(), next_ebp.value() };
|
StackFrameInfo info = { return_address.value(), next_ebp.value() };
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,8 @@
|
||||||
|
|
||||||
#include "LibDebug/DebugSession.h"
|
#include "LibDebug/DebugSession.h"
|
||||||
|
|
||||||
namespace StackFrameUtils {
|
namespace Debug::StackFrameUtils {
|
||||||
|
|
||||||
struct StackFrameInfo {
|
struct StackFrameInfo {
|
||||||
FlatPtr return_address;
|
FlatPtr return_address;
|
||||||
FlatPtr next_ebp;
|
FlatPtr next_ebp;
|
||||||
|
|
|
@ -47,7 +47,7 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
static OwnPtr<DebugSession> g_debug_session;
|
static OwnPtr<Debug::DebugSession> g_debug_session;
|
||||||
static bool g_should_output_color = false;
|
static bool g_should_output_color = false;
|
||||||
|
|
||||||
static void handle_sigint(int)
|
static void handle_sigint(int)
|
||||||
|
@ -126,7 +126,7 @@ int main(int argc, char** argv)
|
||||||
"program", Core::ArgsParser::Required::Yes);
|
"program", Core::ArgsParser::Required::Yes);
|
||||||
args_parser.parse(argc, argv);
|
args_parser.parse(argc, argv);
|
||||||
|
|
||||||
auto result = DebugSession::exec_and_attach(command);
|
auto result = Debug::DebugSession::exec_and_attach(command);
|
||||||
if (!result) {
|
if (!result) {
|
||||||
fprintf(stderr, "Failed to start debugging session for: \"%s\"\n", command);
|
fprintf(stderr, "Failed to start debugging session for: \"%s\"\n", command);
|
||||||
exit(1);
|
exit(1);
|
||||||
|
@ -143,29 +143,29 @@ int main(int argc, char** argv)
|
||||||
size_t depth = 0;
|
size_t depth = 0;
|
||||||
bool new_function = true;
|
bool new_function = true;
|
||||||
|
|
||||||
g_debug_session->run([&](DebugSession::DebugBreakReason reason, Optional<PtraceRegisters> regs) {
|
g_debug_session->run([&](Debug::DebugSession::DebugBreakReason reason, Optional<PtraceRegisters> regs) {
|
||||||
if (reason == DebugSession::DebugBreakReason::Exited) {
|
if (reason == Debug::DebugSession::DebugBreakReason::Exited) {
|
||||||
printf("Program exited.\n");
|
printf("Program exited.\n");
|
||||||
return DebugSession::DebugDecision::Detach;
|
return Debug::DebugSession::DebugDecision::Detach;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reason == DebugSession::DebugBreakReason::Syscall) {
|
if (reason == Debug::DebugSession::DebugBreakReason::Syscall) {
|
||||||
print_syscall(regs.value(), depth + 1);
|
print_syscall(regs.value(), depth + 1);
|
||||||
return DebugSession::DebugDecision::ContinueBreakAtSyscall;
|
return Debug::DebugSession::DebugDecision::ContinueBreakAtSyscall;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (new_function) {
|
if (new_function) {
|
||||||
auto function_name = g_debug_session->elf().symbolicate(regs.value().eip);
|
auto function_name = g_debug_session->elf().symbolicate(regs.value().eip);
|
||||||
print_function_call(function_name, depth);
|
print_function_call(function_name, depth);
|
||||||
new_function = false;
|
new_function = false;
|
||||||
return DebugSession::ContinueBreakAtSyscall;
|
return Debug::DebugSession::ContinueBreakAtSyscall;
|
||||||
}
|
}
|
||||||
auto instruction = instrumented->get((void*)regs.value().eip).value();
|
auto instruction = instrumented->get((void*)regs.value().eip).value();
|
||||||
|
|
||||||
if (instruction.mnemonic() == "RET") {
|
if (instruction.mnemonic() == "RET") {
|
||||||
if (depth != 0)
|
if (depth != 0)
|
||||||
--depth;
|
--depth;
|
||||||
return DebugSession::ContinueBreakAtSyscall;
|
return Debug::DebugSession::ContinueBreakAtSyscall;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: we could miss some leaf functions that were called with a jump
|
// FIXME: we could miss some leaf functions that were called with a jump
|
||||||
|
@ -174,6 +174,6 @@ int main(int argc, char** argv)
|
||||||
++depth;
|
++depth;
|
||||||
new_function = true;
|
new_function = true;
|
||||||
|
|
||||||
return DebugSession::DebugDecision::SingleStep;
|
return Debug::DebugSession::DebugDecision::SingleStep;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue