1/* $NetBSD: rtld_start.S,v 1.3 2004/05/17 13:16:02 skrll Exp $ */ 2 3/*- 4 * Copyright (c) 2002 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Matt Fredette. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39#include <machine/asm.h> 40#define _LOCORE /* XXX fredette we MUST get rid of this */ 41#include <machine/frame.h> 42#undef _LOCORE 43 44 .import _GLOBAL_OFFSET_TABLE_ 45 46ENTRY($rtld_start,32) 47 48 /* Start stack calling convention. */ 49 copy %r3, %r1 50 copy %sp, %r3 51 stw,ma %r1, HPPA_FRAME_SIZE(%sp) 52 53 /* 54 * Save our single argument, the ps_strings pointer. 55 * We'll need this twice later: once to call _rtld, 56 * and again to transfer to the program's entry point. 57 */ 58 stw %arg0, HPPA_FRAME_ARG(0)(%r3) 59 60 /* 61 * We can't move to C until we relocate at least the 62 * Global Offset Table. Even finding the GOT is tricky 63 * without inadvertently causing the linker to make 64 * relocations for this part of the text segment. 65 */ 66 67 bl L$lpc1, %r19 68 depi 0, 31, 2, %r19 69L$lpc1: addil L'_DYNAMIC - ($PIC_pcrel$0 - 8), %r19 70 ldo R'_DYNAMIC - ($PIC_pcrel$0 - 12)(%r1),%arg0 71 72 /* 73 * Load the absolute address of the beginning of the 74 * GOT into %r19, the shared library linkage table 75 * register, leaving it ready-to-use by the dynamic 76 * linker C code. 77 */ 78 addil L'_GLOBAL_OFFSET_TABLE_ - ($PIC_pcrel$0 - 16), %r19 79 ldo R'_GLOBAL_OFFSET_TABLE_ - ($PIC_pcrel$0 - 20)(%r1),%r19 80 81 /* 82 * The linker sets the first entry in the GOT to the 83 * unrelocated address of _DYNAMIC. Subtract this 84 * from the absolute address of _DYNAMIC to get our 85 * relocbase. 86 */ 87 ldw 0(%r19), %arg1 88 sub %arg0, %arg1, %arg1 ; %arg1 = relocbase 89 bl _rtld_relocate_nonplt_self, %rp 90 copy %arg1, %r4 ; save for later 91 92 /* 93 * Recover the ps_strings pointer, and take out the 94 * ps_argvstr member. 95 */ 96 ldw HPPA_FRAME_ARG(0)(%r3), %arg0 ; ps_strings 97 ldw 0(%arg0), %arg0 ; ps_argvstr member first in struct 98 99 /* 100 * ps_argvstr - 4 would get us a pointer to argc, 101 * comparable to the initial stack pointer on 102 * architectures where the stack grows down. 103 * Subtracting an additional eight creates the 104 * storage for obj and cleanup that _rtld needs. 105 */ 106 ldo -12(%arg0), %arg0 107 stw %arg0, HPPA_FRAME_ARG(1)(%r3) 108 109 /* Call _rtld, copying relocbase into arg1. */ 110 bl _rtld, %rp 111 copy %r4, %arg1 ; %arg1 = relocbase 112 113 /* Prepare the arguments for the entry point. */ 114 ldw HPPA_FRAME_ARG(1)(%r3), %r1 115 ldw HPPA_FRAME_ARG(0)(%r3), %arg0 ; ps_strings 116 ldw 0(%r1), %arg1 ; cleanup 117 ldw 4(%r1), %arg2 ; obj 118 119 /* End stack calling convention. */ 120 ldo HPPA_FRAME_SIZE(%r3), %sp 121 ldw,mb -HPPA_FRAME_SIZE(%sp), %r3 122 123 /* Go for it. */ 124 bv %r0(%ret0) 125 copy %r0, %rp 126EXIT($rtld_start) 127 128/* 129 * This does our setup for an object's GOT. %arg0 is the 130 * Obj_Entry * for the object, and %arg1 is its GOT pointer. 131 */ 132LEAF_ENTRY(__rtld_setup_hppa_pltgot) 133 134 /* 135 * The second entry of the GOT is reserved for 136 * the dynamic linker. We put the Obj_Entry * 137 * for the object in there. 138 */ 139 stw %arg0, 4(%arg1) 140 141 /* 142 * Fill the fixup_func and fixup_ltp members of 143 * the PLT stub. This stub is inserted by the 144 * linker immediately before the GOT. We use 145 * this stub to enter our binder. 146 */ 147 148 bl L$lpc2, %arg0 149 depi 0, 31, 2, %arg0 150L$lpc2: addil L'_rtld_bind_start - ($PIC_pcrel$0 - 8), %arg0 151 ldo R'_rtld_bind_start - ($PIC_pcrel$0 - 12)(%r1),%arg0 152 153 stw %arg0, -8(%arg1) 154 bv %r0(%rp) 155 stw %r19, -4(%arg1) 156EXIT(__rtld_hppa_setup_pltgot) 157 158/* 159 * In order to support lazy binding, this implementation of 160 * _rtld_bind_start is very closely tied to the shared-library 161 * call stub and the PLT stub, both inserted by the linker. 162 */ 163ENTRY(_rtld_bind_start,32) 164 165 /* Start stack calling convention. */ 166 copy %r3, %r1 167 copy %sp, %r3 168 169 stw,ma %r1, HPPA_FRAME_SIZE(%sp) 170 171 /* 172 * We have to save all calling convention registers 173 * that are set by the caller, because we have to 174 * restore them before transferring to the bound 175 * function. Note that this includes %ret0 and %ret1, 176 * because they can have meaning on entry to a function. 177 */ 178 stw %rp, HPPA_FRAME_CRP(%r3) 179 stw %arg0, HPPA_FRAME_ARG(0)(%r3) 180 stw %arg1, HPPA_FRAME_ARG(1)(%r3) 181 stw %arg2, HPPA_FRAME_ARG(2)(%r3) 182 stw %arg3, HPPA_FRAME_ARG(3)(%r3) 183 /* 0(%r3) is filled with the saved %r3 above */ 184 stw %ret0, 4(%r3) 185 stw %ret1, 8(%r3) 186 187 /* 188 * The linker PLT stub loads %r20 with (GOT - 8) for 189 * the object that needs binding done. The second entry 190 * of the GOT is reserved for the dynamic linker's use, 191 * and we previously stashed the object's Obj_Entry * 192 * there. 193 */ 194 ldw 12(%r20), %arg0 195 196 /* 197 * The linker shared-library call stub loads %r19 from 198 * the shared linkage member of the PLT entry. We 199 * previously stashed the reloff of the relocation there. 200 */ 201 copy %r19, %arg1 202 203 /* 204 * The linker PLT stub loads %r21 with the fixup_ltp 205 * word in itself. We previously stashed our %r19 206 * value there. 207 */ 208 bl _rtld_bind, %rp 209 copy %r21, %r19 210 211 /* 212 * Our hppa version of _rtld_bind 213 * returns to us the address of the PLT entry that 214 * it fixed up. Load the function address and 215 * shared linkage for the newly bound function. 216 */ 217 ldw 0(%ret0), %r21 218 ldw 4(%ret0), %r19 219 220 /* Restore registers saved above. */ 221 ldw HPPA_FRAME_CRP(%r3), %rp 222 ldw HPPA_FRAME_ARG(0)(%r3), %arg0 223 ldw HPPA_FRAME_ARG(1)(%r3), %arg1 224 ldw HPPA_FRAME_ARG(2)(%r3), %arg2 225 ldw HPPA_FRAME_ARG(3)(%r3), %arg3 226 ldw 4(%r3), %ret0 227 ldw 8(%r3), %ret1 228 229 /* End stack calling convention. */ 230 ldo HPPA_FRAME_SIZE(%r3), %sp 231 ldw,mb -HPPA_FRAME_SIZE(%sp), %r3 232 233 /* Transfer to the function. */ 234 bv %r0(%r21) 235 nop 236EXIT(_rtld_bind_start) 237