@xref{Objfiles In Python}, for details of the @code{gdb.Objfile} object.
@end defvar
+@item events.free_objfile
+Emits @code{gdb.FreeObjFileEvent} which indicates that an object file
+is about to be removed from @value{GDBN}. One reason this can happen
+is when the inferior calls @code{dlclose}.
+@code{gdb.FreeObjFileEvent} has one attribute:
+
+@defvar NewObjFileEvent.objfile
+A reference to the object file (@code{gdb.Objfile}) which will be unloaded.
+@xref{Objfiles In Python}, for details of the @code{gdb.Objfile} object.
+@end defvar
+
@item events.clear_objfiles
Emits @code{gdb.ClearObjFilesEvent} which indicates that the list of object
files for a program space has been reset.
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)
"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",
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);
}
}
+/* 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.
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");
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);
+}
+
\f
/* Subroutine of emit_clear_objfiles_event to simplify it. */
--- /dev/null
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2022 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include <unistd.h>
+
+#ifdef __WIN32__
+#include <windows.h>
+#define dlopen(name, mode) LoadLibrary (TEXT (name))
+#define dlclose(handle) FreeLibrary (handle)
+#else
+#include <dlfcn.h>
+#endif
+
+/* This is updated by the .exp file. */
+char *libname = "py-events-shlib.so";
+
+int
+main ()
+{
+ void *h;
+
+ h = dlopen (libname, RTLD_LAZY);
+
+ dlclose (h);
+
+ h = NULL; /* final breakpoint here */
+ return 0;
+}
--- /dev/null
+# Copyright 2022 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+# Test the Python free_objfile event.
+
+load_lib gdb-python.exp
+
+if {[skip_shlib_tests]} {
+ untested "skipping shared library tests"
+ return -1
+}
+
+if {[get_compiler_info]} {
+ warning "Could not get compiler info"
+ untested "no compiler info"
+ return -1
+}
+
+standard_testfile .c
+if {[gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" \
+ executable {debug shlib_load}] != ""} {
+ untested "failed to compile"
+ return -1
+}
+
+set testfile2 py-events-shlib
+set srcfile2 ${testfile2}.c
+set binfile2 [standard_output_file ${testfile2}.so]
+set binfile2_dlopen [shlib_target_file ${testfile2}.so]
+if {[gdb_compile_shlib "${srcdir}/${subdir}/${srcfile2}" \
+ ${binfile2} {debug}] != ""} {
+ untested "failed to compile shared library"
+ return -1
+}
+
+clean_restart $testfile
+
+if {![runto_main]} {
+ return
+}
+
+if { [skip_python_tests] } { return }
+
+gdb_test_no_output "set var libname = \"$binfile2_dlopen\""
+
+set pyfile [gdb_remote_download host ${srcdir}/${subdir}/py-event-load.py]
+gdb_test_no_output "source ${pyfile}" "load python file"
+
+gdb_breakpoint [gdb_get_line_number "final breakpoint here"]
+
+gdb_continue_to_breakpoint "run to final breakpoint"
+
+gdb_test "python print(freed_objfile)" [string_to_regexp $binfile2_dlopen] \
+ "print name of unloaded objfile"
--- /dev/null
+# Copyright (C) 2022 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# Test Python free_objfile event.
+
+import gdb
+
+
+freed_objfile = None
+
+
+def free_objfile_handler(event):
+ assert isinstance(event, gdb.FreeObjFileEvent)
+ global freed_objfile
+ freed_objfile = event.objfile.username
+
+
+gdb.events.free_objfile.connect(free_objfile_handler)