1/* $OpenBSD: ldasm.S,v 1.27 2010/10/27 20:44:23 millert Exp $ */ 2/* $NetBSD: rtld_start.S,v 1.5 2001/08/14 22:17:48 eeh Exp $ */ 3 4/* 5 * Copyright (c) 2001 Jason L. Wright (jason@thought.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 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 21 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 25 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 26 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 * POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30/*- 31 * Copyright (c) 2000 Eduardo Horvath. 32 * Copyright (c) 1999 The NetBSD Foundation, Inc. 33 * All rights reserved. 34 * 35 * This code is derived from software contributed to The NetBSD Foundation 36 * by Christos Zoulas and Paul Kranenburg. 37 * 38 * Redistribution and use in source and binary forms, with or without 39 * modification, are permitted provided that the following conditions 40 * are met: 41 * 1. Redistributions of source code must retain the above copyright 42 * notice, this list of conditions and the following disclaimer. 43 * 2. Redistributions in binary form must reproduce the above copyright 44 * notice, this list of conditions and the following disclaimer in the 45 * documentation and/or other materials provided with the distribution. 46 * 3. All advertising materials mentioning features or use of this software 47 * must display the following acknowledgement: 48 * This product includes software developed by the NetBSD 49 * Foundation, Inc. and its contributors. 50 * 4. Neither the name of The NetBSD Foundation nor the names of its 51 * contributors may be used to endorse or promote products derived 52 * from this software without specific prior written permission. 53 * 54 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 55 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 56 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 57 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 58 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 59 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 60 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 61 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 62 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 63 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 64 * POSSIBILITY OF SUCH DAMAGE. 65 */ 66 67#include <sys/syscall.h> 68#include <machine/trap.h> 69#include <machine/asm.h> 70#define _LOCORE 71#include <machine/frame.h> 72 73/* 74 * ELF: 75 * On startup the stack should contain 16 extended word register save 76 * area, followed by the arg count, etc. 77 * 78 * _rtld() expects the stack pointer to point to two longwords for argument 79 * return followed by argc, etc. We need to create a pointer to 80 * &argc + 16 and pass that in. The return args will be in those 81 * locations. 82 * 83 * NB: We are violating the ELF spec by passing a pointer to the ps strings in 84 * %g1 instead of a termination routine. 85 */ 86 87/* Offset of ARGC from bottom of stack */ 88#define ARGC CC64FSZ 89/* XXX - DL_DATA_SIZE should be (9*8), but I can't think right now. */ 90#define DL_DATA_SIZE (16*8) 91 92 .section ".text" 93 .align 16 94 .register %g2,#scratch 95 96_ENTRY(_dl_start) 97 sub %g0, %g0, %fp ! clear frame 98 mov %g1, %l1 ! save ps_strings 99 sub %sp, 48 + DL_DATA_SIZE, %sp ! make room for dl_data 100 add %sp, BIAS + ARGC, %l3 101 102 add %l3, DL_DATA_SIZE, %o0 103 mov %o0, %l0 104 105 /* 106 * need to figure out where _DYNAMIC is located, newer binutils 107 * does not fill in GOT to read _DYNAMIC before relocation. 108 */ 109 call 0f 110 nop 111 call _DYNAMIC+8 ! not executed (no delay needed) 1120: ld [%o7+8], %o2 ! load stub call instruction 113 sll %o2, 2, %o2 ! extract PC offset 114 sra %o2, 0, %o2 ! sign-extend 115 116 add %o2, %o7, %o2 ! real &_DYNAMIC 117 118 call _dl_boot_bind ! _dl_boot_bind(sp,dl_data,dynamicp) 119 mov %l3, %o1 120 121 mov %l3, %o3 122 ldx [%l0], %l3 ! argc = *sp 123 sllx %l3, 3, %l3 ! argc *= sizeof(long) 124 addx %l0, 8, %o0 ! argv = [sp + argc] 125 addx %l0, 16, %o1 ! envp = sp + 16 + 126 addx %o1, %l3, %o1 ! + argc 127 128 addx %o3, (7*8), %l2 129 ldx [%l2], %o2 ! loff = dl_data[AUX_base]; 130 131 call _dl_boot ! _dl_boot(argv,envp,loff,dl_data) 132 nop 133 134 add %sp, 48 + DL_DATA_SIZE, %sp ! restore stack 135 mov %l1, %g1 ! restore ps_strings 136 137 jmp %o0 138 nop 139 140 /* 141 * We have two separate entry points to the runtime linker. 142 * I'm implementing this following the SPARC v9 ABI spec. 143 * 144 * _dl_bind_start_0(x, y) is called from .PLT0, and is used for 145 * PLT entries above 32768. 146 * 147 * _dl_bind_start_1(x, y) is called from .PLT1, and is used for 148 * PLT entries below 32768. 149 * 150 * The first two entries of PLT2 contain the xword object pointer. 151 * 152 * These routines are called with two longword arguments, 153 * x and y. To calculate the address of the entry, 154 * _dl_bind_start_1(x, y) does: 155 * 156 * n = x >> 15; 157 * 158 * and _dl_bind_start_0(x, y) does: 159 * 160 * i = x - y + 8 - 32768*32; 161 * n = 32768 + (i/5120)*160 + (i%5120)/24; 162 * 163 * Neither routine needs to issue a save since it's already been 164 * done in the PLT entry. 165 */ 166 167 /* NOTE: _dl_bind_start_0 is untested. Hence the debug stuff */ 168 169_ENTRY(_dl_bind_start_0) # (x, y) 170 sethi %hi(32768*32-8), %l1 171 sub %o0, %o1, %l0 /* x - y */ 172 or %l1, %lo(32768*32-8), %l1 173 sub %l0, %l1, %l0 /* x - y + 8 - 32768*32 */ 174 175 sethi %hi(5120), %l1 176 sdivx %l0, %l1, %l1 /* Calculate i/5120 */ 177 ldx [%o1 + (10*4)], %o0 /* Load object pointer from PLT2 */ 178 sllx %l1, 2, %l2 179 add %l1, %l2, %l2 180 sllx %l2, 10, %l2 181 sub %l0, %l2, %l2 /* And i%5120 */ 182 183 /* Let the division churn for a bit. */ 184 sdivx %l2, 24, %l4 /* (i%5120)/24 */ 185 186 /* 160 is (32 * 5) or (32 * (4 + 1)) */ 187 sllx %l1, 2, %l3 /* 4 * (i/5120) */ 188 add %l1, %l3, %l3 /* 5 * (i/5120) */ 189 sllx %l3, 5, %l3 /* 32 * 5 * (i/5120) */ 190 191 sethi %hi(32768), %l6 192 add %l3, %l4, %l5 /* %l5 = (i/5120)*160 + (i%5120)/24; */ 193 add %l5, %l6, %l5 194 195 call _dl_bind /* Call _dl_bind(obj, offset) */ 196 mov %l5, %o1 197 198 jmp %o0 /* return value == function address */ 199 restore /* Dump our stack frame */ 200 201_ENTRY(_dl_bind_start_1) # (x, y) 202 srax %o0, 15, %o2 /* %o0 is the index to our PLT slot */ 203 204 ldx [%o1 + 8], %o0 /* The object pointer is at [%o1 + 8] */ 205 206 call _dl_bind /* Call _dl_bind(obj, offset) */ 207 mov %o2, %o1 208 209 jmp %o0 /* return value == function address */ 210 restore /* Dump our stack frame */ 211 212_ENTRY(_dl_close) 213 mov SYS_close | SYSCALL_G2RFLAG, %g1 ! call sys_close 214 add %o7, 8, %g2 ! just return on success 215 t ST_SYSCALL ! off to wonderland 216 retl 217 sub %g0, %o0, %o0 ! error: result = -errno 218 219_ENTRY(_dl_exit) 220 mov SYS_exit | SYSCALL_G2RFLAG, %g1 ! call sys_exit 221 add %o7, 8, %g2 ! just return on success 222 t ST_SYSCALL ! off to wonderland 223 retl 224 sub %g0, %o0, %o0 ! error: result = -errno 225 226_ENTRY(_dl_issetugid) 227 mov SYS_issetugid | SYSCALL_G2RFLAG, %g1 ! call sys_issetugid 228 add %o7, 8, %g2 ! just return on success 229 t ST_SYSCALL ! off to wonderland 230 retl 231 sub %g0, %o0, %o0 ! error: result = -errno 232 233_ENTRY(_dl__syscall) 234 mov SYS___syscall | SYSCALL_G2RFLAG, %g1 ! call sys___syscall 235 add %o7, 8, %g2 ! just return on success 236 t ST_SYSCALL ! off to wonderland 237 retl 238 sub %g0, %o0, %o0 ! error: result = -errno 239 240_ENTRY(_dl_munmap) 241 mov SYS_munmap | SYSCALL_G2RFLAG, %g1 ! calling sys_munmap 242 add %o7, 8, %g2 ! just return on success 243 t ST_SYSCALL ! off to wonderland 244 retl 245 sub %g0, %o0, %o0 ! error: result = -errno 246 247_ENTRY(_dl_mprotect) 248 mov SYS_mprotect | SYSCALL_G2RFLAG, %g1 ! calling sys_mprotect 249 add %o7, 8, %g2 ! just return on success 250 t ST_SYSCALL ! off to wonderland 251 retl 252 sub %g0, %o0, %o0 ! error: result = -errno 253 254_ENTRY(_dl_open) 255 mov SYS_open | SYSCALL_G2RFLAG, %g1 ! calling sys_open 256 add %o7, 8, %g2 ! just return on success 257 t ST_SYSCALL ! off to wonderland 258 retl 259 sub %g0, %o0, %o0 ! error: result = -errno 260 261_ENTRY(_dl_read) 262 mov SYS_read | SYSCALL_G2RFLAG, %g1 ! calling sys_read 263 add %o7, 8, %g2 ! just return on success 264 t ST_SYSCALL ! off to wonderland 265 retl 266 sub %g0, %o0, %o0 ! error: result = -errno 267 268_ENTRY(_dl_write) 269 mov SYS_write | SYSCALL_G2RFLAG, %g1 ! calling sys_write 270 add %o7, 8, %g2 ! just return on success 271 t ST_SYSCALL ! off to wonderland 272 retl 273 sub %g0, %o0, %o0 ! error: result = -errno 274 275_ENTRY(_dl_stat) 276 mov SYS_stat | SYSCALL_G2RFLAG, %g1 ! call sys_stat 277 add %o7, 8, %g2 ! just return on success 278 t ST_SYSCALL ! off to wonderland 279 retl 280 sub %g0, %o0, %o0 ! error: result = -errno 281 282_ENTRY(_dl_fstat) 283 mov SYS_fstat | SYSCALL_G2RFLAG, %g1 ! call sys_fstat 284 add %o7, 8, %g2 ! just return on success 285 t ST_SYSCALL ! off to wonderland 286 retl 287 sub %g0, %o0, %o0 ! error: result = -errno 288 289_ENTRY(_dl_fcntl) 290 mov SYS_fcntl | SYSCALL_G2RFLAG, %g1 ! call sys_fcntl 291 add %o7, 8, %g2 ! just return on success 292 t ST_SYSCALL ! off to wonderland 293 retl 294 sub %g0, %o0, %o0 ! error: result = -errno 295 296_ENTRY(_dl_getdirentries) 297 mov SYS_getdirentries | SYSCALL_G2RFLAG, %g1 ! call sys_getdirentries 298 add %o7, 8, %g2 ! just return on success 299 t ST_SYSCALL ! off to wonderland 300 retl 301 sub %g0, %o0, %o0 ! error: result = -errno 302 303 /* _dl_sigprocmask does not support NULL new mask */ 304_ENTRY(_dl_sigprocmask) 305 ld [%o1], %o1 ! indirect for new mask 306 mov SYS_sigprocmask, %g1 ! call sys_sigprocmask 307 t ST_SYSCALL ! off to wonderland 308 ! what about errors? 309 cmp %o2, 0 310 bne,a 1f ! if oset != NULL 311 st %o0, [%o2] ! *oset = oldmask 3121: 313 retl 314 clr %o0 315 316_ENTRY(_dl_sysctl) 317 mov SYS___sysctl | SYSCALL_G2RFLAG, %g1 ! call sys___sysctl 318 add %o7, 8, %g2 ! just return on success 319 t ST_SYSCALL ! off to wonderland 320 retl 321 sub %g0, %o0, %o0 ! error: result = -errno 322 323_ENTRY(_dl_gettimeofday) 324 mov SYS_gettimeofday | SYSCALL_G2RFLAG, %g1 ! calling sys_gettimeofday 325 add %o7, 8, %g2 ! just return on success 326 t ST_SYSCALL ! off to wonderland 327 retl 328 sub %g0, %o0, %o0 ! error: result = -errno 329 330