Linux二进制实用工具Binutils工具集解析()
From:http://blog.csdn.net/zqixiao_09/article/details/50783007
GNU Binutils:http://www.gnu.org/software/binutils/
GNU Binutils詳解:http://www.crifan.com/files/doc/docbook/binutils_intro/release/html/binutils_intro.html
交叉編譯詳解:http://www.crifan.com/files/doc/docbook/cross_compile/release/html/cross_compile.html
? ? ?對于嵌入式系統開發,掌握相應的工具至關重要,它能使我們解決問題的效率大大提高。目前,可以說嵌入式系統的開發工具是GNU的天下,因為來自GNU的GCC編譯器支持大量的目標處理器。除了GCC,還有一個非常重要的、同樣來自于GNU的工具集(toolchain) —— binutils toolchain。這一工具集中存在的一些工具,可以說是我們開發和調試不可缺少的利器。 Binutils中的工具不少和GCC相類似,也是針對特定的處理器的。
? ? ?在binutils中以下的工具是我們在做嵌入式系統開發時需要掌握的:
| addr2line | 將程序地址翻譯成文件名和行號;給定地址和可執行文件名稱,它使用其中的調試信息判斷與此地址有關聯的源文件和行號。 |
| ar | 創建、修改和提取歸檔 |
| as | 一個匯編器,as工具主要用來將匯編語言編寫的源程序轉換成二進制形式的目標代碼。Linux平臺的標準匯編器是GAS,它是Gnu GCC編譯器所依賴的后臺匯編工具,通常包含在Binutils軟件包中。 |
| c++filt | 被鏈接器用于修復 C++ 和 Java 符號,防止重載的函數相互沖突 |
| elfedit | 更新 ELF 文件的 ELF 頭 |
| gprof | 顯示分析數據的調用圖表。gprof是Linux下一個強有力的程序分析工具。能夠以“日志”的形式記錄程序運行時的統計信息:程序運行中各個函數消耗的時間和函數調用關 系,以及每個函數被調用的次數等等。從而可以幫助程序員找出眾多函數中耗時最多的函數,也可以幫助程序員分析程序的運行流程。相信這些功能對于分析開源代 碼的程序員來說,有著相當大的誘惑力;同時我們也可以借助gprof進行性能優化和分析。 |
| ld | 一個鏈接器,將幾個對象和歸檔文件組合成一個文件,重新定位它們的數據并且捆綁符號索引。同as一樣,ld也是GNU Binutils工具集中重要的工具,Linux使用ld作為標準的鏈接程序,由匯編器產生的目標代碼是不能直接在計算機上運行的,它必須經過鏈接器的處 理才能生成可執行代碼,鏈接是創建一個可執行程序的最后一個步驟,ld可以將多個目標文件鏈接成為可執行程序,同時指定了程序在運行時是如何執行的。 |
| ld.bfd | 到?ld?的硬鏈接 |
| nm | 列出給定對象文件中出現的符號(列出目標文件(.o)的符號清單) |
| objcopy | 將一種對象文件翻譯成另一種,.bin 轉換成 .elf 、.elf 轉換成 .bin等。 |
| objdump | 顯示有關給定對象文件的內容信息,包含指定顯示信息的選項;顯示的信息對編譯工具開發者很有用(能實現(ar,nm)的很多功能) |
| ranlib | 創建一個歸檔的內容索引并存儲在歸檔內;索引列出其成員中可重定位的對象文件定義的所有符號。ranlib 生成索引以加快對歸檔文件的訪問,并將結果保存到這個歸檔文件中,在索引中列出了歸檔文件各個成員所定義的可重分配目標文件。ar -s可以實現類似的功能。 |
| readelf | 顯示有關 ELF 二進制文件的信息,readelf -h *.exe進行查看。是ELF文件查看利器。 |
| size | 列出給定對象文件每個部分的尺寸和總尺寸,代碼段、數據段、總大小等。 |
| strings | 對每個給定的文件輸出不短于指定長度 (默認為 4) 的所有可打印字符序列;對于對象文件默認只打印初始化和加載部分的字符串,否則掃描整個文件 |
| strip | 移除對象文件中的符號,進行文件壓縮,進行瘦身。即刪除目標文件中的全部或者特定符號,這樣可以減小可執行文件的大小。在嵌入式應用中,可執行文件一般存放在flash中,空間有限,因此在產品 release的過程中采用strip對程序進行裁剪很有必要。 |
| libiberty | 包含多個 GNU 程序會使用的途徑,包括?getopt、obstack、strerror、strtol?和?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是用來放未初始化好的數據的,等等。在嵌入式系統的開發過程中,我們有時需要知道所生成的程序中的段信息來分析問題。比如,我們需要知道其中的某個段在程序運行時,共起始地址是什么,或者,我們需要知道正在運行的程序中是否存在調試信息等等。?
objdump命令的使用
objdump命令是Linux下的反匯編目標文件或者可執行文件的命令,它還有其他作用,下面以ELF格式可執行文件test為例詳細介紹:
objdump -f test 顯示test的文件頭信息 objdump -d test 反匯編test中的需要執行指令的那些section objdump -D test 與-d類似,但反匯編test中的所有section objdump -h test 顯示test的Section Header信息 objdump -x test 顯示test的全部Header信息 objdump -s test 除了顯示test的全部Header信息,還顯示他們對應的十六進制文件代碼
舉例: 將C源代碼和反匯編出來的指令對照: 1.編譯成目標文件(要加-g選項):gcc -g -o test.c 2.輸出C源代碼和反匯編出來的指令對照的格式:objdump -S test.o
1)-- 下面是使用objdump的--h選項來查看程序中的段信息,練習用的程序如前面的圖,這里假設你已將其編譯成了可執行文件test
2)-- 反匯編
如何對任意一個二進制文件進行反匯編?
我們可以這樣做:objdump -D -b binary -m i386 a.bin
-D表示對全部文件進行反匯編,-b表示二進制,-m表示指令集架構,a.bin就是我們要反匯編的二進制文件
objdump -m可以查看更多支持的指令集架構,如i386:x86-64,i8086等
另外上面的所有objdump命令的參數同樣適用于arm-linux-objdump。
同時我們也可以指定big-endian或little-endian(-EB或-EL),我們可以指定從某一個位置開始反匯編等。所以objdump命令是非常強大的!
7、objcopy?
? ? ? objcopy的功能非常的強大,它可以對最后生成的程序文件進行一定的編輯。
? ? ??作用:格式轉換
?例:objcopy -O binary ?xx ?xx.bin
8、readelf
? ? ???readelf可以顯示elf格式可執行文件的信息。ELF格式是UNIX系統實驗室作為應用程序二進制接口開發的。ELF格式是Unix/Linux平臺上應用最廣泛的二進制工業標準之一。
常用的有以下幾個功能選項:
1)-h或者--file-header 顯示在ELF文件頭里包含的所有信息 2)-l或者--program-headers或者--segments顯示程序頭表信息,包擴有幾個段,每個段的屬性,以及每個段中包含有哪幾個節(Section) 3)-S或者--section-headers或者--sections 顯示節區表內的所有信息,包括每個節的屬性,注意這里是用的是大寫的“S” 4)-t或者--section-details 用來顯示所有節的詳細信息,感覺上但從信息量上來說,和前面的“-S”沒有什么大的不同 5)-e或者--headers 顯示所有頭的信息,包括ELF文件頭、程序頭和節頭,也就是“-h -l -S”的組合。 6)-s或者--syms或者--symbols 顯示符號表的信息,包含靜態符號表(.symtab)和動態符號表(.dynsym) 7)-r或者--relocs 顯示所有重定位入口的信息 8)-d或者--dynamic 顯示動態節區的內容 9)-x或者--hex-dump=<number|name> 顯示某個節區的二進制碼,具體哪個節可以用該節的編號或者名字來指定,例如“-x .text”
對比objdump與readelf readelf objdump nm
objdump和readelf都可以用來查看二進制文件的一些內部信息.?區別在于objdump借助BFD(LIB BFD, the Binary File Descriptor Library:http://www.mssl.ucl.ac.uk/swift/om/sw/help/man/bfd.html)而更加通用一些,?可以應付不同文件格式,?readelf則并不借助BFD,?而是直接讀取ELF格式文件的信息,?按readelf手冊頁上所說,?得到的信息也略細致一些.?
幾個功能對比.?
1. 反匯編代碼
查看源代碼被翻譯成的匯編代碼, 大概有3種方法,
1) 通過編譯器直接從源文件生成, 如gcc -S
2) 對目標代碼反匯編, 一種是靜態反匯編, 就是使用objdump
3) 另外一種就是對運行時的代碼反匯編, 一般通過gdb
readelf并不提供反匯編功能.
objdump可以指定反匯編哪個節, 一般只有對包含指令的節反匯編才有意義. 而對于一些其他的類型的節, objdump也可以將特殊節的數據以解析后的形式呈現出來, 例如對于.plt, 輸出如下:
Linux開發工具 — readelf、objdump、hexdump。:http://blog.csdn.net/u011118014/article/details/20869441
總結
以上是生活随笔為你收集整理的Linux二进制实用工具Binutils工具集解析()的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Office 安装
- 下一篇: JavaScript 和 typeScr