2.3.1測試----objdump學習
阿新 • • 發佈:2021-11-01
2.3.1測試
20191331 lyx
測試要求
0 推薦在OpenEuler系統中實現
1 編輯並執行2.3.1中的程式碼,要求在不修改t2.c 和 t1.c中main函式中的程式碼的情況下,程式執行結果是你的後四位學號。提交程式碼和執行結果截圖。
2 網上學習objdump命令,提交不少於5篇部落格連結和微信讀書上的圖書連結,並給出你認為最好的講解資源的連結或圖書名及章節
3 用objdump分析第1步中的可執行檔案和目標檔案,提交你的分析截圖以及如何和教材講解內容對應的,比如obj檔案的檔案頭,程式碼段,資料段等,可執行檔案如何連結mysum的。
0.實驗準備
- 實驗環境
本次實驗使用 OpenEuler 20.03LTS
1.編輯並執行
- 實驗程式碼
********************t1.c*******************
#include <stdio.h>
int g = 100;
int h;
static int s;
main(int argc,char *argv[]){
int a = 1; int b ;
static int c = 3;
b =2;
c = mysum(a,b);
printf("sum = %d\n",c);
}
********************t2.c******************* extern int g; int mysum(int x,int y){ return 1229*x + y + g; }
實驗截圖:
2.objdump學習
objdump命令是用檢視目標檔案或者可執行的目標檔案的構成的gcc工具。
--archive-headers -a 顯示檔案庫的成員資訊,類似ls -l將lib*.a的資訊列出。 -b bfdname --target=bfdname 指定目標碼格式。這不是必須的,objdump能自動識別許多格式,比如: objdump -b oasys -m vax -h fu.o 顯示fu.o的頭部摘要資訊,明確指出該檔案是Vax系統下用Oasys編譯器生成的目標檔案。objdump -i將給出這裡可以指定的目標碼格式列表。 -C --demangle 將底層的符號名解碼成使用者級名字,除了去掉所開頭的下劃線之外,還使得C++函式名以可理解的方式顯示出來。 --debugging -g 顯示除錯資訊。企圖解析儲存在檔案中的除錯資訊並以C語言的語法顯示出來。僅僅支援某些型別的除錯資訊。有些其他的格式被readelf -w支援。 -e --debugging-tags 類似-g選項,但是生成的資訊是和ctags工具相相容的格式。 --disassemble -d 從objfile中反彙編那些特定指令機器碼的section。 -D --disassemble-all 與 -d 類似,但反彙編所有section. --prefix-addresses 反彙編的時候,顯示每一行的完整地址。這是一種比較老的反彙編格式。 -EB -EL --endian={big|little} 指定目標檔案的小端。這個項將影響反彙編出來的指令。在反彙編的檔案沒描述小端資訊的時候用。例如S-records. -f --file-headers 顯示objfile中每個檔案的整體頭部摘要資訊。 -h --section-headers --headers 顯示目標檔案各個section的頭部摘要資訊。 -H --help 簡短的幫助資訊。 -i --info 顯示對於 -b 或者 -m 選項可用的架構和目標格式列表。 -j name --section=name 僅僅顯示指定名稱為name的section的資訊 -l --line-numbers 用檔名和行號標註相應的目的碼,僅僅和-d、-D或者-r一起使用使用-ld和使用-d的區別不是很大,在原始碼級除錯的時候有用,要求編譯時使用了-g之類的除錯編譯選項。 -m machine --architecture=machine 指定反彙編目標檔案時使用的架構,當待反彙編檔案本身沒描述架構資訊的時候(比如S-records),這個選項很有用。可以用-i選項列出這裡能夠指定的架構. --reloc -r 顯示檔案的重定位入口。如果和-d或者-D一起使用,重定位部分以反彙編後的格式顯示出來。 --dynamic-reloc -R 顯示檔案的動態重定位入口,僅僅對於動態目標檔案意義,比如某些共享庫。 -s --full-contents 顯示指定section的完整內容。預設所有的非空section都會被顯示。 -S --source 儘可能反彙編出原始碼,尤其當編譯的時候指定了-g這種除錯引數時,效果比較明顯。隱含了-d引數。 --show-raw-insn 反彙編的時候,顯示每條彙編指令對應的機器碼,如不指定--prefix-addresses,這將是預設選項。 --no-show-raw-insn 反彙編時,不顯示彙編指令的機器碼,如不指定--prefix-addresses,這將是預設選項。 --start-address=address 從指定地址開始顯示資料,該選項影響-d、-r和-s選項的輸出。 --stop-address=address 顯示資料直到指定地址為止,該項影響-d、-r和-s選項的輸出。 -t --syms 顯示檔案的符號表入口。類似於nm -s提供的資訊 -T --dynamic-syms 顯示檔案的動態符號表入口,僅僅對動態目標檔案意義,比如某些共享庫。它顯示的資訊類似於 nm -D|--dynamic 顯示的資訊。 -V --version 版本資訊 --all-headers -x 顯示所可用的頭資訊,包括符號表、重定位入口。-x 等價於-a -f -h -r -t 同時指定。 -z --disassemble-zeroes 一般反彙編輸出將省略大塊的零,該選項使得這些零塊也被反彙編。
對目標檔案.o
的反彙編:
gcc -c -o main.o main.c
objdump -s -d main.o > main.o.txt
對可執行檔案.exe
或.elf
的反彙編:
gcc -o main main.c
objdump -s -d main > main.txt
我認為學習objdump最好的兩篇部落格:
- Linux下C程式的反彙編【轉】 https://www.cnblogs.com/sky-heaven/p/8547950.html
- objdump反彙編程式碼閱讀 http://cxd2014.github.io/2019/12/12/objdump/
知識補充
每個.0
檔案都包含:
- 一個檔案頭,包含程式碼段、資料段和BSS段的大小
- 一個程式碼段,包含機器指令
- 一個數據段,包含初始化全域性變數和初始化靜態區域性變數
- 一個BSS段,包含未初始化全域性變數和未初始化靜態區域性變數
- 程式碼中的指標以及資料和BSS中的偏移量的重定位資訊
- 一個符號表,包含非靜態全域性變數、函式名稱及其屬性
可執行檔案包含以下部分:
- 檔案頭:檔案頭包含可執行檔案的載入資訊和大小,其中
- tsize=程式碼段大小
- dsize=包含初始化全域性變數和初始化靜態區域性變數的資料段大小
- bsize=包含未初始化全域性變數和未初始化靜態區域性變數的bss段大小
- total_size=載入的可執行檔案的總大小
- 程式碼段:也稱為正文段,其包含程式的可執行程式碼。程式碼段從標準C啟動程式碼zrt0.o開始,該程式碼呼叫main()函式。
- 資料段:資料段包含初始化全域性變數和初始化靜態資料
- 符號表:可選,僅位執行除錯所需。
參考資料:
- 怎麼將二進位制程式碼轉換為中間程式碼(IR) https://www.zhihu.com/question/36734147/answer/80345324
- 為何.o檔案Objdump反彙編看不到函式名,二進位制反彙編能看到? https://bbs.csdn.net/topics/392027741
- objdump反彙編程式碼閱讀 http://cxd2014.github.io/2019/12/12/objdump/
- Linux下C程式的反彙編【轉】 https://www.cnblogs.com/sky-heaven/p/8547950.html
- 反彙編工具 objdump的使用簡介 https://www.cnblogs.com/yygsj/p/5023789.html
- objdump命令 https://man.linuxde.net/objdump
- objdump命令的使用 https://blog.csdn.net/beyondioi/article/details/7796414
- objdump(Linux)反彙編命令使用指南 https://zhuanlan.zhihu.com/p/335550245
3.使用objdump分析可執行檔案和目標檔案
使用objdump分析目標檔案:
使用objdump分析可執行檔案:
由於我在t1.c中引用了stdio.h
標準庫 這就導致我的可執行程式反彙編後會包含所呼叫的stdio.h
庫中的內容,使反編譯檔案分析難度加大。
資料段:初始化的全域性變數和初始化的靜態區域性變數
main函式:
mysum函式引用:
顯示所可用的頭資訊,包括符號表、重定位入口:
可執行程式和目標檔案的聯絡: