1 /* Python interface to lazy strings.
2
3 Copyright (C) 2010-2024 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 "python-internal.h"
21 #include "charset.h"
22 #include "value.h"
23 #include "valprint.h"
24 #include "language.h"
25
26 struct lazy_string_object {
27 PyObject_HEAD
28
29 /* Holds the address of the lazy string. */
30 CORE_ADDR address;
31
32 /* Holds the encoding that will be applied to the string
33 when the string is printed by GDB. If the encoding is set
34 to None then GDB will select the most appropriate
35 encoding when the sting is printed. */
36 char *encoding;
37
38 /* If TYPE is an array: If the length is known, then this value is the
39 array's length, otherwise it is -1.
40 If TYPE is not an array: Then this value represents the string's length.
41 In either case, if the value is -1 then the string will be fetched and
42 encoded up to the first null of appropriate width. */
43 long length;
44
45 /* This attribute holds the type of the string.
46 For example if the lazy string was created from a C "char*" then TYPE
47 represents a C "char*".
48 To get the type of the character in the string call
49 stpy_lazy_string_elt_type.
50 This is recorded as a PyObject so that we take advantage of support for
51 preserving the type should its owning objfile go away. */
52 PyObject *type;
53 };
54
55 extern PyTypeObject lazy_string_object_type
56 CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("lazy_string_object");
57
58 static PyObject *
stpy_get_address(PyObject * self,void * closure)59 stpy_get_address (PyObject *self, void *closure)
60 {
61 lazy_string_object *self_string = (lazy_string_object *) self;
62
63 return gdb_py_object_from_ulongest (self_string->address).release ();
64 }
65
66 static PyObject *
stpy_get_encoding(PyObject * self,void * closure)67 stpy_get_encoding (PyObject *self, void *closure)
68 {
69 lazy_string_object *self_string = (lazy_string_object *) self;
70 PyObject *result;
71
72 /* An encoding can be set to NULL by the user, so check before
73 attempting a Python FromString call. If NULL return Py_None. */
74 if (self_string->encoding)
75 result = PyUnicode_FromString (self_string->encoding);
76 else
77 {
78 result = Py_None;
79 Py_INCREF (result);
80 }
81
82 return result;
83 }
84
85 static PyObject *
stpy_get_length(PyObject * self,void * closure)86 stpy_get_length (PyObject *self, void *closure)
87 {
88 lazy_string_object *self_string = (lazy_string_object *) self;
89
90 return gdb_py_object_from_longest (self_string->length).release ();
91 }
92
93 static PyObject *
stpy_get_type(PyObject * self,void * closure)94 stpy_get_type (PyObject *self, void *closure)
95 {
96 lazy_string_object *str_obj = (lazy_string_object *) self;
97
98 Py_INCREF (str_obj->type);
99 return str_obj->type;
100 }
101
102 static PyObject *
stpy_convert_to_value(PyObject * self,PyObject * args)103 stpy_convert_to_value (PyObject *self, PyObject *args)
104 {
105 lazy_string_object *self_string = (lazy_string_object *) self;
106
107 if (self_string->address == 0)
108 {
109 PyErr_SetString (gdbpy_gdb_memory_error,
110 _("Cannot create a value from NULL."));
111 return NULL;
112 }
113
114 PyObject *result = nullptr;
115 try
116 {
117 scoped_value_mark free_values;
118
119 struct type *type = type_object_to_type (self_string->type);
120 struct type *realtype;
121 struct value *val;
122
123 gdb_assert (type != NULL);
124 realtype = check_typedef (type);
125 switch (realtype->code ())
126 {
127 case TYPE_CODE_PTR:
128 /* If a length is specified we need to convert this to an array
129 of the specified size. */
130 if (self_string->length != -1)
131 {
132 /* PR 20786: There's no way to specify an array of length zero.
133 Record a length of [0,-1] which is how Ada does it. Anything
134 we do is broken, but this is one possible solution. */
135 type = lookup_array_range_type (realtype->target_type (),
136 0, self_string->length - 1);
137 val = value_at_lazy (type, self_string->address);
138 }
139 else
140 val = value_from_pointer (type, self_string->address);
141 break;
142 default:
143 val = value_at_lazy (type, self_string->address);
144 break;
145 }
146
147 result = value_to_value_object (val);
148 }
149 catch (const gdb_exception &except)
150 {
151 GDB_PY_HANDLE_EXCEPTION (except);
152 }
153
154 return result;
155 }
156
157 static void
stpy_dealloc(PyObject * self)158 stpy_dealloc (PyObject *self)
159 {
160 lazy_string_object *self_string = (lazy_string_object *) self;
161
162 xfree (self_string->encoding);
163 Py_TYPE (self)->tp_free (self);
164 }
165
166 /* Low level routine to create a <gdb.LazyString> object.
167
168 Note: If TYPE is an array, LENGTH either must be -1 (meaning to use the
169 size of the array, which may itself be unknown in which case a length of
170 -1 is still used) or must be the length of the array. */
171
172 PyObject *
gdbpy_create_lazy_string_object(CORE_ADDR address,long length,const char * encoding,struct type * type)173 gdbpy_create_lazy_string_object (CORE_ADDR address, long length,
174 const char *encoding, struct type *type)
175 {
176 lazy_string_object *str_obj = NULL;
177 struct type *realtype;
178
179 if (length < -1)
180 {
181 PyErr_SetString (PyExc_ValueError, _("Invalid length."));
182 return NULL;
183 }
184
185 if (address == 0 && length != 0)
186 {
187 PyErr_SetString (gdbpy_gdb_memory_error,
188 _("Cannot create a lazy string with address 0x0, " \
189 "and a non-zero length."));
190 return NULL;
191 }
192
193 if (!type)
194 {
195 PyErr_SetString (PyExc_RuntimeError,
196 _("A lazy string's type cannot be NULL."));
197 return NULL;
198 }
199
200 realtype = check_typedef (type);
201 switch (realtype->code ())
202 {
203 case TYPE_CODE_ARRAY:
204 {
205 LONGEST array_length = -1;
206 LONGEST low_bound, high_bound;
207
208 if (get_array_bounds (realtype, &low_bound, &high_bound))
209 array_length = high_bound - low_bound + 1;
210 if (length == -1)
211 length = array_length;
212 else if (length != array_length)
213 {
214 PyErr_SetString (PyExc_ValueError, _("Invalid length."));
215 return NULL;
216 }
217 break;
218 }
219 }
220
221 str_obj = PyObject_New (lazy_string_object, &lazy_string_object_type);
222 if (!str_obj)
223 return NULL;
224
225 str_obj->address = address;
226 str_obj->length = length;
227 if (encoding == NULL || !strcmp (encoding, ""))
228 str_obj->encoding = NULL;
229 else
230 str_obj->encoding = xstrdup (encoding);
231 str_obj->type = type_to_type_object (type);
232
233 return (PyObject *) str_obj;
234 }
235
236 static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
gdbpy_initialize_lazy_string(void)237 gdbpy_initialize_lazy_string (void)
238 {
239 if (PyType_Ready (&lazy_string_object_type) < 0)
240 return -1;
241
242 Py_INCREF (&lazy_string_object_type);
243 return 0;
244 }
245
246 /* Determine whether the printer object pointed to by OBJ is a
247 Python lazy string. */
248 int
gdbpy_is_lazy_string(PyObject * result)249 gdbpy_is_lazy_string (PyObject *result)
250 {
251 return PyObject_TypeCheck (result, &lazy_string_object_type);
252 }
253
254 /* Return the type of a character in lazy string LAZY. */
255
256 static struct type *
stpy_lazy_string_elt_type(lazy_string_object * lazy)257 stpy_lazy_string_elt_type (lazy_string_object *lazy)
258 {
259 struct type *type = type_object_to_type (lazy->type);
260 struct type *realtype;
261
262 gdb_assert (type != NULL);
263 realtype = check_typedef (type);
264
265 switch (realtype->code ())
266 {
267 case TYPE_CODE_PTR:
268 case TYPE_CODE_ARRAY:
269 return check_typedef (realtype->target_type ());
270 default:
271 /* This is done to preserve existing behaviour. PR 20769.
272 E.g., gdb.parse_and_eval("my_int_variable").lazy_string().type. */
273 return realtype;
274 }
275 }
276
277 /* Extract the parameters from the lazy string object STRING.
278 ENCODING may be set to NULL, if no encoding is found. */
279
280 void
gdbpy_extract_lazy_string(PyObject * string,CORE_ADDR * addr,struct type ** str_elt_type,long * length,gdb::unique_xmalloc_ptr<char> * encoding)281 gdbpy_extract_lazy_string (PyObject *string, CORE_ADDR *addr,
282 struct type **str_elt_type,
283 long *length,
284 gdb::unique_xmalloc_ptr<char> *encoding)
285 {
286 lazy_string_object *lazy;
287
288 gdb_assert (gdbpy_is_lazy_string (string));
289
290 lazy = (lazy_string_object *) string;
291
292 *addr = lazy->address;
293 *str_elt_type = stpy_lazy_string_elt_type (lazy);
294 *length = lazy->length;
295 encoding->reset (lazy->encoding ? xstrdup (lazy->encoding) : NULL);
296 }
297
298 /* __str__ for LazyString. */
299
300 static PyObject *
stpy_str(PyObject * self)301 stpy_str (PyObject *self)
302 {
303 lazy_string_object *str = (lazy_string_object *) self;
304
305 struct value_print_options opts;
306 get_user_print_options (&opts);
307 opts.addressprint = false;
308
309 string_file stream;
310 try
311 {
312 struct type *type = stpy_lazy_string_elt_type (str);
313 val_print_string (type, str->encoding, str->address, str->length,
314 &stream, &opts);
315 }
316 catch (const gdb_exception &exc)
317 {
318 GDB_PY_HANDLE_EXCEPTION (exc);
319 }
320
321 return host_string_to_python_string (stream.c_str ()).release ();
322 }
323
324 GDBPY_INITIALIZE_FILE (gdbpy_initialize_lazy_string);
325
326
327
328 static PyMethodDef lazy_string_object_methods[] = {
329 { "value", stpy_convert_to_value, METH_NOARGS,
330 "Create a (lazy) value that contains a pointer to the string." },
331 {NULL} /* Sentinel */
332 };
333
334
335 static gdb_PyGetSetDef lazy_string_object_getset[] = {
336 { "address", stpy_get_address, NULL, "Address of the string.", NULL },
337 { "encoding", stpy_get_encoding, NULL, "Encoding of the string.", NULL },
338 { "length", stpy_get_length, NULL, "Length of the string.", NULL },
339 { "type", stpy_get_type, NULL, "Type associated with the string.", NULL },
340 { NULL } /* Sentinel */
341 };
342
343 PyTypeObject lazy_string_object_type = {
344 PyVarObject_HEAD_INIT (NULL, 0)
345 "gdb.LazyString", /*tp_name*/
346 sizeof (lazy_string_object), /*tp_basicsize*/
347 0, /*tp_itemsize*/
348 stpy_dealloc, /*tp_dealloc*/
349 0, /*tp_print*/
350 0, /*tp_getattr*/
351 0, /*tp_setattr*/
352 0, /*tp_compare*/
353 0, /*tp_repr*/
354 0, /*tp_as_number*/
355 0, /*tp_as_sequence*/
356 0, /*tp_as_mapping*/
357 0, /*tp_hash */
358 0, /*tp_call*/
359 stpy_str, /*tp_str*/
360 0, /*tp_getattro*/
361 0, /*tp_setattro*/
362 0, /*tp_as_buffer*/
363 Py_TPFLAGS_DEFAULT, /*tp_flags*/
364 "GDB lazy string object", /* tp_doc */
365 0, /* tp_traverse */
366 0, /* tp_clear */
367 0, /* tp_richcompare */
368 0, /* tp_weaklistoffset */
369 0, /* tp_iter */
370 0, /* tp_iternext */
371 lazy_string_object_methods, /* tp_methods */
372 0, /* tp_members */
373 lazy_string_object_getset /* tp_getset */
374 };
375