运行时链接程序提供了调试功能,允许您详细地跟踪应用程序的运行时链接及其依赖项情况。使用此功能显示的信息类型应保持不变。不过,信息的确切格式可能随发行版的不同而有所变化。
不了解运行时链接程序的用户可能不熟悉某些调试输出。不过,您可能对其中许多方面不太感兴趣。
可使用环境变量 LD_DEBUG 来启用调试。所有调试输出都使用进程标识符作为前缀。必须使用一个或多个标记来扩充此环境变量,以指示所需调试的类型。
使用 LD_DEBUG=help,可以显示 LD_DEBUG 中可用的标记。
$ LD_DEBUG=help prog
prog 可以是任何动态可执行文件。在将控制权转交给 prog 之前,进程终止并随后显示帮助信息。可执行文件的选择并不重要。
缺省情况下,会将所有调试输出发送到标准错误输出文件 stderr。可以使用 output 标记将调试输出定向到其他文件。例如,可以在名为 rtld-debug.txt 的文件中捕获帮助文本。
$ LD_DEBUG=help,output=rtld-debug.txt prog
此外,还可以通过设置环境变量 LD_DEBUG_OUTPUT 来重定向调试输出。使用 LD_DEBUG_OUTPUT 时,进程标识符作为后缀添加到输出文件名。
如果同时指定 LD_DEBUG_OUTPUT 和 output 标记,则 LD_DEBUG_OUTPUT 优先。如果同时指定 LD_DEBUG_OUTPUT 和 output 标记,则 LD_DEBUG_OUTPUT 优先。将 output 标记与调用 fork(2) 的程序结合使用会导致每个进程都将调试输出写入同一文件。调试输出因此会变得混乱且不完整。在这种情况下应使用 LD_DEBUG_OUTPUT,以将每个进程的调试输出定向到唯一的文件。
对于安全的应用程序,不允许进行调试。
其中一个最有用的调试选项是显示运行时进行的符号绑定。以下示例使用很简单的动态可执行文件,该可执行文件依赖于两个局部共享目标文件。
$ cat bar.c int bar = 10; $ cc -o bar.so.1 -K pic -G bar.c $ cat foo.c int foo(int data) { return (data); } $ cc -o foo.so.1 -K pic -G foo.c $ cat main.c extern int foo(); extern int bar; int main() { return (foo(bar)); } $ cc -o prog main.c -R/tmp:. foo.so.1 bar.so.1
通过设置 LD_DEBUG=bindings,可以显示运行时符号绑定。
$ LD_DEBUG=bindings prog 11753: .... 11753: binding file=prog to file=./bar.so.1: symbol bar 11753: .... 11753: transferring control: prog 11753: .... 11753: binding file=prog to file=./foo.so.1: symbol foo 11753: ....
即时重定位需要的符号 bar 是在应用程序获得控制权之前绑定的。然而,符号 foo 是延迟重定位所需的,将在应用程序获得第一次调用函数的控制权之后绑定。此重定位说明了延迟绑定的缺省模式。如果设置了环境变量 LD_BIND_NOW,则所有符号绑定都会在应用程序获取控制权之前进行。
通过设置 LD_DEBUG=bindings,detail,可提供有关实际绑定位置的实际地址和相对地址的其他信息。
可以使用 LD_DEBUG 来显示使用的各个搜索路径。例如,通过设置 LD_DEBUG=libs,可以显示用于查找所有依赖项的搜索路径机制。
$ LD_DEBUG=libs prog 11775: 11775: find object=foo.so.1; searching 11775: search path=/tmp:. (RUNPATH/RPATH from file prog) 11775: trying path=/tmp/foo.so.1 11775: trying path=./foo.so.1 11775: 11775: find object=bar.so.1; searching 11775: search path=/tmp:. (RUNPATH/RPATH from file prog) 11775: trying path=/tmp/bar.so.1 11775: trying path=./bar.so.1 11775: ....
应用程序 prog 中记录的运行路径将影响两个依赖项 foo.so.1 和 bar.so.1 的搜索。
同样,可通过设置 LD_DEBUG=symbols 来显示每个符号查找的搜索路径。组合使用 symbols 和 bindings 可生成符号重定位进程的完整信息。
$ LD_DEBUG=bindings,symbols prog 11782: .... 11782: symbol=bar; lookup in file=./foo.so.1 [ ELF ] 11782: symbol=bar; lookup in file=./bar.so.1 [ ELF ] 11782: binding file=prog to file=./bar.so.1: symbol bar 11782: .... 11782: transferring control: prog 11782: .... 11782: symbol=foo; lookup in file=prog [ ELF ] 11782: symbol=foo; lookup in file=./foo.so.1 [ ELF ] 11782: binding file=prog to file=./foo.so.1: symbol foo 11782: ....
在前面的示例中,未在应用程序 prog 中搜索符号 bar。省略数据引用查找是因为在处理复制重定位时使用了优化。有关此重定位类型的更多详细信息,请参见复制重定位。