[Lldb-commits] [lldb] [lldb] Change lldb's breakpoint handling behavior (PR #96260)

Jason Molenda via lldb-commits lldb-commits at lists.llvm.org
Fri Aug 2 23:10:01 PDT 2024


jasonmolenda wrote:

I had to work on some other things the past couple of weeks but got back to this for a bit this afternoon.   Wanted to add a quick update of where things are.

There were five debuginfo dexter tests that failed on ubuntu and dwarf5.  I can reproduce these (or at least four of them), it took me a little while to figure out how to run these tests and get more detailed output of what dexter was outputting.  I don't have a fix yet, but it does look like the change in how breakpoints are seen as hit is the cause.  These tests are written to work with multiple debuggers so it may require a little care to fix, I'll start on debugging them soon.

I thought about the arm-ubuntu failures.  I remember that armv7 doesn't have an instruction step feature, it uses a hardware breakpoint in the form of "stop when $pc is not equal to current-instruction-address".  These failures make a lot of sense when I think of that, and I don't know how I'll fix this yet.  When we see a thread stopped at a BreakpointSite, we have three possibilities:

1.  The thread stopped here with no stop reason, it just happens to be sitting at a BreakpointSite and has not triggered it yet.  (another thread stopped for a Reason, and this thread just happens to be here)

2. The thread hit the breakpoint, the stop reason from the gdb stub will be "breakpoint-hit". thread.GetTemporaryResumeState() == eStateStepping means we were already at the BreakpointSite before, and the user did an instruction step, triggered the breakpoint and the pc has not advanced.  thread.GetTemporaryResumeState() != eStateStepping means that we were running freely and hit the breakpoint.

3. We are at a BreakpointSite with an instruction-step reason, and thread.GetTemporaryResumeState() == eStateStepping which means the thread had been instruction stepping.  We have not hit the breakpoint yet.

You can already see the problem when we cannot distinguish between "process has halted because it finished instruction step" and "process has halted because it hit a breakpoint".  In this environment, we have

1.  The thread stopped here with no stop reason, it just happens to be sitting at a BreakpointSite and has not triggered it yet.  (another thread stopped for a Reason, and this thread just happens to be here)

2. We are at a BreakpointSite, and we have a "breakpoint hit" stop reason.  If thread.GetTemporaryResumeState() == eStateStepping, we EITHER have just finished an instruction step from the previous instruction and are now sitting at a BreakpointSite, OR we were previous at this same PC, instruction stepped and hit the breakpoint, pc has not advanced.  Both are reported as "breakpoint hit" on armv7, because of how instruction step is accomplished.  I don't see how we can distinguish between these two states, and this presents a big problem for my whole change of only making the stop reason "breakpoint-hit" when we've actually executed the breakpoint. 

I don't know what I'm going to do here, and besides armv7 this same problem will occur for a target that has no instruction-step primitive.  Another common trick is to have enough instruction emulation that you can tell what instruction will execute next by decoding the current instruction, and putting a breakpoint there.  That has the same effect as armv7's instruction-step-by-breakpoints -- the reported stop reason from the stub will be "breakpoint hit".

I haven't looked at the x86_64 windows/mingw failure reported by Martin yet.

https://github.com/llvm/llvm-project/pull/96260


More information about the lldb-commits mailing list