【问题标题】:objcopy prepends directory pathname to symbol nameobjcopy 将目录路径名添加到符号名称之前
【发布时间】:2013-03-13 18:20:47
【问题描述】:

我打算使用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 仅将文件名的主干作为链接器符号?还是有其他方法可以解决这个问题?

【问题讨论】:

    标签: c++ c objcopy


    【解决方案1】:

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

    【讨论】:

    • 使用stdinextern避免存储源。
    • @Alex 我不确定我理解你的意思。
    • 使用-x&lt;language&gt;-作为gcc/g++的输入
    • @Alex 这有什么帮助?抱歉,我没有关注你。
    • 这样xxd -i input.txt | sed 's/input_txt/test/' | gcc -c -xc - -o obj.o
    【解决方案2】:

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

    【讨论】:

    • --redefine-sym 的提法很好,但似乎不够:objcopy 的调用者应该如何知道如何形成“原始”符号名称?我注意到,如果 objcopy 的输入文件类似于 ../../foo/bar.txt,则符号名称类似于 _binary________foo_bar_txt_start。必须对逻辑进行编码以将点、斜线和可能的其他字符(哪个?)转换为下划线似乎很愚蠢。奇怪的是,objcopy 的 --wildcard 选项可以帮助我们,但它似乎对 --redefine-sym 没有影响(我想他们打算将它用于其他用途)。
    • @JohnZwinck:您只需要能够重建非目录部分,然后 objdump 获取名称并检查以您想要的名称结尾,然后使用它进行重命名。
    • 看代码,所有非字母数字字符都转换为_。所以下面转换文件名echo -n "$filename" | tr -c '[A-Za-z0-9]' '_'。前置 _binary_ 并附加 _start 等。
    【解决方案3】:

    .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
    

    【讨论】:

      【解决方案4】:

      我使用的另一种替代方法是将cd 指向源目录,然后将objcopy 赋予源的基本名称。在bash 中,这将是:

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

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

      【讨论】:

        【解决方案5】:

        我必须用 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)
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2019-02-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-10-28
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多