2017-07-21 80 views
-1

给定一个可执行文件,使得:有没有办法在链接时设置elf NEEDED字段?

>objdump -x someprog | grep c++ 
NEEDED    libstdc++.so.6 

我想换到完整版本的要求(包括次要版本和补丁级别):

>objdump -x someprog | grep c++ 
NEEDED    libstdc++.so.6.0.22 

我知道有两种方法可以做到这:

  1. 创建一个虚拟库按这个问题(Forcing or preventing use of a particular minor version of libstdc++
  2. 使用PATC HELF
 
    >patchelf --add-needed libstdc++.so.6.0.22 someprog 
    >objdump -x someprog | grep c++ 
    NEEDED    libstdc++.so.6 
    NEEDED    libstdc++.so.6.0.22 

(我还没有想出了--replace需要的工作命令行)

的这些感觉像黑客给我两个。 有没有办法在编译或链接时使用相应的-Wl标志来实现gcc?

理想情况下,我想避免使用-nostdlib,因为这需要我具体不只是libstd ++,但libc和其他所有我想要的标准版本。

对于只连接到特定版本的常规库就足够用于libstdC++,它不是(或者说我怀疑-stdlib覆盖了我提供的后续完全限定名称)。

背景:我的可执行文件需要安装在系统上的更高版本的libstdc++。不幸的是,安装的版本可能是相同的主要版本,如果是ld会很乐意使用的系统版本,因为它符合SONAMElibstdc++.so.6

我不喜欢静态链接,因为我真的想安装许多小程序共享同一C++运行时间,这会大大增加安装量。


对我(的)库搜索路径的一些信息,请访问:

LD --verbose | grep SEARCH_DIR SEARCH_DIR(“/ usr/x86_64-redhat-linux/lib64”); SEARCH_DIR( “/ USR/lib64下”); SEARCH_DIR( “/ USR /本地/ lib64下”); SEARCH_DIR( “/ lib64下”); SEARCH_DIR( “/ USR/x86_64的-红帽-LINUX/LIB”); SEARCH_DIR( “/ USR/local/lib目录”); SEARCH_DIR( “/ LIB”); SEARCH_DIR( “/ usr/lib中”);

这是在我的情况清楚地表明在/ usr /正在搜索lib64的前可执行的RPATH是:

>objdump -x /opt/emma/bin/stm2emma | 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 

这是与另外一个问题我不得不install shared imported library with necessary links其中建议是,不需要链接的交互。 如果你没有指定完整的语义版本,他们显然

+0

之前/之后的情况似乎没有区别,所以目前还不清楚你想要什么。 –

+0

这是我的错误(现在已修复),我的意思是如此.6.0.22。不是这样。0 –

+0

现在它再次有意义,希望downvotes将被删除。 –

回答

1

我想我已经回答了我的问题,但不是我实际询问的问题。

RPATHLD_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

没有符号链接,该规则是遵循平台的标准(他们是明智的)。在这种情况下: 每当您安装共享库时,也要安装所需的链接。

我认为我问的实际问题在技术上仍然很有意思,所以如果任何人有一个(甚至几年后),我仍然会接受更好的答案。

+0

GCC为您安装该符号链接。如果你把'libstdC++。so.6.0.22'文件放在别的地方,也不要把符号链接放在那里,那么你就会得到你要求的!问题只是用户错误,修复方法是正确安装库,而不是复杂的,容易出错的黑客,如重命名库或编辑NEEDED标签。 –

+0

如果你安装完整的gcc堆栈,当然是。但是我们不希望仅仅因为应用程序在开发中使用它而在生产服务器上安装gcc。那将是疯狂。我们只需要C++运行时。 –

+0

我并不是建议在生产服务器上安装整个GCC,只是在安装树中复制的库旁边的**。我没有提到有关安装编译器二进制文件,头文件,文档等甚至其他运行时库的信息。但是当GCC安装libstdC++时,它也会创建必要的符号链接。在其他地方移动图书馆时也应该这样做。 –

1

这将不起作用,因为libstdc++.so.6.0.22将导出与系统libstdC++相同的符号,并且最终会在两个库之间出现混搭(假设您确实更改了较新的libstdC++版本的soname)。

您应该静态链接整个libstdC++(这可能需要库的静态PIC变体),并且不导出任何符号(可能使用链接器版本脚本),或者仅静态链接新符号。

第二种方法似乎是目前最好的选择:它允许您使用大多数新语言功能,但您仍然与系统其余部分有很大程度的互操作性(尤其是如果您使用--with-default-libstdcxx-abi=gcc4-compatible配置GCC) ,而且您不必安装任何其他共享对象进行部署。这就是Developer Toolset software collection提供更新版本的GCC(我也相信SUSE Linux Toolchain Module)。如果C++对象通过共享对象边界(包括异常处理)进行传递,则完全静态链接会导致问题,并且这种选择性静态链接可避免这些问题中的许多问题。

+0

我想你可能会误解问题的背景。可执行文件是由gcc的后期版本构建的(6.3 vs 4.9版本,所以令人惊讶的是soname只给出了不同的'patchlevel'。象征性的GLIBCXX版本更加不同)使用.so.6.0.22和*只有*与该版本链接。问题出在运行时,可执行文件要求输入.so.6并获取系统.so.6,而不是它需要的.so.6.0.22。 或者您指的是将.so.6和.so.6.0.22列为必需的patchelf命令?这可能是有道理的。 –

+0

如果可执行文件已经编译完成,唯一的解决方法是将新版本的libstdC++放在库搜索路径中,这样程序就可以为旧代码和新代码提取它。我正在建议避免这种情况的方法。 –

+0

更新版本的libstdC++已经在RPATH上。不幸的是,系统路径/ usr/lib64(包含libstdC++。so.6作为libstdC++。so.6.0.19的链接)胜过了RPATH。 –

相关问题