如何将二进制文件作为数据添加到自己程序中?这是我最近遇到的问题,google上找到这两篇说得已经很清楚:
《Embedding of binary data into programs》 《Embedding Blobs in Binaries》
一种方法是将想二进制文件生成c代码,与项目一起编译,这方法对于小数据没问题,但如果二进制文件太大,生成的c代码更是巨大,增加编译器负担,好处就是完全没有跨平台问题。网上可以找到相关的工具(搜索 bin2c
或 bin2h
),比如这个embed-resource
第二种方式就是用GNU的objcopy
工具来实现。
objcopy
本身就提供了二进制数据转成obj文件的能力
执行如下指令即可将 file.bin
生成 elf32-i386
格式的obj文件 file.o
objcopy -I binary -O elf32-i386 -B i386 file.bin file.o
另外GNU的ld
也可以实现,
ld -r -b binary -o file.o file.bin
与
objcopy
不同,ld
不需要指定输出格式,默认即为当前平台的obj格式,比如Windows平台下的MinGW ld则默认为pe-x86-64
,NDK 的ld默认为elf32-littlearm
可以通过执行ld --print-output-format
显示ld
默认的输出格式
在NDK(NDK 19c)下需要找到正确的ld或objcopy才行,
之前我使用 $android-ndk-r19c/toolchains/llvm/prebuilt\windows-x86_64/bin/x86_64-linux-android-objcopy
和$android-ndk-r19c/toolchains/llvm/prebuilt\windows-x86_64/bin/llvm-objcopy
都不能生成结果。
使用$android-ndk-r19c/toolchains/arm-linux-androideabi-4.9/prebuilt/windows-x86_64/arm-linux-androideabi/bin/objcopy
和$android-ndk-r19c/toolchains/llvm/prebuilt/windows-x86_64/arm-linux-androideabi/bin/objcopy
执行正常
如下执行NDK 的objcopy
生成 elf32-littlearm
格式的obj
:: 将ndk objcopy位置添加到搜索路径
$ SET PATH=${android-ndk-r19c}/toolchains/arm-linux-androideabi-4.9/prebuilt/windows-x86_64/arm-linux-androideabi/bin;%PATH%
$ objcopy -I binary -O elf32-littlearm -B arm fall.jpg fall_elf32_littlearm.o
或如下使用ld
来生成obj文件
ld -r -b binary -o fall_elf32_littlearm.o fall.jpg
执行objdump
查看
$ objdump -t -f fall_elf32_littlearm.o
fall_elf32_littlearm.o: file format elf32-littlearm
architecture: arm, flags 0x00000010:
HAS_SYMS
start address 0x00000000
SYMBOL TABLE:
00000000 l d .data 00000000 .data
00000000 g .data 00000000 _binary_fall_jpg_start
000085b9 g .data 00000000 _binary_fall_jpg_end
000085b9 g *ABS* 00000000 _binary_fall_jpg_size
msvc并没有提供类型GNU objcopy的命令行工具可以直接将二进制文件转为obj文件.怎么办?有两个解决方案:
bin2coff
或bin2obj
可以找到第三方的工具.比如这个github上的bin2coff(我没测试)。objcopy
或ld
就可以生成MS COFF格式的obj文件了如下生成MSVC所需的PE格式obj文件
objcopy -I binary -O pe-x86-64 -B i386 fall.jpg fall_pe-x86-64.obj
或如下使用ld
来生成obj文件
ld -r -b binary -o fall_pe-x86-64.obj fall.jpg
执行objdump
查看生成的fall_pe-x86-64.obj
>objdump -t fall_pe-x86-64.obj
fall_pe-x86-64.obj: file format pe-x86-64
SYMBOL TABLE:
[ 0](sec 1)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000000 _binary_fall_jpg_start
[ 1](sec 1)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000000085b9 _binary_fall_jpg_end
[ 2](sec -1)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000000085b9 _binary_fall_jpg_size
也可执行MSVC的dumpbin
查看生成的obj文件,可以确认生成的是MSVC格式obj
>dumpbin /symbols /headers fall_pe-x86-64.obj
Microsoft (R) COFF/PE Dumper Version 14.00.24215.1
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file fall_pe-x86-64.obj
File Type: COFF OBJECT
FILE HEADER VALUES
8664 machine (x64)
1 number of sections
0 time date stamp
85F8 file pointer to symbol table
3 number of symbols
0 size of optional header
5 characteristics
Relocations stripped
Line numbers stripped
SECTION HEADER #1
.data name
0 physical address
0 virtual address
85B9 size of raw data
3C file pointer to raw data (0000003C to 000085F4)
0 file pointer to relocation table
0 file pointer to line numbers
0 number of relocations
0 number of line numbers
C0100040 flags
Initialized Data
1 byte align
Read Write
COFF SYMBOL TABLE
000 00000000 SECT1 notype External | _binary_fall_jpg_start
001 000085B9 SECT1 notype External | _binary_fall_jpg_end
002 000085B9 ABS notype External | _binary_fall_jpg_size
String Table Size = 0x46 bytes
Summary
85B9 .data
习惯于使用cmake进行项目集成编译的人会想如何将生成obj的过程集成到cmake脚本中自动化执行。关于这个问题可以参考这篇文章 《Embedding binary resources with CMake and C++11》 我就是参考它来实现的
参考资料 《Embedding of binary data into programs》 《Embedding Blobs in Binaries》 《objcopy》 《llvm-objcopy - object copying and editing tool》