objcopy prepends directory pathname to symbol name

谁说我不能喝 提交于 2019-11-30 12:41:15

Somewhat ironically you can use objcopy to solve the problem via the --redefine-sym option that allows renaming of symbols...

If I use objcopy to create an object file from a PNG in another directory:

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

The resulting object has the following symbols:

$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

These can then be renamed:

$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

Resulting in an object with the symbol names that objcopy would have generated if the PNG had been located in the current directory:

$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

Generic method of including raw data into ELF is supported by .incbin assembler directive.

The trick is to create template .S file that could look like this:

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

        .global foo_end
foo_end:    

This file is preprocessed via cpp so we don't have to hardcode file name there, eg. we can write:

        .incbin __raw_file_path__

... and then pass it while compiling:

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

Lastly, as we prepare .S file ourself we can add some extra data and/or information. If you include raw "text files" and want these to be available as C strings you can add '0' byte just after raw data:

        .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

If you want full-blown flexibility, you can of course pre-process file manually to alter any part of it, eg.

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

... and then compile it:

sed -e "s,@sym@,passwd,g" -e "s,@file@,/etc/passwd," <foo.S.in | gcc -x assembler-with-cpp - -o passwd.o -c

Another alternative which I have used is to cd to the source directory and then give objcopy the basename of the source. In bash, this would be:

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

This way the symbols generated are always _binary_file_name_xxx without the path.

One simple solution is to transform your text file into what could be used to initialize an array of char. So, you'd get 0x41,0x42,0x43,0x30,0x31,0x32 for "ABC012". You can then #include this sequence of bytes. You can also escape all non-ASCII chars instead of converting everything into bytes so that most of the text is still readable in the generated include file.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!