[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Bug ld/10326] New: globbing in linker script doesn't match C++ vtable/t

From: thiago at kde dot org
Subject: [Bug ld/10326] New: globbing in linker script doesn't match C++ vtable/typeinfo/etc.
Date: 24 Jun 2009 13:27:54 -0000

When writing a linker script to control the versioning/exporting/unexporting of
C++ symbols, the globbing provided in the linker script doesn't match some of
the automatically-generated symbols by the C++ ABI. I have noticed that this
applies to the vtable, the VTT, construction vtables, typeinfo, typeinfo names
and all manners of thunks.

Suppose the following code:
$ cat a.cpp
struct Padding { virtual ~Padding() {} };

struct PublicA
    virtual ~PublicA();
    virtual PublicA *a();

struct PublicB: Padding, PublicA
    virtual PublicB *a();

struct PublicC: virtual PublicA
    virtual PublicC *a();

PublicA::~PublicA() { }
PublicA *PublicA::a() { return 0; }
PublicB *PublicB::a() { return 0; }
PublicC *PublicC::a() { return 0; }

If we compile it into a shared library:
$ g++ -shared -o a.so a.cpp

The dynamic symbol table will be like this:
$ paste <(nm -D --defined a.so) <(nm -DC --defined a.so | cut -b11-) | grep
00000cee T _ZN7PublicA1aEv       PublicA::a()
00000cc8 T _ZN7PublicAD0Ev       PublicA::~PublicA()
00000ca2 T _ZN7PublicAD1Ev       PublicA::~PublicA()
00000c7c T _ZN7PublicAD2Ev       PublicA::~PublicA()
00000d00 T _ZN7PublicB1aEv       PublicB::a()
00000ef0 W _ZN7PublicBD0Ev       PublicB::~PublicB()
00000ea0 W _ZN7PublicBD1Ev       PublicB::~PublicB()
00000d1a T _ZN7PublicC1aEv       PublicC::a()
00000e4c W _ZN7PublicCD0Ev       PublicC::~PublicC()
00000df0 W _ZN7PublicCD1Ev       PublicC::~PublicC()
0000108c V _ZTI7PublicA  typeinfo for PublicA
00001060 V _ZTI7PublicB  typeinfo for PublicB
00001030 V _ZTI7PublicC  typeinfo for PublicC
00001094 V _ZTS7PublicA  typeinfo name for PublicA
00001080 V _ZTS7PublicB  typeinfo name for PublicB
00001048 V _ZTS7PublicC  typeinfo name for PublicC
00000fc8 V _ZTT7PublicC  VTT for PublicC
00001008 V _ZTV7PublicA  vtable for PublicA
00000fe0 V _ZTV7PublicB  vtable for PublicB
00000fa0 V _ZTV7PublicC  vtable for PublicC
00000d4d T _ZTch0_h4_N7PublicB1aEv       covariant return thunk to PublicB::a()
00000d24 T _ZTch0_v0_n20_N7PublicC1aEv   covariant return thunk to PublicC::a()
00000cf8 T _ZTchn4_h4_N7PublicB1aEv      covariant return thunk to PublicB::a()
00000d0a T _ZTcv0_n16_v0_n20_N7PublicC1aEv       covariant return thunk to
00000ee8 W _ZThn4_N7PublicBD0Ev  non-virtual thunk to PublicB::~PublicB()
00000e98 W _ZThn4_N7PublicBD1Ev  non-virtual thunk to PublicB::~PublicB()
00000e3c W _ZTv0_n12_N7PublicCD0Ev       virtual thunk to PublicC::~PublicC()
00000de0 W _ZTv0_n12_N7PublicCD1Ev       virtual thunk to PublicC::~PublicC()

Now suppose we use a linker script to hide the internal symbols in our library,
but export only those that we want to:
$ cat a.script
    global: extern "C++" { Public*; };
    local: *;

If we compile it:
$ g++ -shared -o a.so a.cpp a.script

The symbol table is:
$ paste <(nm -D --defined a.so) <(nm -DC --defined a.so | cut -b11-) | grep
000007fe T _ZN7PublicA1aEv       PublicA::a()
000007d8 T _ZN7PublicAD0Ev       PublicA::~PublicA()
000007b2 T _ZN7PublicAD1Ev       PublicA::~PublicA()
0000078c T _ZN7PublicAD2Ev       PublicA::~PublicA()
00000810 T _ZN7PublicB1aEv       PublicB::a()
00000a00 W _ZN7PublicBD0Ev       PublicB::~PublicB()
000009b0 W _ZN7PublicBD1Ev       PublicB::~PublicB()
0000082a T _ZN7PublicC1aEv       PublicC::a()
0000095c W _ZN7PublicCD0Ev       PublicC::~PublicC()
00000900 W _ZN7PublicCD1Ev       PublicC::~PublicC()

To export those symbols, I am forced to know of their existence and the
mangling that they acquire. And it's not possible to match them effectively
with simple globbing (regexp would be necessary at least). And note that spaces
in symbol names are also not possible to match without wildcards in the linker
scripts, which makes it impossible to match " for Public*" reliably.

One way I can think of to solve this problem would be to change the demangling
(the pretty name) of those symbols to place the class name leftmost. For
0000108c V _ZTI7PublicA  PublicA::.typeinfo
00001060 V _ZTI7PublicB  PublicB::.typeinfo
00001030 V _ZTI7PublicC  PublicC::.typeinfo
00001094 V _ZTS7PublicA  PublicA::.typeinfo name
00001080 V _ZTS7PublicB  PublicB::.typeinfo name
00001048 V _ZTS7PublicC  PublicC::.typeinfo name
00000fc8 V _ZTT7PublicC  PublicC::.VTT
00001008 V _ZTV7PublicA  PublicA::.vtable
00000fe0 V _ZTV7PublicB  PublicB::.vtable
00000fa0 V _ZTV7PublicC  PublicC::.vtable
00000d4d T _ZTch0_h4_N7PublicB1aEv       PublicB::a() [covariant return thunk]
00000d24 T _ZTch0_v0_n20_N7PublicC1aEv   PublicC::a() [covariant return thunk]
00000cf8 T _ZTchn4_h4_N7PublicB1aEv      PublicB::a() [covariant return thunk]
00000d0a T _ZTcv0_n16_v0_n20_N7PublicC1aEv       PublicC::a() [covariant return
00000ee8 W _ZThn4_N7PublicBD0Ev  PublicB::~PublicB() [non-virtual thunk]
00000e98 W _ZThn4_N7PublicBD1Ev  PublicB::~PublicB() [non-virtual thunk]
00000e3c W _ZTv0_n12_N7PublicCD0Ev       PublicC::~PublicC() [virtual thunk]
00000de0 W _ZTv0_n12_N7PublicCD1Ev       PublicC::~PublicC() [virtual thunk]

(For the thunks, it may be a good idea to match to the base encoding, so that
exporting "PublicC::a()" exports all thunks associated with it)

           Summary: globbing in linker script doesn't match C++
           Product: binutils
           Version: 2.19
            Status: NEW
          Severity: normal
          Priority: P2
         Component: ld
        AssignedTo: unassigned at sources dot redhat dot com
        ReportedBy: thiago at kde dot org
                CC: bug-binutils at gnu dot org
 GCC build triplet: i586-manbo-linux-gnu
  GCC host triplet: i586-manbo-linux-gnu
GCC target triplet: i586-manbo-linux-gnu


------- You are receiving this mail because: -------
You are on the CC list for the bug, or are watching someone who is.

reply via email to

[Prev in Thread] Current Thread [Next in Thread]