diff options
author | Tom Tromey <tromey@adacore.com> | 2021-08-20 10:05:10 -0600 |
---|---|---|
committer | Tom Tromey <tromey@adacore.com> | 2021-09-24 09:29:09 -0600 |
commit | 6ad036d703099508c388038b57c77a8f7aaffb1d (patch) | |
tree | 72713be9603f7a609a6adfd96b3bed39f577f6c1 | |
parent | fbd6ddfdbf6c41fed3f355e278f68e8e0433ad0d (diff) | |
download | fsf-binutils-gdb-6ad036d703099508c388038b57c77a8f7aaffb1d.zip fsf-binutils-gdb-6ad036d703099508c388038b57c77a8f7aaffb1d.tar.gz fsf-binutils-gdb-6ad036d703099508c388038b57c77a8f7aaffb1d.tar.bz2 |
Fix handling of DW_AT_data_bit_offset
A newer version of GCC will now emit member locations using just
DW_AT_data_bit_offset, like:
<3><14fe>: Abbrev Number: 1 (DW_TAG_member)
<14ff> DW_AT_name : (indirect string, offset: 0x215e): nb_bytes
<1503> DW_AT_decl_file : 1
<1503> DW_AT_decl_line : 10
<1504> DW_AT_decl_column : 7
<1505> DW_AT_type : <0x150b>
<1509> DW_AT_bit_size : 31
<150a> DW_AT_data_bit_offset: 64
whereas earlier versions would emit something like:
<3><164f>: Abbrev Number: 7 (DW_TAG_member)
<1650> DW_AT_name : (indirect string, offset: 0x218d): nb_bytes
<1654> DW_AT_decl_file : 1
<1655> DW_AT_decl_line : 10
<1656> DW_AT_decl_column : 7
<1657> DW_AT_type : <0x165f>
<165b> DW_AT_byte_size : 4
<165c> DW_AT_bit_size : 31
<165d> DW_AT_bit_offset : 1
<165e> DW_AT_data_member_location: 8
That is, DW_AT_data_member_location is not emitted any more. This is
a change due to the switch to DWARF 5 by default.
This change pointed out an existing bug in gdb, namely that the
attr_to_dynamic_prop depends on the presence of
DW_AT_data_member_location. This patch moves the handling of
DW_AT_data_bit_offset into handle_data_member_location, and updates
attr_to_dynamic_prop to handle this new case.
A new test case is included. This test fails with GCC 11, but passes
with an earlier version of GCC.
-rw-r--r-- | gdb/dwarf2/read.c | 49 | ||||
-rw-r--r-- | gdb/testsuite/gdb.ada/packed_record.exp | 47 | ||||
-rw-r--r-- | gdb/testsuite/gdb.ada/packed_record/pr.adb | 35 |
3 files changed, 114 insertions, 17 deletions
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c index 3c81ac6..d2501c9 100644 --- a/gdb/dwarf2/read.c +++ b/gdb/dwarf2/read.c @@ -14420,14 +14420,14 @@ dwarf2_access_attribute (struct die_info *die, struct dwarf2_cu *cu) } } -/* Look for DW_AT_data_member_location. Set *OFFSET to the byte - offset. If the attribute was not found return 0, otherwise return - 1. If it was found but could not properly be handled, set *OFFSET - to 0. */ +/* Look for DW_AT_data_member_location or DW_AT_data_bit_offset. Set + *OFFSET to the byte offset. If the attribute was not found return + 0, otherwise return 1. If it was found but could not properly be + handled, set *OFFSET to 0. */ static int -handle_data_member_location (struct die_info *die, struct dwarf2_cu *cu, - LONGEST *offset) +handle_member_location (struct die_info *die, struct dwarf2_cu *cu, + LONGEST *offset) { struct attribute *attr; @@ -14451,15 +14451,25 @@ handle_data_member_location (struct die_info *die, struct dwarf2_cu *cu, return 1; } + else + { + attr = dwarf2_attr (die, DW_AT_data_bit_offset, cu); + if (attr != nullptr) + { + *offset = attr->constant_value (0); + return 1; + } + } return 0; } -/* Look for DW_AT_data_member_location and store the results in FIELD. */ +/* Look for DW_AT_data_member_location or DW_AT_data_bit_offset and + store the results in FIELD. */ static void -handle_data_member_location (struct die_info *die, struct dwarf2_cu *cu, - struct field *field) +handle_member_location (struct die_info *die, struct dwarf2_cu *cu, + struct field *field) { struct attribute *attr; @@ -14501,6 +14511,12 @@ handle_data_member_location (struct die_info *die, struct dwarf2_cu *cu, else dwarf2_complex_location_expr_complaint (); } + else + { + attr = dwarf2_attr (die, DW_AT_data_bit_offset, cu); + if (attr != nullptr) + SET_FIELD_BITPOS (*field, attr->constant_value (0)); + } } /* Add an aggregate field to the field list. */ @@ -14562,7 +14578,7 @@ dwarf2_add_field (struct field_info *fip, struct die_info *die, } /* Get bit offset of field. */ - handle_data_member_location (die, cu, fp); + handle_member_location (die, cu, fp); attr = dwarf2_attr (die, DW_AT_bit_offset, cu); if (attr != nullptr && attr->form_is_constant ()) { @@ -14609,10 +14625,6 @@ dwarf2_add_field (struct field_info *fip, struct die_info *die, - bit_offset - FIELD_BITSIZE (*fp))); } } - attr = dwarf2_attr (die, DW_AT_data_bit_offset, cu); - if (attr != NULL) - SET_FIELD_BITPOS (*fp, (FIELD_BITPOS (*fp) - + attr->constant_value (0))); /* Get name of field. */ fieldname = dwarf2_name (die, cu); @@ -14673,7 +14685,7 @@ dwarf2_add_field (struct field_info *fip, struct die_info *die, else if (die->tag == DW_TAG_inheritance) { /* C++ base class field. */ - handle_data_member_location (die, cu, fp); + handle_member_location (die, cu, fp); FIELD_BITSIZE (*fp) = 0; fp->set_type (die_type (die, cu)); FIELD_NAME (*fp) = fp->type ()->name (); @@ -18388,6 +18400,9 @@ attr_to_dynamic_prop (const struct attribute *attr, struct die_info *die, if (target_attr == NULL) target_attr = dwarf2_attr (target_die, DW_AT_data_member_location, target_cu); + if (target_attr == nullptr) + target_attr = dwarf2_attr (target_die, DW_AT_data_bit_offset, + target_cu); if (target_attr == NULL) { const char *name = var_decl_name (target_die, target_cu); @@ -18431,11 +18446,11 @@ attr_to_dynamic_prop (const struct attribute *attr, struct die_info *die, } break; case DW_AT_data_member_location: + case DW_AT_data_bit_offset: { LONGEST offset; - if (!handle_data_member_location (target_die, target_cu, - &offset)) + if (!handle_member_location (target_die, target_cu, &offset)) return 0; baton = XOBNEW (obstack, struct dwarf2_property_baton); diff --git a/gdb/testsuite/gdb.ada/packed_record.exp b/gdb/testsuite/gdb.ada/packed_record.exp new file mode 100644 index 0000000..c5573c7 --- /dev/null +++ b/gdb/testsuite/gdb.ada/packed_record.exp @@ -0,0 +1,47 @@ +# Copyright 2021 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +load_lib "ada.exp" + +if { [skip_ada_tests] } { return -1 } + +standard_ada_testfile pr + +foreach_with_prefix scenario {all minimal} { + set flags [list debug additional_flags=-fgnat-encodings=$scenario] + + if {[gdb_compile_ada "${srcfile}" "${binfile}" executable $flags] != ""} { + return -1 + } + + clean_restart ${testfile} + + set bp_location [gdb_get_line_number "STOP" ${testdir}/pr.adb] + runto "pr.adb:$bp_location" + + set test "print var" + gdb_test_multiple $test $test { + -re " = \\(length => 11, length_t => 23, bytes => 13, msg => hello, val => \"abcdefghijk\"\\)\[\r\n\]+$gdb_prompt $" { + pass $test + } + -re " = .*more than max-value-size.*\[\r\n\]+$gdb_prompt $" { + # GNAT >= 12.0 has the needed fix here. + if {$scenario == "minimal" && ![test_compiler_info {gcc-1[2-9]-*}]} { + setup_kfail "minimal encodings" *-*-* + } + fail $test + } + } +} diff --git a/gdb/testsuite/gdb.ada/packed_record/pr.adb b/gdb/testsuite/gdb.ada/packed_record/pr.adb new file mode 100644 index 0000000..7abfda9 --- /dev/null +++ b/gdb/testsuite/gdb.ada/packed_record/pr.adb @@ -0,0 +1,35 @@ +-- Copyright 2021 Free Software Foundation, Inc. +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see <http://www.gnu.org/licenses/>. + +procedure pr is + + type Report is (Hello, Goodbye); + + type Response (Length : integer ) is record + Length_t : Integer; + Bytes : Natural; + Msg : Report; + Val : String(1..Length); + end record; + + pragma pack (Response); + + Var : Response(11) := (11, 23, 13, Hello, "abcdefghijk"); + +begin + + null; -- STOP + +end pr; |