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