diff options
author | Jan Vrany <jan.vrany@labware.com> | 2024-11-21 13:52:19 +0000 |
---|---|---|
committer | Jan Vrany <jan.vrany@labware.com> | 2024-11-21 13:52:19 +0000 |
commit | 8adaaeb6addea1f1692729b8c9fab4ba3417ae55 (patch) | |
tree | f8fe04bda6dec9e3a4442e1999a85589a6a5eab9 | |
parent | 840a8c0eee3cc5c3f206bddfabd979ed65577d5a (diff) | |
download | fsf-binutils-gdb-8adaaeb6addea1f1692729b8c9fab4ba3417ae55.zip fsf-binutils-gdb-8adaaeb6addea1f1692729b8c9fab4ba3417ae55.tar.gz fsf-binutils-gdb-8adaaeb6addea1f1692729b8c9fab4ba3417ae55.tar.bz2 |
gdb/python: allow instantiation of gdb.Objfile from Python
This commit adds code to allow user extension to instantiate
gdb.Objfile. This is a step towards a Python support for dynamically
generated code (JIT) in GDB.
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
-rw-r--r-- | gdb/doc/python.texi | 13 | ||||
-rw-r--r-- | gdb/python/py-inferior.c | 10 | ||||
-rw-r--r-- | gdb/python/py-objfile.c | 111 | ||||
-rw-r--r-- | gdb/python/python-internal.h | 1 | ||||
-rw-r--r-- | gdb/testsuite/gdb.python/py-objfile.exp | 38 |
5 files changed, 169 insertions, 4 deletions
diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi index 59d6d34..b3262f7 100644 --- a/gdb/doc/python.texi +++ b/gdb/doc/python.texi @@ -5656,6 +5656,19 @@ Reading symbols from ./hello... A @code{gdb.Objfile} object has the following methods: +@defun Objfile.__init__ (filename @r{[}, inferior @r{][}, arch @r{]}) +Create a new objfile with given @var{filename}. + +The optional @var{inferior} argument specifies the inferior to which the newly +created objfile is added. Defaults to currently selected inferior. +@pxref{Inferiors In Python}. + +The optional @var{arch} argument specifies the architectore to associate with +the newly created objfile. Defaults to inferior's architecture. +@xref{Architectures In Python}. + +@end defun + @defun Objfile.is_valid () Returns @code{True} if the @code{gdb.Objfile} object is valid, @code{False} if not. A @code{gdb.Objfile} object can become invalid diff --git a/gdb/python/py-inferior.c b/gdb/python/py-inferior.c index 60bf56d..7255807 100644 --- a/gdb/python/py-inferior.c +++ b/gdb/python/py-inferior.c @@ -225,6 +225,16 @@ python_free_objfile (struct objfile *objfile) gdbpy_print_stack (); } +/* Return inferior reference that is wrapped by this object. */ + +inferior * +inferior_object_to_inferior (PyObject *obj) +{ + if (! PyObject_TypeCheck (obj, &inferior_object_type)) + return nullptr; + return ((inferior_object *) obj)->inferior; +} + /* Return a reference to the Python object of type Inferior representing INFERIOR. If the object has already been created, return it and increment the reference count, otherwise, create it. diff --git a/gdb/python/py-objfile.c b/gdb/python/py-objfile.c index e006fcc..cc225ca 100644 --- a/gdb/python/py-objfile.c +++ b/gdb/python/py-objfile.c @@ -25,6 +25,7 @@ #include "symtab.h" #include "python.h" #include "inferior.h" +#include "observable.h" struct objfile_object { @@ -251,6 +252,84 @@ objfpy_new (PyTypeObject *type, PyObject *args, PyObject *keywords) return (PyObject *) self.release (); } +/* Object initializer; creates new a objfile. + + Use: __init__(FILENAME [, INFERIOR [,ARCH]]). */ + +static int +objfpy_init (PyObject *zelf, PyObject *args, PyObject *kw) +{ + struct objfile_object *self = (struct objfile_object*) zelf; + + if (self->objfile) + { + PyErr_Format (PyExc_RuntimeError, + _("Objfile object already initialized.")); + return -1; + } + + static const char *keywords[] = { "filename", "inferior", "arch", nullptr }; + const char *filename; + PyObject* inf_obj = nullptr; + PyObject* arch_obj = nullptr; + + + if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "s|OO", keywords, + &filename, &inf_obj, &arch_obj)) + return -1; + + inferior *inf = nullptr; + if (inf_obj) + { + inf = inferior_object_to_inferior (inf_obj); + if (! inf) + { + PyErr_Format (PyExc_TypeError, + _("The inferior argument is not gdb.Inferior object")); + return -1; + } + } + else + { + inf = current_inferior (); + } + + gdbarch *arch = nullptr; + if (arch_obj) + { + if (! gdbpy_is_architecture (arch_obj)) + { + PyErr_Format (PyExc_TypeError, + _("The arch argument is not gdb.Architecture object")); + return -1; + } + arch = arch_object_to_gdbarch (arch_obj); + } + else + { + arch = inf->arch (); + } + + if (!objfpy_initialize (self)) + { + PyErr_Format (PyExc_RuntimeError, + _("Failed to initialize Objfile object.")); + return -1; + } + + struct objfile *objfile; + + objfile = objfile::make (nullptr, inf->pspace, filename, OBJF_NOT_FILENAME | OBJF_READNOW); + objfile->per_bfd->gdbarch = arch; + + self->objfile = objfile; + objfpy_objfile_data_key.set(objfile, self); + /* Increment refcount on self as it is now referenced from objfile! */ + Py_INCREF (self); + + return 0; +} + PyObject * objfpy_get_printers (PyObject *o, void *ignore) { @@ -731,6 +810,32 @@ objfile_to_objfile_object (struct objfile *objfile) return gdbpy_ref<>::new_reference (result); } +/* This function remove any dynamic objfiles left over when the + inferior exits. */ + +static void +objfpy_inferior_exit_hook (struct inferior *inf) +{ + for (objfile *objf : current_program_space->objfiles_safe ()) + { + if (objf->obfd == nullptr) + { + /* Following check is to only unlink dynamic objfiles created by + Python code. Dynamic objfiles created by JIT reader API are + unlinked in jit_inferior_exit_hook (). */ + if (objf->jited_data == nullptr || objf->jited_data->addr != 0) + objf->unlink (); + } + } +} + +void _initialize_py_objfile (); +void +_initialize_py_objfile () +{ + gdb::observers::inferior_exit.attach (objfpy_inferior_exit_hook, "py-objfile"); +} + static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION gdbpy_initialize_objfile (void) { @@ -835,8 +940,8 @@ PyTypeObject objfile_object_type = 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ - offsetof (objfile_object, dict), /* tp_dictoffset */ - 0, /* tp_init */ + offsetof (objfile_object, dict),/* tp_dictoffset */ + objfpy_init, /* tp_init */ 0, /* tp_alloc */ - objfpy_new, /* tp_new */ + objfpy_new, /* tp_new */ }; diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h index 0a52cb8..a5bcfed 100644 --- a/gdb/python/python-internal.h +++ b/gdb/python/python-internal.h @@ -574,6 +574,7 @@ struct symtab_and_line *sal_object_to_symtab_and_line (PyObject *obj); frame_info_ptr frame_object_to_frame_info (PyObject *frame_obj); struct gdbarch *arch_object_to_gdbarch (PyObject *obj); struct compunit_symtab *compunit_object_to_compunit (PyObject *obj); +inferior *inferior_object_to_inferior(PyObject *obj); extern PyObject *gdbpy_execute_mi_command (PyObject *self, PyObject *args, PyObject *kw); diff --git a/gdb/testsuite/gdb.python/py-objfile.exp b/gdb/testsuite/gdb.python/py-objfile.exp index 2f5b775..250ae47 100644 --- a/gdb/testsuite/gdb.python/py-objfile.exp +++ b/gdb/testsuite/gdb.python/py-objfile.exp @@ -172,4 +172,40 @@ if ![ishost *-*-mingw*] { gdb_py_test_silent_cmd "python objfile = gdb.objfiles()\[0\]" \ "get first objfile" 1 gdb_file_cmd ${binfile} -gdb_test "python print(objfile)" "<gdb.Objfile \\\(invalid\\\)>" +gdb_test "python print(objfile)" "<gdb.Objfile \\\(invalid\\\)>" "print invalid objfile" + +# Test creating objfile dynamically from Python +gdb_py_test_silent_cmd "python objfile = gdb.Objfile(\"Test objfile\")" \ + "create objfile" 1 + +gdb_test "python print(objfile)" \ + "<gdb.Objfile filename=Test objfile>" \ + "print dynamic objfile" + +gdb_test "python print(objfile.is_file)" \ + "False" \ + "(dynamic) objfile.is_file" + +gdb_test "python print(objfile.is_valid())" \ + "True" \ + "(dynamic) objfile.is_valid()" + +gdb_test "python print(objfile in gdb.objfiles())" \ + "True" \ + "(dynamic) objfile in gdb.objfiles()" + +gdb_test "python print( gdb.Objfile(\"Test objfile 2\", gdb.selected_inferior()))" \ + "<gdb.Objfile filename=Test objfile 2>" \ + "create objfile with inferior" + +gdb_test "python print( gdb.Objfile(\"Test objfile 3\", gdb.selected_inferior(), gdb.selected_inferior().architecture()))" \ + "<gdb.Objfile filename=Test objfile 3>" \ + "create objfile with inferior and arch" + +gdb_test "python print( gdb.Objfile(\"Test objfile 4\", gdb))" \ + "TypeError.*:.*" \ + "create objfile with invalid inferior" + +gdb_test "python print( gdb.Objfile(\"Test objfile 5\", gdb.selected_inferior(), gdb.selected_inferior()))" \ + "TypeError.*:.*" \ + "create objfile with valid inferior but invalid arch" |