[doc,RFA] New clear_objfiles python event

Message ID yjt21tqb7g1u.fsf@ruffy.mtv.corp.google.com
State New, archived
Headers

Commit Message

Doug Evans Oct. 13, 2014, 10:36 p.m. UTC
  Hi.

If one is watching new_objfile events in python, it helps to know
when the list of objfiles is cleared.  This patch adds a new
clear_objfiles event to support this.

This patch is all just cut-n-paste-n-tweak derived from
the new_objfiles event.

Regression tested on amd64-linux.

2014-10-13  Doug Evans  <dje@google.com>

	* NEWS: Mention new event gdb.clear_objfiles.
	* python/py-event.h (emit_clear_objfiles_event): Clear
	* python/py-events.h (events_object): New member clear_objfiles.
	* python/py-evts.c (gdbpy_initialize_py_events): Add clear_objfiles
	event.
	* python/py-inferior.c (python_new_objfile): If objfile is NULL,
	emit clear_objfiles event.
	* python/py-newobjfileevent.c (create_clear_objfiles_event_object): New
	function.
	(emit_clear_objfiles_event): New function.
	(clear_objfiles): New event.
	* python/python-internal.h (gdbpy_initialize_clear_objfiles_event):
	Declare.
	* python/python.c (_initialize_python): Call
	gdbpy_initialize_clear_objfiles_event.

	doc/
	* python.texi (Events In Python): Document clear_objfiles event.

	testsuite/
	* gdb.python/py-events.exp: Update expected output for clear_objfiles
	event.
	* gdb.python/py-events.py: Add clear_objfiles event.
  

Comments

Eli Zaretskii Oct. 14, 2014, 6:16 a.m. UTC | #1
> From: Doug Evans <dje@google.com>
> Date: Mon, 13 Oct 2014 15:36:45 -0700
> 
> If one is watching new_objfile events in python, it helps to know
> when the list of objfiles is cleared.  This patch adds a new
> clear_objfiles event to support this.
> 
> This patch is all just cut-n-paste-n-tweak derived from
> the new_objfiles event.
> 
> Regression tested on amd64-linux.
> 
> 2014-10-13  Doug Evans  <dje@google.com>
> 
> 	* NEWS: Mention new event gdb.clear_objfiles.
> 	* python/py-event.h (emit_clear_objfiles_event): Clear
> 	* python/py-events.h (events_object): New member clear_objfiles.
> 	* python/py-evts.c (gdbpy_initialize_py_events): Add clear_objfiles
> 	event.
> 	* python/py-inferior.c (python_new_objfile): If objfile is NULL,
> 	emit clear_objfiles event.
> 	* python/py-newobjfileevent.c (create_clear_objfiles_event_object): New
> 	function.
> 	(emit_clear_objfiles_event): New function.
> 	(clear_objfiles): New event.
> 	* python/python-internal.h (gdbpy_initialize_clear_objfiles_event):
> 	Declare.
> 	* python/python.c (_initialize_python): Call
> 	gdbpy_initialize_clear_objfiles_event.
> 
> 	doc/
> 	* python.texi (Events In Python): Document clear_objfiles event.
> 
> 	testsuite/
> 	* gdb.python/py-events.exp: Update expected output for clear_objfiles
> 	event.
> 	* gdb.python/py-events.py: Add clear_objfiles event.

OK for the documentation parts.

Thanks.
  
Doug Evans Oct. 17, 2014, 6:14 p.m. UTC | #2
Eli Zaretskii writes:
 > > From: Doug Evans <dje@google.com>
 > > Date: Mon, 13 Oct 2014 15:36:45 -0700
 > > 
 > > If one is watching new_objfile events in python, it helps to know
 > > when the list of objfiles is cleared.  This patch adds a new
 > > clear_objfiles event to support this.
 > > 
 > > This patch is all just cut-n-paste-n-tweak derived from
 > > the new_objfiles event.
 > > 
 > > Regression tested on amd64-linux.
 > > 
 > > 2014-10-13  Doug Evans  <dje@google.com>
 > > 
 > > 	* NEWS: Mention new event gdb.clear_objfiles.
 > > 	* python/py-event.h (emit_clear_objfiles_event): Clear
 > > 	* python/py-events.h (events_object): New member clear_objfiles.
 > > 	* python/py-evts.c (gdbpy_initialize_py_events): Add clear_objfiles
 > > 	event.
 > > 	* python/py-inferior.c (python_new_objfile): If objfile is NULL,
 > > 	emit clear_objfiles event.
 > > 	* python/py-newobjfileevent.c (create_clear_objfiles_event_object): New
 > > 	function.
 > > 	(emit_clear_objfiles_event): New function.
 > > 	(clear_objfiles): New event.
 > > 	* python/python-internal.h (gdbpy_initialize_clear_objfiles_event):
 > > 	Declare.
 > > 	* python/python.c (_initialize_python): Call
 > > 	gdbpy_initialize_clear_objfiles_event.
 > > 
 > > 	doc/
 > > 	* python.texi (Events In Python): Document clear_objfiles event.
 > > 
 > > 	testsuite/
 > > 	* gdb.python/py-events.exp: Update expected output for clear_objfiles
 > > 	event.
 > > 	* gdb.python/py-events.py: Add clear_objfiles event.
 > 
 > OK for the documentation parts.
 > 
 > Thanks.

