1/* $NetBSD: rtld_start.S,v 1.8 2001/12/14 21:25:23 thorpej Exp $ */ 2 3/* 4 * Copyright 1996 Matt Thomas <matt@3am-software.com> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30#include <machine/asm.h> 31 32 .extern _GLOBAL_OFFSET_TABLE_ 33 .extern _GOT_END_ 34 35/* 36 * Note: we can call ourselves LEAF even though we use callee-saved 37 * registers because we're the root of the call graph. 38 */ 39LEAF_NOPROFILE(_rtld_start, 0) 40 .set noreorder 41 br pv, 1f 421: LDGP(pv) 43 44 /* XXX Partially relocate ourself. */ 45 46 /* Step 1 -- Figure out the displacement */ 47 48 br t2, 2f /* get our PC */ 492: ldiq t3, 2b /* get where the linker thought we were */ 50 subq t2, t3, t8 /* calculate the displacement */ 51 52 53 /* Step 2 -- Find bounds of global offset table */ 54 55 lda t5, _GLOBAL_OFFSET_TABLE_ 56 addq t8, t5, t9 /* add the displacement */ 57 lda t4, _GOT_END_ /* Get the address of the end of the GOT */ 58 addq t8, t4, t10 /* add the displacement */ 59 60 /* 61 * Step 3 -- Every entry in the global offset table needs to 62 * modified for the displacement before any code will work. 63 */ 64 653: ldq t1, 0(t9) /* load the value */ 66 addq t8, t1, t1 /* add the displacement */ 67 stq t1, 0(t9) /* save the new value */ 68 lda t9, 8(t9) /* point to next entry */ 69 cmpult t9, t10, t1 /* are we done? */ 70 bne t1, 3b /* no, do more */ 71 72 /* 73 * Ya! Things are far enough so we can do some dynamic linking! 74 */ 75 76 /* Squirrel away ps_strings. */ 77 mov a3, s0 78 79 /* 80 * Allocate space on the stack for the cleanup and obj_main 81 * entries that _rtld() will provide for us. 82 */ 83 lda sp, -16(sp) 84 85 mov sp, a0 /* v0 = _rtld(sp); */ 86 CALL(_rtld) 87 88 ldq a1, 0(sp) /* cleanup */ 89 ldq a2, 8(sp) /* obj_main */ 90 lda sp, 16(sp) /* pop stack */ 91 92 mov sp, a0 /* stack pointer */ 93 mov s0, a3 /* ps_strings */ 94 95 mov v0, pv /* set up PV for entry point */ 96 97 jsr ra, (v0), 0 /* (*_start)(sp, cleanup, obj, ps_strings); */ 98 ldgp gp, 0(ra) 99 100 CALL(exit) 101 halt 102END(_rtld_start) 103 104#define RTLD_BIND_START_PROLOGUE \ 105 /* at_reg already used by PLT code. */ \ 106 .set noat ; \ 107 \ 108 /* \ 109 * Allocate stack frame and preserve all registers that the \ 110 * caller would have normally saved themselves. \ 111 */ \ 112 lda sp, -168(sp) ; \ 113 stq ra, 0(sp) ; \ 114 stq v0, 8(sp) ; \ 115 stq t0, 16(sp) ; \ 116 stq t1, 24(sp) ; \ 117 stq t2, 32(sp) ; \ 118 stq t3, 40(sp) ; \ 119 stq t4, 48(sp) ; \ 120 stq t5, 56(sp) ; \ 121 stq t6, 64(sp) ; \ 122 stq t7, 72(sp) ; \ 123 stq a0, 80(sp) ; \ 124 stq a1, 88(sp) ; \ 125 stq a2, 96(sp) ; \ 126 stq a3, 104(sp) ; \ 127 stq a4, 112(sp) ; \ 128 stq a5, 120(sp) ; \ 129 stq t8, 128(sp) ; \ 130 stq t9, 136(sp) ; \ 131 stq t10, 144(sp) ; \ 132 stq t11, 152(sp) ; \ 133 stq gp, 160(sp) ; \ 134 \ 135 /* \ 136 * Load our global pointer. Note, can't use pv, since it is \ 137 * already used by the PLT code. \ 138 */ \ 139 br t0, 1f ; \ 1401: LDGP(t0) 141 142#define RTLD_BIND_START_EPILOGUE \ 143 /* Move the destination address into position. */ \ 144 mov v0, pv ; \ 145 \ 146 /* Restore program registers. */ \ 147 ldq ra, 0(sp) ; \ 148 ldq v0, 8(sp) ; \ 149 ldq t0, 16(sp) ; \ 150 ldq t1, 24(sp) ; \ 151 ldq t2, 32(sp) ; \ 152 ldq t3, 40(sp) ; \ 153 ldq t4, 48(sp) ; \ 154 ldq t5, 56(sp) ; \ 155 ldq t6, 64(sp) ; \ 156 ldq t7, 72(sp) ; \ 157 ldq a0, 80(sp) ; \ 158 ldq a1, 88(sp) ; \ 159 ldq a2, 96(sp) ; \ 160 ldq a3, 104(sp) ; \ 161 ldq a4, 112(sp) ; \ 162 ldq a5, 120(sp) ; \ 163 ldq t8, 128(sp) ; \ 164 ldq t9, 136(sp) ; \ 165 ldq t10, 144(sp) ; \ 166 ldq t11, 152(sp) ; \ 167 ldq gp, 160(sp) ; \ 168 /* XXX LDGP? */ \ 169 \ 170 /* \ 171 * We've patched the PLT; sync the I-stream. \ 172 */ \ 173 imb ; \ 174 \ 175 /* Pop the stack frame and turn control to the destination. */ \ 176 lda sp, 168(sp) ; \ 177 jmp zero, (pv) 178 179/* 180 * Lazy binding entry point, called via PLT. 181 */ 182NESTED_NOPROFILE(_rtld_bind_start, 0, 168, ra, 0, 0) 183 184 RTLD_BIND_START_PROLOGUE 185 186 /* Set up the arguments for _rtld_bind. */ 187 subq at_reg, pv, a1 /* calculate offset of reloc entry */ 188 ldq a0, 8(pv) /* object structure */ 189 subq a1, 20, a1 /* = (at - pv - 20) / 12 * 24 */ 190 addq a1, a1, a1 191 192 CALL(_rtld_bind) 193 194 RTLD_BIND_START_EPILOGUE 195 196END(_rtld_bind_start) 197 198/* 199 * Lazy binding entry point, called via PLT. This version is for the 200 * old PLT entry format. 201 */ 202NESTED_NOPROFILE(_rtld_bind_start_old, 0, 168, ra, 0, 0) 203 204 RTLD_BIND_START_PROLOGUE 205 206 /* Set up the arguments for _rtld_bind. */ 207 ldq a0, 8(pv) /* object structure */ 208 mov at_reg, a1 /* offset of reloc entry */ 209 210 CALL(_rtld_bind) 211 212 RTLD_BIND_START_EPILOGUE 213 214END(_rtld_bind_start_old) 215