aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShahab Vahedi <shahab@synopsys.com>2021-07-19 16:13:47 +0200
committerShahab Vahedi <shahab@synopsys.com>2021-08-02 13:04:48 +0200
commite4c1aea498ff84bcb3086509d125ac8249f35db2 (patch)
tree5d66077b5b1839efd22f08f526db9e8985bd773b
parent3bea08edb3cdf30a96b5e0c385bc67c09865fe7e (diff)
downloadgdb-e4c1aea498ff84bcb3086509d125ac8249f35db2.zip
gdb-e4c1aea498ff84bcb3086509d125ac8249f35db2.tar.gz
gdb-e4c1aea498ff84bcb3086509d125ac8249f35db2.tar.bz2
gdb: Make the builtin "boolean" type an unsigned type
When printing the fields of a register that is of a custom struct type, the "unpack_bits_as_long ()" function is used: do_val_print (...) cp_print_value_fields (...) value_field_bitfield (...) unpack_value_bitfield (...) unpack_bits_as_long (...) This function may sign-extend the extracted field while returning it: val >>= lsbcount; if (...) { valmask = (((ULONGEST) 1) << bitsize) - 1; val &= valmask; if (!field_type->is_unsigned ()) if (val & (valmask ^ (valmask >> 1))) val |= ~valmask; } return val; lsbcount: Number of lower bits to get rid of. bitsize: The bit length of the field to be extracted. val: The register value. field_type: The type of field that is being handled. While the logic here is correct, there is a problem when it is handling "field_type"s of "boolean". Those types are NOT marked as "unsigned" and therefore they end up being sign extended. Although this is not a problem for "false" (0), it definitely causes trouble for "true". This patch constructs the builtin boolean type as such that it is marked as an "unsigned" entity. The issue tackled here was first encountered for arc-elf32 target running on an x86_64 machine. The unit-test introduced in this change has passed for all the targets (--enable-targets=all) running on the same x86_64 host. gdb/ChangeLog: PR gdb/28104 * gdbtypes.c (gdbtypes_post_init): Use "arch_boolean_type (..., unsigned=1, ...) to construct "boolean". cp-valprint.c (test_print_flags): New. (_initialize_cp_valprint): Run the "test_print_flags" unit-test.
-rw-r--r--gdb/ChangeLog9
-rw-r--r--gdb/cp-valprint.c68
-rw-r--r--gdb/gdbtypes.c2
3 files changed, 78 insertions, 1 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index f371a2d..3138024 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,12 @@
+2021-08-02 Shahab Vahedi <shahab@synopsys.com>
+
+ PR gdb/28104
+ * gdbtypes.c (gdbtypes_post_init): Use
+ "arch_boolean_type (..., unsigned=1, ...) to construct
+ "boolean".
+ cp-valprint.c (test_print_flags): New.
+ (_initialize_cp_valprint): Run the "test_print_flags" unit-test.
+
2021-07-28 Tom de Vries <tdevries@suse.de>
* dwarf2/read.c (attr_to_dynamic_prop): Handle DW_FORM_data16.
diff --git a/gdb/cp-valprint.c b/gdb/cp-valprint.c
index 6c04494..7442ec0 100644
--- a/gdb/cp-valprint.c
+++ b/gdb/cp-valprint.c
@@ -38,6 +38,8 @@
#include "gdbsupport/byte-vector.h"
#include "gdbarch.h"
#include "cli/cli-style.h"
+#include "gdbsupport/selftest.h"
+#include "selftest-arch.h"
static struct obstack dont_print_vb_obstack;
static struct obstack dont_print_statmem_obstack;
@@ -715,11 +717,77 @@ cp_print_class_member (const gdb_byte *valaddr, struct type *type,
fprintf_filtered (stream, "%ld", (long) val);
}
+#if GDB_SELF_TEST
+
+/* Test printing of TYPE_CODE_STRUCT values. */
+
+static void
+test_print_fields (gdbarch *arch)
+{
+ struct field *f;
+ type *uint8_type = builtin_type (arch)->builtin_uint8;
+ type *bool_type = builtin_type (arch)->builtin_bool;
+ type *the_struct = arch_composite_type (arch, NULL, TYPE_CODE_STRUCT);
+ TYPE_LENGTH (the_struct) = 4;
+
+ /* Value: 1110 1001
+ Fields: C-BB B-A- */
+ if (gdbarch_byte_order (arch) == BFD_ENDIAN_LITTLE)
+ {
+ f = append_composite_type_field_raw (the_struct, "A", bool_type);
+ SET_FIELD_BITPOS (*f, 1);
+ FIELD_BITSIZE (*f) = 1;
+ f = append_composite_type_field_raw (the_struct, "B", uint8_type);
+ SET_FIELD_BITPOS (*f, 3);
+ FIELD_BITSIZE (*f) = 3;
+ f = append_composite_type_field_raw (the_struct, "C", bool_type);
+ SET_FIELD_BITPOS (*f, 7);
+ FIELD_BITSIZE (*f) = 1;
+ }
+ /* According to the logic commented in "make_gdb_type_struct ()" of
+ * target-descriptions.c, bit positions are numbered differently for
+ * little and big endians. */
+ else
+ {
+ f = append_composite_type_field_raw (the_struct, "A", bool_type);
+ SET_FIELD_BITPOS (*f, 30);
+ FIELD_BITSIZE (*f) = 1;
+ f = append_composite_type_field_raw (the_struct, "B", uint8_type);
+ SET_FIELD_BITPOS (*f, 26);
+ FIELD_BITSIZE (*f) = 3;
+ f = append_composite_type_field_raw (the_struct, "C", bool_type);
+ SET_FIELD_BITPOS (*f, 24);
+ FIELD_BITSIZE (*f) = 1;
+ }
+
+ value *val = allocate_value (the_struct);
+ gdb_byte *contents = value_contents_writeable (val);
+ store_unsigned_integer (contents, TYPE_LENGTH (value_enclosing_type (val)),
+ gdbarch_byte_order (arch), 0xe9);
+
+ string_file out;
+ struct value_print_options opts;
+ get_no_prettyformat_print_options (&opts);
+ cp_print_value_fields(val, &out, 0, &opts, NULL, 0);
+ SELF_CHECK (out.string () == "{A = false, B = 5, C = true}");
+
+ out.clear();
+ opts.format = 'x';
+ cp_print_value_fields(val, &out, 0, &opts, NULL, 0);
+ SELF_CHECK (out.string () == "{A = 0x0, B = 0x5, C = 0x1}");
+}
+
+#endif
+
void _initialize_cp_valprint ();
void
_initialize_cp_valprint ()
{
+#if GDB_SELF_TEST
+ selftests::register_test_foreach_arch ("print-fields", test_print_fields);
+#endif
+
obstack_begin (&dont_print_stat_array_obstack,
32 * sizeof (struct type *));
obstack_begin (&dont_print_statmem_obstack,
diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c
index dbc82f0..1b54a23 100644
--- a/gdb/gdbtypes.c
+++ b/gdb/gdbtypes.c
@@ -6093,7 +6093,7 @@ gdbtypes_post_init (struct gdbarch *gdbarch)
builtin_type->builtin_string
= arch_type (gdbarch, TYPE_CODE_STRING, TARGET_CHAR_BIT, "string");
builtin_type->builtin_bool
- = arch_type (gdbarch, TYPE_CODE_BOOL, TARGET_CHAR_BIT, "bool");
+ = arch_boolean_type (gdbarch, TARGET_CHAR_BIT, 1, "bool");
/* The following three are about decimal floating point types, which
are 32-bits, 64-bits and 128-bits respectively. */