1/* $OpenBSD: ldasm.S,v 1.21 2014/07/14 03:54:51 deraadt Exp $ */ 2 3/* 4 * Copyright (c) 1999 Dale Rahn 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 16 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 19 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * 27 */ 28 29#define AUX_entry 9 30 31#include <machine/asm.h> 32#include <sys/syscall.h> 33 34ENTRY(_dl_start) 35 mr 19, 1 36 stwu 1, (-16 -((AUX_entry+3)*4))(1) # Some space. 37 38 mflr 27 /* save off old link register */ 39 stw 27, 4(19) /* save in normal location */ 40 41 # squirrel away the arguments for main 42 mr 20, 3 #argc 43 mr 21, 4 #argv 44 mr 22, 5 #envp 45 mr 23, 6 # ??? 46 47 bl 1f 48 # this instruction never gets executed but can be used 49 # to find the virtual address where the page is loaded. 50 bl _GLOBAL_OFFSET_TABLE_@local-4 51 bl _DYNAMIC@local 521: 53 mflr 5 # this stores where we are (+4) 54 lwz 18, 0(5) # load the instruction at offset_sym 55 # it contains an offset to the location 56 # of the GOT. 57 58 rlwinm 18,18,0,8,30 # mask off the offset portion of the instr. 59 60 /* 61 * these adds effectively calculate the value the 62 * bl _GLOBAL_OFFSET_TABLE_@local-4 63 * operation that would be below would calculate. 64 */ 65 add 28, 18, 5 66 mr 6, 5 # save offset for later use 67 68 /* mprotect GOT-4 for correct execution of blrl instruction */ 69 li 0, SYS_mprotect 70 mr 3, 28 71 li 4, 4 72 li 5, 7 /* (PROT_READ|PROT_WRITE|PROT_EXEC) */ 73 sc 74 75 mr 5, 6 76 77 li 0, 0 78 dcbf 5, 18 79 sync 80 isync 81 icbi 5, 18 # make certain that the got table addr is 82 # not in the icache 83 sync 84 isync 85 86 /* This calculates the address of _DYNAMIC the same way 87 * that the GLOBAL_OFFSET_TABLE was calculated. 88 */ 89 lwz 18, 4(5) 90 rlwinm 18,18,0,8,30 # mask off the offset portion of the instr. 91 add 8, 18, 5 # address of _DYNAMIC (arg6 for _dl_boot) 92 addi 18, 8, 4 # correction. 93 lwz 4, 4(28) # load address of _DYNAMIC according to got. 94 sub 4, 18, 4 # determine load offset 95 96 mr 17, 4 # save for _dl_boot 97 98 99 subi 3, 21, 4 # Get stack pointer (arg0 for _dl_boot). 100 addi 4, 1, 8 # dl_data 101 mr 5, 18 # dynamicp 102 103 bl _dl_boot_bind@local 104 105 mr 3, 21 # argv 106 mr 4, 22 # envp 107 mr 5, 17 # loff 108 addi 6, 1, 8 # dl_data 109 110 bl _dl_boot@local 111 112 mtctr 3 # put return value into ctr to execute 113 114 # get back the squirreled away the arguments for main 115 mr 3, 20 116 mr 4, 21 117 mr 5, 22 118 mr 6, 23 119 120 bl _GLOBAL_OFFSET_TABLE_@local-4 121 mflr 31 122 lwz 7, _dl_dtors@got(31) 123 124 mtlr 27 125 lwz 1, 0(1) # Restore stack pointer. 126 bctr # Go execute the 'real' program. 127 128ENTRY(_dl_bind_start) 129 stwu 1,-64(1) 130 131 stw 0,8(1) # save r0 - cerror ;-) 132 mflr 0 133 stw 0,68(1) # save lr 134 135 stw 3,12(1) # save r3-r10, C calling convention 136 stw 4,20(1) # r13 - r31 are preserved by called code 137 stw 5,24(1) 138 stw 6,28(1) 139 stw 7,32(1) 140 stw 8,36(1) 141 stw 9,40(1) 142 stw 10,44(1) 143 144 mr 3,12 # obj 145 mr 4,11 # reloff 146 bl _dl_bind@plt # _rtld_bind(obj, reloff) 147 mtctr 3 148 149 lwz 3,12(1) 150 lwz 4,20(1) 151 lwz 5,24(1) 152 lwz 6,28(1) 153 lwz 7,32(1) 154 lwz 8,36(1) 155 lwz 9,40(1) 156 lwz 10,44(1) 157 158 lwz 0,68(1) # restore lr 159 mtlr 0 160 lwz 0,8(1) 161 162 addi 1,1,64 163 bctr 164 165#define DL_SYSCALL(n) DL_SYSCALL2(n,n) 166#define DL_SYSCALL_NOERR(n) DL_SYSCALL2_NOERR(n,n) 167#define DL_SYSCALL2(n,c) \ 168ENTRY(_dl_##n) \ 169 li 0, SYS_##c; \ 170 sc; \ 171 cmpwi 0, 0; \ 172 beqlr+; \ 173 b _dl_cerror 174#define DL_SYSCALL2_NOERR(n,c) \ 175ENTRY(_dl_##n) \ 176 li 0, SYS_##c; \ 177 sc; \ 178 blr 179 180_dl_cerror: 181 neg 3, 3 182 blr 183 184ENTRY(_dl_sigprocmask) 185 /* _dl_sigprocmask does not support NULL as the new mask */ 186#if 0 187 cmpwi 4, 0 188 bne+ 1f 189 li 3, 1 /* SIG_BLOCK */ 190 b 2f 1911: 192#endif 193 lwz 4, 0(4) 1942: 195 li 0, SYS_sigprocmask 196 sc 197 cmpwi 0, 0 198 bne- _dl_cerror 199 cmpwi 5, 0 200 beq- 1f 201 stw 3, 0(5) 2021: 203 li 3, 0 204 blr 205 206DL_SYSCALL(close) 207DL_SYSCALL_NOERR(exit) 208DL_SYSCALL(fstat) 209DL_SYSCALL2(getcwd,__getcwd) 210DL_SYSCALL(getdents) 211DL_SYSCALL(getentropy) 212DL_SYSCALL(sendsyslog) 213DL_SYSCALL(gettimeofday) 214DL_SYSCALL_NOERR(issetugid) 215DL_SYSCALL(lstat) 216DL_SYSCALL(mmap) 217DL_SYSCALL(mprotect) 218DL_SYSCALL(munmap) 219DL_SYSCALL(open) 220DL_SYSCALL(read) 221DL_SYSCALL(readlink) 222DL_SYSCALL2(_syscall,__syscall) 223DL_SYSCALL2(sysctl,__sysctl) 224DL_SYSCALL(utrace) 225DL_SYSCALL(write) 226