我了解如何在链接/编译时定义包含共享对象。但是,我仍然想知道可执行文件*.so在执行时如何查找共享对象(库)。
例如,我的应用程序a.out调用lib.so库中定义的函数。编译后,我移动lib.so到我的$HOME.
我怎么知道a.out去那里找呢?
我知道 Linux 下的共享对象使用“so numbers”,即不同版本的共享对象被赋予不同的扩展名,例如:
example.so.1example.so.2我理解这个想法是有两个不同的文件,以便系统上可以存在两个版本的库(而不是 Windows 上的“DLL Hell”)。我想知道这在实践中是如何工作的?通常情况下,我看到example.so其实是一个符号链接到example.so.2这里.2是最新版本。那么依赖于旧版本的应用程序如何example.so正确识别它?对于必须使用的数字是否有任何规则?或者这只是惯例?是否与在系统之间传输软件二进制文件的 Windows 不同,如果系统具有较新版本的共享对象,它会在从源代码编译时自动链接到较旧版本?
我怀疑这与有关,ldconfig但我不确定如何。
我想找出运行时二进制加载的动态库列表(及其完整路径)。我正在使用 CentOS 6.0。这该怎么做?
我目前在 debian (wheezy/amd64) 上有一个奇怪的问题。
我创建了一个 chroot 来安装服务器(抱歉,我无法提供更多详细信息)。让我们称其为 path /chr_path/。为方便起见,我使用 debootstrap(也是 wheezy/amd64)初始化了这个 chroot。
在 chroot 中一切似乎都运行良好,但是当我启动服务器的安装程序脚本时,我得到了 :(
zsh: Not found /some_path/perl由于某些原因,安装程序包含一个 perl 二进制文件)
当然,我检查了/some_path/位置并找到了“perl”二进制文件。file在 chroot 环境中返回:
/some_path/perl ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.2.5, not stripped
Run Code Online (Sandbox Code Playgroud)
该文件存在,似乎没问题,具有正确的权限。我可以在它上面使用file, ls,vim但是一旦我尝试执行它 -./perl例如 - 我得到 : zsh: Not found ./perl。
这种情况对我来说是可以理解的。而且 :
/chr_path/some_path/perl …在strace输出中,可执行文件调用的库的路径在调用中open()。这是动态链接的可执行文件使用的系统调用吗?怎么样dlopen()?open()不是我猜想的调用会在程序执行中发挥作用。
我想启动wine可执行文件(版本 2.12),但出现以下错误($=shell 提示):
$ wine
bash: /usr/bin/wine: No such file or directory
$ /usr/bin/wine
bash: /usr/bin/wine: No such file or directory
$ cd /usr/bin
$ ./wine
bash: ./wine: No such file or directory
Run Code Online (Sandbox Code Playgroud)
但是,该文件在那里:
$ which wine
/usr/bin/wine
Run Code Online (Sandbox Code Playgroud)
可执行文件肯定存在并且没有死符号链接:
$ stat /usr/bin/wine
File: /usr/bin/wine
Size: 9712 Blocks: 24 IO Block: 4096 regular file
Device: 802h/2050d Inode: 415789 Links: 1
Access: (0755/-rwxr-xr-x) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2017-07-13 13:53:00.000000000 +0200
Modify: 2017-07-08 03:42:45.000000000 …Run Code Online (Sandbox Code Playgroud) 有没有人gold以前使用过链接器?为了链接一个相当大的项目,我不得不使用它而不是 GNU ld,后者抛出了一些错误并且无法链接。
gold链接器如何能够链接ld失败的大型项目?某处是否存在某种记忆欺骗?
基本上,这是将两个问题合二为一——因为如果我可以列出系统内导出的所有符号,以及它们的共享库路径,那么我可以简单地grep输出。
对于内核符号,我想它更容易一些 - 因为我们总是可以cat /proc/kallsyms获取内存中加载的那些模块的所有符号的列表;thensudo cat /proc/modules将给出一个已加载模块的列表及其地址,但不会给出加载模块的路径(如果它们是作为单独的、树外的 .ko 对象构建的)
例如,我尝试kst使用ltrace以下方法跟踪程序:
$ ltrace kst2
...
_ZNK13QGraphicsItem10parentItemEv(0xa1ccdb4, 0, 0xbfe631a8, 0x823652b, 0xbfe63298) = 0xa1ce854
__dynamic_cast(0xa1ce854, 0x839ff00, 0x8306b80, 84, 0xbfe63298) = 0xa1ce800
_ZNK13QGraphicsItem10parentItemEv(0xa1ccdb4, 0x839ff00, 0x8306b80, 84, 0xbfe63298) = 0xa1ce854
__dynamic_cast(0xa1ce854, 0x839ff00, 0x8306b80, 84, 0xbfe63298) = 0xa1ce800
...
Run Code Online (Sandbox Code Playgroud)
......我想知道它在哪里_ZNK13QGraphicsItem10parentItemEv。
那么,如何处理共享库符号呢?通读[gcc-help] 回复:找到定义符号的库。; 我试过这样的事情:
$ find /usr/lib -name '*.so*' -exec nm --print-file-name --defined-only --dynamic {} \; | grep "QGraphicsItem"
...
/usr/lib/libQtGui.so.4.7.2:00766d70 T _Zls6QDebugN13QGraphicsItem16GraphicsItemFlagE …Run Code Online (Sandbox Code Playgroud) 假设我想测试一个库是否已安装并可由程序使用。我可以ldconfig -p | grep mylib用来确定它是否安装在系统上。但是如果图书馆只能通过设置知道LD_LIBRARY_PATH怎么办?
在这种情况下,程序可能能够找到库,但ldconfig不会。如何检查库是否在组合链接器路径中?
我要补充一点,我正在寻找一种解决方案,即使我手头实际上没有该程序(例如该程序尚未编译),我也正在寻找一种解决方案,我只想知道某个库存在于ld' s 路径。
这不是重复的,因为这是处理我在使用/etc/ld.so.conf.
要获取动态链接器搜索库的路径,我运行命令ldconfig -v | grep -v "^"$'\t' | sed "s/:$//g". 什么时候/etc/ld.so.conf没有列出路径。上一条命令的输出是
/lib
/usr/lib
Run Code Online (Sandbox Code Playgroud)
我认为它/lib首先搜索,然后搜索/usr/lib. 当我添加一个新路径时,例如/usr/local/lib, to/etc/ld.so.conf然后 remake /etc/ld.so.cache,输出ldconfig -v | grep -v "^"$'\t' | sed "s/:$//g"变为
/usr/local/lib
/lib
/usr/lib
Run Code Online (Sandbox Code Playgroud)
我觉得这很奇怪,因为如果我认为列出目录的搜索顺序是从上到下是正确的,那么在/lib和之前搜索其他目录/usr/lib。在受信任的目录之前搜索附加目录本身并不奇怪,但是在/libbefore 搜索时/usr/lib,这很奇怪,因为/bin&/sbin在/usr/bin& /usr/sbinin之后搜索PATH。
即使列出的路径ldconfig -v | grep -Ev "^"$'\t' | sed "s/:$//g"是从下到上搜索的,它仍然是一个倾斜的排序,因为会在受信任的目录之后搜索其他目录,而/lib会在/usr/lib …