mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-08-06 14:49:38 +08:00
gdb/python: make the executable_changed event available from Python
This commit makes the executable_changed observable available through the Python API as an event. There's nothing particularly interesting going on here, it just follows the same pattern as many of the other Python events we support. The new event registry is called events.executable_changed, and this emits an ExecutableChangedEvent object which has two attributes, a gdb.Progspace called 'progspace', this is the program space in which the executable changed, and a Boolean called 'reload', which is True if the same executable changed on disk and has been reloaded, or is False when a new executable has been loaded. One interesting thing did come up during testing though, you'll notice the test contains a setup_kfail call. During testing I observed that the executable_changed event would trigger twice when GDB restarted an inferior. However, the ExecutableChangedEvent object is identical for both calls, so the wrong information is never sent out, we just see one too many events. I tracked this down to how the reload_symbols function (symfile.c) takes care to also reload the executable, however, I've split fixing this into a separate commit, so see the next commit for details. Reviewed-By: Eli Zaretskii <eliz@gnu.org> Approved-By: Tom Tromey <tom@tromey.com>
This commit is contained in:
@ -26,6 +26,8 @@
|
||||
#include "arch-utils.h"
|
||||
#include "solib.h"
|
||||
#include "block.h"
|
||||
#include "py-event.h"
|
||||
#include "observable.h"
|
||||
|
||||
struct pspace_object
|
||||
{
|
||||
@ -592,9 +594,61 @@ gdbpy_is_progspace (PyObject *obj)
|
||||
return PyObject_TypeCheck (obj, &pspace_object_type);
|
||||
}
|
||||
|
||||
/* Emit an ExecutableChangedEvent event to REGISTRY. Return 0 on success,
|
||||
or a negative value on error. PSPACE is the program_space in which the
|
||||
current executable has changed, and RELOAD_P is true if the executable
|
||||
path stayed the same, but the file on disk changed, or false if the
|
||||
executable path actually changed. */
|
||||
|
||||
static int
|
||||
emit_executable_changed_event (eventregistry_object *registry,
|
||||
struct program_space *pspace, bool reload_p)
|
||||
{
|
||||
gdbpy_ref<> event_obj
|
||||
= create_event_object (&executable_changed_event_object_type);
|
||||
if (event_obj == nullptr)
|
||||
return -1;
|
||||
|
||||
gdbpy_ref<> py_pspace = pspace_to_pspace_object (pspace);
|
||||
if (py_pspace == nullptr
|
||||
|| evpy_add_attribute (event_obj.get (), "progspace",
|
||||
py_pspace.get ()) < 0)
|
||||
return -1;
|
||||
|
||||
gdbpy_ref<> py_reload_p (PyBool_FromLong (reload_p ? 1 : 0));
|
||||
if (py_reload_p == nullptr
|
||||
|| evpy_add_attribute (event_obj.get (), "reload",
|
||||
py_reload_p.get ()) < 0)
|
||||
return -1;
|
||||
|
||||
return evpy_emit_event (event_obj.get (), registry);
|
||||
}
|
||||
|
||||
/* Listener for the executable_changed observable, this is called when the
|
||||
current executable within PSPACE changes. RELOAD_P is true if the
|
||||
executable path stayed the same but the file changed on disk. RELOAD_P
|
||||
is false if the executable path was changed. */
|
||||
|
||||
static void
|
||||
gdbpy_executable_changed (struct program_space *pspace, bool reload_p)
|
||||
{
|
||||
if (!gdb_python_initialized)
|
||||
return;
|
||||
|
||||
gdbpy_enter enter_py;
|
||||
|
||||
if (!evregpy_no_listeners_p (gdb_py_events.executable_changed))
|
||||
if (emit_executable_changed_event (gdb_py_events.executable_changed,
|
||||
pspace, reload_p) < 0)
|
||||
gdbpy_print_stack ();
|
||||
}
|
||||
|
||||
static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
|
||||
gdbpy_initialize_pspace (void)
|
||||
{
|
||||
gdb::observers::executable_changed.attach (gdbpy_executable_changed,
|
||||
"py-progspace");
|
||||
|
||||
if (PyType_Ready (&pspace_object_type) < 0)
|
||||
return -1;
|
||||
|
||||
|
Reference in New Issue
Block a user