* [PATCH] gdb/python: Handle unnamed frames in caller-matching functions
[not found] <b555285517bf4506b85c0421ea062784@huawei.com>
@ 2026-10-13 11:35 ` Dmitry Ivanov (A)
2026-10-14 16:04 ` Tom Tromey
0 siblings, 1 reply; 2+ messages in thread
From: Dmitry Ivanov (A) @ 2026-10-13 11:35 UTC (permalink / raw)
To: gdb-patches
[-- Attachment #1: Type: text/plain, Size: 3251 bytes --]
gdb.Frame.name() can return None when GDB cannot determine a frame's
function name. and currently
pass that value directly to Python's regular expression functions,
causing a TypeError.
Treat unnamed frames as non-matches. For None, keep
walking older frames after encountering an unnamed frame.
Add regression tests for both convenience functions.
---
This is my first GDB contribution.
I used ChatGPT to help investigate the issue and draft an initial
version of the patch (it's fairly simple but still worth mentioning).
I reviewed, simplified, and tested the final change myself.
Tested with:
make -C gdb check RUNTESTFLAGS='gdb.python/py-caller-is.exp'
gdb/python/lib/gdb/function/caller_is.py | 6 ++++--
gdb/testsuite/gdb.python/py-caller-is.exp | 20 ++++++++++++++++++++
2 files changed, 24 insertions(+), 2 deletions(-)
diff --git a/gdb/python/lib/gdb/function/caller_is.py b/gdb/python/lib/gdb/function/caller_is.py
index bca09590811..a2a5798b914 100644
--- a/gdb/python/lib/gdb/function/caller_is.py
+++ b/gdb/python/lib/gdb/function/caller_is.py
@@ -80,7 +80,8 @@ class CallerMatches(gdb.Function):
if frame is None:
return False
nframes = nframes - 1
- return re.match(name.string(), frame.name()) is not None
+ frame_name = frame.name()
+ return frame_name is not None and re.match(name.string(), frame_name) is not None
class AnyCallerIs(gdb.Function):
@@ -143,7 +144,8 @@ class AnyCallerMatches(gdb.Function):
frame = gdb.selected_frame()
name_re = re.compile(name.string())
while nframes >= 0:
- if name_re.match(frame.name()) is not None:
+ frame_name = frame.name()
+ if frame_name is not None and name_re.match(frame_name) is not None:
return True
frame = frame.older()
if frame is None:
diff --git a/gdb/testsuite/gdb.python/py-caller-is.exp b/gdb/testsuite/gdb.python/py-caller-is.exp
index d9b826cb6a2..74ee2ae645a 100644
--- a/gdb/testsuite/gdb.python/py-caller-is.exp
+++ b/gdb/testsuite/gdb.python/py-caller-is.exp
@@ -70,3 +70,23 @@ proc test_all_caller_is_fns { } {
}
test_all_caller_is_fns
+
+# Prepend an unnamed frame to the current stack without depending on
+# missing symbols in the host's runtime libraries.
+gdb_test_multiline "define unnamed frame helper" \
+ "python" "" \
+ "from unittest.mock import Mock, patch" "" \
+ "def check_unnamed_frame(expr):" "" \
+ " frame = Mock()" "" \
+ " frame.name.return_value = None" "" \
+ " frame.older.return_value = gdb.selected_frame()" "" \
+ " with patch.object(gdb, 'selected_frame', return_value=frame):" "" \
+ " print(int(gdb.parse_and_eval(expr)))" "" \
+ "end" ""
+
+gdb_test {python check_unnamed_frame('$_caller_matches(".*", 0)')} \
+ "0" "caller_matches with unnamed frame"
+gdb_test {python check_unnamed_frame('$_any_caller_matches(".*", 0)')} \
+ "0" "any_caller_matches with unnamed frame"
+gdb_test {python check_unnamed_frame('$_any_caller_matches("^bottom_func$", 1)')} \
+ "1" "any_caller_matches skips unnamed frame"
--
2.34.1
[-- Attachment #2: Type: text/html, Size: 9259 bytes --]
^ permalink raw reply [flat|nested] 2+ messages in thread