1/* $NetBSD: rtld_start.S,v 1.15 2002/10/05 11:59:05 mycroft Exp $ */ 2 3/* 4 * Copyright 1996 Matt Thomas <matt@3am-software.com> 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 31#include <machine/asm.h> 32 33/* 34 * Note: we can call ourselves LEAF even though we use callee-saved 35 * registers because we're the root of the call graph. 36 */ 37LEAF_NOPROFILE(_rtld_start, 0) 38 .set noreorder 39 br pv, 1f 401: LDGP(pv) 41 42 /* 43 * Relocate ourself. 44 */ 45 br s2, 2f /* get our PC */ 462: ldiq s3, 2b /* get where the linker thought we were */ 47 48 subq s2, s3, a1 /* relocbase */ 49 lda t5, _DYNAMIC 50 addq a1, t5, a0 /* &_DYNAMIC */ 51 52 /* Squirrel away ps_strings. */ 53 mov a3, s0 54 55 bsr ra, _rtld_relocate_nonplt_self 56 LDGP(ra) 57 58 /* 59 * Allocate space on the stack for the cleanup and obj_main 60 * entries that _rtld() will provide for us. 61 */ 62 lda sp, -16(sp) 63 64 subq s2, s3, a1 /* relocbase */ 65 mov sp, a0 /* sp */ 66 CALL(_rtld) /* v0 = _rtld(sp, relocbase); */ 67 68 ldq a1, 0(sp) /* cleanup */ 69 ldq a2, 8(sp) /* obj_main */ 70 lda sp, 16(sp) /* pop stack */ 71 72 mov sp, a0 /* stack pointer */ 73 mov s0, a3 /* ps_strings */ 74 75 mov v0, pv /* set up PV for entry point */ 76 77 jsr ra, (v0), 0 /* (*_start)(sp, cleanup, obj, ps_strings); */ 78 ldgp gp, 0(ra) 79 80 CALL(exit) 81 halt 82END(_rtld_start) 83 84#define RTLD_BIND_START_PROLOGUE \ 85 /* at_reg already used by PLT code. */ \ 86 .set noat ; \ 87 \ 88 /* \ 89 * Allocate stack frame and preserve all registers that the \ 90 * caller would have normally saved themselves. \ 91 */ \ 92 lda sp, -168(sp) ; \ 93 stq ra, 0(sp) ; \ 94 stq v0, 8(sp) ; \ 95 stq t0, 16(sp) ; \ 96 stq t1, 24(sp) ; \ 97 stq t2, 32(sp) ; \ 98 stq t3, 40(sp) ; \ 99 stq t4, 48(sp) ; \ 100 stq t5, 56(sp) ; \ 101 stq t6, 64(sp) ; \ 102 stq t7, 72(sp) ; \ 103 stq a0, 80(sp) ; \ 104 stq a1, 88(sp) ; \ 105 stq a2, 96(sp) ; \ 106 stq a3, 104(sp) ; \ 107 stq a4, 112(sp) ; \ 108 stq a5, 120(sp) ; \ 109 stq t8, 128(sp) ; \ 110 stq t9, 136(sp) ; \ 111 stq t10, 144(sp) ; \ 112 stq t11, 152(sp) ; \ 113 stq gp, 160(sp) ; \ 114 \ 115 /* \ 116 * Load our global pointer. Note, can't use pv, since it is \ 117 * already used by the PLT code. \ 118 */ \ 119 br t0, 1f ; \ 1201: LDGP(t0) 121 122#define RTLD_BIND_START_EPILOGUE \ 123 /* Move the destination address into position. */ \ 124 mov v0, pv ; \ 125 \ 126 /* Restore program registers. */ \ 127 ldq ra, 0(sp) ; \ 128 ldq v0, 8(sp) ; \ 129 ldq t0, 16(sp) ; \ 130 ldq t1, 24(sp) ; \ 131 ldq t2, 32(sp) ; \ 132 ldq t3, 40(sp) ; \ 133 ldq t4, 48(sp) ; \ 134 ldq t5, 56(sp) ; \ 135 ldq t6, 64(sp) ; \ 136 ldq t7, 72(sp) ; \ 137 ldq a0, 80(sp) ; \ 138 ldq a1, 88(sp) ; \ 139 ldq a2, 96(sp) ; \ 140 ldq a3, 104(sp) ; \ 141 ldq a4, 112(sp) ; \ 142 ldq a5, 120(sp) ; \ 143 ldq t8, 128(sp) ; \ 144 ldq t9, 136(sp) ; \ 145 ldq t10, 144(sp) ; \ 146 ldq t11, 152(sp) ; \ 147 ldq gp, 160(sp) ; \ 148 /* XXX LDGP? */ \ 149 \ 150 /* \ 151 * We've patched the PLT; sync the I-stream. \ 152 */ \ 153 imb ; \ 154 \ 155 /* Pop the stack frame and turn control to the destination. */ \ 156 lda sp, 168(sp) ; \ 157 jmp zero, (pv) 158 159/* 160 * Lazy binding entry point, called via PLT. 161 */ 162NESTED_NOPROFILE(_rtld_bind_start, 0, 168, ra, 0, 0) 163 164 RTLD_BIND_START_PROLOGUE 165 166 /* Set up the arguments for _rtld_bind. */ 167 subq at_reg, pv, a1 /* calculate offset of reloc entry */ 168 ldq a0, 8(pv) /* object structure */ 169 subq a1, 20, a1 /* = (at - pv - 20) / 12 * 24 */ 170 addq a1, a1, a1 171 172 CALL(_rtld_bind) 173 174 RTLD_BIND_START_EPILOGUE 175 176END(_rtld_bind_start) 177 178/* 179 * Lazy binding entry point, called via PLT. This version is for the 180 * old PLT entry format. 181 */ 182NESTED_NOPROFILE(_rtld_bind_start_old, 0, 168, ra, 0, 0) 183 184 RTLD_BIND_START_PROLOGUE 185 186 /* Set up the arguments for _rtld_bind. */ 187 ldq a0, 8(pv) /* object structure */ 188 mov at_reg, a1 /* offset of reloc entry */ 189 190 CALL(_rtld_bind) 191 192 RTLD_BIND_START_EPILOGUE 193 194END(_rtld_bind_start_old) 195