1. 程式人生 > >Linux的nm檢視動態和靜態庫中的符號

Linux的nm檢視動態和靜態庫中的符號

功能

列出.o .a .so中的符號資訊,包括諸如符號的值,符號型別及符號名稱等。所謂符號,通常指定義出的函式,全域性變數等等。

使用

nm [option(s)] [file(s)]

有用的options:

  • -A 在每個符號資訊的前面列印所在物件檔名稱;
  • -C 輸出demangle過了的符號名稱;
  • -D 列印動態符號;
  • -l 使用物件檔案中的除錯資訊打印出所在原始檔及行號;
  • -n 按照地址/符號值來排序;
  • -u 打印出那些未定義的符號;

常見的符號型別:

  • A 該符號的值在今後的連結中將不再改變;
  • B 該符號放在BSS段中,通常是那些未初始化的全域性變數;
  • D 該符號放在普通的資料段中,通常是那些已經初始化的全域性變數;
  • T 該符號放在程式碼段中,通常是那些全域性非靜態函式;
  • U 該符號未定義過,需要自其他物件檔案中連結進來;
  • W 未明確指定的弱連結符號;同連結的其他物件檔案中有它的定義就用上,否則就用一個系統特別指定的預設值。

注意幾點:

  • -C 總是適用於c++編譯出來的物件檔案。還記得c++中有過載麼?為了區分過載函式,c++編譯器會將函式返回值/引數等資訊附加到函式名稱中去形成一個mangle過的符號,那用這個選項列出符號的時候,做一個逆操作,輸出那些原始的、我們可理解的符號名稱。
  • 使用 -l 時,必須保證你的物件檔案中帶有符號調式資訊,這一般要求你在編譯的時候指定一個 -g 選項,見 Linux:Gcc
  • 使用nm前,最好先用
    Linux:File檢視物件檔案所屬處理器架構,然後再用相應交叉版本的nm工具。

舉例

更詳細的內容見man page。這裡舉例說明:

nm -u hello.o
顯示hello.o 中的未定義符號,需要和其他物件檔案進行連結.
nm -A /usr/lib/* 2>/dev/null | grep "T memset"

在 /usr/lib/ 目錄下找出哪個庫檔案定義了memset函式.