0

Is it normal to have multiple entries for a single method listed out by nm? I ran the following:

nm -C myObjectFile.o | grep MyObject::

and received the following:

... stuff...
... stuff...
0000027e0 T MyObject::MyObject(MyDepend*)
0000027e0 T MyObject::MyObject(MyDepend*)
000000030 T MyObject::~MyObject()
000000000 T MyObject::~MyObject()
000000000 T MyObject::~MyObject()
000000060 T non-virtual thunk to MyObject::~MyObject()
000000020 T non-virtual thunk to MyObject::~MyObject()

This seems wrong to me. Does it seem wrong to you? If so, can you elaborate why it is wrong and what could cause it? If it's correct only under certain circumstances, then I'll explain more about the issue that has me looking at the nm output and we can go from there.

DavidZemon
  • 501
  • 5
  • 21
  • I think it is something on the nm, because the address are the same – Lefsler Jun 29 '15 at 03:28
  • I had a small typo in one of the lines. Fixed now. The address of the first destructor is non-zero and the other two are zero. Not odd to you? – DavidZemon Jun 29 '15 at 03:31

1 Answers1

2

In some cases the demangler will demangle different inputs to the same output. This can be mildly confusing at times but is done, I think, because in other cases it is less confusing; for example the demangler is used by gdb and this approach lets breakpoints on constructors do the right thing without additional effort by the user. Maybe some improvement is possible here with some thought and work.

Anyway, here is a simple example:

class K
{
  K ();
  virtual ~K();
};

K::K() { }
K::~K() { }

Compiling with -g and then running nm -C shows results similar to yours:

$ nm -C q.o
         U operator delete(void*)
0000000000000000 T K::K()
0000000000000000 T K::K()
0000000000000048 T K::~K()
0000000000000018 T K::~K()
0000000000000018 T K::~K()
0000000000000000 V typeinfo for K
0000000000000000 V typeinfo name for K
0000000000000000 V vtable for K
         U vtable for __cxxabiv1::__class_type_info

But let's see what happens if we run plain nm:

$ nm q.o
         U _ZdlPv
0000000000000000 T _ZN1KC1Ev
0000000000000000 T _ZN1KC2Ev
0000000000000048 T _ZN1KD0Ev
0000000000000018 T _ZN1KD1Ev
0000000000000018 T _ZN1KD2Ev
0000000000000000 V _ZTI1K
0000000000000000 V _ZTS1K
0000000000000000 V _ZTV1K
         U _ZTVN10__cxxabiv117__class_type_infoE

Here we can see more clearly that the underlying symbols are different.

From this we can go to the C++ ABI that GCC follows; in particular to the section about mangling constructors and destructors. For historical reasons this is called the "Itanium" ABI, but really it is used (perhaps with minor variants) on all platforms.

This section explains the meanings of the names, though you'd have to dig deeper into the document to fully understand. The basic idea is that, in the implementation of C++, there is a need for different entry points to constructors and destructors; and this is done by providing different symbols for the different entry points.

Tom Tromey
  • 21,507
  • 2
  • 45
  • 63
  • Thanks for the detailed answer. This certainly helps and I couldn't find anyone else that had run into this. – DavidZemon Jun 29 '15 at 18:35