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 bsr ra, _rtld_relocate_nonplt_self 53 LDGP(ra) 54 55 /* 56 * Allocate space on the stack for the cleanup and obj_main 57 * entries that _rtld() will provide for us. 58 */ 59 lda sp, -16(sp) 60 61 subq s2, s3, a1 /* relocbase */ 62 mov sp, a0 /* sp */ 63 CALL(_rtld) /* v0 = _rtld(sp, relocbase); */ 64 65 ldq a1, 0(sp) /* cleanup */ 66 ldq a2, 8(sp) /* obj_main */ 67 lda sp, 16(sp) /* pop stack */ 68 69 mov sp, a0 /* stack pointer */ 70 mov s0, a3 /* ps_strings */ 71 72 mov v0, pv /* set up PV for entry point */ 73 74 jsr ra, (v0), 0 /* (*_start)(sp, cleanup, obj, ps_strings); */ 75 ldgp gp, 0(ra) 76 77 CALL(exit) 78 halt 79END(_rtld_start) 80 81#define RTLD_BIND_START_PROLOGUE \ 82 /* at_reg already used by PLT code. */ \ 83 .set noat ; \ 84 \ 85 /* \ 86 * Allocate stack frame and preserve all registers that the \ 87 * caller would have normally saved themselves. \ 88 */ \ 89 lda sp, -168(sp) ; \ 90 stq ra, 0(sp) ; \ 91 stq v0, 8(sp) ; \ 92 stq t0, 16(sp) ; \ 93 stq t1, 24(sp) ; \ 94 stq t2, 32(sp) ; \ 95 stq t3, 40(sp) ; \ 96 stq t4, 48(sp) ; \ 97 stq t5, 56(sp) ; \ 98 stq t6, 64(sp) ; \ 99 stq t7, 72(sp) ; \ 100 stq a0, 80(sp) ; \ 101 stq a1, 88(sp) ; \ 102 stq a2, 96(sp) ; \ 103 stq a3, 104(sp) ; \ 104 stq a4, 112(sp) ; \ 105 stq a5, 120(sp) ; \ 106 stq t8, 128(sp) ; \ 107 stq t9, 136(sp) ; \ 108 stq t10, 144(sp) ; \ 109 stq t11, 152(sp) ; \ 110 stq gp, 160(sp) ; \ 111 \ 112 /* \ 113 * Load our global pointer. Note, can't use pv, since it is \ 114 * already used by the PLT code. \ 115 */ \ 116 br t0, 1f ; \ 1171: LDGP(t0) 118 119#define RTLD_BIND_START_EPILOGUE \ 120 /* Move the destination address into position. */ \ 121 mov v0, pv ; \ 122 \ 123 /* Restore program registers. */ \ 124 ldq ra, 0(sp) ; \ 125 ldq v0, 8(sp) ; \ 126 ldq t0, 16(sp) ; \ 127 ldq t1, 24(sp) ; \ 128 ldq t2, 32(sp) ; \ 129 ldq t3, 40(sp) ; \ 130 ldq t4, 48(sp) ; \ 131 ldq t5, 56(sp) ; \ 132 ldq t6, 64(sp) ; \ 133 ldq t7, 72(sp) ; \ 134 ldq a0, 80(sp) ; \ 135 ldq a1, 88(sp) ; \ 136 ldq a2, 96(sp) ; \ 137 ldq a3, 104(sp) ; \ 138 ldq a4, 112(sp) ; \ 139 ldq a5, 120(sp) ; \ 140 ldq t8, 128(sp) ; \ 141 ldq t9, 136(sp) ; \ 142 ldq t10, 144(sp) ; \ 143 ldq t11, 152(sp) ; \ 144 ldq gp, 160(sp) ; \ 145 /* XXX LDGP? */ \ 146 \ 147 /* \ 148 * We've patched the PLT; sync the I-stream. \ 149 */ \ 150 imb ; \ 151 \ 152 /* Pop the stack frame and turn control to the destination. */ \ 153 lda sp, 168(sp) ; \ 154 jmp zero, (pv) 155 156/* 157 * Lazy binding entry point, called via PLT. 158 */ 159NESTED_NOPROFILE(_rtld_bind_start, 0, 168, ra, 0, 0) 160 161 RTLD_BIND_START_PROLOGUE 162 163 /* Set up the arguments for _rtld_bind. */ 164 subq at_reg, pv, a1 /* calculate offset of reloc entry */ 165 ldq a0, 8(pv) /* object structure */ 166 subq a1, 20, a1 /* = (at - pv - 20) / 12 * 24 */ 167 addq a1, a1, a1 168 169 CALL(_rtld_bind) 170 171 RTLD_BIND_START_EPILOGUE 172 173END(_rtld_bind_start) 174 175/* 176 * Lazy binding entry point, called via PLT. This version is for the 177 * old PLT entry format. 178 */ 179NESTED_NOPROFILE(_rtld_bind_start_old, 0, 168, ra, 0, 0) 180 181 RTLD_BIND_START_PROLOGUE 182 183 /* Set up the arguments for _rtld_bind. */ 184 ldq a0, 8(pv) /* object structure */ 185 mov at_reg, a1 /* offset of reloc entry */ 186 187 CALL(_rtld_bind) 188 189 RTLD_BIND_START_EPILOGUE 190 191END(_rtld_bind_start_old) 192