[Lldb-commits] [lldb] 9144646 - [lldb][windows] add assert frame recognizer Windows (#197282)

via lldb-commits lldb-commits at lists.llvm.org
Fri May 15 01:59:33 PDT 2026


Author: Charles Zablit
Date: 2026-05-15T10:59:28+02:00
New Revision: 9144646bed5684833fd4c7874c5d1ad78f3f3fe0

URL: https://github.com/llvm/llvm-project/commit/9144646bed5684833fd4c7874c5d1ad78f3f3fe0
DIFF: https://github.com/llvm/llvm-project/commit/9144646bed5684833fd4c7874c5d1ad78f3f3fe0.diff

LOG: [lldb][windows] add assert frame recognizer Windows (#197282)

This patch implements `AssertFrameRecognizer` on Windows.

Since the Windows C Runtime can be either statically or dynamically
linked, lldb can't match the module name to be able to support both.
Therefore, the matches on `abort` and `_wassert` do not check the name
of the module.

The `assert.test` test was also relaxed to check the Windows error
format (`Exception 0xc0000409`), since Windows surfaces `__fastfail` as
a `STATUS_STACK_BUFFER_OVERRUN` exception rather than a POSIX signal.

rdar://175328961

Added: 
    

Modified: 
    lldb/source/Target/AssertFrameRecognizer.cpp
    lldb/test/Shell/Recognizer/assert.test

Removed: 
    


################################################################################
diff  --git a/lldb/source/Target/AssertFrameRecognizer.cpp b/lldb/source/Target/AssertFrameRecognizer.cpp
index 0ed02ba42dfc9..15a4f83995fac 100644
--- a/lldb/source/Target/AssertFrameRecognizer.cpp
+++ b/lldb/source/Target/AssertFrameRecognizer.cpp
@@ -16,15 +16,15 @@ using namespace lldb_private;
 namespace lldb_private {
 /// Fetches the abort frame location depending on the current platform.
 ///
-/// \param[in] os
-///    The target's os type.
+/// \param[in] triple
+///    The target's triple.
 /// \param[in,out] location
 ///    The struct that will contain the abort module spec and symbol names.
 /// \return
 ///    \b true, if the platform is supported
 ///    \b false, otherwise.
-bool GetAbortLocation(llvm::Triple::OSType os, SymbolLocation &location) {
-  switch (os) {
+bool GetAbortLocation(const llvm::Triple &triple, SymbolLocation &location) {
+  switch (triple.getOS()) {
   case llvm::Triple::Darwin:
   case llvm::Triple::MacOSX:
   case llvm::Triple::IOS:
@@ -44,6 +44,19 @@ bool GetAbortLocation(llvm::Triple::OSType os, SymbolLocation &location) {
     location.symbols.push_back(ConstString("pthread_kill"));
     location.symbols_are_regex = true;
     break;
+  case llvm::Triple::Win32:
+    if (!triple.isWindowsMSVCEnvironment()) {
+      Log *log = GetLog(LLDBLog::Unwind);
+      LLDB_LOG(log, "AssertFrameRecognizer::GetAbortLocation Unsupported "
+                    "Windows environment");
+      return false;
+    }
+    // Windows MSVC CRT can be statically or dynamically linked. With dynamic
+    // linking, abort lives in ucrtbase.dll. With static linking it's embedded
+    // in the executable.
+    // Match on the symbol only to handle both.
+    location.symbols.push_back(ConstString("abort"));
+    break;
   default:
     Log *log = GetLog(LLDBLog::Unwind);
     LLDB_LOG(log, "AssertFrameRecognizer::GetAbortLocation Unsupported OS");
@@ -55,15 +68,15 @@ bool GetAbortLocation(llvm::Triple::OSType os, SymbolLocation &location) {
 
 /// Fetches the assert frame location depending on the current platform.
 ///
-/// \param[in] os
-///    The target's os type.
+/// \param[in] triple
+///    The target's triple.
 /// \param[in,out] location
 ///    The struct that will contain the assert module spec and symbol names.
 /// \return
 ///    \b true, if the platform is supported
 ///    \b false, otherwise.
-bool GetAssertLocation(llvm::Triple::OSType os, SymbolLocation &location) {
-  switch (os) {
+bool GetAssertLocation(const llvm::Triple &triple, SymbolLocation &location) {
+  switch (triple.getOS()) {
   case llvm::Triple::Darwin:
   case llvm::Triple::MacOSX:
   case llvm::Triple::IOS:
@@ -80,6 +93,16 @@ bool GetAssertLocation(llvm::Triple::OSType os, SymbolLocation &location) {
     location.symbols.push_back(ConstString("__assert_fail"));
     location.symbols.push_back(ConstString("__GI___assert_fail"));
     break;
+  case llvm::Triple::Win32:
+    if (!triple.isWindowsMSVCEnvironment()) {
+      Log *log = GetLog(LLDBLog::Unwind);
+      LLDB_LOG(log, "AssertFrameRecognizer::GetAssertLocation Unsupported "
+                    "Windows environment");
+      return false;
+    }
+    // See comment in GetAbortLocation for why we skip the module check.
+    location.symbols.push_back(ConstString("_wassert"));
+    break;
   default:
     Log *log = GetLog(LLDBLog::Unwind);
     LLDB_LOG(log, "AssertFrameRecognizer::GetAssertLocation Unsupported OS");
@@ -91,10 +114,10 @@ bool GetAssertLocation(llvm::Triple::OSType os, SymbolLocation &location) {
 
 void RegisterAssertFrameRecognizer(Process *process) {
   Target &target = process->GetTarget();
-  llvm::Triple::OSType os = target.GetArchitecture().GetTriple().getOS();
+  const llvm::Triple &triple = target.GetArchitecture().GetTriple();
   SymbolLocation location;
 
-  if (!GetAbortLocation(os, location))
+  if (!GetAbortLocation(triple, location))
     return;
 
   if (!location.symbols_are_regex) {
@@ -136,10 +159,10 @@ AssertFrameRecognizer::RecognizeFrame(lldb::StackFrameSP frame_sp) {
   ThreadSP thread_sp = frame_sp->GetThread();
   ProcessSP process_sp = thread_sp->GetProcess();
   Target &target = process_sp->GetTarget();
-  llvm::Triple::OSType os = target.GetArchitecture().GetTriple().getOS();
+  const llvm::Triple &triple = target.GetArchitecture().GetTriple();
   SymbolLocation location;
 
-  if (!GetAssertLocation(os, location))
+  if (!GetAssertLocation(triple, location))
     return RecognizedStackFrameSP();
 
   const uint32_t frames_to_fetch = 6;
@@ -160,7 +183,11 @@ AssertFrameRecognizer::RecognizeFrame(lldb::StackFrameSP frame_sp) {
     SymbolContext sym_ctx =
         prev_frame_sp->GetSymbolContext(eSymbolContextEverything);
 
-    if (!sym_ctx.module_sp ||
+    if (!sym_ctx.module_sp)
+      continue;
+    // On Windows the abort/assert symbols may live in the executable (static
+    // CRT) or a CRT DLL, so skip the module check there.
+    if (!triple.isOSWindows() &&
         !sym_ctx.module_sp->GetFileSpec().FileEquals(location.module_spec))
       continue;
 

diff  --git a/lldb/test/Shell/Recognizer/assert.test b/lldb/test/Shell/Recognizer/assert.test
index 201e834cf357e..31f5a746482dc 100644
--- a/lldb/test/Shell/Recognizer/assert.test
+++ b/lldb/test/Shell/Recognizer/assert.test
@@ -4,7 +4,6 @@
 # llvm.org/pr56144
 # UNSUPPORTED: system-linux
 #
-# UNSUPPORTED: system-windows
 # RUN: %clang_host -g -O0 %S/Inputs/assert.c -o %t.out
 # RUN: %lldb -b -s %s %t.out | FileCheck %s
 run
@@ -14,5 +13,5 @@ frame recognizer info 0
 # CHECK: frame 0 is recognized by Assert StackFrame Recognizer
 set set thread-format "{${thread.stop-reason-raw}}\n"
 thread info
-# CHECK: signal SIGABRT
+# CHECK: {{(signal SIGABRT|Exception 0x[0-9a-fA-F]+)}}
 q


        


More information about the lldb-commits mailing list