1 /* $NetBSD: rtld_start.S,v 1.10 2009/12/14 00:41:19 matt Exp $ */
4 * Copyright 1997 Michael L. Hitch <mhitch@montana.edu>
5 * Portions copyright 2002 Charles M. Hannum <root@ihack.net>
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
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.
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.
33 #include <machine/asm.h>
35 #if defined(__clang__) || (defined(__GNUC__) && __GNUC__ > 4)
36 .cfi_sections .debug_frame
39 .globl _C_LABEL(_rtld_relocate_nonplt_self)
40 .globl _C_LABEL(_rtld)
42 #define PTR_SIZE (1<<PTR_SCALESHIFT)
46 * a1 rtld cleanup (filled in by dynamic loader)
47 * a2 rtld object (filled in by dynamic loader)
50 NESTED(rtld_start, 4*PTR_SIZE, ra)
51 .mask 0x10090000,-PTR_SIZE
54 PTR_SUBU sp, 4*PTR_SIZE /* adjust stack pointer */
55 SETUP_GP64(s4, rtld_start)
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 */
64 PTR_LA t0, _C_LABEL(_rtld_relocate_nonplt_self)
65 1: PTR_SUBU a1, ra, a1 /* relocbase */
68 jalr t9 /* _rtld_relocate_nonplt_self(dynp, relocabase) */
69 PTR_ADDU a0, a1, a0 /* &_DYNAMIC */
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) */
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 */
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 */
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)
107 * Trampoline for "old" PLT stubs which use .got entries.
109 .globl _rtld_bind_start
110 .ent _rtld_bind_start
112 .frame sp, XCALLFRAME_SIZ, $15
113 .cfi_startproc simple
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 */
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
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
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
159 lw a0, 4(a0) /* object = pltgot[1] & 0x7fffffff */
160 and a0, a0, 0x7fffffff
162 move a1, t8 /* symbol index */
164 PTR_LA t9, _C_LABEL(_mips_rtld_bind)
169 REG_L ra, XCALLFRAME_RA(sp)
171 REG_L s0, XCALLFRAME_S0(sp)
173 REG_L a0, XCALLFRAME_A0(sp)
175 REG_L a1, XCALLFRAME_A1(sp)
177 REG_L a2, XCALLFRAME_A2(sp)
179 REG_L a3, XCALLFRAME_A3(sp)
181 #if defined(__mips_n32) || defined(__mips_n64)
182 REG_L a4, XCALLFRAME_A4(sp)
184 REG_L a5, XCALLFRAME_A5(sp)
186 REG_L a6, XCALLFRAME_A6(sp)
188 REG_L a7, XCALLFRAME_A7(sp)
192 PTR_ADDU sp, XCALLFRAME_SIZ
197 END(_rtld_bind_start)
201 * Trampoline for PLT stubs using .pltrel entries and .got.plt.
203 .globl _rtld_pltbind_start
204 .ent _rtld_pltbind_start
206 .frame sp, XCALLFRAME_SIZ, $15
207 .cfi_startproc simple
209 .cfi_register ra, $15
210 #if defined(__mips_o32)
211 move v1, gp /* save pointer to .got.plt */
213 move v1, t2 /* save pointer to .got.plt */
215 #if defined(__mips_o32) || defined(__mips_o64)
216 PTR_ADDU t9, 8 /* modify T9 to point at .cpload */
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
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
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 */
252 lw a0, 4(a0) /* object = .got.plt[1] */
253 sll a1, t8, 3 /* PLT entry index to .rel.plt offset */
256 PTR_LA t9, _C_LABEL(_rtld_bind)
261 REG_L ra, XCALLFRAME_RA(sp)
263 REG_L s0, XCALLFRAME_S0(sp)
265 REG_L a0, XCALLFRAME_A0(sp)
267 REG_L a1, XCALLFRAME_A1(sp)
269 REG_L a2, XCALLFRAME_A2(sp)
271 REG_L a3, XCALLFRAME_A3(sp)
273 #if defined(__mips_n32) || defined(__mips_n64)
274 REG_L a4, XCALLFRAME_A4(sp)
276 REG_L a5, XCALLFRAME_A5(sp)
278 REG_L a6, XCALLFRAME_A6(sp)
280 REG_L a7, XCALLFRAME_A7(sp)
284 PTR_ADDU sp, XCALLFRAME_SIZ
289 END(_rtld_pltbind_start)