Float parameter passing in funcall on ppc-aix & ppc-lynx178.

Given the following code:

    float global_float = 0.0;

    void
    set_float (float f)
    {
      global_float = f;
    }

GDB incorrectly calls set_float if the set_float function is marked
as prototyped:

    (gdb) call set_float (5.0)
    (gdb) print global_float
    $1 = 2048

What happens, when the function is marked as prototyped, is that
GDB finds that the argument is a float, casts the value given in
the expression to a float, and then gives that float to ppc-aix/
ppc-lynx178's push_dummy_call gdbarch routine. The latter then blindly
copies it as is in the first floating-point register, instead of
making sure that it has the proper format first.

gdb/ChangeLog:

        * rs6000-aix-tdep.c (rs6000_push_dummy_call): Convert
        floating point registers to register type before storing
        value.
        * rs6000-lynx178-tdep.c (rs6000_lynx178_push_dummy_call):
        Likewise.
This commit is contained in:
Joel Brobecker 2013-05-13 10:27:35 +00:00
parent 8414efeff8
commit 36d1c68c70
3 changed files with 28 additions and 9 deletions

View File

@ -1,3 +1,11 @@
2013-05-13 Joel Brobecker <brobecker@adacore.com>
* rs6000-aix-tdep.c (rs6000_push_dummy_call): Convert
floating point registers to register type before storing
value.
* rs6000-lynx178-tdep.c (rs6000_lynx178_push_dummy_call):
Likewise.
2013-05-10 Joel Brobecker <brobecker@adacore.com>
Tom Tromey <tromey@redhat.com>

View File

@ -254,16 +254,21 @@ rs6000_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
if (TYPE_CODE (type) == TYPE_CODE_FLT)
{
/* Floating point arguments are passed in fpr's, as well as gpr's.
There are 13 fpr's reserved for passing parameters. At this point
there is no way we would run out of them. */
there is no way we would run out of them.
Always store the floating point value using the register's
floating-point format. */
const int fp_regnum = tdep->ppc_fp0_regnum + 1 + f_argno;
gdb_byte reg_val[MAX_REGISTER_SIZE];
struct type *reg_type = register_type (gdbarch, fp_regnum);
gdb_assert (len <= 8);
regcache_cooked_write (regcache,
tdep->ppc_fp0_regnum + 1 + f_argno,
value_contents (arg));
convert_typed_floating (value_contents (arg), type,
reg_val, reg_type);
regcache_cooked_write (regcache, fp_regnum, reg_val);
++f_argno;
}

View File

@ -100,13 +100,19 @@ rs6000_lynx178_push_dummy_call (struct gdbarch *gdbarch,
/* Floating point arguments are passed in fpr's, as well as gpr's.
There are 13 fpr's reserved for passing parameters. At this point
there is no way we would run out of them. */
there is no way we would run out of them.
Always store the floating point value using the register's
floating-point format. */
const int fp_regnum = tdep->ppc_fp0_regnum + 1 + f_argno;
gdb_byte reg_val[MAX_REGISTER_SIZE];
struct type *reg_type = register_type (gdbarch, fp_regnum);
gdb_assert (len <= 8);
regcache_cooked_write (regcache,
tdep->ppc_fp0_regnum + 1 + f_argno,
value_contents (arg));
convert_typed_floating (value_contents (arg), type,
reg_val, reg_type);
regcache_cooked_write (regcache, fp_regnum, reg_val);
++f_argno;
}