This is the mail archive of the gdb-patches@sources.redhat.com 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]

[RFC] (was Re: How does GDB/MI give the current frame)


 > > 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);
+ }


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