public inbox for gdb@sourceware.org
 help / color / mirror / Atom feed
* Changing "info frame" output?
@ 2004-11-03 16:28 Andrew Cagney
  2004-11-04 21:59 ` Mark Kettenis
  0 siblings, 1 reply; 6+ messages in thread
From: Andrew Cagney @ 2004-11-03 16:28 UTC (permalink / raw)
  To: gdb

[-- Attachment #1: Type: text/plain, Size: 2322 bytes --]

Hello,

GDB's current info frame output looks like:

Stack level 1, frame at 0x7ffff290:
  pc = 0x1005e5f8 in fprintf_filtered 
(/home/scratch/GDB/src/gdb/utils.c:2231);
     saved pc 0x1005a6b8
  called by frame at 0x7ffff2b0, caller of frame at 0x7ffff210
  source language c.
  Arglist at 0x7ffff210, args: stream=0x10465888,
     format=0x1036fe4c "GNU gdb %s\n"
  Locals at 0x7ffff210, Previous frame's sp is 0x7ffff290
  Saved registers:
   pc at 0x7ffff294, lr at 0x7ffff294

I see several problems (some apparent, some not so):

- PC and SP as registers really no longer apply.
Phrases such as ``pc = ...'' and ``saved pc'', and ``Previous frame's 
SP'' should be worded in a more ISA netural way.

- Often there isn't an "Arglist at ..."
Modern architectures often don't push any arguments on the stack so the 
argument address isn't meaningful.

- More register info.
Modern ISAs also save registers in other registers, that should be 
displayed.  That its talking about registers saved by this frame should 
be clarified.

and with that in mind have come up with the following as a draft:

Stack level 1, frame at 0x7ffff240:
  Code at 0x1005e5f8 in fprintf_filtered (stream=0x10467888,
     format=0x10371b74 "GNU gdb %s\n")
     at /home/scratch/PENDING/2004-10-29-full-location/src/gdb/utils.c:2231
  called by frame at 0x7ffff260, caller of frame at 0x7ffff1c0
  Source language c.
  Frame base at 0x7ffff1c0.
  Registers saved by this frame:
     pc at 0x7ffff244, lr at 0x7ffff244

Notice how:

-- source location (second line) uses a more "standard" format
The one printed when switching frames using up/down.  The format 
includes the argment list.  I've also modified it to print "Code at" 
instead of "pc =".

-- the separate ``Arglist at ...'' line is dropped
The actual list is moved to "source location"; while the args address is 
moved to ...

-- a new "Frame base" line
Where applicable frame locals and args addresses are also printed.

-- /Saved registers:/Registered saved by this frame/
And the list can include registers saved in another register (but the 
example doesn't show this).

I'm still wondering:

-- Frame's ID?
Should this be printed - the frame address is the frame ID's address 
already.

-- "saved pc" dropped
Perhaphs it should print "Return address ..."?

thoughts,
Andrew

[-- Attachment #2: diffs --]
[-- Type: text/plain, Size: 11389 bytes --]

2004-11-03  Andrew Cagney  <cagney@gnu.org>

	* stack.c (frame_info): List registers saved in another register.
	Use the standard format when printing the source and frame
	information.  Only print the frame's args or locals address when
	different to the frame's base address.

Index: stack.c
===================================================================
RCS file: /cvs/src/src/gdb/stack.c,v
retrieving revision 1.115
diff -p -u -r1.115 stack.c
--- stack.c	30 Oct 2004 21:16:10 -0000	1.115
+++ stack.c	3 Nov 2004 15:55:50 -0000
@@ -851,106 +851,30 @@ frame_info (char *addr_exp, int from_tty
   struct frame_info *fi;
   struct symtab_and_line sal;
   struct symbol *func;
-  struct symtab *s;
   struct frame_info *calling_frame_info;
-  int i, count, numregs;
+  int i;
   char *funname = 0;
   enum language funlang = language_unknown;
   const char *pc_regname;
   int selected_frame_p;
+  struct gdbarch *gdbarch;
 
   fi = parse_frame_specification_1 (addr_exp, "No stack.", &selected_frame_p);
-
-  /* Name of the value returned by get_frame_pc().  Per comments, "pc"
-     is not a good name.  */
-  if (PC_REGNUM >= 0)
-    /* OK, this is weird.  The PC_REGNUM hardware register's value can
-       easily not match that of the internal value returned by
-       get_frame_pc().  */
-    pc_regname = REGISTER_NAME (PC_REGNUM);
-  else
-    /* But then, this is weird to.  Even without PC_REGNUM, an
-       architectures will often have a hardware register called "pc",
-       and that register's value, again, can easily not match
-       get_frame_pc().  */
-    pc_regname = "pc";
-
-  find_frame_sal (fi, &sal);
-  func = get_frame_function (fi);
-  /* FIXME: cagney/2002-11-28: Why bother?  Won't sal.symtab contain
-     the same value.  */
-  s = find_pc_symtab (get_frame_pc (fi));
-  if (func)
-    {
-      /* 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. RT
-       * (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 the demangler fails, try the demangled name
-	   * from the symbol table. This'll have parameters,
-	   * but that's preferable to diplaying a mangled name.
-	   */
-	  if (demangled == NULL)
-	    funname = SYMBOL_PRINT_NAME (func);
-	}
-    }
-  else
-    {
-      struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (get_frame_pc (fi));
-      if (msymbol != NULL)
-	{
-	  funname = DEPRECATED_SYMBOL_NAME (msymbol);
-	  funlang = SYMBOL_LANGUAGE (msymbol);
-	}
-    }
+  gdbarch = get_frame_arch (fi);
   calling_frame_info = get_prev_frame (fi);
 
-  if (selected_frame_p && frame_relative_level (fi) >= 0)
-    {
-      printf_filtered ("Stack level %d, frame at ",
-		       frame_relative_level (fi));
-      print_address_numeric (get_frame_base (fi), 1, gdb_stdout);
-      printf_filtered (":\n");
-    }
+  /* Opening line, dump out the frame's stack address ...  */
+  if (selected_frame_p)
+    fprintf_filtered (gdb_stdout, "Stack level %d, frame at ",
+		      frame_relative_level (fi));
   else
-    {
-      printf_filtered ("Stack frame at ");
-      print_address_numeric (get_frame_base (fi), 1, gdb_stdout);
-      printf_filtered (":\n");
-    }
-  printf_filtered (" %s = ", pc_regname);
-  print_address_numeric (get_frame_pc (fi), 1, gdb_stdout);
-
-  wrap_here ("   ");
-  if (funname)
-    {
-      printf_filtered (" in ");
-      fprintf_symbol_filtered (gdb_stdout, funname, funlang,
-			       DMGL_ANSI | DMGL_PARAMS);
-    }
-  wrap_here ("   ");
-  if (sal.symtab)
-    printf_filtered (" (%s:%d)", sal.symtab->filename, sal.line);
-  puts_filtered ("; ");
-  wrap_here ("    ");
-  printf_filtered ("saved %s ", pc_regname);
-  print_address_numeric (frame_pc_unwind (fi), 1, gdb_stdout);
-  printf_filtered ("\n");
+    fprintf_filtered (gdb_stdout, "Stack frame at ");
+  print_address_numeric (get_frame_base (fi), 1, gdb_stdout);
+  fprintf_filtered (gdb_stdout, ":\n");
+
+  /* Report where this frame is.  */
+  fprintf_filtered (gdb_stdout, " Code at ");
+  print_frame_info (fi, 0/*level*/, LOC_AND_ADDRESS, 1/*print_args*/);
 
   if (calling_frame_info)
     {
@@ -969,56 +893,49 @@ frame_info (char *addr_exp, int from_tty
     }
   if (get_next_frame (fi) || calling_frame_info)
     puts_filtered ("\n");
-  if (s)
-    printf_filtered (" source language %s.\n",
-		     language_str (s->language));
 
+  /* The source language, if known.  */
   {
-    /* Address of the argument list for this frame, or 0.  */
-    CORE_ADDR arg_list = get_frame_args_address (fi);
-    /* Number of args for this frame, or -1 if unknown.  */
-    int numargs;
-
-    if (arg_list == 0)
-      printf_filtered (" Arglist at unknown address.\n");
-    else
-      {
-	printf_filtered (" Arglist at ");
-	print_address_numeric (arg_list, 1, gdb_stdout);
-	printf_filtered (",");
-
-	if (!FRAME_NUM_ARGS_P ())
-	  {
-	    numargs = -1;
-	    puts_filtered (" args: ");
-	  }
-	else
-	  {
-	    numargs = FRAME_NUM_ARGS (fi);
-	    gdb_assert (numargs >= 0);
-	    if (numargs == 0)
-	      puts_filtered (" no args.");
-	    else if (numargs == 1)
-	      puts_filtered (" 1 arg: ");
-	    else
-	      printf_filtered (" %d args: ", numargs);
-	  }
-	print_frame_args (func, fi, numargs, gdb_stdout);
-	puts_filtered ("\n");
-      }
+    struct symtab *s;
+    s = find_pc_symtab (get_frame_pc (fi));
+    if (s)
+      printf_filtered (" Source language %s.\n",
+		       language_str (s->language));
   }
+
+  /* Print the frame's base, args, and locals addresses (if any are
+     different).  */
   {
-    /* Address of the local variables for this frame, or 0.  */
-    CORE_ADDR arg_list = get_frame_locals_address (fi);
+    CORE_ADDR base_addr;
+    CORE_ADDR args_addr;
+    CORE_ADDR locals_addr;
 
-    if (arg_list == 0)
-      printf_filtered (" Locals at unknown address,");
+    base_addr = get_frame_base_address (fi);
+    if (base_addr)
+      {
+	fprintf_filtered (gdb_stdout, " Frame base at ");
+	print_address_numeric (base_addr, 1, gdb_stdout);
+      }
     else
+      printf_filtered (" Frame base at unknown address");
+    args_addr = get_frame_args_address (fi);
+    if (args_addr && args_addr != base_addr)
+      {
+	fprintf_filtered (gdb_stdout, ",");
+	wrap_here ("   ");
+	fprintf_filtered (gdb_stdout, " arglist at ");
+	print_address_numeric (args_addr, 1, gdb_stdout);
+      }
+    locals_addr = get_frame_locals_address (fi);
+    if (locals_addr && locals_addr != base_addr)
       {
-	printf_filtered (" Locals at ");
-	print_address_numeric (arg_list, 1, gdb_stdout);
-	printf_filtered (",");
+	fprintf_filtered (gdb_stdout, ",");
+	wrap_here ("   ");
+	fprintf_filtered (gdb_stdout, " locals at ");
+	print_address_numeric (locals_addr, 1, gdb_stdout);
       }
+    if (base_addr || args_addr || locals_addr)
+      fprintf_filtered (gdb_stdout, ".\n");
   }
 
   /* Print as much information as possible on the location of all the
@@ -1028,77 +945,50 @@ frame_info (char *addr_exp, int from_tty
     int optimized;
     CORE_ADDR addr;
     int realnum;
-    int count;
-    int i;
-    int need_nl = 1;
-
-    /* The sp is special; what's displayed isn't the save address, but
-       the value of the previous frame's sp.  This is a legacy thing,
-       at one stage the frame cached the previous frame's SP instead
-       of its address, hence it was easiest to just display the cached
-       value.  */
-    if (SP_REGNUM >= 0)
+    int regnum;
+    int count = 0;
+    const int numregs = NUM_REGS + NUM_PSEUDO_REGS;
+
+    for (regnum = 0; regnum < numregs; regnum++)
       {
-	/* Find out the location of the saved stack pointer with out
-           actually evaluating it.  */
-	frame_register_unwind (fi, SP_REGNUM, &optimized, &lval, &addr,
+	/* Filter out system registers and the like.  */
+	if (!gdbarch_register_reggroup_p (current_gdbarch, regnum,
+					  all_reggroup))
+	  continue;
+	/* Find out the location of the saved register without
+	   fetching the corresponding value.  */
+	frame_register_unwind (fi, regnum, &optimized, &lval, &addr,
 			       &realnum, NULL);
-	if (!optimized && lval == not_lval)
+	/* Filter out registers that haven't been saved in another
+	   register or memory.  */
+	if (optimized)
+	  continue;
+	if (lval != lval_memory
+	    && (lval != lval_register || realnum == regnum))
+	  continue;
+	/* Print the value.  */
+	if (count == 0)
+	  puts_filtered (" Registers saved by this frame:\n   ");
+	else
 	  {
-	    char value[MAX_REGISTER_SIZE];
-	    CORE_ADDR sp;
-	    frame_register_unwind (fi, SP_REGNUM, &optimized, &lval, &addr,
-				   &realnum, value);
-	    /* NOTE: cagney/2003-05-22: This is assuming that the
-               stack pointer was packed as an unsigned integer.  That
-               may or may not be valid.  */
-	    sp = extract_unsigned_integer (value, register_size (current_gdbarch, SP_REGNUM));
-	    printf_filtered (" Previous frame's sp is ");
-	    print_address_numeric (sp, 1, gdb_stdout);
-	    printf_filtered ("\n");
-	    need_nl = 0;
+	    puts_filtered (",");
+	    wrap_here ("   ");
 	  }
-	else if (!optimized && lval == lval_memory)
+	count++;
+	printf_filtered (" %s", gdbarch_register_name (gdbarch, regnum));
+	switch (lval)
 	  {
-	    printf_filtered (" Previous frame's sp at ");
+	  case lval_memory:
+	    printf_filtered (" at ");
 	    print_address_numeric (addr, 1, gdb_stdout);
-	    printf_filtered ("\n");
-	    need_nl = 0;
-	  }
-	else if (!optimized && lval == lval_register)
-	  {
-	    printf_filtered (" Previous frame's sp in %s\n",
-			     REGISTER_NAME (realnum));
-	    need_nl = 0;
+	    break;
+	  case lval_register:
+	    printf_filtered (" in %s",
+			     gdbarch_register_name (gdbarch, realnum));
+	    break;
 	  }
-	/* else keep quiet.  */
       }
-
-    count = 0;
-    numregs = NUM_REGS + NUM_PSEUDO_REGS;
-    for (i = 0; i < numregs; i++)
-      if (i != SP_REGNUM
-	  && gdbarch_register_reggroup_p (current_gdbarch, i, all_reggroup))
-	{
-	  /* Find out the location of the saved register without
-             fetching the corresponding value.  */
-	  frame_register_unwind (fi, i, &optimized, &lval, &addr, &realnum,
-				 NULL);
-	  /* For moment, only display registers that were saved on the
-	     stack.  */
-	  if (!optimized && lval == lval_memory)
-	    {
-	      if (count == 0)
-		puts_filtered (" Saved registers:\n ");
-	      else
-		puts_filtered (",");
-	      wrap_here (" ");
-	      printf_filtered (" %s at ", REGISTER_NAME (i));
-	      print_address_numeric (addr, 1, gdb_stdout);
-	      count++;
-	    }
-	}
-    if (count || need_nl)
+    if (count)
       puts_filtered ("\n");
   }
 }

^ permalink raw reply	[flat|nested] 6+ messages in thread
* RE: Changing "info frame" output?
@ 2004-11-03 20:49 Nick Roberts
  2004-11-05 15:00 ` Andrew Cagney
  0 siblings, 1 reply; 6+ messages in thread
