Linux 調試利器:nm 命令使用與符號分析全解析

在 Linux 開發(fā)與調試中,nm 命令是分析二進制文件符號表的必備工具徊哑。無論是排查未定義符號錯誤袜刷,還是逆向分析程序結構,掌握 nm 的使用都能讓你事半功倍莺丑。本文將結合真實案例著蟹,手把手教你玩轉 nm 命令。

一梢莽、nm 命令是什么萧豆?

nm(Names 的縮寫)是 GNU Binutils 工具集的一員,用于顯示目標文件(如.o蟹漓、.a炕横、.so)中的符號信息。它能快速告訴你:

  • 哪些函數(shù)已定義葡粒?
  • 哪些變量在全局數(shù)據(jù)段份殿?
  • 是否存在未鏈接的符號?

其基本語法非常簡單:nm [選項] [文件]嗽交。這里的文件就是我們想要查看符號表的目標文件卿嘲,可以是可執(zhí)行文件、目標文件(.o 文件)或者共享庫文件(.so 文件)夫壁。而選項則用于對輸出進行各種定制拾枣,以滿足不同的需求。

典型應用場景

  1. 排查編譯/鏈接時的符號缺失問題。
  2. 分析動態(tài)庫的導出和依賴關系梅肤。
  3. 逆向工程中查看二進制文件的函數(shù)列表司蔬。

二、核心用法速查表

1. 基礎命令格式

nm [選項] 文件名

常用選項

  • -C:解析 C++ 符號(Demangle)
  • -D:顯示動態(tài)符號(適用于動態(tài)庫)
  • -u:僅顯示未定義符號(排查鏈接問題)
  • -l:顯示符號所在行號(需編譯時加-g)
  • --defined-only:僅列出已定義符號

2. 符號類型解析

nm 輸出的第二列字母代表符號類型姨蝴,常見類型如下:

符號 含義 示例場景
T/t 代碼段(函數(shù)) main俊啼、print 函數(shù)
D/d 初始化數(shù)據(jù)段 int g_var=1;
B/b 未初始化數(shù)據(jù)段(BSS) static int a;
U 未定義符號(需外部鏈接) 外部函數(shù)調用
W/w 弱符號(可被覆蓋) attribute((weak)) 修飾的變量/函數(shù)
R/r 只讀數(shù)據(jù)段 const char* str="hello";

注意:大寫表示全局符號,小寫多為局部符號(部分例外如 u 表示未定義)左医。

查看符號表全貌

如果我們想要快速查看一個可執(zhí)行文件 a.out 的符號表信息授帕,直接在終端輸入 nm a.out 即可。命令執(zhí)行后浮梢,會輸出一系列的行跛十,每一行代表一個符號,包含了符號值(地址)秕硝、符號類型和符號名稱芥映。

例如:

0000000000300526 T main
0000000000401030 D global_variable
0000000000401040 B bss_variable
                 U printf

在這個輸出中,0000000000300526main 函數(shù)的地址缝裤,T 表示 main 函數(shù)位于代碼段屏轰,main 就是函數(shù)名颊郎。global_variable 是一個已初始化的全局變量憋飞,位于數(shù)據(jù)段(D 類型),bss_variable 是未初始化的全局變量(B 類型)姆吭,而 printf 是一個未定義的符號(U 類型)榛做,說明程序中使用了 printf 函數(shù),但它的定義在其他地方内狸。

三检眯、實戰(zhàn)案例:如何排查"undefined reference"?

問題場景

編譯鏈接動態(tài)庫時,報錯 undefined reference to 'clickhouse::ColumnArray()'昆淡,但代碼中明明有定義锰瘸。

排查步驟

  1. 確認符號是否存在

    nm -CD libXXX.so | grep clickhouse::ColumnArray
    

    若輸出 U clickhouse::ColumnArray,說明該符號在庫中未定義昂灵。

  2. 檢查符號可見性

    • C++ 函數(shù)需用 extern "C" 導出避凝,避免名稱修飾(Name Mangling)。
    • 使用 __attribute__((visibility("default"))) 確保符號可見眨补。
  3. 驗證依賴庫

    ldd libXXX.so  # 查看依賴庫
    nm -D libYYY.so | grep clickhouse::ColumnArray  # 檢查依賴庫是否包含符號
    
  4. 編譯選項檢查

    • 確保編譯時未使用 -fvisibility=hidden 隱藏符號管削。
    • 動態(tài)庫鏈接時需添加 -lXXX 指定依賴庫。

檢查某個目標文件中是否有該符號定義

nm test.o | grep 'function_name'

