diff options
author | Joel Brobecker <brobecker@gnat.com> | 2011-01-13 16:23:00 +0000 |
---|---|---|
committer | Joel Brobecker <brobecker@gnat.com> | 2011-01-13 16:23:00 +0000 |
commit | 825d6d8a6983bce3664db1058afb19335db795cc (patch) | |
tree | ceeb6cf15a9dd5a730c48f947b72a571a79c70f7 | |
parent | 7458e66756c1515ff07193a097c2cdc71837012c (diff) | |
download | gdb-825d6d8a6983bce3664db1058afb19335db795cc.zip gdb-825d6d8a6983bce3664db1058afb19335db795cc.tar.gz gdb-825d6d8a6983bce3664db1058afb19335db795cc.tar.bz2 |
[ia64] small integral parameters and return values
This patch fixes a small problem on ia64-hpux when calling functions
whose parameter are small integral values (less than 8 bytes). In
that case, the parameter value was stored on the wrong side of the
register. Same problem for return values.
With this patch, the results for gdb.base/callfuncs.exp improve from
# of expected passes 41
# of unexpected failures 78
To:
# of expected passes 95
# of unexpected failures 24
gdb/ChangeLog:
* ia64-tdep.c (ia64_struct_type_p): New function.
(ia64_extract_return_value): Handle integral values that are
less than 8 bytes long.
(ia64_push_dummy_call): Likewise.
-rw-r--r-- | gdb/ChangeLog | 7 | ||||
-rw-r--r-- | gdb/ia64-tdep.c | 50 |
2 files changed, 55 insertions, 2 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index c548a19..e52214d 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,12 @@ 2011-01-13 Joel Brobecker <brobecker@adacore.com> + * ia64-tdep.c (ia64_struct_type_p): New function. + (ia64_extract_return_value): Handle integral values that are + less than 8 bytes long. + (ia64_push_dummy_call): Likewise. + +2011-01-13 Joel Brobecker <brobecker@adacore.com> + * ia64-tdep.c (floatformat_ia64_ext_little): Renames floatformat_ia64_ext. (floatformat_ia64_ext_big): New static const. diff --git a/gdb/ia64-tdep.c b/gdb/ia64-tdep.c index 81d42b6..05ca3a1 100644 --- a/gdb/ia64-tdep.c +++ b/gdb/ia64-tdep.c @@ -3177,6 +3177,15 @@ ia64_use_struct_convention (struct type *type) return TYPE_LENGTH (type) > 32; } +/* Return non-zero if TYPE is a structure or union type. */ + +static int +ia64_struct_type_p (const struct type *type) +{ + return (TYPE_CODE (type) == TYPE_CODE_STRUCT + || TYPE_CODE (type) == TYPE_CODE_UNION); +} + static void ia64_extract_return_value (struct type *type, struct regcache *regcache, gdb_byte *valbuf) @@ -3201,6 +3210,21 @@ ia64_extract_return_value (struct type *type, struct regcache *regcache, regnum++; } } + else if (!ia64_struct_type_p (type) && TYPE_LENGTH (type) < 8) + { + /* This is an integral value, and its size is less than 8 bytes. + These values are LSB-aligned, so extract the relevant bytes, + and copy them into VALBUF. */ + /* brobecker/2005-12-30: Actually, all integral values are LSB aligned, + so I suppose we should also add handling here for integral values + whose size is greater than 8. But I wasn't able to create such + a type, neither in C nor in Ada, so not worrying about these yet. */ + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + ULONGEST val; + + regcache_cooked_read_unsigned (regcache, IA64_GR8_REGNUM, &val); + store_unsigned_integer (valbuf, TYPE_LENGTH (type), byte_order, val); + } else { ULONGEST val; @@ -3705,8 +3729,30 @@ ia64_push_dummy_call (struct gdbarch *gdbarch, struct value *function, char val_buf[8]; memset (val_buf, 0, 8); - memcpy (val_buf, value_contents (arg) + argoffset, - (len > 8) ? 8 : len); + if (!ia64_struct_type_p (type) && len < 8) + { + /* Integral types are LSB-aligned, so we have to be careful + to insert the argument on the correct side of the buffer. + This is why we use store_unsigned_integer. */ + store_unsigned_integer + (val_buf, 8, byte_order, + extract_unsigned_integer (value_contents (arg), len, + byte_order)); + } + else + { + /* This is either an 8bit integral type, or an aggregate. + For 8bit integral type, there is no problem, we just + copy the value over. + + For aggregates, the only potentially tricky portion + is to write the last one if it is less than 8 bytes. + In this case, the data is Byte0-aligned. Happy news, + this means that we don't need to differentiate the + handling of 8byte blocks and less-than-8bytes blocks. */ + memcpy (val_buf, value_contents (arg) + argoffset, + (len > 8) ? 8 : len); + } if (slotnum < rseslots) write_memory (rse_address_add (bsp, slotnum), val_buf, 8); |