使用GCC的C/C++:将资源文件静态地添加到可执行文件/库中

您所在的位置:网站首页 shell调用二进制 使用GCC的C/C++:将资源文件静态地添加到可执行文件/库中

使用GCC的C/C++:将资源文件静态地添加到可执行文件/库中

2023-04-12 16:22| 来源: 网络整理| 查看: 265

From http://www.linuxjournal.com/content/embedding-file-executable-aka-hello-world-version-5967:

我最近需要在一个可执行文件中嵌入一个文件。由于我是在命令行上用gcc等工具工作,而不是用一个花哨的RAD工具来使这一切神奇地发生,所以对我来说,如何使这一切发生并不明显。在网上搜索了一下,发现了一个黑客,基本上是把它放在可执行文件的末尾,然后根据一堆我不想知道的信息来解读它在哪里。似乎应该有一个更好的方法......

objcopy可以将对象文件或可执行文件从一种格式转换为另一种格式。它所理解的格式之一是 "二进制",基本是指任何不属于它所理解的其他格式的文件。所以,你可能已经设想了这个想法:把我们想要嵌入的文件转换成一个对象文件,然后它就可以简单地与我们的其他代码链接在一起。

假设我们有一个名为data.txt的文件,我们想把它嵌入到我们的可执行文件中。

# cat data.txt Hello world

为了将其转换为我们可以与我们的程序连接的对象文件,我们只需使用objcopy来生成一个".o "文件。

# objcopy --input binary \ --output elf32-i386 \ --binary-architecture i386 data.txt data.o

这告诉objcopy,我们的输入文件是 "二进制 "格式,我们的输出文件应该是 "elf32-i386 "格式(x86上的对象文件)。--二进制-architecture选项告诉objcopy,输出文件是要在x86上 "运行 "的。这是需要的,这样ld才会接受该文件与x86的其他文件连接。人们认为将输出格式指定为 "elf32-i386 "会意味着这一点,但事实并非如此。

现在我们有了一个对象文件,我们只需要在运行链接器时包括它。

# gcc main.c data.o

当我们运行结果时,我们得到了祈祷的输出。

# ./a.out Hello world

当然,我还没有告诉你整个故事,也没有给你看main.c。当objcopy进行上述转换时,它在转换后的对象文件中加入了一些 "链接器 "符号。

_binary_data_txt_start _binary_data_txt_end

链接后,这些符号指定了嵌入文件的开始和结束。符号名称的形成是通过预加二进制并在文件名后面加上_start或_end。如果文件名包含任何在符号名中无效的字符,它们会被转换为下划线(例如data.txt变成data_txt)。如果你在使用这些符号进行链接时得到未解决的名称,在对象文件上做一个hexdump -C,并在转储的末尾查看objcopy选择的名称。

实际使用嵌入文件的代码现在应该是相当明显的。

#include extern char _binary_data_txt_start; extern char _binary_data_txt_end; main() { char* p = &_binary_data_txt_start; while ( p != &_binary_data_txt_end ) putchar(*p++); }

需要注意的一件重要而微妙的事情是,添加到对象文件中的符号并不是 "变量"。它们不包含任何数据,相反,它们的地址就是它们的值。我把它们声明为char类型,因为这对这个例子很方便:嵌入的数据是字符数据。然而,你可以把它们声明为任何类型,如果数据是一个整数数组,就声明为int,如果数据是任何foo bar的数组,就声明为struct foo_bar_t。如果嵌入的数据不是统一的,那么char可能是最方便的:当你遍历数据时,取其地址并将指针转换为适当的类型。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3