Linux ELF檔案格式分析---objcopy命令的使用
本文轉自:https://blog.csdn.net/xj178926426/article/details/73777611
Linux ELF檔案格式分析—objcopy命令的使用 最近在看《程式設計師的自我修養—連結、裝載與庫》一書,對書中提到的一個小問題,自己做了個試驗驗證一番,然後記錄之。其具體問題如下: 如果我們將一個二進位制檔案,比如圖片,MP3音樂,詞典一類的東西作為目標檔案的一段,該怎麼做? 可以使用objcopy工具,比如我們有一個圖片檔案”image.jpg” 大小為8846Bytes :
[[email protected] testforobjcopy]$ ls -al image.jpg -rw-rw-r-- 1 james_xie james_xie 8846 Jun 21 12:51 image.jpg
[[email protected] testforobjcopy]$ objcopy -I binary -O elf64-x86-64 -B i386 image.jpg image.o
[[email protected] testforobjcopy]$ objdump -ht image.o
image.o: file format elf64-x86-64
Sections: Idx Name Size VMA LMA File off Algn 0 .data 0000228e 0000000000000000 0000000000000000 00000040 2**0 CONTENTS, ALLOC, LOAD, DATA SYMBOL TABLE: 0000000000000000 l d .data 0000000000000000 .data 0000000000000000 g .data 0000000000000000 _binary_test_jpg_start 000000000000228e g .data 0000000000000000 _binary_test_jpg_end 000000000000228e g *ABS* 0000000000000000 _binary_test_jpg_size 符號“_binary_test_jpg_start”,“ _binary_test_jpg_end”和“_binary_test_jpg_size”分別表示該圖片檔案在記憶體中的起始地址,結束地址和大小,我們可以在程式裡面直接宣告並使用它們。 下面結合一個簡單的例子來嘗試,新建一個檔名為test.c的檔案:
#include <stdio.h>
extern char _binary_test_jpg_start; extern char _binary_test_jpg_end; extern char _binary_test_jpg_size;
int main() { int i = 0; unsigned char *p = NULL; printf("_binary_test_jpg_start 0x%lx\n",(unsigned long)&_binary_test_jpg_start); printf("_binary_test_jpg_end 0x%lx\n",(unsigned long)&_binary_test_jpg_end); printf("_binary_test_jpg_size %ld\n",(unsigned long)&_binary_test_jpg_size);
p = (unsigned char *)(unsigned long)&_binary_test_jpg_start; printf("First 8 bytes of the Image : \n"); for(i=0;i<8;++i){ printf("0x%02x ",*p++); } printf("\n");
return 0; } 首先把該檔案編譯成目標檔案(.o檔案):
gcc -c test.c 連結生成最後的可執行檔案:
gcc test.o image.o -o test 執行結果如下:
[[email protected] testforobjcopy]$ ./test _binary_test_jpg_start 0x601044 _binary_test_jpg_end 0x6032d2 _binary_test_jpg_size 8846 First 8 bytes of the Image : 0xff 0xd8 0xff 0xe0 0x00 0x10 0x4a 0x46 程式碼非常簡單,沒什麼值得深入分析的,但是還有個小小的疑問,符號的值(即symbol’s value),通常可通過如下命令去檢視:
[[email protected] testforobjcopy]$ objdump -t test
test: file format elf64-x86-64
SYMBOL TABLE: ...... 0000000000601044 g .data 0000000000000000 _binary_test_jpg_start ...... 000000000000228e g *ABS* 0000000000000000 _binary_test_jpg_size 00000000006032d2 g .data 0000000000000000 _binary_test_jpg_end ...... 為了更加直觀,其他的符號表的輸出結果被刪除,其結果中第一列就是我所說的符號的值(即symbol’s value),按照我的理解這個值應該是該符號(symbol)的虛擬記憶體地址,為了驗證我這個想法,我上面的例子程式碼中嘗試去列印_binary_test_jpg_start開始位置的連續8個位元組的值,跟我直接通過hexdump命令檢視圖片檔案的值一樣:
[[email protected] testforobjcopy]$ hexdump -C image.jpg 00000000 ff d8 ff e0 00 10 4a 46 49 46 00 01 01 00 00 01 |......JFIF......| 00000010 00 01 00 00 ff db 00 43 00 0f 0f 0f 0f 0f 0f 0f |.......C........| 00000020 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f |................| * 這說明我的理解是對的,但是我還有個疑問就是這個符號“_binary_test_jpg_size”,這個符號的值(即symbol’s value)是000000000000228e,轉換位十進位制剛好是8846,即為我們圖片檔案的大小,這很明顯應該不是一個地址,但是我上面的程式碼中,確確實實是通過
printf("_binary_test_jpg_size %ld\n",(unsigned long)&_binary_test_jpg_size); 地址取操作符&來訪問的,而且如果我要是去掉這個地址操作符,如下方操作的話:
printf("_binary_test_jpg_size %ld\n",(unsigned long)_binary_test_jpg_size); 會直接出現:Segmentation fault (core dumped),即我們常碰到的段錯誤,這時我就有點方了,為了驗證這個問題,我絕對去研究下objcopy的程式碼,看看它裡面定義絕對符號(Absolute Symbol)表是具體怎麼操作的,將在下一篇文章中來進行分析,未完待續。