在Stackoverflow看到類似的問題,紀錄一下
假設我門需要把一個resource加入執行檔或Library,可以使用以下的方法
假設我們現在有個檔案,叫做data
裡面的內容還是我們的老朋友Hello world!
有兩個方式可以達成
將檔案變成 object file
1
| $ objcopy -I binary -O elf64-x86-64 -B i386 data data.o
|
如果我們用nm來觀看其內容
1 2 3 4
| $ nm data.o 000000000000000d D _binary_data_end 000000000000000d A _binary_data_size 0000000000000000 D _binary_data_start
|
其中的A代表在之後的連結過程,其數值不會再之後的動作所更改。接著我們寫另外一段程式
1 2 3 4 5 6 7 8 9 10 11 12 13
| #include <stdio.h>
extern char my_data[] asm("_binary_data_start"); extern char my_data_size[] asm("_binary_data_size"); extern char my_data_end[] asm("_binary_data_end");
int main() { char *c; for (c = my_data; c != my_data_end; c++) putchar(*c); printf("String length: %ld\n", (long)(void *)my_data_size); return 0; }
|
編譯且執行他
1 2 3 4
| $ gcc test.c data.o -o test $ ./test Hello world! String length: 13
|
從code可以看出,我們的my_data就是對應_binary_data_start的部分
please reference Controlling Names Used in Assembler Code
重新用nm看產生的執行檔,關切我們在意的部分
1 2 3 4
| $ nm test 0000000000601035 D _binary_data_end 000000000000000d A _binary_data_size 0000000000601028 D _binary_data_start
|
發現_binary_data_start跟_binary_data_end在連結之後,都被重定位了。而_binary_data_size的位置保持不變,因此可以做為一個sentinel使用。
利用工具將Binary Data轉成Header file,這邊用linux的xxd來做示範。
1
| $ xxd xxd -i data data.h
|
重寫我們的程式
1 2 3 4 5 6 7 8 9 10 11
| nclude <stdio.h> #include "data.h"
int main() { int i; for (i = 0; i < data_len; i++) putchar(data[i]); printf("String length: %d\n", data_len); return 0; }
|
編譯且執行他
1 2 3 4
| $ gcc test.c -o test $ ./test Hello world! String length: 13
|
可以得到跟上面一樣的結果。