From: Nick Roberts @ 2004-11-03 20:49 UTC (permalink / raw)
  To: cagney; +Cc: gdb



> and with that in mind have come up with the following as a draft:

> Stack level 1, frame at 0x7ffff240:
>  Code at 0x1005e5f8 in fprintf_filtered (stream=0x10467888,
>     format=0x10371b74 "GNU gdb %s\n")
>     at /home/scratch/PENDING/2004-10-29-full-location/src/gdb/utils.c:2231
>  called by frame at 0x7ffff260, caller of frame at 0x7ffff1c0
>  Source language c.
>  Frame base at 0x7ffff1c0.
>  Registers saved by this frame:
>     pc at 0x7ffff244, lr at 0x7ffff244

...
> thoughts,

Well gdb-ui.el in CVS Emacs uses the existing info frame" output to update the
GUI. If you are going to change this output then I think it is important to
have an equivalent MI command whose output is stable. I started a thread about
this on the gdb mailing list back in June, and posted a patch, probably lousy,
on gdb-patches:

     http://sources.redhat.com/ml/gdb-patches/2004-06/msg00652.html

to describe the functionality I was hoping to have and which was titled:

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

Could this be included in the discussion too, please.


Nick


Update on Emacs: We're six months into the feature freeze and there still
hasn't been a pretest. Emacs is starting to look like one of those immaculate
classic cars that goes everywhere on a trailer. Well you wouldn't want to
get it dirty, would you?

