From patchwork Fri Jul 7 15:08:01 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tom Tromey X-Patchwork-Id: 72306 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 8FEFC3852ACD for ; Fri, 7 Jul 2023 15:10:07 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 8FEFC3852ACD DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1688742607; bh=H88h79Zx6GmlQ69v7nB1EeebnIjl+StdqbV4GA/8lgQ=; h=Date:Subject:References:In-Reply-To:To:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=Jx5JRUGWYlZwbDwePkeuuCUJFXX5kZMxzcT7DJEgYthnSAykmp8fOCcmVln0S1g9K oxRyJnyi7W8zoJXWfVukujR3fIiEi2nukgpfQvitq1R+vgZ4dIUKW3O4oETP8Z/wKu SGFamxV03GtjLFdJLmsG1G/yYcm4J2IFETZMtmWE= X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mail-io1-xd2f.google.com (mail-io1-xd2f.google.com [IPv6:2607:f8b0:4864:20::d2f]) by sourceware.org (Postfix) with ESMTPS id 7C79C3852ACC for ; Fri, 7 Jul 2023 15:08:03 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 7C79C3852ACC Received: by mail-io1-xd2f.google.com with SMTP id ca18e2360f4ac-7866189cff1so70517339f.0 for ; Fri, 07 Jul 2023 08:08:03 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1688742482; x=1691334482; h=to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=H88h79Zx6GmlQ69v7nB1EeebnIjl+StdqbV4GA/8lgQ=; b=ItMsTHy51OdFjMdK+BWhzQU868NDS+fejoWFyjJzFAt07GQnCcBQvxLJtzbdbPeJ68 SrgL82AlIf/ZWY+iaHJEjHXTJBZfU/knmDr1pYGxY/9hqImiSqTuLU4cc3dTWEzNXhlc PHJivu59MkJf/tcF0dpTuGBj01xWwDHjuhGxk2Bug6Kc9iZFefryhH9MzryY9EiLzkfo eAcFHoPciTJKTyjsyLc2Nph1M129uCyWvpKZ2lU/f6MUzsRZSVBwTb4Tcqr1DRmHtYaK GIXSfCEEVV/wTkOlod6VN05fR69bII9/NN+iR8P9FCYOsBdTCcNu+GPmXYCEsJOXalqF bjng== X-Gm-Message-State: ABy/qLbEuP+YoVE/fnAaDKNvv/QqgmmROeO2Hvy56+NPatgND4svK9C+ YUQdbam8zycobmzKwuaeunbxuOY4NF/7Vr+1aiksjA== X-Google-Smtp-Source: APBJJlFU1ILX4xOjauf3rhDNYRtT1mTdWERzUgrK/VLmEtTvFueWweXdkbHNSAtqK3yCXWjWVxOIgg== X-Received: by 2002:a5e:8914:0:b0:786:7100:72de with SMTP id k20-20020a5e8914000000b00786710072demr5390863ioj.16.1688742482481; Fri, 07 Jul 2023 08:08:02 -0700 (PDT) Received: from localhost.localdomain (75-166-135-140.hlrn.qwest.net. [75.166.135.140]) by smtp.gmail.com with ESMTPSA id b16-20020a5ea710000000b0076ffebfc9fasm1340650iod.47.2023.07.07.08.08.02 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 07 Jul 2023 08:08:02 -0700 (PDT) Date: Fri, 07 Jul 2023 09:08:01 -0600 Subject: [PATCH 5/5] Use correct inferior in Inferior.read_memory et al MIME-Version: 1.0 Message-Id: <20230707-py-inf-fixes-30615-v1-5-7792ab559530@adacore.com> References: <20230707-py-inf-fixes-30615-v1-0-7792ab559530@adacore.com> In-Reply-To: <20230707-py-inf-fixes-30615-v1-0-7792ab559530@adacore.com> To: gdb-patches@sourceware.org X-Mailer: b4 0.12.3 X-Spam-Status: No, score=-11.4 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE 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: Tom Tromey via Gdb-patches From: Tom Tromey Reply-To: Tom Tromey Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org Sender: "Gdb-patches" A user noticed that Inferior.read_memory and a few other Python APIs will always use the currently selected inferior, not the one passed to the call. This patch fixes the bug by arranging to switch to the inferior. I found this same issue in several APIs, so this fixes them all. I also found out that setting current_inferior isn't enough when reading memory -- one must also set inferior_ptid. This seems very confusing to me, especially considering that current_inferior must be set properly anyway in order to access the target stack. Finally, I also added a few missing calls to INFPY_REQUIRE_VALID to these methods. Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30615 --- gdb/python/py-inferior.c | 36 ++++++++++++++++++++++++++++---- gdb/testsuite/gdb.python/py-inferior.exp | 25 ++++++++++++++++++++++ 2 files changed, 57 insertions(+), 4 deletions(-) diff --git a/gdb/python/py-inferior.c b/gdb/python/py-inferior.c index af8bd8855a3..7fb422f621e 100644 --- a/gdb/python/py-inferior.c +++ b/gdb/python/py-inferior.c @@ -30,6 +30,7 @@ #include "gdbsupport/gdb_signals.h" #include "py-event.h" #include "py-stopevent.h" +#include "progspace-and-thread.h" #include using thread_map_t @@ -528,11 +529,14 @@ gdbpy_inferiors (PyObject *unused, PyObject *unused2) static PyObject * infpy_read_memory (PyObject *self, PyObject *args, PyObject *kw) { + inferior_object *inf = (inferior_object *) self; CORE_ADDR addr, length; gdb::unique_xmalloc_ptr buffer; PyObject *addr_obj, *length_obj; static const char *keywords[] = { "address", "length", NULL }; + INFPY_REQUIRE_VALID (inf); + if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "OO", keywords, &addr_obj, &length_obj)) return NULL; @@ -543,6 +547,12 @@ infpy_read_memory (PyObject *self, PyObject *args, PyObject *kw) try { + scoped_restore_current_inferior restore_inferior; + scoped_restore_current_pspace_and_thread restore_thread; + + thread_info *thr = any_thread_of_inferior (inf->inferior); + switch_to_thread_no_regs (thr); + buffer.reset ((gdb_byte *) xmalloc (length)); read_memory (addr, buffer.get (), length); @@ -565,6 +575,7 @@ infpy_read_memory (PyObject *self, PyObject *args, PyObject *kw) static PyObject * infpy_write_memory (PyObject *self, PyObject *args, PyObject *kw) { + inferior_object *inf = (inferior_object *) self; struct gdb_exception except; Py_ssize_t buf_len; const gdb_byte *buffer; @@ -573,6 +584,8 @@ infpy_write_memory (PyObject *self, PyObject *args, PyObject *kw) static const char *keywords[] = { "address", "buffer", "length", NULL }; Py_buffer pybuf; + INFPY_REQUIRE_VALID (inf); + if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "Os*|O", keywords, &addr_obj, &pybuf, &length_obj)) return NULL; @@ -591,6 +604,12 @@ infpy_write_memory (PyObject *self, PyObject *args, PyObject *kw) try { + scoped_restore_current_inferior restore_inferior; + scoped_restore_current_pspace_and_thread restore_thread; + + thread_info *thr = any_thread_of_inferior (inf->inferior); + switch_to_thread_no_regs (thr); + write_memory_with_notification (addr, buffer, length); } catch (gdb_exception &ex) @@ -604,7 +623,7 @@ infpy_write_memory (PyObject *self, PyObject *args, PyObject *kw) } /* Implementation of - gdb.search_memory (address, length, pattern). ADDRESS is the + Inferior.search_memory (address, length, pattern). ADDRESS is the address to start the search. LENGTH specifies the scope of the search from ADDRESS. PATTERN is the pattern to search for (and must be a Python object supporting the buffer protocol). @@ -614,6 +633,7 @@ infpy_write_memory (PyObject *self, PyObject *args, PyObject *kw) static PyObject * infpy_search_memory (PyObject *self, PyObject *args, PyObject *kw) { + inferior_object *inf = (inferior_object *) self; struct gdb_exception except; CORE_ADDR start_addr, length; static const char *keywords[] = { "address", "length", "pattern", NULL }; @@ -624,6 +644,8 @@ infpy_search_memory (PyObject *self, PyObject *args, PyObject *kw) int found = 0; Py_buffer pybuf; + INFPY_REQUIRE_VALID (inf); + if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "OOs*", keywords, &start_addr_obj, &length_obj, &pybuf)) @@ -656,6 +678,12 @@ infpy_search_memory (PyObject *self, PyObject *args, PyObject *kw) try { + scoped_restore_current_inferior restore_inferior; + scoped_restore_current_pspace_and_thread restore_thread; + + thread_info *thr = any_thread_of_inferior (inf->inferior); + switch_to_thread_no_regs (thr); + found = target_search_memory (start_addr, length, buffer, pattern_size, &found_addr); @@ -912,10 +940,10 @@ infpy_get_main_name (PyObject *self, void *closure) /* This is unfortunate but the implementation of main_name can reach into memory. */ scoped_restore_current_inferior restore_inferior; - set_current_inferior (inf->inferior); + scoped_restore_current_pspace_and_thread restore_thread; - scoped_restore_current_program_space restore_current_progspace; - set_current_program_space (inf->inferior->pspace); + thread_info *thr = any_thread_of_inferior (inf->inferior); + switch_to_thread_no_regs (thr); name = main_name (); } diff --git a/gdb/testsuite/gdb.python/py-inferior.exp b/gdb/testsuite/gdb.python/py-inferior.exp index 41e26878031..9b0643d63e2 100644 --- a/gdb/testsuite/gdb.python/py-inferior.exp +++ b/gdb/testsuite/gdb.python/py-inferior.exp @@ -90,6 +90,7 @@ gdb_py_test_silent_cmd "python addr = gdb.selected_frame ().read_var ('str')" \ "read str address" 0 gdb_py_test_silent_cmd "python astr = gdb.inferiors()\[0\].read_memory (addr, 5); print(str)" \ "read str contents" 1 +gdb_test "python print(astr\[0\])" .* gdb_py_test_silent_cmd "python a = bytes('a', 'ascii')" "" 0 gdb_py_test_silent_cmd "python astr\[1\] = a" "change str" 0 gdb_py_test_silent_cmd "python gdb.inferiors()\[0\].write_memory (addr, astr)" \ @@ -97,6 +98,10 @@ gdb_py_test_silent_cmd "python gdb.inferiors()\[0\].write_memory (addr, astr)" \ gdb_test "print str" " = \"hallo, testsuite\"" \ "ensure str was changed in the inferior" +# Add a new inferior here, so we can test that operations work on the +# correct inferior. +set num [add_inferior] + # Test memory search. set hex_number {0x[0-9a-fA-F][0-9a-fA-F]*} @@ -114,6 +119,9 @@ with_test_prefix "string" { gdb_test_no_output "py start_addr = search_buf.address" gdb_test_no_output "py length = search_buf.type.sizeof" + # Switch to the new inferior before testing. + gdb_test "inferior $num" ".*" "switch to inferior $num" + gdb_test "py print (gdb.inferiors()\[0\].search_memory (start_addr, length, 'aaa'))" \ "${one_pattern_found}" "find string pattern" @@ -127,6 +135,23 @@ with_test_prefix "string" { "${one_pattern_found}" "pattern found at end of range" } +# While still in the new inferior, test reading and writing memory +# again. +gdb_py_test_silent_cmd "python astr = gdb.inferiors()\[0\].read_memory (addr, 5); print(str)" \ + "read str while other inferior selected" 1 +gdb_test "python print(astr\[1\])" "b'a'" \ + "print a character from the string" +gdb_py_test_silent_cmd "python astr\[1\] = b'X'" "change str again" 0 +gdb_py_test_silent_cmd "python gdb.inferiors()\[0\].write_memory (addr, astr)" \ + "write str while other inferior selected" 1 + +gdb_test "inferior 1" ".*" "switch back to inferior 1" + +gdb_test "print str" " = \"hXllo, testsuite\"" \ + "ensure str was changed while other inferior selected" + +gdb_test_no_output "remove-inferiors $num" "remove-inferiors $num" + # Import struct to pack the following patterns. gdb_test_no_output "py from struct import *"