How to find shared objects loaded during startup of an application? - linux

I know that using dlopen with RLTD_NOLOAD one can find out whether a shared object is already loaded or not. This, however, doesn't seem to work if a so is linked to the executable and loaded by the linker during application startup.
I mean, lets say I have mylib.so and load it with dlopen. Later, if I make dlopen with RLTD_NOLOAD, I get the handle as expected.
However, if I link mylib.so to the application ( -lmylib at the makefile ) dlopen returns NULL.
How can I get a handle to the shared object if it is directly linked to the exec. and not loaded explicitly?
Thanks in Advance

This is way too late, but -
dlopen(NULL, RTLD_LAZY/*Any load option u want*/) will get a handle to the binary. And it is supposed to be able to find any symbol in the binary or shared libs it has loaded. I think that is a good place to start.

Related

LD_PRELOAD to override functions from dynamically loaded library

I'm using a wrapper library to trace functions using LD_PRELOAD which does work when the functions I'm tracing are referenced in the application.
The wrapper library uses dlsym to populate symbols it wraps.
But this is not working if the application doesn't reference functions directly but through dlopen.
Should the wrapper library work with dynamically loaded libraries? If not, is there a way to make it work?
But this is not working if the application doesn't reference functions directly but through dlopen.
If the application performs:
void *h = dlopen("libfoo.so", ...);
void *sym = dlsym(h, "symbol");
then the symbol will be resolved to libfoo.so, regardless of any LD_PRELOADs (and indeed regardless of any other instances of symbol in other already loaded libraries). This is working as intended.
Should the wrapper library work with dynamically loaded libraries?
No.
If not, is there a way to make it work?
Yes, you can make it work. You would need to provide a replacement.so which provides all the symbols which the application looks up in libfoo.so, and then make it so the replacement.so is dlopend()ed by the application.
One way to do that is to rename libfoo.so -> libfoo.so.orig, copy replacement.so -> libfoo.so, and have replacement.so itself dlopen("libfoo.so.orig", ...).
If the application dlopens libfoo.so without absolute path, you may be able to arrange so replacement.so is earlier in the search path, e.g.
mkdir /tmp/replacement
ln -s /path/to/replacement.so /tmp/replacement/liboo.so
LD_LIBRARY_PATH=/tmp/replacement /path/to/a.out
If you go that route, replacement.so would still need to know how to dlopen the original libfoo.so (could use hard-coded absolute path for that).

When a shared library is loaded, is it possible that it references something in the current binary?

Say I have a binary server, and when it's compiled, it's linked from server.c, static_lib.a, and dynamically with dynamic_lib.so.
When server is executed and it loads dynamic_lib.so dynamically, but on the code path, dynamic_lib.so actually expects some symbols from static_lib.a. What I'm seeing is that, dynamic_lib.so pulls in static_lib.so so essentially I have two static_lib in memory.
Let's assume there's no way we can change dynamic_lib.so, because it's a 3rd-party library.
My question is, is it possible to make dynamic_lib.so or ld itself search the current binary first, or even not search for it in ld's path, just use the binary's symbol, or abort.
I tried to find some related docs about it, but it's not easy for noobs about linkers like me :-)
You can not change library to not load static_lib.so but you can trick it to use static_lib.a instead.
By default ld does not export any symbols from executables but you can change this via -rdynamic. This option is quite crude as it exports all static symbols so for finer-grained control you can use -Wl,--dynamic-list (see example use in Clang sources).

Linking to a custom .a from multiple objects

In our build system, we generate multiple .so files (foo.so, bar.so, ...) that are loaded during runtime by the main executable (biz). So the .so files are linked separately.
We also have our own util.a static library, that has some utility functions and global data.
The problem comes when some of the .so want to use util.a data/function, but we can't link each .so to util.a. It's because of the data section: global data must be unique in the program address space. If more than one .so is linked to util.a and has a copy of the data, the program behavior will be very surprising but hard to debug.
We can't link executable (biz) to util.a either. The linker will not put everything to the target, since biz doesn't reference the functions on behalf of .so.
Of course, unless linking util.a with -Wl,-whole-archive. But is there a better way to do this?
Solution 1: consider making util.a a dynamic library util.so.
Solution 2: don't let the linker export any symbols exported by util.a. When using gcc you can achieve this for example by using __attribute__((visibility("hidden"))):
int __attribute__((visibility("hidden"))) helperfunc(void *p);
You can use objdump to check which symbols are exported.
To answer myself's question, the eventual solution was like:
http://lists.gnu.org/archive/html/qemu-devel/2014-09/msg00099.html
TL;DR: Search for all the interesting symbols (that you want to pull from archives) inside the .so objects with nm (1), and inject into the compiling command line with -Wl,-u,$SYMBOL. Note that the -Wl,-u,$SYMBOL arguments need to come before archive names in the command line, so the linker knows that it needs to link them.

