From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id y0qSImB0d2rx0hQAWB0awg (envelope-from ) for ; Sat, 08 Aug 2026 14:24:32 -0400 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=E3xsfkOa; dkim-atps=neutral Received: by simark.ca (Postfix, from userid 112) id 7BFE81E166; Sat, 08 Aug 2026 14:24:32 -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.1 required=5.0 tests=ARC_SIGNED,ARC_VALID,BAYES_00, DKIM_INVALID,DKIM_SIGNED,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 91D111E09B for ; Sat, 08 Aug 2026 14:24:30 -0400 (EDT) Received: from vm01.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 2F2D14BA79BA for ; Sat, 8 Aug 2026 18:24:23 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 2F2D14BA79BA 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=E3xsfkOa Received: from omta040.useast.a.cloudfilter.net (omta040.useast.a.cloudfilter.net [44.202.169.39]) by sourceware.org (Postfix) with ESMTPS id 700AE4BA23DC for ; Sat, 8 Aug 2026 18:23:53 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 700AE4BA23DC 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 700AE4BA23DC Authentication-Results: sourceware.org; arc=none smtp.remote-ip=44.202.169.39 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1786213433; cv=none; b=ASWSNZ7jMk/GBkn7Cjt+1ZyyL1P7NXA7X3NQvVt+AQRrsNvuO0PiKozLrNgQilsDHXi9sRS8tz84mTtTPHwLzTkexYOy90g1ZJZrVdIUUNs14AV41c2ozfb8SH3/jwgZ8af/JzmncTNOw955L0dYjWuXaahALFE/IAP3Hdm4eQQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1786213433; c=relaxed/simple; bh=sPtxkaIyBntcligk9HHD4vyCXXcOUcpI1olVwRAzDZY=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=I2OnxchDDYmUOaqW9A09UgZxn0IoPm8y9CGH7HBycWNNckkF9M/uRmqPJaG7bNW50BI6XWa2CCIcYolNNO5mnIOwzXJnbEFJ68Lt5vcDGavqKLT3kz51inMywRHBoq7I5uENaztRlQ++hmIncndMtjoW5prc/PEbZyYe3Vfn8bE= ARC-Authentication-Results: i=1; sourceware.org; dkim=policy (768-bit key, unprotected) header.d=tromey.com header.i=@tromey.com header.a=rsa-sha256 header.s=default header.b=E3xsfkOa reason="signing key too small" DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 700AE4BA23DC Received: from eig-obgw-6002b.ext.cloudfilter.net ([10.0.30.203]) by cmsmtp with ESMTPS id sNvPwbejluFzgsli4wrH8d; Sat, 08 Aug 2026 18:23:53 +0000 Received: from box5379.bluehost.com ([162.241.216.53]) by cmsmtp with ESMTPS id sli4w828TRY4Isli4wYtq7; Sat, 08 Aug 2026 18:23:52 +0000 X-Authority-Analysis: v=2.4 cv=WNl/XmsR c=1 sm=1 tr=0 ts=6a777438 a=ApxJNpeYhEAb1aAlGBBbmA==:117 a=ApxJNpeYhEAb1aAlGBBbmA==:17 a=Sv0fKeRqtYgA:10 a=ItBw4LHWJt0A:10 a=jgXFTg0ZnfDVbEUB6xwA:9 a=3ZKOabzyN94A:10 a=O8hF6Hzn-FEA:10 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: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: In-Reply-To:References:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=1arSArz3PR15cLqihjIf7GSHcudM1hz1GfEnq+kOwxQ=; b=E3xsfkOa/6IQD8YXd1iQMomSYm 6laRwBMxU/h+IM9mFBOjievilB2yWnZ5CH9RzYa0mWXwXo7J+gEGxpBHiDzOmRRQ5zVQkQCfrvEoO ERWPqdhWqU/G4aWk6ggsVBl0/; Received: from 75-166-225-82.hlrn.qwest.net ([75.166.225.82]:52036 helo=localhost.localdomain) by box5379.bluehost.com with esmtpsa (TLS1.3) tls TLS_AES_256_GCM_SHA384 (Exim 4.99.5) (envelope-from ) id 1wsli2-000000036E0-46Vl; Sat, 08 Aug 2026 12:23:51 -0600 From: Tom Tromey To: gdb-patches@sourceware.org Cc: Tom Tromey Subject: [PATCH] Convert py-arch.c to "safety" approach Date: Sat, 8 Aug 2026 12:23:39 -0600 Message-ID: <20260808182339.3936136-1-tom@tromey.com> X-Mailer: git-send-email 2.49.0 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: 75.166.225.82 X-Source-L: No X-Exim-ID: 1wsli2-000000036E0-46Vl X-Source: X-Source-Args: X-Source-Dir: X-Source-Sender: 75-166-225-82.hlrn.qwest.net (localhost.localdomain) [75.166.225.82]:52036 X-Source-Auth: tom+tromey.com X-Email-Count: 1 X-Org: HG=bhshared;ORG=bluehost; X-Source-Cap: ZWx5bnJvYmk7ZWx5bnJvYmk7Ym94NTM3OS5ibHVlaG9zdC5jb20= X-Local-Domain: yes X-CMAE-Envelope: MS4xfA1eoOMGdvMF1KW5KdQBQ7bSMr3ho0FUcZwumbbLTYY+NPpLh0QWtJUZY9Wmi5g8qQ9KFNWOnttLkWRzEB5skbvt2ULH8Cq6+iM1ljTfkHpXN+vzHdFo Hp45yJxV0IB9xFwQcVofzy3VvB/JH8m/D+ZvSGmAfqPjE1yCgvb97lcJgqZZ7BDU7a1j2Xm0CMWhU9i26BxGen8lQcpot99F+AM= 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 patch converts py-arch.c to the new Python safety approach. A few changes outside this file were also needed: some updates to py-register.c (changing some functions that are only called from py-arch.c), the new noargs_function template, and the use of a wrapper in python.c. Regression tested on x86-64 Fedora 40. --- gdb/python/py-arch.c | 306 +++++++++++++++-------------------- gdb/python/py-registers.c | 39 ++--- gdb/python/py-safety.h | 26 +++ gdb/python/py-wrappers.h | 11 ++ gdb/python/python-internal.h | 8 +- gdb/python/python.c | 4 +- 6 files changed, 189 insertions(+), 205 deletions(-) diff --git a/gdb/python/py-arch.c b/gdb/python/py-arch.c index 5b3cfbdc876..51dfcb97b36 100644 --- a/gdb/python/py-arch.c +++ b/gdb/python/py-arch.c @@ -25,6 +25,56 @@ struct arch_object : public PyObject { struct gdbarch *gdbarch; + + /* Return the gdbarch associated with OBJ. Throws an exception on + error. */ + struct gdbarch *require () + { + if (gdbarch == nullptr) + gdbpy_err_set_string (PyExc_RuntimeError, _("Architecture is invalid.")); + return gdbarch; + } + + /* Implementation of gdb.Architecture.name (self) -> String. + Returns the name of the architecture as a string value. */ + const char *name () + { + return gdbarch_bfd_arch_info (require ())->printable_name; + } + + /* __repr__ implementation for gdb.Architecture. */ + gdbpy_ref<> repr (); + + /* Implementation of gdb.void_type. */ + gdbpy_ref<> void_type () + { + return type_to_type_object (builtin_type (require ())->builtin_void); + } + + /* Implementation of gdb.Architecture.register_groups (self) -> Iterator. + Returns an iterator that will give up all valid register groups in the + architecture SELF. */ + gdbpy_ref<> register_groups () + { + return gdbpy_new_reggroup_iterator (require ()); + } + + /* Implementation of + gdb.Architecture.disassemble (self, start_pc [, end_pc [,count]]) -> List. + Returns a list of instructions in a memory address range. Each instruction + in the list is a Python dict object. */ + gdbpy_ref<> disassemble (gdbpy_borrowed_ref<> args, + gdbpy_opt_borrowed_ref<> kw); + + /* Implementation of gdb.integer_type. */ + gdbpy_ref<> integer_type (gdbpy_borrowed_ref<> args, + gdbpy_opt_borrowed_ref<> kw); + + /* Implementation of gdb.Architecture.registers (self, reggroup) -> + Iterator. Returns an iterator over register descriptors for + registers in GROUP within the architecture SELF. */ + gdbpy_ref<> registers (gdbpy_borrowed_ref<> args, + gdbpy_opt_borrowed_ref<> kw); }; static_assert (gdb::is_python_allocatable_v); @@ -32,18 +82,6 @@ static_assert (gdb::is_python_allocatable_v); static const registry::key> arch_object_data; -/* Require a valid Architecture. */ -#define ARCHPY_REQUIRE_VALID(arch_obj, arch) \ - do { \ - arch = arch_object_to_gdbarch (arch_obj); \ - if (arch == NULL) \ - { \ - PyErr_SetString (PyExc_RuntimeError, \ - _("Architecture is invalid.")); \ - return NULL; \ - } \ - } while (0) - extern PyTypeObject arch_object_type; /* Associates an arch_object with GDBARCH as gdbarch_data via the gdbarch @@ -102,80 +140,46 @@ gdbarch_to_arch_object (struct gdbarch *gdbarch) return gdbpy_ref<> (new_ref); } -/* Implementation of gdb.Architecture.name (self) -> String. - Returns the name of the architecture as a string value. */ - -static PyObject * -archpy_name (PyObject *self, PyObject *args) -{ - struct gdbarch *gdbarch = NULL; - const char *name; - - ARCHPY_REQUIRE_VALID (self, gdbarch); - - name = (gdbarch_bfd_arch_info (gdbarch))->printable_name; - return PyUnicode_FromString (name); -} - -/* Implementation of - gdb.Architecture.disassemble (self, start_pc [, end_pc [,count]]) -> List. - Returns a list of instructions in a memory address range. Each instruction - in the list is a Python dict object. -*/ - -static PyObject * -archpy_disassemble (PyObject *self, PyObject *args, PyObject *kw) +gdbpy_ref<> +arch_object::disassemble (gdbpy_borrowed_ref<> args, + gdbpy_opt_borrowed_ref<> kw) { static const char *keywords[] = { "start_pc", "end_pc", "count", "styling", nullptr }; - CORE_ADDR start = 0, end = 0; CORE_ADDR pc; long count = 0, i; PyObject *start_obj = nullptr, *end_obj = nullptr, *count_obj = nullptr; - struct gdbarch *gdbarch = NULL; int styling_p = 0; - ARCHPY_REQUIRE_VALID (self, gdbarch); + struct gdbarch *gdbarch = require (); - if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "O|OOp", - keywords, &start_obj, &end_obj, - &count_obj, &styling_p)) - return NULL; + gdbpy_arg_parse_tuple_and_keywords (args, kw, "O|OOp", + keywords, &start_obj, &end_obj, + &count_obj, &styling_p); - if (get_addr_from_python (start_obj, &start) < 0) - return nullptr; + CORE_ADDR start = gdbpy_get_address (start_obj); + CORE_ADDR end = 0; if (end_obj != nullptr) { - if (get_addr_from_python (end_obj, &end) < 0) - return nullptr; + end = gdbpy_get_address (end_obj); if (end < start) - { - PyErr_SetString (PyExc_ValueError, - _("Argument 'end_pc' should be greater than or " - "equal to the argument 'start_pc'.")); - - return NULL; - } + gdbpy_err_set_string (PyExc_ValueError, + _("Argument 'end_pc' should be greater than or " + "equal to the argument 'start_pc'.")); } if (count_obj) { - count = PyLong_AsLong (count_obj); - if (PyErr_Occurred () || count < 0) - { - PyErr_SetString (PyExc_TypeError, - _("Argument 'count' should be an non-negative " - "integer.")); - - return NULL; - } + count = gdbpy_long_as_long (count_obj); + if (count < 0) + gdbpy_err_set_string (PyExc_TypeError, + _("Argument 'count' should be an non-negative " + "integer.")); } - gdbpy_ref<> result_list (PyList_New (0)); - if (result_list == NULL) - return NULL; + gdbpy_ref<> result_list = gdbpy_new_list (0); for (pc = start, i = 0; /* All args are specified. */ @@ -187,105 +191,72 @@ archpy_disassemble (PyObject *self, PyObject *args, PyObject *kw) /* Both end_pc and count are not specified. */ || (end_obj == NULL && count_obj == NULL && pc == start);) { - int insn_len = 0; - gdbpy_ref<> insn_dict (PyDict_New ()); + gdbpy_ref<> insn_dict = gdbpy_new_dict (); - if (insn_dict == NULL) - return NULL; - if (PyList_Append (result_list.get (), insn_dict.get ())) - return NULL; /* PyList_Append Sets the exception. */ + gdbpy_list_append (result_list, insn_dict); string_file stb (styling_p); + int insn_len = gdb_print_insn (gdbarch, pc, &stb, NULL); - try - { - insn_len = gdb_print_insn (gdbarch, pc, &stb, NULL); - } - catch (const gdb_exception &except) - { - return gdbpy_handle_gdb_exception (nullptr, except); - } - + /* FIXME: Python safety. Eventually gdb_py_object_from_ulongest + should throw. */ gdbpy_ref<> pc_obj = gdb_py_object_from_ulongest (pc); if (pc_obj == nullptr) - return nullptr; + throw gdb_python_exception (); - gdbpy_ref<> asm_obj - (PyUnicode_FromString (!stb.empty () ? stb.c_str () : "")); - if (asm_obj == nullptr) - return nullptr; + gdbpy_ref<> asm_obj = gdbpy_unicode_from_string (!stb.empty () + ? stb.c_str () + : ""); + /* FIXME: Python safety. Eventually gdb_py_object_from_longest + should throw. */ gdbpy_ref<> len_obj = gdb_py_object_from_longest (insn_len); if (len_obj == nullptr) - return nullptr; + throw gdb_python_exception (); - if (PyDict_SetItemString (insn_dict.get (), "addr", pc_obj.get ()) - || PyDict_SetItemString (insn_dict.get (), "asm", asm_obj.get ()) - || PyDict_SetItemString (insn_dict.get (), "length", len_obj.get ())) - return NULL; + gdbpy_dict_set_item_string (insn_dict, "addr", pc_obj); + gdbpy_dict_set_item_string (insn_dict, "asm", asm_obj); + gdbpy_dict_set_item_string (insn_dict, "length", len_obj); pc += insn_len; i++; } - return result_list.release (); + return result_list; } -/* Implementation of gdb.Architecture.registers (self, reggroup) -> Iterator. - Returns an iterator over register descriptors for registers in GROUP - within the architecture SELF. */ - -static PyObject * -archpy_registers (PyObject *self, PyObject *args, PyObject *kw) +gdbpy_ref<> +arch_object::registers (gdbpy_borrowed_ref<> args, + gdbpy_opt_borrowed_ref<> kw) { static const char *keywords[] = { "reggroup", NULL }; - struct gdbarch *gdbarch = NULL; const char *group_name = NULL; /* Parse method arguments. */ - if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "|s", keywords, - &group_name)) - return NULL; + gdbpy_arg_parse_tuple_and_keywords (args, kw, "|s", keywords, &group_name); /* Extract the gdbarch from the self object. */ - ARCHPY_REQUIRE_VALID (self, gdbarch); + struct gdbarch *gdbarch = require (); return gdbpy_new_register_descriptor_iterator (gdbarch, group_name); } -/* Implementation of gdb.Architecture.register_groups (self) -> Iterator. - Returns an iterator that will give up all valid register groups in the - architecture SELF. */ - -static PyObject * -archpy_register_groups (PyObject *self, PyObject *args) -{ - struct gdbarch *gdbarch = NULL; - - /* Extract the gdbarch from the self object. */ - ARCHPY_REQUIRE_VALID (self, gdbarch); - return gdbpy_new_reggroup_iterator (gdbarch); -} - -/* Implementation of gdb.integer_type. */ -static PyObject * -archpy_integer_type (PyObject *self, PyObject *args, PyObject *kw) +gdbpy_ref<> +arch_object::integer_type (gdbpy_borrowed_ref<> args, + gdbpy_opt_borrowed_ref<> kw) { static const char *keywords[] = { "size", "signed", NULL }; int size; PyObject *is_signed_obj = Py_True; - if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "i|O!", keywords, - &size, - &PyBool_Type, &is_signed_obj)) - return nullptr; + gdbpy_arg_parse_tuple_and_keywords (args, kw, "i|O!", keywords, &size, + &PyBool_Type, &is_signed_obj); /* Assume signed by default. */ gdb_assert (PyBool_Check (is_signed_obj)); bool is_signed = is_signed_obj == Py_True; - struct gdbarch *gdbarch; - ARCHPY_REQUIRE_VALID (self, gdbarch); + struct gdbarch *gdbarch = require (); const struct builtin_type *builtins = builtin_type (gdbarch); struct type *type = nullptr; @@ -314,61 +285,41 @@ archpy_integer_type (PyObject *self, PyObject *args, PyObject *kw) break; default: - PyErr_SetString (PyExc_ValueError, - _("no integer type of that size is available")); - return nullptr; + gdbpy_err_set_string (PyExc_ValueError, + _("no integer type of that size is available")); } - return type_to_type_object (type).release (); + return type_to_type_object (type); } -/* Implementation of gdb.void_type. */ -static PyObject * -archpy_void_type (PyObject *self, PyObject *args) -{ - struct gdbarch *gdbarch; - ARCHPY_REQUIRE_VALID (self, gdbarch); - - return type_to_type_object (builtin_type (gdbarch)->builtin_void).release (); -} - -/* __repr__ implementation for gdb.Architecture. */ - -static PyObject * -archpy_repr (PyObject *self) +gdbpy_ref<> +arch_object::repr () { - const auto gdbarch = arch_object_to_gdbarch (self); if (gdbarch == nullptr) - return gdb_py_invalid_object_repr (self); + /* FIXME: Python safety. Eventually gdb_py_invalid_object_repr + should throw. */ + return gdbpy_ref<> (gdb_py_invalid_object_repr (this)); auto arch_info = gdbarch_bfd_arch_info (gdbarch); - return PyUnicode_FromFormat ("<%s arch_name=%s printable_name=%s>", - gdbpy_py_obj_tp_name (self).c_str (), - arch_info->arch_name, - arch_info->printable_name); + return gdbpy_unicode_from_format ("<%s arch_name=%s printable_name=%s>", + gdbpy_py_obj_tp_name (this).c_str (), + arch_info->arch_name, + arch_info->printable_name); } /* Implementation of gdb.architecture_names(). Return a list of all the BFD architecture names that GDB understands. */ -PyObject * -gdbpy_all_architecture_names (PyObject *self, PyObject *args) +gdbpy_ref<> +gdbpy_all_architecture_names () { - gdbpy_ref<> list (PyList_New (0)); - if (list == nullptr) - return nullptr; + gdbpy_ref<> list = gdbpy_new_list (0); std::vector name_list = gdbarch_printable_names (); for (const char *name : name_list) - { - gdbpy_ref <> py_name (PyUnicode_FromString (name)); - if (py_name == nullptr) - return nullptr; - if (PyList_Append (list.get (), py_name.get ()) < 0) - return nullptr; - } + gdbpy_list_append (list, gdbpy_unicode_from_string (name)); - return list.release (); + return list; } /* Initializes the Architecture class in the gdb module. */ @@ -385,32 +336,27 @@ GDBPY_INITIALIZE_FILE (gdbpy_initialize_arch); static PyMethodDef arch_object_methods [] = { - { "name", archpy_name, METH_NOARGS, + noargs_method ("name", "name () -> String.\n\ -Return the name of the architecture as a string value." }, - { "disassemble", (PyCFunction) archpy_disassemble, - METH_VARARGS | METH_KEYWORDS, +Return the name of the architecture as a string value."), + varargs_method ("disassemble", "disassemble (start_pc [, end_pc [, count]]) -> List.\n\ Return a list of at most COUNT disassembled instructions from START_PC to\n\ -END_PC." }, - { "integer_type", (PyCFunction) archpy_integer_type, - METH_VARARGS | METH_KEYWORDS, +END_PC."), + varargs_method ("integer_type", "integer_type (size [, signed]) -> type\n\ Return an integer Type corresponding to the given bitsize and signed-ness.\n\ -If not specified, the type defaults to signed." }, - { "void_type", (PyCFunction) archpy_void_type, - METH_NOARGS, +If not specified, the type defaults to signed."), + noargs_method ("void_type", "void_type () -> type\n\ -Return a void Type." }, - { "registers", (PyCFunction) archpy_registers, - METH_VARARGS | METH_KEYWORDS, +Return a void Type."), + varargs_method ("registers", "registers ([ group-name ]) -> Iterator.\n\ Return an iterator of register descriptors for the registers in register\n\ -group GROUP-NAME." }, - { "register_groups", archpy_register_groups, - METH_NOARGS, +group GROUP-NAME."), + noargs_method ("register_groups", "register_groups () -> Iterator.\n\ -Return an iterator over all of the register groups in this architecture." }, +Return an iterator over all of the register groups in this architecture."), {NULL} /* Sentinel */ }; @@ -424,7 +370,7 @@ PyTypeObject arch_object_type = { 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ - archpy_repr, /* tp_repr */ + wrap_tp_callback, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ diff --git a/gdb/python/py-registers.c b/gdb/python/py-registers.c index e0180660715..80a57207b0a 100644 --- a/gdb/python/py-registers.c +++ b/gdb/python/py-registers.c @@ -43,6 +43,8 @@ struct register_descriptor_iterator_object : public PyObject /* Pointer back to the architecture we're finding registers for. */ struct gdbarch *gdbarch; + + static PyTypeObject *corresponding_object_type; }; static_assert (gdb::is_python_allocatable_v); @@ -71,6 +73,8 @@ struct reggroup_iterator_object : public PyObject /* Pointer back to the architecture we're finding registers for. */ struct gdbarch *gdbarch; + + static PyTypeObject *corresponding_object_type; }; static_assert (gdb::is_python_allocatable_v); @@ -231,20 +235,17 @@ gdbpy_reggroup_iter_next (PyObject *self) /* Return a new gdb.RegisterGroupsIterator over all the register groups in GDBARCH. */ -PyObject * +gdbpy_ref<> gdbpy_new_reggroup_iterator (struct gdbarch *gdbarch) { gdb_assert (gdbarch != nullptr); /* Create a new object and fill in its internal state. */ - reggroup_iterator_object *iter - = PyObject_New (reggroup_iterator_object, - ®group_iterator_object_type); - if (iter == NULL) - return NULL; + gdbpy_ref iter + = gdbpy_new (); iter->index = 0; iter->gdbarch = gdbarch; - return (PyObject *) iter; + return iter; } /* Create and return a new gdb.RegisterDescriptorIterator object which @@ -255,7 +256,7 @@ gdbpy_new_reggroup_iterator (struct gdbarch *gdbarch) This function can return NULL if GROUP_NAME isn't found. */ -PyObject * +gdbpy_ref<> gdbpy_new_register_descriptor_iterator (struct gdbarch *gdbarch, const char *group_name) { @@ -268,25 +269,19 @@ gdbpy_new_register_descriptor_iterator (struct gdbarch *gdbarch, { grp = reggroup_find (gdbarch, group_name); if (grp == NULL) - { - PyErr_SetString (PyExc_ValueError, - _("Unknown register group name.")); - return NULL; - } + gdbpy_err_set_string (PyExc_ValueError, + _("Unknown register group name.")); } /* Create a new iterator object initialised for this architecture and fill in all of the details. */ - register_descriptor_iterator_object *iter - = PyObject_New (register_descriptor_iterator_object, - ®ister_descriptor_iterator_object_type); - if (iter == NULL) - return NULL; + gdbpy_ref iter + = gdbpy_new (); iter->regnum = 0; iter->gdbarch = gdbarch; gdb_assert (grp != NULL); iter->reggroup = grp; - return (PyObject *) iter; + return iter; } /* Return a reference to the gdb.RegisterDescriptorIterator object. */ @@ -494,6 +489,9 @@ PyTypeObject register_descriptor_iterator_object_type = { register_descriptor_iterator_object_methods /*tp_methods */ }; +PyTypeObject *register_descriptor_iterator_object::corresponding_object_type + = ®ister_descriptor_iterator_object_type; + static gdb_PyGetSetDef gdbpy_register_descriptor_getset[] = { { "name", gdbpy_register_descriptor_name, NULL, "The name of this register.", NULL }, @@ -564,6 +562,9 @@ PyTypeObject reggroup_iterator_object_type = { 0 /*tp_methods */ }; +PyTypeObject *reggroup_iterator_object::corresponding_object_type + = ®group_iterator_object_type; + static gdb_PyGetSetDef gdbpy_reggroup_getset[] = { { "name", gdbpy_reggroup_name, NULL, "The name of this register group.", NULL }, diff --git a/gdb/python/py-safety.h b/gdb/python/py-safety.h index 3294f38c8b6..d47a34b760f 100644 --- a/gdb/python/py-safety.h +++ b/gdb/python/py-safety.h @@ -233,6 +233,32 @@ varargs_wrapper (PyObject *self, PyObject *args, PyObject *kw) } /* namespace safety_details */ +/* Create a PyMethodDef for a no-argument function. It takes the + takes the underlying implementation function as a template + argument, and also arguments for the method name and documentation + string. + + The underlying function should take no arguments. + + The function can return any type (see the to_python overloads); and + should throw an exception on error. If gdb_python_exception is + thrown, the Python exception must already have been set. */ +template +constexpr PyMethodDef +noargs_function (const char *name, const char *doc) +{ + using namespace safety_details; + return { + name, + [] (PyObject *self, PyObject *args) -> PyObject * + { + return wrapped_function (); + }, + METH_NOARGS, + doc, + }; +} + /* Create a PyMethodDef for a no-argument method. It takes the underlying class C and a pointer-to-method M as template parameters, and the name and documentation as arguments. The diff --git a/gdb/python/py-wrappers.h b/gdb/python/py-wrappers.h index 6c2b5e4d41e..d45682d1ddb 100644 --- a/gdb/python/py-wrappers.h +++ b/gdb/python/py-wrappers.h @@ -358,4 +358,15 @@ gdbpy_sequence_concat (gdbpy_borrowed_ref<> first, gdbpy_borrowed_ref<> second) return result; } +/* A wrapper for get_addr_from_python that returns the address or + throws an exception. */ +static inline CORE_ADDR +gdbpy_get_address (gdbpy_borrowed_ref<> obj) +{ + CORE_ADDR result; + if (get_addr_from_python (obj, &result) < 0) + throw gdb_python_exception (); + return result; +} + #endif /* GDB_PYTHON_PY_WRAPPERS_H */ diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h index 1165f165e29..a91ae4957a1 100644 --- a/gdb/python/python-internal.h +++ b/gdb/python/python-internal.h @@ -525,11 +525,11 @@ PyObject *objfpy_get_xmethods (PyObject *, void *); PyObject *gdbpy_lookup_objfile (PyObject *self, PyObject *args, PyObject *kw); gdbpy_ref<> gdbarch_to_arch_object (struct gdbarch *gdbarch); -PyObject *gdbpy_all_architecture_names (PyObject *self, PyObject *args); +gdbpy_ref<> gdbpy_all_architecture_names (); -PyObject *gdbpy_new_register_descriptor_iterator (struct gdbarch *gdbarch, - const char *group_name); -PyObject *gdbpy_new_reggroup_iterator (struct gdbarch *gdbarch); +gdbpy_ref<> gdbpy_new_register_descriptor_iterator (struct gdbarch *gdbarch, + const char *group_name); +gdbpy_ref<> gdbpy_new_reggroup_iterator (struct gdbarch *gdbarch); gdbpy_ref create_thread_object (struct thread_info *tp); gdbpy_ref<> thread_to_thread_object (thread_info *thr);; diff --git a/gdb/python/python.c b/gdb/python/python.c index 7b5de98b903..563b212fb43 100644 --- a/gdb/python/python.c +++ b/gdb/python/python.c @@ -3279,9 +3279,9 @@ Set the value of the convenience variable $NAME." }, Register a TUI window constructor."), #endif /* TUI */ - { "architecture_names", gdbpy_all_architecture_names, METH_NOARGS, + noargs_function ("architecture_names", "architecture_names () -> List.\n\ -Return a list of all the architecture names GDB understands." }, +Return a list of all the architecture names GDB understands."), { "connections", gdbpy_connections, METH_NOARGS, "connections () -> List.\n\ -- 2.49.0