可执行文件嵌入资源文件

在程序的编译层面,可以有一些手段,将任意文件作为一种资源嵌入到可执行文件中,在代码中通过导入符号的方式来访问文件中的内容。利用这种技术,能够很方便的做到一些单纯用C语言做不到的事情

主要介绍以下两种方法

  • incbin汇编指令
  • objcopy

本文环境为Ubuntu虚拟机+gcc编译器

1. incbin汇编指令

汇编指令中的incbin能够将外部资源文件当作一个2进制数据段处理,这种方式下需要用一个单独的汇编文件来处理

依次创建main.c、res.txt、embed.s

main.c内容如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h>

extern long _binary_res_txt_start;
extern long _binary_res_txt_end;
extern int _binary_res_txt_size;

int main(int argc, char *argv[])
{
char *start, *end;

start = &_binary_res_txt_start;
end = &_binary_res_txt_end;

printf("start:0x%x end:0x%x size%d\n",
start, end, _binary_res_txt_size);

printf("resource: %s\n", start);

return 0;
}

res.txt的内容如下

1
Hello, this is resource embeded testing.

embed.s内容如下

1
2
3
4
5
6
7
8
9
10
.section .data
.global _binary_res_txt_start
.global _binary_res_txt_end
.global _binary_res_txt_size

_binary_res_txt_start:
.incbin "res.txt"
_binary_res_txt_end:
_binary_res_txt_size:
.int _binary_res_txt_end - _binary_res_txt_start

执行以下命令编译程序

1
2
gcc main.c embed.s -o main
./main

结果

1
2
start:0xa5dd3010 end:0xa5dd3039 size:41
resource:Hello, this is resource embeded testing.

2. objcopy

objcopy是编译链中的一个工具,可以将文件作为资源编译为一个object文件

输入如下指令将res.txt生成res.o

1
objcopy -I binary -O elf64-x86-64 res.txt res.o

再将main.c和res.o编译生成main可执行文件

1
2
gcc main.c res.o -o main
./main
1
2
start:0xc7484010 end:0xc7484039 size:41
resource:Hello, this is resource embeded testing.