Subversion Repositories HelenOS

Rev

Rev 2726 | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 2726 Rev 2782
1
/* reloc_ia64.S - position independent IA-64 ELF shared object relocator
1
/* reloc_ia64.S - position independent IA-64 ELF shared object relocator
2
   Copyright (C) 1999 Hewlett-Packard Co.
2
   Copyright (C) 1999 Hewlett-Packard Co.
3
	Contributed by David Mosberger <davidm@hpl.hp.com>.
3
	Contributed by David Mosberger <davidm@hpl.hp.com>.
4
 
4
 
5
   This file is part of GNU-EFI, the GNU EFI development environment.
5
   This file is part of GNU-EFI, the GNU EFI development environment.
6
 
6
 
7
   GNU EFI is free software; you can redistribute it and/or modify
7
   GNU EFI is free software; you can redistribute it and/or modify
8
   it under the terms of the GNU General Public License as published by
8
   it under the terms of the GNU General Public License as published by
9
   the Free Software Foundation; either version 2, or (at your option)
9
   the Free Software Foundation; either version 2, or (at your option)
10
   any later version.
10
   any later version.
11
 
11
 
12
   GNU EFI is distributed in the hope that it will be useful,
12
   GNU EFI is distributed in the hope that it will be useful,
13
   but WITHOUT ANY WARRANTY; without even the implied warranty of
13
   but WITHOUT ANY WARRANTY; without even the implied warranty of
14
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
   GNU General Public License for more details.
15
   GNU General Public License for more details.
16
 
16
 
17
   You should have received a copy of the GNU General Public License
17
   You should have received a copy of the GNU General Public License
18
   along with GNU EFI; see the file COPYING.  If not, write to the Free
18
   along with GNU EFI; see the file COPYING.  If not, write to the Free
19
   Software Foundation, 59 Temple Place - Suite 330, Boston, MA
19
   Software Foundation, 59 Temple Place - Suite 330, Boston, MA
20
   02111-1307, USA. */
20
   02111-1307, USA. */
21
 
21
 
22
/*
22
/*
23
 * This is written in assembly because the entire code needs to be position
23
 * This is written in assembly because the entire code needs to be position
24
 * independent.  Note that the compiler does not generate code that's position
24
 * independent.  Note that the compiler does not generate code that's position
25
 * independent by itself because it relies on the global offset table being
25
 * independent by itself because it relies on the global offset table being
26
 * relocated.
26
 * relocated.
27
 */
27
 */
28
	.text
28
	.text
29
	.psr abi64
29
	.psr abi64
30
	.psr lsb
30
	.psr lsb
31
	.lsb
31
	.lsb
32
 
32
 
33
/*
33
/*
34
 * This constant determines how many R_IA64_FPTR64LSB relocations we
34
 * This constant determines how many R_IA64_FPTR64LSB relocations we
35
 * can deal with.  If you get EFI_BUFFER_TOO_SMALL errors, you may
35
 * can deal with.  If you get EFI_BUFFER_TOO_SMALL errors, you may
36
 * need to increase this number.
36
 * need to increase this number.
37
 */
37
 */
38
#define MAX_FUNCTION_DESCRIPTORS	750
38
#define MAX_FUNCTION_DESCRIPTORS	750
39
 
39
 
40
#define ST_VALUE_OFF	8		/* offset of st_value in elf sym */
40
#define ST_VALUE_OFF	8		/* offset of st_value in elf sym */
41
 
41
 
42
#define EFI_SUCCESS		0
42
#define EFI_SUCCESS		0
43
#define EFI_LOAD_ERROR		1
43
#define EFI_LOAD_ERROR		1
44
#define EFI_BUFFER_TOO_SMALL	5
44
#define EFI_BUFFER_TOO_SMALL	5
45
 
45
 
