ld.so.preload 与 x86_32 和 x86_64 没有区别

ld.so.preload 与 x86_32 和 x86_64 没有区别

— 众所周知,如果编译时支持 x86_64 内核,则可以使用 x86_64 内核运行 x86_32 程序。但是动态链接器不提供任何方法来为 32 位程序定义一组单独的预加载库,因此每次运行这样的程序时,如果您进行了 x86_64 预加载,您将面临以下错误消息:

ERROR: ld.so: object '… … …' from /etc/ld.so.preload cannot be preloaded (wrong ELF class: ELFCLASS64): ignored.

如果您将相同的 x86_32 库列表放在其中进行预加载,您将使其正常工作,但所有纯 x86_64 运行也会开始抱怨。

显然,最好的方法是修改动态加载器以支持从单独的文件预加载,但这至少是一个漫长的过程。你能想出一些干净的解决方法吗?

现在我正在考虑一些multi-class-pre-load.so,它可以自己加载所需的文件,但是,正如我所看到的,ELF 中没有“多类”支持。

答案1

在 ld.so.preload 中,您希望在路径中指定“$LIB”,而不是显式的“lib”或“lib64”。因此,在 Redhat 风格的发行版上,对于 32 位进程,“/usr/alternates/$LIB/libfoo.so”变为“/usr/alternates/lib/libfoo.so”,而“/usr/alternates/lib64/ libfoo.so”用于 64 位进程。在 Debian 风格的发行版上,“/usr/alternates/$LIB/libfoo.so”变为“/usr/alternates/lib/i386-linux-gnu/libfoo.so”和“/usr/alternates/x86_64-linux-” gnu/libfoo.so”分别。然后,您的树需要填充两种架构的库。

请参阅“rpath 令牌扩展”ld.so(8) 手册页了解更多相关信息。

但请注意,如果您正在编译要尝试修改其加载的二进制文件,而不是预加载库,您可能会发现最好通过设置来修改路径DT_RUNPATH在链接行上(使用相同的“$LIB”样式路径,从而将二进制文件配置为更喜欢您的库位置而不是系统默认值。

或者,正如其他人所指出的,您可以编辑 ELF 文件以在未编译的二进制文件上设置 DT_RUNPATH。

以下内容适用于 x86_64 Centos 6.5 机器:

cd /tmp
mkdir lib lib64
wget http://carrera.databits.net/~ksb/msrc/local/lib/snoopy/snoopy.h
wget http://carrera.databits.net/~ksb/msrc/local/lib/snoopy/snoopy.c
gcc -m64 -shared -fPIC -ldl snoopy.c -o /tmp/lib64/snoopy.so
gcc -m32 -shared -fPIC -ldl snoopy.c -o /tmp/lib/snoopy.so
cat > true.c <<EOF
int main(void)
{ return 0; }
EOF
gcc -m64 true.c -o true64
gcc -m32 true.c -o true32
sudo bash -c "echo '/tmp/\$LIB/snoopy.so' > /etc/ld.so.preload"
strace -fo /tmp/strace64.out /tmp/true64
strace -fo /tmp/strace32.out /tmp/true32
sudo rm /etc/ld.so.preload"

在 strace 输出中,strace64.out 有:

open("/tmp/lib64/snoopy.so", O_RDONLY) = 3

而 strace32.out 有:

open("/tmp/lib/snoopy.so", O_RDONLY) = 3

这是 ld.so.preload 的内容:

/tmp/$LIB/snoopy.so

答案2

预加载并非旨在成为普通的一个系统的运行。通常,您实际上应该链接到您想要使用的库。

少数在运行多个架构的程序时需要预加载的人被认为不关心无害的错误消息。

或者,只要您的程序没有依次启动不同架构的其他程序,您就可以更好地使用LD_PRELOAD具有不正确库部分的程序。

但实际上,您最好修复 ELF 文件中列出的库,最好是在编译阶段,但稍后有一些工具可以编辑 ELF。

(旁注:起初我以为你的问题是关于 x64_32 的,它完全不同并且有一些有趣的错误)

相关内容