]>
Commit | Line | Data |
---|---|---|
be759fcf PM |
1 | /* Python interface to lazy strings. |
2 | ||
d01e8234 | 3 | Copyright (C) 2010-2025 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 | ||
be759fcf PM |
20 | #include "python-internal.h" |
21 | #include "charset.h" | |
22 | #include "value.h" | |
be759fcf PM |
23 | #include "valprint.h" |
24 | #include "language.h" | |
25 | ||
f99b5177 | 26 | struct lazy_string_object { |
be759fcf | 27 | PyObject_HEAD |
34b43320 | 28 | |
be759fcf PM |
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 | |
586ccf78 | 35 | encoding when the string is printed. */ |
be759fcf PM |
36 | char *encoding; |
37 | ||
34b43320 DE |
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. */ | |
be759fcf PM |
43 | long length; |
44 | ||
34b43320 DE |
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; | |
f99b5177 | 53 | }; |
be759fcf | 54 | |
e36122e9 | 55 | extern PyTypeObject lazy_string_object_type |
62eec1a5 | 56 | CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("lazy_string_object"); |
be759fcf PM |
57 | |
58 | static PyObject * | |
59 | stpy_get_address (PyObject *self, void *closure) | |
60 | { | |
61 | lazy_string_object *self_string = (lazy_string_object *) self; | |
d59b6f6c | 62 | |
d1cab987 | 63 | return gdb_py_object_from_ulongest (self_string->address).release (); |
be759fcf PM |
64 | } |
65 | ||
66 | static PyObject * | |
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) | |
5aee4587 | 75 | result = PyUnicode_FromString (self_string->encoding); |
be759fcf PM |
76 | else |
77 | { | |
78 | result = Py_None; | |
79 | Py_INCREF (result); | |
80 | } | |
81 | ||
82 | return result; | |
83 | } | |
84 | ||
85 | static PyObject * | |
86 | stpy_get_length (PyObject *self, void *closure) | |
87 | { | |
88 | lazy_string_object *self_string = (lazy_string_object *) self; | |
d59b6f6c | 89 | |
062534d4 | 90 | return gdb_py_object_from_longest (self_string->length).release (); |
be759fcf PM |
91 | } |
92 | ||
49a8461d | 93 | static PyObject * |
be759fcf PM |
94 | stpy_get_type (PyObject *self, void *closure) |
95 | { | |
96 | lazy_string_object *str_obj = (lazy_string_object *) self; | |
d59b6f6c | 97 | |
34b43320 DE |
98 | Py_INCREF (str_obj->type); |
99 | return str_obj->type; | |
be759fcf PM |
100 | } |
101 | ||
102 | static PyObject * | |
34b43320 | 103 | stpy_convert_to_value (PyObject *self, PyObject *args) |
be759fcf PM |
104 | { |
105 | lazy_string_object *self_string = (lazy_string_object *) self; | |
be759fcf | 106 | |
fff5cc64 PM |
107 | if (self_string->address == 0) |
108 | { | |
4ea6efe9 | 109 | PyErr_SetString (gdbpy_gdb_memory_error, |
044c0f87 | 110 | _("Cannot create a value from NULL.")); |
fff5cc64 PM |
111 | return NULL; |
112 | } | |
113 | ||
f3d3bbbc | 114 | PyObject *result = nullptr; |
a70b8144 | 115 | try |
76dce0be | 116 | { |
f3d3bbbc TT |
117 | scoped_value_mark free_values; |
118 | ||
34b43320 DE |
119 | struct type *type = type_object_to_type (self_string->type); |
120 | struct type *realtype; | |
f3d3bbbc | 121 | struct value *val; |
34b43320 DE |
122 | |
123 | gdb_assert (type != NULL); | |
124 | realtype = check_typedef (type); | |
78134374 | 125 | switch (realtype->code ()) |
34b43320 DE |
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. */ | |
27710edb | 135 | type = lookup_array_range_type (realtype->target_type (), |
34b43320 DE |
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 | } | |
f3d3bbbc TT |
146 | |
147 | result = value_to_value_object (val); | |
76dce0be | 148 | } |
230d2906 | 149 | catch (const gdb_exception &except) |
492d29ea | 150 | { |
1ccb6f10 | 151 | return gdbpy_handle_gdb_exception (nullptr, except); |
492d29ea | 152 | } |
76dce0be | 153 | |
f3d3bbbc | 154 | return result; |
be759fcf PM |
155 | } |
156 | ||
157 | static void | |
158 | stpy_dealloc (PyObject *self) | |
159 | { | |
160 | lazy_string_object *self_string = (lazy_string_object *) self; | |
d59b6f6c | 161 | |
be759fcf | 162 | xfree (self_string->encoding); |
2e953aca | 163 | Py_TYPE (self)->tp_free (self); |
be759fcf PM |
164 | } |
165 | ||
34b43320 DE |
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 | ||
be759fcf PM |
172 | PyObject * |
173 | gdbpy_create_lazy_string_object (CORE_ADDR address, long length, | |
34b43320 | 174 | const char *encoding, struct type *type) |
be759fcf PM |
175 | { |
176 | lazy_string_object *str_obj = NULL; | |
34b43320 DE |
177 | struct type *realtype; |
178 | ||
179 | if (length < -1) | |
180 | { | |
181 | PyErr_SetString (PyExc_ValueError, _("Invalid length.")); | |
182 | return NULL; | |
183 | } | |
be759fcf | 184 | |
be759fcf PM |
185 | if (!type) |
186 | { | |
187 | PyErr_SetString (PyExc_RuntimeError, | |
044c0f87 | 188 | _("A lazy string's type cannot be NULL.")); |
be759fcf PM |
189 | return NULL; |
190 | } | |
191 | ||
34b43320 | 192 | realtype = check_typedef (type); |
78134374 | 193 | switch (realtype->code ()) |
34b43320 DE |
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 | } | |
c286bfe1 TT |
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"); | |
34b43320 DE |
228 | } |
229 | ||
be759fcf PM |
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); | |
34b43320 | 240 | str_obj->type = type_to_type_object (type); |
be759fcf PM |
241 | |
242 | return (PyObject *) str_obj; | |
243 | } | |
244 | ||
3965bff5 | 245 | static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION |
be759fcf PM |
246 | gdbpy_initialize_lazy_string (void) |
247 | { | |
336bb2a1 | 248 | return gdbpy_type_ready (&lazy_string_object_type); |
be759fcf PM |
249 | } |
250 | ||
251 | /* Determine whether the printer object pointed to by OBJ is a | |
252 | Python lazy string. */ | |
253 | int | |
254 | gdbpy_is_lazy_string (PyObject *result) | |
255 | { | |
256 | return PyObject_TypeCheck (result, &lazy_string_object_type); | |
257 | } | |
258 | ||
34b43320 DE |
259 | /* Return the type of a character in lazy string LAZY. */ |
260 | ||
261 | static struct type * | |
262 | stpy_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 | ||
78134374 | 270 | switch (realtype->code ()) |
34b43320 DE |
271 | { |
272 | case TYPE_CODE_PTR: | |
273 | case TYPE_CODE_ARRAY: | |
8130c1a4 | 274 | return check_typedef (realtype->target_type ()); |
34b43320 | 275 | default: |
2134b0b4 | 276 | gdb_assert_not_reached ("invalid lazy string"); |
34b43320 DE |
277 | } |
278 | } | |
279 | ||
09ca9e2e | 280 | /* Extract the parameters from the lazy string object STRING. |
1eba6383 | 281 | ENCODING may be set to NULL, if no encoding is found. */ |
be759fcf | 282 | |
09ca9e2e TT |
283 | void |
284 | gdbpy_extract_lazy_string (PyObject *string, CORE_ADDR *addr, | |
34b43320 | 285 | struct type **str_elt_type, |
1eba6383 TT |
286 | long *length, |
287 | gdb::unique_xmalloc_ptr<char> *encoding) | |
09ca9e2e TT |
288 | { |
289 | lazy_string_object *lazy; | |
be759fcf | 290 | |
09ca9e2e | 291 | gdb_assert (gdbpy_is_lazy_string (string)); |
be759fcf | 292 | |
09ca9e2e | 293 | lazy = (lazy_string_object *) string; |
be759fcf | 294 | |
09ca9e2e | 295 | *addr = lazy->address; |
34b43320 | 296 | *str_elt_type = stpy_lazy_string_elt_type (lazy); |
09ca9e2e | 297 | *length = lazy->length; |
1eba6383 | 298 | encoding->reset (lazy->encoding ? xstrdup (lazy->encoding) : NULL); |
be759fcf PM |
299 | } |
300 | ||
ee81567c TT |
301 | /* __str__ for LazyString. */ |
302 | ||
303 | static PyObject * | |
304 | stpy_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 | { | |
1ccb6f10 | 321 | return gdbpy_handle_gdb_exception (nullptr, exc); |
ee81567c TT |
322 | } |
323 | ||
324 | return host_string_to_python_string (stream.c_str ()).release (); | |
325 | } | |
326 | ||
3965bff5 AB |
327 | GDBPY_INITIALIZE_FILE (gdbpy_initialize_lazy_string); |
328 | ||
be759fcf PM |
329 | \f |
330 | ||
331 | static 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 | ||
0d1f4ceb | 338 | static gdb_PyGetSetDef lazy_string_object_getset[] = { |
be759fcf PM |
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 | ||
e36122e9 | 346 | PyTypeObject lazy_string_object_type = { |
9a27f2c6 | 347 | PyVarObject_HEAD_INIT (NULL, 0) |
be759fcf PM |
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*/ | |
ee81567c | 362 | stpy_str, /*tp_str*/ |
be759fcf PM |
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 | }; |