為什麼(以及如何)我的共享庫中(看起來!)有重複的符號?

為什麼(以及如何)我的共享庫中(看起來!)有重複的符號?

我碰巧需要從導出的共享庫符號的平面列表中找出哪個庫導出了哪些符號。清單中只有足夠的符號(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,同時保持向後相容性。

相關內容