1. 程式人生 > >Linux ELF檔案格式分析---objcopy命令的使用

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)表是具體怎麼操作的,將在下一篇文章中來進行分析,未完待續。