Reputation: 91805
From a function in a shared library, inside a running process (written in C), how do I discover where that shared library was loaded from?
All of the answers I've found involve using things such as ldd
at the command line, or by peeking in /proc/self/maps
.
On Win32, I'd just use GetModuleFileName(GetModuleHandle("foo.dll"), szPath, COUNTOF(szPath))
. What's the Linux equivalent?
Bonus question: I need the same information in OS X.
Upvotes: 7
Views: 3367
Reputation: 16629
One method to achieve this is to make use of dladdr:
Code for the shared object:
$ cat so.c
#include <stdio.h>
#include <dlfcn.h>
void test_so_func()
{
Dl_info info;
if (dladdr(test_so_func, &info))
{
printf("Loaded from path = %s\n", info.dli_fname);
}
printf("hello\n");
}
Code for the main exec:
$ cat test.c
void test_so_func();
int main() {
test_so_func();
return 0;
}
Makefile:
$ cat Makefile
test: test.o libso.so
gcc test.o -o $@ -Wl,-L.,-lso,-rpath,'$$ORIGIN'
clean:
-rm -f libso.so test.o test
libso.so: so.c
gcc -D_GNU_SOURCE=1 -fPIC -shared $< -o $@ -lc -ldl
test.o: test.c
gcc -fPIC -c $< -o $@
Let's compile!
$ make
gcc -fPIC -c test.c -o test.o
gcc -D_GNU_SOURCE=1 -fPIC -shared so.c -o libso.so -lc -ldl
gcc test.o -o test -Wl,-L.,-lso,-rpath,'$ORIGIN'
Test this binary.
$ ./test
Loaded from path = /spare/scratch/1564054710/libso.so
hello
Verify that libso.so is indeed speaking the truth.
$ ldd ./test
linux-vdso.so.1 => (0x00007ffdf55d5000)
libso.so => /spare/scratch/1564054710/./libso.so (0x00007fbcc4602000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fbcc4238000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fbcc4034000)
/lib64/ld-linux-x86-64.so.2 (0x00007fbcc4804000)
The credit for this answer goes to https://github.com/mingwandroid
Upvotes: 6
Reputation: 21878
You could use dl_iterate_phdr to iterate all loaded libraries and their segments (similar functionality is available for OSX, see e.g. this question). But most of the projects just parse /proc/self/maps
.
As a side note, keep in mind that mappings may change dynamically (if libraries are loaded via dlopen
) so reading them at startup may not be enough.
Upvotes: 4