From: Sami Wagiaalla Date: Fri, 4 Feb 2011 21:54:16 +0000 (+0000) Subject: Add Python support for GDB events. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=505500db28fbb90d6391c2fdcfd27bcab443cd9c;p=binutils-gdb.git Add Python support for GDB events. 2011-02-04 Sami Wagiaalla * gdb.python/py-evthreads.c: New file. * gdb.python/py-evthreads.exp: New file. * gdb.python/py-events.py: New file. * gdb.python/py-events.exp: New file. * gdb.python/py-events.c: New file. 2011-02-04 Sami Wagiaalla Oguz Kayral * python/py-inferior.c (python_on_normal_stop): New function. (python_on_resume): New function. (python_inferior_exit): New function. (gdbpy_initialize_inferior): Add normal_stop, target_resumed, and inferior_exit observers. * python/py-evtregistry.c: New file. * python/py-threadevent.c : New file. * python/py-event.c: New file. * python/py-evts.c: New file. * python/py-continueevent.c: New file. * python/py-bpevent.c: New file. * python/py-signalevent.c: New file. * python/py-exetiedevent.c: New file. * python/py-breakpoint.c (gdbpy_breakpoint_from_bpstats): New function. Move struct breakpoint_object from here... * python/python-internal.h: ... to here. * python/py-event.h: New file. * python/py-events.h: New file. * Makefile.in (SUBDIR_PYTHON_OBS): Add py-breakpointstopevent.o, py-continueevent.o, py-event.o, py-eventregistry.o, py-events.o, py-exitedevent.o, py-signalstopevent.o, and py-stopevent.o. (SUBDIR_PYTHON_SRCS): Add py-breakpointstopevent.c, py-continueevent.c, py-event.c, py-eventregistry.c, py-events.c, py-exitedevent.c, py-signalstopevent.c, and py-stopevent.c. Add build rules for all the above. --- diff --git a/gdb/ChangeLog b/gdb/ChangeLog index c45b6d25477..b55e815a3b4 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,32 @@ +2011-02-04 Sami Wagiaalla + Oguz Kayral + + * python/py-inferior.c (python_on_normal_stop): New function. + (python_on_resume): New function. + (python_inferior_exit): New function. + (gdbpy_initialize_inferior): Add normal_stop, target_resumed, and + inferior_exit observers. + * python/py-evtregistry.c: New file. + * python/py-threadevent.c : New file. + * python/py-event.c: New file. + * python/py-evts.c: New file. + * python/py-continueevent.c: New file. + * python/py-bpevent.c: New file. + * python/py-signalevent.c: New file. + * python/py-exetiedevent.c: New file. + * python/py-breakpoint.c (gdbpy_breakpoint_from_bpstats): New function. + Move struct breakpoint_object from here... + * python/python-internal.h: ... to here. + * python/py-event.h: New file. + * python/py-events.h: New file. + * Makefile.in (SUBDIR_PYTHON_OBS): Add py-breakpointstopevent.o, + py-continueevent.o, py-event.o, py-eventregistry.o, py-events.o, + py-exitedevent.o, py-signalstopevent.o, and py-stopevent.o. + (SUBDIR_PYTHON_SRCS): Add py-breakpointstopevent.c, + py-continueevent.c, py-event.c, py-eventregistry.c, py-events.c, + py-exitedevent.c, py-signalstopevent.c, and py-stopevent.c. + Add build rules for all the above. + 2011-02-04 Tom Tromey * dwarf2read.c (dwarf2_section_empty_p): New function. diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 4882bd4674f..66521a23e67 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -272,8 +272,14 @@ SUBDIR_PYTHON_OBS = \ python.o \ py-auto-load.o \ py-block.o \ + py-bpevent.o \ py-breakpoint.o \ py-cmd.o \ + py-continueevent.o \ + py-event.o \ + py-evtregistry.o \ + py-evts.o \ + py-exitedevent.o \ py-frame.o \ py-function.o \ py-inferior.o \ @@ -283,17 +289,27 @@ SUBDIR_PYTHON_OBS = \ py-param.o \ py-prettyprint.o \ py-progspace.o \ + py-signalevent.o \ + py-stopevent.o \ py-symbol.o \ py-symtab.o \ + py-threadevent.o \ py-type.o \ py-utils.o \ py-value.o + SUBDIR_PYTHON_SRCS = \ python/python.c \ python/py-auto-load.c \ python/py-block.c \ + python/py-bpevent.c \ python/py-breakpoint.c \ python/py-cmd.c \ + python/py-continueevent.c \ + python/py-event.c \ + python/py-evtregistry.c \ + python/py-evts.c \ + python/py-exitedevent.c \ python/py-frame.c \ python/py-function.c \ python/py-inferior.c \ @@ -303,8 +319,11 @@ SUBDIR_PYTHON_SRCS = \ python/py-param.c \ python/py-prettyprint.c \ python/py-progspace.c \ + python/py-signalevent.c \ + python/py-stopevent.c \ python/py-symbol.c \ python/py-symtab.c \ + python/py-threadevent.c \ python/py-type.c \ python/py-utils.c \ python/py-value.c @@ -1995,6 +2014,10 @@ py-block.o: $(srcdir)/python/py-block.c $(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-block.c $(POSTCOMPILE) +py-bpevent.o: $(srcdir)/python/py-bpevent.c + $(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-bpevent.c + $(POSTCOMPILE) + py-breakpoint.o: $(srcdir)/python/py-breakpoint.c $(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-breakpoint.c $(POSTCOMPILE) @@ -2003,6 +2026,26 @@ py-cmd.o: $(srcdir)/python/py-cmd.c $(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-cmd.c $(POSTCOMPILE) +py-continueevent.o: $(srcdir)/python/py-continueevent.c + $(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-continueevent.c + $(POSTCOMPILE) + +py-event.o: $(srcdir)/python/py-event.c + $(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-event.c + $(POSTCOMPILE) + +py-evtregistry.o: $(srcdir)/python/py-evtregistry.c + $(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-evtregistry.c + $(POSTCOMPILE) + +py-evts.o: $(srcdir)/python/py-evts.c + $(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-evts.c + $(POSTCOMPILE) + +py-exitedevent.o: $(srcdir)/python/py-exitedevent.c + $(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-exitedevent.c + $(POSTCOMPILE) + py-frame.o: $(srcdir)/python/py-frame.c $(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-frame.c $(POSTCOMPILE) @@ -2039,6 +2082,14 @@ py-progspace.o: $(srcdir)/python/py-progspace.c $(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-progspace.c $(POSTCOMPILE) +py-signalevent.o: $(srcdir)/python/py-signalevent.c + $(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-signalevent.c + $(POSTCOMPILE) + +py-stopevent.o: $(srcdir)/python/py-stopevent.c + $(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-stopevent.c + $(POSTCOMPILE) + py-symbol.o: $(srcdir)/python/py-symbol.c $(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-symbol.c $(POSTCOMPILE) @@ -2047,6 +2098,10 @@ py-symtab.o: $(srcdir)/python/py-symtab.c $(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-symtab.c $(POSTCOMPILE) +py-threadevent.o: $(srcdir)/python/py-threadevent.c + $(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-threadevent.c + $(POSTCOMPILE) + py-type.o: $(srcdir)/python/py-type.c $(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-type.c $(POSTCOMPILE) diff --git a/gdb/NEWS b/gdb/NEWS index c53dbc705e6..234fb7be382 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -62,6 +62,14 @@ ** The gdb.InferiorThread class has a new "name" attribute. This holds the thread's name. + ** Python Support for Inferior events. + Python scripts can add observers to be notified of events + occurring the in process being debugged. + The following events are currently supported: + - gdb.events.cont Continue event. + - gdb.events.exited Inferior exited event. + - gdb.events.stop Signal received, and Breakpoint hit events. + * C++ Improvements: ** GDB now puts template parameters in scope when debugging in an diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 5ec7c1a6c97..6a3c7dee0e2 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -20704,6 +20704,7 @@ situation, a Python @code{KeyboardInterrupt} exception is thrown. * Selecting Pretty-Printers:: How GDB chooses a pretty-printer. * Writing a Pretty-Printer:: Writing a Pretty-Printer. * Inferiors In Python:: Python representation of inferiors (processes) +* Events In Python:: Listening for events from @value{GDBN}. * Threads In Python:: Accessing inferior threads from Python. * Commands In Python:: Implementing new commands in Python. * Parameters In Python:: Adding new @value{GDBN} parameters. @@ -21796,7 +21797,7 @@ my_library.so: @node Inferiors In Python @subsubsection Inferiors In Python -@cindex inferiors in python +@cindex inferiors in Python @findex gdb.Inferior Programs which are being run under @value{GDBN} are called inferiors @@ -21867,6 +21868,123 @@ the pattern could not be found. @end defmethod @end table +@node Events In Python +@subsubsection Events In Python +@cindex inferior events in Python + +@value{GDBN} provides a general event facility so that Python code can be +notified of various state changes, particularly changes that occur in +the inferior. + +An @dfn{event} is just an object that describes some state change. The +type of the object and its attributes will vary depending on the details +of the change. All the existing events are described below. + +In order to be notified of an event, you must register an event handler +with an @dfn{event registry}. An event registry is an object in the +@code{gdb.events} module which dispatches particular events. A registry +provides methods to register and unregister event handlers: + +@table @code +@defmethod EventRegistry connect object +Add the given callable @var{object} to the registry. This object will be +called when an event corresponding to this registry occurs. +@end defmethod + +@defmethod EventRegistry disconnect object +Remove the given @var{object} from the registry. Once removed, the object +will no longer receive notifications of events. +@end defmethod +@end table + +Here is an example: + +@smallexample +def exit_handler (event): + print "event type: exit" + print "exit code: %d" % (event.exit_code) + +gdb.events.exited.connect (exit_handler) +@end smallexample + +In the above example we connect our handler @code{exit_handler} to the +registry @code{events.exited}. Once connected, @code{exit_handler} gets +called when the inferior exits. The argument @dfn{event} in this example is +of type @code{gdb.ExitedEvent}. As you can see in the example the +@code{ExitedEvent} object has an attribute which indicates the exit code of +the inferior. + +The following is a listing of the event registries that are available and +details of the events they emit: + +@table @code + +@item events.cont +Emits @code{gdb.ThreadEvent}. + +Some events can be thread specific when @value{GDBN} is running in non-stop +mode. When represented in Python, these events all extend +@code{gdb.ThreadEvent}. Note, this event is not emitted directly; instead, +events which are emitted by this or other modules might extend this event. +Examples of these events are @code{gdb.BreakpointEvent} and +@code{gdb.ContinueEvent}. + +@table @code +@defivar ThreadEvent inferior_thread +In non-stop mode this attribute will be set to the specific thread which was +involved in the emitted event. Otherwise, it will be set to @code{None}. +@end defivar +@end table + +Emits @code{gdb.ContinueEvent} which extends @code{gdb.ThreadEvent}. + +This event indicates that the inferior has been continued after a stop. For +inherited attribute refer to @code{gdb.ThreadEvent} above. + +@item events.exited +Emits @code{events.ExitedEvent} which indicates that the inferior has exited. +@code{events.ExitedEvent} has one attribute: +@table @code +@defivar ExitedEvent exit_code +An integer representing the exit code which the inferior has returned. +@end defivar +@end table + +@item events.stop +Emits @code{gdb.StopEvent} which extends @code{gdb.ThreadEvent}. + +Indicates that the inferior has stopped. All events emitted by this registry +extend StopEvent. As a child of @code{gdb.ThreadEvent}, @code{gdb.StopEvent} +will indicate the stopped thread when @value{GDBN} is running in non-stop +mode. Refer to @code{gdb.ThreadEvent} above for more details. + +Emits @code{gdb.SignalEvent} which extends @code{gdb.StopEvent}. + +This event indicates that the inferior or one of its threads has received as +signal. @code{gdb.SignalEvent} has the following attributes: + +@table @code +@defivar SignalEvent stop_signal +A string representing the signal received by the inferior. A list of possible +signal values can be obtained by running the command @code{info signals} in +the @value{GDBN} command prompt. +@end defivar +@end table + +Also emits @code{gdb.BreakpointEvent} which extends @code{gdb.StopEvent}. + +@code{gdb.BreakpointEvent} event indicates that a breakpoint has been hit, and +has the following attributes: + +@table @code +@defivar BreakpointEvent breakpoint +A reference to the breakpoint that was hit of type @code{gdb.Breakpoint}. +@xref{Breakpoints In Python}, for details of the @code{gdb.Breakpoint} object. +@end defivar +@end table + +@end table + @node Threads In Python @subsubsection Threads In Python @cindex threads in python diff --git a/gdb/python/py-breakpoint.c b/gdb/python/py-breakpoint.c index e58533ab208..bfad002d1ae 100644 --- a/gdb/python/py-breakpoint.c +++ b/gdb/python/py-breakpoint.c @@ -29,9 +29,6 @@ #include "cli/cli-script.h" #include "ada-lang.h" -/* From breakpoint.c. */ -typedef struct breakpoint_object breakpoint_object; - static PyTypeObject breakpoint_object_type; /* Number of live breakpoints. */ diff --git a/gdb/python/py-inferior.c b/gdb/python/py-inferior.c index ba81177b867..12a82d21bf0 100644 --- a/gdb/python/py-inferior.c +++ b/gdb/python/py-inferior.c @@ -26,6 +26,9 @@ #include "python-internal.h" #include "arch-utils.h" #include "language.h" +#include "gdb_signals.h" +#include "py-event.h" +#include "py-stopevent.h" struct threadlist_entry { thread_object *thread_obj; @@ -73,6 +76,59 @@ static PyTypeObject membuf_object_type; } \ } while (0) +static void +python_on_normal_stop (struct bpstats *bs, int print_frame) +{ + struct cleanup *cleanup; + enum target_signal stop_signal; + + if (!find_thread_ptid (inferior_ptid)) + return; + + stop_signal = inferior_thread ()->suspend.stop_signal; + + cleanup = ensure_python_env (get_current_arch (), current_language); + + if (emit_stop_event (bs, stop_signal) < 0) + gdbpy_print_stack (); + + do_cleanups (cleanup); +} + +static void +python_on_resume (ptid_t ptid) +{ + struct cleanup *cleanup; + + cleanup = ensure_python_env (get_current_arch (), current_language); + + if (emit_continue_event (ptid) < 0) + gdbpy_print_stack (); + + do_cleanups (cleanup); +} + +static void +python_inferior_exit (struct inferior *inf) +{ + struct cleanup *cleanup; + LONGEST exit_code = -1; + ptid_t ptidp; + struct target_waitstatus status; + + cleanup = ensure_python_env (get_current_arch (), current_language); + + get_last_target_status (&ptidp, &status); + + exit_code = status.value.integer; + + if (exit_code >= 0 + && emit_exited_event (exit_code) < 0) + gdbpy_print_stack (); + + do_cleanups (cleanup); +} + /* Return a borrowed reference to the Python object of type Inferior representing INFERIOR. If the object has already been created, return it, otherwise, create it. Return NULL on failure. */ @@ -108,8 +164,8 @@ inferior_to_inferior_object (struct inferior *inferior) /* Finds the Python Inferior object for the given PID. Returns a borrowed reference, or NULL if PID does not match any inferior - obect. - */ + object. */ + PyObject * find_inferior_object (int pid) { @@ -590,6 +646,9 @@ gdbpy_initialize_inferior (void) observer_attach_new_thread (add_thread_object); observer_attach_thread_exit (delete_thread_object); + observer_attach_normal_stop (python_on_normal_stop); + observer_attach_target_resumed (python_on_resume); + observer_attach_inferior_exit (python_inferior_exit); if (PyType_Ready (&membuf_object_type) < 0) return; diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h index cf4f936d5a9..134268b2a2a 100644 --- a/gdb/python/python-internal.h +++ b/gdb/python/python-internal.h @@ -97,6 +97,7 @@ typedef unsigned long gdb_py_ulongest; /* Also needed to parse enum var_types. */ #include "command.h" +#include "breakpoint.h" #include "exceptions.h" @@ -104,11 +105,18 @@ struct block; struct value; struct language_defn; struct program_space; +struct bpstats; extern PyObject *gdb_module; extern PyTypeObject value_object_type; extern PyTypeObject block_object_type; extern PyTypeObject symbol_object_type; +extern PyTypeObject event_object_type; +extern PyTypeObject events_object_type; +extern PyTypeObject stop_event_object_type; + +/* Defined in py-breakpoint.c */ +typedef struct breakpoint_object breakpoint_object; typedef struct { @@ -161,6 +169,7 @@ PyObject *objfpy_get_printers (PyObject *, void *); thread_object *create_thread_object (struct thread_info *tp); thread_object *find_thread_object (ptid_t ptid); PyObject *find_inferior_object (int pid); +PyObject *inferior_to_inferior_object (struct inferior *inferior); struct block *block_object_to_block (PyObject *obj); struct symbol *symbol_object_to_symbol (PyObject *obj); @@ -187,6 +196,15 @@ void gdbpy_initialize_lazy_string (void); void gdbpy_initialize_parameters (void); void gdbpy_initialize_thread (void); void gdbpy_initialize_inferior (void); +void gdbpy_initialize_eventregistry (void); +void gdbpy_initialize_event (void); +void gdbpy_initialize_py_events (void); +void gdbpy_initialize_stop_event (void); +void gdbpy_initialize_signal_event (void); +void gdbpy_initialize_breakpoint_event (void); +void gdbpy_initialize_continue_event (void); +void gdbpy_initialize_exited_event (void); +void gdbpy_initialize_thread_event (void); struct cleanup *make_cleanup_py_decref (PyObject *py); diff --git a/gdb/python/python.c b/gdb/python/python.c index b2ee8f9bb21..b79504ab6e4 100644 --- a/gdb/python/python.c +++ b/gdb/python/python.c @@ -997,6 +997,16 @@ Enables or disables printing of Python stack traces."), gdbpy_initialize_inferior (); gdbpy_initialize_events (); + gdbpy_initialize_eventregistry (); + gdbpy_initialize_py_events (); + gdbpy_initialize_event (); + gdbpy_initialize_stop_event (); + gdbpy_initialize_signal_event (); + gdbpy_initialize_breakpoint_event (); + gdbpy_initialize_continue_event (); + gdbpy_initialize_exited_event (); + gdbpy_initialize_thread_event (); + PyRun_SimpleString ("import gdb"); PyRun_SimpleString ("gdb.pretty_printers = []"); diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index e4db48bc473..1fc2c7c56e0 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2011-02-04 Sami Wagiaalla + + * gdb.python/py-evthreads.c: New file. + * gdb.python/py-evthreads.exp: New file. + * gdb.python/py-events.py: New file. + * gdb.python/py-events.exp: New file. + * gdb.python/py-events.c: New file. + 2011-02-04 David Daney * gdb.base/catch-syscall.exp: Enable for mips*-linux*.