Bug 20426 - gdb does not interpret DWARF annotating imported units fully
Summary: gdb does not interpret DWARF annotating imported units fully
Status: RESOLVED FIXED
Alias: None
Product: gdb
Classification: Unclassified
Component: gdb (show other bugs)
Version: 7.11.1
: P2 normal
Target Milestone: 8.3
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2016-08-01 12:25 UTC by Richard Biener
Modified: 2018-09-05 10:58 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:
Project(s) to access:
ssh public key:


Attachments
partially linked executable (1.26 KB, application/x-object)
2016-08-01 12:25 UTC, Richard Biener
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Richard Biener 2016-08-01 12:25:53 UTC
Created attachment 9412 [details]
partially linked executable

For

int main(int argc, char **argv)
{
  void *a[argc-1];
  for (int i = 1; i < argc; ++i)
    a[i-1] = argv[i];
  return 0;
}

when compiled with GCC LTO in a private branch produces the attached
debug info.  gdb is not able to pick up DW_AT_upper_bound for the VLA
type correctly.  GCC emits it like

 <0><b>: Abbrev Number: 1 (DW_TAG_compile_unit)
    <c>   DW_AT_producer    : (indirect string, offset: 0x44): GNU C11 7.0.0 201
60801 (experimental) [trunk revision 221942] -mtune=generic -march=x86-64 -g -fl
to
    <10>   DW_AT_language    : 12       (ANSI C99)
    <11>   DW_AT_name        : t.c
    <15>   DW_AT_comp_dir    : (indirect string, offset: 0xa): /abuild/rguenther
/obj-early-lto-debug-g/gcc
 <1><19>: Abbrev Number: 2 (DW_TAG_subprogram)
    <1a>   DW_AT_external    : 1
    <1a>   DW_AT_name        : (indirect string, offset: 0x3f): main
...
 <2><3e>: Abbrev Number: 4 (DW_TAG_variable)
    <3f>   DW_AT_type        : <0x72>
    <43>   DW_AT_artificial  : 1
...
 <2><43>: Abbrev Number: 5 (DW_TAG_variable)
    <44>   DW_AT_name        : a
    <46>   DW_AT_decl_file   : 1
    <47>   DW_AT_decl_line   : 3
    <48>   DW_AT_type        : <0x79>
...
 <1><79>: Abbrev Number: 10 (DW_TAG_array_type)
    <7a>   DW_AT_type        : <0x8c>
    <7e>   DW_AT_sibling     : <0x8c>
 <2><82>: Abbrev Number: 11 (DW_TAG_subrange_type)
    <83>   DW_AT_type        : <0x72>
    <87>   DW_AT_upper_bound : <0x3e>
 <2><8b>: Abbrev Number: 0
...
 <0><9a>: Abbrev Number: 1 (DW_TAG_compile_unit)
    <9b>   DW_AT_producer    : 
    <9c>   DW_AT_language    : 12       (ANSI C99)
    <9d>   DW_AT_low_pc      : 0x0
    <a5>   DW_AT_high_pc     : 0xfd
    <ad>   DW_AT_stmt_list   : 0x0
 <1><b1>: Abbrev Number: 2 (DW_TAG_imported_unit)
    <b2>   DW_AT_import      : <0xb>    [Abbrev Number: 1]
 <1><b6>: Abbrev Number: 3 (DW_TAG_subprogram)
    <b7>   DW_AT_abstract_origin: <0x19>
    <bb>   DW_AT_low_pc      : 0x0
    <c3>   DW_AT_high_pc     : 0xfd
    <cb>   DW_AT_frame_base  : 1 byte block: 9c         (DW_OP_call_frame_cfa)
    <cd>   DW_AT_GNU_all_call_sites: 1
...
 <2><df>: Abbrev Number: 5 (DW_TAG_variable)
    <e0>   DW_AT_abstract_origin: <0x3e>
    <e4>   DW_AT_location    : 2 byte block: 91 60      (DW_OP_fbreg: -32)
 <2><e7>: Abbrev Number: 5 (DW_TAG_variable)
    <e8>   DW_AT_abstract_origin: <0x43>
    <ec>   DW_AT_location    : 4 byte block: 91 a0 7f 6         (DW_OP_fbreg: -96; DW_OP_deref)
