1 |
vapier 14/06/03 02:52:36 |
2 |
|
3 |
Modified: README.history |
4 |
Added: 52_all_binutils-alpha-relax.patch |
5 |
Log: |
6 |
fix from upstream for relax handling on alpha #366025 |
7 |
|
8 |
Revision Changes Path |
9 |
1.5 src/patchsets/binutils/2.24/README.history |
10 |
|
11 |
file : http://sources.gentoo.org/viewvc.cgi/gentoo/src/patchsets/binutils/2.24/README.history?rev=1.5&view=markup |
12 |
plain: http://sources.gentoo.org/viewvc.cgi/gentoo/src/patchsets/binutils/2.24/README.history?rev=1.5&content-type=text/plain |
13 |
diff : http://sources.gentoo.org/viewvc.cgi/gentoo/src/patchsets/binutils/2.24/README.history?r1=1.4&r2=1.5 |
14 |
|
15 |
Index: README.history |
16 |
=================================================================== |
17 |
RCS file: /var/cvsroot/gentoo/src/patchsets/binutils/2.24/README.history,v |
18 |
retrieving revision 1.4 |
19 |
retrieving revision 1.5 |
20 |
diff -u -r1.4 -r1.5 |
21 |
--- README.history 19 Jan 2014 04:39:14 -0000 1.4 |
22 |
+++ README.history 3 Jun 2014 02:52:35 -0000 1.5 |
23 |
@@ -1,3 +1,6 @@ |
24 |
+1.4 [pending] |
25 |
+ + 52_all_binutils-alpha-relax.patch |
26 |
+ |
27 |
1.3 18 Jan 2014 |
28 |
+ 24_all_as-needed.patch |
29 |
|
30 |
|
31 |
|
32 |
|
33 |
1.1 src/patchsets/binutils/2.24/52_all_binutils-alpha-relax.patch |
34 |
|
35 |
file : http://sources.gentoo.org/viewvc.cgi/gentoo/src/patchsets/binutils/2.24/52_all_binutils-alpha-relax.patch?rev=1.1&view=markup |
36 |
plain: http://sources.gentoo.org/viewvc.cgi/gentoo/src/patchsets/binutils/2.24/52_all_binutils-alpha-relax.patch?rev=1.1&content-type=text/plain |
37 |
|
38 |
Index: 52_all_binutils-alpha-relax.patch |
39 |
=================================================================== |
40 |
https://bugs.gentoo.org/366025 |
41 |
|
42 |
From d1c109de72f880ea2a761fccb41f330672674fd9 Mon Sep 17 00:00:00 2001 |
43 |
From: Richard Henderson <rth@×××××××.net> |
44 |
Date: Mon, 21 Apr 2014 08:14:18 -0700 |
45 |
Subject: [PATCH] Fix alpha-elf relaxation |
46 |
|
47 |
ld/ |
48 |
* emultempl/alphaelf.em (alpha_after_parse): Enable 2 relax passes. |
49 |
bfd/ |
50 |
* elf64-alpha.c (elf64_alpha_size_got_sections): New may_merge |
51 |
parameter; honor it and disable got merging when false. |
52 |
(elf64_alpha_relax_got_load): Do not relax to GPREL relocs during |
53 |
the first pass of relaxation. |
54 |
(elf64_alpha_relax_with_lituse): Likewise. Move relaxed relocs to |
55 |
the end of the LITERAL+LITUSE chain. |
56 |
(elf64_alpha_relax_section): Only process LITERAL relocs during the |
57 |
second pass of relaxation. |
58 |
--- |
59 |
bfd/ChangeLog | 9 ++ |
60 |
bfd/elf64-alpha.c | 241 ++++++++++++++++++++++++++++------------------- |
61 |
ld/ChangeLog | 4 + |
62 |
ld/emultempl/alphaelf.em | 1 + |
63 |
4 files changed, 159 insertions(+), 96 deletions(-) |
64 |
|
65 |
2014-04-21 Richard Henderson <rth@××××××.com> |
66 |
|
67 |
* elf64-alpha.c (elf64_alpha_size_got_sections): New may_merge |
68 |
parameter; honor it and disable got merging when false. |
69 |
(elf64_alpha_relax_got_load): Do not relax to GPREL relocs during |
70 |
the first pass of relaxation. |
71 |
(elf64_alpha_relax_with_lituse): Likewise. Move relaxed relocs to |
72 |
the end of the LITERAL+LITUSE chain. |
73 |
(elf64_alpha_relax_section): Only process LITERAL relocs during the |
74 |
second pass of relaxation. |
75 |
|
76 |
diff --git a/bfd/elf64-alpha.c b/bfd/elf64-alpha.c |
77 |
index c9876fb..073e578 100644 |
78 |
--- a/bfd/elf64-alpha.c |
79 |
+++ b/bfd/elf64-alpha.c |
80 |
@@ -2466,7 +2466,8 @@ elf64_alpha_calc_got_offsets (struct bfd_link_info *info) |
81 |
/* Constructs the gots. */ |
82 |
|
83 |
static bfd_boolean |
84 |
-elf64_alpha_size_got_sections (struct bfd_link_info *info) |
85 |
+elf64_alpha_size_got_sections (struct bfd_link_info *info, |
86 |
+ bfd_boolean may_merge) |
87 |
{ |
88 |
bfd *i, *got_list, *cur_got_obj = NULL; |
89 |
struct alpha_elf_link_hash_table * htab; |
90 |
@@ -2521,21 +2522,24 @@ elf64_alpha_size_got_sections (struct bfd_link_info *info) |
91 |
if (cur_got_obj == NULL) |
92 |
return FALSE; |
93 |
|
94 |
- i = alpha_elf_tdata(cur_got_obj)->got_link_next; |
95 |
- while (i != NULL) |
96 |
+ if (may_merge) |
97 |
{ |
98 |
- if (elf64_alpha_can_merge_gots (cur_got_obj, i)) |
99 |
+ i = alpha_elf_tdata(cur_got_obj)->got_link_next; |
100 |
+ while (i != NULL) |
101 |
{ |
102 |
- elf64_alpha_merge_gots (cur_got_obj, i); |
103 |
+ if (elf64_alpha_can_merge_gots (cur_got_obj, i)) |
104 |
+ { |
105 |
+ elf64_alpha_merge_gots (cur_got_obj, i); |
106 |
|
107 |
- alpha_elf_tdata(i)->got->size = 0; |
108 |
- i = alpha_elf_tdata(i)->got_link_next; |
109 |
- alpha_elf_tdata(cur_got_obj)->got_link_next = i; |
110 |
- } |
111 |
- else |
112 |
- { |
113 |
- cur_got_obj = i; |
114 |
- i = alpha_elf_tdata(i)->got_link_next; |
115 |
+ alpha_elf_tdata(i)->got->size = 0; |
116 |
+ i = alpha_elf_tdata(i)->got_link_next; |
117 |
+ alpha_elf_tdata(cur_got_obj)->got_link_next = i; |
118 |
+ } |
119 |
+ else |
120 |
+ { |
121 |
+ cur_got_obj = i; |
122 |
+ i = alpha_elf_tdata(i)->got_link_next; |
123 |
+ } |
124 |
} |
125 |
} |
126 |
|
127 |
@@ -2638,7 +2642,7 @@ elf64_alpha_always_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED, |
128 |
if (htab == NULL) |
129 |
return FALSE; |
130 |
|
131 |
- if (!elf64_alpha_size_got_sections (info)) |
132 |
+ if (!elf64_alpha_size_got_sections (info, TRUE)) |
133 |
return FALSE; |
134 |
|
135 |
/* Allocate space for all of the .got subsections. */ |
136 |
@@ -3074,6 +3078,10 @@ elf64_alpha_relax_got_load (struct alpha_relax_info *info, bfd_vma symval, |
137 |
} |
138 |
else |
139 |
{ |
140 |
+ /* We may only create GPREL relocs during the second pass. */ |
141 |
+ if (info->link_info->relax_pass == 0) |
142 |
+ return TRUE; |
143 |
+ |
144 |
disp = symval - info->gp; |
145 |
insn = (OP_LDA << 26) | (insn & 0x03ff0000); |
146 |
r_type = R_ALPHA_GPREL16; |
147 |
@@ -3214,21 +3222,27 @@ static bfd_boolean |
148 |
elf64_alpha_relax_with_lituse (struct alpha_relax_info *info, |
149 |
bfd_vma symval, Elf_Internal_Rela *irel) |
150 |
{ |
151 |
- Elf_Internal_Rela *urel, *irelend = info->relend; |
152 |
- int flags, count, i; |
153 |
+ Elf_Internal_Rela *urel, *erel, *irelend = info->relend; |
154 |
+ int flags; |
155 |
bfd_signed_vma disp; |
156 |
bfd_boolean fits16; |
157 |
bfd_boolean fits32; |
158 |
bfd_boolean lit_reused = FALSE; |
159 |
bfd_boolean all_optimized = TRUE; |
160 |
+ bfd_boolean changed_contents; |
161 |
+ bfd_boolean changed_relocs; |
162 |
+ bfd_byte *contents = info->contents; |
163 |
+ bfd *abfd = info->abfd; |
164 |
+ bfd_vma sec_output_vma; |
165 |
unsigned int lit_insn; |
166 |
+ int relax_pass; |
167 |
|
168 |
- lit_insn = bfd_get_32 (info->abfd, info->contents + irel->r_offset); |
169 |
+ lit_insn = bfd_get_32 (abfd, contents + irel->r_offset); |
170 |
if (lit_insn >> 26 != OP_LDQ) |
171 |
{ |
172 |
((*_bfd_error_handler) |
173 |
("%B: %A+0x%lx: warning: LITERAL relocation against unexpected insn", |
174 |
- info->abfd, info->sec, |
175 |
+ abfd, info->sec, |
176 |
(unsigned long) irel->r_offset)); |
177 |
return TRUE; |
178 |
} |
179 |
@@ -3237,25 +3251,32 @@ elf64_alpha_relax_with_lituse (struct alpha_relax_info *info, |
180 |
if (alpha_elf_dynamic_symbol_p (&info->h->root, info->link_info)) |
181 |
return TRUE; |
182 |
|
183 |
+ changed_contents = info->changed_contents; |
184 |
+ changed_relocs = info->changed_relocs; |
185 |
+ sec_output_vma = info->sec->output_section->vma + info->sec->output_offset; |
186 |
+ relax_pass = info->link_info->relax_pass; |
187 |
+ |
188 |
/* Summarize how this particular LITERAL is used. */ |
189 |
- for (urel = irel+1, flags = count = 0; urel < irelend; ++urel, ++count) |
190 |
+ for (erel = irel+1, flags = 0; erel < irelend; ++erel) |
191 |
{ |
192 |
- if (ELF64_R_TYPE (urel->r_info) != R_ALPHA_LITUSE) |
193 |
+ if (ELF64_R_TYPE (erel->r_info) != R_ALPHA_LITUSE) |
194 |
break; |
195 |
- if (urel->r_addend <= 6) |
196 |
- flags |= 1 << urel->r_addend; |
197 |
+ if (erel->r_addend <= 6) |
198 |
+ flags |= 1 << erel->r_addend; |
199 |
} |
200 |
|
201 |
/* A little preparation for the loop... */ |
202 |
disp = symval - info->gp; |
203 |
|
204 |
- for (urel = irel+1, i = 0; i < count; ++i, ++urel) |
205 |
+ for (urel = irel+1; urel < erel; ++urel) |
206 |
{ |
207 |
+ bfd_vma urel_r_offset = urel->r_offset; |
208 |
unsigned int insn; |
209 |
int insn_disp; |
210 |
bfd_signed_vma xdisp; |
211 |
+ Elf_Internal_Rela nrel; |
212 |
|
213 |
- insn = bfd_get_32 (info->abfd, info->contents + urel->r_offset); |
214 |
+ insn = bfd_get_32 (abfd, contents + urel_r_offset); |
215 |
|
216 |
switch (urel->r_addend) |
217 |
{ |
218 |
@@ -3267,6 +3288,13 @@ elf64_alpha_relax_with_lituse (struct alpha_relax_info *info, |
219 |
break; |
220 |
|
221 |
case LITUSE_ALPHA_BASE: |
222 |
+ /* We may only create GPREL relocs during the second pass. */ |
223 |
+ if (relax_pass == 0) |
224 |
+ { |
225 |
+ all_optimized = FALSE; |
226 |
+ break; |
227 |
+ } |
228 |
+ |
229 |
/* We can always optimize 16-bit displacements. */ |
230 |
|
231 |
/* Extract the displacement from the instruction, sign-extending |
232 |
@@ -3284,14 +3312,20 @@ elf64_alpha_relax_with_lituse (struct alpha_relax_info *info, |
233 |
/* Take the op code and dest from this insn, take the base |
234 |
register from the literal insn. Leave the offset alone. */ |
235 |
insn = (insn & 0xffe0ffff) | (lit_insn & 0x001f0000); |
236 |
- urel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info), |
237 |
- R_ALPHA_GPREL16); |
238 |
- urel->r_addend = irel->r_addend; |
239 |
- info->changed_relocs = TRUE; |
240 |
- |
241 |
- bfd_put_32 (info->abfd, (bfd_vma) insn, |
242 |
- info->contents + urel->r_offset); |
243 |
- info->changed_contents = TRUE; |
244 |
+ bfd_put_32 (abfd, (bfd_vma) insn, contents + urel_r_offset); |
245 |
+ changed_contents = TRUE; |
246 |
+ |
247 |
+ nrel = *urel; |
248 |
+ nrel.r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info), |
249 |
+ R_ALPHA_GPREL16); |
250 |
+ nrel.r_addend = irel->r_addend; |
251 |
+ |
252 |
+ /* As we adjust, move the reloc to the end so that we don't |
253 |
+ break the LITERAL+LITUSE chain. */ |
254 |
+ if (urel < --erel) |
255 |
+ *urel-- = *erel; |
256 |
+ *erel = nrel; |
257 |
+ changed_relocs = TRUE; |
258 |
} |
259 |
|
260 |
/* If all mem+byte, we can optimize 32-bit mem displacements. */ |
261 |
@@ -3302,15 +3336,16 @@ elf64_alpha_relax_with_lituse (struct alpha_relax_info *info, |
262 |
irel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info), |
263 |
R_ALPHA_GPRELHIGH); |
264 |
lit_insn = (OP_LDAH << 26) | (lit_insn & 0x03ff0000); |
265 |
- bfd_put_32 (info->abfd, (bfd_vma) lit_insn, |
266 |
- info->contents + irel->r_offset); |
267 |
+ bfd_put_32 (abfd, (bfd_vma) lit_insn, contents + irel->r_offset); |
268 |
lit_reused = TRUE; |
269 |
- info->changed_contents = TRUE; |
270 |
+ changed_contents = TRUE; |
271 |
|
272 |
+ /* Since all relocs must be optimized, don't bother swapping |
273 |
+ this relocation to the end. */ |
274 |
urel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info), |
275 |
R_ALPHA_GPRELLOW); |
276 |
urel->r_addend = irel->r_addend; |
277 |
- info->changed_relocs = TRUE; |
278 |
+ changed_relocs = TRUE; |
279 |
} |
280 |
else |
281 |
all_optimized = FALSE; |
282 |
@@ -3324,14 +3359,19 @@ elf64_alpha_relax_with_lituse (struct alpha_relax_info *info, |
283 |
|
284 |
insn &= ~ (unsigned) 0x001ff000; |
285 |
insn |= ((symval & 7) << 13) | 0x1000; |
286 |
- |
287 |
- urel->r_info = ELF64_R_INFO (0, R_ALPHA_NONE); |
288 |
- urel->r_addend = 0; |
289 |
- info->changed_relocs = TRUE; |
290 |
- |
291 |
- bfd_put_32 (info->abfd, (bfd_vma) insn, |
292 |
- info->contents + urel->r_offset); |
293 |
- info->changed_contents = TRUE; |
294 |
+ bfd_put_32 (abfd, (bfd_vma) insn, contents + urel_r_offset); |
295 |
+ changed_contents = TRUE; |
296 |
+ |
297 |
+ nrel = *urel; |
298 |
+ nrel.r_info = ELF64_R_INFO (0, R_ALPHA_NONE); |
299 |
+ nrel.r_addend = 0; |
300 |
+ |
301 |
+ /* As we adjust, move the reloc to the end so that we don't |
302 |
+ break the LITERAL+LITUSE chain. */ |
303 |
+ if (urel < --erel) |
304 |
+ *urel-- = *erel; |
305 |
+ *erel = nrel; |
306 |
+ changed_relocs = TRUE; |
307 |
break; |
308 |
|
309 |
case LITUSE_ALPHA_JSR: |
310 |
@@ -3348,18 +3388,15 @@ elf64_alpha_relax_with_lituse (struct alpha_relax_info *info, |
311 |
if (info->h && info->h->root.root.type == bfd_link_hash_undefweak) |
312 |
{ |
313 |
insn |= 31 << 16; |
314 |
- bfd_put_32 (info->abfd, (bfd_vma) insn, |
315 |
- info->contents + urel->r_offset); |
316 |
+ bfd_put_32 (abfd, (bfd_vma) insn, contents + urel_r_offset); |
317 |
|
318 |
- info->changed_contents = TRUE; |
319 |
+ changed_contents = TRUE; |
320 |
break; |
321 |
} |
322 |
|
323 |
/* If not zero, place to jump without needing pv. */ |
324 |
optdest = elf64_alpha_relax_opt_call (info, symval); |
325 |
- org = (info->sec->output_section->vma |
326 |
- + info->sec->output_offset |
327 |
- + urel->r_offset + 4); |
328 |
+ org = sec_output_vma + urel_r_offset + 4; |
329 |
odisp = (optdest ? optdest : symval) - org; |
330 |
|
331 |
if (odisp >= -0x400000 && odisp < 0x400000) |
332 |
@@ -3371,27 +3408,32 @@ elf64_alpha_relax_with_lituse (struct alpha_relax_info *info, |
333 |
insn = (OP_BSR << 26) | (insn & 0x03e00000); |
334 |
else |
335 |
insn = (OP_BR << 26) | (insn & 0x03e00000); |
336 |
+ bfd_put_32 (abfd, (bfd_vma) insn, contents + urel_r_offset); |
337 |
+ changed_contents = TRUE; |
338 |
|
339 |
- urel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info), |
340 |
- R_ALPHA_BRADDR); |
341 |
- urel->r_addend = irel->r_addend; |
342 |
+ nrel = *urel; |
343 |
+ nrel.r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info), |
344 |
+ R_ALPHA_BRADDR); |
345 |
+ nrel.r_addend = irel->r_addend; |
346 |
|
347 |
if (optdest) |
348 |
- urel->r_addend += optdest - symval; |
349 |
+ nrel.r_addend += optdest - symval; |
350 |
else |
351 |
all_optimized = FALSE; |
352 |
|
353 |
- bfd_put_32 (info->abfd, (bfd_vma) insn, |
354 |
- info->contents + urel->r_offset); |
355 |
- |
356 |
/* Kill any HINT reloc that might exist for this insn. */ |
357 |
xrel = (elf64_alpha_find_reloc_at_ofs |
358 |
- (info->relocs, info->relend, urel->r_offset, |
359 |
+ (info->relocs, info->relend, urel_r_offset, |
360 |
R_ALPHA_HINT)); |
361 |
if (xrel) |
362 |
xrel->r_info = ELF64_R_INFO (0, R_ALPHA_NONE); |
363 |
|
364 |
- info->changed_contents = TRUE; |
365 |
+ /* As we adjust, move the reloc to the end so that we don't |
366 |
+ break the LITERAL+LITUSE chain. */ |
367 |
+ if (urel < --erel) |
368 |
+ *urel-- = *erel; |
369 |
+ *erel = nrel; |
370 |
+ |
371 |
info->changed_relocs = TRUE; |
372 |
} |
373 |
else |
374 |
@@ -3403,14 +3445,14 @@ elf64_alpha_relax_with_lituse (struct alpha_relax_info *info, |
375 |
{ |
376 |
Elf_Internal_Rela *gpdisp |
377 |
= (elf64_alpha_find_reloc_at_ofs |
378 |
- (info->relocs, irelend, urel->r_offset + 4, |
379 |
+ (info->relocs, irelend, urel_r_offset + 4, |
380 |
R_ALPHA_GPDISP)); |
381 |
if (gpdisp) |
382 |
{ |
383 |
- bfd_byte *p_ldah = info->contents + gpdisp->r_offset; |
384 |
+ bfd_byte *p_ldah = contents + gpdisp->r_offset; |
385 |
bfd_byte *p_lda = p_ldah + gpdisp->r_addend; |
386 |
- unsigned int ldah = bfd_get_32 (info->abfd, p_ldah); |
387 |
- unsigned int lda = bfd_get_32 (info->abfd, p_lda); |
388 |
+ unsigned int ldah = bfd_get_32 (abfd, p_ldah); |
389 |
+ unsigned int lda = bfd_get_32 (abfd, p_lda); |
390 |
|
391 |
/* Verify that the instruction is "ldah $29,0($26)". |
392 |
Consider a function that ends in a noreturn call, |
393 |
@@ -3419,12 +3461,12 @@ elf64_alpha_relax_with_lituse (struct alpha_relax_info *info, |
394 |
In that case the insn would use $27 as the base. */ |
395 |
if (ldah == 0x27ba0000 && lda == 0x23bd0000) |
396 |
{ |
397 |
- bfd_put_32 (info->abfd, (bfd_vma) INSN_UNOP, p_ldah); |
398 |
- bfd_put_32 (info->abfd, (bfd_vma) INSN_UNOP, p_lda); |
399 |
+ bfd_put_32 (abfd, (bfd_vma) INSN_UNOP, p_ldah); |
400 |
+ bfd_put_32 (abfd, (bfd_vma) INSN_UNOP, p_lda); |
401 |
|
402 |
gpdisp->r_info = ELF64_R_INFO (0, R_ALPHA_NONE); |
403 |
- info->changed_contents = TRUE; |
404 |
- info->changed_relocs = TRUE; |
405 |
+ changed_contents = TRUE; |
406 |
+ changed_relocs = TRUE; |
407 |
} |
408 |
} |
409 |
} |
410 |
@@ -3433,6 +3475,9 @@ elf64_alpha_relax_with_lituse (struct alpha_relax_info *info, |
411 |
} |
412 |
} |
413 |
|
414 |
+ /* If we reused the literal instruction, we must have optimized all. */ |
415 |
+ BFD_ASSERT(!lit_reused || all_optimized); |
416 |
+ |
417 |
/* If all cases were optimized, we can reduce the use count on this |
418 |
got entry by one, possibly eliminating it. */ |
419 |
if (all_optimized) |
420 |
@@ -3452,17 +3497,19 @@ elf64_alpha_relax_with_lituse (struct alpha_relax_info *info, |
421 |
if (!lit_reused) |
422 |
{ |
423 |
irel->r_info = ELF64_R_INFO (0, R_ALPHA_NONE); |
424 |
- info->changed_relocs = TRUE; |
425 |
+ changed_relocs = TRUE; |
426 |
|
427 |
- bfd_put_32 (info->abfd, (bfd_vma) INSN_UNOP, |
428 |
- info->contents + irel->r_offset); |
429 |
- info->changed_contents = TRUE; |
430 |
+ bfd_put_32 (abfd, (bfd_vma) INSN_UNOP, contents + irel->r_offset); |
431 |
+ changed_contents = TRUE; |
432 |
} |
433 |
- |
434 |
- return TRUE; |
435 |
} |
436 |
- else |
437 |
- return elf64_alpha_relax_got_load (info, symval, irel, R_ALPHA_LITERAL); |
438 |
+ |
439 |
+ info->changed_contents = changed_contents; |
440 |
+ info->changed_relocs = changed_relocs; |
441 |
+ |
442 |
+ if (all_optimized || relax_pass == 0) |
443 |
+ return TRUE; |
444 |
+ return elf64_alpha_relax_got_load (info, symval, irel, R_ALPHA_LITERAL); |
445 |
} |
446 |
|
447 |
static bfd_boolean |
448 |
@@ -3724,6 +3771,7 @@ elf64_alpha_relax_section (bfd *abfd, asection *sec, |
449 |
struct alpha_elf_got_entry **local_got_entries; |
450 |
struct alpha_relax_info info; |
451 |
struct alpha_elf_link_hash_table * htab; |
452 |
+ int relax_pass; |
453 |
|
454 |
htab = alpha_elf_hash_table (link_info); |
455 |
if (htab == NULL) |
456 |
@@ -3739,15 +3787,19 @@ elf64_alpha_relax_section (bfd *abfd, asection *sec, |
457 |
return TRUE; |
458 |
|
459 |
BFD_ASSERT (is_alpha_elf (abfd)); |
460 |
+ relax_pass = link_info->relax_pass; |
461 |
|
462 |
/* Make sure our GOT and PLT tables are up-to-date. */ |
463 |
if (htab->relax_trip != link_info->relax_trip) |
464 |
{ |
465 |
htab->relax_trip = link_info->relax_trip; |
466 |
|
467 |
- /* This should never fail after the initial round, since the only |
468 |
- error is GOT overflow, and relaxation only shrinks the table. */ |
469 |
- if (!elf64_alpha_size_got_sections (link_info)) |
470 |
+ /* This should never fail after the initial round, since the only error |
471 |
+ is GOT overflow, and relaxation only shrinks the table. However, we |
472 |
+ may only merge got sections during the first pass. If we merge |
473 |
+ sections after we've created GPREL relocs, the GP for the merged |
474 |
+ section backs up which may put the relocs out of range. */ |
475 |
+ if (!elf64_alpha_size_got_sections (link_info, relax_pass == 0)) |
476 |
abort (); |
477 |
if (elf_hash_table (link_info)->dynamic_sections_created) |
478 |
{ |
479 |
@@ -3802,24 +3854,21 @@ elf64_alpha_relax_section (bfd *abfd, asection *sec, |
480 |
unsigned long r_symndx = ELF64_R_SYM (irel->r_info); |
481 |
|
482 |
/* Early exit for unhandled or unrelaxable relocations. */ |
483 |
- switch (r_type) |
484 |
- { |
485 |
- case R_ALPHA_LITERAL: |
486 |
- case R_ALPHA_GPRELHIGH: |
487 |
- case R_ALPHA_GPRELLOW: |
488 |
- case R_ALPHA_GOTDTPREL: |
489 |
- case R_ALPHA_GOTTPREL: |
490 |
- case R_ALPHA_TLSGD: |
491 |
- break; |
492 |
- |
493 |
- case R_ALPHA_TLSLDM: |
494 |
- /* The symbol for a TLSLDM reloc is ignored. Collapse the |
495 |
- reloc to the STN_UNDEF (0) symbol so that they all match. */ |
496 |
- r_symndx = STN_UNDEF; |
497 |
- break; |
498 |
- |
499 |
- default: |
500 |
- continue; |
501 |
+ if (r_type != R_ALPHA_LITERAL) |
502 |
+ { |
503 |
+ /* We complete everything except LITERAL in the first pass. */ |
504 |
+ if (relax_pass != 0) |
505 |
+ continue; |
506 |
+ if (r_type == R_ALPHA_TLSLDM) |
507 |
+ { |
508 |
+ /* The symbol for a TLSLDM reloc is ignored. Collapse the |
509 |
+ reloc to the STN_UNDEF (0) symbol so that they all match. */ |
510 |
+ r_symndx = STN_UNDEF; |
511 |
+ } |
512 |
+ else if (r_type != R_ALPHA_GOTDTPREL |
513 |
+ && r_type != R_ALPHA_GOTTPREL |
514 |
+ && r_type != R_ALPHA_TLSGD) |
515 |
+ continue; |
516 |
} |
517 |
|
518 |
/* Get the value of the symbol referred to by the reloc. */ |
519 |
|
520 |
2014-04-21 Richard Henderson <rth@××××××.com> |
521 |
|
522 |
* emultempl/alphaelf.em (alpha_after_parse): Enable 2 relax passes. |
523 |
|
524 |
diff --git a/ld/emultempl/alphaelf.em b/ld/emultempl/alphaelf.em |
525 |
index 091ef66..a36fc7d 100644 |
526 |
--- a/ld/emultempl/alphaelf.em |
527 |
+++ b/ld/emultempl/alphaelf.em |
528 |
@@ -72,6 +72,7 @@ alpha_after_open (void) |
529 |
static void |
530 |
alpha_after_parse (void) |
531 |
{ |
532 |
+ link_info.relax_pass = 2; |
533 |
if (limit_32bit && !link_info.shared && !link_info.relocatable) |
534 |
lang_section_start (".interp", |
535 |
exp_binop ('+', |
536 |
-- |
537 |
2.0.0 |