1/* $FreeBSD$ */ 2/* From: NetBSD: rtld_start.S,v 1.1 1996/12/16 20:38:09 cgd Exp */ 3 4/* 5 * Copyright 1996 Matt Thomas <matt@3am-software.com> 6 * Copyright 2000 John D. Polstra 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. The name of the author may not be used to endorse or promote products 18 * derived from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32#include <machine/asm.h> 33#include <sys/syscall.h> 34 35ENTRY(_rtld_start, 0) 36 alloc r2=ar.pfs,3,0,3,0 37 ;; 381: mov r14=ip // calculate gp 39 addl r3=@gprel(1b),r0 40 ;; 41 sub gp=r14,r3 42 ;; 43 .section .sdata 442: data4 @ltv(1b) // unrelocated address of 1b 45 .align 8 46 .previous 47 add r15=@gprel(2b),gp 48 ;; 49 ld8 r15=[r15] 50 ;; 51 sub out0=r14,r15 // out0 is image base address 52 br.call.sptk.many rp=_rtld_reloc // fixup image 53 54 add sp=-16,sp // 16 bytes for us, 16 for _rtld 55 ;; 56 mov out0=in0 57 add out1=16,sp // address for exit proc 58 add out2=24,sp // address for obj_main 59 60 br.call.sptk.many rp=_rtld // r8=_rtld(sp, &exit_proc, &obj_main) 61 62 add r16=16,sp // address for exit proc 63 ;; 64 ld8 r15=[r16] // read exit proc 65 add sp=16,sp // readjust stack 66 mov b7=r8 // address of real _start 67 ;; 68 alloc r2=ar.pfs,0,0,3,0 // dump register frame 69 mov out2=r15 70 ;; 71 br.call.sptk.many rp=b7 // transfer to main program 72 br.call.sptk.many rp=exit // die 73END(_rtld_start) 74 75/* 76 * _rtld_bind_start: lookup a lazy binding and transfer to real target 77 * 78 * Arguments: 79 * r1 gp value for rtld 80 * r15 Index in plt 81 * r16 Obj_Entry of caller 82 * in0-in7 Arguments for target procedure 83 * rp Return address back to caller 84 */ 85ENTRY(_rtld_bind_start, 0) 86{ .mii 87 alloc loc0=ar.pfs,8,6,3,0 // space to save r8-r11 88 add r17=16-8*16,sp // leave 16 bytes for _rtld_bind 89 add r18=32-8*16,sp 90 ;; 91} { .mii 92 mov loc2=r8 // structure return address 93 add sp=-8*16,sp // space to save f8-f15 94 mov loc1=rp 95 ;; 96} { .mii 97 stf.spill [r17]=f8,32 // save float arguments 98 mov loc3=r9 // language specific 99 mov loc4=r10 // language specific 100} { .mii 101 stf.spill [r18]=f9,32 102 mov loc5=r11 // language specific 103 shl out1=r15,4 // 16 * index 104 ;; 105} { .mmi 106 stf.spill [r17]=f10,32 107 stf.spill [r18]=f11,32 108 mov out0=r16 // Obj_Entry for caller 109 ;; 110} { .mmi 111 stf.spill [r17]=f12,32 112 stf.spill [r18]=f13,32 113 shladd out1=r15,3,out1 // rela offset = 24 * index 114 ;; 115} { .mmb 116 stf.spill [r17]=f14,32 117 stf.spill [r18]=f15,32 118 br.call.sptk.many rp=_rtld_bind 119} { .mii 120 ld8 r14=[r8],8 // target address 121 add r17=16,sp 122 add r18=32,sp 123 ;; 124} { .mii 125 ld8 r1=[r8] // target gp 126 mov ar.pfs=loc0 // clean up 127 mov rp=loc1 128} { .mmi 129 ldf.fill f8=[r17],32 // restore float arguments 130 ldf.fill f9=[r18],32 131 mov r8=loc2 // restore structure pointer 132 ;; 133} { .mmi 134 ldf.fill f10=[r17],32 135 ldf.fill f11=[r18],32 136 mov r9=loc3 137 ;; 138} { .mmi 139 ldf.fill f12=[r17],32 140 ldf.fill f13=[r18],32 141 mov r10=loc4 142 ;; 143} { .mmi 144 ldf.fill f14=[r17],32 145 ldf.fill f15=[r18],32 146 mov r11=loc5 147 ;; 148} { .mii 149 nop.m 0 150 mov b7=r14 151 add sp=8*16,sp 152 ;; 153} { .mib 154 alloc r14=ar.pfs,0,0,8,0 // drop our register frame 155 nop.i 0 156 br.sptk.many b7 // jump to target 157} 158END(_rtld_bind_start) 159 160#define DT_NULL 0 /* Terminating entry. */ 161#define DT_RELA 7 /* Address of ElfNN_Rela relocations. */ 162#define DT_RELASZ 8 /* Total size of ElfNN_Rela relocations. */ 163#define DT_RELAENT 9 /* Size of each ElfNN_Rela relocation entry. */ 164 165#define R_IA_64_NONE 0 /* None */ 166#define R_IA_64_DIR64LSB 0x27 /* word64 LSB S + A */ 167#define R_IA_64_REL64LSB 0x6f /* word64 LSB BD + A */ 168 169/* 170 * _rtld_reloc: relocate the rtld image, apart from @fptrs. 171 * 172 * Assumes that rtld was linked at zero and that we only need to 173 * handle REL64LSB and DIR64LSB relocations. 174 * 175 * Arguments: 176 * r1 gp value for rtld 177 * in0 rtld base address 178 */ 179STATIC_ENTRY(_rtld_reloc, 1) 180 alloc loc0=ar.pfs,1,2,0,0 181 mov loc1=rp 182 ;; 183 movl r15=@gprel(_DYNAMIC) // find _DYNAMIC etc. 184 ;; 185 add r15=r15,gp // relocate _DYNAMIC etc. 186 ;; 1871: ld8 r16=[r15],8 // read r15->d_tag 188 ;; 189 ld8 r17=[r15],8 // and r15->d_val 190 ;; 191 cmp.eq p6,p0=DT_NULL,r16 // done? 192(p6) br.cond.dpnt.few 2f 193 ;; 194 cmp.eq p6,p0=DT_RELA,r16 195 ;; 196(p6) add r18=r17,in0 // found rela section 197 ;; 198 cmp.eq p6,p0=DT_RELASZ,r16 199 ;; 200(p6) mov r19=r17 // found rela size 201 ;; 202 cmp.eq p6,p0=DT_RELAENT,r16 203 ;; 204(p6) mov r22=r17 // found rela entry size 205 ;; 206 br.sptk.few 1b 207 2082: 209 ld8 r15=[r18],8 // read r_offset 210 ;; 211 ld8 r16=[r18],8 // read r_info 212 add r15=r15,in0 // relocate r_offset 213 ;; 214 ld8 r17=[r18],8 // read r_addend 215 sub r19=r19,r22 // update relasz 216 217 extr.u r23=r16,0,32 // ELF64_R_TYPE(r16) 218 ;; 219 cmp.eq p6,p0=R_IA_64_NONE,r23 220(p6) br.cond.dpnt.few 3f 221 ;; 222 cmp.eq p6,p0=R_IA_64_DIR64LSB,r23 223 ;; 224(p6) br.cond.dptk.few 4f 225 ;; 226 cmp.eq p6,p0=R_IA_64_REL64LSB,r23 227 ;; 228(p6) br.cond.dptk.few 4f 229 ;; 230 2313: cmp.ltu p6,p0=0,r19 // more? 232(p6) br.cond.dptk.few 2b // loop 233 234 mov r8=0 // success return value 235 ;; 236 br.cond.sptk.few 9f // done 237 2384: 239 ld8 r16=[r15] // read value 240 ;; 241 add r16=r16,in0 // relocate it 242 ;; 243 st8 [r15]=r16 // and store it back 244 br.cond.sptk.few 3b 245 2469: 247 mov ar.pfs=loc0 248 mov rp=loc1 249 ;; 250 br.ret.sptk.few rp 251 252END(_rtld_reloc) 253