46
#define DT_NULL		0		/* Marks end of dynamic section */
46
#define DT_NULL		0		/* Marks end of dynamic section */
47
#define DT_RELA		7		/* Address of Rela relocs */
47
#define DT_RELA		7		/* Address of Rela relocs */
48
#define DT_RELASZ	8		/* Total size of Rela relocs */
48
#define DT_RELASZ	8		/* Total size of Rela relocs */
49
#define DT_RELAENT	9		/* Size of one Rela reloc */
49
#define DT_RELAENT	9		/* Size of one Rela reloc */
50
#define DT_SYMTAB	6		/* Address of symbol table */
50
#define DT_SYMTAB	6		/* Address of symbol table */
51
#define DT_SYMENT	11		/* Size of one symbol table entry */
51
#define DT_SYMENT	11		/* Size of one symbol table entry */
52
 
52
 
53
#define R_IA64_NONE		0
53
#define R_IA64_NONE		0
54
#define R_IA64_REL64MSB		0x6e
54
#define R_IA64_REL64MSB		0x6e
55
#define R_IA64_REL64LSB		0x6f
55
#define R_IA64_REL64LSB		0x6f
56
#define R_IA64_DIR64MSB		0x26
56
#define R_IA64_DIR64MSB		0x26
57
#define R_IA64_DIR64LSB		0x27
57
#define R_IA64_DIR64LSB		0x27
58
#define R_IA64_FPTR64MSB	0x46
58
#define R_IA64_FPTR64MSB	0x46
59
#define R_IA64_FPTR64LSB	0x47
59
#define R_IA64_FPTR64LSB	0x47
60
 
60
 
61
#define	ldbase	in0	/* load address (address of .text) */
61
#define	ldbase	in0	/* load address (address of .text) */
62
#define	dyn	in1	/* address of _DYNAMIC */
62
#define	dyn	in1	/* address of _DYNAMIC */
63
 
63
 
64
#define d_tag	r16
64
#define d_tag	r16
65
#define d_val	r17
65
#define d_val	r17
66
#define rela	r18
66
#define rela	r18
67
#define relasz	r19
67
#define relasz	r19
68
#define relaent	r20
68
#define relaent	r20
69
#define addr	r21
69
#define addr	r21
70
#define r_info	r22
70
#define r_info	r22
71
#define r_offset r23
71
#define r_offset r23
72
#define r_addend r24
72
#define r_addend r24
73
#define r_type	r25
73
#define r_type	r25
74
#define r_sym	r25	/* alias of r_type ! */
74
#define r_sym	r25	/* alias of r_type ! */
75
#define fptr	r26
75
#define fptr	r26
76
#define fptr_limit r27
76
#define fptr_limit r27
77
#define symtab	f8
77
#define symtab	f8
78
#define syment	f9
78
#define syment	f9
79
#define ftmp	f10
79
#define ftmp	f10
80
 
80
 
81
#define	target	r16
81
#define	target	r16
82
#define val	r17
82
#define val	r17
83
 
83
 
84
#define NLOC	0
84
#define NLOC	0
85
 
85
 
86
#define Pnull		p6
86
#define Pnull		p6
87
#define Prela		p7
87
#define Prela		p7
88
#define Prelasz		p8
88
#define Prelasz		p8
89
#define Prelaent	p9
89
#define Prelaent	p9
90
#define Psymtab		p10
90
#define Psymtab		p10
91
#define Psyment		p11
91
#define Psyment		p11
92
 
92
 
93
#define Pnone		p6
93
#define Pnone		p6
94
#define Prel		p7
94
#define Prel		p7
95
#define Pfptr		p8
95
#define Pfptr		p8
96
 
96
 
97
#define Pmore		p6
97
#define Pmore		p6
98
 
98
 
99
#define Poom		p6	/* out-of-memory */
99
#define Poom		p6	/* out-of-memory */
100
 
100
 
101
	.global _relocate
101
	.global _relocate
102
	.proc _relocate
102
	.proc _relocate
103
_relocate:
103
_relocate:
104
	alloc r2=ar.pfs,2,0,0,0
104
	alloc r2=ar.pfs,2,0,0,0
105
	movl	fptr = @gprel(fptr_mem_base)
105
	movl	fptr = @gprel(fptr_mem_base)
106
	;;
106
	;;
107
	add	fptr = fptr, gp
107
	add	fptr = fptr, gp
108
	movl	fptr_limit = @gprel(fptr_mem_limit)
108
	movl	fptr_limit = @gprel(fptr_mem_limit)
109
	;;
109
	;;
