]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/python/py-lazy-string.c
Update copyright year range in header of all files managed by GDB
[thirdparty/binutils-gdb.git] / gdb / python / py-lazy-string.c
CommitLineData
be759fcf
PM
1/* Python interface to lazy strings.
2
1d506c26 3 Copyright (C) 2010-2024 Free Software Foundation, Inc.
be759fcf
PM
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#include "charset.h"
23#include "value.h"
be759fcf
PM
24#include "valprint.h"
25#include "language.h"
26
f99b5177 27struct lazy_string_object {
be759fcf 28 PyObject_HEAD
34b43320 29
be759fcf
PM
30 /* Holds the address of the lazy string. */
31 CORE_ADDR address;
32
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. */
37 char *encoding;
38
34b43320
DE
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. */
be759fcf
PM
44 long length;
45
34b43320
DE
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. */
53 PyObject *type;
f99b5177 54};
be759fcf 55
e36122e9 56extern PyTypeObject lazy_string_object_type
62eec1a5 57 CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("lazy_string_object");
be759fcf
PM
58
59static PyObject *
60stpy_get_address (PyObject *self, void *closure)
61{
62 lazy_string_object *self_string = (lazy_string_object *) self;
d59b6f6c 63
d1cab987 64 return gdb_py_object_from_ulongest (self_string->address).release ();
be759fcf
PM
65}
66
67static PyObject *
68stpy_get_encoding (PyObject *self, void *closure)
69{
70 lazy_string_object *self_string = (lazy_string_object *) self;
71 PyObject *result;
72
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)
5aee4587 76 result = PyUnicode_FromString (self_string->encoding);
be759fcf
PM
77 else
78 {
79 result = Py_None;
80 Py_INCREF (result);
81 }
82
83 return result;
84}
85
86static PyObject *
87stpy_get_length (PyObject *self, void *closure)
88{
89 lazy_string_object *self_string = (lazy_string_object *) self;
d59b6f6c 90
062534d4 91 return gdb_py_object_from_longest (self_string->length).release ();
be759fcf
PM
92}
93
49a8461d 94static PyObject *
be759fcf
PM
95stpy_get_type (PyObject *self, void *closure)
96{
97 lazy_string_object *str_obj = (lazy_string_object *) self;
d59b6f6c 98
34b43320
DE
99 Py_INCREF (str_obj->type);
100 return str_obj->type;
be759fcf
PM
101}
102
103static PyObject *
34b43320 104stpy_convert_to_value (PyObject *self, PyObject *args)
be759fcf
PM
105{
106 lazy_string_object *self_string = (lazy_string_object *) self;
be759fcf 107
fff5cc64
PM
108 if (self_string->address == 0)
109 {
4ea6efe9 110 PyErr_SetString (gdbpy_gdb_memory_error,
044c0f87 111 _("Cannot create a value from NULL."));
fff5cc64
PM
112 return NULL;
113 }
114
f3d3bbbc 115 PyObject *result = nullptr;
a70b8144 116 try
76dce0be 117 {
f3d3bbbc
TT
118 scoped_value_mark free_values;
119
34b43320
DE
120 struct type *type = type_object_to_type (self_string->type);
121 struct type *realtype;
f3d3bbbc 122 struct value *val;
34b43320
DE
123
124 gdb_assert (type != NULL);
125 realtype = check_typedef (type);
78134374 126 switch (realtype->code ())
34b43320
DE
127 {
128 case TYPE_CODE_PTR:
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)
132 {
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. */
27710edb 136 type = lookup_array_range_type (realtype->target_type (),
34b43320
DE
137 0, self_string->length - 1);
138 val = value_at_lazy (type, self_string->address);
139 }
140 else
141 val = value_from_pointer (type, self_string->address);
142 break;
143 default:
144 val = value_at_lazy (type, self_string->address);
145 break;
146 }
f3d3bbbc
TT
147
148 result = value_to_value_object (val);
76dce0be 149 }
230d2906 150 catch (const gdb_exception &except)
492d29ea
PA
151 {
152 GDB_PY_HANDLE_EXCEPTION (except);
153 }
76dce0be 154
f3d3bbbc 155 return result;
be759fcf
PM
156}
157
158static void
159stpy_dealloc (PyObject *self)
160{
161 lazy_string_object *self_string = (lazy_string_object *) self;
d59b6f6c 162
be759fcf 163 xfree (self_string->encoding);
2e953aca 164 Py_TYPE (self)->tp_free (self);
be759fcf
PM
165}
166
34b43320
DE
167/* Low level routine to create a <gdb.LazyString> object.
168
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. */
172
be759fcf
PM
173PyObject *
174gdbpy_create_lazy_string_object (CORE_ADDR address, long length,
34b43320 175 const char *encoding, struct type *type)
be759fcf
PM
176{
177 lazy_string_object *str_obj = NULL;
34b43320
DE
178 struct type *realtype;
179
180 if (length < -1)
181 {
182 PyErr_SetString (PyExc_ValueError, _("Invalid length."));
183 return NULL;
184 }
be759fcf 185
fff5cc64 186 if (address == 0 && length != 0)
be759fcf 187 {
4ea6efe9 188 PyErr_SetString (gdbpy_gdb_memory_error,
fff5cc64
PM
189 _("Cannot create a lazy string with address 0x0, " \
190 "and a non-zero length."));
be759fcf
PM
191 return NULL;
192 }
193
194 if (!type)
195 {
196 PyErr_SetString (PyExc_RuntimeError,
044c0f87 197 _("A lazy string's type cannot be NULL."));
be759fcf
PM
198 return NULL;
199 }
200
34b43320 201 realtype = check_typedef (type);
78134374 202 switch (realtype->code ())
34b43320
DE
203 {
204 case TYPE_CODE_ARRAY:
205 {
206 LONGEST array_length = -1;
207 LONGEST low_bound, high_bound;
208
209 if (get_array_bounds (realtype, &low_bound, &high_bound))
210 array_length = high_bound - low_bound + 1;
211 if (length == -1)
212 length = array_length;
213 else if (length != array_length)
214 {
215 PyErr_SetString (PyExc_ValueError, _("Invalid length."));
216 return NULL;
217 }
218 break;
219 }
220 }
221
be759fcf
PM
222 str_obj = PyObject_New (lazy_string_object, &lazy_string_object_type);
223 if (!str_obj)
224 return NULL;
225
226 str_obj->address = address;
227 str_obj->length = length;
228 if (encoding == NULL || !strcmp (encoding, ""))
229 str_obj->encoding = NULL;
230 else
231 str_obj->encoding = xstrdup (encoding);
34b43320 232 str_obj->type = type_to_type_object (type);
be759fcf
PM
233
234 return (PyObject *) str_obj;
235}
236
3965bff5 237static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
be759fcf
PM
238gdbpy_initialize_lazy_string (void)
239{
240 if (PyType_Ready (&lazy_string_object_type) < 0)
999633ed 241 return -1;
be759fcf
PM
242
243 Py_INCREF (&lazy_string_object_type);
999633ed 244 return 0;
be759fcf
PM
245}
246
247/* Determine whether the printer object pointed to by OBJ is a
248 Python lazy string. */
249int
250gdbpy_is_lazy_string (PyObject *result)
251{
252 return PyObject_TypeCheck (result, &lazy_string_object_type);
253}
254
34b43320
DE
255/* Return the type of a character in lazy string LAZY. */
256
257static struct type *
258stpy_lazy_string_elt_type (lazy_string_object *lazy)
259{
260 struct type *type = type_object_to_type (lazy->type);
261 struct type *realtype;
262
263 gdb_assert (type != NULL);
264 realtype = check_typedef (type);
265
78134374 266 switch (realtype->code ())
34b43320
DE
267 {
268 case TYPE_CODE_PTR:
269 case TYPE_CODE_ARRAY:
27710edb 270 return realtype->target_type ();
34b43320
DE
271 default:
272 /* This is done to preserve existing behaviour. PR 20769.
273 E.g., gdb.parse_and_eval("my_int_variable").lazy_string().type. */
274 return realtype;
275 }
276}
277
09ca9e2e 278/* Extract the parameters from the lazy string object STRING.
1eba6383 279 ENCODING may be set to NULL, if no encoding is found. */
be759fcf 280
09ca9e2e
TT
281void
282gdbpy_extract_lazy_string (PyObject *string, CORE_ADDR *addr,
34b43320 283 struct type **str_elt_type,
1eba6383
TT
284 long *length,
285 gdb::unique_xmalloc_ptr<char> *encoding)
09ca9e2e
TT
286{
287 lazy_string_object *lazy;
be759fcf 288
09ca9e2e 289 gdb_assert (gdbpy_is_lazy_string (string));
be759fcf 290
09ca9e2e 291 lazy = (lazy_string_object *) string;
be759fcf 292
09ca9e2e 293 *addr = lazy->address;
34b43320 294 *str_elt_type = stpy_lazy_string_elt_type (lazy);
09ca9e2e 295 *length = lazy->length;
1eba6383 296 encoding->reset (lazy->encoding ? xstrdup (lazy->encoding) : NULL);
be759fcf
PM
297}
298
ee81567c
TT
299/* __str__ for LazyString. */
300
301static PyObject *
302stpy_str (PyObject *self)
303{
304 lazy_string_object *str = (lazy_string_object *) self;
305
306 struct value_print_options opts;
307 get_user_print_options (&opts);
308 opts.addressprint = false;
309
310 string_file stream;
311 try
312 {
313 struct type *type = stpy_lazy_string_elt_type (str);
314 val_print_string (type, str->encoding, str->address, str->length,
315 &stream, &opts);
316 }
317 catch (const gdb_exception &exc)
318 {
319 GDB_PY_HANDLE_EXCEPTION (exc);
320 }
321
322 return host_string_to_python_string (stream.c_str ()).release ();
323}
324
3965bff5
AB
325GDBPY_INITIALIZE_FILE (gdbpy_initialize_lazy_string);
326
be759fcf
PM
327\f
328
329static 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 */
333};
334
335
0d1f4ceb 336static gdb_PyGetSetDef lazy_string_object_getset[] = {
be759fcf
PM
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 */
342};
343
e36122e9 344PyTypeObject lazy_string_object_type = {
9a27f2c6 345 PyVarObject_HEAD_INIT (NULL, 0)
be759fcf
PM
346 "gdb.LazyString", /*tp_name*/
347 sizeof (lazy_string_object), /*tp_basicsize*/
348 0, /*tp_itemsize*/
349 stpy_dealloc, /*tp_dealloc*/
350 0, /*tp_print*/
351 0, /*tp_getattr*/
352 0, /*tp_setattr*/
353 0, /*tp_compare*/
354 0, /*tp_repr*/
355 0, /*tp_as_number*/
356 0, /*tp_as_sequence*/
357 0, /*tp_as_mapping*/
358 0, /*tp_hash */
359 0, /*tp_call*/
ee81567c 360 stpy_str, /*tp_str*/
be759fcf
PM
361 0, /*tp_getattro*/
362 0, /*tp_setattro*/
363 0, /*tp_as_buffer*/
364 Py_TPFLAGS_DEFAULT, /*tp_flags*/
365 "GDB lazy string object", /* tp_doc */
366 0, /* tp_traverse */
367 0, /* tp_clear */
368 0, /* tp_richcompare */
369 0, /* tp_weaklistoffset */
370 0, /* tp_iter */
371 0, /* tp_iternext */
372 lazy_string_object_methods, /* tp_methods */
373 0, /* tp_members */
374 lazy_string_object_getset /* tp_getset */
375};