Tux

...making Linux just a little more fun!

2 cent tip: Determining dynamic shared libraries loaded during run-time of a program

Mulyadi Santosa [mulyadi.santosa at gmail.com]


Wed, 15 Aug 2007 20:34:22 +0700

Good day LG readers!

How do you find out the library dependency of your program? Sure, ldd helps but doesn't always help in every circumstances. Some programs load the needed dynamic libraries with the help of dlopen() function, making ldd unaware of them. But you need to track them all, let's say in order to setup a chroot jail. So, how do you detect them?

To explain this concept, take a look on the below codes (taken from man dlopen):

#include <stdio.h> #include <dlfcn.h>

int main(int argc, char **argv) { void *handle; double (*cosine) (double); char *error;

handle = dlopen("libm.so", RTLD_LAZY); if (!handle) { fprintf(stderr, "%s\n", dlerror()); exit(1); }

cosine = dlsym(handle, "cos"); if ((error = dlerror()) != NULL) { fprintf(stderr, "%s\n", error); exit(1); }

printf("%f\n", (*cosine) (1.0)); dlclose(handle); return 0; } Assume you save it as trace.c. Later you compile it with: $ gcc -ldl -o trace trace.c

ldd shows you this: $ ldd ./trace libdl.so.2 => /lib/libdl.so.2 (0x40029000) libc.so.6 => /lib/tls/libc.so.6 (0x42000000) /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)

OK, where's that libm.so? It doesn't show up. This won't be a serious problem if you have its source code, but what if not? ltrace comes to rescue. You just need to tell ltrace to find the occurence of dlopen(): $ ltrace -f -e dlopen ./trace dlopen("libm.so", 1) ....

-f tells ltrace to trace its forked children, not just the parent process. Now, the rest is just a matter of finding those libraries in library search path i.e any paths that are mentioned in /etc/ld.so.conf or LD_LIBRARY_PATH environment variable.

reference: man dlopen

regards,

Mulyadi


Top    Back


Ben Okopnik [ben at linuxgazette.net]


Thu, 16 Aug 2007 12:26:06 -0400

On Wed, Aug 15, 2007 at 08:34:22PM +0700, Mulyadi Santosa wrote:

> Good day LG readers!
> 
>    How do you find out the library dependency of your program? Sure, 
> ldd helps but doesn't always help in every circumstances. Some programs 
> load the needed dynamic libraries with the help of dlopen() function, 
> making ldd unaware of them.  But you need to track them all, let's say 
> in order to setup a chroot jail. So, how do you detect them?

Now that you mention it [1], I'd run something like this:

strace ./trace 2>&1| grep '^open.*[0-9]$'
It shows any successful calls to 'open', in various flavors - which, of course, will get 'libm.so', etc. 'ldd', of course, is the only thing that shows a dependency on 'ld-linux-<whatever>'... I think I understand the mechanism, though (it's really an "external" dependency, not something that "trace" itself calls.)

[1] When I build a chroot jail, I usually do something like

ldd /my/chroot/bin/*|awk '/lib/{print $1}'|sort -u
to generate a list of all the required libraries, which I then install in the jail. I can't say that I've ever had a program fail to work due to a lib dependency problem after that (other external dependencies - e.g., config files, data sources, etc. - are usually the culprits.)

-- 
* Ben Okopnik * Editor-in-Chief, Linux Gazette * http://LinuxGazette.NET *

Top    Back


Mulyadi Santosa [mulyadi.santosa at gmail.com]


Fri, 17 Aug 2007 00:12:24 +0700

Hi :)

> Now that you mention it [1], I'd run something like this:
>
> ``
> strace ./trace 2>&1| grep '^open.*[0-9]$'

Good point! :) Actually, I wanna suggest that too, but I thought tracking dlopen() specificly is a good way to go since it gives you fewer trace and AFAIK dlopen() is the only C function that loads dynamic library. Of course, since I am not so fluent in C/C++ world, I might miss something :)

All in all, thanks for the feedback, I really appreciate it

NB: Writing tips is the best thing I can do so far, sorry. I'll see if I can write a complete article in near future.

regards.

Mulyadi


Top    Back


Ben Okopnik [ben at linuxgazette.net]


Thu, 16 Aug 2007 21:25:33 -0400

On Fri, Aug 17, 2007 at 12:12:24AM +0700, Mulyadi Santosa wrote:

> Hi :)
> 
> > Now that you mention it [1], I'd run something like this:
> >
> > ``
> > strace ./trace 2>&1| grep '^open.*[0-9]$'
> 
> Good point! :) Actually, I wanna suggest that too, but I thought
> tracking dlopen() specificly is a good way to go since it gives you
> fewer trace 

Actually, 'strace' has some very useful "macros" predefined for that; e.g., "strace -e trace=file <foo>" gives you just the file access calls (open, stat, chmod, unlink, lstat, etc.) It's pretty easy to select a subset.

> NB: Writing tips is the best thing I can do so far, sorry. 

[laugh] That's not something to be sorry about - it's something to be proud of, since it's still a positive contribution to the Linux community.

> I'll see if I can write a complete article in near future.

That would be an even bigger contribution. It's all good. :)

-- 
* Ben Okopnik * Editor-in-Chief, Linux Gazette * http://LinuxGazette.NET *

Top    Back