]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame_incremental - gdb/python/py-lazy-string.c
Automatic date update in version.in
[thirdparty/binutils-gdb.git] / gdb / python / py-lazy-string.c
... / ...
CommitLineData
1/* Python interface to lazy strings.
2
3 Copyright (C) 2010-2025 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
26struct 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 string 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
55extern PyTypeObject lazy_string_object_type
56 CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("lazy_string_object");
57
58static PyObject *
59stpy_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
66static PyObject *
67stpy_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
85static PyObject *
86stpy_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
93static PyObject *
94stpy_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
102static PyObject *
103stpy_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 return gdbpy_handle_gdb_exception (nullptr, except);
152 }
153
154 return result;
155}
156
157static void
158stpy_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
172PyObject *
173gdbpy_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 (!type)
186 {
187 PyErr_SetString (PyExc_RuntimeError,
188 _("A lazy string's type cannot be NULL."));
189 return NULL;
190 }
191
192 realtype = check_typedef (type);
193 switch (realtype->code ())
194 {
195 case TYPE_CODE_ARRAY:
196 {
197 LONGEST array_length = -1;
198 LONGEST low_bound, high_bound;
199
200 if (get_array_bounds (realtype, &low_bound, &high_bound))
201 array_length = high_bound - low_bound + 1;
202 if (length == -1)
203 length = array_length;
204 else if (length != array_length)
205 {
206 PyErr_SetString (PyExc_ValueError, _("Invalid length."));
207 return NULL;
208 }
209 break;
210 }
211
212 case TYPE_CODE_PTR:
213 if (address == 0)
214 {
215 if (length > 0)
216 {
217 PyErr_SetString (gdbpy_gdb_memory_error,
218 _("Cannot create a lazy string with address 0x0, " \
219 "and a non-zero length."));
220 return nullptr;
221 }
222 length = 0;
223 }
224 break;
225
226 default:
227 gdb_assert_not_reached ("invalid type in gdbpy_create_lazy_string_object");
228 }
229
230 str_obj = PyObject_New (lazy_string_object, &lazy_string_object_type);
231 if (!str_obj)
232 return NULL;
233
234 str_obj->address = address;
235 str_obj->length = length;
236 if (encoding == NULL || !strcmp (encoding, ""))
237 str_obj->encoding = NULL;
238 else
239 str_obj->encoding = xstrdup (encoding);
240 str_obj->type = type_to_type_object (type);
241
242 return (PyObject *) str_obj;
243}
244
245static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
246gdbpy_initialize_lazy_string (void)
247{
248 return gdbpy_type_ready (&lazy_string_object_type);
249}
250
251/* Determine whether the printer object pointed to by OBJ is a
252 Python lazy string. */
253int
254gdbpy_is_lazy_string (PyObject *result)
255{
256 return PyObject_TypeCheck (result, &lazy_string_object_type);
257}
258
259/* Return the type of a character in lazy string LAZY. */
260
261static struct type *
262stpy_lazy_string_elt_type (lazy_string_object *lazy)
263{
264 struct type *type = type_object_to_type (lazy->type);
265 struct type *realtype;
266
267 gdb_assert (type != NULL);
268 realtype = check_typedef (type);
269
270 switch (realtype->code ())
271 {
272 case TYPE_CODE_PTR:
273 case TYPE_CODE_ARRAY:
274 return check_typedef (realtype->target_type ());
275 default:
276 gdb_assert_not_reached ("invalid lazy string");
277 }
278}
279
280/* Extract the parameters from the lazy string object STRING.
281 ENCODING may be set to NULL, if no encoding is found. */
282
283void
284gdbpy_extract_lazy_string (PyObject *string, CORE_ADDR *addr,
285 struct type **str_elt_type,
286 long *length,
287 gdb::unique_xmalloc_ptr<char> *encoding)
288{
289 lazy_string_object *lazy;
290
291 gdb_assert (gdbpy_is_lazy_string (string));
292
293 lazy = (lazy_string_object *) string;
294
295 *addr = lazy->address;
296 *str_elt_type = stpy_lazy_string_elt_type (lazy);
297 *length = lazy->length;
298 encoding->reset (lazy->encoding ? xstrdup (lazy->encoding) : NULL);
299}
300
301/* __str__ for LazyString. */
302
303static PyObject *
304stpy_str (PyObject *self)
305{
306 lazy_string_object *str = (lazy_string_object *) self;
307
308 struct value_print_options opts;
309 get_user_print_options (&opts);
310 opts.addressprint = false;
311
312 string_file stream;
313 try
314 {
315 struct type *type = stpy_lazy_string_elt_type (str);
316 val_print_string (type, str->encoding, str->address, str->length,
317 &stream, &opts);
318 }
319 catch (const gdb_exception &exc)
320 {
321 return gdbpy_handle_gdb_exception (nullptr, exc);
322 }
323
324 return host_string_to_python_string (stream.c_str ()).release ();
325}
326
327GDBPY_INITIALIZE_FILE (gdbpy_initialize_lazy_string);
328
329\f
330
331static PyMethodDef lazy_string_object_methods[] = {
332 { "value", stpy_convert_to_value, METH_NOARGS,
333 "Create a (lazy) value that contains a pointer to the string." },
334 {NULL} /* Sentinel */
335};
336
337
338static gdb_PyGetSetDef lazy_string_object_getset[] = {
339 { "address", stpy_get_address, NULL, "Address of the string.", NULL },
340 { "encoding", stpy_get_encoding, NULL, "Encoding of the string.", NULL },
341 { "length", stpy_get_length, NULL, "Length of the string.", NULL },
342 { "type", stpy_get_type, NULL, "Type associated with the string.", NULL },
343 { NULL } /* Sentinel */
344};
345
346PyTypeObject lazy_string_object_type = {
347 PyVarObject_HEAD_INIT (NULL, 0)
348 "gdb.LazyString", /*tp_name*/
349 sizeof (lazy_string_object), /*tp_basicsize*/
350 0, /*tp_itemsize*/
351 stpy_dealloc, /*tp_dealloc*/
352 0, /*tp_print*/
353 0, /*tp_getattr*/
354 0, /*tp_setattr*/
355 0, /*tp_compare*/
356 0, /*tp_repr*/
357 0, /*tp_as_number*/
358 0, /*tp_as_sequence*/
359 0, /*tp_as_mapping*/
360 0, /*tp_hash */
361 0, /*tp_call*/
362 stpy_str, /*tp_str*/
363 0, /*tp_getattro*/
364 0, /*tp_setattro*/
365 0, /*tp_as_buffer*/
366 Py_TPFLAGS_DEFAULT, /*tp_flags*/
367 "GDB lazy string object", /* tp_doc */
368 0, /* tp_traverse */
369 0, /* tp_clear */
370 0, /* tp_richcompare */
371 0, /* tp_weaklistoffset */
372 0, /* tp_iter */
373 0, /* tp_iternext */
374 lazy_string_object_methods, /* tp_methods */
375 0, /* tp_members */
376 lazy_string_object_getset /* tp_getset */
377};