Add Python support for GDB events.
authorSami Wagiaalla <swagiaal@redhat.com>
Fri, 4 Feb 2011 21:54:16 +0000 (21:54 +0000)
committerSami Wagiaalla <swagiaal@redhat.com>
Fri, 4 Feb 2011 21:54:16 +0000 (21:54 +0000)
2011-02-04  Sami Wagiaalla  <swagiaal@redhat.com>

* 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  <swagiaal@redhat.com>
                Oguz Kayral <oguzkayral@gmail.com>

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

gdb/ChangeLog
gdb/Makefile.in
gdb/NEWS
gdb/doc/gdb.texinfo
gdb/python/py-breakpoint.c
gdb/python/py-inferior.c
gdb/python/python-internal.h
gdb/python/python.c
gdb/testsuite/ChangeLog

index c45b6d25477845551cd67ed59feebb9c3bac4cf6..b55e815a3b421704b6b3e56e256a0e38a53acbdf 100644 (file)
@@ -1,3 +1,32 @@
+2011-02-04  Sami Wagiaalla  <swagiaal@redhat.com>
+                Oguz Kayral <oguzkayral@gmail.com>
+
+       * 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  <tromey@redhat.com>
 
        * dwarf2read.c (dwarf2_section_empty_p): New function.
index 4882bd4674faadb86de315ead1b7f278b8ee1443..66521a23e679b4b09262bdd52ccccbafa7b57fcc 100644 (file)
@@ -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)
index c53dbc705e61e7316d1ea009cbb656f07e7092d3..234fb7be382305f7a456f521da6d4f07d9ddd44c 100644 (file)
--- a/gdb/NEWS
+++ b/gdb/NEWS
   ** 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
index 5ec7c1a6c9733bc2200fd66fe4f3f53b07a0fae6..6a3c7dee0e2af78a2e37f0b2a9fc5309220a0bb7 100644 (file)
@@ -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
index e58533ab2089fb2cec950c06f15c3293b2b9f3fd..bfad002d1ae34098a66b119f5a67b9753897f1cf 100644 (file)
@@ -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.  */
index ba81177b867194966b60e31b293fc1c60f85e496..12a82d21bf0482fed459b5924cbed3cd228b914a 100644 (file)
@@ -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;
index cf4f936d5a95ee56faf16c36d4a65a02abbd674f..134268b2a2aa2f889adee79ac1d2e9b721d0f87e 100644 (file)
@@ -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);
 
index b2ee8f9bb218f5ee42aac950a1a4287f25d53b34..b79504ab6e4500bc7c09cc6bb5efe513ebbc1d27 100644 (file)
@@ -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 = []");
 
index e4db48bc4738238a496a41f75d7e1e70fa6c7352..1fc2c7c56e046791097c833d6625641a91f56780 100644 (file)
@@ -1,3 +1,11 @@
+2011-02-04  Sami Wagiaalla  <swagiaal@redhat.com>
+
+       * 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 <ddaney@caviumnetworks.com>
 
        * gdb.base/catch-syscall.exp: Enable for mips*-linux*.