2016-01-06 171 views
2

我的命令行程序的構建過程生成一個二進制文件(超過500KB),目前必須由argv的路徑引用。我想將此文件嵌入到可執行文件中。如何在Mac OS X上將二進制文件的內容嵌入到可執行文件中?

在Linux上,它appears possible使用objcopy從二進制文件創建一個對象文件:

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

但是,OS X的開發工具鏈不包括objcopy把命令。缺少安裝binutils,有什麼可能?

我從Xcode構建項目,並使用自定義構建規則生成文件。

回答

2

this other question about 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 

然後,給定一個文件「somefile.gen」是與處理這條規則,大會將是這樣的:

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

的數據可以在C使用data_start_somefiledata_end_somefile符號(MacOS的連接前綴與虛假_ C名稱來訪問,這就是爲什麼assembl Ÿ文件有它們):

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符號)。

3

在鏈接階段,將參數-sectcreate <segname> <sectname> <file>傳遞給鏈接器。如果你通過調用編譯器來驅動鏈接器,這很常見,你可以通過它作爲-Wl,-sectcreate,<segname>,<sectname>,<file>

您將組成段和段名稱。

您可以使用getsectdata() function以及_dyld_get_image_vmaddr_slide()在運行時獲取指向數據的指針。

+0

'getsectiondata'中的任何事實都避免了需要強調的功能? – zneak

+0

此外,有沒有比調用_dyld_get_image_header更好的方式來獲得Mach頭? – zneak

+0

如果能夠依賴'getsectiondata()',那麼唯一的辦法就是將它記錄下來,它似乎不是。你爲什麼迷信「強調」的功能?它們被記錄在案並且使用起來非常安全。如果您需要可執行文件的Mach頭,而不是任何動態庫,並且您正在編寫可執行文件中的代碼,則可以簡單地引用'&_mh_execute_header'。請參閱/usr/include/mach-o/ldsyms.h。順便說一下,可以將索引0傳遞給dyld(3)函數(例如'_dyld_get_image_vmaddr_slide()')來引用主可執行文件。 –

相關問題