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