Committed, thanks.
  

Patch

diff --git a/gdb/NEWS b/gdb/NEWS
index 5de0a33..f327603 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -9,6 +9,8 @@ 
 
   ** You can now access frame registers from Python scripts.
   ** New attribute 'producer' for gdb.Symtab objects.
+  ** A new event "gdb.clear_objfiles" has been added, triggered when
+     selecting a new file to debug.
 
 * New Python-based convenience functions:
 
diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi
index 81ec11b..4049734 100644
--- a/gdb/doc/python.texi
+++ b/gdb/doc/python.texi
@@ -2728,6 +2728,16 @@  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 events.clear_objfiles
+Emits @code{gdb.ClearObjFilesEvent} which indicates that the list of object
+files for a program space has been reset.
+@code{gdb.ClearObjFilesEvent} has one attribute:
+
+@defvar ClearObjFilesEvent.progspace
+A reference to the program space (@code{gdb.Progspace}) whose objfile list has
+been cleared.  @xref{Progspaces In Python}.
+@end defvar
+
 @end table
 
 @node Threads In Python
diff --git a/gdb/python/py-event.h b/gdb/python/py-event.h
index 5a0f29b..c0bd9a6 100644
--- a/gdb/python/py-event.h
+++ b/gdb/python/py-event.h
@@ -112,6 +112,7 @@  extern int evpy_emit_event (PyObject *event,
 extern PyObject *create_event_object (PyTypeObject *py_type);
 extern PyObject *create_thread_event_object (PyTypeObject *py_type);
 extern int emit_new_objfile_event (struct objfile *objfile);
+extern int emit_clear_objfiles_event (void);
 
 extern void evpy_dealloc (PyObject *self);
 extern int evpy_add_attribute (PyObject *event,
diff --git a/gdb/python/py-events.h b/gdb/python/py-events.h
index 3431612..0b5656b 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 *clear_objfiles;
 
   PyObject *module;
 
diff --git a/gdb/python/py-evts.c b/gdb/python/py-evts.c
index a7daf8a..d08b14b 100644
--- a/gdb/python/py-evts.c
+++ b/gdb/python/py-evts.c
@@ -76,6 +76,9 @@  gdbpy_initialize_py_events (void)
   if (add_new_registry (&gdb_py_events.new_objfile, "new_objfile") < 0)
     return -1;
 
+  if (add_new_registry (&gdb_py_events.clear_objfiles, "clear_objfiles") < 0)
+    return -1;
+
   if (gdb_pymodule_addobject (gdb_module,
 			      "events",
 			      (PyObject *) gdb_py_events.module) < 0)
diff --git a/gdb/python/py-inferior.c b/gdb/python/py-inferior.c
index 181059a..1b38d55 100644
--- a/gdb/python/py-inferior.c
+++ b/gdb/python/py-inferior.c
@@ -137,23 +137,32 @@  python_inferior_exit (struct inferior *inf)
 }
 
 /* Callback used to notify Python listeners about new objfiles loaded in the
-   inferior.  */
+   inferior.  OBJFILE may be NULL which means that the objfile list has been
+   cleared (emptied).  */
 
 static void
 python_new_objfile (struct objfile *objfile)
 {
   struct cleanup *cleanup;
 
-  if (objfile == NULL)
-    return;
-
   if (!gdb_python_initialized)
     return;
 
-  cleanup = ensure_python_env (get_objfile_arch (objfile), current_language);
+  cleanup = ensure_python_env (objfile != NULL
+			       ? get_objfile_arch (objfile)
+			       : target_gdbarch (),
+			       current_language);
 
-  if (emit_new_objfile_event (objfile) < 0)
-    gdbpy_print_stack ();
+  if (objfile == NULL)
+    {
+      if (emit_clear_objfiles_event () < 0)
+	gdbpy_print_stack ();
+    }
+  else
+    {
+      if (emit_new_objfile_event (objfile) < 0)
+	gdbpy_print_stack ();
+    }
 
   do_cleanups (cleanup);
 }
diff --git a/gdb/python/py-newobjfileevent.c b/gdb/python/py-newobjfileevent.c
index e4e1351..104ed07 100644
--- a/gdb/python/py-newobjfileevent.c
+++ b/gdb/python/py-newobjfileevent.c
@@ -22,6 +22,8 @@ 
 
 static PyTypeObject new_objfile_event_object_type
     CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("event_object");
+static PyTypeObject clear_objfiles_event_object_type
+    CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("event_object");
 
 static PyObject *
 create_new_objfile_event_object (struct objfile *objfile)
@@ -72,3 +74,56 @@  GDBPY_NEW_EVENT_TYPE (new_objfile,
                       "GDB new object file event object",
                       event_object_type,
                       static);
+
+/* Subroutine of emit_clear_objfiles_event to simplify it.  */
+
+static PyObject *
+create_clear_objfiles_event_object (void)
+{
+  PyObject *objfile_event;
+  PyObject *py_progspace;
+
+  objfile_event = create_event_object (&clear_objfiles_event_object_type);
+  if (!objfile_event)
+    goto fail;
+
+  /* Note that pspace_to_pspace_object returns a borrowed reference,
+     so we don't need a decref here.  */
+  py_progspace = pspace_to_pspace_object (current_program_space);
+  if (!py_progspace || evpy_add_attribute (objfile_event,
+					   "progspace",
+					   py_progspace) < 0)
+    goto fail;
+
+  return objfile_event;
+
+ fail:
+  Py_XDECREF (objfile_event);
+  return NULL;
+}
+
+/* Callback function which notifies observers when the "clear objfiles"
+   event occurs.
+   This function will create a new Python clear_objfiles event object.
+   Return -1 if emit fails.  */
+
+int
+emit_clear_objfiles_event (void)
+{
+  PyObject *event;
+
+  if (evregpy_no_listeners_p (gdb_py_events.clear_objfiles))
+    return 0;
+
+  event = create_clear_objfiles_event_object ();
+  if (event)
+    return evpy_emit_event (event, gdb_py_events.clear_objfiles);
+  return -1;
+}
+
+GDBPY_NEW_EVENT_TYPE (clear_objfiles,
+		      "gdb.ClearObjFilesEvent",
+		      "ClearObjFilesEvent",
+		      "GDB clear object files event object",
+		      event_object_type,
+		      static);
diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h
index c262a46..54eebeb 100644
--- a/gdb/python/python-internal.h
+++ b/gdb/python/python-internal.h
@@ -470,6 +470,8 @@  int gdbpy_initialize_thread_event (void)
   CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
 int gdbpy_initialize_new_objfile_event (void)
   CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
+int gdbpy_initialize_clear_objfiles_event (void)
+  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
 int gdbpy_initialize_arch (void)
   CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
 int gdbpy_initialize_xmethods (void)
diff --git a/gdb/python/python.c b/gdb/python/python.c
index af90bef..ca531e2 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -1756,6 +1756,7 @@  message == an error message without a stack will be printed."),
       || gdbpy_initialize_exited_event () < 0
       || gdbpy_initialize_thread_event () < 0
       || gdbpy_initialize_new_objfile_event ()  < 0
+      || gdbpy_initialize_clear_objfiles_event ()  < 0
       || gdbpy_initialize_arch () < 0
       || gdbpy_initialize_xmethods () < 0)
     goto fail;
