Problem with Nov 21 1997 valops.c:call_function_by_hand change

Peter.Schauer Peter.Schauer@regent.e-technik.tu-muenchen.de
Mon May 4 12:47:00 GMT 1998


This change:

Fri Nov 21 19:43:23 1997  Jim Blandy  <jimb@zwingli.cygnus.com>

	* valops.c (call_function_by_hand): If the function has a
	prototype, convert its arguments as if by assignment.  Otherwise,
	do the usual promotions. 

causes at least two problems.

1) When passing an int to a function expecting a reference to an int,
  GDB now fails. value_cast doesn't convert to a reference, and it
  shouldn't, whereas value_arg_coerce used to get it right in gdb-4.16.

pes@resunserv_1002$ cat tcall.cc
int int_val = 87;
int &int_ref = int_val;

int t_ref(int & a)
{
  return a;
}

main () {}
pes@resunserv_1003$ gcc -g tcall.cc
pes@resunserv_1004$ gdb a.out
GNU gdb 4.17
This GDB was configured as "sparc-sun-solaris2.5.1"...
(gdb) b main
Breakpoint 1 at 0x10ad0: file tcall.cc, line 9.
(gdb) r
Starting program: a.out

Breakpoint 1, main () at tcall.cc:9
9       main () {}
(gdb) p t_ref(int_val)

Program received signal SIGBUS, Bus error.
0x109ac in t_ref (a=@0x57) at tcall.cc:6
6         return a;
The program being debugged stopped while in a function called from GDB.
When the function (t_ref(int &)) is done executing, GDB will silently
stop (instead of continuing to evaluate the expression containing
the function call).


2) When using dwarf2 debugging info under Linux (via -ggdb) for the
  gdb/testsuite/gdb.base/callfuncs.c testcase, t_small_values gets
  TYPE_FLAG_PROTOTYPED set, and the argument types are the non-promoted
  types.
  value_cast then changes the passed integer arguments to char/short
  arguments, causing misplaced arguments on the stack, as the default
  promotion to int via value_arg_coerce is missing now.

bash-2.01$ gdb callfuncs
GNU gdb 4.17
This GDB was configured as "i586-pc-linux-gnu"...
(gdb) b main
Breakpoint 1 at 0x80486c5: file callfuncs.c, line 135.
(gdb) r
Starting program: callfuncs

Breakpoint 1, main () at callfuncs.c:135
135       malloc(1);
(gdb) i source
Current source file is ...
Compilation directory is ...
Located in ...
Contains 268 lines.
Source language is c.
Compiled with DWARF 2 debugging format.
(gdb) p t_small_values(1,2,3,4,5,6,7,8,9,10)
$1 = 117887498


The following patch solves both problems by reverting call_function_by_hand 
to using value_arg_coerce instead of value_cast.
Any comments, suggestions ?

*** gdb/valops.c.orig	Tue Feb 10 08:39:18 1998
--- gdb/valops.c	Mon May  4 21:30:02 1998
***************
*** 47,53 ****
  
  #ifdef CALL_DUMMY
  static CORE_ADDR find_function_addr PARAMS ((value_ptr, struct type **));
! static value_ptr value_arg_coerce PARAMS ((value_ptr, struct type *));
  #endif
  
  
--- 47,53 ----
  
  #ifdef CALL_DUMMY
  static CORE_ADDR find_function_addr PARAMS ((value_ptr, struct type **));
! static value_ptr value_arg_coerce PARAMS ((value_ptr, struct type *, int));
  #endif
  
  
***************
*** 944,955 ****
  /* Perform the standard coercions that are specified
     for arguments to be passed to C functions.
  
!    If PARAM_TYPE is non-NULL, it is the expected parameter type. */
  
  static value_ptr
! value_arg_coerce (arg, param_type)
       value_ptr arg;
       struct type *param_type;
  {
    register struct type *arg_type = check_typedef (VALUE_TYPE (arg));
    register struct type *type
--- 944,957 ----
  /* Perform the standard coercions that are specified
     for arguments to be passed to C functions.
  
!    If PARAM_TYPE is non-NULL, it is the expected parameter type.
!    Performs float to double conversion only if COERCE_FLOAT is non-zero.  */
  
  static value_ptr
! value_arg_coerce (arg, param_type, coerce_float)
       value_ptr arg;
       struct type *param_type;
+      int coerce_float;
  {
    register struct type *arg_type = check_typedef (VALUE_TYPE (arg));
    register struct type *type
***************
*** 973,980 ****
  	type = builtin_type_int;
        break;
     case TYPE_CODE_FLT:
!      /* coerce float to double, unless the function prototype specifies float */
!      if (COERCE_FLOAT_TO_DOUBLE)
         {
  	 if (TYPE_LENGTH (type) < TYPE_LENGTH (builtin_type_double))
  	   type = builtin_type_double;
--- 975,982 ----
  	type = builtin_type_int;
        break;
     case TYPE_CODE_FLT:
!      /* coerce float to double if requested.  */
!      if (coerce_float)
         {
  	 if (TYPE_LENGTH (type) < TYPE_LENGTH (builtin_type_double))
  	   type = builtin_type_double;
***************
*** 1214,1232 ****
  	 promotions.  FIXME: if we had a prototype, this should only
  	 be allowed if ... were present.  */
        if (i >= TYPE_NFIELDS (ftype))
! 	args[i] = value_arg_coerce (args[i], 0);
  
        else 
  	{
  	  struct type *param_type = TYPE_FIELD_TYPE (ftype, i);
  
! 	  /* If we have a prototype, cast as for assignment.  */
  	  if (TYPE_FLAGS (ftype) & TYPE_FLAG_PROTOTYPED)
! 	    args[i] = value_cast (param_type, args[i]);
! 
! 	  /* Otherwise, do the standard promotions.  */
  	  else
! 	    args[i] = value_arg_coerce (args[i], param_type);
  	}
      }
  
--- 1216,1238 ----
  	 promotions.  FIXME: if we had a prototype, this should only
  	 be allowed if ... were present.  */
        if (i >= TYPE_NFIELDS (ftype))
! 	args[i] = value_arg_coerce (args[i], NULL, 1);
  
        else 
  	{
  	  struct type *param_type = TYPE_FIELD_TYPE (ftype, i);
  
! 	  /* We do not request float to double promotions if we have
! 	     a prototype. */
  	  if (TYPE_FLAGS (ftype) & TYPE_FLAG_PROTOTYPED)
! 	    args[i] = value_arg_coerce (args[i], param_type, 0);
  	  else
! 	    /* FIXME: We should always convert floats to doubles in the
! 	       non-prototyped case.  As many debugging formats include
! 	       no information about prototyping, we have to live with
! 	       COERCE_FLOAT_TO_DOUBLE for now.  */
! 	    args[i] = value_arg_coerce (args[i], param_type,
! 					COERCE_FLOAT_TO_DOUBLE);
  	}
      }
  

-- 
Peter Schauer			pes@regent.e-technik.tu-muenchen.de



More information about the Gdb mailing list