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.
This commit is contained in:
Tom Tromey 2022-06-20 11:30:04 -06:00
parent 23948f5602
commit 0b4fe76f95
9 changed files with 208 additions and 0 deletions

View file

@ -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)

View file

@ -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",

View file

@ -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);

View file

@ -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");

View file

@ -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. */