diff --git a/cross-project-tests/debuginfo-tests/dexter/dex/debugger/lldb/LLDB.py b/cross-project-tests/debuginfo-tests/dexter/dex/debugger/lldb/LLDB.py index 3944c1c4b009..2307550aca04 100644 --- a/cross-project-tests/debuginfo-tests/dexter/dex/debugger/lldb/LLDB.py +++ b/cross-project-tests/debuginfo-tests/dexter/dex/debugger/lldb/LLDB.py @@ -206,6 +206,33 @@ class LLDB(DebuggerBase): def step(self): self._thread.StepInto() + stop_reason = self._thread.GetStopReason() + # If we (1) completed a step and (2) are sitting at a breakpoint, + # but (3) the breakpoint is not reported as the stop reason, then + # we'll need to step once more to hit the breakpoint. + # + # dexter sets breakpoints on every source line, then steps + # each source line. Older lldb's would overwrite the stop + # reason with "breakpoint hit" when we stopped at a breakpoint, + # even if the breakpoint hadn't been exectued yet. One + # step per source line, hitting a breakpoint each time. + # + # But a more accurate behavior is that the step completes + # with step-completed stop reason, then when we step again, + # we execute the breakpoint and stop (with the pc the same) and + # a breakpoint-hit stop reason. So we need to step twice per line. + if stop_reason == self._interface.eStopReasonPlanComplete: + stepped_to_breakpoint = False + pc = self._thread.GetFrameAtIndex(0).GetPC() + for bp in self._target.breakpoints: + for bploc in bp.locations: + if ( + bploc.IsEnabled() + and bploc.GetAddress().GetLoadAddress(self._target) == pc + ): + stepped_to_breakpoint = True + if stepped_to_breakpoint: + self._thread.StepInto() def go(self) -> ReturnCode: self._process.Continue()