diff options
author | Scott Bambrough <scottb@netwinder.org> | 2000-04-10 21:02:33 +0000 |
---|---|---|
committer | Scott Bambrough <scottb@netwinder.org> | 2000-04-10 21:02:33 +0000 |
commit | f38e884d673d606a904096c1af631eee5295f220 (patch) | |
tree | 96da64750f0dd125f42608b62ce8b2b18a7e63f7 /gdb/arm-linux-tdep.c | |
parent | 50da7a9c68ba0c2f9a7f59bcab69f425dd85a1e4 (diff) | |
download | gdb-f38e884d673d606a904096c1af631eee5295f220.zip gdb-f38e884d673d606a904096c1af631eee5295f220.tar.gz gdb-f38e884d673d606a904096c1af631eee5295f220.tar.bz2 |
Move arm_skip_solib_resolver from arm-linux-nat.c to arm-linux-tdep.c.
2000-04-10 Philip Blundell <philb@gnu.org>
* arm-linux-nat.c (arm_skip_solib_resolver): Remove and move to
arm-linux-tdep.c.
* arm-linux-tdep.c (arm_skip_solib_resolver): New.
Diffstat (limited to 'gdb/arm-linux-tdep.c')
-rw-r--r-- | gdb/arm-linux-tdep.c | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/gdb/arm-linux-tdep.c b/gdb/arm-linux-tdep.c index 8a575a4..667fd0b 100644 --- a/gdb/arm-linux-tdep.c +++ b/gdb/arm-linux-tdep.c @@ -221,6 +221,132 @@ arm_linux_push_arguments (int nargs, value_ptr * args, CORE_ADDR sp, return sp; } +/* + Dynamic Linking on ARM Linux + ---------------------------- + + Note: PLT = procedure linkage table + GOT = global offset table + + As much as possible, ELF dynamic linking defers the resolution of + jump/call addresses until the last minute. The technique used is + inspired by the i386 ELF design, and is based on the following + constraints. + + 1) The calling technique should not force a change in the assembly + code produced for apps; it MAY cause changes in the way assembly + code is produced for position independent code (i.e. shared + libraries). + + 2) The technique must be such that all executable areas must not be + modified; and any modified areas must not be executed. + + To do this, there are three steps involved in a typical jump: + + 1) in the code + 2) through the PLT + 3) using a pointer from the GOT + + When the executable or library is first loaded, each GOT entry is + initialized to point to the code which implements dynamic name + resolution and code finding. This is normally a function in the + program interpreter (on ARM Linux this is usually ld-linux.so.2, + but it does not have to be). On the first invocation, the function + is located and the GOT entry is replaced with the real function + address. Subsequent calls go through steps 1, 2 and 3 and end up + calling the real code. + + 1) In the code: + + b function_call + bl function_call + + This is typical ARM code using the 26 bit relative branch or branch + and link instructions. The target of the instruction + (function_call is usually the address of the function to be called. + In position independent code, the target of the instruction is + actually an entry in the PLT when calling functions in a shared + library. Note that this call is identical to a normal function + call, only the target differs. + + 2) In the PLT: + + The PLT is a synthetic area, created by the linker. It exists in + both executables and libraries. It is an array of stubs, one per + imported function call. It looks like this: + + PLT[0]: + str lr, [sp, #-4]! @push the return address (lr) + ldr lr, [pc, #16] @load from 6 words ahead + add lr, pc, lr @form an address for GOT[0] + ldr pc, [lr, #8]! @jump to the contents of that addr + + The return address (lr) is pushed on the stack and used for + calculations. The load on the second line loads the lr with + &GOT[3] - . - 20. The addition on the third leaves: + + lr = (&GOT[3] - . - 20) + (. + 8) + lr = (&GOT[3] - 12) + lr = &GOT[0] + + On the fourth line, the pc and lr are both updated, so that: + + pc = GOT[2] + lr = &GOT[0] + 8 + = &GOT[2] + + NOTE: PLT[0] borrows an offset .word from PLT[1]. This is a little + "tight", but allows us to keep all the PLT entries the same size. + + PLT[n+1]: + ldr ip, [pc, #4] @load offset from gotoff + add ip, pc, ip @add the offset to the pc + ldr pc, [ip] @jump to that address + gotoff: .word GOT[n+3] - . + + The load on the first line, gets an offset from the fourth word of + the PLT entry. The add on the second line makes ip = &GOT[n+3], + which contains either a pointer to PLT[0] (the fixup trampoline) or + a pointer to the actual code. + + 3) In the GOT: + + The GOT contains helper pointers for both code (PLT) fixups and + data fixups. The first 3 entries of the GOT are special. The next + M entries (where M is the number of entries in the PLT) belong to + the PLT fixups. The next D (all remaining) entries belong to + various data fixups. The actual size of the GOT is 3 + M + D. + + The GOT is also a synthetic area, created by the linker. It exists + in both executables and libraries. When the GOT is first + initialized , all the GOT entries relating to PLT fixups are + pointing to code back at PLT[0]. + + The special entries in the GOT are: + + GOT[0] = linked list pointer used by the dynamic loader + GOT[1] = pointer to the reloc table for this module + GOT[2] = pointer to the fixup/resolver code + + The first invocation of function call comes through and uses the + fixup/resolver code. On the entry to the fixup/resolver code: + + ip = &GOT[n+3] + lr = &GOT[2] + stack[0] = return address (lr) of the function call + [r0, r1, r2, r3] are still the arguments to the function call + + This is enough information for the fixup/resolver code to work + with. Before the fixup/resolver code returns, it actually calls + the requested function and repairs &GOT[n+3]. */ + +CORE_ADDR +arm_skip_solib_resolver (CORE_ADDR pc) +{ + /* FIXME */ + return 0; +} + void _initialize_arm_linux_tdep (void) { |