0%

Add resource files to executable/library for gcc

在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使用。

將檔案變成單一header file (適用於各種編譯器)

利用工具將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

可以得到跟上面一樣的結果。