[gnu.gdb.bug] Bug in gdb 3.1 printcmd.c + patch

david@CSVAX.CALTECH.EDU (David Hull) (03/16/89)

In the process of porting gdb 3.1 to the Intergraph CLIPPER, I found
the following bug in the function print_frame_args() in printcmd.c:

    The CLIPPER C compiler (written by Green Hills) tries to pass the
    first two arguments to a function in registers.  If the declared
    type of the argument is narrower than the type it was passed as,
    the argument is narrowed by copying it to a local variable, which
    is below the frame pointer on the stack.  Thus its symbol value is
    negative.  print_frame_args() will not print arguments with
    negative symbol values.  Also, the function parameters are not
    necessarily ordered by symbol value, as print_frame_args()
    assumes.  It turns out that, on the CLIPPER at least, the symbols
    for the arguments are always in the correct order in the symbol
    table (I think this is true for all COFF-format files).  My
    solution was to have a special version of print_frame_args() for
    the CLIPPER.  Since I think that it will work for all COFF
    machines, the new code is enabled with COFF_FORMAT.  If I'm wrong,
    please let me know.

    In a related problem, print_frame_nameless_args() didn't always
    print a leading comma when it should.  I added a new argument
    to tell it whether it needs to.

-David
					---------------------------------------
					David Hull  TRW Inc.  Redondo Beach, CA
					  ...!{uunet,cit-vax,trwrb}!wiley!david
					     david%wiley.uucp@csvax.caltech.edu

*** orig/printcmd.c	Thu Feb 16 15:23:26 1989
--- printcmd.c	Tue Mar 14 14:18:17 1989
***************
*** 1159,1164 ****
--- 1159,1224 ----
  
  static void print_frame_nameless_args ();
  
+ #ifdef COFF_FORMAT
+ 
+ void
+ print_frame_args (func, fi, num, stream)
+      struct symbol *func;
+      struct frame_info *fi;
+      int num;
+      FILE *stream;
+ {
+   struct block *b;
+   int nsyms = 0;
+   int first = 1;
+   register int i;
+   register int last_offset = FRAME_ARGS_SKIP;
+   register struct symbol *sym;
+   register value val;
+   register CORE_ADDR addr = FRAME_ARGS_ADDRESS (fi);
+ 
+   if (func)
+     {
+       b = SYMBOL_BLOCK_VALUE (func);
+       nsyms = BLOCK_NSYMS (b);
+     }
+ 
+   for (i = 0; i < nsyms; i++)
+     {
+       QUIT;
+       sym = BLOCK_SYM (b, i);
+       if ((SYMBOL_CLASS (sym) != LOC_ARG) &&
+           (SYMBOL_CLASS (sym) != LOC_REGPARM))
+ 	continue;
+ 
+       /* Print the next arg.  */
+       if (SYMBOL_CLASS (sym) == LOC_REGPARM)
+ 	val = value_from_register (SYMBOL_TYPE (sym),
+ 				   SYMBOL_VALUE (sym),
+ 				   FRAME_INFO_ID (fi));
+       else
+ 	val = value_at (SYMBOL_TYPE (sym), addr + SYMBOL_VALUE (sym));
+ 
+       if (! first)
+ 	fprintf (stream, ", ");
+       fprintf (stream, "%s=", SYMBOL_NAME (sym));
+       value_print (val, stream, 0);
+       first = 0;
+       if ((SYMBOL_CLASS (sym) == LOC_ARG) && (SYMBOL_VALUE (sym) >= 0))
+ 	last_offset = SYMBOL_VALUE (sym) + TYPE_LENGTH (SYMBOL_TYPE (sym));
+       
+       /* Round up address of next arg to multiple of size of int.  */
+       last_offset
+ 	= ((last_offset + sizeof (int) - 1) / sizeof (int)) * sizeof (int);
+     }
+   if (num >= 0 && num * sizeof (int) + FRAME_ARGS_SKIP > last_offset)
+     print_frame_nameless_args (addr, last_offset,
+ 			       num * sizeof (int) + FRAME_ARGS_SKIP,
+ 			       first, stream);
+ }
+ 
+ #else /* not COFF_FORMAT */
+ 
  void
  print_frame_args (func, fi, num, stream)
       struct symbol *func;
***************
*** 1216,1222 ****
  	  && last_offset != (SYMBOL_VALUE (sym) / sizeof (int)) * sizeof (int))
  	{
  	  print_frame_nameless_args (addr, last_offset, SYMBOL_VALUE (sym),
! 				     stream);
  	  first = 0;
  	}
        /* Print the next arg.  */
--- 1276,1282 ----
  	  && last_offset != (SYMBOL_VALUE (sym) / sizeof (int)) * sizeof (int))
  	{
  	  print_frame_nameless_args (addr, last_offset, SYMBOL_VALUE (sym),
! 				     first, stream);
  	  first = 0;
  	}
        /* Print the next arg.  */
***************
*** 1235,1244 ****
        if (SYMBOL_CLASS (sym) == LOC_ARG)
  	last_offset = SYMBOL_VALUE (sym) + TYPE_LENGTH (SYMBOL_TYPE (sym));
        else
! 	{
! 	  last_regparm = SYMBOL_VALUE (sym) + 1;
! 	  last_offset += TYPE_LENGTH (SYMBOL_TYPE (sym));
! 	}
        
        /* Round up address of next arg to multiple of size of int.  */
        last_offset
--- 1295,1301 ----
        if (SYMBOL_CLASS (sym) == LOC_ARG)
  	last_offset = SYMBOL_VALUE (sym) + TYPE_LENGTH (SYMBOL_TYPE (sym));
        else
! 	last_regparm = SYMBOL_VALUE (sym) + 1;
        
        /* Round up address of next arg to multiple of size of int.  */
        last_offset
***************
*** 1247,1267 ****
      }
    if (num >= 0 && num * sizeof (int) + FRAME_ARGS_SKIP > last_offset)
      print_frame_nameless_args (addr, last_offset,
! 			       num * sizeof (int) + FRAME_ARGS_SKIP, stream);
  }
  
  static void
! print_frame_nameless_args (argsaddr, start, end, stream)
       CORE_ADDR argsaddr;
       int start;
       int end;
       FILE *stream;
  {
    while (start < end)
      {
        QUIT;
!       if (start != FRAME_ARGS_SKIP)
  	fprintf (stream, ", ");
        fprintf (stream, "%d",
  	       read_memory_integer (argsaddr + start, sizeof (int)));
        start += sizeof (int);
--- 1304,1329 ----
      }
    if (num >= 0 && num * sizeof (int) + FRAME_ARGS_SKIP > last_offset)
      print_frame_nameless_args (addr, last_offset,
! 			       num * sizeof (int) + FRAME_ARGS_SKIP,
! 			       first, stream);
  }
  
+ #endif /* not COFF_FORMAT */
+ 
  static void
! print_frame_nameless_args (argsaddr, start, end, first, stream)
       CORE_ADDR argsaddr;
       int start;
       int end;
+      int first;
       FILE *stream;
  {
    while (start < end)
      {
        QUIT;
!       if (!first)
  	fprintf (stream, ", ");
+       first = 0;
        fprintf (stream, "%d",
  	       read_memory_integer (argsaddr + start, sizeof (int)));
        start += sizeof (int);