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

时间:2013-03-24 03:53:38

标签: c++ c objcopy

我想用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只将文件名的词干作为链接符号?或者还有另一种解决问题的方法吗?

5 个答案:

答案 0 :(得分:8)

有点讽刺的是,您可以使用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
     

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

$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

答案 1 :(得分:7)

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

诀窍是创建模板.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," <foo.S.in | gcc -x assembler-with-cpp - -o passwd.o -c

答案 2 :(得分:4)

我使用的另一个替代方法是cd到源目录,然后为objcopy提供源的基本名称。在bash中,这将是:

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

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

答案 3 :(得分:0)

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

答案 4 :(得分:0)

我必须使用cmake进行此操作,最终我使用/ dev / stdin作为输入来获得一致的符号名称,然后通过以下方式重新定义符号: 字符串(MAKE_C_IDENTIFIER ...) 然后在生成的目标文件上使用objcopy --redefine-sym。

则结果函数为:

function(make_binary_object __file)
    get_filename_component(__file_name ${__file} NAME)
    set(__object ${CMAKE_CURRENT_BINARY_DIR}/${__file_name}.obj)
    string(MAKE_C_IDENTIFIER ${__file_name} __file_c_identifier)
    add_custom_command(OUTPUT ${__object}
        COMMAND ${CMAKE_OBJCOPY}
            --input-format binary
            --output-format elf64-x86-64
            --binary-architecture i386:x86-64
            /dev/stdin
            ${__object} < ${__file}
        COMMAND ${CMAKE_OBJCOPY}
            --redefine-sym _binary__dev_stdin_start=_binary_${__file_c_identifier}_start
            --redefine-sym _binary__dev_stdin_end=_binary_${__file_c_identifier}_end
            --redefine-sym _binary__dev_stdin_size=_binary_${__file_c_identifier}_size
            ${__object}
        WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
        DEPENDS ${__file})
    set_source_files_properties(${__object} PROPERTIES EXTERNAL_OBJECT TRUE)
endfunction()

您可以像这样使用它:

make_binary_object(index.html)

add_executable(my_server
    server.c
    ${CMAKE_CURRENT_BINARY_DIR}/index.html.obj)