]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - libexec/rtld-elf/mips/rtld_start.S
bhnd(9): Fix a few mandoc related issues
[FreeBSD/FreeBSD.git] / libexec / rtld-elf / mips / rtld_start.S
1 /*      $NetBSD: rtld_start.S,v 1.10 2009/12/14 00:41:19 matt Exp $     */
2
3 /*
4  * Copyright 1997 Michael L. Hitch <mhitch@montana.edu>
5  * Portions copyright 2002 Charles M. Hannum <root@ihack.net>
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. The name of the author may not be used to endorse or promote products
17  *    derived from this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  *
30  * $FreeBSD$
31  */
32
33 #include <machine/asm.h>
34
35 #if defined(__clang__) || (defined(__GNUC__) && __GNUC__ > 4)
36         .cfi_sections .debug_frame
37 #endif
38
39 .globl _C_LABEL(_rtld_relocate_nonplt_self)
40 .globl _C_LABEL(_rtld)
41
42 #define PTR_SIZE        (1<<PTR_SCALESHIFT)
43
44 /*
45  *      a0      stack pointer
46  *      a1      rtld cleanup (filled in by dynamic loader)
47  *      a2      rtld object (filled in by dynamic loader)
48  *      a3      ps_strings
49  */
50 NESTED(rtld_start, 4*PTR_SIZE, ra)      
51         .mask   0x10090000,-PTR_SIZE
52         .set    noreorder
53         SETUP_GP
54         PTR_SUBU sp, 4*PTR_SIZE         /* adjust stack pointer */
55         SETUP_GP64(s4, rtld_start)
56         SAVE_GP(0)
57                                         /* -> 1*PTR_SIZE(sp) for atexit */
58                                         /* -> 2*PTR_SIZE(sp) for obj_main */
59         move    s0, a0                  /* save stack pointer from a0 */
60         move    s3, a3                  /* save ps_strings pointer */
61
62         PTR_LA  a1, 1f
63         bal     1f
64         PTR_LA  t0, _C_LABEL(_rtld_relocate_nonplt_self)
65 1:      PTR_SUBU a1, ra, a1             /* relocbase */
66         PTR_LA  a0, _DYNAMIC
67         PTR_ADDU t9, a1, t0
68         jalr    t9                      /* _rtld_relocate_nonplt_self(dynp, relocabase) */
69         PTR_ADDU a0, a1, a0             /* &_DYNAMIC */
70
71         move    a0, s0                  /* sp */
72         PTR_ADDU a1, sp, 2*PTR_SIZE     /* &our atexit function */
73         PTR_ADDU a2, sp, 3*PTR_SIZE     /* obj_main entry */
74         PTR_SUBU sp, 4*SZREG            /* ABI requires to reserve memory for 4 regs */
75         PTR_LA  t9, _C_LABEL(_rtld)
76         jalr    t9                      /* v0 = _rtld(sp, cleanup, objp) */
77         nop
78         PTR_ADDU sp, 4*SZREG
79
80         PTR_L   a1, 2*PTR_SIZE(sp)      /* our atexit function */
81         PTR_L   a2, 3*PTR_SIZE(sp)      /* obj_main entry */
82         PTR_ADDU sp, 4*PTR_SIZE         /* readjust stack */
83         move    a0, s0                  /* stack pointer */
84         move    t9, v0
85         PTR_SUBU sp, 4*SZREG            /* ABI requires to reserve memory for 4 regs */
86         move    ra,t9                   /* RA == PC signals backtrace routine to stop */
87         j       t9                      /* _start(sp, cleanup, obj); */
88         move    a3, s3                  /* restore ps_strings */
89 END(rtld_start)
90
91 #define XCALLFRAME_SIZ          (12*SZREG)
92 #define XCALLFRAME_RA           (10*SZREG)
93 #define XCALLFRAME_GP           (9*SZREG)
94 #define XCALLFRAME_S0           (8*SZREG)
95 #define XCALLFRAME_A3           (7*SZREG)
96 #define XCALLFRAME_A2           (6*SZREG)
97 #define XCALLFRAME_A1           (5*SZREG)
98 #define XCALLFRAME_A0           (4*SZREG)
99 #if defined(__mips_n32) || defined(__mips_n64)
100 #define XCALLFRAME_A7           (3*SZREG)
101 #define XCALLFRAME_A6           (2*SZREG)
102 #define XCALLFRAME_A5           (1*SZREG)
103 #define XCALLFRAME_A4           (0*SZREG)
104 #endif
105
106 /*
107  * Trampoline for "old" PLT stubs which use .got entries.
108  */
109         .globl  _rtld_bind_start
110         .ent    _rtld_bind_start
111 _rtld_bind_start:
112         .frame  sp, XCALLFRAME_SIZ, $15
113         .cfi_startproc simple
114         .cfi_def_cfa sp, 0
115         .cfi_register ra, $15
116         move    v1, gp                  /* save old GP */
117 #if defined(__mips_o32) || defined(__mips_o64)
118         PTR_ADDU t9, 8                  /* modify T9 to point at .cpload */
119 #endif
120         SETUP_GP
121         PTR_SUBU sp, XCALLFRAME_SIZ     /* save arguments and sp value in stack */
122         .cfi_def_cfa_offset XCALLFRAME_SIZ
123         SETUP_GP64(XCALLFRAME_GP, _rtld_bind_start)
124         SAVE_GP(XCALLFRAME_GP)
125 #if defined(__mips_n32) || defined(__mips_n64)
126         REG_S   a4,  XCALLFRAME_A4(sp)
127         .cfi_rel_offset a4, XCALLFRAME_A4
128         REG_S   a5,  XCALLFRAME_A5(sp)
129         .cfi_rel_offset a5, XCALLFRAME_A5
130         REG_S   a6,  XCALLFRAME_A6(sp)
131         .cfi_rel_offset a6, XCALLFRAME_A6
132         REG_S   a7,  XCALLFRAME_A7(sp)
133         .cfi_rel_offset a7, XCALLFRAME_A7
134 #endif
135         REG_S   a0,  XCALLFRAME_A0(sp)
136         .cfi_rel_offset a0, XCALLFRAME_A0
137         REG_S   a1,  XCALLFRAME_A1(sp)
138         .cfi_rel_offset a1, XCALLFRAME_A1
139         REG_S   a2,  XCALLFRAME_A2(sp)
140         .cfi_rel_offset a2, XCALLFRAME_A2
141         REG_S   a3,  XCALLFRAME_A3(sp)
142         .cfi_rel_offset a3, XCALLFRAME_A3
143         REG_S   $15,  XCALLFRAME_RA(sp) /* ra is in t7/t3 */
144         .cfi_rel_offset ra, XCALLFRAME_RA
145         REG_S   s0,  XCALLFRAME_S0(sp)
146         .cfi_rel_offset s0, XCALLFRAME_S0
147         move    s0, sp
148
149         move    a0, v1                  /* old GP */
150         PTR_SUBU        a0, a0, 0x7ff0          /* The offset of $gp from the   */
151                                         /* beginning of the .got section: */
152                                         /* $gp = .got + 0x7ff0, so      */
153                                         /* .got = $gp - 0x7ff0          */
154                                         /* Simple math as you can see.  */
155 #if defined(__mips_n64)
156         ld      a0, 8(a0)               /* object = pltgot[1] */
157         and     a0, a0, 0x7fffffffffffffff
158 #else
159         lw      a0, 4(a0)               /* object = pltgot[1] & 0x7fffffff */
160         and     a0, a0, 0x7fffffff
161 #endif
162         move    a1, t8                  /* symbol index */
163
164         PTR_LA  t9, _C_LABEL(_mips_rtld_bind)
165         jalr    t9
166         nop
167
168         move    sp, s0
169         REG_L   ra, XCALLFRAME_RA(sp)
170         .cfi_restore ra
171         REG_L   s0, XCALLFRAME_S0(sp)
172         .cfi_restore s0
173         REG_L   a0, XCALLFRAME_A0(sp)
174         .cfi_restore a0
175         REG_L   a1, XCALLFRAME_A1(sp)
176         .cfi_restore a1
177         REG_L   a2, XCALLFRAME_A2(sp)
178         .cfi_restore a2
179         REG_L   a3, XCALLFRAME_A3(sp)
180         .cfi_restore a3
181 #if defined(__mips_n32) || defined(__mips_n64)
182         REG_L   a4, XCALLFRAME_A4(sp)
183         .cfi_restore a4
184         REG_L   a5, XCALLFRAME_A5(sp)
185         .cfi_restore a5
186         REG_L   a6, XCALLFRAME_A6(sp)
187         .cfi_restore a6
188         REG_L   a7, XCALLFRAME_A7(sp)
189         .cfi_restore a7
190 #endif
191         RESTORE_GP64
192         PTR_ADDU sp, XCALLFRAME_SIZ
193         move    t9, v0
194         jr      t9
195         nop
196         .cfi_endproc
197 END(_rtld_bind_start)
198
199
200 /*
201  * Trampoline for PLT stubs using .pltrel entries and .got.plt.
202  */
203         .globl  _rtld_pltbind_start
204         .ent    _rtld_pltbind_start
205 _rtld_pltbind_start:
206         .frame  sp, XCALLFRAME_SIZ, $15
207         .cfi_startproc simple
208         .cfi_def_cfa sp, 0
209         .cfi_register ra, $15
210 #if defined(__mips_o32)
211         move    v1, gp                  /* save pointer to .got.plt */
212 #else
213         move    v1, t2                  /* save pointer to .got.plt */
214 #endif
215 #if defined(__mips_o32) || defined(__mips_o64)
216         PTR_ADDU t9, 8                  /* modify T9 to point at .cpload */
217 #endif
218         SETUP_GP
219         PTR_SUBU sp, XCALLFRAME_SIZ     /* save arguments and sp value in stack */
220         .cfi_def_cfa_offset XCALLFRAME_SIZ
221         SETUP_GP64(XCALLFRAME_GP, _rtld_pltbind_start)
222         SAVE_GP(XCALLFRAME_GP)
223 #if defined(__mips_n32) || defined(__mips_n64)
224         REG_S   a4,  XCALLFRAME_A4(sp)
225         .cfi_rel_offset a4, XCALLFRAME_A4
226         REG_S   a5,  XCALLFRAME_A5(sp)
227         .cfi_rel_offset a5, XCALLFRAME_A5
228         REG_S   a6,  XCALLFRAME_A6(sp)
229         .cfi_rel_offset a6, XCALLFRAME_A6
230         REG_S   a7,  XCALLFRAME_A7(sp)
231         .cfi_rel_offset a7, XCALLFRAME_A7
232 #endif
233         REG_S   a0,  XCALLFRAME_A0(sp)
234         .cfi_rel_offset a0, XCALLFRAME_A0
235         REG_S   a1,  XCALLFRAME_A1(sp)
236         .cfi_rel_offset a1, XCALLFRAME_A1
237         REG_S   a2,  XCALLFRAME_A2(sp)
238         .cfi_rel_offset a2, XCALLFRAME_A2
239         REG_S   a3,  XCALLFRAME_A3(sp)
240         .cfi_rel_offset a3, XCALLFRAME_A3
241         REG_S   $15,  XCALLFRAME_RA(sp) /* ra is in t7/t3 */
242         .cfi_rel_offset ra, XCALLFRAME_RA
243         REG_S   s0,  XCALLFRAME_S0(sp)
244         .cfi_rel_offset s0, XCALLFRAME_S0
245         move    s0, sp
246
247         move    a0, v1                  /* .got.plt */
248 #if defined(__mips_n64)
249         ld      a0, 8(a0)               /* object = .got.plt[1] */
250         sll     a1, t8, 4               /* PLT entry index to .rel.plt offset */
251 #else
252         lw      a0, 4(a0)               /* object = .got.plt[1] */
253         sll     a1, t8, 3               /* PLT entry index to .rel.plt offset */
254 #endif
255
256         PTR_LA  t9, _C_LABEL(_rtld_bind)
257         jalr    t9
258         nop
259
260         move    sp, s0
261         REG_L   ra, XCALLFRAME_RA(sp)
262         .cfi_restore ra
263         REG_L   s0, XCALLFRAME_S0(sp)
264         .cfi_restore s0
265         REG_L   a0, XCALLFRAME_A0(sp)
266         .cfi_restore a0
267         REG_L   a1, XCALLFRAME_A1(sp)
268         .cfi_restore a1
269         REG_L   a2, XCALLFRAME_A2(sp)
270         .cfi_restore a2
271         REG_L   a3, XCALLFRAME_A3(sp)
272         .cfi_restore a3
273 #if defined(__mips_n32) || defined(__mips_n64)
274         REG_L   a4, XCALLFRAME_A4(sp)
275         .cfi_restore a4
276         REG_L   a5, XCALLFRAME_A5(sp)
277         .cfi_restore a5
278         REG_L   a6, XCALLFRAME_A6(sp)
279         .cfi_restore a6
280         REG_L   a7, XCALLFRAME_A7(sp)
281         .cfi_restore a7
282 #endif
283         RESTORE_GP64
284         PTR_ADDU sp, XCALLFRAME_SIZ
285         move    t9, v0
286         jr      t9
287         nop
288         .cfi_endproc
289 END(_rtld_pltbind_start)