This is the mail archive of the gdb-cvs@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[binutils-gdb] Problem printing record with array whose upper bound is record component


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=6ad395a7a64c9b49dab32a9178a8a07a96c17885

commit 6ad395a7a64c9b49dab32a9178a8a07a96c17885
Author: Joel Brobecker <brobecker@adacore.com>
Date:   Fri Mar 20 13:57:36 2015 -0400

    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)
            <DW_AT_data_member_location>: 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.

Diff:
---
 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  <brobecker@adacore.com>
 
+	* dwarf2read.c (attr_to_dynamic_prop)
+	<DW_AT_data_member_location>: Use read_type_die isntead of
+	get_die_type.
+
+2015-05-08  Joel Brobecker  <brobecker@adacore.com>
+
 	* 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;


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]