From patchwork Tue May 26 15:50:12 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Burgess X-Patchwork-Id: 135749 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from vm01.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 25B424BA23DB for ; Tue, 26 May 2026 15:50:59 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 25B424BA23DB Authentication-Results: sourceware.org; dkim=pass (1024-bit key, unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=K9ltG2ge 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 ESMTP id E08434BA2E3F for ; Tue, 26 May 2026 15:50:21 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org E08434BA2E3F Authentication-Results: sourceware.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org E08434BA2E3F Authentication-Results: sourceware.org; arc=none smtp.remote-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1779810622; cv=none; b=CcR+tunSbkSBHVd5TuN1TtbrzvqrpFUurqpycz/jsS+xPJlRBV/ARuS9NYnI89MIob3TAW/2hE/xCh0pG20OQjModnEihqOWc43G6rbVoaj8kt+u3LJgDnB6yLN7Ztr3URtvDS6gJbdscYm11SHUetbZlyMI3MdygxEuLWqGX8w= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1779810622; c=relaxed/simple; bh=WFBMdAi+5k0Moidb7LsX7BW0YeDfdtvLs5/96YRGaK8=; h=DKIM-Signature:From:To:Subject:Date:Message-Id:MIME-Version; b=qh+VO7e/rzfwhNp8EK1MsjM3vfxxYSjukhtVOEI92D6l2vq2JL2D92FClal6OK3ckaCzm9h6WoGLjCjOVvX7jNNeuC+SR+9Enm95F3Ze8Nr/22lJgcuBTAuXtoYZ285xTd4wizHJWqkIDwzV5Wh+Aw242FBfhIcONZpPdUY1Nto= ARC-Authentication-Results: i=1; sourceware.org; dkim=pass (1024-bit key, unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=K9ltG2ge DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org E08434BA2E3F DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1779810621; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=hIXVXk6y313QSEYhKQqT/5Mwb7XtueLaTVHd98kBnpc=; b=K9ltG2geMx4eVLiabohh/xlL10p/We09QQhQ7HfXfSD9WdN3qwjqtvZdMW3+Rf7tQGUZwT jEKb/cnw4KutOdeAutNQ35L3aecd9h9gw2da2RCY8Vvah/koDL1Zs2PENIe+t7KUb3e+hX fs4K/gzNNy0OrkldAlVYIJisUyQnGwI= Received: from mail-wr1-f69.google.com (mail-wr1-f69.google.com [209.85.221.69]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-474-P7nYOqs9NxGjrYPG9-rd3w-1; Tue, 26 May 2026 11:50:16 -0400 X-MC-Unique: P7nYOqs9NxGjrYPG9-rd3w-1 X-Mimecast-MFC-AGG-ID: P7nYOqs9NxGjrYPG9-rd3w_1779810616 Received: by mail-wr1-f69.google.com with SMTP id ffacd0b85a97d-45e73a4f1dfso7724019f8f.0 for ; Tue, 26 May 2026 08:50:16 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1779810616; x=1780415416; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=hIXVXk6y313QSEYhKQqT/5Mwb7XtueLaTVHd98kBnpc=; b=Zo2zPFKiCt3wR/gMtV9Ugc48V/xtmoo0u2ZfCeyVjwHpf2NjdtnADjMwJhtl8ugo9Z 42ZoONicXcw5xiCggrhnEX2SupI5nh7bBrM6byY/x36IGrWuPEIHtFXAbxL+xc/i0lyY hXxU6ycKjx+EBD4+OrIK5PT4kdTVNbPMeQqPrJYt09VLDHr3+j8dxNM/YNtENYNse6Ok 5iHPvThhAEwsmjYWUj6WEx4lZVy+rd7KQwzhm0cKhBpvP+8BHmyi+OgJbfg0pvzsH/Xs 8JlxmfAJ7gVLvPL1o3DIy9AElIG7GqCI8t8RR92AT6FC79LKRBpre6apFeOewbJmPIXg ieGQ== X-Gm-Message-State: AOJu0YwpgsbhYRQ5VKVtweLd9weGDxO1hJLRS3x62BmLshra4s0CWxzr 1RqLR7jprFJBJDO2+S17jV8yhmdFlhw2cUQPrvDgKkmQ/xZgK9pBHmO2JOwlYGZSbxn+k5ZV4AT necUlHNTmAMEl8TbDCfV8oStDE+XAOplnbxmc5ZeybWlobFy6b5u7ttWKkf8z68d7n2Q9vN77Vb 7Rz6xUk5KBzQsrW0RCumrxxJx0iJYrbc/izk+LpPOIX6Ilne4= X-Gm-Gg: Acq92OHEWSHGcFY5VrpCEbXSzQ91nYzs/qncjM70bGIKIs+Ojyz8VhXpgp/insv0Be6 zUWCOBuHkbR8wKIXcEMHJEAPXSt0UZkZ+F03VgMmEjoqQod+bQqp06aYx+m7/JtTa/zhpwq6bsK PrIdEWVVFCa+yqmTx56l7hwycylmHLp7kjaxmuW0/8V3dCzS7x6jVkfJL2e+tM7NyJ+ATrhPGz8 /UmWN7OgLSlMIhxLpBY3zzjiAnZ1uBv9X8UlKhcWt5nWFpcKhwrS2d/5jSaPMImxZbZFmt3S55d ccxzBq77pwFz2pzVr7aZ/rAknKoG6u3FYhMWG1DIb1aWP3LTHQHIZ26obbT7cAL2P+1Kj6VA13p HKheUwIcJ1Wix6BY= X-Received: by 2002:a05:6000:400c:b0:45e:b2b7:1863 with SMTP id ffacd0b85a97d-45eb38a8507mr31437669f8f.16.1779810615194; Tue, 26 May 2026 08:50:15 -0700 (PDT) X-Received: by 2002:a05:6000:400c:b0:45e:b2b7:1863 with SMTP id ffacd0b85a97d-45eb38a8507mr31437575f8f.16.1779810614413; Tue, 26 May 2026 08:50:14 -0700 (PDT) Received: from localhost ([213.31.44.43]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-45eb6cce0a4sm36127461f8f.12.2026.05.26.08.50.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 26 May 2026 08:50:14 -0700 (PDT) From: Andrew Burgess To: gdb-patches@sourceware.org Cc: Andrew Burgess Subject: [PATCH] gdb/python: avoid switching threads for send_packet where possible Date: Tue, 26 May 2026 16:50:12 +0100 Message-Id: X-Mailer: git-send-email 2.25.4 MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: dFXU_K6GMp4Znmr9YYAq4HgbzxEiK-dobNvahXQFVHM_1779810616 X-Mimecast-Originator: redhat.com content-type: text/plain; charset="US-ASCII"; x-default=true X-Spam-Status: No, score=-12.4 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_BLOCKED, RCVD_IN_PBL, SPF_HELO_PASS, SPF_NONE, TXREP, URIBL_BLOCKED shortcircuit=no autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on sourceware.org 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~patchwork=sourceware.org@sourceware.org Bug PR gdb/32120 identifies a case where a user tried to write a custom frame unwinder that made use of RemoteTargetConnection.send_packet, however, this was triggering an assert like this: value.c:3954: internal-error: fetch_lazy_register: Assertion `next_frame != NULL' failed. The implementation of RemoteTargetConnection.send_packet can be found in the function `connpy_send_packet` in python/py-connection.c. This function includes this code: scoped_restore_current_thread restore_thread; switch_to_target_no_thread (conn->target); The purpose of this is to ensure that the currently selected inferior has the required remote connection pushed on its target stack. This is necessary because `send_remote_packet` (see remote.c) still relies on global state read from the currently selected inferior. Switching inferior and thread like this, and then switching back thanks to the scoped restore, will flush the frame cache. Flushing the frame cache while attempting to build the backtrace is not something that GDB currently supports, and it's not clear to me if this can even be supported in the general case. However, in this specific case there's really no need to flush the frame cache. The user's example unwinder does this: class TestCaseUnwinder(Unwinder): def __init__(self): super().__init__("TestCaseUnwinder") def __call__(self, pending_frame): gdb.selected_inferior().connection.send_packet("qtest.case") return None Notice that we're calling send_packet on the connection of the currently selected inferior. As such, the switch_to_target_no_thread will (usually) just be re-switching to the current inferior, and clearing the currently selected thread. The clearing the thread bit isn't really important, the only important bit is that the current inferior is set correctly. I propose that we special case connpy_send_packet so if the correct inferior is already current then we avoid the switch completely. This avoids flushing the frame cache, and all the associated problems. There are two tests. First gdb.python/py-send-packet-unwinder.exp is a new test the checks the specific case the user was reporting. Then there is an update to gdb.python/py-send-packet.exp. Now the test runs first with a single inferior and performs some send_packet checks, then the test creates a second inferior and makes that the current inferior, and checks that we can still perform send_packet calls from a Python variable containing the cached remote connection. This is checking that the switch_to_target_no_thread call is still triggering when needed. While working on gdb.python/py-send-packet.py I spotted a couple of places where we had: raise "some string" which isn't correct, I replaced this with: raise gdb.GdbError("some string") Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32120 --- gdb/python/py-connection.c | 3 +- .../gdb.python/py-send-packet-unwinder.c | 47 ++++++ .../gdb.python/py-send-packet-unwinder.exp | 74 +++++++++ .../gdb.python/py-send-packet-unwinder.py | 46 ++++++ gdb/testsuite/gdb.python/py-send-packet.exp | 146 ++++++++++++------ gdb/testsuite/gdb.python/py-send-packet.py | 39 +++-- 6 files changed, 285 insertions(+), 70 deletions(-) create mode 100644 gdb/testsuite/gdb.python/py-send-packet-unwinder.c create mode 100644 gdb/testsuite/gdb.python/py-send-packet-unwinder.exp create mode 100644 gdb/testsuite/gdb.python/py-send-packet-unwinder.py base-commit: adbfdef7131011d1ec85060128a2467c4f18fe0a diff --git a/gdb/python/py-connection.c b/gdb/python/py-connection.c index 02330b28068..2f6bb9a2547 100644 --- a/gdb/python/py-connection.c +++ b/gdb/python/py-connection.c @@ -405,7 +405,8 @@ connpy_send_packet (PyObject *self, PyObject *args, PyObject *kw) try { scoped_restore_current_thread restore_thread; - switch_to_target_no_thread (conn->target); + if (!current_inferior ()->target_is_pushed (conn->target)) + switch_to_target_no_thread (conn->target); gdb::array_view view (packet_str, packet_len); py_send_packet_callbacks callbacks; diff --git a/gdb/testsuite/gdb.python/py-send-packet-unwinder.c b/gdb/testsuite/gdb.python/py-send-packet-unwinder.c new file mode 100644 index 00000000000..e9a09d50c66 --- /dev/null +++ b/gdb/testsuite/gdb.python/py-send-packet-unwinder.c @@ -0,0 +1,47 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2026 Free Software Foundation, Inc. + + 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 . */ + +void +breakpt () +{ + /* Nothing. */ +} + +void +foo () +{ + breakpt (); +} + +void +bar () +{ + foo (); +} + +void +baz () +{ + bar (); +} + +int +main (void) +{ + baz (); + return 0; +} diff --git a/gdb/testsuite/gdb.python/py-send-packet-unwinder.exp b/gdb/testsuite/gdb.python/py-send-packet-unwinder.exp new file mode 100644 index 00000000000..920eac1c6be --- /dev/null +++ b/gdb/testsuite/gdb.python/py-send-packet-unwinder.exp @@ -0,0 +1,74 @@ +# Copyright (C) 2026 Free Software Foundation, Inc. +# +# 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 . + +# Test for a specific use case of RemoteTargetConnection.send_packet +# that we'd like to support. In general the send_packet method will +# cause GDB to switch inferior in order to ensure that the remote +# target connection is on the target stack of the current inferior. +# +# The problem is that this causes the currently selected frame to +# change, which in turn causes the frame cache to be flushed. +# +# If a user wants to make send_packet calls from a custom frame +# unwinder then this is not possible as we end up flushing the frame +# cache while trying to build the backtrace. +# +# The solution is that we have a special case, if when the send_packet +# call is made, the currently selected inferior already has the +# required remote target connection on its target stack, then it is +# not necessary to change the currently selected inferior or thread. +# +# By not switching we avoid the frame cache flush, and so calling +# send_packet from a frame unwinder is supported, so long as we only +# send the packet to the currently selected inferior's remote target. + +load_lib gdb-python.exp +load_lib gdbserver-support.exp + +standard_testfile + +require allow_gdbserver_tests allow_python_tests + +if { [build_executable "failed to build" ${testfile} ${srcfile}] } { + return +} + +set remote_python_file [gdb_remote_download host \ + ${srcdir}/${subdir}/${testfile}.py] + +clean_restart $testfile + +# Make sure we're disconnected, in case we're testing with an +# extended-remote board, therefore already connected. +gdb_test "disconnect" ".*" + +gdbserver_run "" + +gdb_breakpoint "breakpt" +gdb_continue_to_breakpoint "breakpt" + +gdb_test "source $remote_python_file" "Sourcing complete\\." \ + "source ${testfile}.py script" + +gdb_test "bt" \ + [multi_line \ + "#0 (?:$hex in )?breakpt \\(\\) at \[^\r\n\]+" \ + "#1 (?:$hex in )?foo \\(\\) at \[^\r\n\]+" \ + "#2 (?:$hex in )?bar \\(\\) at \[^\r\n\]+" \ + "#3 (?:$hex in )?baz \\(\\) at \[^\r\n\]+" \ + "#4 (?:$hex in )?main \\(\\) at \[^\r\n\]+"] + +# Check that the custom unwinder was actually called. +gdb_test "python print(TestUnwinder.call_count > 0)" "True" diff --git a/gdb/testsuite/gdb.python/py-send-packet-unwinder.py b/gdb/testsuite/gdb.python/py-send-packet-unwinder.py new file mode 100644 index 00000000000..05063e3c2f0 --- /dev/null +++ b/gdb/testsuite/gdb.python/py-send-packet-unwinder.py @@ -0,0 +1,46 @@ +# Copyright (C) 2026 Free Software Foundation, Inc. +# +# 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 . + +import gdb +from gdb.unwinder import Unwinder + + +# Count the number of times TestUnwinder.__call__ is called. +TestUnwinder_Call_Count = 0 + + +# A frame unwinder that never claims any frame, but does send a packet +# when sniffing the frame. As the packet is only sent to the +# currently selected inferior then we never need to switch thread to +# send the packet, and so we should never need to flush the frame +# cache. +class TestUnwinder(Unwinder): + def __init__(self): + Unwinder.__init__(self, "send packet unwinder") + + call_count = 0 + + def __call__(self, pending_frame): + TestUnwinder.call_count += 1 + + gdb.selected_inferior().connection.send_packet("vMustReplyEmpty") + + # This unwinder never claims any frames. + return None + + +gdb.unwinder.register_unwinder(None, TestUnwinder(), True) + +print("Sourcing complete.") diff --git a/gdb/testsuite/gdb.python/py-send-packet.exp b/gdb/testsuite/gdb.python/py-send-packet.exp index 4464c1c5123..8296b867ae2 100644 --- a/gdb/testsuite/gdb.python/py-send-packet.exp +++ b/gdb/testsuite/gdb.python/py-send-packet.exp @@ -26,69 +26,117 @@ standard_testfile require allow_gdbserver_tests allow_python_tests -if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile}] } { +if { [build_executable "failed to build" ${testfile} ${srcfile}] } { return } -# Make sure we're disconnected, in case we're testing with an -# extended-remote board, therefore already connected. -gdb_test "disconnect" ".*" - -gdbserver_run "" - -gdb_breakpoint "breakpt" -gdb_continue_to_breakpoint "breakpt" - -# Source the python script. set remote_python_file [gdb_remote_download host \ ${srcdir}/${subdir}/${testfile}.py] -gdb_test "source $remote_python_file" "Sourcing complete\\." \ - "source ${testfile}.py script" -# The test is actually written in the Python script. Run it now. -gdb_test "python run_send_packet_test()" "Send packet test passed" +# Start GDB debugging the global TESTFILE. Exercise the +# RemoteTargetConnection.send_packet API to read the auxv data for the +# inferior, the thread list for the inferior, and to set a global +# within the inferior. +# +# When MULTI_INFERIOR is true a second inferior is started and +# selected; an inferior with no remote connection. In this case we +# are checking that calling RemoteTargetConnection.send_packet on a +# stored RemoteTargetConnection object works as expected. +proc run_test { multi_inferior } { + clean_restart $::testfile -# Check the string representation of a remote target connection. -gdb_test "python print(gdb.selected_inferior().connection)" \ - "" + # Make sure we're disconnected, in case we're testing with an + # extended-remote board, therefore already connected. + gdb_test "disconnect" ".*" -# Check to see if there's any auxv data for this target. -gdb_test_multiple "info auxv" "" { - -re -wrap "The program has no auxiliary information now\\. " { - set skip_auxv_test true - } - -re -wrap "0\\s+AT_NULL\\s+End of vector\\s+0x0" { - set skip_auxv_test false - } -} + gdbserver_run "" -if { ! $skip_auxv_test } { - # Use 'maint packet' to fetch the auxv data. - set reply_data "" - gdb_test_multiple "maint packet qXfer:auxv:read::0,1000" "" { - -re "sending: \"qXfer:auxv:read::0,1000\"\r\n" { - exp_continue + gdb_breakpoint "breakpt" + gdb_continue_to_breakpoint "breakpt" + + # Source the python script. + gdb_test "source $::remote_python_file" "Sourcing complete\\." \ + "source ${::testfile}.py script" + + # Check to see if there's any auxv data for this target. + set skip_auxv_test false + gdb_test_multiple "info auxv" "" { + -re -wrap "The program has no auxiliary information now\\." { + set skip_auxv_test true } - -re -wrap "received: \"(.*)\"" { - set reply_data $expect_out(1,string) + -re -wrap "0\\s+AT_NULL\\s+End of vector\\s+0x0" { + set skip_auxv_test false } } - # Escape any backslash characters in the output, so we can safely - # pass a string through to Python. - set reply_data [string map {\\ \\\\} $reply_data] - gdb_assert { ![string equal "$reply_data" ""] } + set auxv_reply_data "" + if { ! $skip_auxv_test } { + # Use 'maint packet' to collect the auxv data. This only + # works on the current inferior, so needs to be done before we + # might add a new inferior. + gdb_test_multiple "maint packet qXfer:auxv:read::0,1000" "" { + -re "sending: \"qXfer:auxv:read::0,1000\"\r\n" { + exp_continue + } + -re -wrap "received: \"(.*)\"" { + set auxv_reply_data $expect_out(1,string) + } + } - # Run the test, fetches the auxv data in Python and confirm it - # matches the expected results. - gdb_test "python run_auxv_send_packet_test(\"$reply_data\")" \ - "auxv send packet test passed" \ - "call python run_auxv_send_packet_test function" + # Escape any backslash characters in the output, so we can safely + # pass a string through to Python. + set auxv_reply_data [string map {\\ \\\\} $auxv_reply_data] + gdb_assert { ![string equal "$auxv_reply_data" ""] } \ + "have got some auxv data" + } + + # If the test requires it, add a second inferior, and make it the + # current inferior. + if { $multi_inferior } { + gdb_test_no_output "python inf=gdb.selected_inferior()" \ + "capture inferior 1" + set inferior "inf" + + gdb_test "add-inferior -no-connection" ".*" + gdb_test "inferior 2" ".*" + } else { + set inferior "gdb.selected_inferior()" + } + + # The test is actually written in the Python script. Run it now. + gdb_test "python run_send_packet_test($inferior)" "Send packet test passed" + + # Check the string representation of a remote target connection. + gdb_test "python print($inferior.connection)" \ + "" + + if { ! $skip_auxv_test } { + # Run the test, fetches the auxv data in Python and confirm it + # matches the expected results. + gdb_test "python run_auxv_send_packet_test($inferior, \"$auxv_reply_data\")" \ + "auxv send packet test passed" \ + "call python run_auxv_send_packet_test function" + } + + # The final test relies on gdb.parse_and_eval, so needs the + # correct inferior selected. + if { $multi_inferior } { + gdb_test "inferior 1" ".*" "return to remote inferior" + } + + set sizeof_global_var [get_valueof "/d" "sizeof(global_var)" "UNKNOWN"] + if { $sizeof_global_var == 4 } { + gdb_test_no_output "set debug remote 1" + gdb_test "python run_set_global_var_test()" \ + "set global_var test passed" + } } -set sizeof_global_var [get_valueof "/d" "sizeof(global_var)" "UNKNOWN"] -if { $sizeof_global_var == 4 } { - gdb_test_no_output "set debug remote 1" - gdb_test "python run_set_global_var_test()" \ - "set global_var test passed" +set modes { false } +if {[allow_multi_inferior_tests]} { + lappend modes true +} + +foreach_with_prefix multi_inferior $modes { + run_test $multi_inferior } diff --git a/gdb/testsuite/gdb.python/py-send-packet.py b/gdb/testsuite/gdb.python/py-send-packet.py index 46be26cac1b..ac66ed2acbe 100644 --- a/gdb/testsuite/gdb.python/py-send-packet.py +++ b/gdb/testsuite/gdb.python/py-send-packet.py @@ -19,7 +19,7 @@ import gdb # Make use of gdb.RemoteTargetConnection.send_packet to fetch the -# thread list from the remote target. +# thread list from the remote target for inferior INF. # # Sending existing serial protocol packets like this is not a good # idea, there should be better ways to get this information using an @@ -28,10 +28,10 @@ import gdb # Really, the send_packet API would be used to send target # specific packets to the target, but these are, by definition, target # specific, so hard to test in a general testsuite. -def get_thread_list_str(): +def get_thread_list_str(inf): start_pos = 0 thread_desc = "" - conn = gdb.selected_inferior().connection + conn = inf.connection if not isinstance(conn, gdb.RemoteTargetConnection): raise gdb.GdbError("connection is the wrong type") while True: @@ -46,19 +46,19 @@ def get_thread_list_str(): # Use gdb.RemoteTargetConnection.send_packet to manually fetch the -# thread list, then extract the thread list using the gdb.Inferior and -# gdb.InferiorThread API. Compare the two results to ensure we -# managed to successfully read the thread list from the remote. -def run_send_packet_test(): +# thread list for inferior INF. Then extract the thread list using +# the gdb.Inferior and gdb.InferiorThread API. Compare the two +# results to ensure we managed to successfully read the thread list +# from the remote. +def run_send_packet_test(inf): # Find the IDs of all current threads. all_threads = {} - for inf in gdb.inferiors(): - for thr in inf.threads(): - id = "p%x.%x" % (thr.ptid[0], thr.ptid[1]) - all_threads[id] = False + for thr in inf.threads(): + id = "p%x.%x" % (thr.ptid[0], thr.ptid[1]) + all_threads[id] = False # Now fetch the thread list from the remote, and parse the XML. - str = get_thread_list_str() + str = get_thread_list_str(inf) threads_xml = ET.fromstring(str) # Look over all threads in the XML list and check we expected to @@ -66,14 +66,14 @@ def run_send_packet_test(): for thr in threads_xml: id = thr.get("id") if id not in all_threads: - raise "found unexpected thread in remote thread list" + raise gdb.GdbError("found unexpected thread in remote thread list") else: all_threads[id] = True # Check that all the threads were found in the XML list. for id in all_threads: if not all_threads[id]: - raise "thread missingt from remote thread list" + raise gdb.GdbError("thread missing from remote thread list") # Test complete. print("Send packet test passed") @@ -93,12 +93,11 @@ def bytes_to_string(byte_array): return res -# A very simple test for sending the packet that reads the auxv data. -# We convert the result to a string and expect to find some -# hex-encoded bytes in the output. This test will only work on -# targets that actually supply auxv data. -def run_auxv_send_packet_test(expected_result): - inf = gdb.selected_inferior() +# A very simple test for sending the packet that reads the auxv data +# for inferior INF. We convert the result to a string and expect to +# find some hex-encoded bytes in the output. This test will only work +# on targets that actually supply auxv data. +def run_auxv_send_packet_test(inf, expected_result): conn = inf.connection assert isinstance(conn, gdb.RemoteTargetConnection) res = conn.send_packet("qXfer:auxv:read::0,1000")