有没有办法在链接时设置精灵需要字段?
Is there a way to set the elf NEEDED field at link time?
给定一个可执行文件,使得:
>objdump -x someprog | grep c++
NEEDED libstdc++.so.6
我想将要求更改为完整版本(包括次要版本和补丁级别(:
>objdump -x someprog | grep c++
NEEDED libstdc++.so.6.0.22
我知道有两种方法可以做到这一点:
- 根据此问题创建一个虚拟库(强制或阻止使用特定的次要版本的libstdc++(
- 使用补丁
>patchelf --add-need libstdc++.so.6.0.22 someprog>objdump -x someprog |grep c++ NEED libstdc++.so.6 需要libstdc++.so.6.0.22
(我还没有找到--replace-need的工作命令行(
这对我来说都像是黑客。有没有办法在编译或链接时使用适当的 -wl 标志到 gcc 来实现相同的目标?
理想情况下,我想避免使用 -nostdlib,因为这不仅需要我指定 libstd++,还需要指定 libc 和我想要标准版本的其他所有内容。
对于常规库,只需链接到特定版本就足以满足libstdc++的需求,它不是(或者更确切地说,我怀疑-stdlib覆盖了我提供的后续完全限定名称(。
背景:我有可执行文件,需要比系统上安装的更高版本的libstdc++
。不幸的是,安装的版本可能是相同的主要版本,如果是这样,ld
将很乐意使用系统版本,因为它与所谓的libstdc++.so.6
匹配
我不喜欢静态链接,因为我实际上想安装许多共享相同C++运行时的小程序,这会大大膨胀安装。
有关我的图书馆搜索路径的一些信息可在此处获得:
ld --verbose | grep SEARCH_DIR SEARCH_DIR("/usr/x86_64-redhat-linux/lib64"(;SEARCH_DIR("/usr/lib64"(;SEARCH_DIR("/usr/local/lib64"(;SEARCH_DIR("/lib64"(;SEARCH_DIR("/usr/x86_64-redhat-linux/lib"(;SEARCH_DIR("/usr/local/lib"(;SEARCH_DIR("/lib"(;SEARCH_DIR("/usr/lib"(;
在我的情况下很明显,/usr/lib64 是在可执行文件的 RPATH 之前搜索的,即:
>objdump -x /opt/foo/bin/bar | grep PATH
RPATH $ORIGIN/../lib64/private:$ORIGIN/../lib64:$ORIGIN/
man ld.so
建议搜索顺序应为:
如果库依赖项不包含斜杠,则搜索它 按以下顺序:
o (ELF only) Using the directories specified in the DT_RPATH dynamic section attribute of the binary if present and DT_RUNPATH attribute does not exist. Use of DT_RPATH is deprecated.
o Using the environment variable LD_LIBRARY_PATH. Except if the executable is a set-user-ID/set-group-ID binary, in which case it is ignored.
o (ELF only) Using the directories specified in the DT_RUNPATH dynamic section attribute of the binary if present.
o From the cache file /etc/ld.so.cache, which contains a compiled list of candidate libraries previously found in the augmented library path. If, however, the binary was linked with the -z node‐
flib linker option, libraries in the default library paths are skipped. Libraries installed in hardware capability directories (see below) are preferred to other libraries.
o In the default path /lib, and then /usr/lib. If the binary was linked with the -z nodeflib linker option, this step is skipped.
同样 https://software.intel.com/sites/default/files/m/a/1/e/dsohowto.pdf两者似乎都被实际使用所压倒,但事实并非如此。 需要的是寻找符号链接:
>LD_LIBRARY_PATH= LD_DEBUG=libs ldd /opt/foo/bin/bar
21720: find library=libstdc++.so.6 [0]; searching
21720: search path=/opt/foo/bin/../lib64/private:/opt/foo/bin/../lib64:/opt/foo/bin (RPATH from file /opt/foo/bin/bar)
21720: trying file=/opt/foo/bin/../lib64/private/libstdc++.so.6
这是与我安装共享导入库的另一个问题的交互,其中包含必要的链接,其中建议不需要链接。 如果未指定完整的语义版本,则显然需要它们。
这是行不通的,因为libstdc++.so.6.0.22
将导出与系统libstdc++相同的符号,并且您最终会在两个库之间混合使用(假设您确实更改了较新的libstdc++版本的别名(。
您应该静态链接整个libstdc++(这可能需要库的静态PIC变体(并且不导出任何符号(可能使用链接器版本脚本(,或者仅静态链接新符号。
第二种方法似乎是目前最好的选择:它允许您使用大多数新的语言功能,但您仍然与系统的其余部分具有很大程度的互操作性(特别是如果您使用--with-default-libstdcxx-abi=gcc4-compatible
配置 GCC(,并且您不必安装任何其他共享对象进行部署。 这就是 Developer Toolset 软件集合提供较新版本 GCC 的方式(我相信 SUSE Linux Toolchain Module( 也是如此(。 如果C++对象跨共享对象边界传递(包括异常处理(,则完全静态链接会导致问题,而这种选择性静态链接避免了其中的许多问题。
我想我已经回答了我的问题,尽管不是我实际提出的问题。
RPATH
在LD_LIBRARY_PATH
之前被搜索。/usr/lib64/libstdc++.so.6
被拾取而不是libstdc++.so.6.0.22
的原因是,从/where/i/installed/libstdc++.so.6
到/where/i/installed/libstdc++.so.6.0.22
之间没有象征性联系
因此,规则是遵循您平台的标准(在合理的情况下(。在这种情况下:每当您安装共享库时,也要安装所需的链接。
我认为我问的实际问题在技术上仍然很有趣,所以如果有人有一个(甚至多年后(,我仍然会接受更好的答案。
- 将结构字段的类型展开为可变模板参数
- 将位字段导出到数组
- 为了方便起见,我应该避免公开私有字段变量吗
- 当字段可以为null时,如何使用C++接口在Avro中写入数据
- 在java中读取c++字节的位字段
- 链接器找不到在虚拟类 c++ 中访问的静态字段的符号
- 私有字段对象与私有继承?
- 声明没有默认构造函数的字段
- C++内存模型和位字段的最大序列
- 声明为无效的变量或字段'...' Ardunio 编译器上的错误
- 如何在QByteArray中放置和检索位字段而不会感到痛苦?
- C++ win32 如何使密码字段可选并启用复制和粘贴?
- 如何通过UDP接收QByteArray并将其解析为位字段结构?
- 仅匹配集合中的某些字段
- 结构字段名称与 GDB 中的 STL 数组冲突
- 如何使用位字段将数据从二进制文件复制到结构中?
- 结构体和类的不同大小(),彼此具有相同的字段类型
- 如何避免在数据结构中包含存储为字段的类?
- 聚合初始化和删除的复制构造函数,也称为不可复制的 obejcts 作为字段
- 有没有办法在链接时设置精灵需要字段?