Skip to content

Conversation

@felipepiovezan
Copy link
Contributor

  • One of the overloads of CreateStopReasonWithBreakpointSiteID was missing a call to SetThreadHitBreakpointSite.
  • ThreadMemory was missing a "DetectThreadStoppedAtUnexecutedBP" in its CalculateStopInfo.
  • When OS plugins are involved, they will sometimes calculate the stop info for the backing thread, and then "grab" it from them (see for example ThreadMemory::CalculateStopInfo. So the stop info is created on the backing thread (e.g. a GDBRemoteThread), and then we call SetStopInfo on the OS plugin thread. As a result, we never call `SetThreadHitBreakpointSite" for MemoryThreads, as this is done at the StopInfo creation. To address this, we add a check in SetStopInfo.)

…oppedAtUnexecutedBP

* One of the overloads of CreateStopReasonWithBreakpointSiteID was
  missing a call to SetThreadHitBreakpointSite.
* ThreadMemory was missing a "DetectThreadStoppedAtUnexecutedBP" in its
  CalculateStopInfo.
* When OS plugins are involved, they will sometimes calculate the stop
  info for the backing thread, and then "grab" it from them (see for
  example `ThreadMemory::CalculateStopInfo`. So the stop info is created
  on the backing thread (e.g. a GDBRemoteThread), and then we call
  SetStopInfo on the OS plugin thread. As a result, we never call
  `SetThreadHitBreakpointSite" for MemoryThreads, as this is done at the
  StopInfo creation. To address this, we add a check in SetStopInfo.
@llvmbot
Copy link
Member

llvmbot commented Feb 25, 2025

@llvm/pr-subscribers-lldb

Author: Felipe de Azevedo Piovezan (felipepiovezan)

Changes
  • One of the overloads of CreateStopReasonWithBreakpointSiteID was missing a call to SetThreadHitBreakpointSite.
  • ThreadMemory was missing a "DetectThreadStoppedAtUnexecutedBP" in its CalculateStopInfo.
  • When OS plugins are involved, they will sometimes calculate the stop info for the backing thread, and then "grab" it from them (see for example ThreadMemory::CalculateStopInfo. So the stop info is created on the backing thread (e.g. a GDBRemoteThread), and then we call SetStopInfo on the OS plugin thread. As a result, we never call `SetThreadHitBreakpointSite" for MemoryThreads, as this is done at the StopInfo creation. To address this, we add a check in SetStopInfo.)

Full diff: https://github.com/llvm/llvm-project/pull/128726.diff

3 Files Affected:

  • (modified) lldb/source/Plugins/Process/Utility/ThreadMemory.cpp (+1)
  • (modified) lldb/source/Target/StopInfo.cpp (+2)
  • (modified) lldb/source/Target/Thread.cpp (+4)
diff --git a/lldb/source/Plugins/Process/Utility/ThreadMemory.cpp b/lldb/source/Plugins/Process/Utility/ThreadMemory.cpp
index 550b53688fd39..9643d721b8501 100644
--- a/lldb/source/Plugins/Process/Utility/ThreadMemory.cpp
+++ b/lldb/source/Plugins/Process/Utility/ThreadMemory.cpp
@@ -66,6 +66,7 @@ ThreadMemory::CreateRegisterContextForFrame(StackFrame *frame) {
 }
 
 bool ThreadMemory::CalculateStopInfo() {
+  DetectThreadStoppedAtUnexecutedBP();
   if (m_backing_thread_sp) {
     lldb::StopInfoSP backing_stop_info_sp(
         m_backing_thread_sp->GetPrivateStopInfo());
diff --git a/lldb/source/Target/StopInfo.cpp b/lldb/source/Target/StopInfo.cpp
index 1c9ecbfe70c3c..1999216f8d2e9 100644
--- a/lldb/source/Target/StopInfo.cpp
+++ b/lldb/source/Target/StopInfo.cpp
@@ -1451,6 +1451,8 @@ StopInfoSP StopInfo::CreateStopReasonWithBreakpointSiteID(Thread &thread,
 StopInfoSP StopInfo::CreateStopReasonWithBreakpointSiteID(Thread &thread,
                                                           break_id_t break_id,
                                                           bool should_stop) {
+  thread.SetThreadHitBreakpointSite();
+
   return StopInfoSP(new StopInfoBreakpoint(thread, break_id, should_stop));
 }
 
diff --git a/lldb/source/Target/Thread.cpp b/lldb/source/Target/Thread.cpp
index 50f7c73f2c4c1..71ea76ebfa0dc 100644
--- a/lldb/source/Target/Thread.cpp
+++ b/lldb/source/Target/Thread.cpp
@@ -462,6 +462,10 @@ void Thread::ResetStopInfo() {
 }
 
 void Thread::SetStopInfo(const lldb::StopInfoSP &stop_info_sp) {
+  if (stop_info_sp &&
+      stop_info_sp->GetStopReason() == lldb::eStopReasonBreakpoint)
+    SetThreadHitBreakpointSite();
+
   m_stop_info_sp = stop_info_sp;
   if (m_stop_info_sp) {
     m_stop_info_sp->MakeStopInfoValid();

Copy link
Collaborator

@jasonmolenda jasonmolenda left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

Comment on lines +465 to +467
if (stop_info_sp &&
stop_info_sp->GetStopReason() == lldb::eStopReasonBreakpoint)
SetThreadHitBreakpointSite();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like you could move this after the m_stop_info_sp check a few lines below.

@jasonmolenda
Copy link
Collaborator

Felipe and I have been discussing these mechanisms all this week, and one edge case would be a thread that hits a breakpoint instruction, and the bp has a thread ID match requirement which this thread doesn't satisfy. In that scenario, the thread will not have an eStopReasonBreakpoint, but we still need to SetThreadHitBreakpointSite() here. That information -- we hit a breakpoint but it's not applicable to this thread -- isn't explicitly recorded in the Thread object today.

@jasonmolenda
Copy link
Collaborator

I'm not sure if this edge case can come up with this MemoryThread use cases.

@felipepiovezan
Copy link
Contributor Author

Yup, as Jason said, we have been thinking about this and we believe there may be a better way of doing this! I'm going to close this PR for now

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants