diff options
author | Joel Brobecker <brobecker@adacore.com> | 2014-01-22 18:40:20 +0400 |
---|---|---|
committer | Joel Brobecker <brobecker@adacore.com> | 2014-02-26 10:39:25 -0800 |
commit | 55426c9d52fdba13df81fcce1b18469cc0362e50 (patch) | |
tree | c754eece02be804b0477cd4966a00b252a409cce /gdb/testsuite/gdb.dwarf2 | |
parent | 0dcb32c3ae07166fc3b04eb4a86ae93ecd87bfb8 (diff) | |
download | gdb-55426c9d52fdba13df81fcce1b18469cc0362e50.zip gdb-55426c9d52fdba13df81fcce1b18469cc0362e50.tar.gz gdb-55426c9d52fdba13df81fcce1b18469cc0362e50.tar.bz2 |
DWARF: Set enum type "flag_enum" and "unsigned" flags at type creation.
Consider the following Ada code:
-- An array whose index is an enumeration type with 128 enumerators.
type Enum_T is (Enum_000, Enum_001, [...], Enum_128);
type Table is array (Enum_T) of Boolean;
When the compiler is configured to generate pure DWARF debugging info,
trying to print type Table's description yields:
ptype pck.table
type = array (enum_000 .. -128) of boolean
The expected output was:
ptype pck.table
type = array (enum_000 .. enum_128) of boolean
The DWARF debugging info for our array looks like this:
<1><44>: Abbrev Number: 5 (DW_TAG_array_type)
<45> DW_AT_name : pck__table
<50> DW_AT_type : <0x28>
<2><54>: Abbrev Number: 6 (DW_TAG_subrange_type)
<55> DW_AT_type : <0x5c>
<59> DW_AT_lower_bound : 0
<5a> DW_AT_upper_bound : 128
The array index type is, by construction with the DWARF standard,
a subrange of our enumeration type, defined as follow:
<2><5b>: Abbrev Number: 0
<1><5c>: Abbrev Number: 7 (DW_TAG_enumeration_type)
<5d> DW_AT_name : pck__enum_t
<69> DW_AT_byte_size : 1
<2><6b>: Abbrev Number: 8 (DW_TAG_enumerator)
<6c> DW_AT_name : pck__enum_000
<7a> DW_AT_const_value : 0
[etc]
Therefore, while processing these DIEs, the array index type ends
up being a TYPE_CODE_RANGE whose target type is our enumeration type.
But the problem is that we read the upper bound as a negative value
(-128), which is then used as is by the type printer to print the
array upper bound. This negative value explains the "-128" in the
output.
To understand why the range type's upper bound is read as a negative
value, one needs to look at how it is determined, in read_subrange_type:
orig_base_type = die_type (die, cu);
base_type = check_typedef (orig_base_type);
[... high is first correctly read as 128, but then ...]
if (!TYPE_UNSIGNED (base_type) && (high & negative_mask))
high |= negative_mask;
The negative_mask is applied, here, because BASE_TYPE->FLAG_UNSIGNED
is not set. And the reason for that is because the base_type was only
partially constructed during the call to die_type. While the enum
is constructed on the fly by read_enumeration_type, its flag_unsigned
flag is only set later on, while creating the symbols corresponding to
the enum type's enumerators (see process_enumeration_scope), after
we've already finished creating our range type - and therefore too
late.
My first naive attempt at fixing this problem consisted in extracting
the part in process_enumeration_scope which processes all enumerators,
to generate the associated symbols, but more importantly set the type's
various flags when necessary. However, this does not always work well,
because we're still in the subrange_type's scope, and it might be
different from the scope where the enumeration type is defined.
So, instead, what this patch does to fix the issue is to extract
from process_enumeration_scope the part that determines whether
the enumeration type should have the flag_unsigned and/or the
flag_flag_enum flags set. It turns out that, aside from the code
implementing the loop, this part is fairly independent of the symbol
creation. With that part extracted, we can then use it at the end
of our enumeration type creation, to produce a type which should now
no longer need any adjustment.
Once the enumeration type produced is correctly marked as unsigned,
the subrange type's upper bound is then correctly read as an unsigned
value, therefore giving us an upper bound of 128 instead of -128.
gdb/ChangeLog:
* dwarf2read.c (update_enumeration_type_from_children): New
function, mostly extracted from process_structure_scope.
(read_enumeration_type): Call update_enumeration_type_from_children.
(process_enumeration_scope): Do not set THIS_TYPE's flag_unsigned
and flag_flag_enum fields.
gdb/testsuite/ChangeLog:
* gdb.dwarf2/arr-subrange.c, gdb.dwarf2/arr-subrange.exp: New files.
Diffstat (limited to 'gdb/testsuite/gdb.dwarf2')
-rw-r--r-- | gdb/testsuite/gdb.dwarf2/arr-subrange.c | 20 | ||||
-rw-r--r-- | gdb/testsuite/gdb.dwarf2/arr-subrange.exp | 99 |
2 files changed, 119 insertions, 0 deletions
diff --git a/gdb/testsuite/gdb.dwarf2/arr-subrange.c b/gdb/testsuite/gdb.dwarf2/arr-subrange.c new file mode 100644 index 0000000..978ef8d --- /dev/null +++ b/gdb/testsuite/gdb.dwarf2/arr-subrange.c @@ -0,0 +1,20 @@ +/* Copyright 2014 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/>. */ + +int +main (void) +{ + return 0; +} diff --git a/gdb/testsuite/gdb.dwarf2/arr-subrange.exp b/gdb/testsuite/gdb.dwarf2/arr-subrange.exp new file mode 100644 index 0000000..9847c13 --- /dev/null +++ b/gdb/testsuite/gdb.dwarf2/arr-subrange.exp @@ -0,0 +1,99 @@ +# Copyright 2014 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 dwarf.exp + +# This test can only be run on targets which support DWARF-2 and use gas. +if {![dwarf2_support]} { + return 0 +} + +standard_testfile arr-subrange.c arr-subrange-dw.S + +# Make some DWARF for the test. +set asm_file [standard_output_file $srcfile2] +Dwarf::assemble $asm_file { + cu {} { + DW_TAG_compile_unit { + {DW_AT_language @DW_LANG_Ada95} + {DW_AT_name foo.adb} + {DW_AT_comp_dir /tmp} + {DW_AT_low_pc 0x1000} + {DW_AT_high_pc 0x2000} + } { + declare_labels boolean_label typedef_label array_label enum_label + + boolean_label: DW_TAG_base_type { + {DW_AT_byte_size 1 DW_FORM_sdata} + {DW_AT_encoding @DW_ATE_boolean} + {DW_AT_name boolean} + } + + typedef_label: DW_TAG_typedef { + {DW_AT_name pck__table} + {DW_AT_type :$array_label} + } + + array_label: DW_TAG_array_type { + {DW_AT_name pck__table} + {DW_AT_type :$boolean_label} + } { + DW_TAG_subrange_type { + {DW_AT_type :$enum_label} + {DW_AT_lower_bound 0 DW_FORM_data1} + {DW_AT_upper_bound 128 DW_FORM_data1} + } + } + + enum_label: DW_TAG_enumeration_type { + {DW_AT_name pck__enum_t} + {DW_AT_byte_size 1 DW_FORM_sdata} + } { + DW_TAG_enumerator { + {DW_AT_name pck__enum_000} + {DW_AT_const_value 0 DW_FORM_sdata} + } + DW_TAG_enumerator { + {DW_AT_name pck__enum_001} + {DW_AT_const_value 1 DW_FORM_sdata} + } + DW_TAG_enumerator { + {DW_AT_name pck__enum_128} + {DW_AT_const_value 128 DW_FORM_sdata} + } + } + } + } +} + +if {[gdb_compile ${srcdir}/${subdir}/${srcfile} ${binfile}1.o \ + object {nodebug}] != ""} { + return -1 +} + +if {[gdb_compile $asm_file ${binfile}2.o object {nodebug}] != ""} { + return -1 +} + +if {[gdb_compile [list ${binfile}1.o ${binfile}2.o] \ + "${binfile}" executable {}] != ""} { + return -1 +} + +clean_restart ${testfile} + +gdb_test_no_output "set language ada" + +gdb_test "ptype pck.table" \ + "type = array \\(enum_000 \\.\\. enum_128\\) of boolean" |