鍍金池/ 教程/ Linux/ nm 目標文件格式分析
進程管理工具
objdump 二進制文件分析
scp 跨機遠程拷貝
crontab 定時任務(wù)
readelf elf文件格式分析
pstack 跟蹤進程棧
系統(tǒng)管理及IPC資源管理
vmstat 監(jiān)視內(nèi)存使用情況
strace 跟蹤進程中的系統(tǒng)調(diào)用
sar 找出系統(tǒng)瓶頸的利器
ipcs 查詢進程間通信狀態(tài)
ps 進程查看器
性能優(yōu)化
wget 文件下載
top linux下的任務(wù)管理器
磁盤管理
size 查看程序內(nèi)存映像大小
free 查詢可用內(nèi)存
文件及目錄管理
iostat 監(jiān)視I/O子系統(tǒng)
性能監(jiān)控
程序構(gòu)建
學(xué)會使用命令幫助
gdb 調(diào)試利器
網(wǎng)絡(luò)工具
nm 目標文件格式分析
lsof 一切皆文件
用戶管理工具
程序調(diào)試
ldd 查看程序依賴庫
文本處理

nm 目標文件格式分析

nm 命令顯示關(guān)于指定 File 中符號的信息,文件可以是對象文件、可執(zhí)行文件或?qū)ο笪募?。如果文件沒有包含符號信息,nm 命令報告該情況,但不把它解釋為出錯條件。 nm 命令缺省情況下報告十進制符號表示法下的數(shù)字值。

$nm myProgrammer
08049f28 d _DYNAMIC
08049ff4 d _GLOBAL_OFFSET_TABLE_
080484dc R _IO_stdin_used
         w _Jv_RegisterClasses
08049f18 d __CTOR_END__
08049f14 d __CTOR_LIST__
08049f20 D __DTOR_END__
08049f1c d __DTOR_LIST__
080485e0 r __FRAME_END__
08049f24 d __JCR_END__
08049f24 d __JCR_LIST__
0804a014 A __bss_start
0804a00c D __data_start
08048490 t __do_global_ctors_aux
08048360 t __do_global_dtors_aux
0804a010 D __dso_handle
         w __gmon_start__
08048482 T __i686.get_pc_thunk.bx
08049f14 d __init_array_end
08049f14 d __init_array_start
08048480 T __libc_csu_fini
08048410 T __libc_csu_init
         U __libc_start_main@@GLIBC_2.0
0804a014 A _edata
0804a01c A _end
080484bc T _fini
080484d8 R _fp_hw
080482b4 T _init
08048330 T _start
0804a014 b completed.6086
0804a00c W data_start
0804a018 b dtor_idx.6088
080483c0 t frame_dummy
080483e4 T main
         U printf@@GLIBC_2.0

這些包含可執(zhí)行代碼的段稱為正文段。同樣地,數(shù)據(jù)段包含了不可執(zhí)行的信息或數(shù)據(jù)。另一種類型的段,稱為 BSS 段,它包含以符號數(shù)據(jù)開頭的塊。對于 nm 命令列出的每個符號,它們的值使用十六進制來表示(缺省行為),并且在該符號前面加上了一個表示符號類型的編碼字符。

可以將目標文件中所包含的不同的部分劃分為段。段可以包含可執(zhí)行代碼、符號名稱、初始數(shù)據(jù)值和許多其他類型的數(shù)據(jù)。有關(guān)這些類型的數(shù)據(jù)的詳細信息,可以閱讀 UNIX 中 nm 的 man 頁面,其中按照該命令輸出中的字符編碼分別對每種類型進行了描述。

選項說明

  • -a或--debug-syms:顯示所有的符號,包括debugger-only symbols。
  • -B:等同于--format=bsd,用來兼容MIPS的nm。
  • -C或--demangle:將低級符號名解析(demangle)成用戶級名字。這樣可以使得C++函數(shù)名具有可讀性。
  • --no-demangle:默認的選項,不需要將低級符號名解析成用戶級名。
  • -D或--dynamic:顯示動態(tài)符號。該任選項僅對于動態(tài)目標(例如特定類型的共享庫)有意義。
  • -f format:使用format格式輸出。format可以選取bsd、sysv或posix,該選項在GNU的nm中有用。默認為bsd。
  • -g或--extern-only:僅顯示外部符號。
  • -n、-v或--numeric-sort:按符號對應(yīng)地址的順序排序,而非按符號名的字符順序。
  • -p或--no-sort:按目標文件中遇到的符號順序顯示,不排序。
  • -P或--portability:使用POSIX.2標準輸出格式代替默認的輸出格式。等同于使用任選項-f posix。
  • -s或--print-armap:當(dāng)列出庫中成員的符號時,包含索引。索引的內(nèi)容包含:哪些模塊包含哪些名字的映射。
  • -r或--reverse-sort:反轉(zhuǎn)排序的順序(例如,升序變?yōu)榻敌?。
  • --size-sort:按大小排列符號順序。該大小是按照一個符號的值與它下一個符號的值進行計算的。
  • --target=bfdname:指定一個目標代碼的格式,而非使用系統(tǒng)的默認格式。
  • -u或--undefined-only:僅顯示沒有定義的符號(那些外部符號)。
  • --defined-only:僅顯示定義的符號。
  • -l或--line-numbers:對每個符號,使用調(diào)試信息來試圖找到文件名和行號。
  • -V或--version:顯示nm的版本號。
  • --help:顯示nm的選項。

符號說明

對于每一個符號來說,其類型如果是小寫的,則表明該符號是local的;大寫則表明該符號是global(external)的。

  • A 該符號的值是絕對的,在以后的鏈接過程中,不允許進行改變。這樣的符號值,常常出現(xiàn)在中斷向量表中,例如用符號來表示各個中斷向量函數(shù)在中斷向量表中的位置。
  • B 該符號的值出現(xiàn)在非初始化數(shù)據(jù)段(bss)中。例如,在一個文件中定義全局static int test。則該符號test的類型為b,位于bss section中。其值表示該符號在bss段中的偏移。一般而言,bss段分配于RAM中。
  • C 該符號為common。common symbol是未初始話數(shù)據(jù)段。該符號沒有包含于一個普通section中。只有在鏈接過程中才進行分配。符號的值表示該符號需要的字節(jié)數(shù)。例如在一個c文件中,定義int test,并且該符號在別的地方會被引用,則該符號類型即為C。否則其類型為B。
  • D 該符號位于初始化數(shù)據(jù)段中。一般來說,分配到data section中。 例如:定義全局int baud_table[5] = {9600, 19200, 38400, 57600, 115200},會分配到初始化數(shù)據(jù)段中。

  • G 該符號也位于初始化數(shù)據(jù)段中。主要用于small object提高訪問small data object的一種方式。
  • I 該符號是對另一個符號的間接引用。
  • N 該符號是一個debugging符號。
  • R 該符號位于只讀數(shù)據(jù)區(qū)。
    • 例如定義全局const int test[] = {123, 123};則test就是一個只讀數(shù)據(jù)區(qū)的符號。
    • 值得注意的是,如果在一個函數(shù)中定義const char *test = "abc", const char test_int = 3。使用nm都不會得到符號信息,但是字符串"abc"分配于只讀存儲器中,test在rodata section中,大小為4。
  • S 符號位于非初始化數(shù)據(jù)區(qū),用于small object。
  • T 該符號位于代碼區(qū)text section。
  • U 該符號在當(dāng)前文件中是未定義的,即該符號的定義在別的文件中。 例如,當(dāng)前文件調(diào)用另一個文件中定義的函數(shù),在這個被調(diào)用的函數(shù)在當(dāng)前就是未定義的;但是在定義它的文件中類型是T。但是對于全局變量來說,在定義它的文件中,其符號類型為C,在使用它的文件中,其類型為U。
  • V 該符號是一個weak object。
  • W The symbol is a weak symbol that has not been specifically tagged as a weak object symbol.
  • ? 該符號類型沒有定義

庫或?qū)ο竺?/em> 如果您指定了 -A 選項,則 nm 命令只報告與該文件有關(guān)的或者庫或者對象名。

示例

  1. 尋找特殊標識

有時會碰到一個編譯了但沒有鏈接的代碼,那是因為它缺失了標識符;這種情況,可以用nm和objdump、readelf命令來查看程序的符號表;所有這些命令做的工作基本一樣;

比如連接器報錯有未定義的標識符;大多數(shù)情況下,會發(fā)生在庫的缺失或企圖鏈接一個錯誤版本的庫的時候;瀏覽目標代碼來尋找一個特殊標識符的引用

nm -uCA *.o | grep foo

-u選項限制了每個目標文件中未定義標識符的輸出。-A選項用于顯示每個標識符的文件名信息;對于C++代碼,常用的還有-C選項,它也為解碼這些標識符;

objdump、readld命令可以完成同樣的任務(wù)。等效命令為:
$objdump  -t
$readelf -s
  1. 列出 a.out 對象文件的靜態(tài)和外部符
    $nm -e a.out
  1. 以十六進制顯示符號大小和值并且按值排序符號
    $nm -xv a.out
  1. 顯示 libc.a 中所有 64 位對象符號,忽略所有 32 位對象
    $nm -X64 /usr/lib/libc.a