1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-26 04:47:34 +00:00

HackStudio: Implement "Step Over" debugging action

The "Step Over" action continues execution without stepping into
instructions in subsequent function calls.
This commit is contained in:
Itamar 2020-08-21 16:48:42 +03:00 committed by Andreas Kling
parent 99788e6b32
commit 5c494eefd6
7 changed files with 75 additions and 13 deletions

View file

@ -138,7 +138,7 @@ Optional<DebugInfo::SourcePosition> DebugInfo::get_source_position(u32 target_ad
// TODO: We can do a binray search here
for (size_t i = 0; i < m_sorted_lines.size() - 1; ++i) {
if (m_sorted_lines[i + 1].address > target_address) {
return Optional<SourcePosition>({ m_sorted_lines[i].file, m_sorted_lines[i].line, m_sorted_lines[i].address });
return SourcePosition::from_line_info(m_sorted_lines[i]);
}
}
return {};
@ -300,11 +300,38 @@ OwnPtr<DebugInfo::VariableInfo> DebugInfo::create_variable_info(const Dwarf::DIE
}
String DebugInfo::name_of_containing_function(u32 address) const
{
auto function = get_containing_function(address);
if (!function.has_value())
return {};
return function.value().name;
}
Optional<DebugInfo::VariablesScope> DebugInfo::get_containing_function(u32 address) const
{
for (const auto& scope : m_scopes) {
if (!scope.is_function || address < scope.address_low || address >= scope.address_high)
continue;
return scope.name;
return scope;
}
return {};
}
Vector<DebugInfo::SourcePosition> DebugInfo::source_lines_in_scope(const VariablesScope& scope) const
{
Vector<DebugInfo::SourcePosition> source_lines;
for (const auto& line : m_sorted_lines) {
if (line.address < scope.address_low)
continue;
if (line.address >= scope.address_high)
break;
source_lines.append(SourcePosition::from_line_info(line));
}
return source_lines;
}
DebugInfo::SourcePosition DebugInfo::SourcePosition::from_line_info(const LineProgram::LineInfo& line)
{
return { line.file, line.line, line.address };
}

View file

@ -47,6 +47,8 @@ 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 !(*this == other); }
static SourcePosition from_line_info(const LineProgram::LineInfo&);
};
struct VariableInfo {
@ -80,7 +82,7 @@ public:
bool is_function { false };
String name;
u32 address_low { 0 };
u32 address_high { 0 };
u32 address_high { 0 }; // Non-inclusive - the lowest address after address_low that's not in this scope
Vector<Dwarf::DIE> dies_of_variables;
};
@ -104,6 +106,8 @@ public:
}
String name_of_containing_function(u32 address) const;
Vector<SourcePosition> source_lines_in_scope(const VariablesScope&) const;
Optional<VariablesScope> get_containing_function(u32 address) const;
private:
void prepare_variable_scopes();

View file

@ -175,6 +175,8 @@ bool DebugSession::enable_breakpoint(void* address)
auto breakpoint = m_breakpoints.get(address);
ASSERT(breakpoint.has_value());
ASSERT(breakpoint.value().state == BreakPointState::Disabled);
if (!poke(reinterpret_cast<u32*>(breakpoint.value().address), (breakpoint.value().original_first_word & ~(uint32_t)0xff) | BREAKPOINT_INSTRUCTION))
return false;

View file

@ -207,10 +207,17 @@ void DebugSession::run(Callback callback)
// Re-enable the breakpoint if it wasn't removed by the user
if (current_breakpoint.has_value() && m_breakpoints.contains(current_breakpoint.value().address)) {
// The current breakpoint was removed in order to make it transparrent to the user.
// The current breakpoint was removed to make it transparrent to the user.
// We now want to re-enable it - the code execution flow could hit it again.
// To re-enable the breakpoint, we first perform a single step and execute the
// instruction of the breakpoint, and then redo the INT3 patch in its first byte.
// If the user manually inserted a breakpoint at were we breaked at originally,
// we need to disable that breakpoint because we want to singlestep over it to execute the
// instruction we breaked on (we re-enable it again later anyways).
if (m_breakpoints.contains(current_breakpoint.value().address) && m_breakpoints.get(current_breakpoint.value().address).value().state == BreakPointState::Enabled) {
disable_breakpoint(current_breakpoint.value().address);
}
auto stopped_address = single_step();
enable_breakpoint(current_breakpoint.value().address);
did_single_step = true;