天天看點

linux程式分析工具

ldd和nm是Linux下兩個非常實用的程式分析工具。ldd是用來分析程式運作時需要依賴的動态連結庫的工具,nm是用來檢視指定程式中的符号表資訊的工具,objdump用來檢視源代碼與彙編代碼,-d隻檢視彙編代碼,-S檢視c和彙編代碼。

源代碼如上邊所示,偷懶,直接使用了别人的代碼。

1、使用指令:gcc -g tooltest.c -o tooltest 編譯源碼生成可執行檔案tooltest

2、使用指令:ldd tooltest 其中ldd工具用來分析程式運作時需要依賴的動态連結庫

3、使用指令:nm tooltest 其中nm工具用來檢視指定程式中的符号表資訊

4、使用指令:objdump -S tooltest 其中objdump工具用來檢視C源代碼與彙編代碼

補充如下:

1、ldd

格式:ldd [options] file   

功能:列出file運作所需的共享庫

參數:

      -d    執行重定位并報告所有丢失的函數

      -r    執行對函數和對象的重定位并報告丢失的任何函數或對象

上邊是ldd的輸出結果,将其分為3列來看:

■ 第一列:程式需要依賴什麼庫

■ 第二列:系統提供的與程式需要的庫對應的庫名稱

■ 第三列:依賴庫加載的開始位址

通過上面的這些資訊,我們可以總結出下面的用途:

(1) 通過對比第一列和第二列,我們可以知道程式需要的動态連結庫和系統實際提供的是否相比配。

(2) 通過第三列,我們可以知道目前動态連結庫中的符号在程序位址空間中的起始位置。

2、nm

格式:nm [options] file   

功能:列出file中的所有符号

     -C   将符号轉化為使用者級的名字

     -s   當用于.a檔案即靜态庫時,輸出把符号名映射到定義該符号的子產品或成員名的索引

     -u   顯示在file外定義的符号或沒有定義的符号

     -l   顯示每個符号的行号,或為定義符号的重定義項

上面便是tooltest這個程式中所有的符号,首先介紹一下上面輸出内容的格式:

■ 第一列:目前符号的位址。

■ 第二列:目前符号的類型(關于類型的說明,可以檢視手冊頁man nm詳細閱讀)。

■ 第三列:目前符号的名稱。

使用nm主要有一下幾個方面的幫助:

(1) 判斷指定的程式中有沒有指定的符号,比較常用的方式為:nm –C program | grep symbol

(2) 解決程式編譯時undefined reference的錯誤,以及multiple definition的錯誤。

(3) 檢視某個符号的位址,以及在程序空間的大概位置(.bss, .data, .text段,具體可以通過第二列的類型來判斷)。

顯示結果的符号如下:

A : 該符号的值是絕對的,在以後的連結過程中,不允許進行改變。這樣的符号值,常常出現在中斷向量表中,例如用符号來表示各個中斷向量函數在中斷向量表中的位置。

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。

? : 該符号類型沒有定義。

3、objdump

格式:objdump [options] file   

      -s    隻是顯示彙編源碼

      -S    同時顯示彙編和C語言代碼

都見到源代碼了,想怎麼折騰都可以,盡情發揮吧

4、splint

格式:splint [options] file.c   

功能:列出file.c代碼的缺陷

  容易看出有4個代碼警告,也可以在代碼編輯時使用-Wall選項來完成同樣的工作。

人就像是被蒙着眼推磨的驢子,生活就像一條鞭子;當鞭子抽到你背上時,你就隻能一直往前走,雖然連你也不知道要走到什麼時候為止,便一直這麼堅持着。