110
	add	fptr_limit = fptr_limit, gp
110
	add	fptr_limit = fptr_limit, gp
111
 
111
 
112
search_dynamic:
112
search_dynamic:
113
	ld8	d_tag = [dyn],8
113
	ld8	d_tag = [dyn],8
114
	;;
114
	;;
115
	ld8	d_val = [dyn],8
115
	ld8	d_val = [dyn],8
116
	cmp.eq	Pnull,p0 = DT_NULL,d_tag
116
	cmp.eq	Pnull,p0 = DT_NULL,d_tag
117
(Pnull)	br.cond.sptk.few apply_relocs
117
(Pnull)	br.cond.sptk.few apply_relocs
118
	cmp.eq	Prela,p0 = DT_RELA,d_tag
118
	cmp.eq	Prela,p0 = DT_RELA,d_tag
119
	cmp.eq	Prelasz,p0 = DT_RELASZ,d_tag
119
	cmp.eq	Prelasz,p0 = DT_RELASZ,d_tag
120
	cmp.eq	Psymtab,p0 = DT_SYMTAB,d_tag
120
	cmp.eq	Psymtab,p0 = DT_SYMTAB,d_tag
121
	cmp.eq	Psyment,p0 = DT_SYMENT,d_tag
121
	cmp.eq	Psyment,p0 = DT_SYMENT,d_tag
122
	cmp.eq	Prelaent,p0 = DT_RELAENT,d_tag
122
	cmp.eq	Prelaent,p0 = DT_RELAENT,d_tag
123
	;;
123
	;;
124
(Prela)	add rela = d_val, ldbase
124
(Prela)	add rela = d_val, ldbase
125
(Prelasz) mov relasz = d_val
125
(Prelasz) mov relasz = d_val
126
(Prelaent) mov relaent = d_val
126
(Prelaent) mov relaent = d_val
127
(Psymtab) add val = d_val, ldbase
127
(Psymtab) add val = d_val, ldbase
128
(Psyment) setf.sig syment = d_val
128
(Psyment) setf.sig syment = d_val
129
	;;
129
	;;
130
(Psymtab) setf.sig symtab = val
130
(Psymtab) setf.sig symtab = val
131
	br.sptk.few search_dynamic
131
	br.sptk.few search_dynamic
132
 
132
 
133
apply_loop:
133
apply_loop:
134
	ld8	r_offset = [rela]
134
	ld8	r_offset = [rela]
135
	add	addr = 8,rela
135
	add	addr = 8,rela
136
	sub	relasz = relasz,relaent
136
	sub	relasz = relasz,relaent
137
	;;
137
	;;
138
 
138
 
139
	ld8	r_info = [addr],8
139
	ld8	r_info = [addr],8
140
	;;
140
	;;
141
	ld8	r_addend = [addr]
141
	ld8	r_addend = [addr]
142
	add	target = ldbase, r_offset
142
	add	target = ldbase, r_offset
143
 
143
 
144
	add	rela = rela,relaent
144
	add	rela = rela,relaent
145
	extr.u	r_type = r_info, 0, 32
145
	extr.u	r_type = r_info, 0, 32
146
	;;
146
	;;
147
	cmp.eq	Pnone,p0 = R_IA64_NONE,r_type
147
	cmp.eq	Pnone,p0 = R_IA64_NONE,r_type
148
	cmp.eq	Prel,p0 = R_IA64_REL64LSB,r_type
148
	cmp.eq	Prel,p0 = R_IA64_REL64LSB,r_type
149
	cmp.eq	Pfptr,p0 = R_IA64_FPTR64LSB,r_type
149
	cmp.eq	Pfptr,p0 = R_IA64_FPTR64LSB,r_type
150
(Prel)	br.cond.sptk.few apply_REL64
150
(Prel)	br.cond.sptk.few apply_REL64
151
	;;
151
	;;
152
	cmp.eq	Prel,p0 = R_IA64_DIR64LSB,r_type // treat DIR64 just like REL64
152
	cmp.eq	Prel,p0 = R_IA64_DIR64LSB,r_type // treat DIR64 just like REL64
153
 
153
 
