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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
|
/* $FreeBSD$ */
/* From: NetBSD: rtld_start.S,v 1.1 1996/12/16 20:38:09 cgd Exp */
/*
* Copyright 1996 Matt Thomas <matt@3am-software.com>
* Copyright 2000 John D. Polstra
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <machine/asm.h>
#include <sys/syscall.h>
ENTRY(_rtld_start, 0)
alloc r2=ar.pfs,3,0,3,0
;;
1: mov r14=ip // calculate gp
addl r3=@gprel(1b),r0
;;
sub gp=r14,r3
;;
.section .sdata
2: data4 @ltv(1b) // unrelocated address of 1b
.align 8
.previous
add r15=@gprel(2b),gp
;;
ld8 r15=[r15]
;;
sub out0=r14,r15 // out0 is image base address
br.call.sptk.many rp=_rtld_reloc // fixup image
add sp=-16,sp // 16 bytes for us, 16 for _rtld
;;
mov out0=in0
add out1=16,sp // address for exit proc
add out2=24,sp // address for obj_main
br.call.sptk.many rp=_rtld // r8=_rtld(sp, &exit_proc, &obj_main)
add r16=16,sp // address for exit proc
;;
ld8 r15=[r16] // read exit proc
add sp=16,sp // readjust stack
mov b7=r8 // address of real _start
;;
alloc r2=ar.pfs,0,0,3,0 // dump register frame
mov out2=r15
;;
br.call.sptk.many rp=b7 // transfer to main program
br.call.sptk.many rp=exit // die
END(_rtld_start)
/*
* _rtld_bind_start: lookup a lazy binding and transfer to real target
*
* Arguments:
* r1 gp value for rtld
* r15 Index in plt
* r16 Obj_Entry of caller
* in0-in7 Arguments for target procedure
* rp Return address back to caller
*/
ENTRY(_rtld_bind_start, 0)
{ .mii
alloc loc0=ar.pfs,8,6,3,0 // space to save r8-r11
add r17=16-8*16,sp // leave 16 bytes for _rtld_bind
add r18=32-8*16,sp
;;
} { .mii
mov loc2=r8 // structure return address
add sp=-8*16,sp // space to save f8-f15
mov loc1=rp
;;
} { .mii
stf.spill [r17]=f8,32 // save float arguments
mov loc3=r9 // language specific
mov loc4=r10 // language specific
} { .mii
stf.spill [r18]=f9,32
mov loc5=r11 // language specific
shl out1=r15,4 // 16 * index
;;
} { .mmi
stf.spill [r17]=f10,32
stf.spill [r18]=f11,32
mov out0=r16 // Obj_Entry for caller
;;
} { .mmi
stf.spill [r17]=f12,32
stf.spill [r18]=f13,32
shladd out1=r15,3,out1 // rela offset = 24 * index
;;
} { .mmb
stf.spill [r17]=f14,32
stf.spill [r18]=f15,32
br.call.sptk.many rp=_rtld_bind
} { .mii
ld8 r14=[r8],8 // target address
add r17=16,sp
add r18=32,sp
;;
} { .mii
ld8 r1=[r8] // target gp
mov ar.pfs=loc0 // clean up
mov rp=loc1
} { .mmi
ldf.fill f8=[r17],32 // restore float arguments
ldf.fill f9=[r18],32
mov r8=loc2 // restore structure pointer
;;
} { .mmi
ldf.fill f10=[r17],32
ldf.fill f11=[r18],32
mov r9=loc3
;;
} { .mmi
ldf.fill f12=[r17],32
ldf.fill f13=[r18],32
mov r10=loc4
;;
} { .mmi
ldf.fill f14=[r17],32
ldf.fill f15=[r18],32
mov r11=loc5
;;
} { .mii
nop.m 0
mov b7=r14
add sp=8*16,sp
;;
} { .mib
alloc r14=ar.pfs,0,0,8,0 // drop our register frame
nop.i 0
br.sptk.many b7 // jump to target
}
END(_rtld_bind_start)
#define DT_NULL 0 /* Terminating entry. */
#define DT_RELA 7 /* Address of ElfNN_Rela relocations. */
#define DT_RELASZ 8 /* Total size of ElfNN_Rela relocations. */
#define DT_RELAENT 9 /* Size of each ElfNN_Rela relocation entry. */
#define R_IA_64_NONE 0 /* None */
#define R_IA_64_DIR64LSB 0x27 /* word64 LSB S + A */
#define R_IA_64_REL64LSB 0x6f /* word64 LSB BD + A */
/*
* _rtld_reloc: relocate the rtld image, apart from @fptrs.
*
* Assumes that rtld was linked at zero and that we only need to
* handle REL64LSB and DIR64LSB relocations.
*
* Arguments:
* r1 gp value for rtld
* in0 rtld base address
*/
STATIC_ENTRY(_rtld_reloc, 1)
alloc loc0=ar.pfs,1,2,0,0
mov loc1=rp
;;
movl r15=@gprel(_DYNAMIC) // find _DYNAMIC etc.
;;
add r15=r15,gp // relocate _DYNAMIC etc.
;;
1: ld8 r16=[r15],8 // read r15->d_tag
;;
ld8 r17=[r15],8 // and r15->d_val
;;
cmp.eq p6,p0=DT_NULL,r16 // done?
(p6) br.cond.dpnt.few 2f
;;
cmp.eq p6,p0=DT_RELA,r16
;;
(p6) add r18=r17,in0 // found rela section
;;
cmp.eq p6,p0=DT_RELASZ,r16
;;
(p6) mov r19=r17 // found rela size
;;
cmp.eq p6,p0=DT_RELAENT,r16
;;
(p6) mov r22=r17 // found rela entry size
;;
br.sptk.few 1b
2:
ld8 r15=[r18],8 // read r_offset
;;
ld8 r16=[r18],8 // read r_info
add r15=r15,in0 // relocate r_offset
;;
ld8 r17=[r18],8 // read r_addend
sub r19=r19,r22 // update relasz
extr.u r23=r16,0,32 // ELF64_R_TYPE(r16)
;;
cmp.eq p6,p0=R_IA_64_NONE,r23
(p6) br.cond.dpnt.few 3f
;;
cmp.eq p6,p0=R_IA_64_DIR64LSB,r23
;;
(p6) br.cond.dptk.few 4f
;;
cmp.eq p6,p0=R_IA_64_REL64LSB,r23
;;
(p6) br.cond.dptk.few 4f
;;
3: cmp.ltu p6,p0=0,r19 // more?
(p6) br.cond.dptk.few 2b // loop
mov r8=0 // success return value
;;
br.cond.sptk.few 9f // done
4:
ld8 r16=[r15] // read value
;;
add r16=r16,in0 // relocate it
;;
st8 [r15]=r16 // and store it back
br.cond.sptk.few 3b
9:
mov ar.pfs=loc0
mov rp=loc1
;;
br.ret.sptk.few rp
END(_rtld_reloc)
|