Skip to content

Commit 94db04f

Browse files
itamar8910awesomekling
authored andcommitted
HackStudio: Make debugger support shared libraries
1 parent dcdb68a commit 94db04f

File tree

7 files changed

+55
-21
lines changed

7 files changed

+55
-21
lines changed

DevTools/HackStudio/Debugger/BacktraceModel.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,10 @@ Vector<BacktraceModel::FrameInfo> BacktraceModel::create_backtrace(const Debug::
5757
u32 current_instruction = regs.eip;
5858
Vector<BacktraceModel::FrameInfo> frames;
5959
do {
60-
String name = debug_session.debug_info().name_of_containing_function(current_instruction);
60+
auto lib = debug_session.library_at(regs.eip);
61+
if (!lib)
62+
continue;
63+
String name = lib->debug_info->name_of_containing_function(current_instruction - lib->base_address);
6164
if (name.is_null()) {
6265
dbgln("BacktraceModel: couldn't find containing function for address: {:p}", current_instruction);
6366
name = "<missing>";

DevTools/HackStudio/Debugger/Debugger.cpp

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,12 @@ Debugger& Debugger::the()
3838
}
3939

4040
void Debugger::initialize(
41+
String source_root,
4142
Function<HasControlPassedToUser(const PtraceRegisters&)> on_stop_callback,
4243
Function<void()> on_continue_callback,
4344
Function<void()> on_exit_callback)
4445
{
45-
s_the = new Debugger(move(on_stop_callback), move(on_continue_callback), move(on_exit_callback));
46+
s_the = new Debugger(source_root, move(on_stop_callback), move(on_continue_callback), move(on_exit_callback));
4647
}
4748

4849
bool Debugger::is_initialized()
@@ -51,10 +52,12 @@ bool Debugger::is_initialized()
5152
}
5253

5354
Debugger::Debugger(
55+
String source_root,
5456
Function<HasControlPassedToUser(const PtraceRegisters&)> on_stop_callback,
5557
Function<void()> on_continue_callback,
5658
Function<void()> on_exit_callback)
57-
: m_on_stopped_callback(move(on_stop_callback))
59+
: m_source_root(source_root)
60+
, m_on_stopped_callback(move(on_stop_callback))
5861
, m_on_continue_callback(move(on_continue_callback))
5962
, m_on_exit_callback(move(on_exit_callback))
6063
{
@@ -76,7 +79,7 @@ void Debugger::on_breakpoint_change(const String& file, size_t line, BreakpointC
7679
if (!session)
7780
return;
7881

79-
auto address = session->debug_info().get_instruction_from_source(position.file_path, position.line_number);
82+
auto address = session->get_address_from_source_position(position.file_path, position.line_number);
8083
if (!address.has_value()) {
8184
dbgln("Warning: couldn't get instruction address from source");
8285
// TODO: Currently, the GUI will indicate that a breakpoint was inserted/removed at this line,
@@ -86,10 +89,10 @@ void Debugger::on_breakpoint_change(const String& file, size_t line, BreakpointC
8689
}
8790

8891
if (change_type == BreakpointChange::Added) {
89-
bool success = session->insert_breakpoint(reinterpret_cast<void*>(address.value()));
92+
bool success = session->insert_breakpoint(reinterpret_cast<void*>(address.value().address));
9093
ASSERT(success);
9194
} else {
92-
bool success = session->remove_breakpoint(reinterpret_cast<void*>(address.value()));
95+
bool success = session->remove_breakpoint(reinterpret_cast<void*>(address.value().address));
9396
ASSERT(success);
9497
}
9598
}
@@ -109,14 +112,14 @@ int Debugger::start_static()
109112

110113
void Debugger::start()
111114
{
112-
m_debug_session = Debug::DebugSession::exec_and_attach(m_executable_path);
115+
m_debug_session = Debug::DebugSession::exec_and_attach(m_executable_path, m_source_root);
113116
ASSERT(!!m_debug_session);
114117

115118
for (const auto& breakpoint : m_breakpoints) {
116-
dbgln("insertig breakpoint at: {}:{}", breakpoint.file_path, breakpoint.line_number);
117-
auto address = m_debug_session->debug_info().get_instruction_from_source(breakpoint.file_path, breakpoint.line_number);
119+
dbgln("inserting breakpoint at: {}:{}", breakpoint.file_path, breakpoint.line_number);
120+
auto address = m_debug_session->get_address_from_source_position(breakpoint.file_path, breakpoint.line_number);
118121
if (address.has_value()) {
119-
bool success = m_debug_session->insert_breakpoint(reinterpret_cast<void*>(address.value()));
122+
bool success = m_debug_session->insert_breakpoint(reinterpret_cast<void*>(address.value().address));
120123
ASSERT(success);
121124
} else {
122125
dbgln("couldn't insert breakpoint");
@@ -130,7 +133,7 @@ int Debugger::debugger_loop()
130133
{
131134
ASSERT(m_debug_session);
132135

133-
m_debug_session->run([this](Debug::DebugSession::DebugBreakReason reason, Optional<PtraceRegisters> optional_regs) {
136+
m_debug_session->run(Debug::DebugSession::DesiredInitialDebugeeState::Running, [this](Debug::DebugSession::DebugBreakReason reason, Optional<PtraceRegisters> optional_regs) {
134137
if (reason == Debug::DebugSession::DebugBreakReason::Exited) {
135138
dbgln("Program exited");
136139
m_on_exit_callback();
@@ -140,9 +143,16 @@ int Debugger::debugger_loop()
140143
ASSERT(optional_regs.has_value());
141144
const PtraceRegisters& regs = optional_regs.value();
142145

143-
auto source_position = m_debug_session->debug_info().get_source_position(regs.eip);
146+
auto source_position = m_debug_session->get_source_position(regs.eip);
147+
if (!source_position.has_value())
148+
return Debug::DebugSession::DebugDecision::SingleStep;
149+
150+
// We currently do no support stepping through assembly source
151+
if (source_position.value().file_path.ends_with(".S"))
152+
return Debug::DebugSession::DebugDecision::SingleStep;
153+
154+
ASSERT(source_position.has_value());
144155
if (m_state.get() == Debugger::DebuggingState::SingleStepping) {
145-
ASSERT(source_position.has_value());
146156
if (m_state.should_stop_single_stepping(source_position.value())) {
147157
m_state.set_normal();
148158
} else {
@@ -241,11 +251,18 @@ void Debugger::do_step_over(const PtraceRegisters& regs)
241251
{
242252
// To step over, we insert a temporary breakpoint at each line in the current function,
243253
// as well as at the current function's return point, and continue execution.
244-
auto current_function = m_debug_session->debug_info().get_containing_function(regs.eip);
254+
auto lib = m_debug_session->library_at(regs.eip);
255+
if (!lib)
256+
return;
257+
auto current_function = lib->debug_info->get_containing_function(regs.eip - lib->base_address);
258+
if (!current_function.has_value()) {
259+
dbgln("cannot perform step_over, failed to find containing function of: {:p}", regs.eip);
260+
return;
261+
}
245262
ASSERT(current_function.has_value());
246-
auto lines_in_current_function = m_debug_session->debug_info().source_lines_in_scope(current_function.value());
263+
auto lines_in_current_function = lib->debug_info->source_lines_in_scope(current_function.value());
247264
for (const auto& line : lines_in_current_function) {
248-
insert_temporary_breakpoint(line.address_of_first_statement);
265+
insert_temporary_breakpoint(line.address_of_first_statement.value() + lib->base_address);
249266
}
250267
insert_temporary_breakpoint_at_return_address(regs);
251268
}

DevTools/HackStudio/Debugger/Debugger.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ class Debugger {
4545
};
4646

4747
static void initialize(
48+
String source_root,
4849
Function<HasControlPassedToUser(const PtraceRegisters&)> on_stop_callback,
4950
Function<void()> on_continue_callback,
5051
Function<void()> on_exit_callback);
@@ -102,6 +103,7 @@ class Debugger {
102103
};
103104

104105
explicit Debugger(
106+
String source_root,
105107
Function<HasControlPassedToUser(const PtraceRegisters&)> on_stop_callback,
106108
Function<void()> on_continue_callback,
107109
Function<void()> on_exit_callback);
@@ -118,6 +120,7 @@ class Debugger {
118120
void insert_temporary_breakpoint_at_return_address(const PtraceRegisters&);
119121

120122
OwnPtr<Debug::DebugSession> m_debug_session;
123+
String m_source_root;
121124
DebuggingState m_state;
122125

123126
pthread_mutex_t m_ui_action_mutex {};

DevTools/HackStudio/Debugger/DisassemblyModel.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,10 @@ namespace HackStudio {
3838

3939
DisassemblyModel::DisassemblyModel(const Debug::DebugSession& debug_session, const PtraceRegisters& regs)
4040
{
41-
auto containing_function = debug_session.debug_info().get_containing_function(regs.eip);
41+
auto lib = debug_session.library_at(regs.eip);
42+
if (!lib)
43+
return;
44+
auto containing_function = lib->debug_info->get_containing_function(regs.eip - lib->base_address);
4245
if (!containing_function.has_value()) {
4346
dbgln("Cannot disassemble as the containing function was not found.");
4447
return;
@@ -54,7 +57,7 @@ DisassemblyModel::DisassemblyModel(const Debug::DebugSession& debug_session, con
5457
kernel_elf = make<ELF::Image>((const u8*)kernel_file->data(), kernel_file->size());
5558
elf = kernel_elf.ptr();
5659
} else {
57-
elf = &debug_session.elf();
60+
elf = &lib->debug_info->elf();
5861
}
5962

6063
auto symbol = elf->find_symbol(containing_function.value().address_low);

DevTools/HackStudio/Debugger/DisassemblyWidget.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,10 @@ void DisassemblyWidget::update_state(const Debug::DebugSession& debug_session, c
6464
m_disassembly_view->set_model(DisassemblyModel::create(debug_session, regs));
6565

6666
if (m_disassembly_view->model()->row_count() > 0) {
67-
auto containing_function = debug_session.debug_info().get_containing_function(regs.eip);
67+
auto lib = debug_session.library_at(regs.eip);
68+
if (!lib)
69+
return;
70+
auto containing_function = lib->debug_info->get_containing_function(regs.eip - lib->base_address);
6871
if (containing_function.has_value())
6972
m_function_name_label->set_text(containing_function.value().name);
7073
else

DevTools/HackStudio/Debugger/VariablesModel.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,10 @@ void VariablesModel::update()
184184

185185
RefPtr<VariablesModel> VariablesModel::create(const PtraceRegisters& regs)
186186
{
187-
auto variables = Debugger::the().session()->debug_info().get_variables_in_current_scope(regs);
187+
auto lib = Debugger::the().session()->library_at(regs.eip);
188+
if (!lib)
189+
return nullptr;
190+
auto variables = lib->debug_info->get_variables_in_current_scope(regs);
188191
return adopt(*new VariablesModel(move(variables), regs));
189192
}
190193

DevTools/HackStudio/HackStudioWidget.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -522,14 +522,16 @@ NonnullRefPtr<GUI::Action> HackStudioWidget::create_debug_action()
522522
void HackStudioWidget::initialize_debugger()
523523
{
524524
Debugger::initialize(
525+
m_project->root_path(),
525526
[this](const PtraceRegisters& regs) {
526527
ASSERT(Debugger::the().session());
527528
const auto& debug_session = *Debugger::the().session();
528-
auto source_position = debug_session.debug_info().get_source_position(regs.eip);
529+
auto source_position = debug_session.get_source_position(regs.eip);
529530
if (!source_position.has_value()) {
530531
dbgln("Could not find source position for address: {:p}", regs.eip);
531532
return Debugger::HasControlPassedToUser::No;
532533
}
534+
dbgln("Debugger stopped at source position: {}:{}", source_position.value().file_path, source_position.value().line_number);
533535

534536
Core::EventLoop::main().post_event(
535537
*window(),

0 commit comments

Comments
 (0)