ELF oddities and dynamic linking in ARM linux
There are things in ARM elf binaries I'd like to understand better.
I need to figure this out get my homebrew assembler output ELF executables for gp2x f200. So I started by compiling this program with open2x cross-compiling toolchain:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(){
chdir("/usr/gp2x");
execl("/usr/gp2x/gp2xmenu", "/usr/gp2x/gp2xmenu", NULL);
return 0;
}
It otherwise looks like just okay, nothing special compared to x86. In the ELF headers the Flags -field is gotten used! I found some ARM elf specs but it is not mentioned why these are needed.
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
Now the other structures do not appear very different from what they are on x86. It actually looks very much familiar! Even the type of relocation is familiar (R_386_JUMP_SLOT vs. R_ARM_JUMP_SLOT). Though here it starts going weird.
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开发者_C百科 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]!
If you look at Sym.Value, it points to this PLT. The problem is I don't understand how this is supposed to work. What is R_ARM_JUMP_SLOT causing here? Why does my PLT contain these weird instructions and how does my dynamic linker take on them?
82ec: e28fc600 add ip, pc, #0 ; 0x0
82f0: e28cca08 add ip, ip, #32768 ; 0x8000
82f4: e5bcf350 ldr pc, [ip, #848]!
The program is getting loaded into 0x8000 so I sort of understand that part. Except that I can't understand how this can be same if I compile this with -fPIC -shared.
So.. How does dynamic linking work under ARM?
I solved it myself today evening. There are lots of possible relocation mechanisms on ARM linux. I looked onto specs and found a relatively sane kind of relocation: R_ARM_ABS32. Only thing I had to do was to use it.
Compared to X86 ELF backend, I didn't need to change much anything else except the bytes in elf header to match ones I found in gcc-produced binaries. For safety I aligned some structures in binary though.
For future I have to provide a way on intervening branching code into my PLT or take some other approach I can produce larger programs that are using shared libraries. This is an assembler design issue more than a trouble in understanding ELF format.
Ran my first app in gp2x f200 just few minutes ago! It used 'system' -libc function to write a greeting into file and returned to machine's main menu. \o/
精彩评论