From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 18412 invoked by alias); 18 Nov 2013 12:39:43 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Received: (qmail 18388 invoked by uid 89); 18 Nov 2013 12:39:43 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-0.5 required=5.0 tests=AWL,BAYES_50,FREEMAIL_FROM,RDNS_NONE,SPF_PASS,URIBL_BLOCKED autolearn=no version=3.3.2 X-HELO: mail-wi0-f176.google.com Received: from Unknown (HELO mail-wi0-f176.google.com) (209.85.212.176) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-SHA encrypted) ESMTPS; Mon, 18 Nov 2013 12:39:41 +0000 Received: by mail-wi0-f176.google.com with SMTP id f4so3740069wiw.3 for ; Mon, 18 Nov 2013 04:39:31 -0800 (PST) X-Received: by 10.194.63.228 with SMTP id j4mr2142716wjs.34.1384778371778; Mon, 18 Nov 2013 04:39:31 -0800 (PST) Received: from [192.168.123.180] (ssh.greglaw.net. [82.71.15.62]) by mx.google.com with ESMTPSA id dn2sm23788167wid.1.2013.11.18.04.39.29 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 18 Nov 2013 04:39:30 -0800 (PST) Message-ID: <528A0A83.1080203@gmail.com> Date: Mon, 18 Nov 2013 12:51:00 -0000 From: Nick Bull User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Thunderbird/24.1.0 MIME-Version: 1.0 To: gdb-patches@sourceware.org Subject: [PATCH v2] Events when inferior is modified References: <51CDBD48.6010903@gmail.com> <87k3k7kbdy.fsf@fleche.redhat.com> In-Reply-To: Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit X-SW-Source: 2013-11/txt/msg00462.txt.bz2 [ 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 * 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 . */ + +#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) {