This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
=frame-selected MI notification
- From: Dmitry Dzhus <dima at sphinx dot net dot ru>
- To: gdb-patches at sources dot redhat dot com
- Date: Thu, 27 Aug 2009 17:54:38 +0400
- Subject: =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
ã