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

zne*_*eak 5 macos xcode objcopy

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

在Linux上,似乎可以用来objcopy从二进制文件制作目标文件:

objcopy --input binary --output elf32-i386 --binary-architecture i386 myfile.dat myfile.o
Run Code Online (Sandbox Code Playgroud)

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

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

Ken*_*ses 8

在链接阶段,将参数传递-sectcreate <segname> <sectname> <file>给链接器。如果您通过调用编译器来驱动链接器(这很常见),您会将它作为-Wl,-sectcreate,<segname>,<sectname>,<file>.

您将组成段和部分名称。

你会使用的getsectdata()功能以及_dyld_get_image_vmaddr_slide()在运行时获得一个指向该数据。


zne*_*eak 3

正如有关 的另一个问题objcopy中所证明的,将二进制文件包含到可执行文件中的另一种方法是使用.incbin汇编程序指令。与此解决方案相比,该解决方案有两个主要优点objcopy:开发人员可以控制符号名称(objcopy似乎有一个固定的方案来命名它们),并且,它不需要objcopy.

该解决方案还比基于链接器的-sectcreate解决方案具有优势。它是跨平台的,并且访问数据更加简单。

我使用这个 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
Run Code Online (Sandbox Code Playgroud)

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

    .global _data_start_somefile
    .global _data_end_somefile
_data_start_somefile:
    .incbin "somefile.gen.out"
_data_end_somefile:
Run Code Online (Sandbox Code Playgroud)

data_start_somefile可以使用和符号在 C 中访问数据data_end_somefile(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
}
Run Code Online (Sandbox Code Playgroud)

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