xref: /DragonStub/gnuefi/reloc_ia64.S (revision 530d68ba191850edafc6da22cb2df55bec0c5fa5)
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