dlopen and C++ libraries (vtables)
Matthew Chapman
enofish@gmail.com
Thu Jul 21 09:08:00 GMT 2011
Hi Carlos,
Thanks for your time and brain space.
On Thu, Jul 21, 2011 at 2:20 AM, Carlos O'Donell
<carlos@systemhalted.org> wrote:
> On 7/20/2011 9:39 AM, Matthew Chapman wrote:
>> During relocation processing, the dynamic linker decides:
>> 3199: file=./libmine.so [0]; needed by
>> /usr/lib64/libxerces-c.so [0] (relocation dependency)
>> (_ZTVN11xercesc_2_713XSerializableE)
>
> Why do you call this a false circular dependency?
>
> You can have two DSO, each with a weak symbol, and the dynamic linker
> gets to choose whichever one it wants.
I agree that technically it can choose whichever one it wants - but
now the link maps have both "libmine.so requires libxerces-c.so
[explicit dependency]" and "libxerces-c.so requires libmine.so
[relocation dependency]" which is a problem when it comes to sorting
the fini calls (see below for test case). I call this a false
dependency because libxerces-c is a system library which does not
really depend on libmine.so that I wrote later. The dependency was
introduced by the linker via its choice of weak symbols.
>> The problem then is that - due to the false dependency - the libraries
>> then sometimes get unloaded in the wrong order, causing symbol
>> resolution errors (or worse) in destructors. I can come up with a
>> test case if needed.
>
> You need to prove they are unloaded in the wrong order.
> You need to provide a reduced test case that shows the behaviour.
I'm attaching a test case. Sorry it's a bit larger than I'd like, but
I've cut it down as much as I could.
Dependency tree:
main or dlmain
\- libplugin [*]
|- libmine
| \- libcplusplus
\- libresolv [*]
[*] libplugin and libresolv are just dummy placeholders because
_dl_sort_fini is quite sensitive to the initial order of the link map,
and this helps reproduce the problem.
libmine and libcplusplus are two C++ libraries that both contain the
same weak vtables (to trigger the problem) and globals that do
reference counting (to demonstrate the wrong fini order).
$ make
$ ./main
libcplusplus_refcnt
libcplusplus_refcnt: refcnt++
libcplusplus_refcnt: refcnt--
~libcplusplus_refcnt
$ ./dlmain
libcplusplus_refcnt
libcplusplus_refcnt: refcnt++
~libcplusplus_refcnt
oops, destroying libcplusplus_refcnt with refcnt > 0
$ LD_DEBUG=files ./dlmain
...
25507: file=./libmine.so [0]; needed by ./libcplusplus.so
[0] (relocation dependency)
...
25507: calling fini: ./libcplusplus.so [0]
25507:
~libcplusplus_refcnt
oops, destroying libcplusplus_refcnt with refcnt > 0
25507:
25507: calling fini: ./libmine.so [0]
25507:
25507: ./libmine.so: error: symbol lookup error: undefined
symbol: _ZN19libcplusplus_refcnt6decrefEv (fatal)
Thanks,
Matt
-------------- next part --------------
A non-text attachment was scrubbed...
Name: libdependtest-1.0.tar.gz
Type: application/x-gzip
Size: 1344 bytes
Desc: not available
URL: <http://sourceware.org/pipermail/libc-help/attachments/20110721/5f14ae55/attachment.bin>
More information about the Libc-help
mailing list