如何将 elf 解释器(ld-linux.so.2/ld-2.17.so)构建为静态库?

2024-05-27

如果我的问题不准确,我深表歉意,因为我没有太多 Linux 相关经验。我目前正在构建一个 Linux 从头开始(主要遵循 linuxfromscratch.org 版本的指南 7.3)。我遇到了以下问题:当我构建可执行文件时 获取一个称为 ELF 解释器的硬编码路径。

readelf -l program

显示类似的东西

[Requesting program interpreter: /lib/ld-linux.so.2]

我追踪这个库 ld-linux-so.2 是 glibc 的一部分。我不太 对此行为感到满意,因为它使二进制文件非常难以移植 - 如果我更改 /lib/ld-linux.so.2 可执行文件的位置则不会 更长的作品,我发现的唯一“修复”是使用 patchelf 实用程序 从 NixOS 将硬编码路径更改为另一个硬编码路径。为了 这个原因我想链接到 ld 的静态版本 库,但没有生成这样的库。这就是我的问题,可以吗 请解释一下我如何构建 glibc 以便它生成一个 ld-linux.so.2 的静态版本,我稍后可以链接到我的 可执行文件。我不完全理解这个 ld 库的作用,但我 假设这是加载其他动态库的部分(或者在 至少 glibc.so)。我想动态链接我的可执行文件,但是 我希望动态链接器本身静态内置到 它们,因此它们不会依赖于硬编码路径。或者我 希望能够设置解释器的路径 环境变量类似于 LD_LIBRARY_PATH,也许 LD_INTERPRETER_PATH。目标是能够生产便携式 二进制文件,可以在任何具有相同 ABI 的平台上运行 目录结构是什么。

一些可能相关的背景:我正在使用 Slackware 14 x86 构建 i686 编译器工具链,所以总体来说都是 x86 主机 目标。我正在使用 glibc 2.17 和 gcc 4.7.x。


我希望能够使用类似于 LD_LIBRARY_PATH(也许是 LD_INTERPRETER_PATH)的环境变量设置解释器的路径。

这根本不可能。仔细阅读(并多次)执行(2) http://man7.org/linux/man-pages/man2/execve.2.html, elf(5) http://man7.org/linux/man-pages/man5/elf.5.html & ld.so(8) http://man7.org/linux/man-pages/man8/ld.so.8.html手册页和 LinuxABI http://en.wikipedia.org/wiki/Application_binary_interface&ELF http://en.wikipedia.org/wiki/Executable_and_Linkable_Format规格。还有内核代码在做execve.

ELF解释器负责动态链接。它必须是一个文件(技术上是静态链接的 ELF 共享库)fixed文件层次结构中的位置(通常/lib/ld.so.2 or /lib/ld-linux.so.2 or /lib64/ld-linux-x86-64.so.2)

The old a.out format from the 1990s had a builtin dynamic linker, partly implemented in old Linux 1.x kernel. It was much less flexible, and much less powerful.

通过这样的(原则上)任意动态链接器路径,内核使得能够具有各种动态链接器。但大多数系统只有一个。这是参数化动态链接器的好方法。如果您想尝试另一个,请将其安装在文件系统中并生成提及该路径的 ELF 可执行文件。

With great pain and effort, you might make your own ld.so-like dynamic linker implementing your LD_INTERPRETER_PATH wish, but that linker still has to be an ELF shared library sitting at some fixed location in the file tree.

如果您想要一个不需要任何文件的系统(在某些预定义的有线位置,例如/lib/ld.so, /dev/null, /sbin/init...),您需要静态构建其所有可执行二进制文件。您可能希望(但当前的 Linux 发行版通常不这样做)有一些静态链接的可执行文件(例如/sbin/init, /bin/sash...)这将使您能够修复损坏到没有任何动态链接器的系统。

BTW, the /sbin/init -or /bin/sh - path is wired inside the kernel itself. You may pass some argument to the kernel at boot load time -e.g. with GRUB- to overwrite the default. So even the kernel wants some files to be here!

正如我评论的那样,你可能会看看MUSL-Libc http://musl-libc.org/另一种 Libc 实现(提供自己的动态链接器)。另请阅读有关VDSO http://en.wikipedia.org/wiki/VDSO and ASLR http://en.wikipedia.org/wiki/ASLR and initrd http://en.wikipedia.org/wiki/Initrd.

在实践中,接受这样一个事实:现代 Linux 和 Unix 需要一些非空文件系统……请注意,动态链接和共享库是一个巨大的进步(在 20 世纪 90 年代的 Linux 内核和发行版中,这要痛苦得多)。

或者,定义您自己的二进制格式,然后制作内核模块或binfmt_misc https://www.kernel.org/doc/Documentation/binfmt_misc.txt条目来处理它。

顺便说一句,大多数(或全部)Linux 是自由软件 http://en.wikipedia.org/wiki/Free_software,这样您就可以改进它(但这将需要您花费数月甚至数年的时间)。请通过发布来分享您的改进。

另请阅读Draper 的《如何编写共享库》 http://software.intel.com/sites/default/files/m/a/1/e/dsohowto.pdf纸;和这个问题 https://stackoverflow.com/q/4757121/841108.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何将 elf 解释器(ld-linux.so.2/ld-2.17.so)构建为静态库? 的相关文章

随机推荐