aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Burgess <andrew.burgess@embecosm.com>2021-09-16 18:30:35 +0100
committerAndrew Burgess <andrew.burgess@embecosm.com>2021-10-22 13:43:42 +0100
commit625f7b1cdc771befb362370c42e32a3476abdb85 (patch)
treea39ec69f519d1bcd69d3bc591c41b00c46ca4436
parent8b87fbe6bb5f682fef889630664884ea8e7d6444 (diff)
downloadgdb-625f7b1cdc771befb362370c42e32a3476abdb85.zip
gdb-625f7b1cdc771befb362370c42e32a3476abdb85.tar.gz
gdb-625f7b1cdc771befb362370c42e32a3476abdb85.tar.bz2
gdb/python: move gdb.Membuf support into a new file
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.
-rw-r--r--gdb/Makefile.in1
-rw-r--r--gdb/python/py-inferior.c182
-rw-r--r--gdb/python/py-membuf.c226
-rw-r--r--gdb/python/python-internal.h5
-rw-r--r--gdb/python/python.c1
5 files changed, 236 insertions, 179 deletions
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 4201f65..ec5d332 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 c8de41d..aec8c0f 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 0000000..3978ace
--- /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 2ad3bc9..24e28bc 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 ()
+ 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 5b1c295..c81814c 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;