TinyOS07:elf文件格式及分析工具objdump

objdump是GUN中專門用於將二進制目標代碼從一種格式轉換成另一種格式的二進制工具(對象文件格式分析工具),並且在轉存過程需可以對二進制代碼進行相關操作;

ELF簡單來說就是一種跨平臺的二進制文件。

GNU中的objdump

  1. objdump屬於GNU中的二進制工具,GNU中的二進制工具專門用於將二進制目標代碼從一種格式轉換爲另一種格式(dump單詞本身有轉存的意思)
  2. 與objdump類似的GNU二進制工具例如objcopy,用於從一個文件拷貝目標代碼到另一個文件,並在這一過程中執行各種轉換。
  3. objdump和objcopy的實現都是基於靈活的bfd二進制能夠操縱函數庫之上,基於這個庫函數的工具能夠很方便地操縱二進制目標文件。
  4. 例如通過objdump查看可執行文件的內容:使用命令如下
objdump -x -d -s 文件名
//-x:顯示文件的所有頭
//-d:反彙編任一可執行段落的內容
//-s:將程序的源代碼與其對應的反彙編代碼混合現實

例如通過objdump輸出的示例程序頭部分的內容:
這裏寫圖片描述

ELF文件

  1. Linux中的ELF(Executable and Linkable Format,可執行連接格式)是UNIX系統實驗室(USL)作爲應用程序二進制接口(Application Binary Interface,ABI)而開發和發佈的。擴展名爲elf,可用作不同操作系統之間可移植的二進制文件格式,即是一種跨平臺的二進制標準。
  2. 如果使用gcc命令的“-g”選項來編譯源代碼,那麼objdump的輸出還可以包含應用程序源代碼的完整反彙編代碼。如下例子顯示了main函數的反彙編代碼和對應的源代碼:
    這裏寫圖片描述

objdump的使用

  1. objdump -t 查看對象文件所有的符號列表,相當於 nm -s objfilename,如:
objdump -t libtest1.o的結果爲:
SYMBOL TABLE:
00000000 l    df *ABS*  00000000 libtest1.c
00000000 l    d  .text  00000000 .text
00000000 l    d  .data  00000000 .data
00000000 l    d  .bss   00000000 .bss
00000000 l    d  .rodata        00000000 .rodata
00000000 l    d  .note.GNU-stack        00000000 .note.GNU-stack
00000000 l    d  .comment       00000000 .comment
00000000 g     F .text  00000014 print_test1
00000000         *UND*  00000000 puts
  1. 使用objdump查看源代碼:
    http://blog.csdn.net/willand1981/article/details/5728972
    如何使用 objdump 查看源代碼
    1、 在編譯時必須使用-g選項,-g意爲debug,一般可以修改源代碼的 Makefile來實現 如:
    CC =(CROSSCOMPILE)gccCC= (CROSSCOM_PILE)gcc -g
    使成生的vmlinux中含有debug信息
    2、所有生成 .o 的 rule 中再加一條 /其他參數除了-c外抄生成.o文件用的參數/
    CC -E -dD -C <>/preprocessing/ (shell pwd)/$<
    生成預處理文件從這個文件裏面能很容易找到 c 源文件的宏定義
    3、objdump -h vmlinux > vmlinux.txt
    顯示 linux 內核段信息,如段的開始虛擬地址,段的長度
    4、objdump -S -l -z vmlinux > vmlinux.txt
    反彙編 vmlinux 到vmlinux.txt, vmlinux.txt 含有彙編和 c 源文件的混合代碼,看起來很方 便。而且能一步步看linux怎麼一步步運行的。
    5、objdump -S -l -z -j xxxx(section name) vmlinux > vmlinux.txt 反彙編 linux 內核段 xxxx 到文件 vmlinux.txt 中。
    6、objdump -x vmlinux > x.txt
    vmliux中所有段的頭信息,其中包口vmlinux的入口地址等
    7、objdump –debugging vmlinux > debugging.txt
    很多有用的debug信息,如函數名,結構體定義等
    我覺的用根據以上信息,ultraedit看很方便。尤其在vmlinux.txt中選中文件名,
    用ultraedit右鍵的open能馬上打開文件,很方便。
  2. –line-numbers -l 用文件名和行號標註相應的目標代碼,僅僅和-d、-D或者-r一起使用 使用-ld和使用-d的區別不是很大,在源碼級調試的時候有用,要求編譯時使用了-g之類的調試編譯選項。
    –source -S 儘可能反彙編出源代碼,尤其當編譯的時候指定了-g這種調試參數時,效果比較明顯。隱含了-d參數。
  3. objdump常用的反彙編方法(老師分享的):
    1、objdump -j .text -Sl objtest | more
    ①、-S 儘可能反彙編出源代碼,尤其當編譯的時候指定了-g這種調試參數時,效果比較明顯。隱含了-d參數。
    ②、-l 用文件名和行號標註相應的目標代碼,僅僅和-d、-D或者-r一起使用,使用-ld和使用-d的區別不是很大,在源碼級調試的時候有用,要求編譯時使用了-g之類的調試編譯選項
    ③、-j name 僅僅顯示指定section的信息
    2、同時發現objdump這個指令功能強大,下面是幾個我認爲常用的option:
    ①、objdump -x obj 以某種分類信息的形式把目標文檔的數據組織(被分爲幾大塊)輸出
    ②、objdump -t obj 輸出目標文檔的符號表
    ③、objdump -h obj 輸出目標文檔的section概括
  4. 編譯過程示例:
//將源文件blink.c編譯成目標文件blink.c;
1、avr-gcc -g -Wall -mmcu=atmega16 -c -o blink.o blink.c
//將目標文件blink.c連接成blink.elf二進制文件(elf文件其實跟.exe文件類似).
2、avr-gcc -g -Wall -mmcu=atmega16 -Wl,-Map,blink.map -o blink.elf blink.o
//通過objdumo將blink.elf文件反編譯成blink.lst文件(lst文件是一個可讀的編譯程序列表,他能夠用於計算指令週期和調試)
3、avr-objdump -h -S blink.elf > blink.lst
//objcopy將blink.lst文件解釋成blink.hex十六進制文件
4、avr-objcopy -j .text -j .data -O ihex blink.elf blink.hex
5、avr-objcopy -j .eeprom --change-section-lma .eeprom=0 -O ihex blink.elf
link_eeprom.hex

ELF文件結構
http://blog.csdn.net/joker0910/article/details/7671769
這裏寫圖片描述
靜態變量、全局變量在ELF文件中的位置, 總結:
1.初始化了的全局變量和靜態變量,最終被寫入了.data字段。(.data字段存放的是已經初始化了的全局靜態變量和局部靜態變量)
2.未被初始化的靜態變量,在彙編階段完成後,被寫入了.bss段。(.bss存放的是未初始化的全局變量和局部靜態變量))
3.未被初始化的全局變量,直到執行鏈接,生成可執行文件後,才被寫入.bss段。

objdump、GNU目標文件可執行文件常用命令

這裏寫圖片描述

gcc:GCC編譯器常用命令
這裏寫圖片描述

ELF格式data、bss、text段內容調查連接:
http://www.docin.com/p-683111172.html

ELF格式文件符號表全解析及readelf命令使用方法:http://blog.csdn.net/edonlii/article/details/8779075

從交叉編譯器生成的elf文件中讀取全局變量信息
這個恐怕不是一個函數能解決的,ELF文件格式還是有點複雜的。 我以前做過類似的功能,從ELF文件中加載所有符號表信息,字符串信息,並下載代碼。 我推薦你用一個開源的庫:ELFIO。 我想這個庫應該可以實現你的功能,只是你要去研究一下它的用法。 當然,你得首先對ELF文件格式有所瞭解。ELFIO庫下載地址:

http://sourceforge.net/projects/elfio/

addr2line:把ELF文件的機器地址轉換到代碼對應的位置。

  1. add2line原來只要跟pc指針就行了。
    一般程序被dump後,dump信息裏會有pc的指針內容,只要將這個pc指針地址作爲add2line的地址,就能很快找出被dump的代碼的位置。這個在嵌入式的程序的調試中很有用。
  2. 列表內容

用法:
add2line -e file [address…]
eg:add2line -e app.exe 0x00382316
上面app.exe爲發生dump情況的程序,0x00382316爲dump出來的pc指針地址,在pc上將這個命令執行一下就會得到出問題的代碼的位置(文件名和行號)。

注意點:
編譯的時候需加上-g選項,另外由於我們的c庫文件是沒有-g選項的,所以如果dump發生在c庫函數裏,那麼這個方法就無能爲力了。否則還是很好用的。

ELF文件分析相關工具(待完善)
-wwm-ChinaUnix博客:

http://www.01yun.com/cc/20130706/562869.html

ELF可執行文件分析工具集binutil, 包括以下工具:
ld - the GNU linker.
as - the GNU assembler.
addr2line - Converts addresses into filenames and line numbers.
ar - A utility for creating, modifying and extracting from archives.
c++filt - Filter to demangle encoded C++ symbols.
gprof - Displays profiling information.
nlmconv - Converts object code into an NLM.
nm - Lists symbols from object files.
objcopy - Copys and translates object files.
objdump - Displays information from object files.
ranlib - Generates an index to the contents of an archive.
readelf - Displays information from any ELF format object file.
size - Lists the section sizes of an object or archive file.
strings - Lists printable strings from files.
strip - Discards symbols.
windres - A compiler for Windows resource files.
其中部分工具對調試極有幫助,如:
你可以用objdump反彙編,查看目標文件或可執行文件內部信息。
你可以用addr2line把機器地址轉換到代碼對應的位置。
你可以用nm查看目標文件或可執行文件中的各種符號。
你可以用gprof分析各個函數的使用情況,找出性能的瓶頸所在(這需要加編譯選項)。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章