From 6ad395a7a64c9b49dab32a9178a8a07a96c17885 Mon Sep 17 00:00:00 2001 From: Joel Brobecker Date: Fri, 20 Mar 2015 13:57:36 -0400 Subject: [PATCH] Problem printing record with array whose upper bound is record component Consider the following declarations... type Obj_T (Selected_Flights_Length : Natural) is record Selected_Flights : Flights.List.T (1 .. Selected_Flights_Length); end record; Broken : Obj_T; ... which defines a variable named "broken" which is a discrimated record where broken.Selected_Flights is an array whose upper bound is stored in the record's Selected_Flights_Length component. Trying to print the value of that object currently fails: (gdb) print broken cannot find reference address for offset property Looking at the debugging info, we see that variable "Broken" is a reference... <1><8e3>: Abbrev Number: 21 (DW_TAG_const_type) <8e4> DW_AT_type : <0x8e8> <1><8e8>: Abbrev Number: 22 (DW_TAG_reference_type) <8e9> DW_AT_byte_size : 8 <8ea> DW_AT_type : <0x7ec> ... to ... <1><7ec>: Abbrev Number: 12 (DW_TAG_structure_type) <7ed> DW_AT_name : (indirect string, offset: 0xc6d): reprod__obj_t <7f1> DW_AT_decl_file : 2 <7f2> DW_AT_decl_line : 15 <7f3> DW_AT_GNAT_descriptive_type: <0x87e> <7f7> DW_AT_sibling : <0x87e> ... which has 2 members, the first one being the discriminant... <2><7fb>: Abbrev Number: 9 (DW_TAG_member) <7fc> DW_AT_name : (indirect string, offset: 0xc98): selected_flights_length <800> DW_AT_decl_file : 2 <801> DW_AT_decl_line : 15 <802> DW_AT_type : <0x807> <806> DW_AT_data_member_location: 0 ... and the second one being the one that causes trouble... <2><83d>: Abbrev Number: 9 (DW_TAG_member) <83e> DW_AT_name : (indirect string, offset: 0xd17): selected_flights <842> DW_AT_decl_file : 2 <843> DW_AT_decl_line : 17 <844> DW_AT_type : <0x815> <848> DW_AT_data_member_location: 4 The second field's type is an array.... <2><815>: Abbrev Number: 14 (DW_TAG_array_type) <816> DW_AT_name : (indirect string, offset: 0xd2f): reprod__obj_t__T5sP <81a> DW_AT_GNAT_descriptive_type: <0x7e1> <81e> DW_AT_type : <0x748> <822> DW_AT_sibling : <0x830> ... whose uppper bound is a reference to <0x7fb>... <3><826>: Abbrev Number: 15 (DW_TAG_subrange_type) <827> DW_AT_type : <0x830> <82b> DW_AT_upper_bound : <0x7fb> <3><82f>: Abbrev Number: 0 Because the upper bound is dynamic, we try to resolve it. As it happens, the upper-bound resolution for this range type works fine. What breaks is when we try to resolve this range type's target type, which is: <2><830>: Abbrev Number: 16 (DW_TAG_subrange_type) <831> DW_AT_upper_bound : <0x7fb> <835> DW_AT_name : (indirect string, offset: 0xc7b): reprod__obj_t__T4s___XDLU_1__selected_flights_length <839> DW_AT_type : <0x766> <83d> DW_AT_artificial : 1 It is actually pretty much the same as the first subrange type, so you might ask why this is causing trouble, when the resolution of the previous DIE worked like a charm??? Well, for that, we need to backtrack a bit, and notice that, ahead of the DW_TAG_structure_type's DIE, there is the following DIE: <1><7e1>: Abbrev Number: 6 (DW_TAG_typedef) <7e2> DW_AT_name : (indirect string, offset: 0xbae): reprod__obj_t__T5s <7e6> DW_AT_decl_file : 2 <7e7> DW_AT_decl_line : 17 <7e8> DW_AT_type : <0x849> ... and that DIE references an array type... <2><849>: Abbrev Number: 14 (DW_TAG_array_type) <84a> DW_AT_name : (indirect string, offset: 0xbae): reprod__obj_t__T5s <84e> DW_AT_GNAT_descriptive_type: <0x864> <852> DW_AT_type : <0x748> <856> DW_AT_sibling : <0x864> ... whose subrange is... <3><85a>: Abbrev Number: 15 (DW_TAG_subrange_type) <85b> DW_AT_type : <0x830> <85f> DW_AT_upper_bound : <0x7fb> ... where the subrange's base type is the DW_TAG_subrange_type DIE that is causing problem. In summary, we process the typedef first, which causes us to process the second subrange BEFORE we process the struct DIE itself, and therefore the struct's discriminent (DW_TAG_member #1). As a result, while trying to handle the reference to that DW_TAG_member #1 as the upper bound of the second range type, we do... case DW_AT_data_member_location: { [...] baton->referenced_type = get_die_type (target_die->parent, target_cu); ... where target_die->parent (DW_TAG_member #1) hasn't been processed yet, and thus get_die_type returns NULL. This is what later causes us problems trying to find the right address to use as the base address for our field, which then triggers the error message we are seeing. This patch fixes the issue by calling read_type_die instead of get_die_type. If the DIE has already been processed, then this is the same as get_die_type. If not, the it'll get the parent die to be read, and then get its type. gdb/ChangeLog: * dwarf2read.c (attr_to_dynamic_prop) : Use read_type_die isntead of get_die_type. Tested on x86_64-linux, no regression. No testcase, unfortunately, as the reproducer was given to us by a customer, and it's been otherwise surprisingly difficult to reproduce the same error outside of that reproducer. --- gdb/ChangeLog | 6 ++++++ gdb/dwarf2read.c | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 4422ada..a08544d 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,11 @@ 2015-05-08 Joel Brobecker + * dwarf2read.c (attr_to_dynamic_prop) + : Use read_type_die isntead of + get_die_type. + +2015-05-08 Joel Brobecker + * ada-lang.c (ada_convert_actual): Add handling of formals passed inside an aligner type. diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index 4982922..8d9a394 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -14851,8 +14851,8 @@ attr_to_dynamic_prop (const struct attribute *attr, struct die_info *die, return 0; baton = obstack_alloc (obstack, sizeof (*baton)); - baton->referenced_type = get_die_type (target_die->parent, - target_cu); + baton->referenced_type = read_type_die (target_die->parent, + target_cu); baton->offset_info.offset = offset; baton->offset_info.type = die_type (target_die, target_cu); prop->data.baton = baton; -- 2.7.4