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 */ 50NESTED(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) 651: 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 */ 89END(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 197END(_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 289END(_rtld_pltbind_start) 290