Weak symbols, shared libraries and dlopen

I have a binary with a weak symbol that I want to be able to link at runtime with a run dependent shared library.
$nm testrun
...
w basic2.test
...
My first test was using a .o file at static linktime, that worked, but I need it to be shared.
So, my second test was getting a shared library with that symbol defined and link it at compile time with -lmy (libmy.so), and this, actually worked as well.
Third step tried not linking at compile time and use ld_preload trick and this did not work.
nm libmy.so
...
00000550 T basic2.test
...
I have really no idea why this particular one does not work, looks like dynamic loader should have enough information to set testruns weak symbol with the one in libmy.so.
My final objective, which I guess will require more work is to load at start a small function that does check for the appropiate symbol with dlsym and sets it there.
Any hint?
It seems that you may need to use LD_DYNAMIC_WEAK along with LD_PRELOAD from the man page:
LD_DYNAMIC_WEAK (glibc since 2.1.91) Allow weak symbols to be overridden (reverting to old glibc behavior). For security reasons, since glibc 2.3.4, LD_DYNAMIC_WEAK is ignored for set-user-ID/set-group-ID binaries.
Note: it could be a typo, but you should use -lmylib.so and not -Lmylib.so

Restricting symbols to local scope for linux executable

Can anyone please suggest some way we can restrict exporting of our symbols to global symbol table?
Thanks in advance
Hi,
Thanks for replying...
Actually I have an executable which is statically linked to a third party library say "ver1.a" and also uses a third party ".so" file which is again linked with same library but different version say "ver2.a". Problem is implementation of both these versions is different. At the beginning, when executable is loaded, symbols from "ver1.a" will get exported to global symbol table. Now whenever ".so" is loaded it will try to refer to symbols from ver2.a, it will end up referring to symbols from "ver1.a" which were previously loaded.Thus crashing our binary.
we thought of a solution that we wont be exporting the symbols for executable to Global symbol table, thus when ".so" gets loaded and will try to use symbols from ver2.a it wont find it in global symbol table and it will use its own symbols i.e symbols from ver2.a
I cant find any way by which i can restrict exporting of symbols to global symbol table. I tried with --version-script and retain-symbol-file, but it didn't work. For -fvisibility=hidden option, its giving an error that " -f option may only be used with -shared". So I guess, this too like "--version-script" works only for shared libraries not for executable binaries.
code is in c++, OS-Linux, gcc version-3.2. It may not be possible to recompile any of the third party libraries and ".so"s. So option of recompiling "so' file with bsymbolic flag is ruled out.
Any help would be appreciated.
Pull in the 3rd party library with dlopen.
You might be able to avoid that by creating your own shared lib that hides all the third party symbols and only exposes your own API to them, but if all else fails dlopen gives you complete control.
I had, what sounds like, a similar issue/question: Segfault on C++ Plugin Library with Duplicate Symbols
If you can rebuild the 3rd party library, you could try adding the linker flag -Bsymbolic (the flag to gcc/g++ would be -Wl,-Bsymbolic). That might solve your issue. It all depends on the organization of your code and stuff, as there are caveats to using it:
http://www.technovelty.org/code/c/bsymbolic.html
http://software.intel.com/en-us/articles/performance-tools-for-software-developers-bsymbolic-can-cause-dangerous-side-effects/
If you can't rebuild it, according to the first caveat link:
In fact, the only thing the -Bsymbolic
flag does when building a shared
library is add a flag in the dynamic
section of the binary called
DT_SYMBOLIC.
So maybe there's a way to add the DT_SYMBOLIC flag to the dynamic section post-linking?
The simplest solution is to rename the symbols (by changing source code) in your executable so they don't conflict with the shared library in the first place.
The next simplest thing is to localize the "problem" symbols with 'objcopy -L problem_symbol'.
Finally, if you don't link directly with the third party library (but dlopen it instead, as bmargulies suggests), and none of your other shared libraries use of define the "problem" symbol, and you don't link with -rdynamic or one of its equivalents, then the symbol should not be exported to the dynamic symbol table of the executable, and thus you shouldn't have a conflict.
Note: 'nm a.out' will still, show the symbol as globally defined, but that doesn't matter for dynamic linking. You want to look at the dynamic symbol table of a.out with 'nm -D a.out'.

Resources