Странности ELF и динамическое связывание в ARM linux - PullRequest
3 голосов
/ 26 февраля 2010

В двоичных файлах ARM-эльфов есть вещи, которые я бы хотел лучше понять.

Мне нужно выяснить это, чтобы получить мои доморощенные ассемблеры для вывода исполняемых файлов ELF для gp2x f200. Итак, я начал с компиляции этой программы с помощью кросс-компиляции open2x:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(){
    chdir("/usr/gp2x");
    execl("/usr/gp2x/gp2xmenu", "/usr/gp2x/gp2xmenu", NULL);
    return 0;
}

В остальном все выглядит просто хорошо, ничего особенного по сравнению с x86. В заголовках ELF используется поле Flags! Я нашел некоторые спецификации ARM-эльфов, но не указано, зачем они нужны.

ELF Header:
  Magic:   7f 45 4c 46 01 01 01 61 00 00 00 00 00 00 00 00 
  Class:                             ELF32
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            ARM
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           ARM
  Version:                           0x1
  Entry point address:               0x82f8
  Start of program headers:          52 (bytes into file)
  Start of section headers:          3032 (bytes into file)
  Flags:                             0x202, has entry point, GNU EABI, software FP
  Size of this header:               52 (bytes)
  Size of program headers:           32 (bytes)
  Number of program headers:         6
  Size of section headers:           40 (bytes)
  Number of section headers:         31
  Section header string table index: 28

Теперь другие структуры не сильно отличаются от того, что есть на x86. На самом деле это выглядит очень знакомо! Даже тип перемещения знаком (R_386_JUMP_SLOT против R_ARM_JUMP_SLOT). Хотя здесь все начинает странно.

Relocation section '.rel.plt' at offset 0x280 contains 4 entries:
 Offset     Info    Type            Sym.Value  Sym. Name
00010638  00000116 R_ARM_JUMP_SLOT   000082c8   abort
0001063c  00000416 R_ARM_JUMP_SLOT   000082d4   __libc_start_main
00010640  00000516 R_ARM_JUMP_SLOT   000082e0   execl
00010644  00000716 R_ARM_JUMP_SLOT   000082ec   chdir

Disassembly of section .plt:

000082b4 <.plt>:
    82b4:   e52de004    str lr, [sp, #-4]!
    82b8:   e59fe004    ldr lr, [pc, #4]    ; 82c4 <.plt+0x10>
    82bc:   e08fe00e    add lr, pc, lr
    82c0:   e5bef008    ldr pc, [lr, #8]!
    82c4:   00008368    andeq   r8, r0, r8, ror #6
    82c8:   e28fc600    add ip, pc, #0  ; 0x0
    82cc:   e28cca08    add ip, ip, #32768  ; 0x8000
    82d0:   e5bcf368    ldr pc, [ip, #872]!
    82d4:   e28fc600    add ip, pc, #0  ; 0x0
    82d8:   e28cca08    add ip, ip, #32768  ; 0x8000
    82dc:   e5bcf360    ldr pc, [ip, #864]!
    82e0:   e28fc600    add ip, pc, #0  ; 0x0
    82e4:   e28cca08    add ip, ip, #32768  ; 0x8000
    82e8:   e5bcf358    ldr pc, [ip, #856]!
    82ec:   e28fc600    add ip, pc, #0  ; 0x0
    82f0:   e28cca08    add ip, ip, #32768  ; 0x8000
    82f4:   e5bcf350    ldr pc, [ip, #848]!

Если вы посмотрите на Sym.Value, он указывает на этот PLT. Проблема в том, что я не понимаю, как это должно работать. Что вызывает R_ARM_JUMP_SLOT здесь? Почему мой PLT содержит эти странные инструкции и как их выполняет мой динамический компоновщик?

    82ec:   e28fc600    add ip, pc, #0  ; 0x0
    82f0:   e28cca08    add ip, ip, #32768  ; 0x8000
    82f4:   e5bcf350    ldr pc, [ip, #848]!

Программа загружается в 0x8000, поэтому я понимаю эту часть. За исключением того, что я не могу понять, как это может быть одинаково, если я скомпилирую это с -fPIC -shared.

Итак. Как работает динамическое связывание в ARM?

1 Ответ

1 голос
/ 27 февраля 2010

Я решил это сам сегодня вечером. Существует множество возможных механизмов перемещения на ARM Linux. Я посмотрел на спецификации и нашел относительно нормальный вид перемещения: R_ARM_ABS32. Единственное, что мне нужно было сделать - это использовать его.

По сравнению с бэкэндом X86 ELF мне не нужно было ничего менять, кроме байтов в заголовке elf, чтобы они соответствовали тем, которые я нашел в двоичных файлах, созданных gcc. Для безопасности я выровнял некоторые структуры в двоичном формате.

В будущем я должен предоставить способ для вставки кода ветвления в мой PLT или воспользоваться другим подходом, который позволит мне создавать более крупные программы, использующие разделяемые библиотеки. Это проблема разработки ассемблера больше, чем проблема понимания формата ELF.

Запустил мое первое приложение в gp2x f200 всего несколько минут назад! Он использовал функцию 'system' -libc для записи приветствия в файл и вернулся в главное меню машины. \ О /

...