aboutsummaryrefslogtreecommitdiff
path: root/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
diff options
context:
space:
mode:
authorJason Molenda <jmolenda@apple.com>2024-07-19 18:42:17 -0700
committerJason Molenda <jmolenda@apple.com>2024-07-19 18:43:53 -0700
commit52c08d7ffd380f4abd819c20bec76252272f6337 (patch)
treec50d58e085dccc63165362d23809065b85984257 /lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
parenta3ebb669d1027700a2f12bd5e075ad3fde3d4f70 (diff)
downloadllvm-52c08d7ffd380f4abd819c20bec76252272f6337.zip
llvm-52c08d7ffd380f4abd819c20bec76252272f6337.tar.gz
llvm-52c08d7ffd380f4abd819c20bec76252272f6337.tar.bz2
Revert "[lldb] Change lldb's breakpoint handling behavior (#96260)"
This reverts commit 05f0e86cc895181b3d2210458c78938f83353002. The debuginfo dexter tests are failing, probably because the way stepping over breakpoints has changed with my patches. And there are two API tests fails on the ubuntu-arm (32-bit) bot. I'll need to investigate both of these, neither has an obvious failure reason.
Diffstat (limited to 'lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp')
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp93
1 files changed, 62 insertions, 31 deletions
diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index 9ab03c1..604c923 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -1598,8 +1598,29 @@ bool ProcessGDBRemote::CalculateThreadStopInfo(ThreadGDBRemote *thread) {
// that have stop reasons, and if there is no entry for a thread, then it
// has no stop reason.
thread->GetRegisterContext()->InvalidateIfNeeded(true);
- if (!GetThreadStopInfoFromJSON(thread, m_jstopinfo_sp))
+ if (!GetThreadStopInfoFromJSON(thread, m_jstopinfo_sp)) {
+ // If a thread is stopped at a breakpoint site, set that as the stop
+ // reason even if it hasn't executed the breakpoint instruction yet.
+ // We will silently step over the breakpoint when we resume execution
+ // and miss the fact that this thread hit the breakpoint.
+ const size_t num_thread_ids = m_thread_ids.size();
+ for (size_t i = 0; i < num_thread_ids; i++) {
+ if (m_thread_ids[i] == thread->GetID() && m_thread_pcs.size() > i) {
+ addr_t pc = m_thread_pcs[i];
+ lldb::BreakpointSiteSP bp_site_sp =
+ thread->GetProcess()->GetBreakpointSiteList().FindByAddress(pc);
+ if (bp_site_sp) {
+ if (bp_site_sp->ValidForThisThread(*thread)) {
+ thread->SetStopInfo(
+ StopInfo::CreateStopReasonWithBreakpointSiteID(
+ *thread, bp_site_sp->GetID()));
+ return true;
+ }
+ }
+ }
+ }
thread->SetStopInfo(StopInfoSP());
+ }
return true;
}
@@ -1708,12 +1729,6 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo(
if (ThreadSP memory_thread_sp = m_thread_list.GetBackingThread(thread_sp))
thread_sp = memory_thread_sp;
- addr_t pc = thread_sp->GetRegisterContext()->GetPC();
- BreakpointSiteSP bp_site_sp =
- thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress(pc);
- if (bp_site_sp && bp_site_sp->IsEnabled())
- thread_sp->SetThreadStoppedAtUnexecutedBP(pc);
-
if (exc_type != 0) {
const size_t exc_data_size = exc_data.size();
@@ -1730,10 +1745,26 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo(
// to no reason.
if (!reason.empty() && reason != "none") {
if (reason == "trace") {
- thread_sp->SetStopInfo(StopInfo::CreateStopReasonToTrace(*thread_sp));
+ addr_t pc = thread_sp->GetRegisterContext()->GetPC();
+ lldb::BreakpointSiteSP bp_site_sp =
+ thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress(
+ pc);
+
+ // If the current pc is a breakpoint site then the StopInfo should be
+ // set to Breakpoint Otherwise, it will be set to Trace.
+ if (bp_site_sp && bp_site_sp->ValidForThisThread(*thread_sp)) {
+ thread_sp->SetStopInfo(
+ StopInfo::CreateStopReasonWithBreakpointSiteID(
+ *thread_sp, bp_site_sp->GetID()));
+ } else
+ thread_sp->SetStopInfo(
+ StopInfo::CreateStopReasonToTrace(*thread_sp));
handled = true;
} else if (reason == "breakpoint") {
- thread_sp->SetThreadHitBreakpointSite();
+ addr_t pc = thread_sp->GetRegisterContext()->GetPC();
+ lldb::BreakpointSiteSP bp_site_sp =
+ thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress(
+ pc);
if (bp_site_sp) {
// If the breakpoint is for this thread, then we'll report the hit,
// but if it is for another thread, we can just report no reason.
@@ -1849,41 +1880,39 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo(
StopInfo::CreateStopReasonVForkDone(*thread_sp));
handled = true;
}
+ } else if (!signo) {
+ addr_t pc = thread_sp->GetRegisterContext()->GetPC();
+ lldb::BreakpointSiteSP bp_site_sp =
+ thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress(pc);
+
+ // If a thread is stopped at a breakpoint site, set that as the stop
+ // reason even if it hasn't executed the breakpoint instruction yet.
+ // We will silently step over the breakpoint when we resume execution
+ // and miss the fact that this thread hit the breakpoint.
+ if (bp_site_sp && bp_site_sp->ValidForThisThread(*thread_sp)) {
+ thread_sp->SetStopInfo(StopInfo::CreateStopReasonWithBreakpointSiteID(
+ *thread_sp, bp_site_sp->GetID()));
+ handled = true;
+ }
}
if (!handled && signo && !did_exec) {
if (signo == SIGTRAP) {
// Currently we are going to assume SIGTRAP means we are either
// hitting a breakpoint or hardware single stepping.
-
- // We can't disambiguate between stepping-to-a-breakpointsite and
- // hitting-a-breakpointsite.
- //
- // A user can instruction-step, and be stopped at a BreakpointSite.
- // Or a user can be sitting at a BreakpointSite,
- // instruction-step which hits the breakpoint and the pc does not
- // advance.
- //
- // In both cases, we're at a BreakpointSite when stopped, and
- // the resume state was eStateStepping.
-
- // Assume if we're at a BreakpointSite, we hit it.
handled = true;
addr_t pc =
thread_sp->GetRegisterContext()->GetPC() + m_breakpoint_pc_offset;
- BreakpointSiteSP bp_site_sp =
+ lldb::BreakpointSiteSP bp_site_sp =
thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress(
pc);
- // We can't know if we hit it or not. So if we are stopped at
- // a BreakpointSite, assume we hit it, and should step past the
- // breakpoint when we resume. This is contrary to how we handle
- // BreakpointSites in any other location, but we can't know for
- // sure what happened so it's a reasonable default.
if (bp_site_sp) {
- if (bp_site_sp->IsEnabled())
- thread_sp->SetThreadHitBreakpointSite();
-
+ // If the breakpoint is for this thread, then we'll report the hit,
+ // but if it is for another thread, we can just report no reason.
+ // We don't need to worry about stepping over the breakpoint here,
+ // that will be taken care of when the thread resumes and notices
+ // that there's a breakpoint under the pc.
if (bp_site_sp->ValidForThisThread(*thread_sp)) {
if (m_breakpoint_pc_offset != 0)
thread_sp->GetRegisterContext()->SetPC(pc);
@@ -1897,6 +1926,8 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo(
} else {
// If we were stepping then assume the stop was the result of the
// trace. If we were not stepping then report the SIGTRAP.
+ // FIXME: We are still missing the case where we single step over a
+ // trap instruction.
if (thread_sp->GetTemporaryResumeState() == eStateStepping)
thread_sp->SetStopInfo(
StopInfo::CreateStopReasonToTrace(*thread_sp));