Skip to content

Commit 48a0fc1

Browse files
committed
Add pc check for instruction stepping by breakpoints
NativeProcessFreeBSD::MonitorSIGTRAP (MIPS) and NativeProcessLinux::MonitorBreakpoint (MIPS, armv7, RISCV, LoongArch) do instruction stepping by setting a breakpoint on the next instruction that will be executed, and resuming the thread. They check that there was one of these "instruction step" breakpoints set for this thread, and rewrite the stop reason from "breakpoint hit" to "trace". However, if a user is sitting at a BreakpointSite (break instruction), and does `stepi`, then a breakpoint instruction will be put on the next instruction, the thread resumes, and we stop at the same location having hit our *original* breakpoint, not the one inserted on the next instruction for stepping. The stop reason is rewritten to "trace" but the pc hasn't advanced. The stepping logic will try to instruction step again and it infinite loops. I changed NativeProcessLinux and NativeProcessFreeBSD to only rewrite the stop reason to "trace" when the pc is the breakpoint we added for the insn-step. I don't have any of the devices that use this behavior, but I did at least compile test NativeProcessLinux in an Ubuntu AArch64 VM (but my core doesn't support aarch32 so I can't test it).
1 parent 3408ce1 commit 48a0fc1

File tree

2 files changed

+9
-3
lines changed

2 files changed

+9
-3
lines changed

lldb/source/Plugins/Process/FreeBSD/NativeProcessFreeBSD.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -318,9 +318,12 @@ void NativeProcessFreeBSD::MonitorSIGTRAP(lldb::pid_t pid) {
318318
info.pl_siginfo.si_addr);
319319

320320
if (thread) {
321+
auto &regctx = static_cast<NativeRegisterContextFreeBSD &>(
322+
thread->GetRegisterContext());
321323
auto thread_info =
322324
m_threads_stepping_with_breakpoint.find(thread->GetID());
323-
if (thread_info != m_threads_stepping_with_breakpoint.end()) {
325+
if (thread_info != m_threads_stepping_with_breakpoint.end() &&
326+
threads_info->second == regctx.GetPC()) {
324327
thread->SetStoppedByTrace();
325328
Status brkpt_error = RemoveBreakpoint(thread_info->second);
326329
if (brkpt_error.Fail())

lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -829,8 +829,11 @@ void NativeProcessLinux::MonitorBreakpoint(NativeThreadLinux &thread) {
829829
thread.SetStoppedByBreakpoint();
830830
FixupBreakpointPCAsNeeded(thread);
831831

832-
if (m_threads_stepping_with_breakpoint.find(thread.GetID()) !=
833-
m_threads_stepping_with_breakpoint.end())
832+
NativeRegisterContextLinux &reg_ctx = thread.GetRegisterContext();
833+
auto stepping_with_bp_it =
834+
m_threads_stepping_with_breakpoint.find(thread.GetID());
835+
if (stepping_with_bp_it != m_threads_stepping_with_breakpoint.end() &&
836+
stepping_with_bp_it->second == reg_ctx.GetPC())
834837
thread.SetStoppedByTrace();
835838

836839
StopRunningThreads(thread.GetID());

0 commit comments

Comments
 (0)