[Since this gcc problem affects gdb, I'm sending this to both lists] [Warning, long mail. But the actual description isn't that long, just the testcases are.]
Hi, a specific test in the GDB testsuite (namespace.exp) contains tests on variables within anonymous namespaces. When compiling the testcases under g++ 4.2, all these tests fail. The same tests pass successfully when built with gcc 4.1. I reproduced it on a native i686-pc-linux-gnu and on a cross i686-pc-linux-gnu-x-mips64-elf. The below testcases are generated using the native toolchain. The reason for the GDB FAILs is two-fold. First of all, the following code fails to generate any useful code for the symbol `b' in the anonymous namespace when building under 4.2: cat > x1.cc << EOF namespace A { int a = 1; } namespace { int b = 2; } EOF $ g++ -S x1.cc -o- .file "x1.cc" .globl _ZN1A1aE .data .align 4 .type _ZN1A1aE, @object .size _ZN1A1aE, 4 _ZN1A1aE: .long 1 .ident "GCC: (GNU) 4.2.1 20070516 (prerelease) (GNUPro 07r1) (Based on: GCC 4.2, BINUTILS 2.17, GDB 6.6)" .section .note.GNU-stack,"",@progbits The symbol b just doesn't show up. One could think that it has been intentionally optimized away, which would make sort of sense, given that symbols in the anonymous namespace are compilation unit local and the symbol b is never referenced. However, there's something weird here. Consider the next example which consists only of the anonymous namespace: cat > x2.cc << EOF namespace { int b = 2; } EOF $ g++ -S x2.cc -o- .file "x2.cc" .data .align 4 .type _ZN34_GLOBAL__N_x2.cc_00000000_8E6B23431bE, @object .size _ZN34_GLOBAL__N_x2.cc_00000000_8E6B23431bE, 4 _ZN34_GLOBAL__N_x2.cc_00000000_8E6B23431bE: .long 2 .ident "GCC: (GNU) 4.2.1 20070516 (prerelease) (GNUPro 07r1) (Based on: GCC 4.2, BINUTILS 2.17, GDB 6.6)" .section .note.GNU-stack,"",@progbits Suddenly the symbol b shows up. b and the anonymous namespace are still compilation unit local, so why the difference? The next testcase is the shortest possible approximation for the GDB testcase namespace.exp. The symbol b is referenced the same way as the symbols in the actual GDB testcase: cat > x3.cc << EOF namespace A { int a = 1; } namespace { int b = 2; int foo () { b; } } EOF $ g++ -S x3.cc -o- .file "x3.cc" .text .align 2 .type _ZN19_GLOBAL__N__ZN1A1aE3fooEv, @function _ZN19_GLOBAL__N__ZN1A1aE3fooEv: .LFB2: pushl %ebp .LCFI0: movl %esp, %ebp .LCFI1: popl %ebp ret .LFE2: .size _ZN19_GLOBAL__N__ZN1A1aE3fooEv, .-_ZN19_GLOBAL__N__ZN1A1aE3fooEv .globl __gxx_personality_v0 .globl _ZN1A1aE .data .align 4 .type _ZN1A1aE, @object .size _ZN1A1aE, 4 _ZN1A1aE: .long 1 .ident "GCC: (GNU) 4.2.1 20070516 (prerelease) (GNUPro 07r1) (Based on: GCC 4.2, BINUTILS 2.17, GDB 6.6)" .section .note.GNU-stack,"",@progbits Ok, so there has been code generated for the function foo and the function foo has a mangled name. There hasn't been code generated for b, though, even though the symbol is referenced. Shouldn't that only happen when some -O option has been given? Now, let's generate an object file with additional debug information: $ g++ -g -c x3.cc -o x3.o $ nm x3.o 00000000 t _ZN19_GLOBAL__N__ZN1A1aE3fooEv 00000000 G _ZN1A1aE U __gxx_personality_v0 The symbol table has a mangled name for the function foo, the symbol b doesn't show up. This was to be expected from the above generated assembler code. What about foo and b in the debug information? $ readelf -wi x3.o The section .debug_info contains: Compilation Unit @ offset 0x0: Length: 248 Version: 2 Abbrev Offset: 0 Pointer Size: 4 <0><b>: Abbrev Number: 1 (DW_TAG_compile_unit) DW_AT_producer : GNU C++ 4.2.1 20070516 (prerelease) (GNUPro 07r1) (Based on: GCC 4.2, BINUTILS 2.17, GDB 6.6) DW_AT_language : 4 (C++) DW_AT_name : x3.cc DW_AT_comp_dir : /home/corinna/tests DW_AT_low_pc : 0 DW_AT_high_pc : 0x5 DW_AT_stmt_list : 0 <1><91>: Abbrev Number: 2 (DW_TAG_namespace) DW_AT_sibling : <ad> <2><96>: Abbrev Number: 3 (DW_TAG_subprogram) DW_AT_name : foo DW_AT_decl_file : 1 DW_AT_decl_line : 6 DW_AT_type : <b4> DW_AT_declaration : 1 <2><a2>: Abbrev Number: 4 (DW_TAG_variable) DW_AT_name : b DW_AT_decl_file : 1 DW_AT_decl_line : 5 DW_AT_type : <b4> DW_AT_declaration : 1 <1><ad>: Abbrev Number: 5 (DW_TAG_imported_module) DW_AT_decl_file : 1 DW_AT_decl_line : 4 DW_AT_import : <91> <1><b4>: Abbrev Number: 6 (DW_TAG_base_type) DW_AT_byte_size : 4 DW_AT_encoding : 5 (signed) DW_AT_name : int <1><bb>: Abbrev Number: 7 (DW_TAG_subprogram) DW_AT_specification: <96> DW_AT_low_pc : 0 DW_AT_high_pc : 0x5 DW_AT_frame_base : 0 (location list) <1><cc>: Abbrev Number: 8 (DW_TAG_variable) DW_AT_specification: <a2> DW_AT_const_value : 2 <1><d2>: Abbrev Number: 9 (DW_TAG_namespace) DW_AT_name : A DW_AT_decl_file : 1 DW_AT_decl_line : 1 DW_AT_sibling : <f0> <2><db>: Abbrev Number: 10 (DW_TAG_variable) DW_AT_name : a DW_AT_decl_file : 1 DW_AT_decl_line : 2 DW_AT_MIPS_linkage_name: _ZN1A1aE DW_AT_type : <b4> DW_AT_external : 1 DW_AT_declaration : 1 <1><f0>: Abbrev Number: 11 (DW_TAG_variable) DW_AT_specification: <db> DW_AT_location : 5 byte block: 3 0 0 0 0 (DW_OP_addr: 0) So, we have an entry for function foo, but the mangled name (the DW_AT_MIPS_linkage_name row) is missing. This is bad. The function foo is not known as function foo in the symbol table, but as _ZN19_GLOBAL__N__ZN1A1aE3fooEv. OTOH, in the debug information the mangled name doesn't show up. This means, the connection between the symbol table and the debug information is broken. GDB can't figure out that foo in the debug information and _ZN19_GLOBAL__N__ZN1A1aE3fooEv in the symbol table are actually the same symbol. Interestingly, even though b does neither exist in the data section, nor in the symbol table, b shows up in the .debug_info section. It also has no mangled name attached, but in this testcase, it doesn't matter. However, let's create a testcase in which b actually exists: $ cat > x4.cc << EOF namespace A { int a = 1; } namespace { int b = 2; } int foo (int i) { b = i; } EOF $ g++ -S x4.cc -o- .file "x4.cc" .text .align 2 .globl _Z3fooi .type _Z3fooi, @function _Z3fooi: .LFB2: pushl %ebp .LCFI0: movl %esp, %ebp .LCFI1: movl 8(%ebp), %eax movl %eax, _ZN19_GLOBAL__N__ZN1A1aE1bE popl %ebp ret .LFE2: .size _Z3fooi, .-_Z3fooi .globl __gxx_personality_v0 .globl _ZN1A1aE .data .align 4 .type _ZN1A1aE, @object .size _ZN1A1aE, 4 _ZN1A1aE: .long 1 .align 4 .type _ZN19_GLOBAL__N__ZN1A1aE1bE, @object .size _ZN19_GLOBAL__N__ZN1A1aE1bE, 4 _ZN19_GLOBAL__N__ZN1A1aE1bE: .long 2 .ident "GCC: (GNU) 4.2.1 20070516 (prerelease) (GNUPro 07r1) (Based on: GCC 4.2, BINUTILS 2.17, GDB 6.6)" .section .note.GNU-stack,"",@progbits Now the symbol b exists and is created with a mangled name. When creating an object file, b shows up in the symbol table with its mangled name: $ g++ -g -c x4.cc -o x4.o $ nm x4.o 00000000 T _Z3fooi 00000004 g _ZN19_GLOBAL__N__ZN1A1aE1bE 00000000 G _ZN1A1aE U __gxx_personality_v0 Looks good. And the debug information? $ readelf -wi x4.o The section .debug_info contains: Compilation Unit @ offset 0x0: Length: 273 Version: 2 Abbrev Offset: 0 Pointer Size: 4 <0><b>: Abbrev Number: 1 (DW_TAG_compile_unit) DW_AT_producer : GNU C++ 4.2.1 20070516 (prerelease) (GNUPro 07r1) (Based on: GCC 4.2, BINUTILS 2.17, GDB 6.6) DW_AT_language : 4 (C++) DW_AT_name : x4.cc DW_AT_comp_dir : /home/corinna/tests DW_AT_low_pc : 0 DW_AT_high_pc : 0xd DW_AT_stmt_list : 0 <1><91>: Abbrev Number: 2 (DW_TAG_namespace) DW_AT_sibling : <a1> <2><96>: Abbrev Number: 3 (DW_TAG_variable) DW_AT_name : b DW_AT_decl_file : 1 DW_AT_decl_line : 5 DW_AT_type : <d9> DW_AT_declaration : 1 <1><a1>: Abbrev Number: 4 (DW_TAG_imported_module) DW_AT_decl_file : 1 DW_AT_decl_line : 4 DW_AT_import : <91> <1><a8>: Abbrev Number: 5 (DW_TAG_subprogram) DW_AT_external : 1 DW_AT_name : foo DW_AT_decl_file : 1 DW_AT_decl_line : 7 DW_AT_MIPS_linkage_name: _Z3fooi DW_AT_type : <d9> DW_AT_low_pc : 0 DW_AT_high_pc : 0xd DW_AT_frame_base : 0 (location list) DW_AT_sibling : <d9> <2><cc>: Abbrev Number: 6 (DW_TAG_formal_parameter) DW_AT_name : i DW_AT_decl_file : 1 DW_AT_decl_line : 7 DW_AT_type : <d9> DW_AT_location : 2 byte block: 91 0 (DW_OP_fbreg: 0) <1><d9>: Abbrev Number: 7 (DW_TAG_base_type) DW_AT_byte_size : 4 DW_AT_encoding : 5 (signed) DW_AT_name : int <1><e0>: Abbrev Number: 8 (DW_TAG_variable) DW_AT_specification: <96> DW_AT_location : 5 byte block: 3 4 0 0 0 (DW_OP_addr: 4) <1><eb>: Abbrev Number: 9 (DW_TAG_namespace) DW_AT_name : A DW_AT_decl_file : 1 DW_AT_decl_line : 1 DW_AT_sibling : <109> <2><f4>: Abbrev Number: 10 (DW_TAG_variable) DW_AT_name : a DW_AT_decl_file : 1 DW_AT_decl_line : 2 DW_AT_MIPS_linkage_name: _ZN1A1aE DW_AT_type : <d9> DW_AT_external : 1 DW_AT_declaration : 1 <1><109>: Abbrev Number: 8 (DW_TAG_variable) DW_AT_specification: <f4> DW_AT_location : 5 byte block: 3 0 0 0 0 (DW_OP_addr: 0) b shows up in .debug_info, now expectedly so. But again it shows up without a DW_AT_MIPS_linkage_name row. So, in this testcase GDB again has no chance to recognize this b in the .debug_info and _ZN19_GLOBAL__N__ZN1A1aE1bE in the symbol table meaning the same symbol. IMHO, this is a bug in g++. The mangled name in DW_AT_MIPS_linkage_name is required so that GDB can correctly recognize mangled c++ symbols. Corinna -- Corinna Vinschen Cygwin Project Co-Leader Red Hat