From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id IekXJaEXzmqwBwEAWB0awg (envelope-from ) for ; Tue, 13 Oct 2026 07:36:01 -0400 Authentication-Results: simark.ca; dkim=pass (1024-bit key; unprotected) header.d=huawei.com header.i=@huawei.com header.a=rsa-sha256 header.s=dkim header.b=Taw0kQFG; dkim-atps=neutral Received: by simark.ca (Postfix, from userid 112) id 8AA9B1E051; Tue, 13 Oct 2026 07:36:01 -0400 (EDT) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-25) on simark.ca X-Spam-Level: X-Spam-Status: No, score=-5.4 required=5.0 tests=ARC_SIGNED,ARC_VALID,BAYES_00, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HTML_MESSAGE,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=ham autolearn_force=no version=4.0.1 Received: from vm01.sourceware.org (vm01.sourceware.org [IPv6:2620:52:6:3111::32]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature ECDSA (prime256v1) server-digest SHA256) (No client certificate requested) by simark.ca (Postfix) with ESMTPS id 2AC261E04E for ; Tue, 13 Oct 2026 07:35:57 -0400 (EDT) Received: from vm01.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 4D5714BA23DB for ; Tue, 13 Oct 2026 11:35:55 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 4D5714BA23DB Authentication-Results: sourceware.org; dkim=pass (1024-bit key, unprotected) header.d=huawei.com header.i=@huawei.com header.a=rsa-sha256 header.s=dkim header.b=Taw0kQFG Received: from frasgout.his.huawei.com (frasgout.his.huawei.com [185.176.79.56]) by sourceware.org (Postfix) with ESMTPS id 39C334BA5434 for ; Tue, 13 Oct 2026 11:35:26 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 39C334BA5434 Authentication-Results: sourceware.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=huawei.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 39C334BA5434 Authentication-Results: sourceware.org; arc=none smtp.remote-ip=185.176.79.56 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1791891326; cv=none; b=oixHczryY/dOveWzH0JDRMSQJOh67i+FDvh9prHZ3GH0ZhJoKEL7mi1cM9kCVjGSU3YpAVVAVV0lU/DALy9e/aq+hLRd3rXaXWTGC6sf0EzeWtl+pd9qK7hG6HrCERE4acag7RbW/1zx9YfVHTWTWtKbIXj1XT0+mYY4fj71UjM= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1791891326; c=relaxed/simple; bh=slDmvQj3rrNFlQlUZT8pnXJMBe3xUhL7xnZ1H2gVYNg=; h=dkim-signature:From:To:Subject:Date:Message-ID:MIME-Version; b=kXE6E2nGc0SDf4/a8nYQB9W3NZZyIMaBEk64aKw9cX3j5CjVnU2q5O0avNFFkDFMb47HdG2N7IdFVErnisMRjEl0kblTYxib9SLelrObNPAanBBolPhaJFgMYXNtnVZMh2GTkqXSczs4KIV8ZRMQgzVaalmqP5anX0lja+P3JxI= ARC-Authentication-Results: i=1; sourceware.org; dkim=pass (1024-bit key, unprotected) header.d=huawei.com header.i=@huawei.com header.a=rsa-sha256 header.s=dkim header.b=Taw0kQFG DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 39C334BA5434 dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=F8K6224NlpLucFnZqAFbVJQYW4cc47s9hvSjJVlzhuQ=; b=Taw0kQFGXDynh15oXTAw+FMEnLCEG8aYal/MwEUo1eVTTXt6AUV0tiP32h7t+zIk6CcH5jfJ3 GAku8tfECRl6MdqjtVnPCI/tX/Mbl4EmFDy9/PQRPluXoBnYxhtq5Xy+tLTaGWNQMzRsvX7TyMF h49clPjFtW7q6TRE9uDvo6w= Received: from mail.maildlp.com (unknown [172.18.224.107]) by frasgout.his.huawei.com (SkyGuard) with ESMTPS id 4j3shF5dGJzHnH40 for ; Tue, 13 Oct 2026 19:35:09 +0800 (CST) Received: from frapema100005.china.huawei.com (unknown [7.182.19.229]) by mail.maildlp.com (Postfix) with ESMTPS id 4F1FA40584 for ; Tue, 13 Oct 2026 19:35:17 +0800 (CST) Received: from frapema500005.china.huawei.com (7.182.19.99) by frapema100005.china.huawei.com (7.182.19.229) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.46; Tue, 13 Oct 2026 13:35:17 +0200 Received: from frapema500005.china.huawei.com ([7.182.19.99]) by frapema500005.china.huawei.com ([7.182.19.99]) with mapi id 15.02.2562.046; Tue, 13 Oct 2026 13:35:16 +0200 From: "Dmitry Ivanov (A)" To: "gdb-patches@sourceware.org" Subject: [PATCH] gdb/python: Handle unnamed frames in caller-matching functions Thread-Topic: [PATCH] gdb/python: Handle unnamed frames in caller-matching functions Thread-Index: Ad1SUSorFsxHQeoQQtSTORVriZR40wH5zDYA Date: Tue, 13 Oct 2026 11:35:16 +0000 Message-ID: References: In-Reply-To: Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-originating-ip: [10.221.99.70] Content-Type: multipart/alternative; boundary="_000_b6c0fdcc58b0404fac6f31fa40c6156fhuaweicom_" MIME-Version: 1.0 X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces~public-inbox=simark.ca@sourceware.org --_000_b6c0fdcc58b0404fac6f31fa40c6156fhuaweicom_ Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable 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=3D'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 =3D nframes - 1 - return re.match(name.string(), frame.name()) is not None + frame_name =3D frame.name() + return frame_name is not None and re.match(name.string(), frame_na= me) is not None class AnyCallerIs(gdb.Function): @@ -143,7 +144,8 @@ class AnyCallerMatches(gdb.Function): frame =3D gdb.selected_frame() name_re =3D re.compile(name.string()) while nframes >=3D 0: - if name_re.match(frame.name()) is not None: + frame_name =3D frame.name() + if frame_name is not None and name_re.match(frame_name) is not= None: return True frame =3D 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 =3D Mock()" "" \ + " frame.name.return_value =3D None" "" \ + " frame.older.return_value =3D gdb.selected_frame()" "" \ + " with patch.object(gdb, 'selected_frame', return_value=3Dframe):" = "" \ + " 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 --_000_b6c0fdcc58b0404fac6f31fa40c6156fhuaweicom_ Content-Type: text/html; charset="us-ascii" Content-Transfer-Encoding: quoted-printable

