ld-linux.so
Glibc 安装的库中有一个为 ld-linux.so.X,其中X为一个数字,在不同的平台上名字也会不同。可以用 ldd 查看:
#ldd /bin/cat linux-gate.so.1 => (0x00bfe000) libc.so.6 => /lib/libc.so.6 (0x00a4a000) /lib/ld-linux.so.2 (0x00a28000)
最后一个没有=>的就是。其中第一个不是实际的库文件,只是一个虚拟库文件用于和 kernel 交互。
ld-linux.so 是专门负责寻找库文件的库。以 cat 为例,cat 首先告诉 ld-linux.so 它需要 libc.so.6 这个库文件,ld-linux.so 将按一定顺序找到 libc.so.6 库再给 cat 调用。
那 ld-linux.so 又是怎么找到的呢?其实不用找,ld-linux.so 的位置是 gcc 在编译程序时就写死在里面了,不过 gcc 写到程序中的 ld-linux.so 位置是可以改变的,可以通过修改 gcc 的 spec 文件。
编译时,ld-linux.so 查找共享库的顺序
(1)ld-linux.so.6 由 gcc 的 spec 文件中所设定
(2)gcc --print-search-dirs 所打印出的路径,主要是 libgcc_s.so 等库。可以通过 GCC_EXEC_PREFIX 来设定
(3)LIBRARY_PATH 环境变量中所设定的路径,或编译时命令行中指定的路径 -L/usr/local/lib
(4)binutils 中的 ld 所设定的缺省搜索路径顺序,编译binutils时指定(可以通过“ld --verbose | grep SEARCH”来查看)
(5)二进制程序的搜索路径顺序为 PATH 环境变量中所设定。一般 /usr/local/bin 高于 /usr/bin
(6)编译时的头文件的搜索路径顺序,与 library 的查找顺序类似。一般 /usr/local/include 高于 /usr/include
运行时,ld-linux.so查找共享库的顺序
(1)ld-linux.so.6 在可执行的目标文件中被指定,可用 readelf 命令查看
(2)编译时通过 RPATH 指定的目录
(3)LD_LIBRARY_PATH 环境变量中所设定的路径
(4)/etc/ld.so.conf(或/usr/local/etc/ld.so.conf)中所指定的路径,由 ldconfig 生成二进制的 ld.so.cache 中
(5)ld-linux.so.6 缺省在 /usr/lib 和 lib 中搜索;当 glibc 安装到 /usr/local 下时,它查找 /usr/local/lib
【注】:-Wl,rpath 的含义(见 stackoverflow)
The -Wl,xxx
option for gcc passes a comma-separated list of tokens as a space-separated list of arguments to the linker. So
gcc -Wl,aaa,bbb,ccc
eventually becomes a linker call
ld aaa bbb ccc
To say "ld -rpath .
", so pass this to gcc as -Wl,-rpath,.