如何将二进制文件的内容嵌入到 Mac OS X 上的可执行文件中?

How do I embed the contents of a binary file in an executable on Mac OS X?

我的命令行程序的构建过程生成了一个二进制文件(超过 500KB),当前必须通过 argv 的路径引用该文件。我想将此文件嵌入到可执行文件中。

在 Linux 上,appears possible 使用 objcopy 从二进制文件生成目标文件:

objcopy --input binary --output elf32-i386 --binary-architecture i386 myfile.dat myfile.o

但是,OS X 开发人员工具链不包含 objcopy 命令。没有安装binutils,有什么可能?

我从 Xcode 构建我的项目,文件是使用自定义构建规则生成的。

在 link 阶段,将参数 -sectcreate <segname> <sectname> <file> 传递给 linker。如果您通过调用编译器来驱动 linker,这很常见,您可以将其作为 -Wl,-sectcreate,<segname>,<sectname>,<file>.

传递

您可以编写段和部分名称。

您将使用 getsectdata() function along with _dyld_get_image_vmaddr_slide() 在运行时获取指向数据的指针。

this other question about objcopy 所示,另一种将二进制文件包含到可执行文件中的方法是使用 .incbin 汇编指令。与 objcopy 相比,此解决方案有两个主要优势:开发人员可以控制符号名称(objcopy 似乎有固定的方案来命名它们),而且,它不需要 objcopy.

该解决方案也优于 linker-based -sectcreate 解决方案。 cross-platform 并且访问数据要简单得多。

我正在使用此 Xcode 构建规则脚本来生成要包含的文件和带有 .incbin 指令的程序集文件:

my_generation_tool -o $DERIVED_FILE_DIR/$INPUT_FILE_NAME.out $INPUT_FILE_PATH

export AS_PATH=$DERIVED_FILE_DIR/$INPUT_FILE_NAME.out.s

echo "\t.global _data_start_$INPUT_FILE_BASE" > $AS_PATH
echo "\t.global _data_end_$INPUT_FILE_BASE" >> $AS_PATH
echo "_data_start_ $INPUT_FILE_BASE:" >> $AS_PATH
echo "\t.incbin \"$INPUT_FILE_NAME.out\"" >> $AS_PATH
echo "_data_end_$INPUT_FILE_BASE:" >> $AS_PATH

然后,给定一个使用此规则处理的文件 "somefile.gen",程序集将如下所示:

    .global _data_start_somefile
    .global _data_end_somefile
_data_start_somefile:
    .incbin "somefile.gen.out"
_data_end_somefile:

可以使用 data_start_somefiledata_end_somefile 符号在 C 中访问数据(macOS 链接器在 C 名称前加上虚假的 _ 前缀,这就是汇编文件包含它们的原因) :

extern char data_start_somefile, data_end_somefile;

for (const char* c = &data_start_somefile; c != &data_end_somefile; ++c)
{
    // do something with character
}

另一个线程上的答案有更多的花里胡哨的东西,有些人可能会觉得有用(例如,length 符号)。