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.
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).
(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.
(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...
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.