Skip to content

Commit baea7fc

Browse files
committed
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: llvm/llvm-project#137123 This patch reworks the base type size logic a bit to handle this situation.
1 parent a153733 commit baea7fc

File tree

3 files changed

+59
-30
lines changed

3 files changed

+59
-30
lines changed

gdb/dwarf2/read.c

Lines changed: 38 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -13634,7 +13634,6 @@ read_base_type (struct die_info *die, struct dwarf2_cu *cu)
1363413634
struct type *type;
1363513635
struct attribute *attr;
1363613636
ULONGEST encoding = 0;
13637-
int bits = 0;
1363813637
const char *name;
1363913638

1364013639
attr = dwarf2_attr (die, DW_AT_encoding, cu);
@@ -13644,9 +13643,33 @@ read_base_type (struct die_info *die, struct dwarf2_cu *cu)
1364413643
if (value.has_value ())
1364513644
encoding = *value;
1364613645
}
13646+
1364713647
attr = dwarf2_attr (die, DW_AT_byte_size, cu);
13648+
std::optional<ULONGEST> byte_size;
13649+
if (attr != nullptr)
13650+
byte_size = attr->unsigned_constant ();
13651+
attr = dwarf2_attr (die, DW_AT_bit_size, cu);
13652+
std::optional<ULONGEST> bit_size;
1364813653
if (attr != nullptr)
13649-
bits = attr->unsigned_constant ().value_or (0) * TARGET_CHAR_BIT;
13654+
bit_size = attr->unsigned_constant ();
13655+
13656+
attr = dwarf2_attr (die, DW_AT_data_bit_offset, cu);
13657+
std::optional<ULONGEST> bit_offset;
13658+
if (attr != nullptr)
13659+
bit_offset = attr->unsigned_constant ();
13660+
13661+
int bits = 0;
13662+
if (byte_size.has_value ())
13663+
bits = TARGET_CHAR_BIT * *byte_size;
13664+
else if (bit_size.has_value ())
13665+
bits = align_up (*bit_size, 8);
13666+
else
13667+
{
13668+
/* No size, so arrange for an error type. */
13669+
complaint (_("DW_TAG_base_type has neither bit- nor byte-size"));
13670+
encoding = (ULONGEST) -1;
13671+
}
13672+
1365013673
name = dwarf2_full_name (nullptr, die, cu);
1365113674
if (!name)
1365213675
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)
1379213815

1379313816
type->set_endianity_is_not_default (not_default);
1379413817

13795-
if (TYPE_SPECIFIC_FIELD (type) == TYPE_SPECIFIC_INT)
13818+
/* If both a byte size and bit size were provided, then that means
13819+
that not every bit in the object contributes to the value. */
13820+
if (TYPE_SPECIFIC_FIELD (type) == TYPE_SPECIFIC_INT
13821+
&& byte_size.has_value ()
13822+
&& bit_size.has_value ())
1379613823
{
13797-
attr = dwarf2_attr (die, DW_AT_bit_size, cu);
13798-
if (attr != nullptr && attr->form_is_constant ())
13824+
/* DWARF says: If this attribute is omitted a default data bit
13825+
offset of zero is assumed. */
13826+
ULONGEST offset = bit_offset.value_or (0);
13827+
13828+
/* Only use the attributes if they make sense together. */
13829+
if (*bit_size + offset <= 8 * type->length ())
1379913830
{
13800-
unsigned real_bit_size = attr->unsigned_constant ().value_or (0);
13801-
if (real_bit_size >= 0 && real_bit_size <= 8 * type->length ())
13802-
{
13803-
attr = dwarf2_attr (die, DW_AT_data_bit_offset, cu);
13804-
/* Only use the attributes if they make sense together. */
13805-
std::optional<ULONGEST> bit_offset;
13806-
if (attr == nullptr)
13807-
bit_offset = 0;
13808-
else if (attr->form_is_constant ())
13809-
{
13810-
bit_offset = attr->unsigned_constant ();
13811-
if (bit_offset.has_value ()
13812-
&& *bit_offset + real_bit_size > 8 * type->length ())
13813-
bit_offset.reset ();
13814-
}
13815-
if (bit_offset.has_value ())
13816-
{
13817-
TYPE_MAIN_TYPE (type)->type_specific.int_stuff.bit_size
13818-
= real_bit_size;
13819-
if (attr != nullptr)
13820-
TYPE_MAIN_TYPE (type)->type_specific.int_stuff.bit_offset
13821-
= *bit_offset;
13822-
}
13823-
}
13831+
TYPE_MAIN_TYPE (type)->type_specific.int_stuff.bit_size = *bit_size;
13832+
TYPE_MAIN_TYPE (type)->type_specific.int_stuff.bit_offset = offset;
1382413833
}
1382513834
}
1382613835

gdb/testsuite/gdb.dwarf2/intbits.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ unsigned char be30_1_off[4] = { 0x80, 0, 0, 2 };
4141
here, to catch any situation where gdb tries to use the memory. */
4242
unsigned char u32_0[4] = { 0xff, 0xff, 0xff, 0xff };
4343

44+
/* An 8 bit slot holding a 3 bit value. */
45+
unsigned char just_bit_0 = 5;
46+
4447
int
4548
main (void)
4649
{

gdb/testsuite/gdb.dwarf2/intbits.exp

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ Dwarf::assemble ${asm_file} {
3636
{DW_AT_language @DW_LANG_C_plus_plus}
3737
} {
3838
declare_labels i7_type u1_type u17_type u31_type \
39-
u31_1_type u32_0_type u0_0_type be30_1_type
39+
u31_1_type u32_0_type u0_0_type be30_1_type just_bit_type
4040

4141
i7_type: DW_TAG_base_type {
4242
{DW_AT_encoding @DW_ATE_signed}
@@ -167,6 +167,20 @@ Dwarf::assemble ${asm_file} {
167167
{DW_AT_location {DW_OP_addr [gdb_target_symbol "u32_0"]}
168168
SPECIAL_expr}
169169
}
170+
171+
just_bit_type: DW_TAG_base_type {
172+
{DW_AT_encoding @DW_ATE_unsigned}
173+
{DW_AT_name "just_bit_type"}
174+
{DW_AT_bit_size 3 DW_FORM_udata}
175+
}
176+
177+
DW_TAG_variable {
178+
{DW_AT_name "v_just_bit"}
179+
{DW_AT_type :${just_bit_type}}
180+
{DW_AT_external 1 DW_FORM_flag}
181+
{DW_AT_location {DW_OP_addr [gdb_target_symbol "just_bit_0"]}
182+
SPECIAL_expr}
183+
}
170184
}
171185
}
172186
}
@@ -197,3 +211,6 @@ gdb_test "x/4xb &v_u32_1_off" ":\t0x0e\t0x00\t0x00\t0x00"
197211
gdb_test "print v_be30_1_off" "= 1"
198212
gdb_test "print v_be30_1_off = 7" " = 7"
199213
gdb_test "x/4xb &v_be30_1_off" ":\t0x00\t0x00\t0x00\t0x0e"
214+
215+
gdb_test "print/x v_just_bit" " = 0x5"
216+
gdb_test "print/x (just_bit_type) 5" " = 0x5"

0 commit comments

Comments
 (0)