天天看點

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 程式會使用的途徑,包括 getopt、obstack、strerror、strtol 和 strtoul

libbfd

二進制檔案描述器庫

libopcodes

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

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

1、 addr2line 

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

Binutils工具集 解析

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

Binutils工具集 解析

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

Binutils工具集 解析

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

Binutils工具集 解析

2、as

as彙編器,将彙編代碼彙編成目标檔案

3、 size  

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

Binutils工具集 解析

4、nm

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

Binutils工具集 解析

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

第一列是指程式運作時的符号所對應的位址,對于函數則位址表示的是函數的開始位址,對于變量則表示的是變量的存儲位址;

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

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

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

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

Binutils工具集 解析

5、strip 

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

Binutils工具集 解析

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

6、objdump  

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

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

Binutils工具集 解析

2)-- 反彙編

Binutils工具集 解析

7、objcopy 

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

      作用:格式轉換

 例:objcopy -O binary  xx  xx.bin

8、readelf

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

Binutils工具集 解析