From 0b4fe76f956293778f109764911a0b14dc944f5d Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Mon, 20 Jun 2022 11:30:04 -0600 Subject: Add gdb.free_objfile event registry Currently, Python code can use event registries to detect when gdb loads a new objfile, and when gdb clears the objfile list. However, there's no way to detect the removal of an objfile, say when the inferior calls dlclose. This patch adds a gdb.free_objfile event registry and arranges for an event to be emitted in this case. --- gdb/python/py-all-events.def | 1 + gdb/python/py-event-types.def | 5 +++++ gdb/python/py-event.h | 1 + gdb/python/py-inferior.c | 15 +++++++++++++++ gdb/python/py-newobjfileevent.c | 36 ++++++++++++++++++++++++++++++++++++ 5 files changed, 58 insertions(+) (limited to 'gdb/python') diff --git a/gdb/python/py-all-events.def b/gdb/python/py-all-events.def index 7db8efa..e8ae906 100644 --- a/gdb/python/py-all-events.def +++ b/gdb/python/py-all-events.def @@ -27,6 +27,7 @@ GDB_PY_DEFINE_EVENT(stop) GDB_PY_DEFINE_EVENT(cont) GDB_PY_DEFINE_EVENT(exited) GDB_PY_DEFINE_EVENT(new_objfile) +GDB_PY_DEFINE_EVENT(free_objfile) GDB_PY_DEFINE_EVENT(clear_objfiles) GDB_PY_DEFINE_EVENT(new_inferior) GDB_PY_DEFINE_EVENT(inferior_deleted) diff --git a/gdb/python/py-event-types.def b/gdb/python/py-event-types.def index 596e68a..e613e69 100644 --- a/gdb/python/py-event-types.def +++ b/gdb/python/py-event-types.def @@ -86,6 +86,11 @@ GDB_PY_DEFINE_EVENT_TYPE (new_objfile, "GDB new object file event object", event_object_type); +GDB_PY_DEFINE_EVENT_TYPE (free_objfile, + "FreeObjFileEvent", + "GDB free object file event object", + event_object_type); + GDB_PY_DEFINE_EVENT_TYPE (clear_objfiles, "ClearObjFilesEvent", "GDB clear object files event object", diff --git a/gdb/python/py-event.h b/gdb/python/py-event.h index 831dd10..220af1f 100644 --- a/gdb/python/py-event.h +++ b/gdb/python/py-event.h @@ -74,6 +74,7 @@ extern gdbpy_ref<> create_thread_event_object (PyTypeObject *py_type, PyObject *thread); extern int emit_new_objfile_event (struct objfile *objfile); +extern int emit_free_objfile_event (struct objfile *objfile); extern int emit_clear_objfiles_event (void); extern void evpy_dealloc (PyObject *self); diff --git a/gdb/python/py-inferior.c b/gdb/python/py-inferior.c index ebcd5b0..61ed342 100644 --- a/gdb/python/py-inferior.c +++ b/gdb/python/py-inferior.c @@ -197,6 +197,20 @@ python_new_objfile (struct objfile *objfile) } } +/* Emit a Python event when an objfile is about to be removed. */ + +static void +python_free_objfile (struct objfile *objfile) +{ + if (!gdb_python_initialized) + return; + + gdbpy_enter enter_py (objfile->arch ()); + + if (emit_free_objfile_event (objfile) < 0) + gdbpy_print_stack (); +} + /* 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. @@ -853,6 +867,7 @@ gdbpy_initialize_inferior (void) gdb::observers::new_objfile.attach (python_new_objfile, "py-inferior", { &auto_load_new_objfile_observer_token }); + gdb::observers::free_objfile.attach (python_free_objfile, "py-inferior"); gdb::observers::inferior_added.attach (python_new_inferior, "py-inferior"); gdb::observers::inferior_removed.attach (python_inferior_deleted, "py-inferior"); diff --git a/gdb/python/py-newobjfileevent.c b/gdb/python/py-newobjfileevent.c index dcbd0fa..929d0ea 100644 --- a/gdb/python/py-newobjfileevent.c +++ b/gdb/python/py-newobjfileevent.c @@ -53,6 +53,42 @@ emit_new_objfile_event (struct objfile *objfile) return -1; } +/* Create an event object representing a to-be-freed objfile. Return + nullptr, with the Python exception set, on error. */ + +static gdbpy_ref<> +create_free_objfile_event_object (struct objfile *objfile) +{ + gdbpy_ref<> objfile_event + = create_event_object (&free_objfile_event_object_type); + if (objfile_event == nullptr) + return nullptr; + + gdbpy_ref<> py_objfile = objfile_to_objfile_object (objfile); + if (py_objfile == nullptr + || evpy_add_attribute (objfile_event.get (), "objfile", + py_objfile.get ()) < 0) + return nullptr; + + return objfile_event; +} + +/* Callback function which notifies observers when a free objfile + event occurs. This function will create a new Python event object. + Return -1 if emit fails. */ + +int +emit_free_objfile_event (struct objfile *objfile) +{ + if (evregpy_no_listeners_p (gdb_py_events.free_objfile)) + return 0; + + gdbpy_ref<> event = create_free_objfile_event_object (objfile); + if (event == nullptr) + return -1; + return evpy_emit_event (event.get (), gdb_py_events.free_objfile); +} + /* Subroutine of emit_clear_objfiles_event to simplify it. */ -- cgit v1.1