aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoel Brobecker <brobecker@gnat.com>2011-01-13 16:23:00 +0000
committerJoel Brobecker <brobecker@gnat.com>2011-01-13 16:23:00 +0000
commit825d6d8a6983bce3664db1058afb19335db795cc (patch)
treeceeb6cf15a9dd5a730c48f947b72a571a79c70f7
parent7458e66756c1515ff07193a097c2cdc71837012c (diff)
downloadgdb-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/ChangeLog7
-rw-r--r--gdb/ia64-tdep.c50
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);