1 /* Python interface to symbol tables.
2 
3    Copyright (C) 2008-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 "charset.h"
21 #include "symtab.h"
22 #include "source.h"
23 #include "python-internal.h"
24 #include "objfiles.h"
25 #include "block.h"
26 
27 struct symtab_object {
28   PyObject_HEAD
29   /* The GDB Symbol table structure.  */
30   struct symtab *symtab;
31   /* A symtab object is associated with an objfile, so keep track with
32      a doubly-linked list, rooted in the objfile.  This allows
33      invalidation of the underlying struct symtab when the objfile is
34      deleted.  */
35   symtab_object *prev;
36   symtab_object *next;
37 };
38 
39 /* This function is called when an objfile is about to be freed.
40    Invalidate the symbol table as further actions on the symbol table
41    would result in bad data.  All access to obj->symtab should be
42    gated by STPY_REQUIRE_VALID which will raise an exception on
43    invalid symbol tables.  */
44 struct stpy_deleter
45 {
operatorstpy_deleter46   void operator() (symtab_object *obj)
47   {
48     while (obj)
49       {
50           symtab_object *next = obj->next;
51 
52           obj->symtab = NULL;
53           obj->next = NULL;
54           obj->prev = NULL;
55           obj = next;
56       }
57   }
58 };
59 
60 extern PyTypeObject symtab_object_type
61     CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("symtab_object");
62 static const registry<objfile>::key<symtab_object, stpy_deleter>
63      stpy_objfile_data_key;
64 
65 /* Require a valid symbol table.  All access to symtab_object->symtab
66    should be gated by this call.  */
67 #define STPY_REQUIRE_VALID(symtab_obj, symtab)               \
68   do {                                                                 \
69     symtab = symtab_object_to_symtab (symtab_obj);           \
70     if (symtab == NULL)                                                \
71       {                                                                \
72           PyErr_SetString (PyExc_RuntimeError,               \
73                                _("Symbol Table is invalid.")); \
74           return NULL;                                                 \
75       }                                                                \
76   } while (0)
77 
78 struct sal_object {
79   PyObject_HEAD
80   /* The GDB Symbol table structure.  */
81   PyObject *symtab;
82   /* The GDB Symbol table and line structure.  */
83   struct symtab_and_line *sal;
84   /* A Symtab and line object is associated with an objfile, so keep
85      track with a doubly-linked list, rooted in the objfile.  This
86      allows invalidation of the underlying struct symtab_and_line
87      when the objfile is deleted.  */
88   sal_object *prev;
89   sal_object *next;
90 };
91 
92 /* This is called when an objfile is about to be freed.  Invalidate
93    the sal object as further actions on the sal would result in bad
94    data.  All access to obj->sal should be gated by
95    SALPY_REQUIRE_VALID which will raise an exception on invalid symbol
96    table and line objects.  */
97 struct salpy_deleter
98 {
operatorsalpy_deleter99   void operator() (sal_object *obj)
100   {
101     gdbpy_enter enter_py;
102 
103     while (obj)
104       {
105           sal_object *next = obj->next;
106 
107           gdbpy_ref<> tmp (obj->symtab);
108           obj->symtab = Py_None;
109           Py_INCREF (Py_None);
110 
111           obj->next = NULL;
112           obj->prev = NULL;
113           xfree (obj->sal);
114           obj->sal = NULL;
115 
116           obj = next;
117       }
118   }
119 };
120 
121 extern PyTypeObject sal_object_type
122     CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("sal_object");
123 static const registry<objfile>::key<sal_object, salpy_deleter>
124      salpy_objfile_data_key;
125 
126 /* Require a valid symbol table and line object.  All access to
127    sal_object->sal should be gated by this call.  */
128 #define SALPY_REQUIRE_VALID(sal_obj, sal)                                       \
129   do {                                                                                    \
130     sal = sal_object_to_symtab_and_line (sal_obj);                              \
131     if (sal == NULL)                                                                      \
132       {                                                                                   \
133             PyErr_SetString (PyExc_RuntimeError,                                \
134                                  _("Symbol Table and Line is invalid."));       \
135             return NULL;                                                                  \
136           }                                                                               \
137   } while (0)
138 
139 static PyObject *
stpy_str(PyObject * self)140 stpy_str (PyObject *self)
141 {
142   PyObject *result;
143   struct symtab *symtab = NULL;
144 
145   STPY_REQUIRE_VALID (self, symtab);
146 
147   result = PyUnicode_FromString (symtab_to_filename_for_display (symtab));
148 
149   return result;
150 }
151 
152 static PyObject *
stpy_get_filename(PyObject * self,void * closure)153 stpy_get_filename (PyObject *self, void *closure)
154 {
155   PyObject *str_obj;
156   struct symtab *symtab = NULL;
157   const char *filename;
158 
159   STPY_REQUIRE_VALID (self, symtab);
160   filename = symtab_to_filename_for_display (symtab);
161 
162   str_obj = host_string_to_python_string (filename).release ();
163   return str_obj;
164 }
165 
166 static PyObject *
stpy_get_objfile(PyObject * self,void * closure)167 stpy_get_objfile (PyObject *self, void *closure)
168 {
169   struct symtab *symtab = NULL;
170 
171   STPY_REQUIRE_VALID (self, symtab);
172 
173   return objfile_to_objfile_object (symtab->compunit ()->objfile ()).release ();
174 }
175 
176 /* Getter function for symtab.producer.  */
177 
178 static PyObject *
stpy_get_producer(PyObject * self,void * closure)179 stpy_get_producer (PyObject *self, void *closure)
180 {
181   struct symtab *symtab = NULL;
182   struct compunit_symtab *cust;
183 
184   STPY_REQUIRE_VALID (self, symtab);
185   cust = symtab->compunit ();
186   if (cust->producer () != nullptr)
187     {
188       const char *producer = cust->producer ();
189 
190       return host_string_to_python_string (producer).release ();
191     }
192 
193   Py_RETURN_NONE;
194 }
195 
196 static PyObject *
stpy_fullname(PyObject * self,PyObject * args)197 stpy_fullname (PyObject *self, PyObject *args)
198 {
199   const char *fullname;
200   struct symtab *symtab = NULL;
201 
202   STPY_REQUIRE_VALID (self, symtab);
203 
204   fullname = symtab_to_fullname (symtab);
205 
206   return host_string_to_python_string (fullname).release ();
207 }
208 
209 /* Implementation of gdb.Symtab.is_valid (self) -> Boolean.
210    Returns True if this Symbol table still exists in GDB.  */
211 
212 static PyObject *
stpy_is_valid(PyObject * self,PyObject * args)213 stpy_is_valid (PyObject *self, PyObject *args)
214 {
215   struct symtab *symtab = NULL;
216 
217   symtab = symtab_object_to_symtab (self);
218   if (symtab == NULL)
219     Py_RETURN_FALSE;
220 
221   Py_RETURN_TRUE;
222 }
223 
224 /* Return the GLOBAL_BLOCK of the underlying symtab.  */
225 
226 static PyObject *
stpy_global_block(PyObject * self,PyObject * args)227 stpy_global_block (PyObject *self, PyObject *args)
228 {
229   struct symtab *symtab = NULL;
230   const struct blockvector *blockvector;
231 
232   STPY_REQUIRE_VALID (self, symtab);
233 
234   blockvector = symtab->compunit ()->blockvector ();
235   const struct block *block = blockvector->global_block ();
236 
237   return block_to_block_object (block, symtab->compunit ()->objfile ());
238 }
239 
240 /* Return the STATIC_BLOCK of the underlying symtab.  */
241 
242 static PyObject *
stpy_static_block(PyObject * self,PyObject * args)243 stpy_static_block (PyObject *self, PyObject *args)
244 {
245   struct symtab *symtab = NULL;
246   const struct blockvector *blockvector;
247 
248   STPY_REQUIRE_VALID (self, symtab);
249 
250   blockvector = symtab->compunit ()->blockvector ();
251   const struct block *block = blockvector->static_block ();
252 
253   return block_to_block_object (block, symtab->compunit ()->objfile ());
254 }
255 
256 /* Implementation of gdb.Symtab.linetable (self) -> gdb.LineTable.
257    Returns a gdb.LineTable object corresponding to this symbol
258    table.  */
259 
260 static PyObject *
stpy_get_linetable(PyObject * self,PyObject * args)261 stpy_get_linetable (PyObject *self, PyObject *args)
262 {
263   struct symtab *symtab = NULL;
264 
265   STPY_REQUIRE_VALID (self, symtab);
266 
267   return symtab_to_linetable_object (self);
268 }
269 
270 static PyObject *
salpy_str(PyObject * self)271 salpy_str (PyObject *self)
272 {
273   const char *filename;
274   sal_object *sal_obj;
275   struct symtab_and_line *sal = NULL;
276 
277   SALPY_REQUIRE_VALID (self, sal);
278 
279   sal_obj = (sal_object *) self;
280   if (sal_obj->symtab == Py_None)
281     filename = "<unknown>";
282   else
283     {
284       symtab *symtab = symtab_object_to_symtab (sal_obj->symtab);
285       filename = symtab_to_filename_for_display (symtab);
286     }
287 
288   return PyUnicode_FromFormat ("symbol and line for %s, line %d", filename,
289                                      sal->line);
290 }
291 
292 static void
stpy_dealloc(PyObject * obj)293 stpy_dealloc (PyObject *obj)
294 {
295   symtab_object *symtab = (symtab_object *) obj;
296 
297   if (symtab->prev)
298     symtab->prev->next = symtab->next;
299   else if (symtab->symtab)
300     stpy_objfile_data_key.set (symtab->symtab->compunit ()->objfile (),
301                                      symtab->next);
302   if (symtab->next)
303     symtab->next->prev = symtab->prev;
304   symtab->symtab = NULL;
305   Py_TYPE (obj)->tp_free (obj);
306 }
307 
308 
309 static PyObject *
salpy_get_pc(PyObject * self,void * closure)310 salpy_get_pc (PyObject *self, void *closure)
311 {
312   struct symtab_and_line *sal = NULL;
313 
314   SALPY_REQUIRE_VALID (self, sal);
315 
316   return gdb_py_object_from_ulongest (sal->pc).release ();
317 }
318 
319 /* Implementation of the get method for the 'last' attribute of
320    gdb.Symtab_and_line.  */
321 
322 static PyObject *
salpy_get_last(PyObject * self,void * closure)323 salpy_get_last (PyObject *self, void *closure)
324 {
325   struct symtab_and_line *sal = NULL;
326 
327   SALPY_REQUIRE_VALID (self, sal);
328 
329   if (sal->end > 0)
330     return gdb_py_object_from_ulongest (sal->end - 1).release ();
331   else
332     Py_RETURN_NONE;
333 }
334 
335 static PyObject *
salpy_get_line(PyObject * self,void * closure)336 salpy_get_line (PyObject *self, void *closure)
337 {
338   struct symtab_and_line *sal = NULL;
339 
340   SALPY_REQUIRE_VALID (self, sal);
341 
342   return gdb_py_object_from_longest (sal->line).release ();
343 }
344 
345 static PyObject *
salpy_get_symtab(PyObject * self,void * closure)346 salpy_get_symtab (PyObject *self, void *closure)
347 {
348   struct symtab_and_line *sal;
349   sal_object *self_sal = (sal_object *) self;
350 
351   SALPY_REQUIRE_VALID (self, sal);
352 
353   Py_INCREF (self_sal->symtab);
354 
355   return (PyObject *) self_sal->symtab;
356 }
357 
358 /* Implementation of gdb.Symtab_and_line.is_valid (self) -> Boolean.
359    Returns True if this Symbol table and line object still exists GDB.  */
360 
361 static PyObject *
salpy_is_valid(PyObject * self,PyObject * args)362 salpy_is_valid (PyObject *self, PyObject *args)
363 {
364   struct symtab_and_line *sal;
365 
366   sal = sal_object_to_symtab_and_line (self);
367   if (sal == NULL)
368     Py_RETURN_FALSE;
369 
370   Py_RETURN_TRUE;
371 }
372 
373 static void
salpy_dealloc(PyObject * self)374 salpy_dealloc (PyObject *self)
375 {
376   sal_object *self_sal = (sal_object *) self;
377 
378   if (self_sal->prev)
379     self_sal->prev->next = self_sal->next;
380   else if (self_sal->symtab != Py_None)
381     salpy_objfile_data_key.set
382       (symtab_object_to_symtab (self_sal->symtab)->compunit ()->objfile (),
383        self_sal->next);
384 
385   if (self_sal->next)
386     self_sal->next->prev = self_sal->prev;
387 
388   Py_DECREF (self_sal->symtab);
389   xfree (self_sal->sal);
390   Py_TYPE (self)->tp_free (self);
391 }
392 
393 /* Given a sal, and a sal_object that has previously been allocated
394    and initialized, populate the sal_object with the struct sal data.
395    Also, register the sal_object life-cycle with the life-cycle of the
396    object file associated with this sal, if needed.  If a failure
397    occurs during the sal population, this function will return -1.  */
398 static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
set_sal(sal_object * sal_obj,struct symtab_and_line sal)399 set_sal (sal_object *sal_obj, struct symtab_and_line sal)
400 {
401   PyObject *symtab_obj;
402 
403   if (sal.symtab)
404     {
405       symtab_obj = symtab_to_symtab_object  (sal.symtab);
406       /* If a symtab existed in the sal, but it cannot be duplicated,
407            we exit.  */
408       if (symtab_obj == NULL)
409           return -1;
410     }
411   else
412     {
413       symtab_obj = Py_None;
414       Py_INCREF (Py_None);
415     }
416 
417   sal_obj->sal = ((struct symtab_and_line *)
418                       xmemdup (&sal, sizeof (struct symtab_and_line),
419                                  sizeof (struct symtab_and_line)));
420   sal_obj->symtab = symtab_obj;
421   sal_obj->prev = NULL;
422 
423   /* If the SAL does not have a symtab, we do not add it to the
424      objfile cleanup observer linked list.  */
425   if (sal_obj->symtab != Py_None)
426     {
427       symtab *symtab = symtab_object_to_symtab (sal_obj->symtab);
428 
429       sal_obj->next
430           = salpy_objfile_data_key.get (symtab->compunit ()->objfile ());
431       if (sal_obj->next)
432           sal_obj->next->prev = sal_obj;
433 
434       salpy_objfile_data_key.set (symtab->compunit ()->objfile (), sal_obj);
435     }
436   else
437     sal_obj->next = NULL;
438 
439   return 0;
440 }
441 
442 /* Given a symtab, and a symtab_object that has previously been
443    allocated and initialized, populate the symtab_object with the
444    struct symtab data.  Also, register the symtab_object life-cycle
445    with the life-cycle of the object file associated with this
446    symtab, if needed.  */
447 static void
set_symtab(symtab_object * obj,struct symtab * symtab)448 set_symtab (symtab_object *obj, struct symtab *symtab)
449 {
450   obj->symtab = symtab;
451   obj->prev = NULL;
452   if (symtab)
453     {
454       obj->next = stpy_objfile_data_key.get (symtab->compunit ()->objfile ());
455       if (obj->next)
456           obj->next->prev = obj;
457       stpy_objfile_data_key.set (symtab->compunit ()->objfile (), obj);
458     }
459   else
460     obj->next = NULL;
461 }
462 
463 /* Create a new symbol table (gdb.Symtab) object that encapsulates the
464    symtab structure from GDB.  */
465 PyObject *
symtab_to_symtab_object(struct symtab * symtab)466 symtab_to_symtab_object (struct symtab *symtab)
467 {
468   symtab_object *symtab_obj;
469 
470   symtab_obj = PyObject_New (symtab_object, &symtab_object_type);
471   if (symtab_obj)
472     set_symtab (symtab_obj, symtab);
473 
474   return (PyObject *) symtab_obj;
475 }
476 
477 /* Create a new symtab and line (gdb.Symtab_and_line) object
478    that encapsulates the symtab_and_line structure from GDB.  */
479 PyObject *
symtab_and_line_to_sal_object(struct symtab_and_line sal)480 symtab_and_line_to_sal_object (struct symtab_and_line sal)
481 {
482   gdbpy_ref<sal_object> sal_obj (PyObject_New (sal_object, &sal_object_type));
483   if (sal_obj != NULL)
484     {
485       if (set_sal (sal_obj.get (), sal) < 0)
486           return NULL;
487     }
488 
489   return (PyObject *) sal_obj.release ();
490 }
491 
492 /* Return struct symtab_and_line reference that is wrapped by this
493    object.  */
494 struct symtab_and_line *
sal_object_to_symtab_and_line(PyObject * obj)495 sal_object_to_symtab_and_line (PyObject *obj)
496 {
497   if (! PyObject_TypeCheck (obj, &sal_object_type))
498     return NULL;
499   return ((sal_object *) obj)->sal;
500 }
501 
502 /* Return struct symtab reference that is wrapped by this object.  */
503 struct symtab *
symtab_object_to_symtab(PyObject * obj)504 symtab_object_to_symtab (PyObject *obj)
505 {
506   if (! PyObject_TypeCheck (obj, &symtab_object_type))
507     return NULL;
508   return ((symtab_object *) obj)->symtab;
509 }
510 
511 static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
gdbpy_initialize_symtabs(void)512 gdbpy_initialize_symtabs (void)
513 {
514   symtab_object_type.tp_new = PyType_GenericNew;
515   if (PyType_Ready (&symtab_object_type) < 0)
516     return -1;
517 
518   sal_object_type.tp_new = PyType_GenericNew;
519   if (PyType_Ready (&sal_object_type) < 0)
520     return -1;
521 
522   if (gdb_pymodule_addobject (gdb_module, "Symtab",
523                                     (PyObject *) &symtab_object_type) < 0)
524     return -1;
525 
526   return gdb_pymodule_addobject (gdb_module, "Symtab_and_line",
527                                          (PyObject *) &sal_object_type);
528 }
529 
530 GDBPY_INITIALIZE_FILE (gdbpy_initialize_symtabs);
531 
532 
533 
534 static gdb_PyGetSetDef symtab_object_getset[] = {
535   { "filename", stpy_get_filename, NULL,
536     "The symbol table's source filename.", NULL },
537   { "objfile", stpy_get_objfile, NULL, "The symtab's objfile.",
538     NULL },
539   { "producer", stpy_get_producer, NULL,
540     "The name/version of the program that compiled this symtab.", NULL },
541   {NULL}  /* Sentinel */
542 };
543 
544 static PyMethodDef symtab_object_methods[] = {
545   { "is_valid", stpy_is_valid, METH_NOARGS,
546     "is_valid () -> Boolean.\n\
547 Return true if this symbol table is valid, false if not." },
548   { "fullname", stpy_fullname, METH_NOARGS,
549     "fullname () -> String.\n\
550 Return the symtab's full source filename." },
551   { "global_block", stpy_global_block, METH_NOARGS,
552     "global_block () -> gdb.Block.\n\
553 Return the global block of the symbol table." },
554   { "static_block", stpy_static_block, METH_NOARGS,
555     "static_block () -> gdb.Block.\n\
556 Return the static block of the symbol table." },
557     { "linetable", stpy_get_linetable, METH_NOARGS,
558     "linetable () -> gdb.LineTable.\n\
559 Return the LineTable associated with this symbol table" },
560   {NULL}  /* Sentinel */
561 };
562 
563 PyTypeObject symtab_object_type = {
564   PyVarObject_HEAD_INIT (NULL, 0)
565   "gdb.Symtab",                           /*tp_name*/
566   sizeof (symtab_object),       /*tp_basicsize*/
567   0,                                      /*tp_itemsize*/
568   stpy_dealloc,                           /*tp_dealloc*/
569   0,                                      /*tp_print*/
570   0,                                      /*tp_getattr*/
571   0,                                      /*tp_setattr*/
572   0,                                      /*tp_compare*/
573   0,                                      /*tp_repr*/
574   0,                                      /*tp_as_number*/
575   0,                                      /*tp_as_sequence*/
576   0,                                      /*tp_as_mapping*/
577   0,                                      /*tp_hash */
578   0,                                      /*tp_call*/
579   stpy_str,                               /*tp_str*/
580   0,                                      /*tp_getattro*/
581   0,                                      /*tp_setattro*/
582   0,                                      /*tp_as_buffer*/
583   Py_TPFLAGS_DEFAULT,                     /*tp_flags*/
584   "GDB symtab object",                    /*tp_doc */
585   0,                                      /*tp_traverse */
586   0,                                      /*tp_clear */
587   0,                                      /*tp_richcompare */
588   0,                                      /*tp_weaklistoffset */
589   0,                                      /*tp_iter */
590   0,                                      /*tp_iternext */
591   symtab_object_methods,        /*tp_methods */
592   0,                                      /*tp_members */
593   symtab_object_getset                    /*tp_getset */
594 };
595 
596 static gdb_PyGetSetDef sal_object_getset[] = {
597   { "symtab", salpy_get_symtab, NULL, "Symtab object.", NULL },
598   { "pc", salpy_get_pc, NULL, "Return the symtab_and_line's pc.", NULL },
599   { "last", salpy_get_last, NULL,
600     "Return the symtab_and_line's last address.", NULL },
601   { "line", salpy_get_line, NULL,
602     "Return the symtab_and_line's line.", NULL },
603   {NULL}  /* Sentinel */
604 };
605 
606 static PyMethodDef sal_object_methods[] = {
607   { "is_valid", salpy_is_valid, METH_NOARGS,
608     "is_valid () -> Boolean.\n\
609 Return true if this symbol table and line is valid, false if not." },
610   {NULL}  /* Sentinel */
611 };
612 
613 PyTypeObject sal_object_type = {
614   PyVarObject_HEAD_INIT (NULL, 0)
615   "gdb.Symtab_and_line",        /*tp_name*/
616   sizeof (sal_object),                    /*tp_basicsize*/
617   0,                                      /*tp_itemsize*/
618   salpy_dealloc,                /*tp_dealloc*/
619   0,                                      /*tp_print*/
620   0,                                      /*tp_getattr*/
621   0,                                      /*tp_setattr*/
622   0,                                      /*tp_compare*/
623   0,                                      /*tp_repr*/
624   0,                                      /*tp_as_number*/
625   0,                                      /*tp_as_sequence*/
626   0,                                      /*tp_as_mapping*/
627   0,                                      /*tp_hash */
628   0,                                      /*tp_call*/
629   salpy_str,                              /*tp_str*/
630   0,                                      /*tp_getattro*/
631   0,                                      /*tp_setattro*/
632   0,                                      /*tp_as_buffer*/
633   Py_TPFLAGS_DEFAULT,                     /*tp_flags*/
634   "GDB symtab_and_line object",           /*tp_doc */
635   0,                                      /*tp_traverse */
636   0,                                      /*tp_clear */
637   0,                                      /*tp_richcompare */
638   0,                                      /*tp_weaklistoffset */
639   0,                                      /*tp_iter */
640   0,                                      /*tp_iternext */
641   sal_object_methods,                     /*tp_methods */
642   0,                                      /*tp_members */
643   sal_object_getset             /*tp_getset */
644 };
645