gdb.Frame.name() can return None when GDB cannot det= ermine a frame's

function name.   and  currently<= /o:p>

pass that value directly to Python's regular express= ion functions,

causing a TypeError.

 

Treat unnamed frames as non-matches.  For None,= keep

walking older frames after encountering an unnamed f= rame.

 

Add regression tests for both convenience functions.=

---

 

This is my first GDB contribution.

 

I used ChatGPT to help investigate the issue and dra= ft an initial

version of the patch (it's fairly simple but still w= orth mentioning).

I reviewed, simplified, and tested the final change = myself.

 

Tested with:

 

  make -C gdb check RUNTESTFLAGS=3D'gdb.python/= py-caller-is.exp'

 

gdb/python/lib/gdb/function/caller_is.py  |&nbs= p; 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.p= y b/gdb/python/lib/gdb/function/caller_is.py

index bca09590811..a2a5798b914 100644

--- a/gdb/python/lib/gdb/function/caller_is.py<= /o:p>

+++ b/gdb/python/lib/gdb/function/caller= _is.py

@@ -80,7 +80,8 @@ class CallerMatches(gdb.Functi= on):

        &nbs= p;    if frame is None:

        &nbs= p;        return False

        &nbs= p;    nframes =3D nframes - 1

-        return r= e.match(name.string(), frame.name()) is not None

+        fram= e_name =3D frame.name()

+        retu= rn frame_name is not None and re.match(name.string(), frame_name) is not No= ne

 

 

 class AnyCallerIs(gdb.Function):

@@ -143,7 +144,8 @@ class AnyCallerMatches(gdb.F= unction):

         fra= me =3D gdb.selected_frame()

         nam= e_re =3D re.compile(name.string())

         whi= le nframes >=3D 0:

-        &nb= sp;   if name_re.match(frame.name()) is not None:

+        = ;    frame_name =3D frame.name()

+        = ;    if frame_name is not None and name_re.match(frame_name)= is not None:

        &nbs= p;        return True

        &nbs= p;    frame =3D frame.older()

        &nbs= p;    if frame is None:

diff --git a/gdb/testsuite/gdb.python/py-caller-is.e= xp 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 librari= es.

+gdb_test_multiline "define unnamed frame h= elper" \

+    "python" "&qu= ot; \

+    "from unittest.mock imp= ort Mock, patch" "" \

+    "def check_unnamed_fram= e(expr):" "" \

+    "    fra= me =3D Mock()" "" \

+    "    fra= me.name.return_value =3D None" "" \

+    "    fra= me.older.return_value =3D gdb.selected_frame()" "" \

+    "    wit= h patch.object(gdb, 'selected_frame', return_value=3Dframe):" "&q= uot; \

+    "   &nbs= p;    print(int(gdb.parse_and_eval(expr)))" ""= ; \

+    "end" ""=

+

+gdb_test {python check_unnamed_frame('$_caller_= matches(".*", 0)')} \

+    "0" "caller_m= atches with unnamed frame"

+gdb_test {python check_unnamed_frame('$_any_cal= ler_matches(".*", 0)')} \

+    "0" "any_call= er_matches with unnamed frame"

+gdb_test {python check_unnamed_frame('$_any_cal= ler_matches("^bottom_func$", 1)')} \

+    "1" "any_call= er_matches skips unnamed frame"

--

2.34.1

 

--_000_b6c0fdcc58b0404fac6f31fa40c6156fhuaweicom_--