[Lldb-commits] [lldb] [lldb] add a marker before hidden frames (PR #167550)
Charles Zablit via lldb-commits
lldb-commits at lists.llvm.org
Fri Jan 16 07:30:15 PST 2026
https://github.com/charles-zablit updated https://github.com/llvm/llvm-project/pull/167550
>From 52eb5a9396fb2c667fd070b4cb4e914022005d6d Mon Sep 17 00:00:00 2001
From: Charles Zablit <c_zablit at apple.com>
Date: Wed, 10 Dec 2025 15:37:03 +0000
Subject: [PATCH 1/7] [lldb] add a marker before skipped frames
---
lldb/include/lldb/Target/StackFrame.h | 4 +-
lldb/include/lldb/Target/StackFrameList.h | 13 +++++-
lldb/source/Target/StackFrame.cpp | 5 +-
lldb/source/Target/StackFrameList.cpp | 57 ++++++++++++++++-------
lldb/source/Target/Thread.cpp | 6 +--
5 files changed, 61 insertions(+), 24 deletions(-)
diff --git a/lldb/include/lldb/Target/StackFrame.h b/lldb/include/lldb/Target/StackFrame.h
index 46922448d6e59..0d07515bf0f13 100644
--- a/lldb/include/lldb/Target/StackFrame.h
+++ b/lldb/include/lldb/Target/StackFrame.h
@@ -363,7 +363,7 @@ class StackFrame : public ExecutionContextScope,
/// \param [in] frame_marker
/// Optional string that will be prepended to the frame output description.
virtual void DumpUsingSettingsFormat(Stream *strm, bool show_unique = false,
- const char *frame_marker = nullptr);
+ const llvm::StringRef frame_marker = "");
/// Print a description for this frame using a default format.
///
@@ -400,7 +400,7 @@ class StackFrame : public ExecutionContextScope,
/// Returns true if successful.
virtual bool GetStatus(Stream &strm, bool show_frame_info, bool show_source,
bool show_unique = false,
- const char *frame_marker = nullptr);
+ const llvm::StringRef frame_marker = "");
/// Query whether this frame is a concrete frame on the call stack, or if it
/// is an inlined frame derived from the debug information and presented by
diff --git a/lldb/include/lldb/Target/StackFrameList.h b/lldb/include/lldb/Target/StackFrameList.h
index 539c070ff0f4b..c5b74522be0bb 100644
--- a/lldb/include/lldb/Target/StackFrameList.h
+++ b/lldb/include/lldb/Target/StackFrameList.h
@@ -49,6 +49,17 @@ class StackFrameList : public std::enable_shared_from_this<StackFrameList> {
/// Resets the selected frame index of this object.
void ClearSelectedFrameIndex();
+ /// Returns \code true if the next frame is hidden.
+ bool IsNextFrameHidden(lldb_private::StackFrame &frame);
+
+ /// Returns \code true if the previous frame is hidden.
+ bool IsPreviousFrameHidden(lldb_private::StackFrame &frame);
+
+ /// Returns the stack frame marker based on the whether the terminal supports
+ /// Unicode.
+ std::wstring FrameMarker(lldb::StackFrameSP frame_sp,
+ lldb::StackFrameSP selected_frame_sp);
+
/// Get the currently selected frame index.
/// We should only call SelectMostRelevantFrame if (a) the user hasn't already
/// selected a frame, and (b) if this really is a user facing
@@ -96,7 +107,7 @@ class StackFrameList : public std::enable_shared_from_this<StackFrameList> {
size_t GetStatus(Stream &strm, uint32_t first_frame, uint32_t num_frames,
bool show_frame_info, uint32_t num_frames_with_source,
bool show_unique = false, bool show_hidden = false,
- const char *frame_marker = nullptr);
+ bool show_selected_frame = false);
/// Returns whether we have currently fetched all the frames of a stack.
bool WereAllFramesFetched() const;
diff --git a/lldb/source/Target/StackFrame.cpp b/lldb/source/Target/StackFrame.cpp
index 3bbb851b88007..7988473069668 100644
--- a/lldb/source/Target/StackFrame.cpp
+++ b/lldb/source/Target/StackFrame.cpp
@@ -1945,7 +1945,7 @@ bool StackFrame::DumpUsingFormat(Stream &strm,
}
void StackFrame::DumpUsingSettingsFormat(Stream *strm, bool show_unique,
- const char *frame_marker) {
+ const llvm::StringRef frame_marker) {
if (strm == nullptr)
return;
@@ -2044,7 +2044,8 @@ bool StackFrame::HasCachedData() const {
}
bool StackFrame::GetStatus(Stream &strm, bool show_frame_info, bool show_source,
- bool show_unique, const char *frame_marker) {
+ bool show_unique,
+ const llvm::StringRef frame_marker) {
if (show_frame_info) {
strm.Indent();
DumpUsingSettingsFormat(&strm, show_unique, frame_marker);
diff --git a/lldb/source/Target/StackFrameList.cpp b/lldb/source/Target/StackFrameList.cpp
index 896a760f61d26..cadad17a75212 100644
--- a/lldb/source/Target/StackFrameList.cpp
+++ b/lldb/source/Target/StackFrameList.cpp
@@ -27,6 +27,7 @@
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/Support/ConvertUTF.h"
#include <memory>
@@ -928,11 +929,42 @@ StackFrameList::GetStackFrameSPForStackFramePtr(StackFrame *stack_frame_ptr) {
return ret_sp;
}
+bool StackFrameList::IsNextFrameHidden(lldb_private::StackFrame &frame) {
+ uint32_t frame_idx = frame.GetFrameIndex();
+ StackFrameSP frame_sp = GetFrameAtIndex(frame_idx + 1);
+ if (!frame_sp)
+ return false;
+ return frame_sp->IsHidden();
+}
+
+bool StackFrameList::IsPreviousFrameHidden(lldb_private::StackFrame &frame) {
+ uint32_t frame_idx = frame.GetFrameIndex();
+ if (frame_idx == 0)
+ return false;
+ StackFrameSP frame_sp = GetFrameAtIndex(frame_idx - 1);
+ if (!frame_sp)
+ return false;
+ return frame_sp->IsHidden();
+}
+
+std::wstring StackFrameList::FrameMarker(lldb::StackFrameSP frame_sp,
+ lldb::StackFrameSP selected_frame_sp) {
+ if (frame_sp == selected_frame_sp)
+ return Terminal::SupportsUnicode() ? L" * " : L"* ";
+ else if (!Terminal::SupportsUnicode())
+ return L" ";
+ else if (IsPreviousFrameHidden(*frame_sp))
+ return L" ﹉";
+ else if (IsNextFrameHidden(*frame_sp))
+ return L" ﹍";
+ return L" ";
+}
+
size_t StackFrameList::GetStatus(Stream &strm, uint32_t first_frame,
uint32_t num_frames, bool show_frame_info,
uint32_t num_frames_with_source,
bool show_unique, bool show_hidden,
- const char *selected_frame_marker) {
+ bool show_selected_frame) {
size_t num_frames_displayed = 0;
if (num_frames == 0)
@@ -950,25 +982,17 @@ size_t StackFrameList::GetStatus(Stream &strm, uint32_t first_frame,
StackFrameSP selected_frame_sp =
m_thread.GetSelectedFrame(DoNoSelectMostRelevantFrame);
- const char *unselected_marker = nullptr;
std::string buffer;
- if (selected_frame_marker) {
- size_t len = strlen(selected_frame_marker);
- buffer.insert(buffer.begin(), len, ' ');
- unselected_marker = buffer.c_str();
- }
- const char *marker = nullptr;
+ std::wstring marker;
for (frame_idx = first_frame; frame_idx < last_frame; ++frame_idx) {
frame_sp = GetFrameAtIndex(frame_idx);
if (!frame_sp)
break;
- if (selected_frame_marker != nullptr) {
- if (frame_sp == selected_frame_sp)
- marker = selected_frame_marker;
- else
- marker = unselected_marker;
- }
+ if (show_selected_frame)
+ marker = FrameMarker(frame_sp, selected_frame_sp);
+ else
+ marker = FrameMarker(frame_sp, nullptr);
// Hide uninteresting frames unless it's the selected frame.
if (!show_hidden && frame_sp != selected_frame_sp && frame_sp->IsHidden())
@@ -982,10 +1006,11 @@ size_t StackFrameList::GetStatus(Stream &strm, uint32_t first_frame,
m_thread.GetID(), num_frames_displayed))
break;
-
+ std::string marker_utf8;
+ llvm::convertWideToUTF8(marker, marker_utf8);
if (!frame_sp->GetStatus(strm, show_frame_info,
num_frames_with_source > (first_frame - frame_idx),
- show_unique, marker))
+ show_unique, marker_utf8))
break;
++num_frames_displayed;
}
diff --git a/lldb/source/Target/Thread.cpp b/lldb/source/Target/Thread.cpp
index b40e753aca1e9..800099888b99a 100644
--- a/lldb/source/Target/Thread.cpp
+++ b/lldb/source/Target/Thread.cpp
@@ -1887,16 +1887,16 @@ size_t Thread::GetStatus(Stream &strm, uint32_t start_frame,
const bool show_frame_info = true;
const bool show_frame_unique = only_stacks;
- const char *selected_frame_marker = nullptr;
+ bool show_selected_frame = false;
if (num_frames == 1 || only_stacks ||
(GetID() != GetProcess()->GetThreadList().GetSelectedThread()->GetID()))
strm.IndentMore();
else
- selected_frame_marker = "* ";
+ show_selected_frame = true;
num_frames_shown = GetStackFrameList()->GetStatus(
strm, start_frame, num_frames, show_frame_info, num_frames_with_source,
- show_frame_unique, show_hidden, selected_frame_marker);
+ show_frame_unique, show_hidden, show_selected_frame);
if (num_frames == 1)
strm.IndentLess();
strm.IndentLess();
>From cb637eea97a59d3864ecd18da2b2144e04c46804 Mon Sep 17 00:00:00 2001
From: Charles Zablit <c_zablit at apple.com>
Date: Mon, 15 Dec 2025 12:33:48 +0000
Subject: [PATCH 2/7] add test
---
lldb/include/lldb/Target/StackFrameList.h | 13 ++++++---
.../Python/lldbsuite/test/decorators.py | 29 +++++++++++++++++++
.../terminal/hidden_frame_markers/Makefile | 3 ++
.../TestHiddenFrameMarkers.py | 20 +++++++++++++
.../terminal/hidden_frame_markers/main.cpp | 12 ++++++++
5 files changed, 73 insertions(+), 4 deletions(-)
create mode 100644 lldb/test/API/terminal/hidden_frame_markers/Makefile
create mode 100644 lldb/test/API/terminal/hidden_frame_markers/TestHiddenFrameMarkers.py
create mode 100644 lldb/test/API/terminal/hidden_frame_markers/main.cpp
diff --git a/lldb/include/lldb/Target/StackFrameList.h b/lldb/include/lldb/Target/StackFrameList.h
index c5b74522be0bb..a3bb761ca6572 100644
--- a/lldb/include/lldb/Target/StackFrameList.h
+++ b/lldb/include/lldb/Target/StackFrameList.h
@@ -49,14 +49,19 @@ class StackFrameList : public std::enable_shared_from_this<StackFrameList> {
/// Resets the selected frame index of this object.
void ClearSelectedFrameIndex();
- /// Returns \code true if the next frame is hidden.
+ /// Returns \p true if the next frame is hidden.
bool IsNextFrameHidden(lldb_private::StackFrame &frame);
- /// Returns \code true if the previous frame is hidden.
+ /// Returns \p true if the previous frame is hidden.
bool IsPreviousFrameHidden(lldb_private::StackFrame &frame);
- /// Returns the stack frame marker based on the whether the terminal supports
- /// Unicode.
+ /// Returns the stack frame marker depending on if \p frame_sp:
+ /// @li is selected: *
+ /// @li is the first non hidden frame: ﹍
+ /// @li is the last non hidden frame: ﹉
+ ///
+ /// If the terminal does not support Unicode rendering, the hidden frame
+ /// markers are replaced with whitespaces.
std::wstring FrameMarker(lldb::StackFrameSP frame_sp,
lldb::StackFrameSP selected_frame_sp);
diff --git a/lldb/packages/Python/lldbsuite/test/decorators.py b/lldb/packages/Python/lldbsuite/test/decorators.py
index 150f5bbd3868b..3f193f9ac09d7 100644
--- a/lldb/packages/Python/lldbsuite/test/decorators.py
+++ b/lldb/packages/Python/lldbsuite/test/decorators.py
@@ -438,6 +438,35 @@ def impl(func):
return impl
+def unicode_test(func):
+ """Decorate the item as a test which requires Unicode to be enabled.
+
+ lldb checks the value of the `LANG` environment variable for the substring "utf-8"
+ to determine if the terminal supports Unicode (except on Windows, were we assume
+ it's always supported).
+ This decorator sets LANG to `utf-8` before running the test and resets it to its
+ previous value afterwards.
+ """
+
+ def unicode_wrapped(*args, **kwargs):
+ import os
+
+ previous_lang = os.environ.get("LANG", None)
+ os.environ["LANG"] = "en_US.UTF-8"
+ try:
+ func(*args, **kwargs)
+ except Exception as err:
+ raise err
+ finally:
+ # Reset the value, whether the test failed or not.
+ if previous_lang is not None:
+ os.environ["LANG"] = previous_lang
+ else:
+ del os.environ["LANG"]
+
+ return unicode_wrapped
+
+
def no_debug_info_test(func):
"""Decorate the item as a test what don't use any debug info. If this annotation is specified
then the test runner won't generate a separate test for each debug info format."""
diff --git a/lldb/test/API/terminal/hidden_frame_markers/Makefile b/lldb/test/API/terminal/hidden_frame_markers/Makefile
new file mode 100644
index 0000000000000..99998b20bcb05
--- /dev/null
+++ b/lldb/test/API/terminal/hidden_frame_markers/Makefile
@@ -0,0 +1,3 @@
+CXX_SOURCES := main.cpp
+
+include Makefile.rules
diff --git a/lldb/test/API/terminal/hidden_frame_markers/TestHiddenFrameMarkers.py b/lldb/test/API/terminal/hidden_frame_markers/TestHiddenFrameMarkers.py
new file mode 100644
index 0000000000000..e1de92e400f7d
--- /dev/null
+++ b/lldb/test/API/terminal/hidden_frame_markers/TestHiddenFrameMarkers.py
@@ -0,0 +1,20 @@
+"""
+Test that hidden frames are delimited with markers.
+"""
+
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+from lldbsuite.test.lldbpexpect import PExpectTest
+
+
+class HiddenFrameMarkerTest(TestBase):
+ @unicodeTest
+ def test_hidden_frame_markers(self):
+ """Test that hidden frame markers are rendered in backtraces"""
+ self.build()
+ lldbutil.run_to_source_breakpoint(
+ self, "// break here", lldb.SBFileSpec("main.cpp")
+ )
+ self.expect("bt", substrs=["﹍frame #1:", "﹉frame #7:", " frame #8:", " frame #9:"])
diff --git a/lldb/test/API/terminal/hidden_frame_markers/main.cpp b/lldb/test/API/terminal/hidden_frame_markers/main.cpp
new file mode 100644
index 0000000000000..745560bc3cb17
--- /dev/null
+++ b/lldb/test/API/terminal/hidden_frame_markers/main.cpp
@@ -0,0 +1,12 @@
+#include <functional>
+#include <iostream>
+
+static void target() {
+ int a = 0; // break here
+}
+
+int main() {
+ std::function<void()> fn = [] { target(); };
+ fn();
+ return 0;
+}
\ No newline at end of file
>From eb4dda300ca79d1b2d16a59ed4505069b12f3678 Mon Sep 17 00:00:00 2001
From: Charles Zablit <c_zablit at apple.com>
Date: Mon, 15 Dec 2025 14:54:49 +0000
Subject: [PATCH 3/7] fixup! add test
---
lldb/source/Target/StackFrameList.cpp | 8 ++--
.../TestHiddenFrameMarkers.py | 38 +++++++++++++++++--
2 files changed, 39 insertions(+), 7 deletions(-)
diff --git a/lldb/source/Target/StackFrameList.cpp b/lldb/source/Target/StackFrameList.cpp
index cadad17a75212..9ae2d54f4a0af 100644
--- a/lldb/source/Target/StackFrameList.cpp
+++ b/lldb/source/Target/StackFrameList.cpp
@@ -950,14 +950,14 @@ bool StackFrameList::IsPreviousFrameHidden(lldb_private::StackFrame &frame) {
std::wstring StackFrameList::FrameMarker(lldb::StackFrameSP frame_sp,
lldb::StackFrameSP selected_frame_sp) {
if (frame_sp == selected_frame_sp)
- return Terminal::SupportsUnicode() ? L" * " : L"* ";
+ return Terminal::SupportsUnicode() ? L" * " : L"* ";
else if (!Terminal::SupportsUnicode())
return L" ";
else if (IsPreviousFrameHidden(*frame_sp))
- return L" ﹉";
+ return L"﹉ ";
else if (IsNextFrameHidden(*frame_sp))
- return L" ﹍";
- return L" ";
+ return L"﹍ ";
+ return L" ";
}
size_t StackFrameList::GetStatus(Stream &strm, uint32_t first_frame,
diff --git a/lldb/test/API/terminal/hidden_frame_markers/TestHiddenFrameMarkers.py b/lldb/test/API/terminal/hidden_frame_markers/TestHiddenFrameMarkers.py
index e1de92e400f7d..b501ca331d255 100644
--- a/lldb/test/API/terminal/hidden_frame_markers/TestHiddenFrameMarkers.py
+++ b/lldb/test/API/terminal/hidden_frame_markers/TestHiddenFrameMarkers.py
@@ -6,15 +6,47 @@
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil
-from lldbsuite.test.lldbpexpect import PExpectTest
class HiddenFrameMarkerTest(TestBase):
- @unicodeTest
+ @unicode_test
def test_hidden_frame_markers(self):
"""Test that hidden frame markers are rendered in backtraces"""
self.build()
lldbutil.run_to_source_breakpoint(
self, "// break here", lldb.SBFileSpec("main.cpp")
)
- self.expect("bt", substrs=["﹍frame #1:", "﹉frame #7:", " frame #8:", " frame #9:"])
+ self.expect(
+ "bt",
+ substrs=[
+ " * frame #0:",
+ " ﹍ frame #1:",
+ " ﹉ frame #7:",
+ " frame #8:",
+ " frame #9:",
+ ],
+ )
+
+ self.runCmd("f 1")
+ self.expect(
+ "bt",
+ substrs=[
+ " frame #0:",
+ " ﹍ frame #1:",
+ " * frame #7:",
+ " frame #8:",
+ " frame #9:",
+ ],
+ )
+
+ self.runCmd("f 7")
+ self.expect(
+ "bt",
+ substrs=[
+ " frame #0:",
+ " * frame #1:",
+ " ﹉ frame #7:",
+ " frame #8:",
+ " frame #9:",
+ ],
+ )
>From 7e318b68bd7752068bd72f6473b1ab33ae3c0577 Mon Sep 17 00:00:00 2001
From: Charles Zablit <c_zablit at apple.com>
Date: Mon, 15 Dec 2025 15:23:35 +0000
Subject: [PATCH 4/7] fix inverted test
---
.../hidden_frame_markers/TestHiddenFrameMarkers.py | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/lldb/test/API/terminal/hidden_frame_markers/TestHiddenFrameMarkers.py b/lldb/test/API/terminal/hidden_frame_markers/TestHiddenFrameMarkers.py
index b501ca331d255..387718250baea 100644
--- a/lldb/test/API/terminal/hidden_frame_markers/TestHiddenFrameMarkers.py
+++ b/lldb/test/API/terminal/hidden_frame_markers/TestHiddenFrameMarkers.py
@@ -32,8 +32,8 @@ def test_hidden_frame_markers(self):
"bt",
substrs=[
" frame #0:",
- " ﹍ frame #1:",
- " * frame #7:",
+ " * frame #1:",
+ " ﹉ frame #7:",
" frame #8:",
" frame #9:",
],
@@ -44,8 +44,8 @@ def test_hidden_frame_markers(self):
"bt",
substrs=[
" frame #0:",
- " * frame #1:",
- " ﹉ frame #7:",
+ " ﹍ frame #1:",
+ " * frame #7:",
" frame #8:",
" frame #9:",
],
>From ac9b1d02c4ca16b39125a33b064c393b5aef7add Mon Sep 17 00:00:00 2001
From: Charles Zablit <c_zablit at apple.com>
Date: Fri, 9 Jan 2026 18:26:38 +0000
Subject: [PATCH 5/7] remove std::wstring usage
---
lldb/include/lldb/Target/StackFrameList.h | 4 ++--
lldb/source/Target/StackFrameList.cpp | 20 +++++++++-----------
2 files changed, 11 insertions(+), 13 deletions(-)
diff --git a/lldb/include/lldb/Target/StackFrameList.h b/lldb/include/lldb/Target/StackFrameList.h
index a3bb761ca6572..525269005d05f 100644
--- a/lldb/include/lldb/Target/StackFrameList.h
+++ b/lldb/include/lldb/Target/StackFrameList.h
@@ -62,8 +62,8 @@ class StackFrameList : public std::enable_shared_from_this<StackFrameList> {
///
/// If the terminal does not support Unicode rendering, the hidden frame
/// markers are replaced with whitespaces.
- std::wstring FrameMarker(lldb::StackFrameSP frame_sp,
- lldb::StackFrameSP selected_frame_sp);
+ std::string FrameMarker(lldb::StackFrameSP frame_sp,
+ lldb::StackFrameSP selected_frame_sp);
/// Get the currently selected frame index.
/// We should only call SelectMostRelevantFrame if (a) the user hasn't already
diff --git a/lldb/source/Target/StackFrameList.cpp b/lldb/source/Target/StackFrameList.cpp
index 9ae2d54f4a0af..42cf2d87c17e8 100644
--- a/lldb/source/Target/StackFrameList.cpp
+++ b/lldb/source/Target/StackFrameList.cpp
@@ -947,17 +947,17 @@ bool StackFrameList::IsPreviousFrameHidden(lldb_private::StackFrame &frame) {
return frame_sp->IsHidden();
}
-std::wstring StackFrameList::FrameMarker(lldb::StackFrameSP frame_sp,
- lldb::StackFrameSP selected_frame_sp) {
+std::string StackFrameList::FrameMarker(lldb::StackFrameSP frame_sp,
+ lldb::StackFrameSP selected_frame_sp) {
if (frame_sp == selected_frame_sp)
- return Terminal::SupportsUnicode() ? L" * " : L"* ";
+ return Terminal::SupportsUnicode() ? u8" * " : u8"* ";
else if (!Terminal::SupportsUnicode())
- return L" ";
+ return u8" ";
else if (IsPreviousFrameHidden(*frame_sp))
- return L"﹉ ";
+ return u8"﹉ ";
else if (IsNextFrameHidden(*frame_sp))
- return L"﹍ ";
- return L" ";
+ return u8"﹍ ";
+ return u8" ";
}
size_t StackFrameList::GetStatus(Stream &strm, uint32_t first_frame,
@@ -983,7 +983,7 @@ size_t StackFrameList::GetStatus(Stream &strm, uint32_t first_frame,
StackFrameSP selected_frame_sp =
m_thread.GetSelectedFrame(DoNoSelectMostRelevantFrame);
std::string buffer;
- std::wstring marker;
+ std::string marker;
for (frame_idx = first_frame; frame_idx < last_frame; ++frame_idx) {
frame_sp = GetFrameAtIndex(frame_idx);
if (!frame_sp)
@@ -1006,11 +1006,9 @@ size_t StackFrameList::GetStatus(Stream &strm, uint32_t first_frame,
m_thread.GetID(), num_frames_displayed))
break;
- std::string marker_utf8;
- llvm::convertWideToUTF8(marker, marker_utf8);
if (!frame_sp->GetStatus(strm, show_frame_info,
num_frames_with_source > (first_frame - frame_idx),
- show_unique, marker_utf8))
+ show_unique, marker))
break;
++num_frames_displayed;
}
>From 0f558476458ead0e68dbf53fa42a3f829af24791 Mon Sep 17 00:00:00 2001
From: Charles Zablit <c_zablit at apple.com>
Date: Thu, 15 Jan 2026 22:12:51 +0000
Subject: [PATCH 6/7] add a setting to display the marker or not
---
lldb/include/lldb/Core/Debugger.h | 2 +
lldb/source/Core/CoreProperties.td | 4 ++
lldb/source/Core/Debugger.cpp | 7 +++
lldb/source/Target/Thread.cpp | 6 +--
.../TestHiddenFrameMarkers.py | 45 +++++++++++++++++++
5 files changed, 61 insertions(+), 3 deletions(-)
diff --git a/lldb/include/lldb/Core/Debugger.h b/lldb/include/lldb/Core/Debugger.h
index a39413c06340c..2894b2ffc8c44 100644
--- a/lldb/include/lldb/Core/Debugger.h
+++ b/lldb/include/lldb/Core/Debugger.h
@@ -340,6 +340,8 @@ class Debugger : public std::enable_shared_from_this<Debugger>,
bool SetUseSourceCache(bool use_source_cache);
+ bool GetMarkSkippedFrames() const;
+
bool GetHighlightSource() const;
lldb::StopShowColumn GetStopShowColumn() const;
diff --git a/lldb/source/Core/CoreProperties.td b/lldb/source/Core/CoreProperties.td
index a54d5538f4c0c..c9379e438d01d 100644
--- a/lldb/source/Core/CoreProperties.td
+++ b/lldb/source/Core/CoreProperties.td
@@ -114,6 +114,10 @@ let Definition = "debugger" in {
Global,
DefaultTrue,
Desc<"If true, LLDB will highlight the displayed source code.">;
+ def MarkSkippedFrames: Property<"mark-skipped-frames", "Boolean">,
+ Global,
+ DefaultTrue,
+ Desc<"If true, LLDB will add a marker to delimit skipped frames.">;
def StopShowColumn: Property<"stop-show-column", "Enum">,
DefaultEnumValue<"eStopShowColumnAnsiOrCaret">,
EnumValues<"OptionEnumValues(s_stop_show_column_values)">,
diff --git a/lldb/source/Core/Debugger.cpp b/lldb/source/Core/Debugger.cpp
index 99f4a728e3f17..57056c3a3c125 100644
--- a/lldb/source/Core/Debugger.cpp
+++ b/lldb/source/Core/Debugger.cpp
@@ -584,6 +584,13 @@ bool Debugger::SetUseSourceCache(bool b) {
}
return ret;
}
+
+bool Debugger::GetMarkSkippedFrames() const {
+ const uint32_t idx = ePropertyMarkSkippedFrames;
+ return GetPropertyAtIndexAs<bool>(
+ idx, g_debugger_properties[idx].default_uint_value != 0);
+}
+
bool Debugger::GetHighlightSource() const {
const uint32_t idx = ePropertyHighlightSource;
return GetPropertyAtIndexAs<bool>(
diff --git a/lldb/source/Target/Thread.cpp b/lldb/source/Target/Thread.cpp
index 800099888b99a..2248b5f9b523c 100644
--- a/lldb/source/Target/Thread.cpp
+++ b/lldb/source/Target/Thread.cpp
@@ -1851,9 +1851,9 @@ size_t Thread::GetStatus(Stream &strm, uint32_t start_frame,
uint32_t num_frames, uint32_t num_frames_with_source,
bool stop_format, bool show_hidden, bool only_stacks) {
+ ExecutionContext exe_ctx(shared_from_this());
+ Target *target = exe_ctx.GetTargetPtr();
if (!only_stacks) {
- ExecutionContext exe_ctx(shared_from_this());
- Target *target = exe_ctx.GetTargetPtr();
Process *process = exe_ctx.GetProcessPtr();
strm.Indent();
bool is_selected = false;
@@ -1892,7 +1892,7 @@ size_t Thread::GetStatus(Stream &strm, uint32_t start_frame,
(GetID() != GetProcess()->GetThreadList().GetSelectedThread()->GetID()))
strm.IndentMore();
else
- show_selected_frame = true;
+ show_selected_frame = target->GetDebugger().GetMarkSkippedFrames();
num_frames_shown = GetStackFrameList()->GetStatus(
strm, start_frame, num_frames, show_frame_info, num_frames_with_source,
diff --git a/lldb/test/API/terminal/hidden_frame_markers/TestHiddenFrameMarkers.py b/lldb/test/API/terminal/hidden_frame_markers/TestHiddenFrameMarkers.py
index 387718250baea..b9d20bd1c5d74 100644
--- a/lldb/test/API/terminal/hidden_frame_markers/TestHiddenFrameMarkers.py
+++ b/lldb/test/API/terminal/hidden_frame_markers/TestHiddenFrameMarkers.py
@@ -50,3 +50,48 @@ def test_hidden_frame_markers(self):
" frame #9:",
],
)
+
+ def test_hidden_frame_markers(self):
+ """
+ Test that hidden frame markers are not rendered in backtraces when
+ mark-skipped-frames is set to false
+ """
+ self.build()
+ self.runCmd("settings set mark-skipped-frames 0")
+ lldbutil.run_to_source_breakpoint(
+ self, "// break here", lldb.SBFileSpec("main.cpp")
+ )
+ self.expect(
+ "bt",
+ substrs=[
+ " * frame #0:",
+ " frame #1:",
+ " frame #7:",
+ " frame #8:",
+ " frame #9:",
+ ],
+ )
+
+ self.runCmd("f 1")
+ self.expect(
+ "bt",
+ substrs=[
+ " frame #0:",
+ " * frame #1:",
+ " frame #7:",
+ " frame #8:",
+ " frame #9:",
+ ],
+ )
+
+ self.runCmd("f 7")
+ self.expect(
+ "bt",
+ substrs=[
+ " frame #0:",
+ " frame #1:",
+ " * frame #7:",
+ " frame #8:",
+ " frame #9:",
+ ],
+ )
>From fbdb128ed28a2d8cf7dc3c600061ac37b36755ee Mon Sep 17 00:00:00 2001
From: Charles Zablit <c_zablit at apple.com>
Date: Fri, 16 Jan 2026 16:29:57 +0100
Subject: [PATCH 7/7] ensure we use 'hidden' instead of 'skipped';
---
lldb/include/lldb/Core/Debugger.h | 2 +-
lldb/include/lldb/Target/StackFrameList.h | 1 +
lldb/source/Core/CoreProperties.td | 4 +--
lldb/source/Core/Debugger.cpp | 4 +--
lldb/source/Target/StackFrameList.cpp | 1 +
lldb/source/Target/Thread.cpp | 17 +++++++---
.../TestHiddenFrameMarkers.py | 34 +++++++++----------
.../terminal/hidden_frame_markers/main.cpp | 2 +-
8 files changed, 37 insertions(+), 28 deletions(-)
diff --git a/lldb/include/lldb/Core/Debugger.h b/lldb/include/lldb/Core/Debugger.h
index 2894b2ffc8c44..dadccaeb5d17b 100644
--- a/lldb/include/lldb/Core/Debugger.h
+++ b/lldb/include/lldb/Core/Debugger.h
@@ -340,7 +340,7 @@ class Debugger : public std::enable_shared_from_this<Debugger>,
bool SetUseSourceCache(bool use_source_cache);
- bool GetMarkSkippedFrames() const;
+ bool GetMarkHiddenFrames() const;
bool GetHighlightSource() const;
diff --git a/lldb/include/lldb/Target/StackFrameList.h b/lldb/include/lldb/Target/StackFrameList.h
index 525269005d05f..663b583479cfd 100644
--- a/lldb/include/lldb/Target/StackFrameList.h
+++ b/lldb/include/lldb/Target/StackFrameList.h
@@ -112,6 +112,7 @@ class StackFrameList : public std::enable_shared_from_this<StackFrameList> {
size_t GetStatus(Stream &strm, uint32_t first_frame, uint32_t num_frames,
bool show_frame_info, uint32_t num_frames_with_source,
bool show_unique = false, bool show_hidden = false,
+ bool show_hidden_marker = true,
bool show_selected_frame = false);
/// Returns whether we have currently fetched all the frames of a stack.
diff --git a/lldb/source/Core/CoreProperties.td b/lldb/source/Core/CoreProperties.td
index c9379e438d01d..62e5a169aeff5 100644
--- a/lldb/source/Core/CoreProperties.td
+++ b/lldb/source/Core/CoreProperties.td
@@ -114,10 +114,10 @@ let Definition = "debugger" in {
Global,
DefaultTrue,
Desc<"If true, LLDB will highlight the displayed source code.">;
- def MarkSkippedFrames: Property<"mark-skipped-frames", "Boolean">,
+ def MarkHiddenFrames: Property<"mark-hidden-frames", "Boolean">,
Global,
DefaultTrue,
- Desc<"If true, LLDB will add a marker to delimit skipped frames.">;
+ Desc<"If true, LLDB will add a marker to delimit hidden frames in backtraces.">;
def StopShowColumn: Property<"stop-show-column", "Enum">,
DefaultEnumValue<"eStopShowColumnAnsiOrCaret">,
EnumValues<"OptionEnumValues(s_stop_show_column_values)">,
diff --git a/lldb/source/Core/Debugger.cpp b/lldb/source/Core/Debugger.cpp
index 57056c3a3c125..c112c37861ac0 100644
--- a/lldb/source/Core/Debugger.cpp
+++ b/lldb/source/Core/Debugger.cpp
@@ -585,8 +585,8 @@ bool Debugger::SetUseSourceCache(bool b) {
return ret;
}
-bool Debugger::GetMarkSkippedFrames() const {
- const uint32_t idx = ePropertyMarkSkippedFrames;
+bool Debugger::GetMarkHiddenFrames() const {
+ const uint32_t idx = ePropertyMarkHiddenFrames;
return GetPropertyAtIndexAs<bool>(
idx, g_debugger_properties[idx].default_uint_value != 0);
}
diff --git a/lldb/source/Target/StackFrameList.cpp b/lldb/source/Target/StackFrameList.cpp
index 42cf2d87c17e8..8aa631519013b 100644
--- a/lldb/source/Target/StackFrameList.cpp
+++ b/lldb/source/Target/StackFrameList.cpp
@@ -964,6 +964,7 @@ size_t StackFrameList::GetStatus(Stream &strm, uint32_t first_frame,
uint32_t num_frames, bool show_frame_info,
uint32_t num_frames_with_source,
bool show_unique, bool show_hidden,
+ bool show_hidden_marker,
bool show_selected_frame) {
size_t num_frames_displayed = 0;
diff --git a/lldb/source/Target/Thread.cpp b/lldb/source/Target/Thread.cpp
index 2248b5f9b523c..4b2576f411dd5 100644
--- a/lldb/source/Target/Thread.cpp
+++ b/lldb/source/Target/Thread.cpp
@@ -1892,11 +1892,14 @@ size_t Thread::GetStatus(Stream &strm, uint32_t start_frame,
(GetID() != GetProcess()->GetThreadList().GetSelectedThread()->GetID()))
strm.IndentMore();
else
- show_selected_frame = target->GetDebugger().GetMarkSkippedFrames();
+ show_selected_frame = true;
+ bool show_hidden_marker =
+ target && target->GetDebugger().GetMarkHiddenFrames();
num_frames_shown = GetStackFrameList()->GetStatus(
strm, start_frame, num_frames, show_frame_info, num_frames_with_source,
- show_frame_unique, show_hidden, show_selected_frame);
+ show_frame_unique, show_hidden, show_hidden_marker,
+ show_selected_frame);
if (num_frames == 1)
strm.IndentLess();
strm.IndentLess();
@@ -1996,9 +1999,13 @@ size_t Thread::GetStackFrameStatus(Stream &strm, uint32_t first_frame,
uint32_t num_frames, bool show_frame_info,
uint32_t num_frames_with_source,
bool show_hidden) {
- return GetStackFrameList()->GetStatus(strm, first_frame, num_frames,
- show_frame_info, num_frames_with_source,
- /*show_unique*/ false, show_hidden);
+ ExecutionContext exe_ctx(shared_from_this());
+ Target *target = exe_ctx.GetTargetPtr();
+ bool show_hidden_marker =
+ target && target->GetDebugger().GetMarkHiddenFrames();
+ return GetStackFrameList()->GetStatus(
+ strm, first_frame, num_frames, show_frame_info, num_frames_with_source,
+ /*show_unique*/ false, show_hidden, show_hidden_marker);
}
Unwind &Thread::GetUnwinder() {
diff --git a/lldb/test/API/terminal/hidden_frame_markers/TestHiddenFrameMarkers.py b/lldb/test/API/terminal/hidden_frame_markers/TestHiddenFrameMarkers.py
index b9d20bd1c5d74..178d97fce17c2 100644
--- a/lldb/test/API/terminal/hidden_frame_markers/TestHiddenFrameMarkers.py
+++ b/lldb/test/API/terminal/hidden_frame_markers/TestHiddenFrameMarkers.py
@@ -54,21 +54,21 @@ def test_hidden_frame_markers(self):
def test_hidden_frame_markers(self):
"""
Test that hidden frame markers are not rendered in backtraces when
- mark-skipped-frames is set to false
+ mark-hidden-frames is set to false
"""
self.build()
- self.runCmd("settings set mark-skipped-frames 0")
+ self.runCmd("settings set mark-hidden-frames 0")
lldbutil.run_to_source_breakpoint(
self, "// break here", lldb.SBFileSpec("main.cpp")
)
self.expect(
"bt",
substrs=[
- " * frame #0:",
- " frame #1:",
- " frame #7:",
- " frame #8:",
- " frame #9:",
+ " * frame #0:",
+ " frame #1:",
+ " frame #7:",
+ " frame #8:",
+ " frame #9:",
],
)
@@ -76,11 +76,11 @@ def test_hidden_frame_markers(self):
self.expect(
"bt",
substrs=[
- " frame #0:",
- " * frame #1:",
- " frame #7:",
- " frame #8:",
- " frame #9:",
+ " frame #0:",
+ " * frame #1:",
+ " frame #7:",
+ " frame #8:",
+ " frame #9:",
],
)
@@ -88,10 +88,10 @@ def test_hidden_frame_markers(self):
self.expect(
"bt",
substrs=[
- " frame #0:",
- " frame #1:",
- " * frame #7:",
- " frame #8:",
- " frame #9:",
+ " frame #0:",
+ " frame #1:",
+ " * frame #7:",
+ " frame #8:",
+ " frame #9:",
],
)
diff --git a/lldb/test/API/terminal/hidden_frame_markers/main.cpp b/lldb/test/API/terminal/hidden_frame_markers/main.cpp
index 745560bc3cb17..c0b7e0884538a 100644
--- a/lldb/test/API/terminal/hidden_frame_markers/main.cpp
+++ b/lldb/test/API/terminal/hidden_frame_markers/main.cpp
@@ -9,4 +9,4 @@ int main() {
std::function<void()> fn = [] { target(); };
fn();
return 0;
-}
\ No newline at end of file
+}
More information about the lldb-commits
mailing list