4

我想更好地理解 ARM elf 二进制文件中的某些内容。

我需要弄清楚这一点,让我的自制汇编器为 gp2x f200 输出 ELF 可执行文件。所以我开始用 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 规格,但没有提到为什么需要这些规格。

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 下如何工作?

4

1 回答 1

1

我今天晚上自己解决了。ARM linux 上有很多可能的重定位机制。我查看了规格,发现了一种相对合理的重定位:R_ARM_ABS32。我唯一要做的就是使用它。

与 X86 ELF 后端相比,除了 elf 标头中的字节以匹配我在 gcc 生成的二进制文件中找到的字节外,我不需要更改任何其他内容。为了安全起见,我将一些结构对齐为二进制。

对于未来,我必须提供一种将分支代码干预到我的 PLT 中的方法,或者采取其他一些方法,我可以生成使用共享库的更大程序。这是一个汇编程序设计问题,而不是理解 ELF 格式的麻烦。

就在几分钟前,我在 gp2x f200 中运行了我的第一个应用程序!它使用'system' -libc 函数将问候语写入文件并返回到机器的主菜单。\o/

于 2010-02-26T23:24:45.527 回答