1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
|
/*
* Stolen from glibc-2.2.2 by David Schleef <ds@schleef.org>
*/
.text
.align 4
.globl _dl_linux_resolver
.globl _dl_linux_resolve
.type _dl_linux_resolve,@function
_dl_linux_resolve:
// We need to save the registers used to pass parameters, and register 0,
// which is used by _mcount; the registers are saved in a stack frame.
stwu 1,-64(1)
stw 0,12(1)
stw 3,16(1)
stw 4,20(1)
// The code that calls this has put parameters for 'fixup' in r12 and r11.
mr 3,12
stw 5,24(1)
mr 4,11
stw 6,28(1)
mflr 0
// We also need to save some of the condition register fields.
stw 7,32(1)
stw 0,48(1)
stw 8,36(1)
mfcr 0
stw 9,40(1)
stw 10,44(1)
stw 0,8(1)
bl _dl_linux_resolver@local
// 'fixup' returns the address we want to branch to.
mtctr 3
// Put the registers back...
lwz 0,48(1)
lwz 10,44(1)
lwz 9,40(1)
mtlr 0
lwz 8,36(1)
lwz 0,8(1)
lwz 7,32(1)
lwz 6,28(1)
mtcrf 0xFF,0
lwz 5,24(1)
lwz 4,20(1)
lwz 3,16(1)
lwz 0,12(1)
// ...unwind the stack frame, and jump to the PLT entry we updated.
addi 1,1,64
bctr
.LFE2:
.size _dl_linux_resolve,.LFE2-_dl_linux_resolve
#if 0
pusha /* preserve all regs */
lea 0x20(%esp),%eax /* eax = tpnt and reloc_entry params */
pushl 4(%eax) /* push copy of reloc_entry param */
pushl (%eax) /* push copy of tpnt param */
#ifdef __PIC__
call .L24
.L24:
popl %ebx
addl $_GLOBAL_OFFSET_TABLE_+[.-.L24],%ebx
movl _dl_linux_resolver@GOT(%ebx),%ebx /* eax = resolved func */
call *%ebx
#else
call _dl_linux_resolver
#endif
movl %eax,0x28(%esp) /* store func addr over original
* tpnt param */
addl $0x8,%esp /* remove copy parameters */
popa /* restore regs */
ret $4 /* jump to func removing original
* reloc_entry param from stack */
#endif
|