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]

=frame-selected MI notification


This patch adds =frame-selected notification to GDB/MI. This
notification is important, because it provides front-ends a way to find
out that user has asked for frame change via frontend console using CLI
command `up`, `down` or `frame N`.

I had to move `frame_info` structure description to `frame.h` so its
fields may be accessed from mi-main.c. I'm not sure if this is the
correct approach.

Nick Roberts once posted a patch which implements both =thread-selected
and =frame-selected via observers:
http://sourceware.org/ml/gdb-patches/2008-04/msg00377.html. Current
implementation of =thread-selected in mi-main.c uses a different
approach, comparing current thread ID before and after executing a
command in `mi_execute_command` function. My patch does the same for
frame level. I don't know how is it technically better. I think it would
be nice if somebody reviewed Nick's patch once again or at least
accepted the one proposed by me.

diff --git a/gdb/frame.c b/gdb/frame.c
index 67e0607..8ad349b 100644
--- a/gdb/frame.c
+++ b/gdb/frame.c
@@ -57,71 +57,6 @@ static struct frame_info *get_prev_frame_raw (struct frame_info *this_frame);
    frames (e.g. "set heuristic-fence-post" in mips-tdep.c, or anything
    which reads new symbols)), we should call reinit_frame_cache.  */
 
-struct frame_info
-{
-  /* Level of this frame.  The inner-most (youngest) frame is at level
-     0.  As you move towards the outer-most (oldest) frame, the level
-     increases.  This is a cached value.  It could just as easily be
-     computed by counting back from the selected frame to the inner
-     most frame.  */
-  /* NOTE: cagney/2002-04-05: Perhaps a level of ``-1'' should be
-     reserved to indicate a bogus frame - one that has been created
-     just to keep GDB happy (GDB always needs a frame).  For the
-     moment leave this as speculation.  */
-  int level;
-
-  /* The frame's low-level unwinder and corresponding cache.  The
-     low-level unwinder is responsible for unwinding register values
-     for the previous frame.  The low-level unwind methods are
-     selected based on the presence, or otherwise, of register unwind
-     information such as CFI.  */
-  void *prologue_cache;
-  const struct frame_unwind *unwind;
-
-  /* Cached copy of the previous frame's architecture.  */
-  struct
-  {
-    int p;
-    struct gdbarch *arch;
-  } prev_arch;
-
-  /* Cached copy of the previous frame's resume address.  */
-  struct {
-    int p;
-    CORE_ADDR value;
-  } prev_pc;
-  
-  /* Cached copy of the previous frame's function address.  */
-  struct
-  {
-    CORE_ADDR addr;
-    int p;
-  } prev_func;
-  
-  /* This frame's ID.  */
-  struct
-  {
-    int p;
-    struct frame_id value;
-  } this_id;
-  
-  /* The frame's high-level base methods, and corresponding cache.
-     The high level base methods are selected based on the frame's
-     debug info.  */
-  const struct frame_base *base;
-  void *base_cache;
-
-  /* Pointers to the next (down, inner, younger) and previous (up,
-     outer, older) frame_info's in the frame cache.  */
-  struct frame_info *next; /* down, inner, younger */
-  int prev_p;
-  struct frame_info *prev; /* up, outer, older */
-
-  /* The reason why we could not set PREV, or UNWIND_NO_REASON if we
-     could.  Only valid when PREV_P is set.  */
-  enum unwind_stop_reason stop_reason;
-};
-
 /* Flag to control debugging.  */
 
 int frame_debug;
diff --git a/gdb/frame.h b/gdb/frame.h
index febef5c..900d263 100644
--- a/gdb/frame.h
+++ b/gdb/frame.h
@@ -80,8 +80,6 @@ struct ui_file;
 
 /* The frame object.  */
 