檢查某個庫文件中是否有該符號定義

nm -D test.so | grep 'function_name'

四撑螺、高級技巧:符號分析進階

1. 分析內存分布

通過符號地址判斷變量/函數(shù)位置:

nm -n a.out  # 按地址排序

2. 逆向調試輔助

結合 objdump 反匯編:

nm a.out | grep suspicious_func  # 獲取函數(shù)地址
objdump -d a.out | grep <地址>    # 查看匯編代碼

3. 靜態(tài)庫分析

查看 .a 文件中的目標文件:

nm -A libtest.a  # 顯示每個.o 文件的符號

五含思、常見問題 QA

Q1:nm 無法查看源碼文件(.c/.cpp)?

Anm 僅支持二進制文件(.o/.a/.so/可執(zhí)行文件)。

Q2:如何查看 C++ 類的成員函數(shù)含潘?

A:使用 -C 選項解析修飾名饲做,例如:

nm -C lib.so | grep MyClass::method

Q3:符號顯示為 V 類型是什么?

A:V 表示弱符號(Weak Symbol)遏弱,常見于虛函數(shù)表(vtable)艇炎。


結語:掌握 nm 命令,相當于擁有了透視二進制文件的“X 光眼”腾窝。無論是日常開發(fā)中的鏈接問題缀踪,還是復雜的內存分析,它都能提供關鍵線索虹脯。下次遇到符號問題時驴娃,不妨先敲一句 nm -CD,或許答案就在其中循集。

擴展工具推薦:

  • objdump:反匯編與段信息分析
  • readelf:查看 ELF 文件頭信息
  • ldd:動態(tài)庫依賴檢查

參考文檔:

  1. Linux 命令詳解:nm
  2. C++ 符號解析實戰(zhàn)
  3. 靜態(tài)庫與動態(tài)庫分析
  4. undefined reference 排查案例
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末唇敞,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子咒彤,更是在濱河造成了極大的恐慌疆柔,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,807評論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件镶柱,死亡現(xiàn)場離奇詭異旷档,居然都是意外死亡,警方通過查閱死者的電腦和手機歇拆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,284評論 3 399
  • 文/潘曉璐 我一進店門鞋屈,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人故觅,你說我怎么就攤上這事厂庇。” “怎么了输吏?”我有些...
    開封第一講書人閱讀 169,589評論 0 363
  • 文/不壞的土叔 我叫張陵权旷,是天一觀的道長。 經(jīng)常有香客問我贯溅,道長拄氯,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,188評論 1 300
  • 正文 為了忘掉前任盗迟,我火速辦了婚禮坤邪,結果婚禮上,老公的妹妹穿的比我還像新娘罚缕。我一直安慰自己艇纺,他們只是感情好,可當我...
    茶點故事閱讀 69,185評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著黔衡,像睡著了一般蚓聘。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上盟劫,一...
    開封第一講書人閱讀 52,785評論 1 314
  • 那天夜牡,我揣著相機與錄音,去河邊找鬼侣签。 笑死塘装,一個胖子當著我的面吹牛,可吹牛的內容都是我干的影所。 我是一名探鬼主播蹦肴,決...
    沈念sama閱讀 41,220評論 3 423
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼猴娩!你這毒婦竟也來了阴幌?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 40,167評論 0 277
  • 序言:老撾萬榮一對情侶失蹤卷中,失蹤者是張志新(化名)和其女友劉穎矛双,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蟆豫,經(jīng)...
    沈念sama閱讀 46,698評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡议忽,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,767評論 3 343
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了无埃。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片徙瓶。...
    茶點故事閱讀 40,912評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡毛雇,死狀恐怖嫉称,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情灵疮,我是刑警寧澤织阅,帶...
    沈念sama閱讀 36,572評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站震捣,受9級特大地震影響荔棉,放射性物質發(fā)生泄漏。R本人自食惡果不足惜蒿赢,卻給世界環(huán)境...
    茶點故事閱讀 42,254評論 3 336
  • 文/蒙蒙 一润樱、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧羡棵,春花似錦壹若、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,746評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽养篓。三九已至,卻和暖如春赂蕴,著一層夾襖步出監(jiān)牢的瞬間柳弄,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,859評論 1 274
  • 我被黑心中介騙來泰國打工概说, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留碧注,地道東北人。 一個月前我還...
    沈念sama閱讀 49,359評論 3 379
  • 正文 我出身青樓糖赔,卻偏偏與公主長得像应闯,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子挂捻,可洞房花燭夜當晚...
    茶點故事閱讀 45,922評論 2 361

推薦閱讀更多精彩內容