xref: /netbsd-src/external/gpl3/gdb.old/dist/gdb/python/py-membuf.c (revision 6881a4007f077b54e5f51159c52b9b25f57deb0d)
1 /* Python memory buffer interface for reading inferior memory.
2 
3    Copyright (C) 2009-2023 Free Software Foundation, Inc.
4 
5    This file is part of GDB.
6 
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11 
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16 
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19 
20 #include "defs.h"
21 #include "python-internal.h"
22 
23 struct membuf_object {
24   PyObject_HEAD
25 
26   /* Pointer to the raw data, and array of gdb_bytes.  */
27   void *buffer;
28 
29   /* The address from where the data was read, held for mbpy_str.  */
30   CORE_ADDR addr;
31 
32   /* The number of octets in BUFFER.  */
33   CORE_ADDR length;
34 };
35 
36 extern PyTypeObject membuf_object_type
37     CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("membuf_object");
38 
39 /* Wrap BUFFER, ADDRESS, and LENGTH into a gdb.Membuf object.  ADDRESS is
40    the address within the inferior that the contents of BUFFER were read,
41    and LENGTH is the number of octets in BUFFER.  */
42 
43 PyObject *
44 gdbpy_buffer_to_membuf (gdb::unique_xmalloc_ptr<gdb_byte> buffer,
45 			CORE_ADDR address,
46 			ULONGEST length)
47 {
48   gdbpy_ref<membuf_object> membuf_obj (PyObject_New (membuf_object,
49 						     &membuf_object_type));
50   if (membuf_obj == nullptr)
51     return nullptr;
52 
53   membuf_obj->buffer = buffer.release ();
54   membuf_obj->addr = address;
55   membuf_obj->length = length;
56 
57   return PyMemoryView_FromObject ((PyObject *) membuf_obj.get ());
58 }
59 
60 /* Destructor for gdb.Membuf objects.  */
61 
62 static void
63 mbpy_dealloc (PyObject *self)
64 {
65   xfree (((membuf_object *) self)->buffer);
66   Py_TYPE (self)->tp_free (self);
67 }
68 
69 /* Return a description of the gdb.Membuf object.  */
70 
71 static PyObject *
72 mbpy_str (PyObject *self)
73 {
74   membuf_object *membuf_obj = (membuf_object *) self;
75 
76   return PyUnicode_FromFormat (_("Memory buffer for address %s, \
77 which is %s bytes long."),
78 			       paddress (gdbpy_enter::get_gdbarch (),
79 					 membuf_obj->addr),
80 			       pulongest (membuf_obj->length));
81 }
82 
83 static int
84 get_buffer (PyObject *self, Py_buffer *buf, int flags)
85 {
86   membuf_object *membuf_obj = (membuf_object *) self;
87   int ret;
88 
89   ret = PyBuffer_FillInfo (buf, self, membuf_obj->buffer,
90 			   membuf_obj->length, 0,
91 			   PyBUF_CONTIG);
92 
93   /* Despite the documentation saying this field is a "const char *",
94      in Python 3.4 at least, it's really a "char *".  */
95   buf->format = (char *) "c";
96 
97   return ret;
98 }
99 
100 /* General Python initialization callback.  */
101 
102 int
103 gdbpy_initialize_membuf (void)
104 {
105   membuf_object_type.tp_new = PyType_GenericNew;
106   if (PyType_Ready (&membuf_object_type) < 0)
107     return -1;
108 
109   return gdb_pymodule_addobject (gdb_module, "Membuf",
110 				 (PyObject *) &membuf_object_type);
111 }
112 
113 static PyBufferProcs buffer_procs =
114 {
115   get_buffer
116 };
117 
118 PyTypeObject membuf_object_type = {
119   PyVarObject_HEAD_INIT (nullptr, 0)
120   "gdb.Membuf",			  /*tp_name*/
121   sizeof (membuf_object),	  /*tp_basicsize*/
122   0,				  /*tp_itemsize*/
123   mbpy_dealloc,			  /*tp_dealloc*/
124   0,				  /*tp_print*/
125   0,				  /*tp_getattr*/
126   0,				  /*tp_setattr*/
127   0,				  /*tp_compare*/
128   0,				  /*tp_repr*/
129   0,				  /*tp_as_number*/
130   0,				  /*tp_as_sequence*/
131   0,				  /*tp_as_mapping*/
132   0,				  /*tp_hash */
133   0,				  /*tp_call*/
134   mbpy_str,			  /*tp_str*/
135   0,				  /*tp_getattro*/
136   0,				  /*tp_setattro*/
137   &buffer_procs,		  /*tp_as_buffer*/
138   Py_TPFLAGS_DEFAULT,		  /*tp_flags*/
139   "GDB memory buffer object", 	  /*tp_doc*/
140   0,				  /* tp_traverse */
141   0,				  /* tp_clear */
142   0,				  /* tp_richcompare */
143   0,				  /* tp_weaklistoffset */
144   0,				  /* tp_iter */
145   0,				  /* tp_iternext */
146   0,				  /* tp_methods */
147   0,				  /* tp_members */
148   0,				  /* tp_getset */
149   0,				  /* tp_base */
150   0,				  /* tp_dict */
151   0,				  /* tp_descr_get */
152   0,				  /* tp_descr_set */
153   0,				  /* tp_dictoffset */
154   0,				  /* tp_init */
155   0,				  /* tp_alloc */
156 };
157