Я привязываюсь к использованию 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
В результате получается объект с именами символов, которые будут иметь 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
Общий метод включения необработанных данных в 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," <foo.S.in | gcc -x assembler-with-cpp - -o passwd.o -c
Другой альтернативой, которую я использовал, является cd
в исходный каталог, а затем дать objcopy
базовое имя источника. В bash
, это было бы:
cd $(dirname $SOURCE)
objcopy ... $(basename $SOURCE) $TARGET
Таким образом, генерируемые символы всегда _binary_file_name_xxx
без пути.
Одним из простых решений является преобразование вашего текстового файла в то, что можно использовать для инициализации массива char. Таким образом, вы получите 0x41,0x42,0x43,0x30,0x31,0x32 для «ABC012». Затем вы можете #include эту последовательность байтов. Вы также можете побег все не-ASCII-символы вместо того, чтобы преобразовывать все в байты, так что большая часть текста по-прежнему читается в сгенерированном включаемом файле.