简体   繁体   中英

Library load error when compiled with -fvisibility=hidden in Linux

We face an issue with our shared library linked statically with OpenSSL. The library is used in Apache HTTP Server.Although we have compiled our shared library statically with OpenSSL, it was using system OpenSSL library path, which the web server was using for https (web server SSL). We could reverse this behavior and force the https to use our OpenSSL library by setting LD_LIBRARY_PATH. But this is not what we want. We want Apache HTTP Server to use its own OpenSSL library and our SSL module (loaded on Apache) to use its own version of OpenSSL libraries. This we could not achieve and hence we followed the compiler option mentioned in the below link to control the visibility of symbols hoping it may fix the problem. (we are not doing wrapper shared library)

https://wiki.openssl.org/index.php/Android#Wrapper_Shared_Objects

g++ SSlModule.cpp -fPIC -shared -I/usr/local/ssl/include -fvisibility=hidden -Wl,--exclude-libs,ALL \
-Wl,-Bstatic -lcrypto -lssl -L/usr/local/ssl/lib -o SSLModule.so -Wl,-Bdynamic

The new shared library gives the error “undefined symbol OPENSSL_sk_num” while starting Apache HTTP Server. Can someone suggest any solution to our problem?

SOLUTION:

Drepper's paper pointed by Basile Starynkevitch was quite useful. Finally we have successfully compiled our module statically linked to OpenSSL

Detailing the main steps.

1)Used -Wl,-z,defs option. Then it was reporting many errors. Hence I have used a Makefile. Our module actually contained more than just a.cpp file

2)Used linker option --exclude-libs and excluded libssl.a and libcrypto.a from the export

3)Used -fvisbility=hidden flag in make file so that some of the symbols were made hidden

4)Used attribute ((visibility ("default"))) for exported functions The output shared library was still exporting two symbols for which it was reading from the global scope

5)Statically linked against OpenSSL

As a special use case we have used the flag RTLD_NOW| RTLD_DEEPBIND(second argument to dlopen) so that our library reads from local scope. RTLD_DEEPBIND flag is to be used in rare use cases as per Drepper's post. So we will not include this in our general solution to all customers.

We face an issue with our shared library linked statically with OpenSSL.

This static linking into a shared library a bad idea on Linux , both technically and perhaps even legally. But I am not a lawyer. Read Program Library HowTO and Linkers and Loaders

For the technical reasons, understand that a shared library on Linux practically needs to be position-independent-code (PIC) because of ASLR . See also vdso(7) , execve(2) , syscalls(2) , credentials(7) . Every Linux program except /sbin/init (and a few others related to systemd and udev or modprobe ) is started by execve which often would run ld.so(8) .

Drepper's paper How to write shared libraries explains that in details.

Read also Advanced Linux Programming and see kernelnewbies.org

Your user would be annoyed too. Use strace(1) and ltrace(1) and gdb(1) to understand what is going on. See also this draft report (explaining interesting facts about GCC compilers ).

And some open source licenses discourage static linking into a shared library. Check with your lawyer and perhaps with the FSF , and the copyright owners of OpenSSL .

At the very least, recompile OpenSSL from its source code into PIC code and object files .

NB: Android is sort-of a Linux system. It runs a Linux kernel .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM