Chinaunix首页 | 论坛 | 博客
  • 博客访问: 153070
  • 博文数量: 19
  • 博客积分: 1425
  • 博客等级: 上尉
  • 技术积分: 425
  • 用 户 组: 普通用户
  • 注册时间: 2007-08-20 16:48
文章分类

全部博文(19)

文章存档

2009年(1)

2008年(18)

我的朋友

分类: LINUX

2008-12-05 10:05:16

 

有时候我们在运行某个程式的时候,总是会报FILE A no such file or directory之类的错误。但是我们又不知道这个程式是以怎么个形式在找A文件,有时候在某个目录明明有A文件,程式还是会报错,那我们就得知道这个程式在找这个文件的时候,是去哪个目录下找的。ldd truss nm命令就是实现这个功能的利器。

I've decided to write down a few useful tips on observing binary files in Solaris. The commands used are available since Solaris 8, so hopefully you'll find these tricks useful.

Quite often it happens that the programs we run don't work as they should, showing us errors like "referenced symbol not found" or this:
ld.so.1: ./thunderbird-bin: fatal: libmozjs.so: open failed: No such file or directory

So in order for us to find out what exact librabries are being used by a given binary, or where it expects these libraries to be found, and what libraries are not found at all, we have to take the following steps:

1) First we have to see what libraries the ld linker is going to use for our file. For instance, this is how you would find our what libraries are used by the main executable of the Thunderbird mail client:

bash-3.00$ ldd thunderbird-bin
libmozjs.so => (file not found)
libgtk-x11-2.0.so.0 => /usr/lib/libgtk-x11-2.0.so.0
libgdk-x11-2.0.so.0 => /usr/lib/libgdk-x11-2.0.so.0
libatk-1.0.so.0 => /usr/lib/libatk-1.0.so.0
libgdk_pixbuf-2.0.so.0 => /usr/lib/libgdk_pixbuf-2.0.so.0
libm.so.2 => /lib/libm.so.2
...


As always in my examples, the command output is abridged, but you get the idea. It's clearly seen that one of the files - the libmozjs.so library - isn't found. This means, there is no such file in either of the standard library paths or in the current working directory.

2) Now it's about time we find our where the linker expects this libmozjs.so to be found. To do this, we're going to use the truss command. All we're interested in at this stage are the stat and open system calls: stat is used to verify whether some file exists, and open is used to open this file for the later access.

bash-3.00$ truss -f -t stat,open ./thunderbird-bin
13070: stat("/export/soft/thunderbird/thunderbird-bin", 0xFFBFFAD0) = 0
13070: open("/var/ld/ld.config", O_RDONLY) Err#2 ENOENT
13070: stat("/export/soft/thunderbird/libc.so.1", 0xFFBFF600) Err#2 ENOENT
13070: stat("/export/soft/thunderbird/../libc.so.1", 0xFFBFF600) Err#2 ENOENT
13070: stat("/usr/sfw/lib/libc.so.1", 0xFFBFF600) Err#2 ENOENT
13070: stat("/opt/sfw/lib/libc.so.1", 0xFFBFF600) Err#2 ENOENT
13070: stat("/usr/local/lib/libc.so.1", 0xFFBFF600) Err#2 ENOENT
13070: stat("/usr/openwin/lib/libc.so.1", 0xFFBFF600) Err#2 ENOENT
13070: stat("/lib/libc.so.1", 0xFFBFF600) = 0
13070: open("/lib/libc.so.1", O_RDONLY) = 3
13070: stat("/export/soft/thunderbird/libxpcom.so", 0xFFBFF418) = 0
13070: open("/export/soft/thunderbird/libxpcom.so", O_RDONLY) = 3
13070: stat("/export/soft/thunderbird/libmozjs.so", 0xFFBFF398) Err#2 ENOENT
13070: stat("/export/soft/thunderbird/../libmozjs.so", 0xFFBFF398) Err#2 ENOENT
13070: stat("/usr/sfw/lib/libmozjs.so", 0xFFBFF398) Err#2 ENOENT
13070: stat("/opt/sfw/lib/libmozjs.so", 0xFFBFF398) Err#2 ENOENT
13070: stat("/usr/local/lib/libmozjs.so", 0xFFBFF398) Err#2 ENOENT
13070: stat("/usr/openwin/lib/libmozjs.so", 0xFFBFF398) Err#2 ENOENT
13070: stat("/lib/libmozjs.so", 0xFFBFF398) Err#2 ENOENT
13070: stat("/usr/lib/libmozjs.so", 0xFFBFF398) Err#2 ENOENT
ld.so.1: ./thunderbird-bin: fatal: libmozjs.so: open failed: No such file or directory
13070: stat("/export/soft/thunderbird/libgtk-x11-2.0.so.0", 0xFFBFF398) Err#2 ENOENT
...


From this output you can see very well how linker goes through one standard libraries directory to another in a cyclic search for ever library our binary needs. And for our libmozjs.so we can see that logically this library would be found in the current directory where I'm running the thunderbird-bin from, /export/soft/thunderbird. There is no such file there, simply because I've renamed it for this demo.

And this is how the same ldd command would look when all the files are in place:

bash-3.00$ ldd thunderbird-bin
libmozjs.so => /export/soft/thunderbird/libmozjs.so
libgtk-x11-2.0.so.0 => /usr/lib/libgtk-x11-2.0.so.0
libgdk-x11-2.0.so.0 => /usr/lib/libgdk-x11-2.0.so.0
libatk-1.0.so.0 => /usr/lib/libatk-1.0.so.0
libgdk_pixbuf-2.0.so.0 => /usr/lib/libgdk_pixbuf-2.0.so.0
libm.so.2 => /lib/libm.so.2
...


So you can be assured now that our library is found and loaded from the /export/soft/thunderbird/libmozjs.so location.

Thus, by using this simple yet very powerful combination of ldd and truss commands, you can stop guessing and find out exactly which libraries are loaded in a particular order and where they are loaded from.

3) For the "referenced symbol not found" errors, we have to take one more step. These errors happen mostly because the linker finds the library our binary needs, but this library somehow doesn't have the functions we're interested in. So, once we know the exact library file after following the steps 1 and 2 of this manual, it's time for us to look at this particular file and see what functions are available. Many libraries have thousands of functions accessible, so it would make sense to use grep if you know the function you're looking for.

For instance, the following command shows all the functions of the libgdk-x11-2.0 library, which have gdk_threads in their names:

bash-3.00$ nm /usr/lib/libgdk-x11-2.0.so.0 | grep gdk_threads
[3632] | 86512| 68|FUNC |GLOB |0 |11 |gdk_threads_enter
[219] | 86648| 104|FUNC |LOCL |0 |11 |gdk_threads_impl_lock
[220] | 86752| 104|FUNC |LOCL |0 |11 |gdk_threads_impl_unlock
[4329] | 86856| 212|FUNC |GLOB |0 |11 |gdk_threads_init
[3507] | 86580| 68|FUNC |GLOB |0 |11 |gdk_threads_leave
[4095] | 532720| 4|OBJT |GLOB |0 |17 |gdk_threads_lock
[3579] | 532716| 4|OBJT |GLOB |0 |17 |gdk_threads_mutex
[4391] | 87068| 144|FUNC |GLOB |0 |11 |gdk_threads_set_lock_functions
[4443] | 532724| 4|OBJT |GLOB |0 |17 |gdk_threads_unlock


As you understand, if you get a "referenced symbol not found" error, this is quite often because an incorrect (incompatible) version of some library is used - it could be very old or just too new a version of the library, so the functions your binary is looking for are simply not there anymore or called differently.

Well, that's all for today. If you have any additional info to add to this short manual, you're very welcome to leave comments. I'll be happy to hear your opinion.

Defined tags for this entry: , , , , , , ,

 

阅读(1124) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~