On Wed, Mar 7, 2012 at 9:41 PM, Timothy Pearson
<kb9vqf(a)pearsoncomputing.net> wrote:
<snip>
> Yes! I'll pick an obvious example,
KHTML. I would like to replace the
broken KHTML engine with Webkit using Qt4.
Problem is, I can't link a
Qt4
> library into a TDE library or program due to
symbol conflicts. Even if
you trick the compiler and linker, the program will
crash at runtime
because the C++ runtime will not know which symbols (Qt3 or Qt4) to use
^^^
when function names and static members have the same
name.
> But that is what the linker does. Isn't it?
...
Actually the linker creates a reference to a "mangled" symbol--see
http://en.wikipedia.org/wiki/Name_mangling#Name_mangling_in_C.2B.2B
Let's take a simple example, qWarning. This becomes _Z8qWarningPKcz in
libqt-mt.so.3.3.8 (nm -D /usr/lib/libqt-mt.so | grep qWarning), and
_Z8qWarningPKcz in /usr/lib/libQtCore.so (nm -D /usr/lib/libQtCore.so |
grep qWarning). If my program references Z8qWarningPKcz, which library
will the symbol resolver choose at runtime? They are not binary
compatible with each other, and when the symbol resolver chooses the wrong
one at runtime (which it will do quite often) the entire program will
crash.
Ok, you are telling about dynamic (or runtime) linking then. That is
not 'C++ runtime'. Saying this had lead me to misunderstanding,
because C++ runtime is exception and type handling.
Well, I understand now that the problem is a bit more complex. But
I've found two solution candidates so far! Obvious one and cunning
one. The obvious is to compile Qt4 in different namespace
(-qtnamespace option).
The cunning one is to make run-time loader to correctly do symbol
mapping. Since ld.so loader yet doesn't support direct binding
(
http://en.wikipedia.org/wiki/Direct_binding) this can be done with
dlopen(RTLD_DEEPBIND) at SO init time. I've put some example in bug
900. Please, look at lib_vinegret.tar.gz.
You'll find in 'lib_vinegret' dir the simplified matter of problem:
lib_v1.c: Qt3 library
lib_v1_user.c: Most TDE code
lib_v2.c: Qt4 library
lib_v2_user.c: TDE code that wants to use Qt4
When you intermix 'lib_v1' and 'lib_v2' in one executable you will get
'lib_v2_user' executing 'lib_v1' instead of 'lib_v2'.
Please, type 'make', then './run.sh' to look at the results:
This is v1 user
This is v1 library!
This is v2 user
This is v1 library!
You can examine why this happened in generated rtld.log. The
interesting lines are:
4885: object=./lib_v1_user.so [0]
4885: scope 0: ./executable ./lib_v1_user.so
./lib_v2_user.so /lib/x86_64-linux-gnu/libc.so.6 ./lib_v1.so
./lib_v2.so /lib64/ld-linux-x86-64.so.2
4885:
4885: object=./lib_v2_user.so [0]
4885: scope 0: ./executable ./lib_v1_user.so
./lib_v2_user.so /lib/x86_64-linux-gnu/libc.so.6 ./lib_v1.so
./lib_v2.so /lib64/ld-linux-x86-64.so.2
Note the 'scope 0'. It is same for all objects and called 'global
scope'. The order in this scope shows the actual order of symbol
searches. So the 'lib_function' symbol will be found always from
./lib_v1.so. Further entries in rtld.log confirm that.
Sadly enough, there is no way to force dynamic linker to load
different objects with different lookup scopes. But here comes
RTLD_DEEPBIND to the stage. Please, look at this diff:
http://bugs.pearsoncomputing.net/attachment.cgi?id=468&action=diff
I made some wrapper 'lib_v2_user_scoper' around the code we want to
load with different library. If you run this variant, you should see
this:
This is v1 user
This is v1 library!
This is v2 user
This is v2 library!
This is v1 user
This is v1 library!
This is v2 user
This is v2 library!
Voila! :-)
If per chance you will remove RTLD_DEEPBIND flag you will see the old
flat way of resolution:
This is v1 user
This is v1 library!
This is v2 user
This is v1 library!
This is v1 user
This is v1 library!
This is v2 user
This is v1 library!
Alex
<snip>
I suppose this could be done in more easy way
without renaming.
Not really, see above. :-)
And if you want to work on a "pure" KDE 3.5.10 fork you have that right;
just be aware that you will hit a dead end far before TDE will. ;-)
Tim
---------------------------------------------------------------------
To unsubscribe, e-mail: trinity-devel-unsubscribe(a)lists.pearsoncomputing.net
For additional commands, e-mail: trinity-devel-help(a)lists.pearsoncomputing.net
Read list messages on the web archive:
http://trinity-devel.pearsoncomputing.net/
Please remember not to top-post:
http://trinity.pearsoncomputing.net/mailing_lists/#top-posting