MSVC/GCC/NDK:将二进制文件生成obj文件

2021-01-26 16:18:40 浏览数 (1)

如何将二进制文件作为数据添加到自己程序中?这是我最近遇到的问题,google上找到这两篇说得已经很清楚:

《Embedding of binary data into programs》 《Embedding Blobs in Binaries》

一种方法是将想二进制文件生成c代码,与项目一起编译,这方法对于小数据没问题,但如果二进制文件太大,生成的c代码更是巨大,增加编译器负担,好处就是完全没有跨平台问题。网上可以找到相关的工具(搜索 bin2cbin2h),比如这个embed-resource

第二种方式就是用GNU的objcopy工具来实现。 objcopy本身就提供了二进制数据转成obj文件的能力 执行如下指令即可将 file.bin 生成 elf32-i386 格式的obj文件 file.o

代码语言:javascript复制
objcopy -I binary -O elf32-i386 -B i386 file.bin file.o

另外GNU的ld也可以实现,

代码语言:javascript复制
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(NDK 19c)下需要找到正确的ld或objcopy才行, 之前我使用 $android-ndk-r19c/toolchains/llvm/prebuiltwindows-x86_64/bin/x86_64-linux-android-objcopy$android-ndk-r19c/toolchains/llvm/prebuiltwindows-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

代码语言:javascript复制
:: 将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文件

代码语言:javascript复制
ld -r -b binary -o fall_elf32_littlearm.o fall.jpg 

执行objdump查看

代码语言:javascript复制
$ 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

msvc并没有提供类型GNU objcopy的命令行工具可以直接将二进制文件转为obj文件.怎么办?有两个解决方案:

  • 如这篇文章中所说《Embedding of binary data into programs》,在网上搜索 bin2coffbin2obj可以找到第三方的工具.比如这个github上的bin2coff(我没测试)。
  • 如果你已经安装了MinGW编译器,使用MinGW提供的objcopyld就可以生成MS COFF格式的obj文件了

如下生成MSVC所需的PE格式obj文件

代码语言:javascript复制
objcopy -I binary -O pe-x86-64 -B i386 fall.jpg fall_pe-x86-64.obj

或如下使用ld来生成obj文件

代码语言:javascript复制
ld -r -b binary -o fall_pe-x86-64.obj fall.jpg 

执行objdump查看生成的fall_pe-x86-64.obj

代码语言:javascript复制
>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

代码语言:javascript复制
>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

习惯于使用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》

0 人点赞