Skip to content

Commit 93e45a6

Browse files
authored
[Dexter] Adapt to upcoming lldb stepping behavior (llvm#108127)
lldb will change how it reports stop reasons around breakpoints in the near future. I landed an earlier version of this change and noticed debuginfo test failures on the CI bots due to the changes. I'm addressing the issues found by CI at llvm#105594 and will re-land once I've done all of them. Currently, when lldb stops at a breakpoint instruction -- but has not yet executed the instruction -- it will overwrite the thread's Stop Reason with "breakpoint-hit". This caused bugs when the original stop reason was important to the user - for instance, a watchpoint on an AArch64 system where we have to instruction-step past the watchpoint to find the new value. Normally we would instruction step, fetch the new value, then report the user that a watchpoint has been hit with the old and new values. But if the instruction after this access is a breakpoint site, we overwrite the "watchpoint hit" stop reason (and related actions) with "breakpoint hit". dexter sets breakpoints on all source lines, then steps line-to-line, hitting the breakpoints. But with this new behavior, we see two steps per source line: The first step gets us to the start of the next line, with a "step completed" stop reason. Then we step again and we execute the breakpoint instruction, stop with the pc the same, and report "breakpoint hit". Now we can step a second time and move past the breakpoint. I've changed the `step` method in LLDB.py to check if we step to a breakpoint site but have a "step completed" stop reason -- in which case we have this new breakpoint behavior, and we need to step a second time to actually hit the breakpoint like the debuginfo tests expect.
1 parent b690cae commit 93e45a6

File tree

1 file changed

+27
-0
lines changed
  • cross-project-tests/debuginfo-tests/dexter/dex/debugger/lldb

1 file changed

+27
-0
lines changed

Diff for: cross-project-tests/debuginfo-tests/dexter/dex/debugger/lldb/LLDB.py

+27
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,33 @@ def launch(self, cmdline):
206206

207207
def step(self):
208208
self._thread.StepInto()
209+
stop_reason = self._thread.GetStopReason()
210+
# If we (1) completed a step and (2) are sitting at a breakpoint,
211+
# but (3) the breakpoint is not reported as the stop reason, then
212+
# we'll need to step once more to hit the breakpoint.
213+
#
214+
# dexter sets breakpoints on every source line, then steps
215+
# each source line. Older lldb's would overwrite the stop
216+
# reason with "breakpoint hit" when we stopped at a breakpoint,
217+
# even if the breakpoint hadn't been exectued yet. One
218+
# step per source line, hitting a breakpoint each time.
219+
#
220+
# But a more accurate behavior is that the step completes
221+
# with step-completed stop reason, then when we step again,
222+
# we execute the breakpoint and stop (with the pc the same) and
223+
# a breakpoint-hit stop reason. So we need to step twice per line.
224+
if stop_reason == self._interface.eStopReasonPlanComplete:
225+
stepped_to_breakpoint = False
226+
pc = self._thread.GetFrameAtIndex(0).GetPC()
227+
for bp in self._target.breakpoints:
228+
for bploc in bp.locations:
229+
if (
230+
bploc.IsEnabled()
231+
and bploc.GetAddress().GetLoadAddress(self._target) == pc
232+
):
233+
stepped_to_breakpoint = True
234+
if stepped_to_breakpoint:
235+
self._thread.StepInto()
209236

210237
def go(self) -> ReturnCode:
211238
self._process.Continue()

0 commit comments

Comments
 (0)