From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id YXatF31im2lpsgUAWB0awg (envelope-from ) for ; Sun, 22 Feb 2026 15:09:33 -0500 Authentication-Results: simark.ca; dkim=fail reason="signature verification failed" (768-bit key; unprotected) header.d=tromey.com header.i=@tromey.com header.a=rsa-sha256 header.s=default header.b=aX9ebpiT; dkim-atps=neutral Received: by simark.ca (Postfix, from userid 112) id 512341E0BA; Sun, 22 Feb 2026 15:09:33 -0500 (EST) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-25) on simark.ca X-Spam-Level: X-Spam-Status: No, score=-0.8 required=5.0 tests=ARC_SIGNED,ARC_VALID,BAYES_00, DKIM_INVALID,DKIM_SIGNED,MAILING_LIST_MULTI,RCVD_IN_BL_SPAMCOP_NET, RCVD_IN_DNSWL_MED,RCVD_IN_VALIDITY_CERTIFIED_BLOCKED, RCVD_IN_VALIDITY_RPBL_BLOCKED,RCVD_IN_VALIDITY_SAFE_BLOCKED autolearn=no autolearn_force=no version=4.0.1 Received: from vm01.sourceware.org (vm01.sourceware.org [38.145.34.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 F26C01E08D for ; Sun, 22 Feb 2026 15:09:31 -0500 (EST) Received: from vm01.sourceware.org (localhost [127.0.0.1]) by sourceware.org (Postfix) with ESMTP id 5FF564BA23D7 for ; Sun, 22 Feb 2026 20:09:31 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 5FF564BA23D7 Authentication-Results: sourceware.org; dkim=fail reason="signature verification failed" (768-bit key, unprotected) header.d=tromey.com header.i=@tromey.com header.a=rsa-sha256 header.s=default header.b=aX9ebpiT Received: from omta036.useast.a.cloudfilter.net (omta036.useast.a.cloudfilter.net [44.202.169.35]) by sourceware.org (Postfix) with ESMTPS id B8D034BA23CF for ; Sun, 22 Feb 2026 20:08:14 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org B8D034BA23CF Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=tromey.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=tromey.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org B8D034BA23CF Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=44.202.169.35 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1771790894; cv=none; b=HrTs2aFbKExdg7OTIhSVWEHYpYnzjb9ubs3B1yO0Kc/9NhN6Uo0jx5oAWIrpQAnKemB+i0y962MDYxhtlH45jf70oRKhbR9Me4RoQh6aanFO5hsMIfVgwIcYtnQ2NiAzH28Ow6l/Ti1RAMuS9yiTWzVtqW4UB45Ozecut0dRSwE= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1771790894; c=relaxed/simple; bh=HgMcwXKBhkmia77SEga97lTZ46+zQCWvF2hB6udT128=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=E9apa5uBzb2cfQlYfYDEYM24dey2cAuEEl2/+jaWRKneA2MAmHWaARSBCm80wTc7Ygw8zt/yALYS8sMJ3J0sr+pnfLDKtWJiohrlp7TtVLGAmRg+z5YExpolvr/WsCSgNIcUI4XXRFGI6d6i2uj9RkMHnbCmBUXci7UMHH6nA04= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org B8D034BA23CF Received: from eig-obgw-6005b.ext.cloudfilter.net ([10.0.30.162]) by cmsmtp with ESMTPS id tnWcvDEGzKXDJuFkUv7EaD; Sun, 22 Feb 2026 20:08:14 +0000 Received: from box5379.bluehost.com ([162.241.216.53]) by cmsmtp with ESMTPS id uFkTvIDScHSQMuFkTv1y7n; Sun, 22 Feb 2026 20:08:13 +0000 X-Authority-Analysis: v=2.4 cv=GIQIEvNK c=1 sm=1 tr=0 ts=699b622d a=ApxJNpeYhEAb1aAlGBBbmA==:117 a=ApxJNpeYhEAb1aAlGBBbmA==:17 a=HzLeVaNsDn8A:10 a=ItBw4LHWJt0A:10 a=mDV3o1hIAAAA:8 a=TQzmjlG3JMCGRRZmcD0A:9 a=DCx65vhANUyCzuf5D8fC:22 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=tromey.com; s=default; h=Content-Transfer-Encoding:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:Cc:To:From:Sender:Reply-To:Content-Type:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=tmAgFvikwMMZuEKVzDjRxJ+aJeSNKaMpCUZC5FP1lQY=; b=aX9ebpiTEr7SVqqHuaOyrXwZFR WCJb51ctKNQsmBurO0WBYc12hcj1Cfn7oKXJjLTnSFVZiyR53fXEr1wUR2ScPWd1LeNKoctIw0YhF kcE7aHlR81TAHg1cS+gLmGu8z; Received: from 97-122-122-234.hlrn.qwest.net ([97.122.122.234]:37760 helo=localhost.localdomain) by box5379.bluehost.com with esmtpsa (TLS1.3) tls TLS_AES_256_GCM_SHA384 (Exim 4.98.2) (envelope-from ) id 1vuFkT-00000003hGc-0lXC; Sun, 22 Feb 2026 13:08:13 -0700 From: Tom Tromey To: gdb-patches@sourceware.org Cc: Tom Tromey Subject: [RFC 2/4] Add wrappers for some Python APIs Date: Sun, 22 Feb 2026 12:49:35 -0700 Message-ID: <20260222200759.1587070-3-tom@tromey.com> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20260222200759.1587070-1-tom@tromey.com> References: <20260222200759.1587070-1-tom@tromey.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-AntiAbuse: This header was added to track abuse, please include it with any abuse report X-AntiAbuse: Primary Hostname - box5379.bluehost.com X-AntiAbuse: Original Domain - sourceware.org X-AntiAbuse: Originator/Caller UID/GID - [47 12] / [47 12] X-AntiAbuse: Sender Address Domain - tromey.com X-BWhitelist: no X-Source-IP: 97.122.122.234 X-Source-L: No X-Exim-ID: 1vuFkT-00000003hGc-0lXC X-Source: X-Source-Args: X-Source-Dir: X-Source-Sender: 97-122-122-234.hlrn.qwest.net (localhost.localdomain) [97.122.122.234]:37760 X-Source-Auth: tom+tromey.com X-Email-Count: 3 X-Org: HG=bhshared;ORG=bluehost; X-Source-Cap: ZWx5bnJvYmk7ZWx5bnJvYmk7Ym94NTM3OS5ibHVlaG9zdC5jb20= X-Local-Domain: yes X-CMAE-Envelope: MS4xfIpWfaiOA8Do2CDW4fr5X4DkXWFMeo0cRkiIbz65KOBlsfRKTBAWBcVqfVeYGpMxcFCXJ5IA/baOobMNY5cg/oezbsd5HkP8U+OJjFEU76wrxDDduZUx DkYQdCgwNuWZ9mTbRaUK697c0vSsGqYm4pW05FMYhCkCdj2dLjQpfptEt3D8/TsbTWeImEJgx7GGxkzCB2bzD4rMw7MxntHcQ/U= 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 This adds some new functions that wrap Python APIs. The wrapping follows some proposed rules for Python safety in gdb: * Functions returning a new reference return gdbpy_ref<>; * Errors are reported via exceptions, not special values; * Functions accepting a stolen reference take a gdbpy_ref<>&& (there aren't any of these yet) --- gdb/python/py-wrappers.h | 163 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100644 gdb/python/py-wrappers.h diff --git a/gdb/python/py-wrappers.h b/gdb/python/py-wrappers.h new file mode 100644 index 00000000000..6471012a75a --- /dev/null +++ b/gdb/python/py-wrappers.h @@ -0,0 +1,163 @@ +/* Wrappers for some Python safety. + + Copyright (C) 2026 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef GDB_PYTHON_PY_WRAPPERS_H +#define GDB_PYTHON_PY_WRAPPERS_H + +#include "py-ref.h" + +/* Gdb implements its own wrappers for many Python APIs. This is done + in an attempt to be more safe. + + In particular, in gdb: + + - APIs returning a new reference will return gdbpy_ref<>. This + makes reference counting errors less likely. + + - APIs will throw an exception rather than return a special value + (NULL or -1). This makes error checking simpler. + + - APIs requiring a stolen reference take a gdbpy_ref<>&&, to make + this more type-safe. + + This file holds the currently-defined wrappers. If new APIs are + needed, the normal approach is to add a wrapper here. + + APIs here are named after the underlying Python function, but using + lower case and an "_" at each word break. */ + +/* The type of exception thrown when the Python exception has been + set. */ +struct gdb_python_exception +{ + gdb_python_exception () + { + gdb_assert (PyErr_Occurred ()); + } +}; + +template +gdbpy_ref +gdbpy_new () +{ + gdbpy_ref result (PyObject_New (T, T::corresponding_object_type)); + if (result == nullptr) + throw gdb_python_exception (); + return result; +} + +static inline gdbpy_ref<> +gdbpy_new_list (Py_ssize_t len) +{ + gdbpy_ref<> result (PyList_New (len)); + if (result == nullptr) + throw gdb_python_exception (); + return result; +} + +static inline void +gdbpy_list_append (gdbpy_borrowed_ref list, gdbpy_borrowed_ref val) +{ + if (PyList_Append (list, val) < 0) + throw gdb_python_exception (); +} + +static inline gdbpy_ref<> +gdbpy_new_dict () +{ + gdbpy_ref<> result (PyDict_New ()); + if (result == nullptr) + throw gdb_python_exception (); + return result; +} + +static inline void +gdbpy_dict_set_item_string (gdbpy_borrowed_ref dict, + const char *key, + gdbpy_borrowed_ref value) +{ + if (PyDict_SetItemString (dict, key, value) != 0) + throw gdb_python_exception (); +} + +static inline gdbpy_ref<> +gdbpy_unicode_from_string (const char *str) +{ + gdbpy_ref<> result (PyUnicode_FromString (str)); + if (result == nullptr) + throw gdb_python_exception (); + return result; +} + +static inline gdbpy_ref<> +gdbpy_unicode_from_format (const char *fmt, ...) +{ + va_list args; + va_start (args, fmt); + gdbpy_ref<> result (PyUnicode_FromFormatV (fmt, args)); + if (result == nullptr) + throw gdb_python_exception (); + va_end (args); + return result; +} + +[[noreturn]] static inline void +gdbpy_err_set_string (PyObject *type, const char *str) +{ + PyErr_SetString (type, str); + throw gdb_python_exception (); +} + +/* This is a template because PyErr_FormatV was only added in Python + 3.5. */ +template +[[noreturn]] void +gdbpy_err_format (PyObject *type, const char *fmt, Arg... args) +{ + PyErr_Format (type, fmt, std::forward (args)...); + throw gdb_python_exception (); +} + +template +void +gdbpy_arg_parse_tuple_and_keywords (gdbpy_borrowed_ref args, + gdbpy_borrowed_ref kw, + const char *fmt, + const char **keywords, + Arg... outputs) +{ + /* It would be cool if callers could use references to the + out-parameters and also if gdbpy_borrowed_ref could be used for + those. That requires some hairy template metaprogramming + though. */ + if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, fmt, keywords, + std::forward (outputs)...)) + throw gdb_python_exception (); +} + +static inline long +gdbpy_long_as_long (gdbpy_borrowed_ref arg) +{ + long result = PyLong_AsLong (arg); + if (result == -1 && PyErr_Occurred ()) + throw gdb_python_exception (); + return result; +} + +#endif /* GDB_PYTHON_PY_WRAPPERS_H */ -- 2.49.0