aboutsummaryrefslogtreecommitdiff
path: root/gdb/dwarf2
diff options
context:
space:
mode:
authorTom Tromey <tromey@adacore.com>2025-04-25 08:13:36 -0600
committerTom Tromey <tromey@adacore.com>2025-04-29 11:34:49 -0600
commit48d0ac705c45cb588a8e6d19ee911bc225c897cf (patch)
tree2916bf012082517567d779b19488042893825a91 /gdb/dwarf2
parenta7175864d96765b291276cf3a6508b78ad3a9b23 (diff)
downloadbinutils-48d0ac705c45cb588a8e6d19ee911bc225c897cf.zip
binutils-48d0ac705c45cb588a8e6d19ee911bc225c897cf.tar.gz
binutils-48d0ac705c45cb588a8e6d19ee911bc225c897cf.tar.bz2
Handle base type without DW_AT_byte_size
DWARF says that a base type can have DW_AT_bit_size, without DW_AT_byte_size. However, gdb does not correctly handle this; in fact, it crashes, as pointed out in this LLVM merge request: https://github.com/llvm/llvm-project/pull/137123 This patch reworks the base type size logic a bit to handle this situation. Tested-by: Kevin Buettner <kevinb@redhat.com> Approved-by: Kevin Buettner <kevinb@redhat.com>
Diffstat (limited to 'gdb/dwarf2')
-rw-r--r--gdb/dwarf2/read.c67
1 files changed, 38 insertions, 29 deletions
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index 6b7f2c7..a177a05 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -13634,7 +13634,6 @@ read_base_type (struct die_info *die, struct dwarf2_cu *cu)
struct type *type;
struct attribute *attr;
ULONGEST encoding = 0;
- int bits = 0;
const char *name;
attr = dwarf2_attr (die, DW_AT_encoding, cu);
@@ -13644,9 +13643,33 @@ read_base_type (struct die_info *die, struct dwarf2_cu *cu)
if (value.has_value ())
encoding = *value;
}
+
attr = dwarf2_attr (die, DW_AT_byte_size, cu);
+ std::optional<ULONGEST> byte_size;
+ if (attr != nullptr)
+ byte_size = attr->unsigned_constant ();
+ attr = dwarf2_attr (die, DW_AT_bit_size, cu);
+ std::optional<ULONGEST> bit_size;
if (attr != nullptr)
- bits = attr->unsigned_constant ().value_or (0) * TARGET_CHAR_BIT;
+ bit_size = attr->unsigned_constant ();
+
+ attr = dwarf2_attr (die, DW_AT_data_bit_offset, cu);
+ std::optional<ULONGEST> bit_offset;
+ if (attr != nullptr)
+ bit_offset = attr->unsigned_constant ();
+
+ int bits = 0;
+ if (byte_size.has_value ())
+ bits = TARGET_CHAR_BIT * *byte_size;
+ else if (bit_size.has_value ())
+ bits = align_up (*bit_size, 8);
+ else
+ {
+ /* No size, so arrange for an error type. */
+ complaint (_("DW_TAG_base_type has neither bit- nor byte-size"));
+ encoding = (ULONGEST) -1;
+ }
+
name = dwarf2_full_name (nullptr, die, cu);
if (!name)
complaint (_("DW_AT_name missing from DW_TAG_base_type"));
@@ -13792,35 +13815,21 @@ read_base_type (struct die_info *die, struct dwarf2_cu *cu)
type->set_endianity_is_not_default (not_default);
- if (TYPE_SPECIFIC_FIELD (type) == TYPE_SPECIFIC_INT)
+ /* If both a byte size and bit size were provided, then that means
+ that not every bit in the object contributes to the value. */
+ if (TYPE_SPECIFIC_FIELD (type) == TYPE_SPECIFIC_INT
+ && byte_size.has_value ()
+ && bit_size.has_value ())
{
- attr = dwarf2_attr (die, DW_AT_bit_size, cu);
- if (attr != nullptr && attr->form_is_constant ())
+ /* DWARF says: If this attribute is omitted a default data bit
+ offset of zero is assumed. */
+ ULONGEST offset = bit_offset.value_or (0);
+
+ /* Only use the attributes if they make sense together. */
+ if (*bit_size + offset <= 8 * type->length ())
{
- unsigned real_bit_size = attr->unsigned_constant ().value_or (0);
- if (real_bit_size >= 0 && real_bit_size <= 8 * type->length ())
- {
- attr = dwarf2_attr (die, DW_AT_data_bit_offset, cu);
- /* Only use the attributes if they make sense together. */
- std::optional<ULONGEST> bit_offset;
- if (attr == nullptr)
- bit_offset = 0;
- else if (attr->form_is_constant ())
- {
- bit_offset = attr->unsigned_constant ();
- if (bit_offset.has_value ()
- && *bit_offset + real_bit_size > 8 * type->length ())
- bit_offset.reset ();
- }
- if (bit_offset.has_value ())
- {
- TYPE_MAIN_TYPE (type)->type_specific.int_stuff.bit_size
- = real_bit_size;
- if (attr != nullptr)
- TYPE_MAIN_TYPE (type)->type_specific.int_stuff.bit_offset
- = *bit_offset;
- }
- }
+ TYPE_MAIN_TYPE (type)->type_specific.int_stuff.bit_size = *bit_size;
+ TYPE_MAIN_TYPE (type)->type_specific.int_stuff.bit_offset = offset;
}
}