Commit | Line | Data |
---|---|---|
be759fcf PM |
1 | /* Python interface to lazy strings. |
2 | ||
42a4f53d | 3 | Copyright (C) 2010-2019 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 | ||
27 | typedef struct { | |
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; | |
be759fcf PM |
54 | } lazy_string_object; |
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 | |
74aedc46 | 64 | return gdb_py_long_from_ulongest (self_string->address); |
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 | |
be759fcf PM |
91 | return PyLong_FromLong (self_string->length); |
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); | |
123 | switch (TYPE_CODE (realtype)) | |
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 PM |
158 | xfree (self_string->encoding); |
159 | } | |
160 | ||
34b43320 DE |
161 | /* Low level routine to create a <gdb.LazyString> object. |
162 | ||
163 | Note: If TYPE is an array, LENGTH either must be -1 (meaning to use the | |
164 | size of the array, which may itself be unknown in which case a length of | |
165 | -1 is still used) or must be the length of the array. */ | |
166 | ||
be759fcf PM |
167 | PyObject * |
168 | gdbpy_create_lazy_string_object (CORE_ADDR address, long length, | |
34b43320 | 169 | const char *encoding, struct type *type) |
be759fcf PM |
170 | { |
171 | lazy_string_object *str_obj = NULL; | |
34b43320 DE |
172 | struct type *realtype; |
173 | ||
174 | if (length < -1) | |
175 | { | |
176 | PyErr_SetString (PyExc_ValueError, _("Invalid length.")); | |
177 | return NULL; | |
178 | } | |
be759fcf | 179 | |
fff5cc64 | 180 | if (address == 0 && length != 0) |
be759fcf | 181 | { |
4ea6efe9 | 182 | PyErr_SetString (gdbpy_gdb_memory_error, |
fff5cc64 PM |
183 | _("Cannot create a lazy string with address 0x0, " \ |
184 | "and a non-zero length.")); | |
be759fcf PM |
185 | return NULL; |
186 | } | |
187 | ||
188 | if (!type) | |
189 | { | |
190 | PyErr_SetString (PyExc_RuntimeError, | |
044c0f87 | 191 | _("A lazy string's type cannot be NULL.")); |
be759fcf PM |
192 | return NULL; |
193 | } | |
194 | ||
34b43320 DE |
195 | realtype = check_typedef (type); |
196 | switch (TYPE_CODE (realtype)) | |
197 | { | |
198 | case TYPE_CODE_ARRAY: | |
199 | { | |
200 | LONGEST array_length = -1; | |
201 | LONGEST low_bound, high_bound; | |
202 | ||
203 | if (get_array_bounds (realtype, &low_bound, &high_bound)) | |
204 | array_length = high_bound - low_bound + 1; | |
205 | if (length == -1) | |
206 | length = array_length; | |
207 | else if (length != array_length) | |
208 | { | |
209 | PyErr_SetString (PyExc_ValueError, _("Invalid length.")); | |
210 | return NULL; | |
211 | } | |
212 | break; | |
213 | } | |
214 | } | |
215 | ||
be759fcf PM |
216 | str_obj = PyObject_New (lazy_string_object, &lazy_string_object_type); |
217 | if (!str_obj) | |
218 | return NULL; | |
219 | ||
220 | str_obj->address = address; | |
221 | str_obj->length = length; | |
222 | if (encoding == NULL || !strcmp (encoding, "")) | |
223 | str_obj->encoding = NULL; | |
224 | else | |
225 | str_obj->encoding = xstrdup (encoding); | |
34b43320 | 226 | str_obj->type = type_to_type_object (type); |
be759fcf PM |
227 | |
228 | return (PyObject *) str_obj; | |
229 | } | |
230 | ||
999633ed | 231 | int |
be759fcf PM |
232 | gdbpy_initialize_lazy_string (void) |
233 | { | |
234 | if (PyType_Ready (&lazy_string_object_type) < 0) | |
999633ed | 235 | return -1; |
be759fcf PM |
236 | |
237 | Py_INCREF (&lazy_string_object_type); | |
999633ed | 238 | return 0; |
be759fcf PM |
239 | } |
240 | ||
241 | /* Determine whether the printer object pointed to by OBJ is a | |
242 | Python lazy string. */ | |
243 | int | |
244 | gdbpy_is_lazy_string (PyObject *result) | |
245 | { | |
246 | return PyObject_TypeCheck (result, &lazy_string_object_type); | |
247 | } | |
248 | ||
34b43320 DE |
249 | /* Return the type of a character in lazy string LAZY. */ |
250 | ||
251 | static struct type * | |
252 | stpy_lazy_string_elt_type (lazy_string_object *lazy) | |
253 | { | |
254 | struct type *type = type_object_to_type (lazy->type); | |
255 | struct type *realtype; | |
256 | ||
257 | gdb_assert (type != NULL); | |
258 | realtype = check_typedef (type); | |
259 | ||
260 | switch (TYPE_CODE (realtype)) | |
261 | { | |
262 | case TYPE_CODE_PTR: | |
263 | case TYPE_CODE_ARRAY: | |
264 | return TYPE_TARGET_TYPE (realtype); | |
265 | default: | |
266 | /* This is done to preserve existing behaviour. PR 20769. | |
267 | E.g., gdb.parse_and_eval("my_int_variable").lazy_string().type. */ | |
268 | return realtype; | |
269 | } | |
270 | } | |
271 | ||
09ca9e2e | 272 | /* Extract the parameters from the lazy string object STRING. |
1eba6383 | 273 | ENCODING may be set to NULL, if no encoding is found. */ |
be759fcf | 274 | |
09ca9e2e TT |
275 | void |
276 | gdbpy_extract_lazy_string (PyObject *string, CORE_ADDR *addr, | |
34b43320 | 277 | struct type **str_elt_type, |
1eba6383 TT |
278 | long *length, |
279 | gdb::unique_xmalloc_ptr<char> *encoding) | |
09ca9e2e TT |
280 | { |
281 | lazy_string_object *lazy; | |
be759fcf | 282 | |
09ca9e2e | 283 | gdb_assert (gdbpy_is_lazy_string (string)); |
be759fcf | 284 | |
09ca9e2e | 285 | lazy = (lazy_string_object *) string; |
be759fcf | 286 | |
09ca9e2e | 287 | *addr = lazy->address; |
34b43320 | 288 | *str_elt_type = stpy_lazy_string_elt_type (lazy); |
09ca9e2e | 289 | *length = lazy->length; |
1eba6383 | 290 | encoding->reset (lazy->encoding ? xstrdup (lazy->encoding) : NULL); |
be759fcf PM |
291 | } |
292 | ||
293 | \f | |
294 | ||
295 | static PyMethodDef lazy_string_object_methods[] = { | |
296 | { "value", stpy_convert_to_value, METH_NOARGS, | |
297 | "Create a (lazy) value that contains a pointer to the string." }, | |
298 | {NULL} /* Sentinel */ | |
299 | }; | |
300 | ||
301 | ||
0d1f4ceb | 302 | static gdb_PyGetSetDef lazy_string_object_getset[] = { |
be759fcf PM |
303 | { "address", stpy_get_address, NULL, "Address of the string.", NULL }, |
304 | { "encoding", stpy_get_encoding, NULL, "Encoding of the string.", NULL }, | |
305 | { "length", stpy_get_length, NULL, "Length of the string.", NULL }, | |
306 | { "type", stpy_get_type, NULL, "Type associated with the string.", NULL }, | |
307 | { NULL } /* Sentinel */ | |
308 | }; | |
309 | ||
e36122e9 | 310 | PyTypeObject lazy_string_object_type = { |
9a27f2c6 | 311 | PyVarObject_HEAD_INIT (NULL, 0) |
be759fcf PM |
312 | "gdb.LazyString", /*tp_name*/ |
313 | sizeof (lazy_string_object), /*tp_basicsize*/ | |
314 | 0, /*tp_itemsize*/ | |
315 | stpy_dealloc, /*tp_dealloc*/ | |
316 | 0, /*tp_print*/ | |
317 | 0, /*tp_getattr*/ | |
318 | 0, /*tp_setattr*/ | |
319 | 0, /*tp_compare*/ | |
320 | 0, /*tp_repr*/ | |
321 | 0, /*tp_as_number*/ | |
322 | 0, /*tp_as_sequence*/ | |
323 | 0, /*tp_as_mapping*/ | |
324 | 0, /*tp_hash */ | |
325 | 0, /*tp_call*/ | |
326 | 0, /*tp_str*/ | |
327 | 0, /*tp_getattro*/ | |
328 | 0, /*tp_setattro*/ | |
329 | 0, /*tp_as_buffer*/ | |
330 | Py_TPFLAGS_DEFAULT, /*tp_flags*/ | |
331 | "GDB lazy string object", /* tp_doc */ | |
332 | 0, /* tp_traverse */ | |
333 | 0, /* tp_clear */ | |
334 | 0, /* tp_richcompare */ | |
335 | 0, /* tp_weaklistoffset */ | |
336 | 0, /* tp_iter */ | |
337 | 0, /* tp_iternext */ | |
338 | lazy_string_object_methods, /* tp_methods */ | |
339 | 0, /* tp_members */ | |
340 | lazy_string_object_getset /* tp_getset */ | |
341 | }; |