我有一个带有非常旧的 glibc 的遗留系统,我们无法在不进行大量测试/验证工作的情况下对其进行升级。
我现在需要在该系统上多次运行较新的程序(例如 Java 1.7)。我选择了 chroot 解决方案,在其中打包所有需要的库,并在 chroot 中运行服务。
不过 chroot 的限制非常大,我宁愿尝试使用 LD_LIBRARY_PATH 来解决问题。不幸的是,libc.so.6: cannot handle TLS data
当我尝试这样做时,我收到了一个错误。
事实证明我/lib/ld-linux.so.2
也需要来自 chroot 的。这有效:
LD_LIBRARY_PATH=/home/chroot/lib /home/chroot/lib/ld-linux.so.2 /home/chroot/bin/program
然而,java
通过检查/proc/self/cmdline
以确定从哪里加载其库来挫败我的伎俩,如果二进制文件未命名为“bin/java”,则会失败。 java 在启动过程中也会执行自身,这使事情变得更加复杂。
为了使这项工作成功,我做了最后的尝试,我用十六进制编辑器打开了 java 二进制文件,并将字符串替换/lib/ld-linux.so.2
为/home/chroot/ld.so
(并使其成为 的符号链接ld-linux.so.2
),它成功了!
但我认为每个人都会同意,将每个新二进制文件的路径重写为嵌套系统的绝对路径是一个巨大的麻烦。
有谁知道使用自定义库路径的更清晰的方法包括自定义 ld-linux.so?
答案1
正如您使用十六进制编辑器发现的那样,加载程序的路径被编译成二进制文件。实际上,您很幸运,可以直接编辑二进制文件,因为/lib/ld-linux.so.2
和/home/chroot/ld.so
的长度相同。这些字符串的长度也在二进制文件中,如果直接修改字符串,可能会导致微妙的问题。
如果你最终选择了这条路线,你应该看看类似的东西帕切尔夫更新解释器。这将使您可以快速、安全地永久更换口译员。