1/* $NetBSD: reloc_ia64.S,v 1.1.1.1 2014/04/01 16:16:08 jakllsch Exp $ */ 2 3/* reloc_ia64.S - position independent IA-64 ELF shared object relocator 4 Copyright (C) 1999 Hewlett-Packard Co. 5 Contributed by David Mosberger <davidm@hpl.hp.com>. 6 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 13 * Redistributions of source code must retain the above copyright 14 notice, this list of conditions and the following disclaimer. 15 * Redistributions in binary form must reproduce the above 16 copyright notice, this list of conditions and the following 17 disclaimer in the documentation and/or other materials 18 provided with the distribution. 19 * Neither the name of Hewlett-Packard Co. nor the names of its 20 contributors may be used to endorse or promote products derived 21 from this software without specific prior written permission. 22 23 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 24 CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 25 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 26 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 27 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 28 BE LIABLE FOR ANYDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 29 OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 30 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 31 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 32 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 33 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 34 THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 SUCH DAMAGE. 36*/ 37 38/* 39 * This is written in assembly because the entire code needs to be position 40 * independent. Note that the compiler does not generate code that's position 41 * independent by itself because it relies on the global offset table being 42 * relocated. 43 */ 44 .text 45 .psr abi64 46 .psr lsb 47 .lsb 48 49/* 50 * This constant determines how many R_IA64_FPTR64LSB relocations we 51 * can deal with. If you get EFI_BUFFER_TOO_SMALL errors, you may 52 * need to increase this number. 53 */ 54#define MAX_FUNCTION_DESCRIPTORS 750 55 56#define ST_VALUE_OFF 8 /* offset of st_value in elf sym */ 57 58#define EFI_SUCCESS 0 59#define EFI_LOAD_ERROR 1 60#define EFI_BUFFER_TOO_SMALL 5 61 62#define DT_NULL 0 /* Marks end of dynamic section */ 63#define DT_RELA 7 /* Address of Rela relocs */ 64#define DT_RELASZ 8 /* Total size of Rela relocs */ 65#define DT_RELAENT 9 /* Size of one Rela reloc */ 66#define DT_SYMTAB 6 /* Address of symbol table */ 67#define DT_SYMENT 11 /* Size of one symbol table entry */ 68 69#define R_IA64_NONE 0 70#define R_IA64_REL64MSB 0x6e 71#define R_IA64_REL64LSB 0x6f 72#define R_IA64_DIR64MSB 0x26 73#define R_IA64_DIR64LSB 0x27 74#define R_IA64_FPTR64MSB 0x46 75#define R_IA64_FPTR64LSB 0x47 76 77#define ldbase in0 /* load address (address of .text) */ 78#define dyn in1 /* address of _DYNAMIC */ 79 80#define d_tag r16 81#define d_val r17 82#define rela r18 83#define relasz r19 84#define relaent r20 85#define addr r21 86#define r_info r22 87#define r_offset r23 88#define r_addend r24 89#define r_type r25 90#define r_sym r25 /* alias of r_type ! */ 91#define fptr r26 92#define fptr_limit r27 93#define symtab f8 94#define syment f9 95#define ftmp f10 96 97#define target r16 98#define val r17 99 100#define NLOC 0 101 102#define Pnull p6 103#define Prela p7 104#define Prelasz p8 105#define Prelaent p9 106#define Psymtab p10 107#define Psyment p11 108 109#define Pnone p6 110#define Prel p7 111#define Pfptr p8 112 113#define Pmore p6 114 115#define Poom p6 /* out-of-memory */ 116 117 .global _relocate 118 .proc _relocate 119_relocate: 120 alloc r2=ar.pfs,2,0,0,0 121 movl fptr = @gprel(fptr_mem_base) 122 ;; 123 add fptr = fptr, gp 124 movl fptr_limit = @gprel(fptr_mem_limit) 125 ;; 126 add fptr_limit = fptr_limit, gp 127 128search_dynamic: 129 ld8 d_tag = [dyn],8 130 ;; 131 ld8 d_val = [dyn],8 132 cmp.eq Pnull,p0 = DT_NULL,d_tag 133(Pnull) br.cond.sptk.few apply_relocs 134 cmp.eq Prela,p0 = DT_RELA,d_tag 135 cmp.eq Prelasz,p0 = DT_RELASZ,d_tag 136 cmp.eq Psymtab,p0 = DT_SYMTAB,d_tag 137 cmp.eq Psyment,p0 = DT_SYMENT,d_tag 138 cmp.eq Prelaent,p0 = DT_RELAENT,d_tag 139 ;; 140(Prela) add rela = d_val, ldbase 141(Prelasz) mov relasz = d_val 142(Prelaent) mov relaent = d_val 143(Psymtab) add val = d_val, ldbase 144 ;; 145(Psyment) setf.sig syment = d_val 146 ;; 147(Psymtab) setf.sig symtab = val 148 br.sptk.few search_dynamic 149 150apply_loop: 151 ld8 r_offset = [rela] 152 add addr = 8,rela 153 sub relasz = relasz,relaent 154 ;; 155 156 ld8 r_info = [addr],8 157 ;; 158 ld8 r_addend = [addr] 159 add target = ldbase, r_offset 160 161 add rela = rela,relaent 162 extr.u r_type = r_info, 0, 32 163 ;; 164 cmp.eq Pnone,p0 = R_IA64_NONE,r_type 165 cmp.eq Prel,p0 = R_IA64_REL64LSB,r_type 166 cmp.eq Pfptr,p0 = R_IA64_FPTR64LSB,r_type 167(Prel) br.cond.sptk.few apply_REL64 168 ;; 169 cmp.eq Prel,p0 = R_IA64_DIR64LSB,r_type // treat DIR64 just like REL64 170 171(Pnone) br.cond.sptk.few apply_relocs 172(Prel) br.cond.sptk.few apply_REL64 173(Pfptr) br.cond.sptk.few apply_FPTR64 174 175 mov r8 = EFI_LOAD_ERROR 176 br.ret.sptk.few rp 177 178apply_relocs: 179 cmp.ltu Pmore,p0=0,relasz 180(Pmore) br.cond.sptk.few apply_loop 181 182 mov r8 = EFI_SUCCESS 183 br.ret.sptk.few rp 184 185apply_REL64: 186 ld8 val = [target] 187 ;; 188 add val = val,ldbase 189 ;; 190 st8 [target] = val 191 br.cond.sptk.few apply_relocs 192 193 // FPTR relocs are a bit more interesting: we need to lookup 194 // the symbol's value in symtab, allocate 16 bytes of memory, 195 // store the value in [target] in the first and the gp in the 196 // second dword. 197apply_FPTR64: 198 st8 [target] = fptr 199 extr.u r_sym = r_info,32,32 200 add target = 8,fptr 201 ;; 202 203 setf.sig ftmp = r_sym 204 mov r8=EFI_BUFFER_TOO_SMALL 205 ;; 206 cmp.geu Poom,p0 = fptr,fptr_limit 207 208 xma.lu ftmp = ftmp,syment,symtab 209(Poom) br.ret.sptk.few rp 210 ;; 211 getf.sig addr = ftmp 212 st8 [target] = gp 213 ;; 214 add addr = ST_VALUE_OFF, addr 215 ;; 216 ld8 val = [addr] 217 ;; 218 add val = val,ldbase 219 ;; 220 st8 [fptr] = val,16 221 br.cond.sptk.few apply_relocs 222 223 .endp _relocate 224 225 .data 226 .align 16 227fptr_mem_base: 228 .space MAX_FUNCTION_DESCRIPTORS*16 229fptr_mem_limit: 230