154
(Pnone)	br.cond.sptk.few apply_relocs
154
(Pnone)	br.cond.sptk.few apply_relocs
155
(Prel)	br.cond.sptk.few apply_REL64
155
(Prel)	br.cond.sptk.few apply_REL64
156
(Pfptr)	br.cond.sptk.few apply_FPTR64
156
(Pfptr)	br.cond.sptk.few apply_FPTR64
157
 
157
 
158
	mov	r8 = EFI_LOAD_ERROR
158
	mov	r8 = EFI_LOAD_ERROR
159
	br.ret.sptk.few rp
159
	br.ret.sptk.few rp
160
 
160
 
161
apply_relocs:
161
apply_relocs:
162
	cmp.ltu	Pmore,p0=0,relasz
162
	cmp.ltu	Pmore,p0=0,relasz
163
(Pmore)	br.cond.sptk.few apply_loop
163
(Pmore)	br.cond.sptk.few apply_loop
164
 
164
 
165
	mov	r8 = EFI_SUCCESS
165
	mov	r8 = EFI_SUCCESS
166
	br.ret.sptk.few rp
166
	br.ret.sptk.few rp
167
 
167
 
168
apply_REL64:
168
apply_REL64:
169
	ld8 val = [target]
169
	ld8 val = [target]
170
	;;
170
	;;
171
	add val = val,ldbase
171
	add val = val,ldbase
172
	;;
172
	;;
173
	st8 [target] = val
173
	st8 [target] = val
174
	br.cond.sptk.few apply_relocs
174
	br.cond.sptk.few apply_relocs
175
 
175
 
176
	// FPTR relocs are a bit more interesting: we need to lookup
176
	// FPTR relocs are a bit more interesting: we need to lookup
177
	// the symbol's value in symtab, allocate 16 bytes of memory,
177
	// the symbol's value in symtab, allocate 16 bytes of memory,
178
	// store the value in [target] in the first and the gp in the
178
	// store the value in [target] in the first and the gp in the
179
	// second dword.
179
	// second dword.
180
apply_FPTR64:
180
apply_FPTR64:
181
	st8	[target] = fptr
181
	st8	[target] = fptr
182
	extr.u	r_sym = r_info,32,32
182
	extr.u	r_sym = r_info,32,32
183
	add	target = 8,fptr
183
	add	target = 8,fptr
184
	;;
184
	;;
185
 
185
 
186
	setf.sig ftmp = r_sym
186
	setf.sig ftmp = r_sym
187
	mov	r8=EFI_BUFFER_TOO_SMALL
187
	mov	r8=EFI_BUFFER_TOO_SMALL
188
	;;
188
	;;
189
	cmp.geu	Poom,p0 = fptr,fptr_limit
189
	cmp.geu	Poom,p0 = fptr,fptr_limit
190
 
190
 
191
	xma.lu	ftmp = ftmp,syment,symtab
191
	xma.lu	ftmp = ftmp,syment,symtab
192
(Poom)	br.ret.sptk.few rp
192
(Poom)	br.ret.sptk.few rp
193
	;;
193
	;;
194
	getf.sig addr = ftmp
194
	getf.sig addr = ftmp
195
	st8	[target] = gp
195
	st8	[target] = gp
196
	;;
196
	;;
197
	add	addr = ST_VALUE_OFF, addr
197
	add	addr = ST_VALUE_OFF, addr
198
	;;
198
	;;
199
	ld8	val = [addr]
199
	ld8	val = [addr]
200
	;;
200
	;;
201
	add	val = val,ldbase
201
	add	val = val,ldbase
202
	;;
202
	;;
203
	st8	[fptr] = val,16
203
	st8	[fptr] = val,16
204
	br.cond.sptk.few apply_relocs
204
	br.cond.sptk.few apply_relocs
205
 
205
 
206
	.endp _relocate
206
	.endp _relocate
207
 
207
 
208
	.data
208
	.data
209
	.align 16
209
	.align 16
210
fptr_mem_base:
210
fptr_mem_base:
211
	.space  MAX_FUNCTION_DESCRIPTORS*16
211
	.space  MAX_FUNCTION_DESCRIPTORS*16
212
fptr_mem_limit:
212
fptr_mem_limit:
213
 
213