【软件开发底层知识修炼】七 Binutils辅助工具之- ar工具与nm工具
生活随笔
收集整理的這篇文章主要介紹了
【软件开发底层知识修炼】七 Binutils辅助工具之- ar工具与nm工具
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
學習交流加
- 個人qq:
1126137994 - 個人微信:
liu1126137994 - 學習交流資源分享qq群:
962535112
上一篇文章學習addr2line與strip工具。點擊鏈接查看上一篇文章:點擊查看
本篇文章學習兩個工具:ar與nm工具。
文章目錄
- 1、ar工具
- 2、nm工具
- 2.1 代碼案例分析
- 3、總結
1、ar工具
ar工具很簡單,用于將目標文件打包生成庫或者將目標文件從庫中解壓出來
- ar crs libname.a x.o y.o 將x.o y.o打包生成libname.a庫
- ar x libname.a 將libname.a庫解壓
2、nm工具
nm工具用于列出目標文件的符號的相關信息:地址,屬性,名字等
使用nm工具,可以輸出三部分內容:地址,段,標識符
如下圖的例子;
其中標識符位于的段信息,需要說明一下。上述的T代表代碼段。還有很多其他段標識符如下圖:
它們具體的信可以參考《程序員的自我修養》,參考這本書后,可以更加詳細的說明各個段標識代表什么意思。如下表:
| B | 該符號的值出現在非初始化數據段(.bss)中。例如,在一個文件中定義全局static int test。則該符號test的類型為b,位于bss section中。其值表示該符號在bss段中的偏移。一般而言,bss段分配于RAM中 。 |
| C | 該符號為common。common symbol是未初始話數據段。該符號沒有包含于一個普通section中。只有在鏈接過程中才進行分配。符號的值表示該符號需要的字節數。例如在一個c文件中,定義int test,并且該符號在別的地方會被引用,則該符號類型即為C。否則其類型為B。 |
| D | 該符號位于初始化數據段中。一般來說,分配到.data section中。例如定義全局int baud_table[5] = {9600, 19200, 38400, 57600, 115200},則會分配于初始化數據段中。 |
| G | 該符號也位于初始化數據段中。主要用于small object提高訪問small data object的一種方式。 |
| I | 該符號是對另一個符號的間接引用。 |
| N | 該符號是一個debugging符號。 |
| R | 該符號位于只讀數據段。例如定義全局const int test[] = {123, 123};則test就是一個只讀數據區的符號。注意在cygwin下如果使用gcc直接編譯成MZ格式時,源文件中的test對應_test,并且其符號類型為D,即初始化數據段中。但是如果使用m6812-elf-gcc這樣的交叉編譯工具,源文件中的test對應目標文件的test,即沒有添加下劃線,并且其符號類型為R。一般而言,位于rodata section。值得注意的是,如果在一個函數中定義const char *test = “abc”, const char test_int = 3。使用nm都不會得到符號信息,但是字符串“abc”分配于只讀存儲器中,test在rodata section中,大小為4。 |
| S | 符號位于非初始化數據段,用于small object。 |
| T | 該符號位于代碼段text section。 |
| U | 該符號在當前文件中是未定義的,即該符號的定義在別的文件中。例如,當前文件調用另一個文件中定義的函數,在這個被調用的函數在當前就是未定義的;但是在定義它的文件中類型是T。但是對于全局變量來說,在定義它的文件中,其符號類型為C,在使用它的文件中,其類型為U。 |
| V | 該符號是一個weak object。 |
| W | The symbol is a weak symbol that has not been specifically tagged as a weak object symbol. |
| - | 該符號是a.out格式文件中的stabs symbol。 |
| ? | 該符號類型沒有定義。 |
2.1 代碼案例分析
還是以上一篇文章的代碼為例(代碼是運行時錯誤的,但是這不影響我們的實驗);
test.c
#include <stdio.h>int g_global = 0; int g_test = 1;extern int* g_pointer; extern void func();int main(int argc, char *argv[]) {printf("&g_global = %p\n", &g_global);printf("&g_test = %p\n", &g_test);printf("&g_pointer = %p\n", &g_pointer);printf("g_pointer = %p\n", g_pointer);printf("&func = %p\n", &func);printf("&main = %p\n", &main);func();return 0; }func.c
#include <stdio.h>int* g_pointer;void func() {*g_pointer = (int)"D.T.Software";return; }對以上兩個程序分別進行如下編譯:
- gcc -g -c func.c -o func.o
- gcc -g -c test.c -o test.o
然后使用nm工具分別查看func.o與test.o
通過以上結果,可以看出
在func.o中:
- func符號位于代碼段,這顯而易見
- g_pointer符號是一個未定義存儲段的符號。參考上表即可知道它的意思
在test.o中
- func未定義,因為它本身是在func.c中定義的
- g_global位于.bss段
- g_pointer未定義
- g_test位于數據段
- main位于代碼段
- printf未定義,因為它是引自標準庫中的代碼
3、總結
學會使用ar工具與nm工具。了解nm輸出對應的符號的說明信息,參考本文表格。
本文參考狄泰軟件學院相關課程
想學習的可以加狄泰軟件學院群,
群聊號碼:199546072
學習探討加個人(可以免費幫忙下載CSDN資源):
qq:1126137994
微信:liu1126137994
總結
以上是生活随笔為你收集整理的【软件开发底层知识修炼】七 Binutils辅助工具之- ar工具与nm工具的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 路由引入—思科命令
- 下一篇: 生成0到1之间随机数的C代码