This is the mail archive of the gdb@sources.redhat.com 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]

Re: gcc HEAD dwarf-2, synthetic methods no longer public, gdb confused


drow> Is the method code emitted beforehand?  How about afterwards?  I'm
drow> assuming that it is emitted in both cases.  Is it marked .globl before
drow> and after?

Good question; I forgot to mention this.

All of the code is exactly the same before and after.
'diff old.s new.s' says that the differences are only in .debug_info.

The synthetic symbols are .weak and not .globl, with both versions of gcc.
Here are all the .globl and .weak symbols (run through c++filt):

  .globl Empty::Empty[not-in-charge]()
  .globl Empty::Empty[in-charge]()
  .globl Empty::Empty[not-in-charge](Empty const&)
  .globl Empty::Empty[in-charge](Empty const&)
  .globl Empty::operator=(Empty const&)
  .globl Empty::~Empty [not-in-charge]()
  .globl Empty::~Empty [in-charge]()
  .globl Alpha::Alpha[not-in-charge]()
  .globl Alpha::Alpha[in-charge]()
  .globl refer(Alpha*)
	  .weak	Alpha::operator=(Alpha const&)
	  .weak	Alpha::~Alpha [in-charge]()
  .globl foo()
	  .weak	Alpha::Alpha[in-charge](Alpha const&)
  .globl main

class 'Empty' has its own ctor, copy-ctor, assign-op, and dtor.  class
'Alpha' has a data member of type 'Empty' and just a ctor, so that gcc
synthesizes the 'Alpha' copy-ctor, assign-op, and dtor.

The whole source file is appended.
Compiled with 'gcc -gdwarf-2 -S' on native i686-pc-linux-gnu.

drow> This is a longstanding bug; it just seems to happen sometimes.
drow> Probably the order we parse something has changed.
drow> DW_AT_MIPS_linkage_name should die anyway, but GDB currently still
drow> requires it.

Ah, I did some more reading, dwarf2read.c is not as hairy
as it looks.  But lookup_symbol is seriously complicated.

===

The .globl/.weak symbols use fully mangled names.  Of course they must,
for the linker to work!

The symbol for the synthetic copy constructor is _ZN5AlphaC1ERKS_, which
demangles to 'Alpha::Alpha[in-charge](Alpha const&)'.

'maint symbols' says:

  # old gcc HEAD
  [20] t 0x80485e0 _ZN5AlphaC1ERKS_ section .text  Alpha::Alpha(Alpha const&)  synthetic.cc

  # new gcc HEAD
  [20] t 0x80485e0 _ZN5AlphaC1ERKS_ section .text  Alpha::Alpha(Alpha const&)  synthetic.cc

This looks okay to me.  It's always been a .weak non-.globl symbol,
and it's always had a fully mangled name.

===

But 'maint psymbols' reveals some quirks in the partial symbols:

  # old gcc HEAD
  Partial symtab for source file synthetic.cc (object 0x82f93f4)
    Read from object file /berman/home/mec.gnu/gcc/pr-synthetic/22-0710.exe (0x82eb730)
    Global partial symbols:
      `Alpha', struct domain, type, 0x0
      `Alpha', type, 0x0
      `Alpha', function, 0x8048450
      `Alpha', function, 0x8048470
      `Alpha', function, 0x80485e0
      `_ZN5AlphaaSERKS_'  `Alpha::operator=(Alpha const&)', function, 0x804859c
      `~Alpha', function, 0x80485ca
    Static partial symbols:
      ...

  # new gcc HEAD
  Partial symtab for source file synthetic.cc (object 0x82f93b0)
    Read from object file /berman/home/mec.gnu/gcc/pr-synthetic/22-0720.exe (0x82eb730)
    Global partial symbols:
      `Alpha', struct domain, type, 0x0
      `Alpha', type, 0x0
      `Alpha', function, 0x8048450
      `Alpha', function, 0x8048470
    Static partial symbols:
      `operator=', function, 0x804859c
      `~Alpha', function, 0x80485ca
      `Alpha', function, 0x80485e0

In gdb's symbol tables, static partial symbols have higher search
priority than global partial symbols.

With both versions of gcc, the global partial symbols have two psymbols
for the types 'class Alpha' and 'Alpha' and then two psymbols for the
two copies of the user-supplied ctor Alpha::Alpha.  The symbols for the
two ctors are lacking DW_AT_MIPS_linkage_name, so they are named 'Alpha'
instead of 'Alpha::Alpha[not-in-charge]()' and 'Alpha::Alpha[in-charge]()'.

Then there are three synthetic methods: assign-op, copy-ctor, and dtor.
With old gcc HEAD, these are DW_AT_external, and they appear in the
global partial symbols.  With new gcc HEAD, these are not
DW_AT_external, and they appear in the static partial symbols.

Also, the synthetic assign-op lost its DW_AT_MIPS_linkage_name.  The
synthetic copy-ctor and synthetic dtor never had
DW_AT_MIPS_linkage_name.  As it turns out, the synthetic assign-op
is not important to this issue, but I saw the difference in 'diff'
and thought it was importnat.

===

gdb has a complicated search order for symbol names.
The interesting part of the call tree is:

  lookup_symbol_file
    lookup_symbol_static                [2]
    lookup_symbol_aux_block
    lookup_symbol_global
      lookup_symbol_aux_symtabs         [1]
      lookup_symbol_aux_psymtabs
    lookup_possible_namespace_symbol

[1] is the point where gdb finds 'Alpha' with old gcc HEAD.
It finds the global symbol for the type 'Alpha'.

[2] is the point where gdb finds 'Alpha' with new gcc HEAD.
It finds the synthetic copy-ctor named 'Alpha' in the
static partial symbols, which have higher search priority
than global partial symbols.

That's why gdb works with old gcc HEAD.  All five symbols named 'Alpha'
are in the same psymtab and gdb happens to find the right one.

With new gcc HEAD, the synthetic ctor is a static psymbol, so it has
higher priority.  So 'ptype Alpha' finds this symbol and returns the
type of this function.

===

What to do?

It would be helpful if gcc emitted DW_AT_MIPS_linkage_name for
the synthetic symbols.  Mark, can we do this?

It would be helpful if gdb were smarter about symbol names
for ctor's and copy-ctor's, which have the same name as the
class.  Right now, we lose if one of those pops up with
no DW_AT_MIPS_linkage_name.

And I will add a new test program to the test suite for this.

===

#include <stdio.h>

class Empty
{
  public:
    Empty ();
    Empty (const Empty &);
    const Empty & operator= (const Empty &);
    ~Empty ();
};

Empty::Empty ()
{
  printf ("ctor\n");
}

Empty::Empty (const Empty &)
{
  printf ("copy ctor\n");
}

const Empty & Empty::operator= (const Empty & e)
{
  printf ("assignment operator\n");
}

Empty::~Empty ()
{
  printf ("dtor\n");
}

class Alpha
{
  public:
    Alpha ();
  private:
    int a_;
    Empty empty_;
};

Alpha::Alpha ()
  : a_ (117)
{
  ;
}

void refer (Alpha * a)
{
  static Alpha asave;
  asave = *a;
}

void foo ()
{
  Alpha a1;
  Alpha a2 (a1);
  Alpha a3 = a1;
  refer (&a1);
  refer (&a2);
  refer (&a3);
  return;
}

int main ()
{
  foo ();
  return 0;
}


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