學習交流加
- 個人qq: 1126137994
- 個人微信: liu1126137994
- 學習交流資源分享qq群: 962535112
上一篇文章我們學習了gcc編譯器的相關內容。點選檢視上一篇文章:gcc編譯器。本篇文章接著上一篇文章,學習GNU為GCC提供的輔助開發工具集Binutils。Binutils工具集,主要是用於在程式碼除錯的時候,定位bug的一些手段。我們主要學習以下幾個工具的使用:
本篇文章先學習使用addr2line與strip工具。
1、addr2line工具
首先我們要知道,gcc編譯程式的時候,加上-g
選項,表示在目標檔案中生成除錯資訊。幾乎所有除錯輔助工具,都依賴於程式的除錯資訊。
addr2line工具。顧名思義,可以將地址轉換為行號。它常用於分析定位記憶體訪問錯誤的問題。以實際例子為例:
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;
}
複製程式碼
我們在linux下編譯以下程式(注意我使用gcc-4.4.5版本編譯沒有警告顯示。但是使用較高版本的gcc編譯器,可能會有警告。這裡我們忽略警告):
- gcc -g func.c test.c -o lyy
執行程式
- ./lyy
顯示結果為:
其實結果也在意料之中。我們分析程式很容易知道,func函式中 *g_pointer = (int)"D.T.Software";
這句話,使得在0地址賦值了。因為int* g_pointer;
只是定義了g_pointer
卻沒有賦值,那麼g_pointer
實際上一開始是指向0地址,後面又對它進行賦值。相當於對0地址進行操作。
但是我們知道0地址,是不能被操作的。所以會產生段錯誤。這個程式很短,問題我們很容易發現。但是如果這個歌程式有一千行,一萬行的話,那麼問題就很難定位到。此時addr2line工具就能夠上場。
下面來說明如何使用addr2line工具。
-
首先開啟core dump選項。使用命令
ulimit -c unlimited
。開啟這個選項後,在執行可執行程式的時候,會將程式崩潰前最後一刻的記憶體狀態資訊,轉儲(儲存)到一個core檔案。這個檔案叫做核心轉儲檔案。我們可以通過讀取該檔案,獲取一些用於除錯的資訊。 -
開啟core dump選項後,再次執行可執行程式,來生成core檔案。
我們可以看到,段錯誤後面顯示核心已轉儲。此時檢視當前目錄的話,就可以看到core檔案。
- 讀取core檔案,獲取IP暫存器的值(IP暫存器存的是當前CPU所要執行指令的值,程式崩潰前最後一刻的IP暫存器的值,就是崩潰的指令地址)。使用
dmesg core
命令讀取core檔案的內容,顯示內容最後部分如下:
可以看到,最後一刻IP暫存器的值為0x080483d1
.出問題的程式碼就在這個地址處。但是我們無法知道這個地址處到底是個啥。但是可以利用addr2line工具,將這個地址轉換為程式碼中對應的行號。
- 使用addr2line定位對應的程式碼行。使用命令:
addr2line 0x080483d1 -f -e lyy
很明顯,已經找打原因,是func.c程式的第7行。當從兩萬行大程式碼中找到這個錯誤,也是很激動的!!!
2、strip工具
實際上,addr2line能夠正常工作,必須依賴於程式的除錯資訊。而我們在編譯程式的時候,也確實讓程式生成了除錯資訊。如上編譯的時候帶的-g
選項。
當可執行程式裡面帶有大量的除錯資訊,會導致可執行程式,非常的大。如果在大型的軟體中,軟體在釋出之前,肯定是要將這些除錯資訊去掉,好讓釋出出去的程式佔用記憶體空間更小,不然程式太大,對使用者來說也是非常不友好的。
其實這就是所謂的release版本的程式。在釋出之前,還需要除錯的程式,我們稱為debug版本程式。
那麼如何剔除除錯資訊?使用strip工具!如下圖是release版本的程式大小為9074:
使用strip將除錯資訊剔除後大小為5512:
結果顯而易見!!!
還有其他工具,放在下一篇文章學習!!!
3、總結
- addr2line用於將程式碼地址轉換為對應的行號。常用於定位記憶體訪問錯誤的問題
- 理解core dump選項。
- strip可以剔除目標程式中的除錯資訊,從而可以減小目的碼的大小,提升目標程式的執行效率。
- 學會使用上述兩個工具。