[Lldb-commits] [lldb] [lldb-dap] Fix core file stop reason overriden to "entry" (PR #195352)

via lldb-commits lldb-commits at lists.llvm.org
Fri May 1 13:49:32 PDT 2026


https://github.com/kusmour created https://github.com/llvm/llvm-project/pull/195352

# Summary:
There's a behavior change on core file stop reason
It used to report the actual crash (stop) reason:
  - reason: "exception" (reflecting the actual crash signal/exception)
  - description:  crash signals, eg."signal SIGSEGV"

However, the stopped event now always reports:                                                                                
  - reason: "entry"
  - The crash reason is lost

## Root Cause
1. `bd0efcaa34b1` (Oct 31, 2025) — "[lldb-dap] Correctly trigger 'entry' stop reasons"

This commit changed CreateThreadStopped in `JSONUtils.cpp`:                                                            
Changed `body.try_emplace("reason", "entry")` to `body["reason"] = "entry"`, and this will overwrites it unconditionally.
                                                                                                                       
2. `51e5b6c6acc0` (Feb 3, 2026) — "Migrating 'stopped' event to structured types"
                                                                                                                       
Rewrote the stopped event with an if/else that completely skips the stop reason switch when on_entry=true:
```
if (on_entry) {
      body.reason = eStoppedReasonEntry;  // thread stop reason never inspected
  } else { ... }
```                                                        
                                                                                                                       
## The Underlying Design Issue                                                                                          
                                                                                                                       
`stop_at_entry` serves double duty in AttachRequestHandler.cpp:40-41:

```
if (!args.coreFile.empty())
      dap.stop_at_entry = true;
```

This flag both (a) `prevents process.Continue()` from being called (correct for core files) and (b) tells `SendThreadStoppedEvent` to use reason "entry" (wrong for core files — should report the actual crash reason).

# Test Plan:
Added DAP test to check for stop reasons
Launch a coredump debug session with local build lldb-dap and observe the stop reason
<img width="262" height="181" alt="image" src="https://github.com/user-attachments/assets/077dced9-2f0a-477a-825f-3b60483a69d3" />

>From 149a4c39c1f3bce93294c2a8db89fcbdb8008b31 Mon Sep 17 00:00:00 2001
From: Wanyi Ye <wanyi at meta.com>
Date: Fri, 1 May 2026 13:15:11 -0700
Subject: [PATCH] [lldb-dap] Fix stop reason entry override for core file

Summary:

Test Plan:

Reviewers:

Subscribers:

Tasks:

Tags:


Differential Revision: https://phabricator.intern.facebook.com/D103451900
---
 .../lldb-dap/coreFile/TestDAP_coreFile.py     | 31 +++++++++++++++++++
 lldb/tools/lldb-dap/DAP.h                     |  1 +
 .../lldb-dap/Handler/AttachRequestHandler.cpp |  4 ++-
 .../ConfigurationDoneRequestHandler.cpp       |  2 +-
 4 files changed, 36 insertions(+), 2 deletions(-)

diff --git a/lldb/test/API/tools/lldb-dap/coreFile/TestDAP_coreFile.py b/lldb/test/API/tools/lldb-dap/coreFile/TestDAP_coreFile.py
index 5a773503c3c63..c48ec020d6e05 100644
--- a/lldb/test/API/tools/lldb-dap/coreFile/TestDAP_coreFile.py
+++ b/lldb/test/API/tools/lldb-dap/coreFile/TestDAP_coreFile.py
@@ -76,6 +76,37 @@ def test_wrong_core_file(self):
         # attach may fail for mutilple reasons.
         self.assertEqual(error_msg, "Failed to create the process")
 
+    @skipIfLLVMTargetMissing("X86")
+    def test_core_file_stopped_reason(self):
+        """Test that the stopped event for a core file reports the actual crash
+        reason (e.g. 'exception') rather than 'entry'."""
+        current_dir = os.path.dirname(__file__)
+        exe_file = os.path.join(current_dir, "linux-x86_64.out")
+        core_file = os.path.join(current_dir, "linux-x86_64.core")
+
+        self.create_debug_adapter()
+        self.attach(program=exe_file, coreFile=core_file)
+        self.dap_server.request_configurationDone()
+        self.dap_server.wait_for_stopped()
+
+        # Core files should report the actual crash reason, not 'entry'.
+        stop_reasons = self.dap_server.thread_stop_reasons
+        self.assertGreater(len(stop_reasons), 0, "Expected at least one stopped thread")
+
+        # Find any thread with a stop reason — the crashing thread should
+        # report 'exception' with a description about the signal.
+        found_exception = False
+        for tid, body in stop_reasons.items():
+            if body.get("reason") == "exception":
+                found_exception = True
+                self.assertIn("description", body)
+                break
+        self.assertTrue(
+            found_exception,
+            f"Expected at least one thread with stop reason 'exception', "
+            f"got: {stop_reasons}",
+        )
+
     @skipIfLLVMTargetMissing("X86")
     def test_core_file_source_mapping_array(self):
         """Test that sourceMap property is correctly applied when loading a core"""
diff --git a/lldb/tools/lldb-dap/DAP.h b/lldb/tools/lldb-dap/DAP.h
index fc402b01376c4..09fcb23395e79 100644
--- a/lldb/tools/lldb-dap/DAP.h
+++ b/lldb/tools/lldb-dap/DAP.h
@@ -121,6 +121,7 @@ struct DAP final : public DAPTransport::MessageHandler {
   llvm::once_flag terminated_event_flag;
   bool stop_at_entry = false;
   bool is_attach = false;
+  bool is_core_file = false;
 
   /// The process event thread normally responds to process exited events by
   /// shutting down the entire adapter. When we're restarting, we keep the id of
diff --git a/lldb/tools/lldb-dap/Handler/AttachRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/AttachRequestHandler.cpp
index 9f708e7087e19..8569e033fb90a 100644
--- a/lldb/tools/lldb-dap/Handler/AttachRequestHandler.cpp
+++ b/lldb/tools/lldb-dap/Handler/AttachRequestHandler.cpp
@@ -38,8 +38,10 @@ Error AttachRequestHandler::Run(const AttachRequestArguments &args) const {
     return err;
 
   dap.SetConfiguration(args.configuration, /*is_attach=*/true);
-  if (!args.coreFile.empty())
+  if (!args.coreFile.empty()) {
     dap.stop_at_entry = true;
+    dap.is_core_file = true;
+  }
 
   PrintWelcomeMessage();
 
diff --git a/lldb/tools/lldb-dap/Handler/ConfigurationDoneRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/ConfigurationDoneRequestHandler.cpp
index 4b84a047cd148..4174679541fe4 100644
--- a/lldb/tools/lldb-dap/Handler/ConfigurationDoneRequestHandler.cpp
+++ b/lldb/tools/lldb-dap/Handler/ConfigurationDoneRequestHandler.cpp
@@ -62,7 +62,7 @@ ConfigurationDoneRequestHandler::Run(const ConfigurationDoneArguments &) const {
   SendProcessEvent(dap, dap.is_attach ? Attach : Launch);
 
   if (dap.stop_at_entry)
-    return SendThreadStoppedEvent(dap, /*on_entry=*/true);
+    return SendThreadStoppedEvent(dap, /*on_entry=*/!dap.is_core_file);
 
   return ToError(process.Continue());
 }



More information about the lldb-commits mailing list