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

后端 未结 2 495
失恋的感觉
失恋的感觉 2021-02-09 07:18

My command-line program\'s build process generates a binary file (over 500KB) that currently has to be referenced by path from argv. I would like to embed this file in the execu

相关标签:
2条回答
  • 2021-02-09 07:33

    During the link phase, pass the arguments -sectcreate <segname> <sectname> <file> to the linker. If you're driving the linker via an invocation of the compiler, which is pretty common, you'd pass it as -Wl,-sectcreate,<segname>,<sectname>,<file>.

    You'd make up segment and section names.

    You would use the getsectdata() function along with _dyld_get_image_vmaddr_slide() to get a pointer to the data at runtime.

    0 讨论(0)
  • 2021-02-09 07:34

    As evidenced in this other question about objcopy, another way to include a binary file into an executable is to use the .incbin assembler directive. This solution has two main advantages over objcopy: the developer is in control of the symbol names (objcopy appears to have a fixed scheme to name them), and, well, it doesn't require objcopy.

    The solution also has advantages over the linker-based -sectcreate solution. It's cross-platform and accessing the data is much, much more straightforward.

    I'm using this Xcode build rule script to generate the file to be included and an assembly file with the .incbin directive:

    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
    

    Then, given a file "somefile.gen" that is processed with this rule, the assembly will look like:

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

    The data can be accessed in C using the data_start_somefile and data_end_somefile symbols (the macOS linker prefixes C names with a spurious _, that's why the assembly file has them):

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

    The answer on the other thread has more bells and whistles that some people may find useful (for instance, a length symbol).

    0 讨论(0)
提交回复
热议问题