The Linux dynamic linker also provides some methods do debug such issues. E.g. you can export LD_DEBUG=bindings
to get lots of information on all symbol bindings. Collect all those outputs in a file, and compare the output in the different scenarios, and you will notice some symbols linking to different files. See the ld.so documentation for more options.
For example, we were tracking down a crash when we linked the TensorFlow into our binary, and also used some embedded Python. We reduced the crash to import hashlib
. It does not crash when not linking TensorFlow. (You find this also being reported here and here.)
With linking TF, I got outputs like this:
2306643: binding file /u/zeyer/.linuxbrew/Cellar/[email protected]/3.11.2_1/lib/python3.11/lib-dynload/_hashlib.cpython-311-x86_64-linux-gnu.so [0] to /u/zeyer/.local/lib/python3.11/site-packages/tensorflow/libtensorflow_framework.so.2 [0]: normal symbol `EVP_MD_size' [OPENSSL_1_1_0]
Just running python -c "import hashlib"
gives me outputs like this:
2307740: binding file /u/zeyer/.linuxbrew/Cellar/[email protected]/3.11.2_1/lib/python3.11/lib-dynload/_hashlib.cpython-311-x86_64-linux-gnu.so [0] to /work/tools/users/zeyer/linuxbrew/lib/libcrypto.so.1.1 [0]: normal symbol `EVP_MD_size' [OPENSSL_1_1_0]
As you see, in the case with TF, it finds those OpenSSL related symbols in libtensorflow_framework.so.2
, in the other case, it finds them in libcrypto.so.1.1
(as it should be).
Our solution here was to add -L/work/tools/users/zeyer/linuxbrew/lib -Wl,-rpath,/work/tools/users/zeyer/linuxbrew/lib -Wl,-no-as-needed -lcrypto
to our linker flags, before we link the TF library. So we enforce that libcrypto.so.1.1
is loaded first. That solves the problem. See here for my compile script.