![为什么(以及如何)我的共享库中(看起来!)有重复的符号?](https://linux22.com/image/154961/%E4%B8%BA%E4%BB%80%E4%B9%88%EF%BC%88%E4%BB%A5%E5%8F%8A%E5%A6%82%E4%BD%95%EF%BC%89%E6%88%91%E7%9A%84%E5%85%B1%E4%BA%AB%E5%BA%93%E4%B8%AD%EF%BC%88%E7%9C%8B%E8%B5%B7%E6%9D%A5%EF%BC%81%EF%BC%89%E6%9C%89%E9%87%8D%E5%A4%8D%E7%9A%84%E7%AC%A6%E5%8F%B7%EF%BC%9F.png)
我碰巧需要从导出的共享库符号的平面列表中找出哪个库导出了哪些符号。列表中只有足够的符号(20 个左右),我不会手动交叉引用每个符号。
我发现这nm -A -D -f sysv <library-name>
似乎产生了有用的输出 - 我可以搜索包含FUNC
在第二列中列出地址的行。所以我对 中的所有内容运行此命令/usr/lib
,将其重定向到一个文件。
令我惊讶的是,我在解析文件的脚本中进行的健全性检查报告存在重复的符号!经调查发现库似乎正在导出重复的符号?!?
我使用一些 shell 脚本验证了这一点,并且能够将我使用的命令变成这样(技术上)一行:
readlink -f /lib/* /usr/lib/* \
| grep -F .so. | sort | uniq \
| while read x; do nm -A -D -f sysv $x; done \
| grep FUNC | cut -d'|' -f1 | sort -g | uniq -c | sort -g \
| sed -n '/^ \+1/!{s/^ \+[0-9]\+ \+//p}' | sed 's/ //g' \
| tr '\n' '\v' \
| sed ':1;s/\([^ ]\+\):\([^\v$]\+\)\v\1:/\1:\2|/g;t1' \
| tr '\v' '\n' \
| while IFS=: read -a x; do \
nm -A -D -f sysv "${x[0]}" | grep ":\\(${x[1]//|/\\|}\\).*FUNC"; \
done
上面的命令将使您的磁盘进行短时间的寻道。如果需要,您可以将其分解为重定向到临时文件的块。还输出会很宽(~150 列)。
我最初在我正在使用的 Debian Squeeze chroot 上运行原始脚本,但出于好奇,我在我的主机系统上运行了上述脚本,以查明 chroot 是否不正常。
嗯... chroot 报告了超过 90 个重复项,但我的主机 (Arch) 系统显然有大约 267 个。
该命令通过 grepnm
的输出工作,因此结果有点嘈杂,但它看起来像这样:
/usr/lib/libasound.so.2.0.0:snd_pcm_hw_params_get_access|00043700| T | FUNC|00000037| |.text
/usr/lib/libasound.so.2.0.0:snd_pcm_hw_params_get_access|000436c0| T | FUNC|0000003c| |.text
/usr/lib/libasound.so.2.0.0:snd_pcm_hw_params_get_access_mask|000458f0| T | FUNC|00000058| |.text
/usr/lib/libasound.so.2.0.0:snd_pcm_hw_params_get_buffer_size|000432a0| T | FUNC|00000037| |.text
/usr/lib/libasound.so.2.0.0:snd_pcm_hw_params_get_buffer_size|00043260| T | FUNC|0000003c| |.text
/usr/lib/libasound.so.2.0.0:snd_pcm_hw_params_get_buffer_size_max|00044ff0| T | FUNC|0000003c| |.text
/usr/lib/libasound.so.2.0.0:snd_pcm_hw_params_get_buffer_size_max|00045030| T | FUNC|00000037| |.text
/usr/lib/libasound.so.2.0.0:snd_pcm_hw_params_get_buffer_size_min|000453c0| T | FUNC|00000037| |.text
/usr/lib/libasound.so.2.0.0:snd_pcm_hw_params_get_buffer_size_min|00045380| T | FUNC|0000003c| |.text
请注意每个符号有两个。地址不同,是的,但是...我认为动态链接是通过符号名称来工作的,就是这样。让我更加困惑的是,(如果您在上面的列表中向右滚动)符号都是FUNC
来自该.text
部分的类型。
我发布这篇文章是为了了解这里的幕后发生了什么有趣的魔法。 (因为我的系统正在运行......)
如果有人有任何好主意,我可以转储大约 600 行文本 - Pastebin 似乎不再流行,而且我不使用 GitHub - 我很乐意分享完整的输出。
答案1
这些符号出现重复是因为 提供的信息nm
不完整:相关符号已版本化。您可以使用以下命令查看objdump -T
:
0000000000059d00 g DF .text 0000000000000044 (ALSA_0.9) snd_pcm_hw_params_get_access
0000000000056040 g DF .text 000000000000004b ALSA_0.9.0rc4 snd_pcm_hw_params_get_access
或nm
的--with-symbol-versions
选项:
/usr/lib/x86_64-linux-gnu/libasound.so.2.0.0:snd_pcm_hw_params_get_access|0000000000059d00| T | FUNC|0000000000000044| |.text@ALSA_0.9
/usr/lib/x86_64-linux-gnu/libasound.so.2.0.0:snd_pcm_hw_params_get_access|0000000000056040| T | FUNC|000000000000004b| |.text@@ALSA_0.9.0rc4
二进制文件与特定版本的符号链接,它们将在链接时获得正确的版本。这允许更改 API,同时保持向后兼容性。