public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
From: Nick Bull <nicholaspbull@gmail.com>
To: gdb-patches@sourceware.org, Phil Muldoon <pmuldoon@redhat.com>
Subject: Re: [PATCH v2] Events when inferior is modified
Date: Thu, 12 Dec 2013 17:12:00 -0000	[thread overview]
Message-ID: <52A9EE5A.7070803@gmail.com> (raw)
In-Reply-To: <52A6F543.9040201@redhat.com>

On 10/12/13 11:04, Phil Muldoon wrote:
>
> Might be a tab or space issue, or even a mailer issue, but indention
> looks incorrect  here.

Editor issue, in fact. Thanks for spotting.

> I apologize for not catching this initially, but is it possible to
> have what registers changed? I suppose you could scan beforehand, and
> scan after.  But it would be a better API if registers' names were
> included as an attribute. If this requires major surgery though, we
> can look again at the original API for inclusion. Also it is not clear
> from the tests. but would this callback trigger on frame change (either
> through execution or the user selecting a different frame)?  Registers
> are swapped in and out as each frame changes.

Added.

I've chosen to to pass through the register identity numerically rather
than by name, on the basis of not doing a conversion until it's known
to be needed. As far as I can see there's no precedent for a Python API
that passes register names or numbers. Arguably the gdb.Architecture
object is the right place to supply a list of register names, should
Python code want to convert register numbers into human-readable form.

The observer is intended to trigger only when the user chooses to
change the state of the debugged program, outside of normal execution.
So it won't trigger on frame change. This is equivalent to the
behaviour of the existing memory_changed observer, which doesn't
trigger due to setting breakpoints, for example.

> This is a fairly new rule, but for all new submissions any pointer
> expression has to be explicitly written.  So, rewrite to:
 >
 > if (event == NULL)

Done.

> I believe there is a problem here in the failed branch.  You have
> already decremented the reference count of addr_obj once, and in the
> fail goto you do it again.  In these cases of conditional cleanups I
> find the make_cleanup/do_cleanup kind of logic easier to write. If you
> believe you will be saved by the XDECREF call not working on NULL,
> remember that Py_DECREF just decrements the reference count of the
> object, and nothing else.  So if the Python GC collected that object,
> any further writes to that address would result in a possible sigsegv.

Rewritten using cleanups.

> We need some tests to see if register changes initiated by frame
> selection or program execution trigger the event mechanism.

