1530d68baSNigel Croxon/* reloc_ia64.S - position independent IA-64 ELF shared object relocator 2530d68baSNigel Croxon Copyright (C) 1999 Hewlett-Packard Co. 3530d68baSNigel Croxon Contributed by David Mosberger <davidm@hpl.hp.com>. 4530d68baSNigel Croxon 5530d68baSNigel Croxon All rights reserved. 6530d68baSNigel Croxon 7530d68baSNigel Croxon Redistribution and use in source and binary forms, with or without 8530d68baSNigel Croxon modification, are permitted provided that the following conditions 9530d68baSNigel Croxon are met: 10530d68baSNigel Croxon 11530d68baSNigel Croxon * Redistributions of source code must retain the above copyright 12530d68baSNigel Croxon notice, this list of conditions and the following disclaimer. 13530d68baSNigel Croxon * Redistributions in binary form must reproduce the above 14530d68baSNigel Croxon copyright notice, this list of conditions and the following 15530d68baSNigel Croxon disclaimer in the documentation and/or other materials 16530d68baSNigel Croxon provided with the distribution. 17530d68baSNigel Croxon * Neither the name of Hewlett-Packard Co. nor the names of its 18530d68baSNigel Croxon contributors may be used to endorse or promote products derived 19530d68baSNigel Croxon from this software without specific prior written permission. 20530d68baSNigel Croxon 21530d68baSNigel Croxon THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 22530d68baSNigel Croxon CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 23530d68baSNigel Croxon INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 24530d68baSNigel Croxon MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25530d68baSNigel Croxon DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 26530d68baSNigel Croxon BE LIABLE FOR ANYDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 27530d68baSNigel Croxon OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 28530d68baSNigel Croxon PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 29530d68baSNigel Croxon PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30530d68baSNigel Croxon THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 31530d68baSNigel Croxon TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 32530d68baSNigel Croxon THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33530d68baSNigel Croxon SUCH DAMAGE. 34530d68baSNigel Croxon*/ 35530d68baSNigel Croxon 36530d68baSNigel Croxon/* 37530d68baSNigel Croxon * This is written in assembly because the entire code needs to be position 38530d68baSNigel Croxon * independent. Note that the compiler does not generate code that's position 39530d68baSNigel Croxon * independent by itself because it relies on the global offset table being 40530d68baSNigel Croxon * relocated. 41530d68baSNigel Croxon */ 42530d68baSNigel Croxon .text 43530d68baSNigel Croxon .psr abi64 44530d68baSNigel Croxon .psr lsb 45530d68baSNigel Croxon .lsb 46530d68baSNigel Croxon 47530d68baSNigel Croxon/* 48530d68baSNigel Croxon * This constant determines how many R_IA64_FPTR64LSB relocations we 49530d68baSNigel Croxon * can deal with. If you get EFI_BUFFER_TOO_SMALL errors, you may 50530d68baSNigel Croxon * need to increase this number. 51530d68baSNigel Croxon */ 52530d68baSNigel Croxon#define MAX_FUNCTION_DESCRIPTORS 750 53530d68baSNigel Croxon 54530d68baSNigel Croxon#define ST_VALUE_OFF 8 /* offset of st_value in elf sym */ 55530d68baSNigel Croxon 56530d68baSNigel Croxon#define EFI_SUCCESS 0 57530d68baSNigel Croxon#define EFI_LOAD_ERROR 1 58530d68baSNigel Croxon#define EFI_BUFFER_TOO_SMALL 5 59530d68baSNigel Croxon 60530d68baSNigel Croxon#define DT_NULL 0 /* Marks end of dynamic section */ 61530d68baSNigel Croxon#define DT_RELA 7 /* Address of Rela relocs */ 62530d68baSNigel Croxon#define DT_RELASZ 8 /* Total size of Rela relocs */ 63530d68baSNigel Croxon#define DT_RELAENT 9 /* Size of one Rela reloc */ 64530d68baSNigel Croxon#define DT_SYMTAB 6 /* Address of symbol table */ 65530d68baSNigel Croxon#define DT_SYMENT 11 /* Size of one symbol table entry */ 66530d68baSNigel Croxon 67530d68baSNigel Croxon#define R_IA64_NONE 0 68530d68baSNigel Croxon#define R_IA64_REL64MSB 0x6e 69530d68baSNigel Croxon#define R_IA64_REL64LSB 0x6f 70530d68baSNigel Croxon#define R_IA64_DIR64MSB 0x26 71530d68baSNigel Croxon#define R_IA64_DIR64LSB 0x27 72530d68baSNigel Croxon#define R_IA64_FPTR64MSB 0x46 73530d68baSNigel Croxon#define R_IA64_FPTR64LSB 0x47 74530d68baSNigel Croxon 75530d68baSNigel Croxon#define ldbase in0 /* load address (address of .text) */ 76530d68baSNigel Croxon#define dyn in1 /* address of _DYNAMIC */ 77530d68baSNigel Croxon 78530d68baSNigel Croxon#define d_tag r16 79530d68baSNigel Croxon#define d_val r17 80530d68baSNigel Croxon#define rela r18 81530d68baSNigel Croxon#define relasz r19 82530d68baSNigel Croxon#define relaent r20 83530d68baSNigel Croxon#define addr r21 84530d68baSNigel Croxon#define r_info r22 85530d68baSNigel Croxon#define r_offset r23 86530d68baSNigel Croxon#define r_addend r24 87530d68baSNigel Croxon#define r_type r25 88530d68baSNigel Croxon#define r_sym r25 /* alias of r_type ! */ 89530d68baSNigel Croxon#define fptr r26 90530d68baSNigel Croxon#define fptr_limit r27 91530d68baSNigel Croxon#define symtab f8 92530d68baSNigel Croxon#define syment f9 93530d68baSNigel Croxon#define ftmp f10 94530d68baSNigel Croxon 95530d68baSNigel Croxon#define target r16 96530d68baSNigel Croxon#define val r17 97530d68baSNigel Croxon 98530d68baSNigel Croxon#define NLOC 0 99530d68baSNigel Croxon 100530d68baSNigel Croxon#define Pnull p6 101530d68baSNigel Croxon#define Prela p7 102530d68baSNigel Croxon#define Prelasz p8 103530d68baSNigel Croxon#define Prelaent p9 104530d68baSNigel Croxon#define Psymtab p10 105530d68baSNigel Croxon#define Psyment p11 106530d68baSNigel Croxon 107530d68baSNigel Croxon#define Pnone p6 108530d68baSNigel Croxon#define Prel p7 109530d68baSNigel Croxon#define Pfptr p8 110530d68baSNigel Croxon 111530d68baSNigel Croxon#define Pmore p6 112530d68baSNigel Croxon 113530d68baSNigel Croxon#define Poom p6 /* out-of-memory */ 114530d68baSNigel Croxon 115530d68baSNigel Croxon .global _relocate 116530d68baSNigel Croxon .proc _relocate 117530d68baSNigel Croxon_relocate: 118530d68baSNigel Croxon alloc r2=ar.pfs,2,0,0,0 119530d68baSNigel Croxon movl fptr = @gprel(fptr_mem_base) 120530d68baSNigel Croxon ;; 121530d68baSNigel Croxon add fptr = fptr, gp 122530d68baSNigel Croxon movl fptr_limit = @gprel(fptr_mem_limit) 123530d68baSNigel Croxon ;; 124530d68baSNigel Croxon add fptr_limit = fptr_limit, gp 125530d68baSNigel Croxon 126530d68baSNigel Croxonsearch_dynamic: 127530d68baSNigel Croxon ld8 d_tag = [dyn],8 128530d68baSNigel Croxon ;; 129530d68baSNigel Croxon ld8 d_val = [dyn],8 130530d68baSNigel Croxon cmp.eq Pnull,p0 = DT_NULL,d_tag 131530d68baSNigel Croxon(Pnull) br.cond.sptk.few apply_relocs 132530d68baSNigel Croxon cmp.eq Prela,p0 = DT_RELA,d_tag 133530d68baSNigel Croxon cmp.eq Prelasz,p0 = DT_RELASZ,d_tag 134530d68baSNigel Croxon cmp.eq Psymtab,p0 = DT_SYMTAB,d_tag 135530d68baSNigel Croxon cmp.eq Psyment,p0 = DT_SYMENT,d_tag 136530d68baSNigel Croxon cmp.eq Prelaent,p0 = DT_RELAENT,d_tag 137530d68baSNigel Croxon ;; 138530d68baSNigel Croxon(Prela) add rela = d_val, ldbase 139530d68baSNigel Croxon(Prelasz) mov relasz = d_val 140530d68baSNigel Croxon(Prelaent) mov relaent = d_val 141530d68baSNigel Croxon(Psymtab) add val = d_val, ldbase 142530d68baSNigel Croxon ;; 143530d68baSNigel Croxon(Psyment) setf.sig syment = d_val 144530d68baSNigel Croxon ;; 145530d68baSNigel Croxon(Psymtab) setf.sig symtab = val 146530d68baSNigel Croxon br.sptk.few search_dynamic 147530d68baSNigel Croxon 148530d68baSNigel Croxonapply_loop: 149530d68baSNigel Croxon ld8 r_offset = [rela] 150530d68baSNigel Croxon add addr = 8,rela 151530d68baSNigel Croxon sub relasz = relasz,relaent 152530d68baSNigel Croxon ;; 153530d68baSNigel Croxon 154530d68baSNigel Croxon ld8 r_info = [addr],8 155530d68baSNigel Croxon ;; 156530d68baSNigel Croxon ld8 r_addend = [addr] 157530d68baSNigel Croxon add target = ldbase, r_offset 158530d68baSNigel Croxon 159530d68baSNigel Croxon add rela = rela,relaent 160530d68baSNigel Croxon extr.u r_type = r_info, 0, 32 161530d68baSNigel Croxon ;; 162530d68baSNigel Croxon cmp.eq Pnone,p0 = R_IA64_NONE,r_type 163530d68baSNigel Croxon cmp.eq Prel,p0 = R_IA64_REL64LSB,r_type 164530d68baSNigel Croxon cmp.eq Pfptr,p0 = R_IA64_FPTR64LSB,r_type 165530d68baSNigel Croxon(Prel) br.cond.sptk.few apply_REL64 166530d68baSNigel Croxon ;; 167530d68baSNigel Croxon cmp.eq Prel,p0 = R_IA64_DIR64LSB,r_type // treat DIR64 just like REL64 168530d68baSNigel Croxon 169530d68baSNigel Croxon(Pnone) br.cond.sptk.few apply_relocs 170530d68baSNigel Croxon(Prel) br.cond.sptk.few apply_REL64 171530d68baSNigel Croxon(Pfptr) br.cond.sptk.few apply_FPTR64 172530d68baSNigel Croxon 173530d68baSNigel Croxon mov r8 = EFI_LOAD_ERROR 174530d68baSNigel Croxon br.ret.sptk.few rp 175530d68baSNigel Croxon 176530d68baSNigel Croxonapply_relocs: 177530d68baSNigel Croxon cmp.ltu Pmore,p0=0,relasz 178530d68baSNigel Croxon(Pmore) br.cond.sptk.few apply_loop 179530d68baSNigel Croxon 180530d68baSNigel Croxon mov r8 = EFI_SUCCESS 181530d68baSNigel Croxon br.ret.sptk.few rp 182530d68baSNigel Croxon 183530d68baSNigel Croxonapply_REL64: 184530d68baSNigel Croxon ld8 val = [target] 185530d68baSNigel Croxon ;; 186530d68baSNigel Croxon add val = val,ldbase 187530d68baSNigel Croxon ;; 188530d68baSNigel Croxon st8 [target] = val 189530d68baSNigel Croxon br.cond.sptk.few apply_relocs 190530d68baSNigel Croxon 191530d68baSNigel Croxon // FPTR relocs are a bit more interesting: we need to lookup 192530d68baSNigel Croxon // the symbol's value in symtab, allocate 16 bytes of memory, 193530d68baSNigel Croxon // store the value in [target] in the first and the gp in the 194530d68baSNigel Croxon // second dword. 195530d68baSNigel Croxonapply_FPTR64: 196530d68baSNigel Croxon st8 [target] = fptr 197530d68baSNigel Croxon extr.u r_sym = r_info,32,32 198530d68baSNigel Croxon add target = 8,fptr 199530d68baSNigel Croxon ;; 200530d68baSNigel Croxon 201530d68baSNigel Croxon setf.sig ftmp = r_sym 202530d68baSNigel Croxon mov r8=EFI_BUFFER_TOO_SMALL 203530d68baSNigel Croxon ;; 204530d68baSNigel Croxon cmp.geu Poom,p0 = fptr,fptr_limit 205530d68baSNigel Croxon 206530d68baSNigel Croxon xma.lu ftmp = ftmp,syment,symtab 207530d68baSNigel Croxon(Poom) br.ret.sptk.few rp 208530d68baSNigel Croxon ;; 209530d68baSNigel Croxon getf.sig addr = ftmp 210530d68baSNigel Croxon st8 [target] = gp 211530d68baSNigel Croxon ;; 212530d68baSNigel Croxon add addr = ST_VALUE_OFF, addr 213530d68baSNigel Croxon ;; 214530d68baSNigel Croxon ld8 val = [addr] 215530d68baSNigel Croxon ;; 216530d68baSNigel Croxon add val = val,ldbase 217530d68baSNigel Croxon ;; 218530d68baSNigel Croxon st8 [fptr] = val,16 219530d68baSNigel Croxon br.cond.sptk.few apply_relocs 220530d68baSNigel Croxon 221530d68baSNigel Croxon .endp _relocate 222530d68baSNigel Croxon 223530d68baSNigel Croxon .data 224530d68baSNigel Croxon .align 16 225530d68baSNigel Croxonfptr_mem_base: 226530d68baSNigel Croxon .space MAX_FUNCTION_DESCRIPTORS*16 227530d68baSNigel Croxonfptr_mem_limit: 228*803b49c4SSergei Trofimovich 229*803b49c4SSergei Trofimovich#if defined(__ELF__) && defined(__linux__) 230*803b49c4SSergei Trofimovich .section .note.GNU-stack,"",%progbits 231*803b49c4SSergei Trofimovich#endif 232