...

where nothing in the DWARF standard suggests that the above wouldn't complete
DW_AT_upper_bound properly (it doesn't matter whether abstract origin or
specification is used).  It would be a shame if the importing CU needs
to pull in the array type its subrange type just to adjust its upper bound.

Note that it doesn't seem to matter (for gdb) whether the importing CU
refers to the imported DIEs via DW_AT_abstract_origin or DW_AT_specification.
Comment 1 Mark Wielaard 2016-08-29 11:06:54 UTC
I admit to not know anything about how gdb implements this. But looking at the DIE tree I think it is not surprising the location of the upper_bound cannot be found.

In other DWARF consumers I have worked with following the specification or abstract origin attribute is used to augment the current DIE under consideration, not the other way around. To make it work the other way around a DWARF consumer would have to keep track of all references through DW_AT_specification or DW_AT_abstract_origin to a specific DIE.

In this case what a DWARF consumer probably would do is find the the subprogram [b6] based on the address (main function) that it covers. If the user wants to inspect the variable "a" it will find [e7] (with the name given through the DW_AT_specification to [43]). Now this variable DIE [e7] will then be passed to some function to resolve it (find the location expression). Given such a variable DIE is normally enough to resolve all relevant location information. In this case it points to the array_type [79] and finally the upper_bound, which points to the variable described at [3e]. Following the DIE reference chain there is nothing indicating that the missing location expression for that variable can be found through the [df] DIE in the other compilation unit.

It is not immediately clear to me which heuristic needs to be used to deduce that the [df] DIE specification attribute pointing to [e3] needs to be remembered as back reference (assuming it has even has been seen yet by DWARF reader, if the variable and formal_parameter were in a different order in the tree we might not even have seen it yet). Or how the consumer can be sure it has seen and collected all such back-references needed (assuming we do want the DWARF consumer to be as efficient as possible by reading as little of the DIE tree as possible).
Comment 2 Mark Wielaard 2016-08-29 11:17:33 UTC
(In reply to Mark Wielaard from comment #1)
> In other DWARF consumers I have worked with following the specification or
> abstract origin attribute is used to augment the current DIE under
> consideration, not the other way around. To make it work the other way
> around a DWARF consumer would have to keep track of all references through
> DW_AT_specification or DW_AT_abstract_origin to a specific DIE.

And I think it is not a 1-on-1 relationship. There could be multiple DIEs pointing to the same abstract_origin (maybe the function got cloned). So the consumer might not even know which one to pick.
Comment 3 Richard Biener 2016-08-30 08:11:38 UTC
(In reply to Mark Wielaard from comment #2)
> (In reply to Mark Wielaard from comment #1)
> > In other DWARF consumers I have worked with following the specification or
> > abstract origin attribute is used to augment the current DIE under
> > consideration, not the other way around. To make it work the other way
> > around a DWARF consumer would have to keep track of all references through
> > DW_AT_specification or DW_AT_abstract_origin to a specific DIE.
> 
> And I think it is not a 1-on-1 relationship. There could be multiple DIEs
> pointing to the same abstract_origin (maybe the function got cloned). So the
> consumer might not even know which one to pick.

That's true.  I guess I can even end up with such a case.  I expected the
consumer to pick the annotation in the same context (probably a bit
optimistic).

I can follow your reasoning about how dwarf consumers work.

It's somewhat unfortunate that for my specific use case I have to replicate
all non-abstract parts of a DIE - esp. that I need to adjust the reference
to the type of 'a'.  I wonder what DWARF says about duplicate DW_AT_type
(one in the concrete and one "different" in the abstract instance) - do
both DW_AT_type complement each other or does the concrete one "hide" the
abstract one.  That is, can I omit DW_AT_type from the DW_TAG_array_type
in the concrete instance and expect it to be picked from the abstract
instance?

Now thinking about how to implement this at all given I have no way to
recreate the type DIEs at the point I can produce the location for
the upper bound...
Comment 4 Tom de Vries 2018-09-05 10:58:56 UTC
With commit "[gdb/exp] Handle DW_OP_GNU_variable_value refs to abstract dies"  ( https://sourceware.org/ml/gdb-cvs/2018-09/msg00016.html ), I think this issue should be resolved.