Done (as per above, they don't).

> We need some tests here to test whether breakpoint hit, creation and
> deletion trigger these (I don't think they should, but let's
> create a barrier test to prove it).

Also done.

Nick

gdb/ChangeLog

2013-12-09  Nick Bull  <nicholaspbull@gmail.com>

	* Makefile.in: add py-infcallevent.c / py-infcallevent.o.
	* doc/observer.texi (inferior_call_pre, inferior_call_post)
	(memory_changed, register_changed): New observers.
	* infcall.c (call_function_by_hand): Notify observer before and
	after inferior call.
	* python/py-event.h (inferior_call_kind): New enum.
	(emit_inferior_call_event): New prototype.
	(emit_register_changed_event): New prototype.
	(emit_memory_changed_event): New prototype.
	* python/py-events.h (events_object): New registries
	inferior_call, memory_changed and register_changed.
	* python/py-evts.c (gdbpy_initialize_py_events): Add the
	inferior_call, memory_changed and register_changed registries.
	* 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-internal.h:
	(gdbpy_initialize_inferior_call_pre_event)
	(gdbpy_initialize_inferior_call_post_event)
	(gdbpy_initialize_register_changed_event)
	(gdbpy_initialize_memory_changed_event): New prototypes.
	* python/python.c (_initialize_python): Initialize new events.
	* valops.c (value_assign): Notify register_changed observer.

gdb/testsuite/ChangeLog

2013-12-09  Nick Bull  <nicholaspbull@gmail.com>

	* gdb.python/py-events.py (inferior_fn_handler): New.
	(register_changed_handler, memory_changed_handler): New.
	(test_events.invoke): Register new handlers.
	* gdb.python/py-events.exp: Add tests for inferior call,
	memory_changed and register_changed events.

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index be30dfd..40e9875 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -296,6 +296,7 @@ SUBDIR_PYTHON_OBS = \
  	py-framefilter.o \
  	py-function.o \
  	py-gdb-readline.o \
+	py-infcallevent.o \
  	py-inferior.o \
  	py-infthread.o \
  	py-lazy-string.o \
@@ -332,6 +333,7 @@ SUBDIR_PYTHON_SRCS = \
  	python/py-framefilter.c \
  	python/py-function.c \
  	python/py-gdb-readline.c \
+	python/py-infcallevent.c \
  	python/py-inferior.c \
  	python/py-infthread.c \
  	python/py-lazy-string.c \
@@ -2217,6 +2219,10 @@ py-gdb-readline.o: $(srcdir)/python/py-gdb-readline.c
  	$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-gdb-readline.c
  	$(POSTCOMPILE)

+py-infcallevent.o: $(srcdir)/python/py-infcallevent.c
+	$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-infcallevent.c
+	$(POSTCOMPILE)
+
  py-inferior.o: $(srcdir)/python/py-inferior.c
  	$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-inferior.c
  	$(POSTCOMPILE)
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 87d5145..1210ea7 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -25808,6 +25808,37 @@ A reference to the object file 
(@code{gdb.Objfile}) which has been loaded.
  @xref{Objfiles In Python}, for details of the @code{gdb.Objfile} object.
  @end defvar

+@item inferior_call_pre
+Emits @code{gdb.InferiorCallPreEvent} which indicates that a function in
+the inferior is about to be called.
+
+@item inferior_call_post
+Emits @code{gdb.InferiorCallPostEvent} which indicates that a function in
+the inferior has returned.
+
+@item memory_changed
+Emits @code{gdb.MemoryChangedEvent} which indicates that the memory of the
+inferior has been modified by the GDB user, for instance via a command like
+@code{set *addr = value}.  The event has the following attributes:
+
+@defvar MemoryChangedEvent.address
+The start address of the changed region.
+@end defvar
+@defvar MemoryChangedEvent.length
+Length in bytes of the changed region.
+@end defvar
+
+@item register_changed
+Emits @code{gdb.RegisterChangedEvent} which indicates that a register 
in the
+inferior has been modified by the GDB user.
+
+@defvar RegisterChangedEvent.frame
+A gdb.Frame object representing the frame in which the register was 
modified.
+@end defvar
+@defvar RegisterChangedEvent.regnum
+Denotes which register was modified.
+@end defvar
+
  @end table

  @node Threads In Python
diff --git a/gdb/doc/observer.texi b/gdb/doc/observer.texi
index f753965..277b112 100644
--- a/gdb/doc/observer.texi
+++ b/gdb/doc/observer.texi
@@ -253,6 +253,18 @@ 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_changed (struct frame_info *@var{frame}, 
short @var{regnum})
+A register 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 212997f..7c1a5ae 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..7579e04 100644
--- a/gdb/python/py-event.h
+++ b/gdb/python/py-event.h
@@ -105,6 +105,16 @@ 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_call_pre,
+  inferior_call_post,
+} inferior_call_kind;
+
+extern int emit_inferior_call_event (inferior_call_kind kind);
+extern int emit_register_changed_event (struct frame_info *frame,
+					short regnum);
+extern int emit_memory_changed_event (CORE_ADDR addr, ssize_t len);
  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..d158211 100644
--- a/gdb/python/py-events.h
+++ b/gdb/python/py-events.h
@@ -46,6 +46,9 @@ typedef struct
    eventregistry_object *cont;
    eventregistry_object *exited;
    eventregistry_object *new_objfile;
+  eventregistry_object *inferior_call;
+  eventregistry_object *memory_changed;
+  eventregistry_object *register_changed;

    PyObject *module;

