nm命令用於將二進制文件或可執行文件(尤其是動態庫)進行剖析
常用參數
1 // 可以直接man 2 -A 或-o或 --print-file-name:打印出每個符號屬於的文件 3 -a或--debug-syms:打印出所有符號,包括debug符號 4 -B:BSD碼顯示 5 -C或--demangle[=style]:對低級符號名稱進行解碼,C++文件需要添加 6 --no-demangle:不對低級符號名稱進行解碼,默認參數 7 -D 或--dynamic:顯示動態符號而不顯示普通符號,一般用於動態庫 8 -f format或--format=format:顯示的形式,默認爲bsd,可選爲sysv和posix 9 -g或--extern-only:僅顯示外部符號 10 -h或--help:國際慣例,顯示命令的幫助信息 11 -n或-v或--numeric-sort:顯示的符號以地址排序,而不是名稱排序 12 -p或--no-sort:不對顯示內容進行排序 13 -P或--portability:使用POSIX.2標準 14 -V或--version:國際管理,查看版本
下面來進行一段代碼解析
1 // co.c 2 #include <stdio.h> 3 int a = 1; 4 int b; 5 void func() { 6 printf("Hello World\n"); 7 } 8 int main() { 9 int a = 1; 10 func(); 11 return 0; 12 }
進行編譯(預處理器,編譯器,彙編器)生成.o重定向文件
1 gcc co.c
用nm命令來查看
1 ➜ C nm -C co.o 2 3 0000000000000000 D a 4 0000000000000004 C b 5 0000000000000000 T func 6 U _GLOBAL_OFFSET_TABLE_ 7 0000000000000017 T main 8 U puts
下面我們再來解析輸出信息中各部分所代表的意思吧
- 首先,前面那一串數字,指的就是地址
- 然後,我們發現,每一個條目前面還有一個字母,類似’U’,‘B’,'D等等,其實這些符號代表的就是當前條目所對應的內存所在部分
- 最右邊的就是對應的符號內容了
首先來看看這些符號的含義
1 A :符號的值是絕對值,不會被更改 2 B或b :未被初始化的全局數據,放在.bss段 3 D或d :已經初始化的全局數據 4 G或g :指被初始化的數據,特指small objects 5 I :另一個符號的間接參考 6 N :debugging 符號 7 p :位於堆棧展開部分 8 R或r :屬於只讀存儲區 9 S或s :指爲初始化的全局數據,特指small objects 10 T或t :代碼段的數據,.test段 11 U :符號未定義 12 W或w :符號爲弱符號,當系統有定義符號時,使用定義符號,當系統未定義符號且定義了弱符號時,使用弱符號。 13 ? :unknown符號
由上可知,
標識爲D的是已經初始化的全局數據,所以初始地址爲0000000000000000;func是在代碼段的.test段,這個地址其實是相對於不同數據區的起始地址。(這些都是由操作系統分配的虛擬地址,操作系統內部會還有一個偏移地址來確定最終的分配到存儲體上的物理地址的)。
所以後面的
main放在代碼段,由前面可知func也是代碼段,佔用了17個bit,所以main代碼段從17開始;至於前面沒有地址的標識U這些是鏈接庫中沒有被使用的,只是在庫文件中進行了使用,沒有具體實現
至於其他可見manual手冊
轉自:https://blog.csdn.net/qq_48322523/article/details/118027964