[pushed] Assert that a floating type's length is at least as long as its format
Commit Message
This would have caught the HP/PA bug fixed in the previous patch:
.../src/gdb/gdbtypes.c:4690: internal-error: arch_float_type: Assertion `len >= floatformat_totalsize_bytes (floatformats[0])' failed.
A problem internal to GDB has been detected,
further debugging may prove unreliable.
Quit this debugging session? (y or n)
Tested on x86-64 Fedora 23, --enable-targets=all.
gdb/ChangeLog:
2016-03-09 Pedro Alves <palves@redhat.com>
* doublest.c (floatformat_totalsize_bytes): New function.
(floatformat_from_type): Assert that the type's length is at least
as long as the floatformat's totalsize.
* doublest.h (floatformat_totalsize_bytes): New declaration.
* gdbtypes.c (arch_float_type): Assert that the type's length is
at least as long as the floatformat's totalsize.
---
gdb/ChangeLog | 9 +++++++++
gdb/doublest.c | 17 +++++++++++++++--
gdb/doublest.h | 4 ++++
gdb/gdbtypes.c | 9 +++++++++
4 files changed, 37 insertions(+), 2 deletions(-)
@@ -1,5 +1,14 @@
2016-03-09 Pedro Alves <palves@redhat.com>
+ * doublest.c (floatformat_totalsize_bytes): New function.
+ (floatformat_from_type): Assert that the type's length is at least
+ as long as the floatformat's totalsize.
+ * doublest.h (floatformat_totalsize_bytes): New declaration.
+ * gdbtypes.c (arch_float_type): Assert that the type's length is
+ at least as long as the floatformat's totalsize.
+
+2016-03-09 Pedro Alves <palves@redhat.com>
+
* hppa-linux-tdep.c (hppa_linux_init_abi): Set the long double
format to floatformats_ieee_double.
@@ -693,6 +693,15 @@ static const struct floatformat *host_double_format = GDB_HOST_DOUBLE_FORMAT;
static const struct floatformat *host_long_double_format
= GDB_HOST_LONG_DOUBLE_FORMAT;
+/* See doublest.h. */
+
+size_t
+floatformat_totalsize_bytes (const struct floatformat *fmt)
+{
+ return ((fmt->totalsize + FLOATFORMAT_CHAR_BIT - 1)
+ / FLOATFORMAT_CHAR_BIT);
+}
+
void
floatformat_to_doublest (const struct floatformat *fmt,
const void *in, DOUBLEST *out)
@@ -802,12 +811,16 @@ const struct floatformat *
floatformat_from_type (const struct type *type)
{
struct gdbarch *gdbarch = get_type_arch (type);
+ const struct floatformat *fmt;
gdb_assert (TYPE_CODE (type) == TYPE_CODE_FLT);
if (TYPE_FLOATFORMAT (type) != NULL)
- return TYPE_FLOATFORMAT (type)[gdbarch_byte_order (gdbarch)];
+ fmt = TYPE_FLOATFORMAT (type)[gdbarch_byte_order (gdbarch)];
else
- return floatformat_from_length (gdbarch, TYPE_LENGTH (type));
+ fmt = floatformat_from_length (gdbarch, TYPE_LENGTH (type));
+
+ gdb_assert (TYPE_LENGTH (type) >= floatformat_totalsize_bytes (fmt));
+ return fmt;
}
/* Extract a floating-point number of type TYPE from a target-order
@@ -89,6 +89,10 @@ extern const char *floatformat_mantissa (const struct floatformat *,
const struct floatformat *floatformat_from_type (const struct type *type);
+/* Return the floatformat's total size in host bytes. */
+
+extern size_t floatformat_totalsize_bytes (const struct floatformat *fmt);
+
extern DOUBLEST extract_typed_floating (const void *addr,
const struct type *type);
extern void store_typed_floating (void *addr, const struct type *type,
@@ -4682,6 +4682,15 @@ arch_float_type (struct gdbarch *gdbarch,
t = arch_type (gdbarch, TYPE_CODE_FLT, bit / TARGET_CHAR_BIT, name);
TYPE_FLOATFORMAT (t) = floatformats;
+
+ if (floatformats != NULL)
+ {
+ size_t len = TYPE_LENGTH (t);
+
+ gdb_assert (len >= floatformat_totalsize_bytes (floatformats[0]));
+ gdb_assert (len >= floatformat_totalsize_bytes (floatformats[1]));
+ }
+
return t;
}