From patchwork Fri Jul 14 17:06:30 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tom Tromey X-Patchwork-Id: 72721 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 75DA2385701C for ; Fri, 14 Jul 2023 17:07:39 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 75DA2385701C DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1689354459; bh=WWIbrthQlwaJVWDTaXKErKdde564Bl6uwIhxZT57/tI=; 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=ED2/HHoxAIBZy3F5ZGICypkAuDF5YoP+N4ThClzkcLuuu9D7SX2FRgvImQP3F7gmu UiIb1/thMhwha5vLRAwWQ+Ad0BXT4bHDMFrZGFSgCIcJjhVwf+zeDRXfJ7ezL1znXE RENP01CRYqW6tvKNTEMqCOmh9qudC/hvOy0321aY= X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mail-io1-xd2c.google.com (mail-io1-xd2c.google.com [IPv6:2607:f8b0:4864:20::d2c]) by sourceware.org (Postfix) with ESMTPS id 71C26385840C for ; Fri, 14 Jul 2023 17:06:39 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 71C26385840C Received: by mail-io1-xd2c.google.com with SMTP id ca18e2360f4ac-78374596182so86924739f.0 for ; Fri, 14 Jul 2023 10:06:39 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1689354398; x=1691946398; 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=WWIbrthQlwaJVWDTaXKErKdde564Bl6uwIhxZT57/tI=; b=dunQRbgOm3n2Udf0ZcZWnRD4EQAdlUBG2bEJNQNY37gTVsF8H0UR7iSdFGNOsjiJyb b0hFkUze7FPRYK8tA0qxzPsVnwUQs7/VEAQtAt0pclBwV48DZgcZk0cZa57jqo0sJDZK O3DYu9USALK7tZJdWu2tSujglBF1B4S12tD5NMAGDfeCKiNK/RPpsPcdmHGLTjApzVyY knPGg0wjzVyRlk3zk1VfCcQ6X4QB8CmN0hjlHFwtlxyatKGp+s1kF74Q5Ws57aeOYdKx S9Jkzx/qzC3dULFmHhgtWwTNrCYVbgM8k307qX7glEX9yqjmNOQpg0f6lsNueTstW0CT yJKA== X-Gm-Message-State: ABy/qLb6GI0ZN5aC3giYYpzdCqdAOhxyLzDF+CkdMcbyCo/jnY8RGOvt +rkJ0rzDad5YC/H4s+aYkVjOKKQshoxJlaYqutpgxw== X-Google-Smtp-Source: APBJJlFGlbzyVlbqh7shMziGE/e0i0uQOt3vZ6knDXuw1LG4B0rho/RAHQHZMvaJ53PBoYrf+Wlr2w== X-Received: by 2002:a05:6602:2114:b0:783:65ba:8614 with SMTP id x20-20020a056602211400b0078365ba8614mr5381213iox.10.1689354398605; Fri, 14 Jul 2023 10:06:38 -0700 (PDT) Received: from localhost.localdomain (75-166-135-140.hlrn.qwest.net. [75.166.135.140]) by smtp.gmail.com with ESMTPSA id cz8-20020a0566384a0800b0042bb09e9345sm2667476jab.90.2023.07.14.10.06.38 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 14 Jul 2023 10:06:38 -0700 (PDT) Date: Fri, 14 Jul 2023 11:06:30 -0600 Subject: [PATCH v4 6/6] Use correct inferior in Inferior.read_memory et al MIME-Version: 1.0 Message-Id: <20230714-py-inf-fixes-30615-v4-6-9189744d8547@adacore.com> References: <20230714-py-inf-fixes-30615-v4-0-9189744d8547@adacore.com> In-Reply-To: <20230714-py-inf-fixes-30615-v4-0-9189744d8547@adacore.com> To: gdb-patches@sourceware.org X-Mailer: b4 0.12.3 X-Spam-Status: No, score=-11.5 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 added a few missing calls to INFPY_REQUIRE_VALID to these methods. Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30615 Reviewed-By: Tom Tromey --- gdb/python/py-inferior.c | 43 ++++++++++++++++++++++++++------ gdb/testsuite/gdb.python/py-inferior.exp | 27 ++++++++++++++++++++ 2 files changed, 63 insertions(+), 7 deletions(-) diff --git a/gdb/python/py-inferior.c b/gdb/python/py-inferior.c index af8bd8855a3..f6000b944da 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,11 @@ infpy_read_memory (PyObject *self, PyObject *args, PyObject *kw) try { + /* Use this scoped-restore because we want to be able to read + memory from an unwinder. */ + scoped_restore_current_inferior_for_memory restore_inferior + (inf->inferior, any_thread_of_inferior (inf->inferior)->ptid); + buffer.reset ((gdb_byte *) xmalloc (length)); read_memory (addr, buffer.get (), length); @@ -565,6 +574,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 +583,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 +603,13 @@ infpy_write_memory (PyObject *self, PyObject *args, PyObject *kw) try { + /* It's probably not too important to avoid invalidating the + frame cache when writing memory, but this scoped-restore is + still used here, just to keep the code similar to other code + in this file. */ + scoped_restore_current_inferior_for_memory restore_inferior + (inf->inferior, any_thread_of_inferior (inf->inferior)->ptid); + 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,13 @@ infpy_search_memory (PyObject *self, PyObject *args, PyObject *kw) try { + /* It's probably not too important to avoid invalidating the + frame cache when searching memory, but this scoped-restore is + still used here, just to keep the code similar to other code + in this file. */ + scoped_restore_current_inferior_for_memory restore_inferior + (inf->inferior, any_thread_of_inferior (inf->inferior)->ptid); + found = target_search_memory (start_addr, length, buffer, pattern_size, &found_addr); @@ -910,12 +939,12 @@ infpy_get_main_name (PyObject *self, void *closure) try { /* 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_program_space restore_current_progspace; - set_current_program_space (inf->inferior->pspace); + reach into memory. It's probably not too important to avoid + invalidating the frame cache here, but this scoped-restore is + still used, just to keep the code similar to other code in + this file. */ + scoped_restore_current_inferior_for_memory restore_inferior + (inf->inferior, any_thread_of_inferior (inf->inferior)->ptid); name = main_name (); } diff --git a/gdb/testsuite/gdb.python/py-inferior.exp b/gdb/testsuite/gdb.python/py-inferior.exp index 8762b6992ca..13beebd08cc 100644 --- a/gdb/testsuite/gdb.python/py-inferior.exp +++ b/gdb/testsuite/gdb.python/py-inferior.exp @@ -91,6 +91,7 @@ gdb_py_test_silent_cmd "python addr = gdb.selected_frame ().read_var ('str')" \ gdb_test "python astr = gdb.inferiors()\[0\].read_memory (addr, 5); print(astr)" \ "" \ "read str contents" +gdb_test "python print(astr\[0\])" "b'h'" 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)" \ @@ -98,6 +99,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]*} @@ -115,6 +120,10 @@ 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" "Switching to 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" @@ -128,6 +137,24 @@ 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_test "python astr = gdb.inferiors()\[0\].read_memory (addr, 5); print(astr)" \ + "" \ + "read str while other inferior selected" +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" "Switching to 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 *"