上次調試一個程序。程序在使用dlopen()出現錯誤。錯誤信息是加載動態(tài)庫時,動態(tài)庫中有未定義的符號。明明知道是動態(tài)庫的問題,可是自己找了半天,沒解決問題。張博士過來,一個ldd查看一下動態(tài)庫就判斷庫有問題,再一個nm就找到錯誤的地方,然后重新ld了一下庫,問題解決了。神奇了!我也用這幾個命令檢查過庫,就是沒發(fā)現問題,還是對命令的用法不熟啊。
這里把這幾個命令好好整理一下,也算幫助記憶吧。(翻譯的成居多,hehe)
nm命令
這個命令列出目標文件的符號。如果沒有指定目標文件,默認是a.out。
命令大綱nm [
-a|
--debug-syms] [
-g|
--extern-only]
[
-B] [
-C|
--demangle[=
style]] [
-D|
--dynamic]
[
-S|
--print-size] [
-s|
--print-armap]
[
-A|
-o|
--print-file-name]
[
-n|
-v|
--numeric-sort] [
-p|
--no-sort]
[
-r|
--reverse-sort] [
--size-sort] [
-u|
--undefined-only]
[
-t radix|
--radix=radix] [
-P|
--portability]
[
--target=bfdname] [
-fformat|
--format=format]
[
--defined-only] [
-l|
--line-numbers] [
--no-demangle]
[
-V|
--version] [
-X 32_64] [
--help] [
objfile...]
輸出格式nm命令的輸出包含三個部分:1 符號值。默認顯示十六進制,也可以指定; 2 符號類型。小寫表示是本地符號,大寫表示全局符號(external); 3 符號名稱。 給個例子:
08049ad8 A __bss_start
080485e8 t call_gmon_start
08049ad8 b completed.1
下面把符號類型介紹一下(我就是不熟悉符號類型,才對錯誤沒這么敏感)
- A
- 符號值是絕對的。在進一步的連接中,不會被改變。
- B
- 符號位于未初始化數據段(known as BSS).
- C
- 共用(common)符號. 共用符號是未初始化的數據。在連接時,多個共用符號可能采用一個同樣的名字,如果這個符號在某個地方被定義,共用符號被認為是未定義的引用.
- D
- 已初始化數據段的符號
- G
- 已初始化數據段中的小目標(small objective)符號. 一些目標文件格式允許更有效的訪問小目標數據,比如一個全局的int變量相對于一個大的全局數組。
- I
- 其他符號的直接應用,這是GNU擴展的,很少用了.
- N
- 調試符號.
- R
- 只讀數據段符號.
- S
- 未初始化數據段中的小目標(small object)符號.
- T
- 代碼段的符號.
- U
- 未定義符號.
- V
- 弱對象(weak object)符號. 當一個已定義的弱符號被連接到一個普通定義符號,普通定義符號可以正常使用,當一個未定義的弱對象被連接到一個未定義的符號,弱符號的值為0.
- W
- 一個沒有被指定一個弱對象符號的弱符號(weak symbol)。
- -
- a.out目標文件中的刺符號(stabs symbol). 這種情況下,打印的下一個值是其他字段,描述字段,和類型。刺符號用于保留調試信息.
- ?
- 未知符號類型,或者目標文件特有的符號類型.
命令參數
- -t radix
-
- --radix=radix
- 符號值得進制。d 十進制, o 八進制, x 十六進制.
- -D
-
- --dynamic
- 顯示動態(tài)符號,只在對象是動態(tài)時有用.
- -f format
-
- --format=format
- 輸出的格式,有"bsd","sysv" 或"posix"可選。默認是“bsd”.
- -g
-
- --extern-only
- 只顯示外部符號.
- -l
-
- --line-numbers
- 對每一個符號,使用調試信息去查找文件名和行號。
- -u
-
- --undefined-only
- 只顯示未定義的符號.
- --defined-only
- 只顯示已定義的符號.
- --help
- 顯示幫助