1/* $OpenBSD: ldasm.S,v 1.8 2013/12/25 13:06:02 miod Exp $ */ 2 3/* 4 * Copyright (c) 2013 Miodrag Vallat. 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18/* 19 * Copyright (c) 2006 Dale Rahn 20 * 21 * Redistribution and use in source and binary forms, with or without 22 * modification, are permitted provided that the following conditions 23 * are met: 24 * 1. Redistributions of source code must retain the above copyright 25 * notice, this list of conditions and the following disclaimer. 26 * 2. Redistributions in binary form must reproduce the above copyright 27 * notice, this list of conditions and the following disclaimer in the 28 * documentation and/or other materials provided with the distribution. 29 * 30 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 31 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 32 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 33 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 34 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 35 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 36 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 37 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 38 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 39 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 40 * SUCH DAMAGE. 41 * 42 */ 43 44#include <machine/asm.h> 45#include <sys/syscall.h> 46#include <SYS.h> 47 48/* 49 * ld.so entry point. 50 * On entry: r31 points to the kernel argument struct (argv, argv, environ). 51 * The environment pointers list is followed by an array of AuxInfo 52 * structs filled by the kernel. 53 */ 54#define DL_DATA_SIZE (4 * 16) /* 16 * sizeof(ELF_Addr) */ 55ENTRY(_dl_start) 56 /* 57 * Two nop because execution may skip up to two instructions. 58 * See setregs() in the kernel for details. 59 * 60 * Note that I have been hacking m88k for years and still fall 61 * into this trap, every time. -- miod 62 */ 63 or %r0, %r0, %r0 64 or %r0, %r0, %r0 65 66 /* 67 * Get some room for the contiguous AUX pointers array. 68 */ 69 or %r30, %r31, 0 70 subu %r31, %r31, DL_DATA_SIZE 71 72 /* 73 * Invoke _dl_boot_bind 74 */ 75 or %r2, %r30, 0 | kernel args 76 or %r3, %r31, 0 | array base 77#if 0 /* _dl_boot_bind() can compute this itself */ 78 bsr 1f | the following instruction is skipped 79 bcnd eq0, %r0, _DYNAMIC | but gives us the pc-relative offset 801: ld.hu %r5, %r1, 2 | fetch branch offset (low 16 bits) 81 lda %r4, %r1[%r5] | 82#endif 83 bsr _dl_boot_bind 84 85 ld %r2, %r30, 0 | argc 86 addu %r6, %r30, 4 + 4 87 lda %r3, %r6[%r2] | envp 88 ld %r4, %r31, 4 * 7 | ldoff 89 or %r5, %r31, 0 | array base 90 bsr.n _dl_boot 91 addu %r2, %r30, 4 | argv 92 93 addu %r31, %r31, DL_DATA_SIZE 94 bsr 1f | the following instruction is skipped 95 bcnd eq0, %r0, _dl_dtors | but gives us the pc-relative offset 961: ld.hu %r5, %r1, 2 | fetch branch offset (low 16 bits) 97 jmp.n %r2 98 lda %r5, %r1[%r5] | cleanup 99END(_dl_start) 100 101/* 102 * PLT resolver entry point. 103 * Invoked with the following stack frame: 104 * r31(0x00) zero 105 * r31(0x04) ELF object 106 * r31(0x08) saved r11 107 * r31(0x0c) saved r1 108 * All registers but r1 and r11 must be preserved. The resolver must return 109 * to the resolved address with r1 restored. 110 */ 111#define OBJECT_OFFSET (4 * 1) 112#define R11_OFFSET (4 * 2) 113#define R1_OFFSET (4 * 3) 114#define PLT_FRAME_SIZE (4 * 4) 115#define REG_SIZE (4 * 12) 116ENTRY(_dl_bind_start) 117 /* 118 * Preserve caller-saved registers. 119 */ 120 subu %r31, %r31, REG_SIZE 121 st.d %r2, %r31, 4 * 0 122 st.d %r4, %r31, 4 * 2 123 st.d %r6, %r31, 4 * 4 124 st.d %r8, %r31, 4 * 6 125 st %r10, %r31, 4 * 8 126 st.d %r12, %r31, 4 * 10 127 128 /* 129 * Invoke resolver entry point. 130 */ 131 ld %r2, %r31, REG_SIZE + OBJECT_OFFSET 132 bsr.n _dl_bind 133 ld %r3, %r31, REG_SIZE + R11_OFFSET | reloff 134 135 /* 136 * Preserve return address. 137 */ 138 or %r11, %r2, %r0 139 140 /* 141 * Restore caller-saved registers. 142 */ 143 ld.d %r12, %r31, 4 * 10 144 ld %r10, %r31, 4 * 8 145 ld.d %r8, %r31, 4 * 6 146 ld.d %r6, %r31, 4 * 4 147 ld.d %r4, %r31, 4 * 2 148 ld.d %r2, %r31, 4 * 0 149 ld %r1, %r31, REG_SIZE + R1_OFFSET 150 151 jmp.n %r11 152 addu %r31, %r31, REG_SIZE + PLT_FRAME_SIZE 153 154/* ld.so SYSCALLS */ 155 156#define DL_SYSCALL(n) DL_SYSCALL2(n,n) 157#define DL_SYSCALL2(n,c) \ 158 __ENTRY(_dl_,n); \ 159 __DO_SYSCALL(c); \ 160 br _dl_cerror 161 162#define DL_SYSCALL2_NOERR(n,c) \ 163 __ENTRY(_dl_,n); \ 164 __DO_SYSCALL(c) 165 166DL_SYSCALL(close) 167 jmp %r1 168 169ENTRY(_dl_exit) 170 __DO_SYSCALL(exit) 1711: br 1b 172 173DL_SYSCALL(issetugid) 174 jmp %r1 175 176DL_SYSCALL2(_syscall,__syscall) 177 jmp %r1 178 179DL_SYSCALL(munmap) 180 jmp %r1 181 182DL_SYSCALL(mprotect) 183 jmp %r1 184 185DL_SYSCALL(open) 186 jmp %r1 187 188DL_SYSCALL(read) 189 jmp %r1 190 191DL_SYSCALL(write) 192 jmp %r1 193 194DL_SYSCALL(fstat) 195 jmp %r1 196 197DL_SYSCALL(fcntl) 198 jmp %r1 199 200DL_SYSCALL(gettimeofday) 201 jmp %r1 202 203DL_SYSCALL(readlink) 204 jmp %r1 205 206DL_SYSCALL(lstat) 207 jmp %r1 208 209DL_SYSCALL(utrace) 210 jmp %r1 211 212DL_SYSCALL2(getcwd,__getcwd) 213 jmp %r1 214 215DL_SYSCALL2(sysctl,__sysctl) 216 jmp %r1 217 218DL_SYSCALL(getdents) 219 jmp %r1 220 221ENTRY(_dl_sigprocmask) 222 bcnd ne0, %r3, 1f 223 or %r2, %r0, 1 /* SIG_BLOCK */ 224 br 2f 2251: 226 ld %r3, %r3, 0 2272: 228 or %r13, %r0, SYS_sigprocmask 229 tb0 0, %r0, 450 230 br _dl_cerror 231 bcnd eq0, %r4, 3f 232 st %r2, %r4, 0 2333: 234 jmp.n %r1 235 or %r2, %r0, 0 236END(_dl_sigprocmask) 237 238_dl_cerror: 239 jmp.n %r1 240 subu %r2, %r0, 1 241 242ENTRY(_dl_cacheflush) 243 tb0 0, %r0, 451 244 br _dl_cerror | never hit 245 jmp %r1 246END(_dl_cacheflush) 247