1 /* Python interface to objfiles.
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 "python-internal.h"
21 #include "charset.h"
22 #include "objfiles.h"
23 #include "language.h"
24 #include "build-id.h"
25 #include "symtab.h"
26 #include "python.h"
27 #include "inferior.h"
28 
29 struct objfile_object
30 {
31   PyObject_HEAD
32 
33   /* The corresponding objfile.  */
34   struct objfile *objfile;
35 
36   /* Dictionary holding user-added attributes.
37      This is the __dict__ attribute of the object.  */
38   PyObject *dict;
39 
40   /* The pretty-printer list of functions.  */
41   PyObject *printers;
42 
43   /* The frame filter list of functions.  */
44   PyObject *frame_filters;
45 
46   /* The list of frame unwinders.  */
47   PyObject *frame_unwinders;
48 
49   /* The type-printer list.  */
50   PyObject *type_printers;
51 
52   /* The debug method matcher list.  */
53   PyObject *xmethods;
54 };
55 
56 extern PyTypeObject objfile_object_type
57     CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("objfile_object");
58 
59 /* Clear the OBJFILE pointer in an Objfile object and remove the
60    reference.  */
61 struct objfpy_deleter
62 {
operatorobjfpy_deleter63   void operator() (objfile_object *obj)
64   {
65     gdbpy_enter enter_py;
66     gdbpy_ref<objfile_object> object (obj);
67     object->objfile = nullptr;
68   }
69 };
70 
71 static const registry<objfile>::key<objfile_object, objfpy_deleter>
72      objfpy_objfile_data_key;
73 
74 /* Require that OBJF be a valid objfile.  */
75 #define OBJFPY_REQUIRE_VALID(obj)                                     \
76   do {                                                                          \
77     if (!(obj)->objfile)                                              \
78       {                                                                         \
79           PyErr_SetString (PyExc_RuntimeError,                        \
80                                _("Objfile no longer exists."));       \
81           return NULL;                                                          \
82       }                                                                         \
83   } while (0)
84 
85 
86 
87 /* An Objfile method which returns the objfile's file name, or None.  */
88 
89 static PyObject *
objfpy_get_filename(PyObject * self,void * closure)90 objfpy_get_filename (PyObject *self, void *closure)
91 {
92   objfile_object *obj = (objfile_object *) self;
93 
94   if (obj->objfile)
95     return (host_string_to_python_string (objfile_name (obj->objfile))
96               .release ());
97   Py_RETURN_NONE;
98 }
99 
100 /* An Objfile method which returns the objfile's file name, as specified
101    by the user, or None.  */
102 
103 static PyObject *
objfpy_get_username(PyObject * self,void * closure)104 objfpy_get_username (PyObject *self, void *closure)
105 {
106   objfile_object *obj = (objfile_object *) self;
107 
108   if (obj->objfile)
109     {
110       const char *username = obj->objfile->original_name;
111 
112       return host_string_to_python_string (username).release ();
113     }
114 
115   Py_RETURN_NONE;
116 }
117 
118 /* Get the 'is_file' attribute.  */
119 
120 static PyObject *
objfpy_get_is_file(PyObject * o,void * ignore)121 objfpy_get_is_file (PyObject *o, void *ignore)
122 {
123   objfile_object *self = (objfile_object *) o;
124 
125   if (self->objfile != nullptr)
126     return PyBool_FromLong ((self->objfile->flags & OBJF_NOT_FILENAME) == 0);
127   Py_RETURN_NONE;
128 }
129 
130 /* If SELF is a separate debug-info file, return the "backlink" field.
131    Otherwise return None.  */
132 
133 static PyObject *
objfpy_get_owner(PyObject * self,void * closure)134 objfpy_get_owner (PyObject *self, void *closure)
135 {
136   objfile_object *obj = (objfile_object *) self;
137   struct objfile *objfile = obj->objfile;
138   struct objfile *owner;
139 
140   OBJFPY_REQUIRE_VALID (obj);
141 
142   owner = objfile->separate_debug_objfile_backlink;
143   if (owner != NULL)
144     return objfile_to_objfile_object (owner).release ();
145   Py_RETURN_NONE;
146 }
147 
148 /* An Objfile method which returns the objfile's build id, or None.  */
149 
150 static PyObject *
objfpy_get_build_id(PyObject * self,void * closure)151 objfpy_get_build_id (PyObject *self, void *closure)
152 {
153   objfile_object *obj = (objfile_object *) self;
154   struct objfile *objfile = obj->objfile;
155   const struct bfd_build_id *build_id = NULL;
156 
157   OBJFPY_REQUIRE_VALID (obj);
158 
159   try
160     {
161       build_id = build_id_bfd_get (objfile->obfd.get ());
162     }
163   catch (const gdb_exception &except)
164     {
165       GDB_PY_HANDLE_EXCEPTION (except);
166     }
167 
168   if (build_id != NULL)
169     {
170       std::string hex_form = bin2hex (build_id->data, build_id->size);
171 
172       return host_string_to_python_string (hex_form.c_str ()).release ();
173     }
174 
175   Py_RETURN_NONE;
176 }
177 
178 /* An Objfile method which returns the objfile's progspace, or None.  */
179 
180 static PyObject *
objfpy_get_progspace(PyObject * self,void * closure)181 objfpy_get_progspace (PyObject *self, void *closure)
182 {
183   objfile_object *obj = (objfile_object *) self;
184 
185   if (obj->objfile)
186     return pspace_to_pspace_object (obj->objfile->pspace).release ();
187 
188   Py_RETURN_NONE;
189 }
190 
191 static void
objfpy_dealloc(PyObject * o)192 objfpy_dealloc (PyObject *o)
193 {
194   objfile_object *self = (objfile_object *) o;
195 
196   Py_XDECREF (self->dict);
197   Py_XDECREF (self->printers);
198   Py_XDECREF (self->frame_filters);
199   Py_XDECREF (self->frame_unwinders);
200   Py_XDECREF (self->type_printers);
201   Py_XDECREF (self->xmethods);
202   Py_TYPE (self)->tp_free (self);
203 }
204 
205 /* Initialize an objfile_object.
206    The result is a boolean indicating success.  */
207 
208 static int
objfpy_initialize(objfile_object * self)209 objfpy_initialize (objfile_object *self)
210 {
211   self->objfile = NULL;
212 
213   self->dict = PyDict_New ();
214   if (self->dict == NULL)
215     return 0;
216 
217   self->printers = PyList_New (0);
218   if (self->printers == NULL)
219     return 0;
220 
221   self->frame_filters = PyDict_New ();
222   if (self->frame_filters == NULL)
223     return 0;
224 
225   self->frame_unwinders = PyList_New (0);
226   if (self->frame_unwinders == NULL)
227     return 0;
228 
229   self->type_printers = PyList_New (0);
230   if (self->type_printers == NULL)
231     return 0;
232 
233   self->xmethods = PyList_New (0);
234   if (self->xmethods == NULL)
235     return 0;
236 
237   return 1;
238 }
239 
240 static PyObject *
objfpy_new(PyTypeObject * type,PyObject * args,PyObject * keywords)241 objfpy_new (PyTypeObject *type, PyObject *args, PyObject *keywords)
242 {
243   gdbpy_ref<objfile_object> self ((objfile_object *) type->tp_alloc (type, 0));
244 
245   if (self != NULL)
246     {
247       if (!objfpy_initialize (self.get ()))
248           return NULL;
249     }
250 
251   return (PyObject *) self.release ();
252 }
253 
254 PyObject *
objfpy_get_printers(PyObject * o,void * ignore)255 objfpy_get_printers (PyObject *o, void *ignore)
256 {
257   objfile_object *self = (objfile_object *) o;
258 
259   Py_INCREF (self->printers);
260   return self->printers;
261 }
262 
263 static int
objfpy_set_printers(PyObject * o,PyObject * value,void * ignore)264 objfpy_set_printers (PyObject *o, PyObject *value, void *ignore)
265 {
266   objfile_object *self = (objfile_object *) o;
267 
268   if (! value)
269     {
270       PyErr_SetString (PyExc_TypeError,
271                            _("Cannot delete the pretty_printers attribute."));
272       return -1;
273     }
274 
275   if (! PyList_Check (value))
276     {
277       PyErr_SetString (PyExc_TypeError,
278                            _("The pretty_printers attribute must be a list."));
279       return -1;
280     }
281 
282   /* Take care in case the LHS and RHS are related somehow.  */
283   gdbpy_ref<> tmp (self->printers);
284   Py_INCREF (value);
285   self->printers = value;
286 
287   return 0;
288 }
289 
290 /* Return the Python dictionary attribute containing frame filters for
291    this object file.  */
292 PyObject *
objfpy_get_frame_filters(PyObject * o,void * ignore)293 objfpy_get_frame_filters (PyObject *o, void *ignore)
294 {
295   objfile_object *self = (objfile_object *) o;
296 
297   Py_INCREF (self->frame_filters);
298   return self->frame_filters;
299 }
300 
301 /* Set this object file's frame filters dictionary to FILTERS.  */
302 static int
objfpy_set_frame_filters(PyObject * o,PyObject * filters,void * ignore)303 objfpy_set_frame_filters (PyObject *o, PyObject *filters, void *ignore)
304 {
305   objfile_object *self = (objfile_object *) o;
306 
307   if (! filters)
308     {
309       PyErr_SetString (PyExc_TypeError,
310                            _("Cannot delete the frame filters attribute."));
311       return -1;
312     }
313 
314   if (! PyDict_Check (filters))
315     {
316       PyErr_SetString (PyExc_TypeError,
317                            _("The frame_filters attribute must be a dictionary."));
318       return -1;
319     }
320 
321   /* Take care in case the LHS and RHS are related somehow.  */
322   gdbpy_ref<> tmp (self->frame_filters);
323   Py_INCREF (filters);
324   self->frame_filters = filters;
325 
326   return 0;
327 }
328 
329 /* Return the frame unwinders attribute for this object file.  */
330 
331 PyObject *
objfpy_get_frame_unwinders(PyObject * o,void * ignore)332 objfpy_get_frame_unwinders (PyObject *o, void *ignore)
333 {
334   objfile_object *self = (objfile_object *) o;
335 
336   Py_INCREF (self->frame_unwinders);
337   return self->frame_unwinders;
338 }
339 
340 /* Set this object file's frame unwinders list to UNWINDERS.  */
341 
342 static int
objfpy_set_frame_unwinders(PyObject * o,PyObject * unwinders,void * ignore)343 objfpy_set_frame_unwinders (PyObject *o, PyObject *unwinders, void *ignore)
344 {
345   objfile_object *self = (objfile_object *) o;
346 
347   if (!unwinders)
348     {
349       PyErr_SetString (PyExc_TypeError,
350                            _("Cannot delete the frame unwinders attribute."));
351       return -1;
352     }
353 
354   if (!PyList_Check (unwinders))
355     {
356       PyErr_SetString (PyExc_TypeError,
357                            _("The frame_unwinders attribute must be a list."));
358       return -1;
359     }
360 
361   /* Take care in case the LHS and RHS are related somehow.  */
362   gdbpy_ref<> tmp (self->frame_unwinders);
363   Py_INCREF (unwinders);
364   self->frame_unwinders = unwinders;
365 
366   return 0;
367 }
368 
369 /* Get the 'type_printers' attribute.  */
370 
371 static PyObject *
objfpy_get_type_printers(PyObject * o,void * ignore)372 objfpy_get_type_printers (PyObject *o, void *ignore)
373 {
374   objfile_object *self = (objfile_object *) o;
375 
376   Py_INCREF (self->type_printers);
377   return self->type_printers;
378 }
379 
380 /* Get the 'xmethods' attribute.  */
381 
382 PyObject *
objfpy_get_xmethods(PyObject * o,void * ignore)383 objfpy_get_xmethods (PyObject *o, void *ignore)
384 {
385   objfile_object *self = (objfile_object *) o;
386 
387   Py_INCREF (self->xmethods);
388   return self->xmethods;
389 }
390 
391 /* Set the 'type_printers' attribute.  */
392 
393 static int
objfpy_set_type_printers(PyObject * o,PyObject * value,void * ignore)394 objfpy_set_type_printers (PyObject *o, PyObject *value, void *ignore)
395 {
396   objfile_object *self = (objfile_object *) o;
397 
398   if (! value)
399     {
400       PyErr_SetString (PyExc_TypeError,
401                            _("Cannot delete the type_printers attribute."));
402       return -1;
403     }
404 
405   if (! PyList_Check (value))
406     {
407       PyErr_SetString (PyExc_TypeError,
408                            _("The type_printers attribute must be a list."));
409       return -1;
410     }
411 
412   /* Take care in case the LHS and RHS are related somehow.  */
413   gdbpy_ref<> tmp (self->type_printers);
414   Py_INCREF (value);
415   self->type_printers = value;
416 
417   return 0;
418 }
419 
420 /* Implementation of gdb.Objfile.is_valid (self) -> Boolean.
421    Returns True if this object file still exists in GDB.  */
422 
423 static PyObject *
objfpy_is_valid(PyObject * self,PyObject * args)424 objfpy_is_valid (PyObject *self, PyObject *args)
425 {
426   objfile_object *obj = (objfile_object *) self;
427 
428   if (! obj->objfile)
429     Py_RETURN_FALSE;
430 
431   Py_RETURN_TRUE;
432 }
433 
434 /* Implementation of gdb.Objfile.add_separate_debug_file (self, string). */
435 
436 static PyObject *
objfpy_add_separate_debug_file(PyObject * self,PyObject * args,PyObject * kw)437 objfpy_add_separate_debug_file (PyObject *self, PyObject *args, PyObject *kw)
438 {
439   static const char *keywords[] = { "file_name", NULL };
440   objfile_object *obj = (objfile_object *) self;
441   const char *file_name;
442 
443   OBJFPY_REQUIRE_VALID (obj);
444 
445   if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "s", keywords, &file_name))
446     return NULL;
447 
448   try
449     {
450       gdb_bfd_ref_ptr abfd (symfile_bfd_open (file_name));
451 
452       symbol_file_add_separate (abfd, file_name, 0, obj->objfile);
453     }
454   catch (const gdb_exception &except)
455     {
456       GDB_PY_HANDLE_EXCEPTION (except);
457     }
458 
459   Py_RETURN_NONE;
460 }
461 
462 /* Implementation of
463   gdb.Objfile.lookup_global_symbol (self, string [, domain]) -> gdb.Symbol.  */
464 
465 static PyObject *
objfpy_lookup_global_symbol(PyObject * self,PyObject * args,PyObject * kw)466 objfpy_lookup_global_symbol (PyObject *self, PyObject *args, PyObject *kw)
467 {
468   static const char *keywords[] = { "name", "domain", NULL };
469   objfile_object *obj = (objfile_object *) self;
470   const char *symbol_name;
471   int domain = VAR_DOMAIN;
472 
473   OBJFPY_REQUIRE_VALID (obj);
474 
475   if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "s|i", keywords, &symbol_name,
476                                                   &domain))
477     return nullptr;
478 
479   try
480     {
481       domain_search_flags flags = from_scripting_domain (domain);
482       struct symbol *sym = lookup_global_symbol_from_objfile
483           (obj->objfile, GLOBAL_BLOCK, symbol_name, flags).symbol;
484       if (sym == nullptr)
485           Py_RETURN_NONE;
486 
487       return symbol_to_symbol_object (sym);
488     }
489   catch (const gdb_exception &except)
490     {
491       GDB_PY_HANDLE_EXCEPTION (except);
492     }
493 
494   Py_RETURN_NONE;
495 }
496 
497 /* Implementation of
498   gdb.Objfile.lookup_static_symbol (self, string [, domain]) -> gdb.Symbol.  */
499 
500 static PyObject *
objfpy_lookup_static_symbol(PyObject * self,PyObject * args,PyObject * kw)501 objfpy_lookup_static_symbol (PyObject *self, PyObject *args, PyObject *kw)
502 {
503   static const char *keywords[] = { "name", "domain", NULL };
504   objfile_object *obj = (objfile_object *) self;
505   const char *symbol_name;
506   int domain = VAR_DOMAIN;
507 
508   OBJFPY_REQUIRE_VALID (obj);
509 
510   if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "s|i", keywords, &symbol_name,
511                                                   &domain))
512     return nullptr;
513 
514   try
515     {
516       domain_search_flags flags = from_scripting_domain (domain);
517       struct symbol *sym = lookup_global_symbol_from_objfile
518           (obj->objfile, STATIC_BLOCK, symbol_name, flags).symbol;
519       if (sym == nullptr)
520           Py_RETURN_NONE;
521 
522       return symbol_to_symbol_object (sym);
523     }
524   catch (const gdb_exception &except)
525     {
526       GDB_PY_HANDLE_EXCEPTION (except);
527     }
528 
529   Py_RETURN_NONE;
530 }
531 
532 /* Implement repr() for gdb.Objfile.  */
533 
534 static PyObject *
objfpy_repr(PyObject * self_)535 objfpy_repr (PyObject *self_)
536 {
537   objfile_object *self = (objfile_object *) self_;
538   objfile *obj = self->objfile;
539 
540   if (obj == nullptr)
541     return gdb_py_invalid_object_repr (self_);
542 
543   return PyUnicode_FromFormat ("<gdb.Objfile filename=%s>",
544                                      objfile_name (obj));
545 }
546 
547 /* Subroutine of gdbpy_lookup_objfile_by_build_id to simplify it.
548    Return non-zero if STRING is a potentially valid build id.  */
549 
550 static int
objfpy_build_id_ok(const char * string)551 objfpy_build_id_ok (const char *string)
552 {
553   size_t i, n = strlen (string);
554 
555   if (n % 2 != 0)
556     return 0;
557   for (i = 0; i < n; ++i)
558     {
559       if (!isxdigit (string[i]))
560           return 0;
561     }
562   return 1;
563 }
564 
565 /* Subroutine of gdbpy_lookup_objfile_by_build_id to simplify it.
566    Returns non-zero if BUILD_ID matches STRING.
567    It is assumed that objfpy_build_id_ok (string) returns TRUE.  */
568 
569 static int
objfpy_build_id_matches(const struct bfd_build_id * build_id,const char * string)570 objfpy_build_id_matches (const struct bfd_build_id *build_id,
571                                const char *string)
572 {
573   size_t i;
574 
575   if (strlen (string) != 2 * build_id->size)
576     return 0;
577 
578   for (i = 0; i < build_id->size; ++i)
579     {
580       char c1 = string[i * 2], c2 = string[i * 2 + 1];
581       int byte = (fromhex (c1) << 4) | fromhex (c2);
582 
583       if (byte != build_id->data[i])
584           return 0;
585     }
586 
587   return 1;
588 }
589 
590 /* Implementation of gdb.lookup_objfile.  */
591 
592 PyObject *
gdbpy_lookup_objfile(PyObject * self,PyObject * args,PyObject * kw)593 gdbpy_lookup_objfile (PyObject *self, PyObject *args, PyObject *kw)
594 {
595   static const char *keywords[] = { "name", "by_build_id", NULL };
596   const char *name;
597   PyObject *by_build_id_obj = NULL;
598   int by_build_id;
599 
600   if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "s|O!", keywords,
601                                                   &name, &PyBool_Type, &by_build_id_obj))
602     return NULL;
603 
604   by_build_id = 0;
605   if (by_build_id_obj != NULL)
606     {
607       int cmp = PyObject_IsTrue (by_build_id_obj);
608 
609       if (cmp < 0)
610           return NULL;
611       by_build_id = cmp;
612     }
613 
614   if (by_build_id && !objfpy_build_id_ok (name))
615     {
616       PyErr_SetString (PyExc_TypeError, _("Not a valid build id."));
617       return NULL;
618     }
619 
620   struct objfile *objfile = nullptr;
621   if (by_build_id)
622     gdbarch_iterate_over_objfiles_in_search_order
623       (current_inferior ()->arch (),
624        [&objfile, name] (struct objfile *obj)
625            {
626              /* Don't return separate debug files.  */
627              if (obj->separate_debug_objfile_backlink != nullptr)
628                return 0;
629 
630              bfd *obfd = obj->obfd.get ();
631              if (obfd == nullptr)
632                return 0;
633 
634              const bfd_build_id *obfd_build_id = build_id_bfd_get (obfd);
635              if (obfd_build_id == nullptr)
636                return 0;
637 
638              if (!objfpy_build_id_matches (obfd_build_id, name))
639                return 0;
640 
641              objfile = obj;
642              return 1;
643            }, gdbpy_current_objfile);
644   else
645     gdbarch_iterate_over_objfiles_in_search_order
646       (current_inferior ()->arch (),
647        [&objfile, name] (struct objfile *obj)
648            {
649              /* Don't return separate debug files.  */
650              if (obj->separate_debug_objfile_backlink != nullptr)
651                return 0;
652 
653              if ((obj->flags & OBJF_NOT_FILENAME) != 0)
654                return 0;
655 
656              const char *filename = objfile_filename (obj);
657              if (filename != NULL
658                  && compare_filenames_for_search (filename, name))
659                {
660                  objfile = obj;
661                  return 1;
662                }
663 
664              if (compare_filenames_for_search (obj->original_name, name))
665                {
666                  objfile = obj;
667                  return 1;
668                }
669 
670              return 0;
671            }, gdbpy_current_objfile);
672 
673   if (objfile != NULL)
674     return objfile_to_objfile_object (objfile).release ();
675 
676   PyErr_SetString (PyExc_ValueError, _("Objfile not found."));
677   return NULL;
678 }
679 
680 
681 
682 /* Return a new reference to the Python object of type Objfile
683    representing OBJFILE.  If the object has already been created,
684    return it.  Otherwise, create it.  Return NULL and set the Python
685    error on failure.  */
686 
687 gdbpy_ref<>
objfile_to_objfile_object(struct objfile * objfile)688 objfile_to_objfile_object (struct objfile *objfile)
689 {
690   PyObject *result
691     = (PyObject *) objfpy_objfile_data_key.get (objfile);
692   if (result == NULL)
693     {
694       gdbpy_ref<objfile_object> object
695           ((objfile_object *) PyObject_New (objfile_object, &objfile_object_type));
696       if (object == NULL)
697           return NULL;
698       if (!objfpy_initialize (object.get ()))
699           return NULL;
700 
701       object->objfile = objfile;
702       objfpy_objfile_data_key.set (objfile, object.get ());
703       result = (PyObject *) object.release ();
704     }
705 
706   return gdbpy_ref<>::new_reference (result);
707 }
708 
709 static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
gdbpy_initialize_objfile(void)710 gdbpy_initialize_objfile (void)
711 {
712   if (PyType_Ready (&objfile_object_type) < 0)
713     return -1;
714 
715   return gdb_pymodule_addobject (gdb_module, "Objfile",
716                                          (PyObject *) &objfile_object_type);
717 }
718 
719 GDBPY_INITIALIZE_FILE (gdbpy_initialize_objfile);
720 
721 
722 
723 static PyMethodDef objfile_object_methods[] =
724 {
725   { "is_valid", objfpy_is_valid, METH_NOARGS,
726     "is_valid () -> Boolean.\n\
727 Return true if this object file is valid, false if not." },
728 
729   { "add_separate_debug_file", (PyCFunction) objfpy_add_separate_debug_file,
730     METH_VARARGS | METH_KEYWORDS,
731     "add_separate_debug_file (file_name).\n\
732 Add FILE_NAME to the list of files containing debug info for the objfile." },
733 
734   { "lookup_global_symbol", (PyCFunction) objfpy_lookup_global_symbol,
735     METH_VARARGS | METH_KEYWORDS,
736     "lookup_global_symbol (name [, domain]).\n\
737 Look up a global symbol in this objfile and return it." },
738 
739   { "lookup_static_symbol", (PyCFunction) objfpy_lookup_static_symbol,
740     METH_VARARGS | METH_KEYWORDS,
741     "lookup_static_symbol (name [, domain]).\n\
742 Look up a static-linkage global symbol in this objfile and return it." },
743 
744   { NULL }
745 };
746 
747 static gdb_PyGetSetDef objfile_getset[] =
748 {
749   { "__dict__", gdb_py_generic_dict, NULL,
750     "The __dict__ for this objfile.", &objfile_object_type },
751   { "filename", objfpy_get_filename, NULL,
752     "The objfile's filename, or None.", NULL },
753   { "username", objfpy_get_username, NULL,
754     "The name of the objfile as provided by the user, or None.", NULL },
755   { "owner", objfpy_get_owner, NULL,
756     "The objfile owner of separate debug info objfiles, or None.",
757     NULL },
758   { "build_id", objfpy_get_build_id, NULL,
759     "The objfile's build id, or None.", NULL },
760   { "progspace", objfpy_get_progspace, NULL,
761     "The objfile's progspace, or None.", NULL },
762   { "pretty_printers", objfpy_get_printers, objfpy_set_printers,
763     "Pretty printers.", NULL },
764   { "frame_filters", objfpy_get_frame_filters,
765     objfpy_set_frame_filters, "Frame Filters.", NULL },
766   { "frame_unwinders", objfpy_get_frame_unwinders,
767     objfpy_set_frame_unwinders, "Frame Unwinders", NULL },
768   { "type_printers", objfpy_get_type_printers, objfpy_set_type_printers,
769     "Type printers.", NULL },
770   { "xmethods", objfpy_get_xmethods, NULL,
771     "Debug methods.", NULL },
772   { "is_file", objfpy_get_is_file, nullptr,
773     "Whether this objfile came from a file.", nullptr },
774   { NULL }
775 };
776 
777 PyTypeObject objfile_object_type =
778 {
779   PyVarObject_HEAD_INIT (NULL, 0)
780   "gdb.Objfile",                /*tp_name*/
781   sizeof (objfile_object),      /*tp_basicsize*/
782   0,                                      /*tp_itemsize*/
783   objfpy_dealloc,               /*tp_dealloc*/
784   0,                                      /*tp_print*/
785   0,                                      /*tp_getattr*/
786   0,                                      /*tp_setattr*/
787   0,                                      /*tp_compare*/
788   objfpy_repr,                            /*tp_repr*/
789   0,                                      /*tp_as_number*/
790   0,                                      /*tp_as_sequence*/
791   0,                                      /*tp_as_mapping*/
792   0,                                      /*tp_hash */
793   0,                                      /*tp_call*/
794   0,                                      /*tp_str*/
795   0,                                      /*tp_getattro*/
796   0,                                      /*tp_setattro*/
797   0,                                      /*tp_as_buffer*/
798   Py_TPFLAGS_DEFAULT,                     /*tp_flags*/
799   "GDB objfile object",                   /* tp_doc */
800   0,                                      /* tp_traverse */
801   0,                                      /* tp_clear */
802   0,                                      /* tp_richcompare */
803   0,                                      /* tp_weaklistoffset */
804   0,                                      /* tp_iter */
805   0,                                      /* tp_iternext */
806   objfile_object_methods,       /* tp_methods */
807   0,                                      /* tp_members */
808   objfile_getset,               /* tp_getset */
809   0,                                      /* tp_base */
810   0,                                      /* tp_dict */
811   0,                                      /* tp_descr_get */
812   0,                                      /* tp_descr_set */
813   offsetof (objfile_object, dict), /* tp_dictoffset */
814   0,                                      /* tp_init */
815   0,                                      /* tp_alloc */
816   objfpy_new,                             /* tp_new */
817 };
818