[3/5] gdb/python: move gdb.Membuf support into a new file

Message ID b89b6b8b568b7c2e106118799711b4ad6d2232cd.1634162144.git.andrew.burgess@embecosm.com
State New
Headers show
Series
  • Add Python API for the disassembler
Related show

Commit Message

Andrew Burgess Oct. 13, 2021, 9:59 p.m.
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

-- 
2.25.4

Comments

Tom Tromey Oct. 20, 2021, 8:42 p.m. | #1
>>>>> "Andrew" == Andrew Burgess <andrew.burgess@embecosm.com> writes:


Andrew> So, then I moved all of the Membuf related code out into a new file,
Andrew> gdb/python/py-membuf.c, the interface is gdbpy_buffer_to_membuf, which
Andrew> wraps an array of bytes into a gdb.Membuf object.

I didn't read the patch in too much detail, but I think the general idea
is great.

Andrew> +int gdbpy_initialize_membuf (void)
Andrew> +  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;

This can use just () instead of (void).

Tom
Andrew Burgess Oct. 22, 2021, 12:52 p.m. | #2
* Tom Tromey <tom@tromey.com> [2021-10-20 14:42:06 -0600]:

> >>>>> "Andrew" == Andrew Burgess <andrew.burgess@embecosm.com> writes:

> 

> Andrew> So, then I moved all of the Membuf related code out into a new file,

> Andrew> gdb/python/py-membuf.c, the interface is gdbpy_buffer_to_membuf, which

> Andrew> wraps an array of bytes into a gdb.Membuf object.

> 

> I didn't read the patch in too much detail, but I think the general idea

> is great.

> 

> Andrew> +int gdbpy_initialize_membuf (void)

> Andrew> +  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;

> 

> This can use just () instead of (void).


Thanks, I made this change.

As I didn't really change any of the code, just moved it to a new
file, I took your liking the idea as good enough, and pushed this
patch.

Thanks,
Andrew

Patch

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<gdb_byte> 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_object> 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 <http://www.gnu.org/licenses/>.  */
+
+#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<gdb_byte> buffer,
+			CORE_ADDR address,
+			ULONGEST length)
+{
+  gdbpy_ref<membuf_object> 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<thread_object> create_thread_object (struct thread_info *tp);
 gdbpy_ref<> thread_to_thread_object (thread_info *thr);;
 gdbpy_ref<inferior_object> inferior_to_inferior_object (inferior *inf);
 
+PyObject *gdbpy_buffer_to_membuf (gdb::unique_xmalloc_ptr<gdb_byte> 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;