Commit | Line | Data |
---|---|---|
be759fcf PM |
1 | /* Python interface to lazy strings. |
2 | ||
3666a048 | 3 | Copyright (C) 2010-2021 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) | |
76 | result = PyString_FromString (self_string->encoding); | |
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; | |
76dce0be | 107 | struct value *val = NULL; |
be759fcf | 108 | |
fff5cc64 PM |
109 | if (self_string->address == 0) |
110 | { | |
4ea6efe9 | 111 | PyErr_SetString (gdbpy_gdb_memory_error, |
044c0f87 | 112 | _("Cannot create a value from NULL.")); |
fff5cc64 PM |
113 | return NULL; |
114 | } | |
115 | ||
a70b8144 | 116 | try |
76dce0be | 117 | { |
34b43320 DE |
118 | struct type *type = type_object_to_type (self_string->type); |
119 | struct type *realtype; | |
120 | ||
121 | gdb_assert (type != NULL); | |
122 | realtype = check_typedef (type); | |
78134374 | 123 | switch (realtype->code ()) |
34b43320 DE |
124 | { |
125 | case TYPE_CODE_PTR: | |
126 | /* If a length is specified we need to convert this to an array | |
127 | of the specified size. */ | |
128 | if (self_string->length != -1) | |
129 | { | |
130 | /* PR 20786: There's no way to specify an array of length zero. | |
131 | Record a length of [0,-1] which is how Ada does it. Anything | |
132 | we do is broken, but this is one possible solution. */ | |
133 | type = lookup_array_range_type (TYPE_TARGET_TYPE (realtype), | |
134 | 0, self_string->length - 1); | |
135 | val = value_at_lazy (type, self_string->address); | |
136 | } | |
137 | else | |
138 | val = value_from_pointer (type, self_string->address); | |
139 | break; | |
140 | default: | |
141 | val = value_at_lazy (type, self_string->address); | |
142 | break; | |
143 | } | |
76dce0be | 144 | } |
230d2906 | 145 | catch (const gdb_exception &except) |
492d29ea PA |
146 | { |
147 | GDB_PY_HANDLE_EXCEPTION (except); | |
148 | } | |
76dce0be | 149 | |
be759fcf PM |
150 | return value_to_value_object (val); |
151 | } | |
152 | ||
153 | static void | |
154 | stpy_dealloc (PyObject *self) | |
155 | { | |
156 | lazy_string_object *self_string = (lazy_string_object *) self; | |
d59b6f6c | 157 | |
be759fcf | 158 | xfree (self_string->encoding); |
2e953aca | 159 | Py_TYPE (self)->tp_free (self); |
be759fcf PM |
160 | } |
161 | ||
34b43320 DE |
162 | /* Low level routine to create a <gdb.LazyString> object. |
163 | ||
164 | Note: If TYPE is an array, LENGTH either must be -1 (meaning to use the | |
165 | size of the array, which may itself be unknown in which case a length of | |
166 | -1 is still used) or must be the length of the array. */ | |
167 | ||
be759fcf PM |
168 | PyObject * |
169 | gdbpy_create_lazy_string_object (CORE_ADDR address, long length, | |
34b43320 | 170 | const char *encoding, struct type *type) |
be759fcf PM |
171 | { |
172 | lazy_string_object *str_obj = NULL; | |
34b43320 DE |
173 | struct type *realtype; |
174 | ||
175 | if (length < -1) | |
176 | { | |
177 | PyErr_SetString (PyExc_ValueError, _("Invalid length.")); | |
178 | return NULL; | |
179 | } | |
be759fcf | 180 | |
fff5cc64 | 181 | if (address == 0 && length != 0) |
be759fcf | 182 | { |
4ea6efe9 | 183 | PyErr_SetString (gdbpy_gdb_memory_error, |
fff5cc64 PM |
184 | _("Cannot create a lazy string with address 0x0, " \ |
185 | "and a non-zero length.")); | |
be759fcf PM |
186 | return NULL; |
187 | } | |
188 | ||
189 | if (!type) | |
190 | { | |
191 | PyErr_SetString (PyExc_RuntimeError, | |
044c0f87 | 192 | _("A lazy string's type cannot be NULL.")); |
be759fcf PM |
193 | return NULL; |
194 | } | |
195 | ||
34b43320 | 196 | realtype = check_typedef (type); |
78134374 | 197 | switch (realtype->code ()) |
34b43320 DE |
198 | { |
199 | case TYPE_CODE_ARRAY: | |
200 | { | |
201 | LONGEST array_length = -1; | |
202 | LONGEST low_bound, high_bound; | |
203 | ||
204 | if (get_array_bounds (realtype, &low_bound, &high_bound)) | |
205 | array_length = high_bound - low_bound + 1; | |
206 | if (length == -1) | |
207 | length = array_length; | |
208 | else if (length != array_length) | |
209 | { | |
210 | PyErr_SetString (PyExc_ValueError, _("Invalid length.")); | |
211 | return NULL; | |
212 | } | |
213 | break; | |
214 | } | |
215 | } | |
216 | ||
be759fcf PM |
217 | str_obj = PyObject_New (lazy_string_object, &lazy_string_object_type); |
218 | if (!str_obj) | |
219 | return NULL; | |
220 | ||
221 | str_obj->address = address; | |
222 | str_obj->length = length; | |
223 | if (encoding == NULL || !strcmp (encoding, "")) | |
224 | str_obj->encoding = NULL; | |
225 | else | |
226 | str_obj->encoding = xstrdup (encoding); | |
34b43320 | 227 | str_obj->type = type_to_type_object (type); |
be759fcf PM |
228 | |
229 | return (PyObject *) str_obj; | |
230 | } | |
231 | ||
999633ed | 232 | int |
be759fcf PM |
233 | gdbpy_initialize_lazy_string (void) |
234 | { | |
235 | if (PyType_Ready (&lazy_string_object_type) < 0) | |
999633ed | 236 | return -1; |
be759fcf PM |
237 | |
238 | Py_INCREF (&lazy_string_object_type); | |
999633ed | 239 | return 0; |
be759fcf PM |
240 | } |
241 | ||
242 | /* Determine whether the printer object pointed to by OBJ is a | |
243 | Python lazy string. */ | |
244 | int | |
245 | gdbpy_is_lazy_string (PyObject *result) | |
246 | { | |
247 | return PyObject_TypeCheck (result, &lazy_string_object_type); | |
248 | } | |
249 | ||
34b43320 DE |
250 | /* Return the type of a character in lazy string LAZY. */ |
251 | ||
252 | static struct type * | |
253 | stpy_lazy_string_elt_type (lazy_string_object *lazy) | |
254 | { | |
255 | struct type *type = type_object_to_type (lazy->type); | |
256 | struct type *realtype; | |
257 | ||
258 | gdb_assert (type != NULL); | |
259 | realtype = check_typedef (type); | |
260 | ||
78134374 | 261 | switch (realtype->code ()) |
34b43320 DE |
262 | { |
263 | case TYPE_CODE_PTR: | |
264 | case TYPE_CODE_ARRAY: | |
265 | return TYPE_TARGET_TYPE (realtype); | |
266 | default: | |
267 | /* This is done to preserve existing behaviour. PR 20769. | |
268 | E.g., gdb.parse_and_eval("my_int_variable").lazy_string().type. */ | |
269 | return realtype; | |
270 | } | |
271 | } | |
272 | ||
09ca9e2e | 273 | /* Extract the parameters from the lazy string object STRING. |
1eba6383 | 274 | ENCODING may be set to NULL, if no encoding is found. */ |
be759fcf | 275 | |
09ca9e2e TT |
276 | void |
277 | gdbpy_extract_lazy_string (PyObject *string, CORE_ADDR *addr, | |
34b43320 | 278 | struct type **str_elt_type, |
1eba6383 TT |
279 | long *length, |
280 | gdb::unique_xmalloc_ptr<char> *encoding) | |
09ca9e2e TT |
281 | { |
282 | lazy_string_object *lazy; | |
be759fcf | 283 | |
09ca9e2e | 284 | gdb_assert (gdbpy_is_lazy_string (string)); |
be759fcf | 285 | |
09ca9e2e | 286 | lazy = (lazy_string_object *) string; |
be759fcf | 287 | |
09ca9e2e | 288 | *addr = lazy->address; |
34b43320 | 289 | *str_elt_type = stpy_lazy_string_elt_type (lazy); |
09ca9e2e | 290 | *length = lazy->length; |
1eba6383 | 291 | encoding->reset (lazy->encoding ? xstrdup (lazy->encoding) : NULL); |
be759fcf PM |
292 | } |
293 | ||
294 | \f | |
295 | ||
296 | static PyMethodDef lazy_string_object_methods[] = { | |
297 | { "value", stpy_convert_to_value, METH_NOARGS, | |
298 | "Create a (lazy) value that contains a pointer to the string." }, | |
299 | {NULL} /* Sentinel */ | |
300 | }; | |
301 | ||
302 | ||
0d1f4ceb | 303 | static gdb_PyGetSetDef lazy_string_object_getset[] = { |
be759fcf PM |
304 | { "address", stpy_get_address, NULL, "Address of the string.", NULL }, |
305 | { "encoding", stpy_get_encoding, NULL, "Encoding of the string.", NULL }, | |
306 | { "length", stpy_get_length, NULL, "Length of the string.", NULL }, | |
307 | { "type", stpy_get_type, NULL, "Type associated with the string.", NULL }, | |
308 | { NULL } /* Sentinel */ | |
309 | }; | |
310 | ||
e36122e9 | 311 | PyTypeObject lazy_string_object_type = { |
9a27f2c6 | 312 | PyVarObject_HEAD_INIT (NULL, 0) |
be759fcf PM |
313 | "gdb.LazyString", /*tp_name*/ |
314 | sizeof (lazy_string_object), /*tp_basicsize*/ | |
315 | 0, /*tp_itemsize*/ | |
316 | stpy_dealloc, /*tp_dealloc*/ | |
317 | 0, /*tp_print*/ | |
318 | 0, /*tp_getattr*/ | |
319 | 0, /*tp_setattr*/ | |
320 | 0, /*tp_compare*/ | |
321 | 0, /*tp_repr*/ | |
322 | 0, /*tp_as_number*/ | |
323 | 0, /*tp_as_sequence*/ | |
324 | 0, /*tp_as_mapping*/ | |
325 | 0, /*tp_hash */ | |
326 | 0, /*tp_call*/ | |
327 | 0, /*tp_str*/ | |
328 | 0, /*tp_getattro*/ | |
329 | 0, /*tp_setattro*/ | |
330 | 0, /*tp_as_buffer*/ | |
331 | Py_TPFLAGS_DEFAULT, /*tp_flags*/ | |
332 | "GDB lazy string object", /* tp_doc */ | |
333 | 0, /* tp_traverse */ | |
334 | 0, /* tp_clear */ | |
335 | 0, /* tp_richcompare */ | |
336 | 0, /* tp_weaklistoffset */ | |
337 | 0, /* tp_iter */ | |
338 | 0, /* tp_iternext */ | |
339 | lazy_string_object_methods, /* tp_methods */ | |
340 | 0, /* tp_members */ | |
341 | lazy_string_object_getset /* tp_getset */ | |
342 | }; |