This is the mail archive of the gdb@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]