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