Roger Lipscombe
Roger Lipscombe

Reputation: 91805

Find location of loaded shared library, from in that shared library?

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

Answers (2)

Nehal J Wani
Nehal J Wani

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

yugr
yugr

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

Related Questions