From patchwork Sun Oct 2 16:53:05 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Burgess X-Patchwork-Id: 58277 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 586463858299 for ; Sun, 2 Oct 2022 16:54:27 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 586463858299 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1664729667; bh=6rO47NLGMJezPtVZfEHV9q6aIhz9OKdzPNhT+EpX0T4=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=nwIyrNIc1sXFzZWCFpq73/ttquDXvMa1Go6RGFdpMPt3eY0zjFuaEmWP+4mU6udAV sxB4HpAwTIwIUV9YVUk/I9wsY+pTwgjabrhs5O6X/hQqbKu9/LGuDSA2TwUmRX7dT8 u2vKI81s5AIQDitaZZKWTJvoNjQA7b0KNBStrvok= X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTPS id 22ED53858407 for ; Sun, 2 Oct 2022 16:53:19 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 22ED53858407 Received: from mail-wm1-f71.google.com (mail-wm1-f71.google.com [209.85.128.71]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_128_GCM_SHA256) id us-mta-262-9vCPGf8mMkCGRrDnRDpXig-1; Sun, 02 Oct 2022 12:53:17 -0400 X-MC-Unique: 9vCPGf8mMkCGRrDnRDpXig-1 Received: by mail-wm1-f71.google.com with SMTP id b5-20020a05600c4e0500b003b499f99aceso7824194wmq.1 for ; Sun, 02 Oct 2022 09:53:17 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date; bh=6rO47NLGMJezPtVZfEHV9q6aIhz9OKdzPNhT+EpX0T4=; b=BaMS5KWd4Rk7gRgDSecrEboNNhmPl6jTDM+O8usRcGnvS9LgfTflVJ1Vd7KoHjTnr8 wwg03BiXl671yuROQIUvASNSgbXpiZHz6SVxhHb/y5naiHfsp9JWCJUzeQaBr2qts8G2 /45gIjduKyfZb5WSrM5nWVuELpsZCe6ZdTWL/+31BF8c91TTTE+lCWZJMLtL33ckH84M 5iOgo77jPj4EVtt+JxuiY5WzgvBqVIL2Ox6k4zBwBiEstkPJvyfZAumswsRkbcLCOCyt lp3T9hQp/mCtmx2PfBoqCj9jw0y30CMEAOW+jkfmalH6scmu1I3CU7A3AGn56sSfmC3y F9Uw== X-Gm-Message-State: ACrzQf35+A6xLGB0VsGH1DyngSJ2F1HWKqf5/AiEXlzvnpuXpeo41e9q BqY8hOfE2C9C8w8wu/RHp0DwKo+wHysGTMPL8bUfBexCGpfcdeRgQr4niITxiiw2z/2hU38i+Ol zYc1lNs9UnIpJb3L1YboboE/7myUtZst4APd4DBf5NMvIG/S+/TPVTX0r2anADsbx39mHnF7Pxw == X-Received: by 2002:adf:e70a:0:b0:22c:da3f:36ee with SMTP id c10-20020adfe70a000000b0022cda3f36eemr10652465wrm.414.1664729595410; Sun, 02 Oct 2022 09:53:15 -0700 (PDT) X-Google-Smtp-Source: AMsMyM7kaoDR+Vw2MXm5rgt/A6thyui0azRla4s2jLyha/vnx0xp/dfxiRUUGKVyqUdEn7vX/K+VEg== X-Received: by 2002:adf:e70a:0:b0:22c:da3f:36ee with SMTP id c10-20020adfe70a000000b0022cda3f36eemr10652442wrm.414.1664729594427; Sun, 02 Oct 2022 09:53:14 -0700 (PDT) Received: from localhost (52.72.115.87.dyn.plus.net. [87.115.72.52]) by smtp.gmail.com with ESMTPSA id bj3-20020a0560001e0300b00226dfac0149sm1468681wrb.114.2022.10.02.09.53.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 02 Oct 2022 09:53:13 -0700 (PDT) To: gdb-patches@sourceware.org Subject: [PATCH 3/3] gdb/python: add gdbpy_register_subsystem mechanism Date: Sun, 2 Oct 2022 17:53:05 +0100 Message-Id: X-Mailer: git-send-email 2.25.4 In-Reply-To: References: MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-11.0 required=5.0 tests=BAYES_00, DKIM_INVALID, DKIM_SIGNED, GIT_PATCH_0, KAM_DMARC_NONE, KAM_DMARC_STATUS, RCVD_IN_BARRACUDACENTRAL, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Andrew Burgess via Gdb-patches From: Andrew Burgess Reply-To: Andrew Burgess Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org Sender: "Gdb-patches" Currently, when we add a new python sub-system to GDB, e.g. py-inferior.c, we end up having to create a new function like gdbpy_initialize_inferior, which then has to be called from the function do_start_initialization in python.c. In some cases (or currently just the one case), like py-micmd.c, we have two functions gdbpy_initialize_micommands, and gdbpy_finalize_micommands, with the second being called from finalize_python which is also in python.c. This commit proposes a mechanism to manage these initialization and finalization calls, this means that adding a new Python subsystem will no longer require changes to python.c, instead, the initialization and finalization functions will be registered directly from the sub-system file, e.g. py-inferior.c, or py-micmd.c. A new function gdbpy_register_subsystem will be added which takes two callbacks, the first is an initialization callback, e.g. gdbpy_initialize_micommands, and the second is a finalization callback, e.g. gdbpy_finalize_micommands. The second callback is optional, and defaults to nullptr. All callbacks registered through gdbpy_register_subsystem are added to a vector, and in python.c we iterate over the vector and all the various functions as needed. The only question is when should gdbpy_register_subsystem be called? The answer I think is to make use of GDB's existing _initialize_* function mechanism. A few of the python sub-system files already include an _initialize_* function, but most needed to have one added. One possible problem with this change is that there is now no guaranteed ordering of how the various sub-systems are initialized (or finalized). The previous two commits have removed all the implicit dependencies that existed between sub-systems, and replaced them with more explicit dependencies. With those two commits in place I now believe that there are no dependencies on the order in which the gdbpy_initialize_* functions are called. To satisfy myself that this was true I ran the testsuite with the patch as presented here, but also, I modified GDB so that the gdbpy_initialize_* functions were called in reverse order, and ran the testsuite again. I saw no regressions in either case. As there's only a single finalize call right now then we can be sure that there's no dependencies there. One other change of note was for gdbpy_initialize_gdb_readline, this function previously returned void. In order to make this function have the correct signature I've updated its return type to int, and we now return 0 to indicate success. All of the other initialize (and finalize) functions have been made static within their respective sub-system files. There should be no user visible changes after this commit. --- gdb/python/py-arch.c | 11 +++- gdb/python/py-auto-load.c | 9 ++- gdb/python/py-block.c | 9 ++- gdb/python/py-breakpoint.c | 7 ++- gdb/python/py-cmd.c | 9 ++- gdb/python/py-connection.c | 4 +- gdb/python/py-disasm.c | 11 +++- gdb/python/py-event.c | 9 ++- gdb/python/py-evtregistry.c | 9 ++- gdb/python/py-finishbreakpoint.c | 11 +++- gdb/python/py-frame.c | 9 ++- gdb/python/py-function.c | 9 ++- gdb/python/py-gdb-readline.c | 10 ++- gdb/python/py-inferior.c | 11 +++- gdb/python/py-infthread.c | 11 +++- gdb/python/py-instruction.c | 9 ++- gdb/python/py-lazy-string.c | 9 ++- gdb/python/py-linetable.c | 9 ++- gdb/python/py-membuf.c | 11 +++- gdb/python/py-micmd.c | 9 ++- gdb/python/py-objfile.c | 9 ++- gdb/python/py-param.c | 9 ++- gdb/python/py-progspace.c | 9 ++- gdb/python/py-record-btrace.c | 9 ++- gdb/python/py-record.c | 9 ++- gdb/python/py-registers.c | 11 +++- gdb/python/py-symbol.c | 9 ++- gdb/python/py-symtab.c | 9 ++- gdb/python/py-tui.c | 9 ++- gdb/python/py-type.c | 9 ++- gdb/python/py-unwind.c | 34 ++++++----- gdb/python/py-value.c | 9 ++- gdb/python/py-xmethods.c | 9 ++- gdb/python/python-internal.h | 102 ++++++++++--------------------- gdb/python/python.c | 73 +++++++++++----------- 35 files changed, 349 insertions(+), 156 deletions(-) diff --git a/gdb/python/py-arch.c b/gdb/python/py-arch.c index cf0978560f9..bd172d6f8c8 100644 --- a/gdb/python/py-arch.c +++ b/gdb/python/py-arch.c @@ -344,7 +344,7 @@ gdbpy_all_architecture_names (PyObject *self, PyObject *args) /* Initializes the Architecture class in the gdb module. */ -int +static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION gdbpy_initialize_arch (void) { arch_object_type.tp_new = PyType_GenericNew; @@ -355,6 +355,15 @@ gdbpy_initialize_arch (void) (PyObject *) &arch_object_type); } +void _initialize_py_arch (); +void +_initialize_py_arch () +{ + gdbpy_register_subsystem (gdbpy_initialize_arch); +} + + + static PyMethodDef arch_object_methods [] = { { "name", archpy_name, METH_NOARGS, "name () -> String.\n\ diff --git a/gdb/python/py-auto-load.c b/gdb/python/py-auto-load.c index 5d60460683a..50131806c18 100644 --- a/gdb/python/py-auto-load.c +++ b/gdb/python/py-auto-load.c @@ -56,7 +56,7 @@ info_auto_load_python_scripts (const char *pattern, int from_tty) auto_load_info_scripts (pattern, from_tty, &extension_language_python); } -int +static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION gdbpy_initialize_auto_load (void) { add_setshow_boolean_cmd ("python-scripts", class_support, @@ -95,3 +95,10 @@ Print the list of automatically loaded Python scripts, deprecated.")); return 0; } + +void _initialize_py_auto_load (); +void +_initialize_py_auto_load () +{ + gdbpy_register_subsystem (gdbpy_initialize_auto_load); +} diff --git a/gdb/python/py-block.c b/gdb/python/py-block.c index b9aea3aca69..204571192bd 100644 --- a/gdb/python/py-block.c +++ b/gdb/python/py-block.c @@ -424,7 +424,7 @@ blpy_iter_is_valid (PyObject *self, PyObject *args) Py_RETURN_TRUE; } -int +static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION gdbpy_initialize_blocks (void) { block_object_type.tp_new = PyType_GenericNew; @@ -443,6 +443,13 @@ gdbpy_initialize_blocks (void) (PyObject *) &block_syms_iterator_object_type); } +void _initialize_py_block (); +void +_initialize_py_block () +{ + gdbpy_register_subsystem (gdbpy_initialize_blocks); +} + static PyMethodDef block_object_methods[] = { diff --git a/gdb/python/py-breakpoint.c b/gdb/python/py-breakpoint.c index 7a757432948..8c972761bf9 100644 --- a/gdb/python/py-breakpoint.c +++ b/gdb/python/py-breakpoint.c @@ -1231,7 +1231,7 @@ gdbpy_breakpoint_modified (struct breakpoint *b) /* Initialize the Python breakpoint code. */ -int +static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION gdbpy_initialize_breakpoints (void) { int i; @@ -1271,7 +1271,7 @@ gdbpy_initialize_breakpoints (void) /* Initialize the Python BreakpointLocation code. */ -int +static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION gdbpy_initialize_breakpoint_locations () { if (PyType_Ready (&breakpoint_location_object_type) < 0) @@ -1433,6 +1433,9 @@ _initialize_py_breakpoint () NULL, show_pybp_debug, &setdebuglist, &showdebuglist); + + gdbpy_register_subsystem (gdbpy_initialize_breakpoints); + gdbpy_register_subsystem (gdbpy_initialize_breakpoint_locations); } /* Python function to set the enabled state of a breakpoint location. */ diff --git a/gdb/python/py-cmd.c b/gdb/python/py-cmd.c index 5cc392af175..e32686da63e 100644 --- a/gdb/python/py-cmd.c +++ b/gdb/python/py-cmd.c @@ -551,7 +551,7 @@ cmdpy_init (PyObject *self, PyObject *args, PyObject *kw) /* Initialize the 'commands' code. */ -int +static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION gdbpy_initialize_commands (void) { int i; @@ -601,6 +601,13 @@ gdbpy_initialize_commands (void) return 0; } +void _initialize_py_cmd (); +void +_initialize_py_cmd () +{ + gdbpy_register_subsystem (gdbpy_initialize_commands); +} + static PyMethodDef cmdpy_object_methods[] = diff --git a/gdb/python/py-connection.c b/gdb/python/py-connection.c index 84660414dd0..d9ffe0d314c 100644 --- a/gdb/python/py-connection.c +++ b/gdb/python/py-connection.c @@ -285,7 +285,7 @@ connpy_get_connection_details (PyObject *self, void *closure) /* Python specific initialization for this file. */ -int +static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION gdbpy_initialize_connection (void) { if (PyType_Ready (&connection_object_type) < 0) @@ -445,6 +445,8 @@ _initialize_py_connection () { gdb::observers::connection_removed.attach (connpy_connection_removed, "py-connection"); + + gdbpy_register_subsystem (gdbpy_initialize_connection); } /* Methods for the gdb.TargetConnection object type. */ diff --git a/gdb/python/py-disasm.c b/gdb/python/py-disasm.c index c37452fcf72..118b50ee208 100644 --- a/gdb/python/py-disasm.c +++ b/gdb/python/py-disasm.c @@ -971,7 +971,7 @@ static struct PyModuleDef python_disassembler_module_def = /* Called to initialize the Python structures in this file. */ -int +static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION gdbpy_initialize_disasm () { /* Create the _gdb.disassembler module, and add it to the _gdb module. */ @@ -1005,6 +1005,15 @@ gdbpy_initialize_disasm () return 0; } +void _initialize_py_disasm (); +void +_initialize_py_disasm () +{ + gdbpy_register_subsystem (gdbpy_initialize_disasm); +} + + + /* Describe the gdb.disassembler.DisassembleInfo type. */ PyTypeObject disasm_info_object_type = { diff --git a/gdb/python/py-event.c b/gdb/python/py-event.c index 4d8a0b909c0..a540243aa6d 100644 --- a/gdb/python/py-event.c +++ b/gdb/python/py-event.c @@ -54,7 +54,7 @@ evpy_add_attribute (PyObject *event, const char *name, PyObject *attr) /* Initialize the Python event code. */ -int +static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION gdbpy_initialize_event (void) { return gdbpy_initialize_event_generic (&event_object_type, @@ -114,6 +114,13 @@ evpy_emit_event (PyObject *event, return 0; } +void _initialize_py_event (); +void +_initialize_py_event () +{ + gdbpy_register_subsystem (gdbpy_initialize_event); +} + static gdb_PyGetSetDef event_object_getset[] = { { "__dict__", gdb_py_generic_dict, NULL, diff --git a/gdb/python/py-evtregistry.c b/gdb/python/py-evtregistry.c index f3a7f0ca244..9d83c54120c 100644 --- a/gdb/python/py-evtregistry.c +++ b/gdb/python/py-evtregistry.c @@ -102,7 +102,7 @@ evregpy_dealloc (PyObject *self) /* Initialize the Python event registry code. */ -int +static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION gdbpy_initialize_eventregistry (void) { if (PyType_Ready (&eventregistry_object_type) < 0) @@ -123,6 +123,13 @@ evregpy_no_listeners_p (eventregistry_object *registry) return registry == nullptr || PyList_Size (registry->callbacks) == 0; } +void _initialize_py_evtregistry (); +void +_initialize_py_evtregistry () +{ + gdbpy_register_subsystem (gdbpy_initialize_eventregistry); +} + static PyMethodDef eventregistry_object_methods[] = { { "connect", evregpy_connect, METH_VARARGS, "Add function" }, diff --git a/gdb/python/py-finishbreakpoint.c b/gdb/python/py-finishbreakpoint.c index 67637f16a39..46b188c7a93 100644 --- a/gdb/python/py-finishbreakpoint.c +++ b/gdb/python/py-finishbreakpoint.c @@ -405,7 +405,7 @@ bpfinishpy_handle_exit (struct inferior *inf) /* Initialize the Python finish breakpoint code. */ -int +static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION gdbpy_initialize_finishbreakpoints (void) { if (!gdbpy_breakpoint_init_breakpoint_type ()) @@ -426,6 +426,15 @@ gdbpy_initialize_finishbreakpoints (void) return 0; } +void _initialize_py_finishbreakpoint (); +void +_initialize_py_finishbreakpoint () +{ + gdbpy_register_subsystem (gdbpy_initialize_finishbreakpoints); +} + + + static gdb_PyGetSetDef finish_breakpoint_object_getset[] = { { "return_value", bpfinishpy_get_returnvalue, NULL, "gdb.Value object representing the return value, if any. \ diff --git a/gdb/python/py-frame.c b/gdb/python/py-frame.c index 8bd2e0bc6da..af7a5e88c75 100644 --- a/gdb/python/py-frame.c +++ b/gdb/python/py-frame.c @@ -713,7 +713,7 @@ frapy_richcompare (PyObject *self, PyObject *other, int op) /* Sets up the Frame API in the gdb module. */ -int +static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION gdbpy_initialize_frames (void) { frame_object_type.tp_new = PyType_GenericNew; @@ -745,6 +745,13 @@ gdbpy_initialize_frames (void) (PyObject *) &frame_object_type); } +void _initialize_py_frame (); +void +_initialize_py_frame () +{ + gdbpy_register_subsystem (gdbpy_initialize_frames); +} + static PyMethodDef frame_object_methods[] = { diff --git a/gdb/python/py-function.c b/gdb/python/py-function.c index c314ee5da71..45e72f3d289 100644 --- a/gdb/python/py-function.c +++ b/gdb/python/py-function.c @@ -134,7 +134,7 @@ fnpy_init (PyObject *self, PyObject *args, PyObject *kwds) /* Initialize internal function support. */ -int +static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION gdbpy_initialize_functions (void) { fnpy_object_type.tp_new = PyType_GenericNew; @@ -145,6 +145,13 @@ gdbpy_initialize_functions (void) (PyObject *) &fnpy_object_type); } +void _initialize_py_function (); +void +_initialize_py_function () +{ + gdbpy_register_subsystem (gdbpy_initialize_functions); +} + PyTypeObject fnpy_object_type = diff --git a/gdb/python/py-gdb-readline.c b/gdb/python/py-gdb-readline.c index af388d5ed72..c7c38eea89d 100644 --- a/gdb/python/py-gdb-readline.c +++ b/gdb/python/py-gdb-readline.c @@ -85,7 +85,7 @@ gdbpy_readline_wrapper (FILE *sys_stdin, FILE *sys_stdout, /* Initialize Python readline support. */ -void +static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION gdbpy_initialize_gdb_readline (void) { /* Python's readline module conflicts with GDB's use of readline @@ -109,5 +109,13 @@ class GdbRemoveReadlineFinder:\n\ sys.meta_path.append(GdbRemoveReadlineFinder())\n\ ") == 0) PyOS_ReadlineFunctionPointer = gdbpy_readline_wrapper; + + return 0; } +void _initialize_py_gdb_readline (); +void +_initialize_py_gdb_readline () +{ + gdbpy_register_subsystem (gdbpy_initialize_gdb_readline); +} diff --git a/gdb/python/py-inferior.c b/gdb/python/py-inferior.c index 0066ae6d6a9..b2c4a11086f 100644 --- a/gdb/python/py-inferior.c +++ b/gdb/python/py-inferior.c @@ -833,7 +833,7 @@ gdbpy_selected_inferior (PyObject *self, PyObject *args) inferior_to_inferior_object (current_inferior ()).release ()); } -int +static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION gdbpy_initialize_inferior (void) { if (PyType_Ready (&inferior_object_type) < 0) @@ -869,6 +869,15 @@ gdbpy_initialize_inferior (void) return 0; } +void _initialize_py_inferior (); +void +_initialize_py_inferior () +{ + gdbpy_register_subsystem (gdbpy_initialize_inferior); +} + + + static gdb_PyGetSetDef inferior_object_getset[] = { { "num", infpy_get_num, NULL, "ID of inferior, as assigned by GDB.", NULL }, diff --git a/gdb/python/py-infthread.c b/gdb/python/py-infthread.c index 34f60526ac9..1e474299f77 100644 --- a/gdb/python/py-infthread.c +++ b/gdb/python/py-infthread.c @@ -361,7 +361,7 @@ gdbpy_selected_thread (PyObject *self, PyObject *args) Py_RETURN_NONE; } -int +static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION gdbpy_initialize_thread (void) { if (PyType_Ready (&thread_object_type) < 0) @@ -371,6 +371,15 @@ gdbpy_initialize_thread (void) (PyObject *) &thread_object_type); } +void _initialize_py_infthread (); +void +_initialize_py_infthread () +{ + gdbpy_register_subsystem (gdbpy_initialize_thread); +} + + + static gdb_PyGetSetDef thread_object_getset[] = { { "name", thpy_get_name, thpy_set_name, diff --git a/gdb/python/py-instruction.c b/gdb/python/py-instruction.c index fee5bba4015..3fe39411507 100644 --- a/gdb/python/py-instruction.c +++ b/gdb/python/py-instruction.c @@ -81,10 +81,17 @@ py_insn_get_insn_type () /* Sets up the gdb.Instruction type. */ -int +static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION gdbpy_initialize_instruction (void) { if (py_insn_get_insn_type () == nullptr) return -1; return 0; } + +void _initialize_py_instruction (); +void +_initialize_py_instruction () +{ + gdbpy_register_subsystem (gdbpy_initialize_instruction); +} diff --git a/gdb/python/py-lazy-string.c b/gdb/python/py-lazy-string.c index 8cd8b91e91b..5f8afcef858 100644 --- a/gdb/python/py-lazy-string.c +++ b/gdb/python/py-lazy-string.c @@ -229,7 +229,7 @@ gdbpy_create_lazy_string_object (CORE_ADDR address, long length, return (PyObject *) str_obj; } -int +static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION gdbpy_initialize_lazy_string (void) { if (PyType_Ready (&lazy_string_object_type) < 0) @@ -291,6 +291,13 @@ gdbpy_extract_lazy_string (PyObject *string, CORE_ADDR *addr, encoding->reset (lazy->encoding ? xstrdup (lazy->encoding) : NULL); } +void _initialize_py_lazy_string (); +void +_initialize_py_lazy_string () +{ + gdbpy_register_subsystem (gdbpy_initialize_lazy_string); +} + static PyMethodDef lazy_string_object_methods[] = { diff --git a/gdb/python/py-linetable.c b/gdb/python/py-linetable.c index 8e545febb17..53cc3c23d22 100644 --- a/gdb/python/py-linetable.c +++ b/gdb/python/py-linetable.c @@ -286,7 +286,7 @@ ltpy_dealloc (PyObject *self) /* Initialize LineTable, LineTableEntry and LineTableIterator objects. */ -int +static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION gdbpy_initialize_linetable (void) { if (PyType_Ready (&linetable_object_type) < 0) @@ -446,6 +446,13 @@ ltpy_iter_is_valid (PyObject *self, PyObject *args) Py_RETURN_TRUE; } +void _initialize_py_linetable (); +void +_initialize_py_linetable () +{ + gdbpy_register_subsystem (gdbpy_initialize_linetable); +} + static PyMethodDef linetable_object_methods[] = { diff --git a/gdb/python/py-membuf.c b/gdb/python/py-membuf.c index d2a059a0e34..d4b830b7a40 100644 --- a/gdb/python/py-membuf.c +++ b/gdb/python/py-membuf.c @@ -99,7 +99,7 @@ get_buffer (PyObject *self, Py_buffer *buf, int flags) /* General Python initialization callback. */ -int +static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION gdbpy_initialize_membuf (void) { membuf_object_type.tp_new = PyType_GenericNew; @@ -110,6 +110,15 @@ gdbpy_initialize_membuf (void) (PyObject *) &membuf_object_type); } +void _initialize_py_membuf (); +void +_initialize_py_membuf () +{ + gdbpy_register_subsystem (gdbpy_initialize_membuf); +} + + + static PyBufferProcs buffer_procs = { get_buffer diff --git a/gdb/python/py-micmd.c b/gdb/python/py-micmd.c index 79e2575f789..b72d66d8154 100644 --- a/gdb/python/py-micmd.c +++ b/gdb/python/py-micmd.c @@ -595,7 +595,7 @@ micmdpy_dealloc (PyObject *obj) /* Python initialization for the MI commands components. */ -int +static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION gdbpy_initialize_micommands () { micmdpy_object_type.tp_new = PyType_GenericNew; @@ -614,7 +614,9 @@ gdbpy_initialize_micommands () return 0; } -void +/* Cleanup just before GDB shuts down the Python interpreter. */ + +static void gdbpy_finalize_micommands () { /* mi_command_py objects hold references to micmdpy_object objects. They must @@ -736,4 +738,7 @@ _initialize_py_micmd () nullptr, show_pymicmd_debug, &setdebuglist, &showdebuglist); + + gdbpy_register_subsystem (gdbpy_initialize_micommands, + gdbpy_finalize_micommands); } diff --git a/gdb/python/py-objfile.c b/gdb/python/py-objfile.c index 757f9aac4fc..e2bcefb58c5 100644 --- a/gdb/python/py-objfile.c +++ b/gdb/python/py-objfile.c @@ -708,7 +708,7 @@ objfile_to_objfile_object (struct objfile *objfile) return gdbpy_ref<>::new_reference (result); } -int +static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION gdbpy_initialize_objfile (void) { if (PyType_Ready (&objfile_object_type) < 0) @@ -718,6 +718,13 @@ gdbpy_initialize_objfile (void) (PyObject *) &objfile_object_type); } +void _initialize_py_objfile (); +void +_initialize_py_objfile () +{ + gdbpy_register_subsystem (gdbpy_initialize_objfile); +} + static PyMethodDef objfile_object_methods[] = diff --git a/gdb/python/py-param.c b/gdb/python/py-param.c index 5d509ba4658..17c6e365ea9 100644 --- a/gdb/python/py-param.c +++ b/gdb/python/py-param.c @@ -828,7 +828,7 @@ parmpy_dealloc (PyObject *obj) } /* Initialize the 'parameters' module. */ -int +static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION gdbpy_initialize_parameters (void) { int i; @@ -856,6 +856,13 @@ gdbpy_initialize_parameters (void) (PyObject *) &parmpy_object_type); } +void _initialize_py_param (); +void +_initialize_py_param () +{ + gdbpy_register_subsystem (gdbpy_initialize_parameters); +} + PyTypeObject parmpy_object_type = diff --git a/gdb/python/py-progspace.c b/gdb/python/py-progspace.c index 4eb33e8292f..18ea7c0ca60 100644 --- a/gdb/python/py-progspace.c +++ b/gdb/python/py-progspace.c @@ -529,7 +529,7 @@ gdbpy_is_progspace (PyObject *obj) return PyObject_TypeCheck (obj, &pspace_object_type); } -int +static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION gdbpy_initialize_pspace (void) { if (PyType_Ready (&pspace_object_type) < 0) @@ -539,6 +539,13 @@ gdbpy_initialize_pspace (void) (PyObject *) &pspace_object_type); } +void _initialize_py_progspace (); +void +_initialize_py_progspace () +{ + gdbpy_register_subsystem (gdbpy_initialize_pspace); +} + static gdb_PyGetSetDef pspace_getset[] = diff --git a/gdb/python/py-record-btrace.c b/gdb/python/py-record-btrace.c index 85401010f0a..4a7dc09a45d 100644 --- a/gdb/python/py-record-btrace.c +++ b/gdb/python/py-record-btrace.c @@ -816,7 +816,7 @@ static PyMappingMethods btpy_list_mapping_methods = /* Sets up the btrace record API. */ -int +static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION gdbpy_initialize_btrace (void) { btpy_list_type.tp_new = PyType_GenericNew; @@ -837,3 +837,10 @@ gdbpy_initialize_btrace (void) return PyType_Ready (&btpy_list_type); } + +void _initialize_py_record_btrace (); +void +_initialize_py_record_btrace () +{ + gdbpy_register_subsystem (gdbpy_initialize_btrace); +} diff --git a/gdb/python/py-record.c b/gdb/python/py-record.c index fd5cfee84eb..04f5fc802b3 100644 --- a/gdb/python/py-record.c +++ b/gdb/python/py-record.c @@ -544,7 +544,7 @@ static gdb_PyGetSetDef recpy_gap_getset[] = { /* Sets up the record API in the gdb module. */ -int +static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION gdbpy_initialize_record (void) { recpy_record_type.tp_new = PyType_GenericNew; @@ -648,3 +648,10 @@ gdbpy_stop_recording (PyObject *self, PyObject *args) Py_RETURN_NONE; } + +void _initialize_py_record (); +void +_initialize_py_record () +{ + gdbpy_register_subsystem (gdbpy_initialize_record); +} diff --git a/gdb/python/py-registers.c b/gdb/python/py-registers.c index fe7481cea9e..542317d3970 100644 --- a/gdb/python/py-registers.c +++ b/gdb/python/py-registers.c @@ -427,7 +427,7 @@ gdbpy_parse_register_id (struct gdbarch *gdbarch, PyObject *pyo_reg_id, /* Initializes the new Python classes from this file in the gdb module. */ -int +static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION gdbpy_initialize_registers () { register_descriptor_object_type.tp_new = PyType_GenericNew; @@ -462,6 +462,15 @@ gdbpy_initialize_registers () (PyObject *) ®ister_descriptor_iterator_object_type)); } +void _initialize_py_registers (); +void +_initialize_py_registers () +{ + gdbpy_register_subsystem (gdbpy_initialize_registers); +} + + + static PyMethodDef register_descriptor_iterator_object_methods [] = { { "find", (PyCFunction) register_descriptor_iter_find, METH_VARARGS | METH_KEYWORDS, diff --git a/gdb/python/py-symbol.c b/gdb/python/py-symbol.c index e5fe5cf8c92..e1d7eca7f58 100644 --- a/gdb/python/py-symbol.c +++ b/gdb/python/py-symbol.c @@ -611,7 +611,7 @@ gdbpy_lookup_static_symbols (PyObject *self, PyObject *args, PyObject *kw) return return_list.release (); } -int +static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION gdbpy_initialize_symbols (void) { if (PyType_Ready (&symbol_object_type) < 0) @@ -680,6 +680,13 @@ gdbpy_initialize_symbols (void) (PyObject *) &symbol_object_type); } +void _initialize_py_symbol (); +void +_initialize_py_symbol () +{ + gdbpy_register_subsystem (gdbpy_initialize_symbols); +} + static gdb_PyGetSetDef symbol_object_getset[] = { diff --git a/gdb/python/py-symtab.c b/gdb/python/py-symtab.c index 03c274dfff6..826ffc19e13 100644 --- a/gdb/python/py-symtab.c +++ b/gdb/python/py-symtab.c @@ -509,7 +509,7 @@ symtab_object_to_symtab (PyObject *obj) return ((symtab_object *) obj)->symtab; } -int +static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION gdbpy_initialize_symtabs (void) { symtab_object_type.tp_new = PyType_GenericNew; @@ -528,6 +528,13 @@ gdbpy_initialize_symtabs (void) (PyObject *) &sal_object_type); } +void _initialize_py_symtab (); +void +_initialize_py_symtab () +{ + gdbpy_register_subsystem (gdbpy_initialize_symtabs); +} + static gdb_PyGetSetDef symtab_object_getset[] = { diff --git a/gdb/python/py-tui.c b/gdb/python/py-tui.c index 6a92251a705..b69fbf1f3c1 100644 --- a/gdb/python/py-tui.c +++ b/gdb/python/py-tui.c @@ -561,7 +561,7 @@ PyTypeObject gdbpy_tui_window_object_type = /* Initialize this module. */ -int +static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION gdbpy_initialize_tui () { #ifdef TUI @@ -572,3 +572,10 @@ gdbpy_initialize_tui () return 0; } + +void _initialize_py_tui (); +void +_initialize_py_tui () +{ + gdbpy_register_subsystem (gdbpy_initialize_tui); +} diff --git a/gdb/python/py-type.c b/gdb/python/py-type.c index 3e558dee7ad..cf18470ba58 100644 --- a/gdb/python/py-type.c +++ b/gdb/python/py-type.c @@ -1465,7 +1465,7 @@ gdbpy_lookup_type (PyObject *self, PyObject *args, PyObject *kw) return type_to_type_object (type); } -int +static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION gdbpy_initialize_types (void) { if (PyType_Ready (&type_object_type) < 0) @@ -1493,6 +1493,13 @@ gdbpy_initialize_types (void) (PyObject *) &field_object_type); } +void _initialize_py_type (); +void +_initialize_py_type () +{ + gdbpy_register_subsystem (gdbpy_initialize_types); +} + static gdb_PyGetSetDef type_object_getset[] = diff --git a/gdb/python/py-unwind.c b/gdb/python/py-unwind.c index 0a1b460e785..c0a35fda6f9 100644 --- a/gdb/python/py-unwind.c +++ b/gdb/python/py-unwind.c @@ -682,23 +682,9 @@ pyuw_on_new_gdbarch (struct gdbarch *newarch) } } -void _initialize_py_unwind (); -void -_initialize_py_unwind () -{ - add_setshow_boolean_cmd - ("py-unwind", class_maintenance, &pyuw_debug, - _("Set Python unwinder debugging."), - _("Show Python unwinder debugging."), - _("When on, Python unwinder debugging is enabled."), - NULL, - show_pyuw_debug, - &setdebuglist, &showdebuglist); -} - /* Initialize unwind machinery. */ -int +static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION gdbpy_initialize_unwind (void) { gdb::observers::architecture_changed.attach (pyuw_on_new_gdbarch, @@ -717,6 +703,24 @@ gdbpy_initialize_unwind (void) (PyObject *) &unwind_info_object_type); } +void _initialize_py_unwind (); +void +_initialize_py_unwind () +{ + add_setshow_boolean_cmd + ("py-unwind", class_maintenance, &pyuw_debug, + _("Set Python unwinder debugging."), + _("Show Python unwinder debugging."), + _("When on, Python unwinder debugging is enabled."), + NULL, + show_pyuw_debug, + &setdebuglist, &showdebuglist); + + gdbpy_register_subsystem (gdbpy_initialize_unwind); +} + + + static PyMethodDef pending_frame_object_methods[] = { { "read_register", pending_framepy_read_register, METH_VARARGS, diff --git a/gdb/python/py-value.c b/gdb/python/py-value.c index 92a15304c34..5ca8aa0f0f7 100644 --- a/gdb/python/py-value.c +++ b/gdb/python/py-value.c @@ -2059,7 +2059,7 @@ gdbpy_is_value_object (PyObject *obj) return PyObject_TypeCheck (obj, &value_object_type); } -int +static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION gdbpy_initialize_values (void) { if (PyType_Ready (&value_object_type) < 0) @@ -2069,6 +2069,13 @@ gdbpy_initialize_values (void) (PyObject *) &value_object_type); } +void _initialize_py_value (); +void +_initialize_py_value () +{ + gdbpy_register_subsystem (gdbpy_initialize_values); +} + static gdb_PyGetSetDef value_object_getset[] = { diff --git a/gdb/python/py-xmethods.c b/gdb/python/py-xmethods.c index 1467e52a960..adee4893b46 100644 --- a/gdb/python/py-xmethods.c +++ b/gdb/python/py-xmethods.c @@ -598,7 +598,7 @@ python_xmethod_worker::python_xmethod_worker (PyObject *py_worker, Py_INCREF (this_type); } -int +static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION gdbpy_initialize_xmethods (void) { py_match_method_name = PyUnicode_FromString (match_method_name); @@ -612,3 +612,10 @@ gdbpy_initialize_xmethods (void) return 1; } + +void _initialize_py_xmethods (); +void +_initialize_py_xmethods () +{ + gdbpy_register_subsystem (gdbpy_initialize_xmethods); +} diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h index a4f54e78268..9630a0dab56 100644 --- a/gdb/python/python-internal.h +++ b/gdb/python/python-internal.h @@ -489,76 +489,38 @@ struct gdbarch *arch_object_to_gdbarch (PyObject *obj); extern struct program_space *progspace_object_to_program_space (PyObject *obj); -void gdbpy_initialize_gdb_readline (void); -int gdbpy_initialize_auto_load (void) - CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION; -int gdbpy_initialize_values (void) - CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION; -int gdbpy_initialize_frames (void) - CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION; -int gdbpy_initialize_instruction (void) - CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION; -int gdbpy_initialize_btrace (void) - CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION; -int gdbpy_initialize_record (void) - CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION; -int gdbpy_initialize_symtabs (void) - CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION; -int gdbpy_initialize_commands (void) - CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION; -int gdbpy_initialize_symbols (void) - CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION; -int gdbpy_initialize_symtabs (void) - CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION; -int gdbpy_initialize_blocks (void) - CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION; -int gdbpy_initialize_types (void) - CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION; -int gdbpy_initialize_functions (void) - CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION; -int gdbpy_initialize_pspace (void) - CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION; -int gdbpy_initialize_objfile (void) - CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION; -int gdbpy_initialize_breakpoints (void) - CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION; -int gdbpy_initialize_breakpoint_locations () - CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION; -int gdbpy_initialize_finishbreakpoints (void) - CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION; -int gdbpy_initialize_lazy_string (void) - CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION; -int gdbpy_initialize_linetable (void) - CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION; -int gdbpy_initialize_parameters (void) - CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION; -int gdbpy_initialize_thread (void) - CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION; -int gdbpy_initialize_inferior (void) - CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION; -int gdbpy_initialize_eventregistry (void) - CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION; -int gdbpy_initialize_event (void) - CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION; -int gdbpy_initialize_arch (void) - CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION; -int gdbpy_initialize_registers () - CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION; -int gdbpy_initialize_xmethods (void) - CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION; -int gdbpy_initialize_unwind (void) - CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION; -int gdbpy_initialize_tui () - CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION; -int gdbpy_initialize_membuf () - CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION; -int gdbpy_initialize_connection () - CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION; -int gdbpy_initialize_micommands (void) - CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION; -void gdbpy_finalize_micommands (); -int gdbpy_initialize_disasm () - CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION; +/* The type of a function that can be called just after GDB has setup the + Python interpreter. This function will setup any additional Python + state required by a particular subsystem. Return 0 if the setup was + successful, or return -1 if setup failed, in which case a Python + exception should have been raised. */ + +typedef int (*gdbpy_initialize_file_func_t) (void); + +/* The type of a function that can be called just before GDB shuts down + the Python interpreter. This function can cleanup an Python state that + is cached within GDB, for example, if GDB is holding any references to + Python objects, these should be released before the Python interpreter + is shut down. + + There is no error return in this case. This function is only called + when GDB is already shutting down. The function should make a best + effort to clean up, and then return. */ + +typedef void (*gdbpy_finalize_file_func_t) (void); + +/* Register the initialization (INIT) and finalization (FINI) functions for + a Python subsystem. See the comments on the function types above for + when these functions will be called. + + Either of these functions can be nullptr, in which case no function will + be called. + + The FINI argument is optional, and defaults to nullptr (no function to + call). */ + +void gdbpy_register_subsystem (gdbpy_initialize_file_func_t init, + gdbpy_finalize_file_func_t fini = nullptr); PyMODINIT_FUNC gdbpy_events_mod_func (); diff --git a/gdb/python/python.c b/gdb/python/python.c index 516e2c983cf..afb4464aad7 100644 --- a/gdb/python/python.c +++ b/gdb/python/python.c @@ -196,6 +196,26 @@ const struct extension_language_defn extension_language_python = #ifdef HAVE_PYTHON +/* A pair containing two function pointers. The first pointer is to be + called just after GDB has setup the Python interpreter, and the second + is to be called just before GDB shuts down the Python interpreter. */ + +using callback_pair_t = std::pair; + +/* A list of callback pairs. */ + +static std::vector gdbpy_setup_callbacks; + +/* See python-internal.h. */ + +void +gdbpy_register_subsystem (gdbpy_initialize_file_func_t init, + gdbpy_finalize_file_func_t fini) +{ + gdbpy_setup_callbacks.emplace_back (init, fini); +} + /* Architecture and language to be used in callbacks from the Python interpreter. */ struct gdbarch *gdbpy_enter::python_gdbarch; @@ -1934,7 +1954,14 @@ finalize_python (void *ignore) (void) PyGILState_Ensure (); gdbpy_enter::finalize (); - gdbpy_finalize_micommands (); + /* Every item in GDBPY_SETUP_CALLBACKS is a pair. The second item in + the pair is (when not nullptr), a function to call to cleanup a + particular Python subsystem within GDB. */ + for (const auto &p : gdbpy_setup_callbacks) + { + if (p.second != nullptr) + p.second (); + } Py_Finalize (); @@ -2122,42 +2149,14 @@ do_start_initialization () gdbpy_gdberror_exc) < 0) return false; - gdbpy_initialize_gdb_readline (); - - if (gdbpy_initialize_auto_load () < 0 - || gdbpy_initialize_values () < 0 - || gdbpy_initialize_disasm () < 0 - || gdbpy_initialize_frames () < 0 - || gdbpy_initialize_commands () < 0 - || gdbpy_initialize_instruction () < 0 - || gdbpy_initialize_record () < 0 - || gdbpy_initialize_btrace () < 0 - || gdbpy_initialize_symbols () < 0 - || gdbpy_initialize_symtabs () < 0 - || gdbpy_initialize_blocks () < 0 - || gdbpy_initialize_functions () < 0 - || gdbpy_initialize_parameters () < 0 - || gdbpy_initialize_types () < 0 - || gdbpy_initialize_pspace () < 0 - || gdbpy_initialize_objfile () < 0 - || gdbpy_initialize_breakpoints () < 0 - || gdbpy_initialize_breakpoint_locations () < 0 - || gdbpy_initialize_finishbreakpoints () < 0 - || gdbpy_initialize_lazy_string () < 0 - || gdbpy_initialize_linetable () < 0 - || gdbpy_initialize_thread () < 0 - || gdbpy_initialize_inferior () < 0 - || gdbpy_initialize_eventregistry () < 0 - || gdbpy_initialize_event () < 0 - || gdbpy_initialize_arch () < 0 - || gdbpy_initialize_registers () < 0 - || gdbpy_initialize_xmethods () < 0 - || gdbpy_initialize_unwind () < 0 - || gdbpy_initialize_membuf () < 0 - || gdbpy_initialize_connection () < 0 - || gdbpy_initialize_tui () < 0 - || gdbpy_initialize_micommands () < 0) - return false; + /* Every item in GDBPY_SETUP_CALLBACKS is a pair. The first item in the + pair is (when not nullptr), a function to call to setup a particular + Python subsystem within GDB. */ + for (const auto &p : gdbpy_setup_callbacks) + { + if (p.first != nullptr && p.first () < 0) + return false; + } #define GDB_PY_DEFINE_EVENT_TYPE(name, py_name, doc, base) \ if (gdbpy_initialize_event_generic (&name##_event_object_type, py_name) < 0) \