objcopy将目录路径名添加到符号名称之前

我想使用objcopy将二进制forms的文本文件包含到可执行文件中。 (在运行时我需要将文件作为字符串)。 这工作正常,直到链接器需要从符号名称中查找引用。 问题是objcopy在符号名称objcopy加上文件的路径名。 由于我使用GNU Autotools发送包,这个前置路径名发生了变化,我不知道在C / C ++程序中使用什么外部链接器符号。

 nm libtest.a |grep textfile textfile.o: 00001d21 D _binary__home_git_textfile_end 00001d21 A _binary__home_git_textfile_size 00000000 D _binary__home_git_textfile_start 

libtest.a是用(从Makefile.am中提取)生成的:

 SUFFIXES = .txt .txt.$(OBJEXT): objcopy --input binary --output elf32-i386 --binary-architecture i386 $< $@ 

我怎样才能告诉objcopy只将文件名的词干作为链接符号? 或者还有另一种解决问题的方法吗?

有点讽刺的是,您可以使用objcopy通过--redefine-sym选项来解决问题,该选项允许重命名符号……

如果我使用objcopy从另一个目录中的PNG创建一个目标文件:

 $ objcopy -I binary -O elf64-x86-64 -B i386 --rename-section .data=.rodata,alloc,load,data,contents,readonly ../../resources/test.png test_png.o 

生成的对象具有以下符号:

 $readelf -s test_png.o -W Symbol table '.symtab' contains 5 entries: Num: Value Size Type Bind Vis Ndx Name 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 1: 0000000000000000 0 SECTION LOCAL DEFAULT 1 2: 0000000000000000 0 NOTYPE GLOBAL DEFAULT 1 _binary_______resources_test_png_start 3: 0000000000003aaa 0 NOTYPE GLOBAL DEFAULT 1 _binary_______resources_test_png_end 4: 0000000000003aaa 0 NOTYPE GLOBAL DEFAULT ABS _binary_______resources_test_png_size 

然后可以重命名这些:

 $objcopy --redefine-sym _binary_______resources_test_png_start=_binary_test_png_start test_png.o $objcopy --redefine-sym _binary_______resources_test_png_size=_binary_test_png_size test_png.o $objcopy --redefine-sym _binary_______resources_test_png_end=_binary_test_png_end test_png.o 

如果PNG位于当前目录中,则导致具有objcopy将生成的符号名称的对象:

 $readelf -s test_png.o -W Symbol table '.symtab' contains 5 entries: Num: Value Size Type Bind Vis Ndx Name 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 1: 0000000000000000 0 SECTION LOCAL DEFAULT 1 2: 0000000000000000 0 NOTYPE GLOBAL DEFAULT 1 _binary_test_png_start 3: 0000000000003aaa 0 NOTYPE GLOBAL DEFAULT 1 _binary_test_png_end 4: 0000000000003aaa 0 NOTYPE GLOBAL DEFAULT ABS _binary_test_png_size 

将原始数据包含到ELF中的通用方法由.incbin汇编程序指令支持。

诀窍是创建模板.S文件,如下所示:

  .global foo_start foo_start: .incbin "foo.raw" .global foo_end foo_end: 

这个文件是通过cpp预处理的,所以我们不必在那里硬编码文件名,例如。 我们可以写:

  .incbin __raw_file_path__ 

…然后在编译时传递它:

 gcc -D__raw_file_path__='"data/foo.png"' foo.S -c -o data/foo.o 

最后,当我们准备.S文件时,我们可以添加一些额外的数据和/或信息。 如果您包含原始“文本文件”并希望这些文件可用作C字符串,则可以在原始数据之后添加“0”字节:

  .global foo_start foo_start: .incbin "foo.raw" .global foo_end foo_end: .byte 0 .global foo_size foo_size: .int foo_end - foo_start 

如果你想要全面的灵活性,你当然可以手动预处理文件来改变它的任何部分,例如。

 .global @sym@_start @sym@_start: .incbin "@file@" .global @sym@_end @sym@_end: 

…然后编译它:

 sed -e "s,@sym@,passwd,g" -e "s,@file@,/etc/passwd,"  

我使用的另一种方法是cd到源目录,然后给objcopy提供objcopy的基名。 在bash ,这将是:

 cd $(dirname $SOURCE) objcopy ... $(basename $SOURCE) $TARGET 

这样生成的符号总是_binary_file_name_xxx而没有路径。

一个简单的解决方案是将文本文件转换为可用于初始化char数组的文件。 所以,对于“ABC012”,你得到0x41,0x42,0x43,0x30,0x31,0x32。 然后,您可以#include这个字节序列。 您还可以转义所有非ASCII字符,而不是将所有内容转换为字节,以便大多数文本在生成的包含文件中仍然可读。