diff options
Diffstat (limited to 'Libraries')
-rw-r--r-- | Libraries/LibDebug/DebugInfo.cpp | 31 | ||||
-rw-r--r-- | Libraries/LibDebug/DebugInfo.h | 6 | ||||
-rw-r--r-- | Libraries/LibDebug/DebugSession.cpp | 2 | ||||
-rw-r--r-- | Libraries/LibDebug/DebugSession.h | 9 |
4 files changed, 44 insertions, 4 deletions
diff --git a/Libraries/LibDebug/DebugInfo.cpp b/Libraries/LibDebug/DebugInfo.cpp index cd46ab1c47..f8b13d25b5 100644 --- a/Libraries/LibDebug/DebugInfo.cpp +++ b/Libraries/LibDebug/DebugInfo.cpp @@ -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 {}; @@ -301,10 +301,37 @@ 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 }; +} diff --git a/Libraries/LibDebug/DebugInfo.h b/Libraries/LibDebug/DebugInfo.h index de9de2ddff..9208dea102 100644 --- a/Libraries/LibDebug/DebugInfo.h +++ b/Libraries/LibDebug/DebugInfo.h @@ -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(); diff --git a/Libraries/LibDebug/DebugSession.cpp b/Libraries/LibDebug/DebugSession.cpp index 242108761a..2c6394de1e 100644 --- a/Libraries/LibDebug/DebugSession.cpp +++ b/Libraries/LibDebug/DebugSession.cpp @@ -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; diff --git a/Libraries/LibDebug/DebugSession.h b/Libraries/LibDebug/DebugSession.h index 84a87922c2..e11f93c944 100644 --- a/Libraries/LibDebug/DebugSession.h +++ b/Libraries/LibDebug/DebugSession.h @@ -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; |