diff --git a/gdb/python/py-evts.c b/gdb/python/py-evts.c
index 1ff3022..76f923b 100644
--- a/gdb/python/py-evts.c
+++ b/gdb/python/py-evts.c
@@ -73,6 +73,18 @@ 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_call,
+			"inferior_call") < 0)
+    return -1;
+
+  if (add_new_registry (&gdb_py_events.memory_changed,
+			"memory_changed") < 0)
+    return -1;
+
+  if (add_new_registry (&gdb_py_events.register_changed,
+			"register_changed") < 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..a651bcb
--- /dev/null
+++ b/gdb/python/py-infcallevent.c
@@ -0,0 +1,203 @@
+/* Python interface to inferior function events.
+
+   Copyright (C) 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_changed_event_object_type;
+static PyTypeObject memory_changed_event_object_type;
+
+static PyObject *
+create_inferior_call_event_object (int flag)
+{
+  PyObject * event;
+
+  switch (flag)
+    {
+    case inferior_call_pre:
+      event = create_event_object (&inferior_call_pre_event_object_type);
+      break;
+    case inferior_call_post:
+      event = create_event_object (&inferior_call_post_event_object_type);
+      break;
+    default:
+      return NULL;
+    }
+
+  return event;
+}
+
+static PyObject *
+create_register_changed_event_object (struct frame_info *frame,
+				      short regnum)
+{
+  PyObject * event;
+  PyObject *frame_obj = NULL;
+  PyObject *regnum_obj = NULL;
+  int failed;
+  struct cleanup *cleanups;
+
+  event = create_event_object (&register_changed_event_object_type);
+  if (event == NULL)
+    return NULL;
+
+  cleanups = make_cleanup_py_decref (event);
+
+  frame_obj = frame_info_to_frame_object (frame);
+  if (frame_obj == NULL)
+    goto fail;
+  make_cleanup_py_decref (frame_obj);
+
+  failed = evpy_add_attribute (event, "frame", frame_obj) < 0;
+  if (failed)
+    goto fail;
+
+  regnum_obj = PyLong_FromLongLong (regnum);
+  if (regnum_obj == NULL)
+    goto fail;
+  make_cleanup_py_decref (regnum_obj);
+
+  failed = evpy_add_attribute (event, "regnum", regnum_obj) < 0;
+  if (failed)
+    goto fail;
+
+  return event;
+
+ fail:
+  do_cleanups (cleanups);
+  return NULL;
+}
+
+static PyObject *
+create_memory_changed_event_object (CORE_ADDR addr, ssize_t len)
+{
+  PyObject * event;
+  PyObject *addr_obj = NULL;
+  PyObject *len_obj = NULL;
+  int failed;
+  struct cleanup *cleanups;
+
+  event = create_event_object (&memory_changed_event_object_type);
+
+  if (event == NULL)
+    return NULL;
+  cleanups = make_cleanup_py_decref (event);
+
+  addr_obj = PyLong_FromLongLong (addr);
+  if (addr_obj == NULL)
+    goto fail;
+  make_cleanup_py_decref (addr_obj);
+
+  failed = evpy_add_attribute (event, "address", addr_obj) < 0;
+  if (failed)
+    goto fail;
+
+  len_obj = PyLong_FromLong (len);
+  if (len_obj == NULL)
+    goto fail;
+  make_cleanup_py_decref (len_obj);
+
+  failed = evpy_add_attribute (event, "length", len_obj) < 0;
+  if (failed)
+    goto fail;
+
+  return event;
+
+ fail:
+  do_cleanups (cleanups);
+  return NULL;
+}
+
+/* Callback function which notifies observers when an event occurs which
+   calls a function in the inferior.
+   This function will create a new Python inferior-call event object.
+   Return -1 if emit fails.  */
+
+int
+emit_inferior_call_event (inferior_call_kind flag)
+{
+  PyObject *event;
+
+  if (evregpy_no_listeners_p (gdb_py_events.inferior_call))
+    return 0;
+
+  event = create_inferior_call_event_object (flag);
+  if (event != NULL)
+    return evpy_emit_event (event, gdb_py_events.inferior_call);
+  return -1;
+}
+
+int
+emit_memory_changed_event (CORE_ADDR addr, ssize_t len)
+{
+  PyObject *event;
+
+  if (evregpy_no_listeners_p (gdb_py_events.memory_changed))
+    return 0;
+
+  event = create_memory_changed_event_object (addr, len);
+  if (event != NULL)
+    return evpy_emit_event (event, gdb_py_events.memory_changed);
+  return -1;
+}
+
+int
+emit_register_changed_event (struct frame_info* frame, short regnum)
+{
+  PyObject *event;
+
+  if (evregpy_no_listeners_p (gdb_py_events.register_changed))
+    return 0;
+
+  event = create_register_changed_event_object (frame, regnum);
+  if (event != NULL)
+    return evpy_emit_event (event, gdb_py_events.register_changed);
+  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_changed,
+		      "gdb.RegisterChangedEvent",
+		      "RegisterChangedEvent",
+		      "GDB register change event object",
+		      event_object_type,
+		      static);
+
+GDBPY_NEW_EVENT_TYPE (memory_changed,
+		      "gdb.MemoryChangedEvent",
+		      "MemoryChangedEvent",
+		      "GDB memory change event object",
+		      event_object_type,
+		      static);
diff --git a/gdb/python/py-inferior.c b/gdb/python/py-inferior.c
index 1a1b774..89bff40 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_call_event (inferior_call_pre) < 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_call_event (inferior_call_post) < 0)
+    gdbpy_print_stack ();
+
+  do_cleanups (cleanup);
+}
+
+static void
+python_on_memory_change (struct inferior *inferior, CORE_ADDR addr, 
ssize_t len, const bfd_byte *data)
+{
+  struct cleanup *cleanup;
+
+  cleanup = ensure_python_env (target_gdbarch (), current_language);
+
+  if (emit_memory_changed_event (addr, len) < 0)
+    gdbpy_print_stack ();
+
+  do_cleanups (cleanup);
+}
+
+static void
+python_on_register_change (struct frame_info *frame, short regnum)
+{
+  struct cleanup *cleanup;
+
+  cleanup = ensure_python_env (target_gdbarch (), current_language);
+
+  if (emit_register_changed_event (frame, regnum) < 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_memory_changed (python_on_memory_change);
+  observer_attach_register_changed (python_on_register_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 125670e..8eba303 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_changed_event (void)
+  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
+int gdbpy_initialize_memory_changed_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 1873936..85cbefa 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_changed_event () < 0
+      || gdbpy_initialize_memory_changed_event () < 0
        || gdbpy_initialize_exited_event () < 0
        || gdbpy_initialize_thread_event () < 0
        || gdbpy_initialize_new_objfile_event ()  < 0
diff --git a/gdb/testsuite/gdb.python/py-events.exp 
b/gdb/testsuite/gdb.python/py-events.exp
index 390a2ba..ef90a1d 100644
--- a/gdb/testsuite/gdb.python/py-events.exp
+++ b/gdb/testsuite/gdb.python/py-events.exp
@@ -79,6 +79,93 @@ all threads stopped"

  delete_breakpoints

+# Test inferior call events
+gdb_test "call do_nothing()" ".*event type: pre-call.*
+.*event type: continue.*
+.*event type: post-call.*"
+
+# Test register changed event
+gdb_test_no_output {set $old_sp = $sp}
+gdb_test {set $sp = 0} ".*event type: register-changed.*
+.*frame: .*
+.*num: .*"
+gdb_test {set $sp = 1} ".*event type: register-changed.*
+.*frame: .*
+.*num: .*"
+gdb_test {set $sp = $old_sp} ".*event type: register-changed.*
+.*frame: .*
+.*num: .*"
+
+# Test that no register_changed event is generated on "non-user"
+# modifications
+set test "up"
+gdb_test_multiple {up} $test {
+    -re "event type: register-changed" {
+	fail $test
+    }
+    -re "#1.*in first.*\r\n.*do_nothing.*\r\n$gdb_prompt $" {
+	pass $test
+    }
+}
+
+set test "down"
+gdb_test_multiple {down} $test {
+    -re "event type: register-changed" {
+	fail $test
+    }
+    -re "#0.*do_nothing.*at.*\r\n.*void do_nothing.*\r\n$gdb_prompt $" {
+	pass $test
+    }
+}
+
+set test "step"
+gdb_test_multiple {step} $test {
+    -re "event type: register-changed" {
+	fail $test
+    }
+    -re "first.*at.*\r\n.*28.*for.*\r\n$gdb_prompt $" {
+	pass $test
+    }
+}
+
+
+# Test memory changed event
+gdb_test_no_output {set $saved = *(int*) $sp}
+gdb_test {set *(int*) $sp = 0} ".*event type: memory-changed.*
+.*address: .*
+.*length: .*"
+gdb_test {set *(int*) $sp = $saved} ".*event type: memory-changed.*
+.*address: .*
+.*length: .*"
+
+# Test that no memory_changed event is generated on breakpoint
+# activity
+set test "break second"
+gdb_test_multiple "break second" $test {
+     -re "event type: memory-changed" {
+	fail $test
+    }
+    -re "Breakpoint 5 at .*\r\n$gdb_prompt $" {
+	pass $test
+    }
+
+}
+
+set test "continue to breakpoint 5"
+gdb_test_multiple "continue" $test {
+     -re "event type: memory-changed" {
+	fail $test
+    }
+    -re ".*event type: continue.*
+.*event type: stop.*
+.*stop reason: breakpoint.*
+.*all threads stopped.*$gdb_prompt $" {
+	pass $test
+    }
+}
+
+gdb_test_no_output "delete 5"
+
  #test exited event.
  gdb_test "continue" ".*event type: continue.*
  .*event type: exit.*
diff --git a/gdb/testsuite/gdb.python/py-events.py 
b/gdb/testsuite/gdb.python/py-events.py
index 7601ca1..1ca701a 100644
--- a/gdb/testsuite/gdb.python/py-events.py
+++ b/gdb/testsuite/gdb.python/py-events.py
@@ -57,6 +57,28 @@ def new_objfile_handler (event):
      print ("event type: new_objfile")
      print ("new objfile name: %s" % (event.new_objfile.filename))

+def inferior_fn_handler (event):
+    if (isinstance (event, gdb.InferiorCallPreEvent)):
+        print ("event type: pre-call")
+    elif (isinstance (event, gdb.InferiorCallPostEvent)):
+        print ("event type: post-call")
+    else:
+        assert False
+
+def register_changed_handler (event):
+    assert (isinstance (event, gdb.RegisterChangedEvent))
+    print ("event type: register-changed")
+    assert (isinstance (event.frame, gdb.Frame))
+    print ("frame: %s" % (event.frame))
+    print ("num: %s" % (event.regnum))
+
+def memory_changed_handler (event):
+    assert (isinstance (event, gdb.MemoryChangedEvent))
+    print ("event type: memory-changed")
+    print ("address: %s" % (event.address))
+    print ("length: %s" % (event.length))
+
+
  class test_events (gdb.Command):
      """Test events."""

@@ -68,6 +90,9 @@ class test_events (gdb.Command):
          gdb.events.stop.connect (breakpoint_stop_handler)
          gdb.events.exited.connect (exit_handler)
          gdb.events.cont.connect (continue_handler)
+        gdb.events.inferior_call.connect(inferior_fn_handler)
+        gdb.events.memory_changed.connect(memory_changed_handler)
+        gdb.events.register_changed.connect(register_changed_handler)
          print ("Event testers registered.")

  test_events ()
diff --git a/gdb/valops.c b/gdb/valops.c
index d43c758..84c6661 100644
--- a/gdb/valops.c
+++ b/gdb/valops.c
@@ -1210,6 +1210,7 @@ value_assign (struct value *toval, struct value 
*fromval)
  	      }
  	  }

+	observer_notify_register_changed (frame, value_reg);
  	if (deprecated_register_changed_hook)
  	  deprecated_register_changed_hook (-1);
  	break;


  reply	other threads:[~2013-12-12 17:12 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-06-28 17:07 Nick Bull
2013-07-30 21:04 ` Tom Tromey
2013-08-01 15:47   ` Pedro Alves
2013-08-07 14:41   ` Nick Bull
2013-11-18 12:51     ` [PATCH v2] " Nick Bull
2013-11-18 15:15       ` Eli Zaretskii
2013-11-25 11:50       ` Phil Muldoon
2013-12-01 15:23         ` Nick Bull
2013-12-09 17:48           ` Nick Bull
2013-12-10 11:04             ` Phil Muldoon
2013-12-12 17:12               ` Nick Bull [this message]
2013-12-21 21:26                 ` Nick Bull

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=52A9EE5A.7070803@gmail.com \
    --to=nicholaspbull@gmail.com \
    --cc=gdb-patches@sourceware.org \
    --cc=pmuldoon@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).