GNU C 4.4.0 20090326 (experimental) GDB variables lookup does not match the C code lookup. Similiar C++ code in PR debug/39524 uses DW_TAG_lexical_block. $ gdb -q ./externvar (gdb) l 1 1 #include <stdlib.h> 2 3 int var = 2; 4 5 int 6 main (void) 7 { 8 int var = 1; 9 10 if (var != 1) 11 abort (); 12 13 { 14 extern int var; 15 16 if (var != 2) 17 abort (); 18 } 19 20 return 0; 21 } (gdb) b 16 Breakpoint 1 at 0x4004d2: file externvar.c, line 16. (gdb) r Starting program: /tmp/externvar Breakpoint 1, main () at externvar.c:16 16 if (var != 2) (gdb) p var $1 = 1 (gdb) c Continuing. Program exited normally. (gdb) q ------------------------------------------------------------------------------ < c> DW_AT_producer : (indirect string, offset: 0xe): GNU C 4.4.0 20090326 (experimental) <1><7d>: Abbrev Number: 5 (DW_TAG_subprogram) <7f> DW_AT_name : (indirect string, offset: 0x63): main <8a> DW_AT_low_pc : 0x4004b8 <92> DW_AT_high_pc : 0x4004e9 <2><a2>: Abbrev Number: 6 (DW_TAG_variable) <a3> DW_AT_name : var <a9> DW_AT_type : <0x34> <ad> DW_AT_location : 2 byte block: 91 6c (DW_OP_fbreg: -20) <1><b1>: Abbrev Number: 7 (DW_TAG_variable) <b2> DW_AT_name : var <b8> DW_AT_type : <0x34> <bc> DW_AT_external : 1 <bd> DW_AT_location : 9 byte block: 3 70 8 60 0 0 0 0 0 (DW_OP_addr: 600870) Missing there something like: <2><c0>: Abbrev Number: 6 (DW_TAG_lexical_block) <c1> DW_AT_low_pc : 0x4005b2 <c9> DW_AT_high_pc : 0x4005c2 <3><b1>: Abbrev Number: 7 (DW_TAG_variable) <b2> DW_AT_name : var <b8> DW_AT_type : <0x34> <bc> DW_AT_external : 1 <bd> DW_AT_location : 9 byte block: 3 70 8 60 0 0 0 0 0 (DW_OP_addr: 600870)
As DW_AT_external-DW_TAG_variable in the inner block is incompatible with current GDB http://sourceware.org/ml/gdb-patches/2009-03/msg00595.html the current C++ method of DW_TAG_imported_declaration referencing the file-level DW_AT_external-DW_TAG_variable may be more appropriate.
This seems to be just a C FE problem, C++ FE compiling the exact same testcase gives the expected output (DW_TAG_lexical_block with DW_TAG_variable with DW_AT_external). So IMHO just the C FE should be fixed to handle it like the C++ FE and if there are gdb bugs, they should be fixed in gdb.
Created attachment 17544 [details] gcc44-pr39563.patch Untested fix. The problem with this patch is that DW_AT_decl_file and DW_AT_decl_line of the DW_AT_external DW_TAG_variable and DW_TAG_subprogram DIEs is wrong. Say for: extern void abort (void); int var = 1; int main (void) { int var = 2; if (var != 2) abort (); { extern int var; extern void abort (void); if (var != 1) abort (); { int var = 3; if (var != 3) abort (); { extern int var; extern void abort (void); if (var != 1) abort (); } } } return 0; } for all DW_AT_external DW_TAG_variable DIEs DW_AT_decl_line is 3 and for abort DW_AT_decl_line is the last extern void abort (void) line.
Created attachment 17547 [details] gcc44-pr39563.patch Updated patch that preserves the correct location info for the nested extern decls.
Created attachment 17548 [details] gcc44-pr39563.patch Patch that actually bootstrapped/regtested successfully. Jan, could you please test it with gdb/archer?
No regressions for GDB. GDB requires the extra patch otherwise it still does not work with patched GCC: http://sourceware.org/ml/gdb-patches/2009-03/msg00595.html FYI the patch generates one extra file-scope declaration: int f (void) { extern int var; return var; } < c> DW_AT_producer : (indirect string, offset: 0x0): GNU C 4.5.0 20090328 (experimental) <1><2d>: Abbrev Number: 2 (DW_TAG_subprogram) <2f> DW_AT_name : f [...] <2><50>: Abbrev Number: 3 (DW_TAG_variable) <51> DW_AT_name : var <55> DW_AT_decl_file : 1 <56> DW_AT_decl_line : 1 <57> DW_AT_type : <0x5e> <5b> DW_AT_external : 1 <5c> DW_AT_declaration : 1 [...] <1><65>: Abbrev Number: 3 (DW_TAG_variable) <66> DW_AT_name : var <6a> DW_AT_decl_file : 1 <6b> DW_AT_decl_line : 1 <6c> DW_AT_type : <0x5e> <70> DW_AT_external : 1 <71> DW_AT_declaration : 1
Subject: Bug 39563 Author: jakub Date: Mon Mar 30 14:35:03 2009 New Revision: 145293 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=145293 Log: PR debug/39563 * c-decl.c (struct c_binding): Add locus field. (bind): Add locus argument, set locus field from it. (pop_scope): For b->nested VAR_DECL or FUNCTION_DECL, add a DECL_EXTERNAL copy of b->decl to current BLOCK_VARS. (push_file_scope, pushtag, pushdecl, pushdecl_top_level, implicitly_declare, undeclared_variable, lookup_label, declare_label, c_make_fname_decl, c_builtin_function, c_builtin_function_ext_scope, store_parm_decls_newstyle): Adjust bind callers. Modified: trunk/gcc/ChangeLog trunk/gcc/c-decl.c
Fixed on the trunk.
Fixed in FSF GDB HEAD: http://sourceware.org/ml/gdb-patches/2009-03/threads.html#00595 http://sourceware.org/ml/gdb-patches/2009-04/threads.html#00040 http://sourceware.org/ml/gdb-cvs/2009-04/msg00021.html gdb/ * dwarf2read.c (new_symbol <DW_TAG_variable> <!DW_AT_location> <DW_AT_external>): Create the symbol in local scope. * symtab.h (cu->list_in_scope <LOC_UNRESOLVED>): New comment part. gdb/testsuite/ * gdb.dwarf2/dw2-unresolved-main.c, gdb.dwarf2/dw2-unresolved.S, gdb.dwarf2/dw2-unresolved.exp: New.