This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH v2] Events when inferior is modified


[ Apologies for taking a long time to resubmit this.  The patch is
  essentially the same as before, but with fixes to address review
  comments, and made consistent with upstream changes in the
  meantime. ]

Hi,

This patch adds new observers, and corresponding Python events, for
various actions on an inferior: calling a function (by hand),
modifying registers or modifying memory.

A use case for these events is that by flagging these occurrences, it
can be noticed that the execution of the program is potentially
'dirty'.  (Hence why the notification doesn't carry information about
what was modified; for my purposes it's enough to know that /a/
change has happened.)

Nick


2013-11-18  Nick Bull  <nicholaspbull@gmail.com>

	* doc/observer.texi (inferior_call_pre, inferior_call_post
	register_change, memory_change): New observers.
	* infcall.c (call_function_by_hand): Notify observer before and
	after inferior call.
	* Makefile.in: add py-infcallevent.c / py-infcallevent.o.
	* python/py-event.h (inferior_altered_kind): New enum.
	(emit_inferior_altered_event): New prototype.
	* python/py-events.h (events_object): New inferior_altered
	registry.
	* python/py-evts.c (gdbpy_initialize_py_events): Add the
	inferior_altered registry.
	* python/py-infcallevent.c: New.
	* python/py-inferior.c (python_on_inferior_call_pre)
	(python_on_inferior_call_post, python_on_register_change)
	(python_on_memory_change): New functions.
	(gdbpy_initialize_inferior): Attach python handler to new
	observers.
	* python/python.c (_initialize_python): Initialize new events.
	* python/python-internal.h:
	(gdbpy_initialize_inferior_call_pre_event)
	(gdbpy_initialize_inferior_call_post_event)
	(gdbpy_initialize_register_change_event)
	(gdbpy_initialize_memory_change_event): New prototypes.
	* target.c (memory_xfer_partial_1, target_xfer_partial):
	Notify memory change observer.
	(target_store_registers): Notify register change observer.


diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 975edbf..7775bde 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -297,6 +297,7 @@ SUBDIR_PYTHON_OBS = \
 	py-function.o \
 	py-gdb-readline.o \
 	py-inferior.o \
+	py-infcallevent.o \
 	py-infthread.o \
 	py-lazy-string.o \
 	py-linetable.o \
@@ -333,6 +334,7 @@ SUBDIR_PYTHON_SRCS = \
 	python/py-function.c \
 	python/py-gdb-readline.c \
 	python/py-inferior.c \
+	python/py-infcallevent.c \
 	python/py-infthread.c \
 	python/py-lazy-string.c \
 	python/py-linetable.c \
@@ -2221,6 +2223,10 @@ py-inferior.o: $(srcdir)/python/py-inferior.c
 	$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-inferior.c
 	$(POSTCOMPILE)

+py-infcallevent.o: $(srcdir)/python/py-infcallevent.c
+	$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-infcallevent.c
+	$(POSTCOMPILE)
+
 py-infthread.o: $(srcdir)/python/py-infthread.c
 	$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-infthread.c
 	$(POSTCOMPILE)
diff --git a/gdb/doc/observer.texi b/gdb/doc/observer.texi
index f753965..ab15725 100644
--- a/gdb/doc/observer.texi
+++ b/gdb/doc/observer.texi
@@ -253,6 +253,22 @@ The trace state variable @var{tsv} is deleted. If @var{tsv} is
 The trace state value @var{tsv} is modified.
 @end deftypefun

+@deftypefun void inferior_call_pre (void)
+An inferior function is about to be called.
+@end deftypefun
+
+@deftypefun void inferior_call_post (void)
+An inferior function has just been called.
+@end deftypefun
+
+@deftypefun void register_change (void)
+One or more registers in the inferior have been modified.
+@end deftypefun
+
+@deftypefun void memory_change (void)
+Memory in the inferior has been modified.
+@end deftypefun
+
 @deftypefun void test_notification (int @var{somearg})
 This observer is used for internal testing.  Do not use.
 See testsuite/gdb.gdb/observer.exp.
diff --git a/gdb/infcall.c b/gdb/infcall.c
index 19af044..07dbbe3 100644
--- a/gdb/infcall.c
+++ b/gdb/infcall.c
@@ -36,6 +36,7 @@
 #include "ada-lang.h"
 #include "gdbthread.h"
 #include "exceptions.h"
+#include "observer.h"

 /* If we can't find a function's name from its address,
    we print this instead.  */
@@ -611,6 +612,8 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
       target_values_type = values_type;
     }

+  observer_notify_inferior_call_pre ();
+
   /* Determine the location of the breakpoint (and possibly other
      stuff) that the called function will return to.  The SPARC, for a
      function returning a structure or union, needs to make space for
@@ -844,6 +847,8 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
     e = run_inferior_call (tp, real_pc);
   }

+  observer_notify_inferior_call_post ();
+
   /* Rethrow an error if we got one trying to run the inferior.  */

   if (e.reason < 0)
diff --git a/gdb/python/py-event.h b/gdb/python/py-event.h
index f0ff629..2f2da90 100644
--- a/gdb/python/py-event.h
+++ b/gdb/python/py-event.h
@@ -105,6 +105,15 @@ typedef struct
 extern int emit_continue_event (ptid_t ptid);
extern int emit_exited_event (const LONGEST *exit_code, struct inferior *inf);

+typedef enum
+{
+  inferior_altered_pre_call,
+  inferior_altered_post_call,
+  inferior_altered_register_change,
+  inferior_altered_memory_change
+} inferior_altered_kind;
+
+extern int emit_inferior_altered_event (inferior_altered_kind kind);
 extern int evpy_emit_event (PyObject *event,
                             eventregistry_object *registry)
   CPYCHECKER_STEALS_REFERENCE_TO_ARG (1);
diff --git a/gdb/python/py-events.h b/gdb/python/py-events.h
index 4ec3832..2f035c7 100644
--- a/gdb/python/py-events.h
+++ b/gdb/python/py-events.h
@@ -46,6 +46,7 @@ typedef struct
   eventregistry_object *cont;
   eventregistry_object *exited;
   eventregistry_object *new_objfile;
+  eventregistry_object *inferior_altered;

   PyObject *module;

diff --git a/gdb/python/py-evts.c b/gdb/python/py-evts.c
index 971c520..f20974e 100644
--- a/gdb/python/py-evts.c
+++ b/gdb/python/py-evts.c
@@ -73,6 +73,10 @@ gdbpy_initialize_py_events (void)
   if (add_new_registry (&gdb_py_events.exited, "exited") < 0)
     return -1;

+  if (add_new_registry (&gdb_py_events.inferior_altered,
+			"inferior_altered") < 0)
+    return -1;
+
   if (add_new_registry (&gdb_py_events.new_objfile, "new_objfile") < 0)
     return -1;

diff --git a/gdb/python/py-infcallevent.c b/gdb/python/py-infcallevent.c
new file mode 100644
index 0000000..68e70f1
--- /dev/null
+++ b/gdb/python/py-infcallevent.c
@@ -0,0 +1,98 @@
+/* Python interface to inferior function events.
+
+   Copyright (C) 2009-2013 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   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 "defs.h"
+#include "py-event.h"
+
+static PyTypeObject inferior_call_pre_event_object_type;
+static PyTypeObject inferior_call_post_event_object_type;
+static PyTypeObject register_change_event_object_type;
+static PyTypeObject memory_change_event_object_type;
+
+static PyObject *
+create_inferior_call_event_object (int flag)
+{
+  PyObject * event;
+
+  switch (flag)
+    {
+    case inferior_altered_pre_call:
+      event = create_event_object (&inferior_call_pre_event_object_type);
+      break;
+    case inferior_altered_post_call:
+      event = create_event_object (&inferior_call_post_event_object_type);
+      break;
+    case inferior_altered_register_change:
+      event = create_event_object (&register_change_event_object_type);
+      break;
+    case inferior_altered_memory_change:
+      event = create_event_object (&memory_change_event_object_type);
+      break;
+    default:
+      return NULL;
+    }
+
+  return event;
+}
+
+/* Callback function which notifies observers when a continue event occurs.
+   This function will create a new Python continue event object.
+   Return -1 if emit fails.  */
+
+int
+emit_inferior_altered_event (inferior_altered_kind flag)
+{
+  PyObject *event;
+
+  if (evregpy_no_listeners_p (gdb_py_events.inferior_altered))
+    return 0;
+
+  event = create_inferior_call_event_object (flag);
+  if (event != NULL)
+    return evpy_emit_event (event, gdb_py_events.inferior_altered);
+  return -1;
+}
+
+GDBPY_NEW_EVENT_TYPE (inferior_call_pre,
+                      "gdb.InferiorCallPreEvent",
+                      "InferiorCallPreEvent",
+                      "GDB inferior function pre-call event object",
+                      event_object_type,
+                      static);
+
+GDBPY_NEW_EVENT_TYPE (inferior_call_post,
+                      "gdb.InferiorCallPostEvent",
+                      "InferiorCallPostEvent",
+                      "GDB inferior function post-call event object",
+                      event_object_type,
+                      static);
+
+GDBPY_NEW_EVENT_TYPE (register_change,
+                      "gdb.RegisterChangeEvent",
+                      "RegisterChangeEvent",
+                      "GDB register change event object",
+                      event_object_type,
+                      static);
+
+GDBPY_NEW_EVENT_TYPE (memory_change,
+                      "gdb.MemoryChangeEvent",
+                      "MemoryChangeEvent",
+                      "GDB memory change event object",
+                      event_object_type,
+                      static);
diff --git a/gdb/python/py-inferior.c b/gdb/python/py-inferior.c
index ed49290..4386f83 100644
--- a/gdb/python/py-inferior.c
+++ b/gdb/python/py-inferior.c
@@ -118,6 +118,58 @@ python_on_resume (ptid_t ptid)
 }

 static void
+python_on_inferior_call_pre (void)
+{
+  struct cleanup *cleanup;
+
+  cleanup = ensure_python_env (target_gdbarch (), current_language);
+
+  if (emit_inferior_altered_event (inferior_altered_pre_call) < 0)
+    gdbpy_print_stack ();
+
+  do_cleanups (cleanup);
+}
+
+static void
+python_on_inferior_call_post (void)
+{
+  struct cleanup *cleanup;
+
+  cleanup = ensure_python_env (target_gdbarch (), current_language);
+
+  if (emit_inferior_altered_event (inferior_altered_post_call) < 0)
+    gdbpy_print_stack ();
+
+  do_cleanups (cleanup);
+}
+
+static void
+python_on_register_change (void)
+{
+  struct cleanup *cleanup;
+
+  cleanup = ensure_python_env (target_gdbarch (), current_language);
+
+  if (emit_inferior_altered_event (inferior_altered_register_change) < 0)
+    gdbpy_print_stack ();
+
+  do_cleanups (cleanup);
+}
+
+static void
+python_on_memory_change (void)
+{
+  struct cleanup *cleanup;
+
+  cleanup = ensure_python_env (target_gdbarch (), current_language);
+
+  if (emit_inferior_altered_event (inferior_altered_memory_change) < 0)
+    gdbpy_print_stack ();
+
+  do_cleanups (cleanup);
+}
+
+static void
 python_inferior_exit (struct inferior *inf)
 {
   struct cleanup *cleanup;
@@ -794,6 +846,10 @@ gdbpy_initialize_inferior (void)
   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_call_pre (python_on_inferior_call_pre);
+  observer_attach_inferior_call_post (python_on_inferior_call_post);
+  observer_attach_register_change (python_on_register_change);
+  observer_attach_memory_change (python_on_memory_change);
   observer_attach_inferior_exit (python_inferior_exit);
   observer_attach_new_objfile (python_new_objfile);

diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h
index 7d8c4ad..6c800a3 100644
--- a/gdb/python/python-internal.h
+++ b/gdb/python/python-internal.h
@@ -393,6 +393,14 @@ int gdbpy_initialize_breakpoint_event (void)
   CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
 int gdbpy_initialize_continue_event (void)
   CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
+int gdbpy_initialize_inferior_call_pre_event (void)
+  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
+int gdbpy_initialize_inferior_call_post_event (void)
+  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
+int gdbpy_initialize_register_change_event (void)
+  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
+int gdbpy_initialize_memory_change_event (void)
+  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
 int gdbpy_initialize_exited_event (void)
   CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
 int gdbpy_initialize_thread_event (void)
diff --git a/gdb/python/python.c b/gdb/python/python.c
index 7cdf8a7..4942414 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -1684,6 +1684,10 @@ message == an error message without a stack will be printed."),
       || gdbpy_initialize_signal_event () < 0
       || gdbpy_initialize_breakpoint_event () < 0
       || gdbpy_initialize_continue_event () < 0
+      || gdbpy_initialize_inferior_call_pre_event () < 0
+      || gdbpy_initialize_inferior_call_post_event () < 0
+      || gdbpy_initialize_register_change_event () < 0
+      || gdbpy_initialize_memory_change_event () < 0
       || gdbpy_initialize_exited_event () < 0
       || gdbpy_initialize_thread_event () < 0
       || gdbpy_initialize_new_objfile_event ()  < 0
diff --git a/gdb/target.c b/gdb/target.c
index 86a5572..3768a61 100644
--- a/gdb/target.c
+++ b/gdb/target.c
@@ -43,6 +43,7 @@
 #include "tracepoint.h"
 #include "gdb/fileio.h"
 #include "agent.h"
+#include "observer.h"

 static void target_info (char *, int);

@@ -1616,6 +1617,8 @@ memory_xfer_partial_1 (struct target_ops *ops, enum target_object object,

   do
     {
+      if (writebuf != NULL)
+	observer_notify_memory_change ();
       res = ops->to_xfer_partial (ops, TARGET_OBJECT_MEMORY, NULL,
 				  readbuf, writebuf, memaddr, reg_len);
       if (res > 0)
@@ -1745,6 +1748,8 @@ target_xfer_partial (struct target_ops *ops,
       if (raw_object == TARGET_OBJECT_RAW_MEMORY)
 	raw_object = TARGET_OBJECT_MEMORY;

+      if (writebuf != NULL)
+	observer_notify_memory_change ();
       retval = ops->to_xfer_partial (ops, raw_object, annex, readbuf,
 				     writebuf, offset, len);
     }
@@ -3992,6 +3997,7 @@ target_store_registers (struct regcache *regcache, int regno)
     {
       if (t->to_store_registers != NULL)
 	{
+	  observer_notify_register_change ();
 	  t->to_store_registers (t, regcache, regno);
 	  if (targetdebug)
 	    {


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]