This is the mail archive of the
gdb-patches@sources.redhat.com
mailing list for the GDB project.
[RFC] (was Re: How does GDB/MI give the current frame)
- From: Nick Roberts <nickrob at gnu dot org>
- To: Andrew Cagney <cagney at gnu dot org>
- Cc: Daniel Jacobowitz <drow at false dot org>,gdb-patches at sources dot redhat dot com
- Date: Mon, 28 Jun 2004 20:25:35 +0100
- Subject: [RFC] (was Re: How does GDB/MI give the current frame)
- References: <16603.23348.569889.284030@nick.uklinux.net><20040624231659.GA16577@nevyn.them.org><16605.15641.474398.42157@nick.uklinux.net><40DE2D1B.4070003@gnu.org>
> > AC> When the user does "up", "down", the debugger should generate a selected
> > AC> CLI frame changed event (it currently doesn't). If the GUI so chooses,
> > AC> it can track the users "selected" frame, by responding to these events.
> >
> > I don't know what a selected CLI frame changed event is but up, down, and
> > frame generate MI output, so I imagine its just a case of hooking
> > -stack-info-frame and -stack-select-frame to that output. I will try to do
> > this if you think it's appropriate.
>
> For the CLI, something like this:
>
> -> -interpreter cli "up"
> <- ~"info on new frame..."
> <- *select-frame,<frame-info>...
> <- done
Are you referring to "-interpreter-exec console up" ? Accessing CLI in this
way currently seems to work how Emacs would need it to for the GUD buffer.
> with similar for -stack-select-frame:
>
> -> -stack-select-frame 1
> <- *select-frame,<frame-info>,....
> <- done
...
I'm a bit lost here, partly because of the lack of documentation (the `simple
examples' in the manual don't seem to work) and partly my ignorance.
To make the discussion less abstract, below is a patch giving the functionality
that I talked about. Its a crude hack with code lifted from stack.c but
perhaps it could be used a vehicle to point me in the right direction. In it,
-stack-select-frame prints frame details but that might not be necessary because
any front-end could run "-stack-info-frame" behind the user's back.
Nick
sample output:
-stack-info-frame
^done,frame={level="0",func="myprint",args=[],file="myprint.c",line="4"}
(gdb)
-stack-select-frame 1
^done,frame={level="1",addr="0x080485d1",func="main",args=[],file="myprog.c",line="61"}
(gdb)
-stack-info-frame
^done,frame={level="1",addr="0x080485d1",func="main",args=[],file="myprog.c",line="61"}
*** mi-cmd-stack.c.~1.23.~ 2004-05-25 20:53:14.000000000 +0100
--- mi-cmd-stack.c 2004-06-28 19:58:09.000000000 +0100
***************
*** 30,38 ****
--- 30,43 ----
#include "stack.h"
#include "dictionary.h"
#include "gdb_string.h"
+ #include "demangle.h"
static void list_args_or_locals (int locals, int values, struct frame_info *fi);
+ static void mi_print_frame();
+
+ extern int addressprint; /* Print addresses, or stay symbolic only? */
+
/* Print a list of the stack frames. Args can be none, in which case
we want to print the whole backtrace, or a pair of numbers
specifying the frame numbers at which to start and stop the
***************
*** 127,132 ****
--- 132,150 ----
return MI_CMD_DONE;
}
+ enum mi_cmd_result
+ mi_cmd_stack_info_frame (char *command, char **argv, int argc)
+ {
+ if (!target_has_stack)
+ error ("mi_cmd_stack_info_frame: No stack.");
+
+ if (argc > 0)
+ error ("mi_cmd_stack_info_frame: No arguments required");
+
+ mi_print_frame();
+ return MI_CMD_DONE;
+ }
+
/* Print a list of the locals for the current frame. With argument of
0, print only the names, with argument of 1 print also the
values. */
***************
*** 340,344 ****
--- 358,467 ----
select_frame_command (0, 1 /* not used */ );
else
select_frame_command (argv[0], 1 /* not used */ );
+
+ mi_print_frame();
return MI_CMD_DONE;
}
+
+ static void
+ mi_print_frame()
+ {
+ struct frame_info *fi;
+ struct cleanup *uiout_cleanup;
+ struct cleanup *old_chain;
+ struct cleanup *args_list_chain;
+ static struct ui_stream *stb = NULL;
+ struct symtab_and_line sal;
+ struct symbol *func;
+ char *funname = 0;
+ enum language funlang = language_unknown;
+
+ fi = get_selected_frame ();
+ find_frame_sal (fi, &sal);
+
+ uiout_cleanup = make_cleanup_ui_out_tuple_begin_end (uiout, "frame");
+ ui_out_field_fmt_int (uiout, 2, ui_left, "level",
+ frame_relative_level (fi));
+ if (addressprint)
+ if (get_frame_pc (fi) != sal.pc || !sal.symtab)
+ ui_out_field_core_addr (uiout, "addr", get_frame_pc (fi));
+
+ stb = ui_out_stream_new (uiout);
+ old_chain = make_cleanup_ui_out_stream_delete (stb);
+
+ func = find_pc_function (get_frame_address_in_block (fi));
+ if (func)
+ {
+ /* In certain pathological cases, the symtabs give the wrong
+ function (when we are in the first function in a file which
+ is compiled without debugging symbols, the previous function
+ is compiled with debugging symbols, and the "foo.o" symbol
+ that is supposed to tell us where the file with debugging symbols
+ ends has been truncated by ar because it is longer than 15
+ characters). This also occurs if the user uses asm() to create
+ a function but not stabs for it (in a file compiled -g).
+
+ So look in the minimal symbol tables as well, and if it comes
+ up with a larger address for the function use that instead.
+ I don't think this can ever cause any problems; there shouldn't
+ be any minimal symbols in the middle of a function; if this is
+ ever changed many parts of GDB will need to be changed (and we'll
+ create a find_pc_minimal_function or some such). */
+
+ struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (get_frame_address_in_block (fi));
+ if (msymbol != NULL
+ && (SYMBOL_VALUE_ADDRESS (msymbol)
+ > BLOCK_START (SYMBOL_BLOCK_VALUE (func))))
+ {
+ /* We also don't know anything about the function besides
+ its address and name. */
+ func = 0;
+ funname = DEPRECATED_SYMBOL_NAME (msymbol);
+ funlang = SYMBOL_LANGUAGE (msymbol);
+ }
+ else
+ {
+ /* I'd like to use SYMBOL_PRINT_NAME() here, to display the
+ demangled name that we already have stored in the symbol
+ table, but we stored a version with DMGL_PARAMS turned
+ on, and here we don't want to display parameters. So call
+ the demangler again, with DMGL_ANSI only. (Yes, I know
+ that printf_symbol_filtered() will again try to demangle
+ the name on the fly, but the issue is that if
+ cplus_demangle() fails here, it'll fail there too. So we
+ want to catch the failure ("demangled==NULL" case below)
+ here, while we still have our hands on the function
+ symbol.) */
+ char *demangled;
+ funname = DEPRECATED_SYMBOL_NAME (func);
+ funlang = SYMBOL_LANGUAGE (func);
+ if (funlang == language_cplus)
+ {
+ demangled = cplus_demangle (funname, DMGL_ANSI);
+ if (demangled == NULL)
+ /* If the demangler fails, try the demangled name from
+ the symbol table. This'll have parameters, but
+ that's preferable to diplaying a mangled name. */
+ funname = SYMBOL_PRINT_NAME (func);
+ }
+ }
+ }
+ else
+ {
+ struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (get_frame_address_in_block (fi));
+ if (msymbol != NULL)
+ {
+ funname = DEPRECATED_SYMBOL_NAME (msymbol);
+ funlang = SYMBOL_LANGUAGE (msymbol);
+ }
+ }
+ fprintf_symbol_filtered (stb->stream, funname ? funname : "??", funlang,
+ DMGL_ANSI);
+ ui_out_field_stream (uiout, "func", stb);
+ do_cleanups (old_chain);
+ args_list_chain = make_cleanup_ui_out_list_begin_end (uiout, "args");
+ do_cleanups (args_list_chain);
+ ui_out_field_string (uiout, "file", sal.symtab->filename);
+ ui_out_field_int (uiout, "line", sal.line);
+ do_cleanups (uiout_cleanup);
+ }