From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-wr1-x42d.google.com (mail-wr1-x42d.google.com [IPv6:2a00:1450:4864:20::42d]) by sourceware.org (Postfix) with ESMTPS id E7E5A3858013 for ; Wed, 13 Oct 2021 21:59:19 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org E7E5A3858013 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=embecosm.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=embecosm.com Received: by mail-wr1-x42d.google.com with SMTP id e12so13018586wra.4 for ; Wed, 13 Oct 2021 14:59:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=embecosm.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=6f9l68IJ2BHUYKmlM/Vd3KkHPkYAD8Xv12IVZ5zsyJU=; b=YmOP8bxvlUWw6ARt6nCBqAwhbYg/b/uzlue5Nul/Jg5gSoNC1/dC7TFm63hsZAsVOz c//zEFHHkn6wb3VM9cyeveygqDay97wePoHRvlk0omhJtE3ylhn6tm1vSU6a1kYl+zmd aMK8yFzWOK4FDGOdHSKOLUW0wjvBjuiTZaerGP8GVHY9LiirC08d+5AH3gxh5D3+2EX0 aCnVk6L/grIlzdPhfSKmfdCAY+jg0Unx9b3VgWL0kUy1OyD4DY0g0DNzUzrfMOXv71aF LK0svOiU3dupZ4CRIqd+a822B1U+jkL+zvpjONuN5G9IUh0cFBJp4AUEWdMXwAjo0xJc /18w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=6f9l68IJ2BHUYKmlM/Vd3KkHPkYAD8Xv12IVZ5zsyJU=; b=DM1izJh+eqMMgev5kuyPCDwEkhxZ7dYnRYqen+DCoE+z0NqvKcV/t//dYwxgz0aMo0 5DMNP1OpfaAhkrCy71wr+sdYFLZcmMVLo6MAh6mg5VQYAkWc9Wsz38MpAWVTABHnmXPH pnUDymGrJfENjPKLGUKv8t5uaaD10B+2gLaPYS2Y4bletRCo2HJuDQtKPfD0qHIlC1gu GzJ4uHWKe1wTVjUKMERcBlLTrna0j5V/Yq0uksGzgc1rOtxFpSlxWC/Ab3U7NSJeKbcj DX8+9yi5QhShE5Sr492WcM11uw95JCigvluR71XImxtbur55PYAWH+Zs3NPMV49SFIM6 5F8g== X-Gm-Message-State: AOAM531qk4CsFoMiQXyd2z/xxDjzLrwMfUJ4R9pJSZFQt4WDnGjRfPSd kWgJAnOtlw5y+v2XnGmaDmFy8FtmtrkmXg== X-Google-Smtp-Source: ABdhPJydyjVDvvY0YbH/UlHVkj5jBdhPNpV3aSeQ4dAwUntCuQEUQbbsE2oLiFy1SIXghaKBhVdxNQ== X-Received: by 2002:a05:600c:4e88:: with SMTP id f8mr15558970wmq.185.1634162356918; Wed, 13 Oct 2021 14:59:16 -0700 (PDT) Received: from localhost (host212-140-123-151.range212-140.btcentralplus.com. [212.140.123.151]) by smtp.gmail.com with ESMTPSA id x17sm686082wrc.51.2021.10.13.14.59.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 13 Oct 2021 14:59:16 -0700 (PDT) From: Andrew Burgess To: gdb-patches@sourceware.org Subject: [PATCH 3/5] gdb/python: move gdb.Membuf support into a new file Date: Wed, 13 Oct 2021 22:59:08 +0100 Message-Id: X-Mailer: git-send-email 2.25.4 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-11.9 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) 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-List-Received-Date: Wed, 13 Oct 2021 21:59:22 -0000 In a future commit I'm going to be creating gdb.Membuf objects from a new file within gdb/python/py*.c. Currently all gdb.Membuf objects are created directly within infpy_read_memory (as a result of calling gdb.Inferior.read_memory()). Initially I split out the Membuf creation code into a new function, and left the new function in gdb/python/py-inferior.c, however, it felt a little random that the Membuf creation code should live with the inferior handling code. So, then I moved all of the Membuf related code out into a new file, gdb/python/py-membuf.c, the interface is gdbpy_buffer_to_membuf, which wraps an array of bytes into a gdb.Membuf object. Most of the code is moved directly from py-inferior.c with only minor tweaks to layout and replacing NULL with nullptr, hence, I've left the copyright date on py-membuf.c as 2009-2021 to match py-inferior.c. Currently, the only user of this code is still py-inferior.c, but in later commits this will change. There should be no user visible changes after this commit. --- gdb/Makefile.in | 1 + gdb/python/py-inferior.c | 182 +--------------------------- gdb/python/py-membuf.c | 226 +++++++++++++++++++++++++++++++++++ gdb/python/python-internal.h | 5 + gdb/python/python.c | 1 + 5 files changed, 236 insertions(+), 179 deletions(-) create mode 100644 gdb/python/py-membuf.c diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 4201f65e68d..ec5d332c145 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -407,6 +407,7 @@ SUBDIR_PYTHON_SRCS = \ python/py-instruction.c \ python/py-lazy-string.c \ python/py-linetable.c \ + python/py-membuf.c \ python/py-newobjfileevent.c \ python/py-objfile.c \ python/py-param.c \ diff --git a/gdb/python/py-inferior.c b/gdb/python/py-inferior.c index c8de41dd009..aec8c0f73cb 100644 --- a/gdb/python/py-inferior.c +++ b/gdb/python/py-inferior.c @@ -62,18 +62,6 @@ extern PyTypeObject inferior_object_type static const struct inferior_data *infpy_inf_data_key; -struct membuf_object { - PyObject_HEAD - void *buffer; - - /* These are kept just for mbpy_str. */ - CORE_ADDR addr; - CORE_ADDR length; -}; - -extern PyTypeObject membuf_object_type - CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("membuf_object"); - /* Require that INFERIOR be a valid inferior ID. */ #define INFPY_REQUIRE_VALID(Inferior) \ do { \ @@ -514,7 +502,7 @@ infpy_read_memory (PyObject *self, PyObject *args, PyObject *kw) { CORE_ADDR addr, length; gdb::unique_xmalloc_ptr buffer; - PyObject *addr_obj, *length_obj, *result; + PyObject *addr_obj, *length_obj; static const char *keywords[] = { "address", "length", NULL }; if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "OO", keywords, @@ -536,23 +524,8 @@ infpy_read_memory (PyObject *self, PyObject *args, PyObject *kw) GDB_PY_HANDLE_EXCEPTION (except); } - gdbpy_ref membuf_obj (PyObject_New (membuf_object, - &membuf_object_type)); - if (membuf_obj == NULL) - return NULL; - - membuf_obj->buffer = buffer.release (); - membuf_obj->addr = addr; - membuf_obj->length = length; -#ifdef IS_PY3K - result = PyMemoryView_FromObject ((PyObject *) membuf_obj.get ()); -#else - result = PyBuffer_FromReadWriteObject ((PyObject *) membuf_obj.get (), 0, - Py_END_OF_BUFFER); -#endif - - return result; + return gdbpy_buffer_to_membuf (std::move (buffer), addr, length); } /* Implementation of Inferior.write_memory (address, buffer [, length]). @@ -602,93 +575,6 @@ infpy_write_memory (PyObject *self, PyObject *args, PyObject *kw) Py_RETURN_NONE; } -/* Destructor of Membuf objects. */ -static void -mbpy_dealloc (PyObject *self) -{ - xfree (((membuf_object *) self)->buffer); - Py_TYPE (self)->tp_free (self); -} - -/* Return a description of the Membuf object. */ -static PyObject * -mbpy_str (PyObject *self) -{ - membuf_object *membuf_obj = (membuf_object *) self; - - return PyString_FromFormat (_("Memory buffer for address %s, \ -which is %s bytes long."), - paddress (python_gdbarch, membuf_obj->addr), - pulongest (membuf_obj->length)); -} - -#ifdef IS_PY3K - -static int -get_buffer (PyObject *self, Py_buffer *buf, int flags) -{ - membuf_object *membuf_obj = (membuf_object *) self; - int ret; - - ret = PyBuffer_FillInfo (buf, self, membuf_obj->buffer, - membuf_obj->length, 0, - PyBUF_CONTIG); - - /* Despite the documentation saying this field is a "const char *", - in Python 3.4 at least, it's really a "char *". */ - buf->format = (char *) "c"; - - return ret; -} - -#else - -static Py_ssize_t -get_read_buffer (PyObject *self, Py_ssize_t segment, void **ptrptr) -{ - membuf_object *membuf_obj = (membuf_object *) self; - - if (segment) - { - PyErr_SetString (PyExc_SystemError, - _("The memory buffer supports only one segment.")); - return -1; - } - - *ptrptr = membuf_obj->buffer; - - return membuf_obj->length; -} - -static Py_ssize_t -get_write_buffer (PyObject *self, Py_ssize_t segment, void **ptrptr) -{ - return get_read_buffer (self, segment, ptrptr); -} - -static Py_ssize_t -get_seg_count (PyObject *self, Py_ssize_t *lenp) -{ - if (lenp) - *lenp = ((membuf_object *) self)->length; - - return 1; -} - -static Py_ssize_t -get_char_buffer (PyObject *self, Py_ssize_t segment, char **ptrptr) -{ - void *ptr = NULL; - Py_ssize_t ret; - - ret = get_read_buffer (self, segment, &ptr); - *ptrptr = (char *) ptr; - - return ret; -} - -#endif /* IS_PY3K */ - /* Implementation of gdb.search_memory (address, length, pattern). ADDRESS is the address to start the search. LENGTH specifies the scope of the @@ -957,12 +843,7 @@ gdbpy_initialize_inferior (void) gdb::observers::inferior_removed.attach (python_inferior_deleted, "py-inferior"); - membuf_object_type.tp_new = PyType_GenericNew; - if (PyType_Ready (&membuf_object_type) < 0) - return -1; - - return gdb_pymodule_addobject (gdb_module, "Membuf", - (PyObject *) &membuf_object_type); + return 0; } static gdb_PyGetSetDef inferior_object_getset[] = @@ -1053,60 +934,3 @@ PyTypeObject inferior_object_type = 0, /* tp_init */ 0 /* tp_alloc */ }; - -#ifdef IS_PY3K - -static PyBufferProcs buffer_procs = -{ - get_buffer -}; - -#else - -static PyBufferProcs buffer_procs = { - get_read_buffer, - get_write_buffer, - get_seg_count, - get_char_buffer -}; -#endif /* IS_PY3K */ - -PyTypeObject membuf_object_type = { - PyVarObject_HEAD_INIT (NULL, 0) - "gdb.Membuf", /*tp_name*/ - sizeof (membuf_object), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - mbpy_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - mbpy_str, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - &buffer_procs, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT, /*tp_flags*/ - "GDB memory buffer object", /*tp_doc*/ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - 0, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ -}; diff --git a/gdb/python/py-membuf.c b/gdb/python/py-membuf.c new file mode 100644 index 00000000000..3978acec907 --- /dev/null +++ b/gdb/python/py-membuf.c @@ -0,0 +1,226 @@ +/* Python memory buffer interface for reading inferior memory. + + Copyright (C) 2009-2021 Free Software Foundation, Inc. + + This file is part of GDB. + + 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 . */ + +#include "defs.h" +#include "python-internal.h" + +struct membuf_object { + PyObject_HEAD + + /* Pointer to the raw data, and array of gdb_bytes. */ + void *buffer; + + /* The address from where the data was read, held for mbpy_str. */ + CORE_ADDR addr; + + /* The number of octets in BUFFER. */ + CORE_ADDR length; +}; + +extern PyTypeObject membuf_object_type + CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("membuf_object"); + +/* Wrap BUFFER, ADDRESS, and LENGTH into a gdb.Membuf object. ADDRESS is + the address within the inferior that the contents of BUFFER were read, + and LENGTH is the number of octets in BUFFER. */ + +PyObject * +gdbpy_buffer_to_membuf (gdb::unique_xmalloc_ptr buffer, + CORE_ADDR address, + ULONGEST length) +{ + gdbpy_ref membuf_obj (PyObject_New (membuf_object, + &membuf_object_type)); + if (membuf_obj == nullptr) + return nullptr; + + membuf_obj->buffer = buffer.release (); + membuf_obj->addr = address; + membuf_obj->length = length; + + PyObject *result; +#ifdef IS_PY3K + result = PyMemoryView_FromObject ((PyObject *) membuf_obj.get ()); +#else + result = PyBuffer_FromReadWriteObject ((PyObject *) membuf_obj.get (), 0, + Py_END_OF_BUFFER); +#endif + + return result; +} + +/* Destructor for gdb.Membuf objects. */ + +static void +mbpy_dealloc (PyObject *self) +{ + xfree (((membuf_object *) self)->buffer); + Py_TYPE (self)->tp_free (self); +} + +/* Return a description of the gdb.Membuf object. */ + +static PyObject * +mbpy_str (PyObject *self) +{ + membuf_object *membuf_obj = (membuf_object *) self; + + return PyString_FromFormat (_("Memory buffer for address %s, \ +which is %s bytes long."), + paddress (python_gdbarch, membuf_obj->addr), + pulongest (membuf_obj->length)); +} + +#ifdef IS_PY3K + +static int +get_buffer (PyObject *self, Py_buffer *buf, int flags) +{ + membuf_object *membuf_obj = (membuf_object *) self; + int ret; + + ret = PyBuffer_FillInfo (buf, self, membuf_obj->buffer, + membuf_obj->length, 0, + PyBUF_CONTIG); + + /* Despite the documentation saying this field is a "const char *", + in Python 3.4 at least, it's really a "char *". */ + buf->format = (char *) "c"; + + return ret; +} + +#else + +static Py_ssize_t +get_read_buffer (PyObject *self, Py_ssize_t segment, void **ptrptr) +{ + membuf_object *membuf_obj = (membuf_object *) self; + + if (segment) + { + PyErr_SetString (PyExc_SystemError, + _("The memory buffer supports only one segment.")); + return -1; + } + + *ptrptr = membuf_obj->buffer; + + return membuf_obj->length; +} + +static Py_ssize_t +get_write_buffer (PyObject *self, Py_ssize_t segment, void **ptrptr) +{ + return get_read_buffer (self, segment, ptrptr); +} + +static Py_ssize_t +get_seg_count (PyObject *self, Py_ssize_t *lenp) +{ + if (lenp) + *lenp = ((membuf_object *) self)->length; + + return 1; +} + +static Py_ssize_t +get_char_buffer (PyObject *self, Py_ssize_t segment, char **ptrptr) +{ + void *ptr = nullptr; + Py_ssize_t ret; + + ret = get_read_buffer (self, segment, &ptr); + *ptrptr = (char *) ptr; + + return ret; +} + +#endif /* IS_PY3K */ + +/* General Python initialization callback. */ + +int +gdbpy_initialize_membuf (void) +{ + membuf_object_type.tp_new = PyType_GenericNew; + if (PyType_Ready (&membuf_object_type) < 0) + return -1; + + return gdb_pymodule_addobject (gdb_module, "Membuf", + (PyObject *) &membuf_object_type); +} + +#ifdef IS_PY3K + +static PyBufferProcs buffer_procs = +{ + get_buffer +}; + +#else + +static PyBufferProcs buffer_procs = { + get_read_buffer, + get_write_buffer, + get_seg_count, + get_char_buffer +}; + +#endif /* IS_PY3K */ + +PyTypeObject membuf_object_type = { + PyVarObject_HEAD_INIT (nullptr, 0) + "gdb.Membuf", /*tp_name*/ + sizeof (membuf_object), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + mbpy_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + mbpy_str, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + &buffer_procs, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT, /*tp_flags*/ + "GDB memory buffer object", /*tp_doc*/ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ +}; diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h index 2ad3bc944a7..735328b49c4 100644 --- a/gdb/python/python-internal.h +++ b/gdb/python/python-internal.h @@ -479,6 +479,9 @@ gdbpy_ref create_thread_object (struct thread_info *tp); gdbpy_ref<> thread_to_thread_object (thread_info *thr);; gdbpy_ref inferior_to_inferior_object (inferior *inf); +PyObject *gdbpy_buffer_to_membuf (gdb::unique_xmalloc_ptr buffer, + CORE_ADDR address, ULONGEST length); + const struct block *block_object_to_block (PyObject *obj); struct symbol *symbol_object_to_symbol (PyObject *obj); struct value *value_object_to_value (PyObject *self); @@ -550,6 +553,8 @@ int gdbpy_initialize_unwind (void) CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION; int gdbpy_initialize_tui () CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION; +int gdbpy_initialize_membuf (void) + CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION; /* A wrapper for PyErr_Fetch that handles reference counting for the caller. */ diff --git a/gdb/python/python.c b/gdb/python/python.c index 6c1baa167d9..2c2d8c5f217 100644 --- a/gdb/python/python.c +++ b/gdb/python/python.c @@ -1876,6 +1876,7 @@ do_start_initialization () || gdbpy_initialize_registers () < 0 || gdbpy_initialize_xmethods () < 0 || gdbpy_initialize_unwind () < 0 + || gdbpy_initialize_membuf () < 0 || gdbpy_initialize_tui () < 0) return false; -- 2.25.4