This is the mail archive of the
gdb@sourceware.org
mailing list for the GDB project.
gcc 4.2 breaks debugging anonymous namespace
- From: Corinna Vinschen <vinschen at redhat dot com>
- To: gdb at sourceware dot org, gcc at gcc dot gnu dot org
- Date: Fri, 25 May 2007 14:00:35 +0200
- Subject: gcc 4.2 breaks debugging anonymous namespace
[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