diff options
author | Andrew Burgess <andrew.burgess@embecosm.com> | 2021-09-16 18:30:35 +0100 |
---|---|---|
committer | Andrew Burgess <andrew.burgess@embecosm.com> | 2021-10-22 13:43:42 +0100 |
commit | 625f7b1cdc771befb362370c42e32a3476abdb85 (patch) | |
tree | a39ec69f519d1bcd69d3bc591c41b00c46ca4436 /gdb/python/py-membuf.c | |
parent | 8b87fbe6bb5f682fef889630664884ea8e7d6444 (diff) | |
download | binutils-625f7b1cdc771befb362370c42e32a3476abdb85.zip binutils-625f7b1cdc771befb362370c42e32a3476abdb85.tar.gz binutils-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.
Diffstat (limited to 'gdb/python/py-membuf.c')
-rw-r--r-- | gdb/python/py-membuf.c | 226 |
1 files changed, 226 insertions, 0 deletions
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 */ +}; |