[Lldb-commits] [lldb] [lldb] Fix empty backtraces for scripted threads with no artificial frames (PR #193387)
via lldb-commits
lldb-commits at lists.llvm.org
Tue Apr 21 18:46:19 PDT 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-lldb
Author: Med Ismail Bennani (medismailben)
<details>
<summary>Changes</summary>
Following 86aa43999bec, `ScriptedThread::LoadArtificialStackFrames` unconditionally calls `SetAllFramesFetched` even when the scripted thread provided zero artificial stack frames via `get_stackframes`.
This prevents the normal unwinder from creating frames from the register context, leaving `m_frames` empty. When GetFrameAtIndex(0) is subsequently called, it triggered the follow on assertion builds:
```
assert(!m_thread.IsValid() && "A valid thread has no frames.")
```
This affects scripted threads that provide register context via `get_register_context` but rely on the unwinder for frame creation rather than overriding `get_stackframes`.
This patch fixes the issue in two parts:
- Only call `SetAllFramesFetched` when artificial frames were actually added, so the normal unwinder can still create frames from the register context when none were provided.
- Replace the assertion with a log message, since a debugger should not crash due to unexpected scripted thread state.
rdar://175019759
---
Full diff: https://github.com/llvm/llvm-project/pull/193387.diff
2 Files Affected:
- (modified) lldb/source/Plugins/Process/scripted/ScriptedThread.cpp (+7-4)
- (modified) lldb/source/Target/StackFrameList.cpp (+6-3)
``````````diff
diff --git a/lldb/source/Plugins/Process/scripted/ScriptedThread.cpp b/lldb/source/Plugins/Process/scripted/ScriptedThread.cpp
index eafd4b90ce296..a576df6221514 100644
--- a/lldb/source/Plugins/Process/scripted/ScriptedThread.cpp
+++ b/lldb/source/Plugins/Process/scripted/ScriptedThread.cpp
@@ -286,10 +286,13 @@ bool ScriptedThread::LoadArtificialStackFrames() {
synth_frame_sp, /*cfa=*/LLDB_INVALID_ADDRESS);
}
- // Mark the stack as fully unwound so the regular unwinder doesn't try to
- // extend it beyond the artificial frames (e.g. by reading lr/fp from the
- // register context).
- frames->SetAllFramesFetched();
+ // If artificial frames were provided, mark the stack as fully unwound so the
+ // regular unwinder doesn't try to extend it beyond the artificial frames
+ // (e.g. by reading lr/fp from the register context). If no artificial frames
+ // were provided, let the regular unwinder create frames from the register
+ // context.
+ if (frame_list_idx > 0)
+ frames->SetAllFramesFetched();
return true;
}
diff --git a/lldb/source/Target/StackFrameList.cpp b/lldb/source/Target/StackFrameList.cpp
index 5423785c2fd51..889cbf77b5c54 100644
--- a/lldb/source/Target/StackFrameList.cpp
+++ b/lldb/source/Target/StackFrameList.cpp
@@ -728,9 +728,12 @@ StackFrameSP StackFrameList::GetFrameAtIndex(uint32_t idx) {
// we thought taking that into account, then reset the current inlined
// depth and return the real zeroth frame.
if (m_frames.empty()) {
- // Why do we have a thread with zero frames, that should not ever
- // happen...
- assert(!m_thread.IsValid() && "A valid thread has no frames.");
+ // This can happen with scripted threads that provide register
+ // context but no stack frames. Log it instead of crashing.
+ if (m_thread.IsValid()) {
+ LLDB_LOG(GetLog(LLDBLog::Thread), "valid thread {0} has no frames",
+ m_thread.GetID());
+ }
} else {
ResetCurrentInlinedDepth();
frame_sp = m_frames[original_idx];
``````````
</details>
https://github.com/llvm/llvm-project/pull/193387
More information about the lldb-commits
mailing list