1 /* Python interface to lazy strings.
3 Copyright (C) 2010-2024 Free Software Foundation, Inc.
5 This file is part of GDB.
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.
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.
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/>. */
21 #include "python-internal.h"
27 struct lazy_string_object
{
30 /* Holds the address of the lazy string. */
33 /* Holds the encoding that will be applied to the string
34 when the string is printed by GDB. If the encoding is set
35 to None then GDB will select the most appropriate
36 encoding when the sting is printed. */
39 /* If TYPE is an array: If the length is known, then this value is the
40 array's length, otherwise it is -1.
41 If TYPE is not an array: Then this value represents the string's length.
42 In either case, if the value is -1 then the string will be fetched and
43 encoded up to the first null of appropriate width. */
46 /* This attribute holds the type of the string.
47 For example if the lazy string was created from a C "char*" then TYPE
48 represents a C "char*".
49 To get the type of the character in the string call
50 stpy_lazy_string_elt_type.
51 This is recorded as a PyObject so that we take advantage of support for
52 preserving the type should its owning objfile go away. */
56 extern PyTypeObject lazy_string_object_type
57 CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("lazy_string_object");
60 stpy_get_address (PyObject
*self
, void *closure
)
62 lazy_string_object
*self_string
= (lazy_string_object
*) self
;
64 return gdb_py_object_from_ulongest (self_string
->address
).release ();
68 stpy_get_encoding (PyObject
*self
, void *closure
)
70 lazy_string_object
*self_string
= (lazy_string_object
*) self
;
73 /* An encoding can be set to NULL by the user, so check before
74 attempting a Python FromString call. If NULL return Py_None. */
75 if (self_string
->encoding
)
76 result
= PyUnicode_FromString (self_string
->encoding
);
87 stpy_get_length (PyObject
*self
, void *closure
)
89 lazy_string_object
*self_string
= (lazy_string_object
*) self
;
91 return gdb_py_object_from_longest (self_string
->length
).release ();
95 stpy_get_type (PyObject
*self
, void *closure
)
97 lazy_string_object
*str_obj
= (lazy_string_object
*) self
;
99 Py_INCREF (str_obj
->type
);
100 return str_obj
->type
;
104 stpy_convert_to_value (PyObject
*self
, PyObject
*args
)
106 lazy_string_object
*self_string
= (lazy_string_object
*) self
;
108 if (self_string
->address
== 0)
110 PyErr_SetString (gdbpy_gdb_memory_error
,
111 _("Cannot create a value from NULL."));
115 PyObject
*result
= nullptr;
118 scoped_value_mark free_values
;
120 struct type
*type
= type_object_to_type (self_string
->type
);
121 struct type
*realtype
;
124 gdb_assert (type
!= NULL
);
125 realtype
= check_typedef (type
);
126 switch (realtype
->code ())
129 /* If a length is specified we need to convert this to an array
130 of the specified size. */
131 if (self_string
->length
!= -1)
133 /* PR 20786: There's no way to specify an array of length zero.
134 Record a length of [0,-1] which is how Ada does it. Anything
135 we do is broken, but this is one possible solution. */
136 type
= lookup_array_range_type (realtype
->target_type (),
137 0, self_string
->length
- 1);
138 val
= value_at_lazy (type
, self_string
->address
);
141 val
= value_from_pointer (type
, self_string
->address
);
144 val
= value_at_lazy (type
, self_string
->address
);
148 result
= value_to_value_object (val
);
150 catch (const gdb_exception
&except
)
152 GDB_PY_HANDLE_EXCEPTION (except
);
159 stpy_dealloc (PyObject
*self
)
161 lazy_string_object
*self_string
= (lazy_string_object
*) self
;
163 xfree (self_string
->encoding
);
164 Py_TYPE (self
)->tp_free (self
);
167 /* Low level routine to create a <gdb.LazyString> object.
169 Note: If TYPE is an array, LENGTH either must be -1 (meaning to use the
170 size of the array, which may itself be unknown in which case a length of
171 -1 is still used) or must be the length of the array. */
174 gdbpy_create_lazy_string_object (CORE_ADDR address
, long length
,
175 const char *encoding
, struct type
*type
)
177 lazy_string_object
*str_obj
= NULL
;
178 struct type
*realtype
;
182 PyErr_SetString (PyExc_ValueError
, _("Invalid length."));
186 if (address
== 0 && length
!= 0)
188 PyErr_SetString (gdbpy_gdb_memory_error
,
189 _("Cannot create a lazy string with address 0x0, " \
190 "and a non-zero length."));
196 PyErr_SetString (PyExc_RuntimeError
,
197 _("A lazy string's type cannot be NULL."));
201 realtype
= check_typedef (type
);
202 switch (realtype
->code ())
204 case TYPE_CODE_ARRAY
:
206 LONGEST array_length
= -1;
207 LONGEST low_bound
, high_bound
;
209 if (get_array_bounds (realtype
, &low_bound
, &high_bound
))
210 array_length
= high_bound
- low_bound
+ 1;
212 length
= array_length
;
213 else if (length
!= array_length
)
215 PyErr_SetString (PyExc_ValueError
, _("Invalid length."));
222 str_obj
= PyObject_New (lazy_string_object
, &lazy_string_object_type
);
226 str_obj
->address
= address
;
227 str_obj
->length
= length
;
228 if (encoding
== NULL
|| !strcmp (encoding
, ""))
229 str_obj
->encoding
= NULL
;
231 str_obj
->encoding
= xstrdup (encoding
);
232 str_obj
->type
= type_to_type_object (type
);
234 return (PyObject
*) str_obj
;
237 static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
238 gdbpy_initialize_lazy_string (void)
240 if (PyType_Ready (&lazy_string_object_type
) < 0)
243 Py_INCREF (&lazy_string_object_type
);
247 /* Determine whether the printer object pointed to by OBJ is a
248 Python lazy string. */
250 gdbpy_is_lazy_string (PyObject
*result
)
252 return PyObject_TypeCheck (result
, &lazy_string_object_type
);
255 /* Return the type of a character in lazy string LAZY. */
258 stpy_lazy_string_elt_type (lazy_string_object
*lazy
)
260 struct type
*type
= type_object_to_type (lazy
->type
);
261 struct type
*realtype
;
263 gdb_assert (type
!= NULL
);
264 realtype
= check_typedef (type
);
266 switch (realtype
->code ())
269 case TYPE_CODE_ARRAY
:
270 return realtype
->target_type ();
272 /* This is done to preserve existing behaviour. PR 20769.
273 E.g., gdb.parse_and_eval("my_int_variable").lazy_string().type. */
278 /* Extract the parameters from the lazy string object STRING.
279 ENCODING may be set to NULL, if no encoding is found. */
282 gdbpy_extract_lazy_string (PyObject
*string
, CORE_ADDR
*addr
,
283 struct type
**str_elt_type
,
285 gdb::unique_xmalloc_ptr
<char> *encoding
)
287 lazy_string_object
*lazy
;
289 gdb_assert (gdbpy_is_lazy_string (string
));
291 lazy
= (lazy_string_object
*) string
;
293 *addr
= lazy
->address
;
294 *str_elt_type
= stpy_lazy_string_elt_type (lazy
);
295 *length
= lazy
->length
;
296 encoding
->reset (lazy
->encoding
? xstrdup (lazy
->encoding
) : NULL
);
299 /* __str__ for LazyString. */
302 stpy_str (PyObject
*self
)
304 lazy_string_object
*str
= (lazy_string_object
*) self
;
306 struct value_print_options opts
;
307 get_user_print_options (&opts
);
308 opts
.addressprint
= false;
313 struct type
*type
= stpy_lazy_string_elt_type (str
);
314 val_print_string (type
, str
->encoding
, str
->address
, str
->length
,
317 catch (const gdb_exception
&exc
)
319 GDB_PY_HANDLE_EXCEPTION (exc
);
322 return host_string_to_python_string (stream
.c_str ()).release ();
325 GDBPY_INITIALIZE_FILE (gdbpy_initialize_lazy_string
);
329 static PyMethodDef lazy_string_object_methods
[] = {
330 { "value", stpy_convert_to_value
, METH_NOARGS
,
331 "Create a (lazy) value that contains a pointer to the string." },
332 {NULL
} /* Sentinel */
336 static gdb_PyGetSetDef lazy_string_object_getset
[] = {
337 { "address", stpy_get_address
, NULL
, "Address of the string.", NULL
},
338 { "encoding", stpy_get_encoding
, NULL
, "Encoding of the string.", NULL
},
339 { "length", stpy_get_length
, NULL
, "Length of the string.", NULL
},
340 { "type", stpy_get_type
, NULL
, "Type associated with the string.", NULL
},
341 { NULL
} /* Sentinel */
344 PyTypeObject lazy_string_object_type
= {
345 PyVarObject_HEAD_INIT (NULL
, 0)
346 "gdb.LazyString", /*tp_name*/
347 sizeof (lazy_string_object
), /*tp_basicsize*/
349 stpy_dealloc
, /*tp_dealloc*/
356 0, /*tp_as_sequence*/
364 Py_TPFLAGS_DEFAULT
, /*tp_flags*/
365 "GDB lazy string object", /* tp_doc */
368 0, /* tp_richcompare */
369 0, /* tp_weaklistoffset */
372 lazy_string_object_methods
, /* tp_methods */
374 lazy_string_object_getset
/* tp_getset */