jasonmolenda wrote:
> // Mark the thread as stopped at breakpoint.
> thread.SetStoppedByBreakpoint();
> FixupBreakpointPCAsNeeded(thread);
>
> if (m_threads_stepping_with_breakpoint.find(thread.GetID()) !=
> m_threads_stepping_with_breakpoint.end())
> thread.SetStoppedByTrace();
>
> StopRunningThreads(thread.GetID());
> }
> ```
>
> I think this is the correct thing to do, since lldb is completely unaware of
> whether software single stepping is taking place(*) I got lost in all of the
> mach exceptions, so it's not clear to me what is the conclusion. Are you
> saying that debugserver does not do this (i.e., it reports the stop as a
> "breakpoint hit", in the mach exception form)?
Ah, very nice, thanks for finding this. I think this helps to show why this is
failing with the new "breakpoints are only 'hit' when they are actually
executed'" scheme.
If the pc is at a BreakpointSite and we're stopped in the debugger. We do
"si", a breakpoint is inserted on the next instruction (pc+4 or 2), this thread
and pc+4 is added to `m_threads_stepping_with_breakpoint`. We resume
execution. The breakpoint at pc is hit, and the pc value does not advance.
This method is only checking that the thread is included in the
`m_threads_stepping_with_breakpoint` map, not checking that the pc of the
breakpoint we hit is the one we inserted (at pc+4/2). I wonder if this can be
fixed by
```
NativeRegisterContextLinux ®_ctx = thread.GetRegisterContext();
if (m_threads_stepping_with_breakpoint.find(thread.GetID()) !=
m_threads_stepping_with_breakpoint.end() &&
m_threads_stepping_with_breakpoint.find(thread.GetID())->second ==
reg_ctx.GetPC())
```
This wasn't necessary with the previous behavior -- if we stopped at a
BreakpointSite, we would declare that we hit the breakpoint, even if we'd just
stepped up to the BreakpointSite. But now that you may have stepped up to a
BreakpointSite OR you may have executed & hit the breakpoint, we're trusting
the gdb-remote stub's response more.
I think @DavidSpickett was seeing some looping in the test case, and I could
imagine a scenario where the pc is at a BreakpointSite, lldb instruction steps,
and we get back an instruction-step stop reason without the pc advancing. We
haven't hit the breakpoint yet (as far as lldb knows), so we try again. And
again.
> Just as a curiosity the linux kernel does allow you do use the hardware
> single step capability if debugging a 32 bit application on a 64-bit kernel
> (I'm not sure if the debugger process needs to be 64-bit or not). At one
> point, I wanted to make use of that, which would make our stepping behavior
> more reliable in these situations. However it would also make it harder to
> reproduce situations like these, as one would have to find actual 32-bit
> hardware...
Yeah on an armv8 system that can run AArch32 or AArch64 code, both will have
MDSCR_EL1.SS instruction stepping capability. It's only on a genuine armv7
processor where that feature doesn't exist. I don't know how much lldb
distinguishes between AArch32 and armv7, but this is one important difference.
(lldb AArch64 cores don't support AArch32 any more, so I haven't worked with
this combination in years).
> (*) The code is probably too casual about this check though, in that it does
> not check whether it was the actual single-stepping breakpoint that got hit.
> If there was a breakpoint under the current PC, it would report this as
> "trace" even though it hasn't actually stepped anything. Could this maybe be
> the problem that you ran into with this patch?
Ah yes, exactly so, we reached the same conclusion, I didn't read your whole
response at first. :)
https://github.com/llvm/llvm-project/pull/96260
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits