]>
Commit | Line | Data |
---|---|---|
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 | 27 | struct 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 | 56 | extern PyTypeObject lazy_string_object_type |
62eec1a5 | 57 | CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("lazy_string_object"); |
be759fcf PM |
58 | |
59 | static PyObject * | |
60 | stpy_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 | ||
67 | static PyObject * | |
68 | stpy_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 | ||
86 | static PyObject * | |
87 | stpy_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 | 94 | static PyObject * |
be759fcf PM |
95 | stpy_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 | ||
103 | static PyObject * | |
34b43320 | 104 | stpy_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 | ||
158 | static void | |
159 | stpy_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 |
173 | PyObject * |
174 | gdbpy_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 | 237 | static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION |
be759fcf PM |
238 | gdbpy_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. */ | |
249 | int | |
250 | gdbpy_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 | ||
257 | static struct type * | |
258 | stpy_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 |
281 | void |
282 | gdbpy_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 | ||
301 | static PyObject * | |
302 | stpy_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 |
325 | GDBPY_INITIALIZE_FILE (gdbpy_initialize_lazy_string); |
326 | ||
be759fcf PM |
327 | \f |
328 | ||
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 */ | |
333 | }; | |
334 | ||
335 | ||
0d1f4ceb | 336 | static 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 | 344 | PyTypeObject 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 | }; |