В сборке, как вставить данные (или код, или символ) в начале раздела? - PullRequest
0 голосов
/ 24 ноября 2018

Я хочу вставить некоторые данные (или код, или символ) в начале определенного раздела.
Предположим, что вставить данные 0x11223344 в начале раздела <.got>.

# gcc -o test test.s
.global main

.section .got.plt
.byte 0x11, 0x22, 0x33, 0x44

main:
 nop

Однако, как вы можете видеть,
После компиляции данные добавляются в конце в <.got.plt>.

Disassembly of section .got.plt:

080495dc <_GLOBAL_OFFSET_TABLE_>:
 80495dc:   f0 94                   lock xchg %eax,%esp
 80495de:   04 08                   add    $0x8,%al
    ...
 80495e8:   86 82 04 08 11 22       xchg   %al,0x22110804(%edx)
 80495ee:   33                      .byte 0x33
 80495ef:   44                      inc    %esp


Вопрос:

Могу ли я вставить данные (или код, или символ) в начале section ?
( .. Есть ли какая-либо опция компиляции или что-то вроде директивы ассемблера? )

1 Ответ

0 голосов
/ 24 ноября 2018

Это проблема связывания, а не сборки.

Если вы попросите GCC (или лучше, ld) показать скрипт связывания с -Wl,--verbose, вы обнаружите строку

.got.plt        : { *(.got.plt)  *(.igot.plt) }

, которая инструктирует компоновщика принять все.got.plt разделов, в порядке совпадения .

Обычно компоновщик размещает файлы и разделы, совпадающие с подстановочными знаками, в порядке, в котором они видны при ссылке.

С здесь

Поскольку вы компилируете с помощью CRT, что подразумевает его собственные объектные файлы, ваши объектные файлы идут после него.
Я не знаю, стандартизирован ли этот порядок или что-то в разных версиях GCC, я думаю, что он может быть изменен в любое время.

Вы должны быть в состоянии подтвердить, что добавление -v и -Wl,-M в командную строку GCC;первая покажет вам, как GCC вызывает компоновщик, для меня это:

/usr/libexec/gcc/x86_64-redhat-linux/4.8.5/collect2 --build-id --no-add-needed --eh-frame-hdr --hash-style=gnu -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o test /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crt1.o /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crti.o /usr/lib/gcc/x86_64-redhat-linux/4.8.5/crtbegin.o -L/usr/lib/gcc/x86_64-redhat-linux/4.8.5 -L/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../.. /tmp/ccref9XH.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/x86_64-redhat-linux/4.8.5/crtend.o /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crtn.o

Это трудно увидеть, но объектный файл test.s равен /tmp/ccref9XH.o (собрал несколько строк выше в полном объемеoutput) и некоторые объектные файлы CRT передаются в collect2 перед ним.

Второй вариант покажет отображение между секциями вывода и ввода:

.got.plt        0x0000000000601000       0x25
 *(.got.plt)
 .got.plt       0x0000000000601000       0x20 /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crt1.o
                0x0000000000601000                _GLOBAL_OFFSET_TABLE_
 .got.plt       0x0000000000601020        0x5 /tmp/ccisjx2P.o
                0x0000000000601024                main

, показывая, что секция crt1.o .got.plt стоит первой (обратите внимание, что вы оставили mainв разделе .got.plt).


Я не нашел удовлетворительного способа преодолеть это.
Одна из возможностей - скопировать скрипт компоновщика и изменить определение .got.plt на что-то вроде:

.got.plt        : { *(.got.plt.pre) *(.got.plt)  *(.igot.plt) }

тогда вы можете поместить свои данные в .got.plt.pre (ПРИМЕЧАНИЕ: не проверено).
Но это кошмар для удобства обслуживания.

Я пытался поиграть с --sort-section=name из ld, который добавляет команду SORT к каждому разделу подстановочных знаков, вводимому в скрипт компоновщика.
Это должно выровнять разделы в соответствии с файлом "или имя раздела".
После нескольких попыток я заглянул в источник, и это фактически только название раздела, поэтому здесь оно бесполезно.

Я вернулся к --sort-section=alignment.
Сначала файл test.s должен быть собран в объектный файл с gcc -c test.s -o test.o.
Проблема здесь заключается в создании раздела .plt.gotв test.o с большим выравниванием, чем 8 (тот, который используется в других .plt.got разделах).
Я проверил objcopy, но ничего не нашел, может быть, кто-то найдет подходящую команду?
I 'мы лично пропатчили файл test.o с помощью шестнадцатеричного редактора, придав этому разделу 32-байтовое выравнивание.
Затем при вызове gcc -Wl,--sort-section=alignment test.o -o test получается ELF с разделом test.s перед остальными.

Однако это громоздкое решение, хотя можно легко разработать инструмент для изменения выравнивания раздела ELF, который я надеюсь найти существующий.

Извините, что ни один из вышеперечисленных вопросов не является правильным ответом на вашу проблему.

...