1. 程式人生 > >Binutils工具集 解析

Binutils工具集 解析

     對於嵌入式系統開發,掌握相應的工具至關重要,它能使我們解決問題的效率大大提高。目前,可以說嵌入式系統的開發工具是GNU的天下,因為來自GNU的GCC編譯器支援大量的目標處理器。除了GCC,還有一個非常重要的、同樣來自於GNU的工具集(toolchain) —— binutils toolchain。這一工具集中存在的一些工具,可以說是我們開發和除錯不可缺少的利器。 Binutils中的工具不少和GCC相類似,也是針對特定的處理器的。

     在binutils中以下的工具是我們在做嵌入式系統開發時需要掌握的:

addr2line

將程式地址翻譯成檔名和行號;給定地址和可執行檔名稱,它使用其中的除錯資訊判斷與此地址有關聯的原始檔和行號

ar

建立、修改和提取歸檔

as

一個彙編器,將 gcc 的輸出彙編為物件檔案 into object files

c++filt

被連結器用於修復 C++ 和 Java 符號,防止過載的函式相互衝突

elfedit

更新 ELF 檔案的 ELF 頭

gprof

顯示分析資料的呼叫圖表

ld

一個連結器,將幾個物件和歸檔檔案組合成一個檔案,重新定位它們的資料並且捆綁符號索引

ld.bfd

到 ld 的硬連結

nm

列出給定物件檔案中出現的符號

objcopy

將一種物件檔案翻譯成另一種,.bin 轉換成 .elf 、.elf 轉換成 .bin等。

objdump

顯示有關給定物件檔案的資訊,包含指定顯示資訊的選項;顯示的資訊對編譯工具開發者很有用,最主要的作用是反彙編

ranlib

建立一個歸檔的內容索引並存儲在歸檔內;索引列出其成員中可重定位的物件檔案定義的所有符號

readelf

顯示有關 ELF 二進位制檔案的資訊,readelf -h *.exe進行檢視。

size

列出給定物件檔案每個部分的尺寸和總尺寸,程式碼段、資料段、總大小等。

strings

對每個給定的檔案輸出不短於指定長度 (預設為 4) 的所有可列印字元序列;對於物件檔案預設只打印初始化和載入部分的字串,否則掃描整個檔案

strip

移除物件檔案中的符號,進行檔案壓縮,進行瘦身;

libiberty

包含多個 GNU 程式會使用的途徑,包括 getoptobstackstrerrorstrtol 和 strtoul

libbfd

二進位制檔案描述器庫

libopcodes

一個庫,用於處理 opcodes——處理器指令的 “可讀文字” 版本;用於編制 objdump 這樣的工具


下面是各命令的詳細使用方法:

1、 addr2line 

       addr2line是用來將程式地址轉換成其所對應的程式原始檔及所對應的程式碼行,當然,也可以得到所對應的函式。為了說明addr2line是如何使用的,我們需要有一個練習用的程式。先採用編輯工具編輯一個test.c原始檔,其內容如圖所示。


執行如下的命令將test.c編譯成可執行檔案,注意:必須加 -g 這個選項 並執行之。在執行test程式後,我們可以在其終端上看到它打印出的fun()函式的地址 —— 0x80483e4。


現在,我們可以用這一地址來看一看addr2line是如何使用的。在終端中執行如下的命令,從命令的執行結果來看,addr2line工具正確的指出了地址0x80483e4 所對於應的程式的具體位置是在哪以及所對應的函式名是什麼。


可能有人會問了:這個0x80483e4地址是我們打印出來,即然有列印,我們一般情況下也會打印出其具體的函式位置,而不是隻列印地址,我為何要這麼繞一下通過addr2line去找到地址所對應的函式呢?其實,這裡打印出地址只是為了得到一個地址以便用於練習。在現實中,地址往往是在除錯過程中或是當程式崩潰時通過某種方式獲得的。此外,採用nm工具(後面會講到)可以得到如下的函式地址資訊。


2、as

as彙編器,將彙編程式碼彙編成目標檔案

3、 size  

size工具,就是列程式檔案中各段的大小。在後面的章節中,我們會使用objdump檢視段資訊,除了這三個段還有.rdata和.idata兩個段,其中.rdata段被歸類到.text段中,而.idata段被歸類到.data段中。下面是採用size工具所顯示出的test中的段大小資訊。


4、nm

      nm用於列出程式檔案中的符號,符號是指函式或是變數名什麼的。下面,我們來看一看圖 2所編譯出來的程式當中有些什麼符號


      nm所列出的每一行有三部分組成:

第一列是指程式執行時的符號所對應的地址,對於函式則地址表示的是函式的開始地址,對於變數則表示的是變數的儲存地址

第二列是指相應符號是放在哪一個段的;

第三列則是指符號的名稱。

在前面我們講解addr2line時,我們提到addr2line是將程式地址轉換成這一地址所對應的具體函式是什麼,而nm則是全面的列出這些資訊。但是,nm不具備列出符號所在的原始檔及其行號這一功能,因此,我們說每一個工具有其特定的功能,在嵌入式系統的開發過程中我們需要靈活的運用它們。  

       對於nm列出的第二列資訊,非常的有用,其意義在於可以瞭解我們在程式中所定義的一個符號(比如變數等等)是被放在程式的哪一個段的,下表列出了第二列將會出現的部分字母的含義,要參看所有字母的意思,請在你的開發環境中執行“man nm”。


5、strip 
      strip的功能也相對的簡單,主要用於去除程式檔案中的除錯資訊以便減小檔案的大小。對於strip的功能,其與objcopy帶--strip-debug引數時的功能是一樣的,這我們前面也有提及。strip所具有的功能,objcopy也都有。


可以看到test小了幾KB,strip在大檔案中有更好的體現。

6、objdump  

      objdump可以用來檢視目標程式中的段資訊和除錯資訊,也可以用來對目標程式進行反彙編。我們知道程式是由多個段組成的,比如.text是用來放程式碼的、.data是用來放初始化好的資料的、.bss是用來放未初始化好的資料的,等等。在嵌入式系統的開發過程中,我們有時需要知道所生成的程式中的段資訊來分析問題。比如,我們需要知道其中的某個段在程式執行時,共起始地址是什麼,或者,我們需要知道正在執行的程式中是否存在除錯資訊等等。  

1)-- 下面是使用objdump的--h選項來檢視程式中的段資訊,練習用的程式如前面的圖,這裡假設你已將其編譯成了可執行檔案test


2)-- 反彙編


7、objcopy 

      objcopy的功能非常的強大,它可以對最後生成的程式檔案進行一定的編輯。

      作用:格式轉換
 例:objcopy -O binary  xx  xx.bin

8、readelf

       readelf可以顯示elf格式可執行檔案的資訊。ELF格式是UNIX系統實驗室作為應用程式二進位制介面開發的。ELF格式是Unix/Linux平臺上應用最廣泛的二進位制工業標準之一。