diff --git a/gdb/testsuite/gdb.python/py-events.exp b/gdb/testsuite/gdb.python/py-events.exp
index 92de550..c4331fe 100644
--- a/gdb/testsuite/gdb.python/py-events.exp
+++ b/gdb/testsuite/gdb.python/py-events.exp
@@ -81,6 +81,7 @@  delete_breakpoints
 
 #test exited event.
 gdb_test "continue" ".*event type: continue.*
+.*clear_objfiles\[\r\n\]*progspace: .*py-events.*
 .*event type: exit.*
 .*exit code: 12.*
 .*exit inf: 1.*
diff --git a/gdb/testsuite/gdb.python/py-events.py b/gdb/testsuite/gdb.python/py-events.py
index 1f0012a..9af768b 100644
--- a/gdb/testsuite/gdb.python/py-events.py
+++ b/gdb/testsuite/gdb.python/py-events.py
@@ -57,6 +57,11 @@  def new_objfile_handler (event):
     print ("event type: new_objfile")
     print ("new objfile name: %s" % (event.new_objfile.filename))
 
+def clear_objfiles_handler (event):
+    assert (isinstance (event, gdb.ClearObjFilesEvent))
+    print ("event type: clear_objfiles")
+    print ("progspace: %s" % (event.progspace.filename))
+
 class test_events (gdb.Command):
     """Test events."""
 
@@ -80,6 +85,7 @@  class test_newobj_events (gdb.Command):
 
     def invoke (self, arg, from_tty):
         gdb.events.new_objfile.connect (new_objfile_handler)
+        gdb.events.clear_objfiles.connect (clear_objfiles_handler)
         print ("Object file events registered.")
 
 test_newobj_events ()