1 /* reloc_ia64.S - position independent IA-64 ELF shared object relocator
2 Copyright (C) 1999 Hewlett-Packard Co.
3 Contributed by David Mosberger <davidm@hpl.hp.com>.
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions
11 * Redistributions of source code must retain the above copyright
12 notice, this list of conditions and the following disclaimer.
13 * Redistributions in binary form must reproduce the above
14 copyright notice, this list of conditions and the following
15 disclaimer in the documentation and/or other materials
16 provided with the distribution.
17 * Neither the name of Hewlett-Packard Co. nor the names of its
18 contributors may be used to endorse or promote products derived
19 from this software without specific prior written permission.
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
22 CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
23 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
24 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
26 BE LIABLE FOR ANYDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
27 OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
31 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
32 THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 * This is written in assembly because the entire code needs to be position
38 * independent. Note that the compiler does not generate code that's position
39 * independent by itself because it relies on the global offset table being
48 * This constant determines how many R_IA64_FPTR64LSB relocations we
49 * can deal with. If you get EFI_BUFFER_TOO_SMALL errors, you may
50 * need to increase this number.
52 #define MAX_FUNCTION_DESCRIPTORS 750
54 #define ST_VALUE_OFF 8 /* offset of st_value in elf sym */
57 #define EFI_LOAD_ERROR 1
58 #define EFI_BUFFER_TOO_SMALL 5
60 #define DT_NULL 0 /* Marks end of dynamic section */
61 #define DT_RELA 7 /* Address of Rela relocs */
62 #define DT_RELASZ 8 /* Total size of Rela relocs */
63 #define DT_RELAENT 9 /* Size of one Rela reloc */
64 #define DT_SYMTAB 6 /* Address of symbol table */
65 #define DT_SYMENT 11 /* Size of one symbol table entry */
68 #define R_IA64_REL64MSB 0x6e
69 #define R_IA64_REL64LSB 0x6f
70 #define R_IA64_DIR64MSB 0x26
71 #define R_IA64_DIR64LSB 0x27
72 #define R_IA64_FPTR64MSB 0x46
73 #define R_IA64_FPTR64LSB 0x47
75 #define ldbase in0 /* load address (address of .text) */
76 #define dyn in1 /* address of _DYNAMIC */
88 #define r_sym r25 /* alias of r_type ! */
90 #define fptr_limit r27
113 #define Poom p6 /* out-of-memory */
118 alloc r2=ar.pfs,2,0,0,0
119 movl fptr = @gprel(fptr_mem_base)
122 movl fptr_limit = @gprel(fptr_mem_limit)
124 add fptr_limit = fptr_limit, gp
130 cmp.eq Pnull,p0 = DT_NULL,d_tag
131 (Pnull) br.cond.sptk.few apply_relocs
132 cmp.eq Prela,p0 = DT_RELA,d_tag
133 cmp.eq Prelasz,p0 = DT_RELASZ,d_tag
134 cmp.eq Psymtab,p0 = DT_SYMTAB,d_tag
135 cmp.eq Psyment,p0 = DT_SYMENT,d_tag
136 cmp.eq Prelaent,p0 = DT_RELAENT,d_tag
138 (Prela) add rela = d_val, ldbase
139 (Prelasz) mov relasz = d_val
140 (Prelaent) mov relaent = d_val
141 (Psymtab) add val = d_val, ldbase
143 (Psyment) setf.sig syment = d_val
145 (Psymtab) setf.sig symtab = val
146 br.sptk.few search_dynamic
149 ld8 r_offset = [rela]
151 sub relasz = relasz,relaent
154 ld8 r_info = [addr],8
156 ld8 r_addend = [addr]
157 add target = ldbase, r_offset
159 add rela = rela,relaent
160 extr.u r_type = r_info, 0, 32
162 cmp.eq Pnone,p0 = R_IA64_NONE,r_type
163 cmp.eq Prel,p0 = R_IA64_REL64LSB,r_type
164 cmp.eq Pfptr,p0 = R_IA64_FPTR64LSB,r_type
165 (Prel) br.cond.sptk.few apply_REL64
167 cmp.eq Prel,p0 = R_IA64_DIR64LSB,r_type // treat DIR64 just like REL64
169 (Pnone) br.cond.sptk.few apply_relocs
170 (Prel) br.cond.sptk.few apply_REL64
171 (Pfptr) br.cond.sptk.few apply_FPTR64
173 mov r8 = EFI_LOAD_ERROR
177 cmp.ltu Pmore,p0=0,relasz
178 (Pmore) br.cond.sptk.few apply_loop
189 br.cond.sptk.few apply_relocs
191 // FPTR relocs are a bit more interesting: we need to lookup
192 // the symbol's value in symtab, allocate 16 bytes of memory,
193 // store the value in [target] in the first and the gp in the
197 extr.u r_sym = r_info,32,32
201 setf.sig ftmp = r_sym
202 mov r8=EFI_BUFFER_TOO_SMALL
204 cmp.geu Poom,p0 = fptr,fptr_limit
206 xma.lu ftmp = ftmp,syment,symtab
207 (Poom) br.ret.sptk.few rp
212 add addr = ST_VALUE_OFF, addr
219 br.cond.sptk.few apply_relocs
226 .space MAX_FUNCTION_DESCRIPTORS*16