...making Linux just a little more fun!
Mulyadi Santosa [mulyadi.santosa at gmail.com]
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
Ben Okopnik [ben at linuxgazette.net]
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 -uto 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 *
Mulyadi Santosa [mulyadi.santosa at gmail.com]
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
Ben Okopnik [ben at linuxgazette.net]
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 *