================
@@ -188,54 +191,98 @@ llvm::Error SendThreadStoppedEvent(DAP &dap, bool 
on_entry) {
 
   llvm::DenseSet<lldb::tid_t> old_thread_ids;
   old_thread_ids.swap(dap.thread_ids);
-  uint32_t stop_id = on_entry ? 0 : process.GetStopID();
   const uint32_t num_threads = process.GetNumThreads();
 
-  // First make a pass through the threads to see if the focused thread
-  // has a stop reason. In case the focus thread doesn't have a stop
-  // reason, remember the first thread that has a stop reason so we can
-  // set it as the focus thread if below if needed.
-  lldb::tid_t first_tid_with_reason = LLDB_INVALID_THREAD_ID;
-  uint32_t num_threads_with_reason = 0;
-  bool focus_thread_exists = false;
+  lldb::tid_t stopped_thread_idx = 0;
   for (uint32_t thread_idx = 0; thread_idx < num_threads; ++thread_idx) {
     lldb::SBThread thread = process.GetThreadAtIndex(thread_idx);
-    const lldb::tid_t tid = thread.GetThreadID();
-    const bool has_reason = ThreadHasStopReason(thread);
-    // If the focus thread doesn't have a stop reason, clear the thread ID
-    if (tid == dap.focus_tid) {
-      focus_thread_exists = true;
-      if (!has_reason)
-        dap.focus_tid = LLDB_INVALID_THREAD_ID;
-    }
-    if (has_reason) {
-      ++num_threads_with_reason;
-      if (first_tid_with_reason == LLDB_INVALID_THREAD_ID)
-        first_tid_with_reason = tid;
-    }
+    dap.thread_ids.insert(thread.GetThreadID());
+
+    if (stopped_thread_idx || !ThreadHasStopReason(thread))
+      continue;
+
+    // Stop at the first thread with a stop reason.
+    stopped_thread_idx = thread_idx;
   }
 
-  // We will have cleared dap.focus_tid if the focus thread doesn't have
-  // a stop reason, so if it was cleared, or wasn't set, or doesn't exist,
-  // then set the focus thread to the first thread with a stop reason.
-  if (!focus_thread_exists || dap.focus_tid == LLDB_INVALID_THREAD_ID)
-    dap.focus_tid = first_tid_with_reason;
-
-  // If no threads stopped with a reason, then report the first one so
-  // we at least let the UI know we stopped.
-  if (num_threads_with_reason == 0) {
-    lldb::SBThread thread = process.GetThreadAtIndex(0);
-    dap.focus_tid = thread.GetThreadID();
-    dap.SendJSON(CreateThreadStopped(dap, thread, stop_id));
+  lldb::SBThread thread = process.GetThreadAtIndex(stopped_thread_idx);
+  assert(thread.IsValid() && "no valid thread found, process not stopped");
+
+  protocol::StoppedEventBody body;
+  if (on_entry) {
+    body.reason = protocol::eStopReasonEntry;
   } else {
-    for (uint32_t thread_idx = 0; thread_idx < num_threads; ++thread_idx) {
-      lldb::SBThread thread = process.GetThreadAtIndex(thread_idx);
-      dap.thread_ids.insert(thread.GetThreadID());
-      if (ThreadHasStopReason(thread)) {
-        dap.SendJSON(CreateThreadStopped(dap, thread, stop_id));
+    switch (thread.GetStopReason()) {
+    case lldb::eStopReasonTrace:
+    case lldb::eStopReasonPlanComplete:
+      body.reason = protocol::eStopReasonStep;
+      break;
+    case lldb::eStopReasonBreakpoint: {
+      ExceptionBreakpoint *exc_bp = dap.GetExceptionBPFromStopReason(thread);
+      if (exc_bp) {
+        body.reason = protocol::eStopReasonException;
+        body.text = exc_bp->GetLabel();
+      } else {
+        InstructionBreakpoint *inst_bp =
+            dap.GetInstructionBPFromStopReason(thread);
+        body.reason = inst_bp ? protocol::eStopReasonInstructionBreakpoint
+                              : protocol::eStopReasonBreakpoint;
+
+        llvm::raw_string_ostream OS(body.text);
+        OS << "breakpoint";
+        for (size_t idx = 0; idx < thread.GetStopReasonDataCount(); idx += 2) {
+          lldb::break_id_t bp_id = thread.GetStopReasonDataAtIndex(idx);
+          lldb::break_id_t bp_loc_id = thread.GetStopReasonDataAtIndex(idx + 
1);
+          body.hitBreakpointIds.push_back(bp_id);
+          OS << " " << bp_id << "." << bp_loc_id;
+        }
       }
+    } break;
+    case lldb::eStopReasonWatchpoint: {
+      body.reason = protocol::eStopReasonDataBreakpoint;
+      lldb::break_id_t bp_id = thread.GetStopReasonDataAtIndex(0);
+      body.hitBreakpointIds.push_back(bp_id);
+      body.text = llvm::formatv("data breakpoint {0}", bp_id).str();
+    } break;
+    case lldb::eStopReasonProcessorTrace:
+      body.reason = protocol::eStopReasonStep; // fallback reason
+      break;
+    case lldb::eStopReasonHistoryBoundary:
+      body.reason = protocol::eStopReasonStep; // fallback reason
+      break;
+    case lldb::eStopReasonSignal:
+    case lldb::eStopReasonException:
+    case lldb::eStopReasonInstrumentation:
+      body.reason = protocol::eStopReasonException;
+      break;
+    case lldb::eStopReasonExec:
+    case lldb::eStopReasonFork:
+    case lldb::eStopReasonVFork:
+    case lldb::eStopReasonVForkDone:
+      body.reason = protocol::eStopReasonEntry;
+      break;
+    case lldb::eStopReasonInterrupt:
+      body.reason = protocol::eStopReasonPause;
+      break;
+    case lldb::eStopReasonThreadExiting:
+    case lldb::eStopReasonInvalid:
+    case lldb::eStopReasonNone:
+      llvm_unreachable("invalid stop reason, thread is not stopped");
+      break;
     }
   }
+  lldb::tid_t tid = thread.GetThreadID();
+  lldb::SBStream description;
+  thread.GetStopDescription(description);
+  body.description = description.GetData();
+  body.threadId = tid;
+  body.preserveFocusHint = tid == dap.focus_tid;
+  body.allThreadsStopped = true;
+
+  // Update focused thread.
+  dap.focus_tid = tid;
+
+  dap.Send(protocol::Event{"stopped", std::move(body)});
----------------
DrSergei wrote:

Sending only one event is very similar to 
[PR](https://github.com/llvm/llvm-project/pull/176230).

https://github.com/llvm/llvm-project/pull/176273
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to