^ permalink raw reply	[flat|nested] 6+ messages in thread
* Re: Changing "info frame" output?
@ 2004-11-05  7:28 Paul Schlie
  0 siblings, 0 replies; 6+ messages in thread
From: Paul Schlie @ 2004-11-05  7:28 UTC (permalink / raw)
  To: gdb

Although possibly too radical a departure, might something like this
be worthy of consideration:

frame: NN, pc: 0x12345678, sr: 0x12345678
line: 442, file: /file_path/.../file_name
source: int function_name(int alpha, int beta);
global: 'zeta=>r5, <return_value>=>r0, sp=>fp
caller: 'alpha=>r1, 'beta=>r2, pc=>(sp+0), sr=>(sp+4)
-saved: r3>r12, r4=>sp+4, r5=>(sp+8)
-local: 'n=>r3, 'o=>r4, <t1>=>r5, <t2>=>r6

Where on a frame by frame basis one can easily see the current state
of program execution simultaneously with the symbolic variable, and
saved register mappings associated with the corresponding call frame;
and independently view their values as desired using print expressions.

Such that if one wanted to see the previously saved pc (i.e. return
address), one could simply print the memory location ($sp+0), as
identified in the frame caller register mapping as having been the
store location of the previous pc. Where hypothetically:

global: lists the logical variable and register mapping established
        within earlier frames, but inherited by the called frame.
        
caller: lists the logical variables and program state passed to the
        frame.

-saved: lists the registers that were saved to either other registers
        or off to the stack prior to being logically allocated for
        local use (and reversed prior to return).

-local: lists the logical variable register and/or memory mappings
        local to the current frame.

(where for the sake of argument I've used 'name to quote symbolic
 names, and used <name> to designate implied logical variable names)

Although there are many ways to skin this cat, it just stuck me as a
potentially simple and succinct way to provide at a glance most of the
information most significant to the debugging process; and does so in a
reasonably flexible way that allows logical variables and/or previous
register values to be easily shown as being mapped to either registers,
or register indirect to memory on a frame by frame basis, therefore
friendly to a variety of CPU architectures, etc.



^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2004-11-05 15:00 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-11-03 16:28 Changing "info frame" output? Andrew Cagney
2004-11-04 21:59 ` Mark Kettenis
2004-11-05 14:53   ` Andrew Cagney
2004-11-03 20:49 Nick Roberts
2004-11-05 15:00 ` Andrew Cagney
2004-11-05  7:28 Paul Schlie

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).