[Lldb-commits] [lldb] [lldb][windows] add assert frame recognizer Windows (PR #224269)
via lldb-commits
lldb-commits at lists.llvm.org
Thu Sep 17 04:26:40 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-lldb
Author: Charles Zablit (charles-zablit)
<details>
<summary>Changes</summary>
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
---
This relands https://github.com/llvm/llvm-project/pull/197282, reverted in https://github.com/llvm/llvm-project/pull/198263 for two buildbot failures.
1. **lldb-x86_64-win** failed with `0xC0000005` in `frame recognizer list` (`commands/frame/recognizer/TestFrameRecognizer.py`, `test_frame_recognizer_target_specific`). This is due to a call to `strlen(nullptr)` which is fixed by https://github.com/llvm/llvm-project/pull/224267.
2. **lldb-remote-linux-win** started running `Recognizer`/`assert.test` and failed with `"stop reason = signal SIGABRT"` where the test expects `"hit program assert"`. That bot debugs a remote Linux target from a Windows host: system-linux is a host feature, so the known-broken Linux target (llvm.org/pr56144) was not skipped. Add remote-linux to the UNSUPPORTED list.
---
Full diff: https://github.com/llvm/llvm-project/pull/224269.diff
2 Files Affected:
- (modified) lldb/source/Target/AssertFrameRecognizer.cpp (+40-13)
- (modified) lldb/test/Shell/Recognizer/assert.test (+4-3)
``````````diff
diff --git a/lldb/source/Target/AssertFrameRecognizer.cpp b/lldb/source/Target/AssertFrameRecognizer.cpp
index 7455f86388e6b1..0768b5eab02c8a 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 201e834cf357ea..a8bb734e1bb024 100644
--- a/lldb/test/Shell/Recognizer/assert.test
+++ b/lldb/test/Shell/Recognizer/assert.test
@@ -2,9 +2,10 @@
# XFAIL: system-netbsd
#
# llvm.org/pr56144
-# UNSUPPORTED: system-linux
+# system-linux only covers a Linux host; remote-linux catches the bots which
+# debug a Linux target from another host.
+# UNSUPPORTED: system-linux, remote-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 +15,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
``````````
</details>
https://github.com/llvm/llvm-project/pull/224269
More information about the lldb-commits
mailing list