Skip to content

[lldb] Inconsistent behaviour when stepping onto a breakpoint instruction #156650

@SLTozer

Description

@SLTozer

Reproducer steps:

int a(int) {return 2;}
int foo() {
  int x = a(1);
  return x;
}
int bar() {
  int x = 2;
  return x;
}
int main() {
  return foo() + bar();
}

Building this reproducer file with clang++ -O0 -g and setting breakpoints on all the lines in foo and bar (3, 4, 7, 8), we see the following behaviour: when we step on the first line in foo (line 3) and step over (n), we stop at line 4 with "stop reason = breakpoint 2.1 -2.1". When we continue (c) and arrive at the first line of bar (line 7), we step over again; this time, we stop at line 8 with "stop reason = step over", and when we continue again we stop at line 8 again with "stop reason = breakpoint 4.1". I've attached a bash log demonstrating this.

Firstly, this appears to be a regression; performing the same action with my system LLDB (version 18.1.8), in both cases I see just "stop reason = breakpoint 2.1" and "stop reason = breakpoint 4.1", with no negative breakpoints or step over visible (log also attached); though I haven't tested it, this likely started with the behaviour change in #105594, in which as far as I understand it the behaviour in bar is the intended outcome. Secondly, running with log enable lldb step, the divergence between the two results appears to start with ThreadPlanStepRange::SetNextBranchBreakpoint; in foo we see Setting breakpoint -2 (site 3) to run to address 0x555555555155, while in bar we see skipping invalid run_to_address; I've attached a full log-enabled session in case it's of any use.

As an aside, the rationale for the intended behaviour makes sense (LLDB does not want to "lose" stop reasons), but does create the need for workarounds in tooling, and feels slightly confusing in general use; is there any feasible way that when there are multiple reasons for stopping at an instruction, they can simply all be returned at once, rather than needing to use continue to advance across different stop reasons at the same instruction? The current behaviour does feel "odd", but it can certainly continue be worked around if there are fundamental limitations (and I'm grateful to @jasonmolenda for writing the current workaround for Dexter!).

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions