This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[PATCH v2] Events when inferior is modified
- From: Nick Bull <nicholaspbull at gmail dot com>
- To: gdb-patches at sourceware dot org
- Date: Mon, 18 Nov 2013 12:39:31 +0000
- Subject: [PATCH v2] Events when inferior is modified
- Authentication-results: sourceware.org; auth=none
- References: <51CDBD48 dot 6010903 at gmail dot com> <87k3k7kbdy dot fsf at fleche dot redhat dot com> <CABbKtXsh+BG6=s6ZmaoEFYeiFR-9SAWqMYk3DqP-Ej047zd7LQ at mail dot gmail dot com>
[ 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 (®ister_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)
{