-struct frame_info;
-
 /* The frame object's ID.  This provides a per-frame unique identifier
    that can be used to relocate a `struct frame_info' after a target
    resume or a frame cache destruct.  It of course assumes that the
@@ -440,6 +438,72 @@ enum unwind_stop_reason
     UNWIND_NO_SAVED_PC,
   };
 
+
+struct frame_info
+{
+  /* Level of this frame.  The inner-most (youngest) frame is at level
+     0.  As you move towards the outer-most (oldest) frame, the level
+     increases.  This is a cached value.  It could just as easily be
+     computed by counting back from the selected frame to the inner
+     most frame.  */
+  /* NOTE: cagney/2002-04-05: Perhaps a level of ``-1'' should be
+     reserved to indicate a bogus frame - one that has been created
+     just to keep GDB happy (GDB always needs a frame).  For the
+     moment leave this as speculation.  */
+  int level;
+
+  /* The frame's low-level unwinder and corresponding cache.  The
+     low-level unwinder is responsible for unwinding register values
+     for the previous frame.  The low-level unwind methods are
+     selected based on the presence, or otherwise, of register unwind
+     information such as CFI.  */
+  void *prologue_cache;
+  const struct frame_unwind *unwind;
+
+  /* Cached copy of the previous frame's architecture.  */
+  struct
+  {
+    int p;
+    struct gdbarch *arch;
+  } prev_arch;
+
+  /* Cached copy of the previous frame's resume address.  */
+  struct {
+    int p;
+    CORE_ADDR value;
+  } prev_pc;
+  
+  /* Cached copy of the previous frame's function address.  */
+  struct
+  {
+    CORE_ADDR addr;
+    int p;
+  } prev_func;
+  
+  /* This frame's ID.  */
+  struct
+  {
+    int p;
+    struct frame_id value;
+  } this_id;
+  
+  /* The frame's high-level base methods, and corresponding cache.
+     The high level base methods are selected based on the frame's
+     debug info.  */
+  const struct frame_base *base;
+  void *base_cache;
+
+  /* Pointers to the next (down, inner, younger) and previous (up,
+     outer, older) frame_info's in the frame cache.  */
+  struct frame_info *next; /* down, inner, younger */
+  int prev_p;
+  struct frame_info *prev; /* up, outer, older */
+
+  /* The reason why we could not set PREV, or UNWIND_NO_REASON if we
+     could.  Only valid when PREV_P is set.  */
+  enum unwind_stop_reason stop_reason;
+};
+
 /* Return the reason why we can't unwind past this frame.  */
 
 enum unwind_stop_reason get_frame_unwind_stop_reason (struct frame_info *);
diff --git a/gdb/mi/mi-main.c b/gdb/mi/mi-main.c
index 6aa1d08..7239700 100644
--- a/gdb/mi/mi-main.c
+++ b/gdb/mi/mi-main.c
@@ -1277,6 +1277,11 @@ mi_execute_command (char *cmd, int from_tty)
     {
       struct gdb_exception result;
       ptid_t previous_ptid = inferior_ptid;
+      struct frame_info *previous_frame;
+      if (has_stack_frames())
+          previous_frame = get_selected_frame (NULL);
+      else
+          previous_frame = NULL;
 
       if (do_timings)
 	{
@@ -1338,6 +1343,29 @@ mi_execute_command (char *cmd, int from_tty)
 	    }
 	}
 
+      /* =frame-selected notification */
+      if (ui_out_is_mi_like_p (interp_ui_out (top_level_interpreter ()))
+	  && previous_frame
+	  && strcmp (command->command, "stack-select-frame") != 0)
+	{
+	  struct mi_interp *mi = top_level_interpreter_data ();
+          struct frame_info *fi = get_selected_frame (NULL);
+	  int report_change = 0;
+
+	  if (fi->level != previous_frame->level)
+              report_change = ((command->frame == -1)
+                               || (fi->level != command->frame));
+
+	  if (report_change)
+	    {     
+	      target_terminal_ours ();
+	      fprintf_unfiltered (mi->event_channel, 
+				  "frame-selected,id=\"%d\"",
+				  get_selected_frame(NULL)->level);
+	      gdb_flush (mi->event_channel);
+	    }
+	}
+
       mi_parse_free (command);
     }
 
-- 
Happy Hacking.

http://sphinx.net.ru
ã

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