summaryrefslogtreecommitdiff
path: root/tools/toolchain-patches/binutils-2.20.1-ld-thumb-interwork-long-call.diff
diff options
context:
space:
mode:
authorSolomon Peachy <pizza@shaftnet.org>2020-04-04 15:42:35 -0400
committerSolomon Peachy <pizza@shaftnet.org>2020-04-04 21:56:30 +0200
commit00c0d2012f2e8d977bad5487ab6f3b8ca46c8572 (patch)
tree5265d39f5954a356abeee1e7368bbd85e3b6c9f6 /tools/toolchain-patches/binutils-2.20.1-ld-thumb-interwork-long-call.diff
parent74ab8d14904041023bd0b66e05b6560110fc71be (diff)
downloadrockbox-00c0d2012f2e8d977bad5487ab6f3b8ca46c8572.tar.gz
rockbox-00c0d2012f2e8d977bad5487ab6f3b8ca46c8572.zip
rockboxdev: Store toolchain patches in-tree, instead of downloading them
This frees us from having to keep the web site in sync. Note that only currently-referenced patches were kept. Change-Id: I50da1b75baeac214cf142c8b76a05a8c56b4c1d4
Diffstat (limited to 'tools/toolchain-patches/binutils-2.20.1-ld-thumb-interwork-long-call.diff')
-rw-r--r--tools/toolchain-patches/binutils-2.20.1-ld-thumb-interwork-long-call.diff569
1 files changed, 569 insertions, 0 deletions
diff --git a/tools/toolchain-patches/binutils-2.20.1-ld-thumb-interwork-long-call.diff b/tools/toolchain-patches/binutils-2.20.1-ld-thumb-interwork-long-call.diff
new file mode 100644
index 0000000000..5eb5debfbf
--- /dev/null
+++ b/tools/toolchain-patches/binutils-2.20.1-ld-thumb-interwork-long-call.diff
@@ -0,0 +1,569 @@
1http://sourceware.org/ml/binutils/2010-02/msg00460.html
2
3Drop this patch when binutils 2.21 is out
4diff -ur binutils-2.20.1.orig/bfd/elf32-arm.c binutils-2.20.1/bfd/elf32-arm.c
5--- binutils-2.20.1.orig/bfd/elf32-arm.c 2010-06-11 18:48:06.000000000 +0200
6+++ binutils-2.20.1/bfd/elf32-arm.c 2010-06-11 18:51:00.000000000 +0200
7@@ -2401,6 +2401,7 @@
8 unsigned long orig_insn;
9 char *stub_name;
10 enum elf32_arm_stub_type stub_type;
11+ int st_type;
12 };
13
14 /* A table of relocs applied to branches which might trigger Cortex-A8
15@@ -2647,6 +2648,9 @@
16 asection *stub_sec;
17 } *stub_group;
18
19+ /* Number of elements in stub_group. */
20+ int top_id;
21+
22 /* Assorted information used by elf32_arm_size_stubs. */
23 unsigned int bfd_count;
24 int top_index;
25@@ -2933,6 +2937,7 @@
26 ret->add_stub_section = NULL;
27 ret->layout_sections_again = NULL;
28 ret->stub_group = NULL;
29+ ret->top_id = 0;
30 ret->bfd_count = 0;
31 ret->top_index = 0;
32 ret->input_list = NULL;
33@@ -3033,7 +3038,7 @@
34 arm_type_of_stub (struct bfd_link_info *info,
35 asection *input_sec,
36 const Elf_Internal_Rela *rel,
37- unsigned char st_type,
38+ int *actual_st_type,
39 struct elf32_arm_link_hash_entry *hash,
40 bfd_vma destination,
41 asection *sym_sec,
42@@ -3048,6 +3053,7 @@
43 int thumb_only;
44 enum elf32_arm_stub_type stub_type = arm_stub_none;
45 int use_plt = 0;
46+ int st_type = *actual_st_type;
47
48 /* We don't know the actual type of destination in case it is of
49 type STT_SECTION: give up. */
50@@ -3065,14 +3071,15 @@
51 + input_sec->output_section->vma
52 + rel->r_offset);
53
54- branch_offset = (bfd_signed_vma)(destination - location);
55-
56 r_type = ELF32_R_TYPE (rel->r_info);
57
58 /* Keep a simpler condition, for the sake of clarity. */
59- if (globals->splt != NULL && hash != NULL && hash->root.plt.offset != (bfd_vma) -1)
60+ if (globals->splt != NULL
61+ && hash != NULL
62+ && hash->root.plt.offset != (bfd_vma) -1)
63 {
64 use_plt = 1;
65+
66 /* Note when dealing with PLT entries: the main PLT stub is in
67 ARM mode, so if the branch is in Thumb mode, another
68 Thumb->ARM stub will be inserted later just before the ARM
69@@ -3081,8 +3088,15 @@
70 Thumb->Arm one and branch directly to the ARM PLT entry
71 because it avoids spreading offset corrections in several
72 places. */
73+
74+ destination = (globals->splt->output_section->vma
75+ + globals->splt->output_offset
76+ + hash->root.plt.offset);
77+ st_type = STT_FUNC;
78 }
79
80+ branch_offset = (bfd_signed_vma)(destination - location);
81+
82 if (r_type == R_ARM_THM_CALL || r_type == R_ARM_THM_JUMP24)
83 {
84 /* Handle cases where:
85@@ -3176,7 +3190,9 @@
86 }
87 }
88 }
89- else if (r_type == R_ARM_CALL || r_type == R_ARM_JUMP24 || r_type == R_ARM_PLT32)
90+ else if (r_type == R_ARM_CALL
91+ || r_type == R_ARM_JUMP24
92+ || r_type == R_ARM_PLT32)
93 {
94 if (st_type == STT_ARM_TFUNC)
95 {
96@@ -3231,6 +3247,12 @@
97 }
98 }
99
100+ /* If a stub is needed, record the actual destination type. */
101+ if (stub_type != arm_stub_none)
102+ {
103+ *actual_st_type = st_type;
104+ }
105+
106 return stub_type;
107 }
108
109@@ -3240,31 +3262,35 @@
110 elf32_arm_stub_name (const asection *input_section,
111 const asection *sym_sec,
112 const struct elf32_arm_link_hash_entry *hash,
113- const Elf_Internal_Rela *rel)
114+ const Elf_Internal_Rela *rel,
115+ enum elf32_arm_stub_type stub_type)
116+
117 {
118 char *stub_name;
119 bfd_size_type len;
120
121 if (hash)
122 {
123- len = 8 + 1 + strlen (hash->root.root.root.string) + 1 + 8 + 1;
124+ len = 8 + 1 + strlen (hash->root.root.root.string) + 1 + 8 + 1 + 2 + 1;
125 stub_name = bfd_malloc (len);
126 if (stub_name != NULL)
127- sprintf (stub_name, "%08x_%s+%x",
128+ sprintf (stub_name, "%08x_%s+%x_%d",
129 input_section->id & 0xffffffff,
130 hash->root.root.root.string,
131- (int) rel->r_addend & 0xffffffff);
132+ (int) rel->r_addend & 0xffffffff,
133+ (int) stub_type);
134 }
135 else
136 {
137- len = 8 + 1 + 8 + 1 + 8 + 1 + 8 + 1;
138+ len = 8 + 1 + 8 + 1 + 8 + 1 + 8 + 1 + 2 + 1;
139 stub_name = bfd_malloc (len);
140 if (stub_name != NULL)
141- sprintf (stub_name, "%08x_%x:%x+%x",
142+ sprintf (stub_name, "%08x_%x:%x+%x_%d",
143 input_section->id & 0xffffffff,
144 sym_sec->id & 0xffffffff,
145 (int) ELF32_R_SYM (rel->r_info) & 0xffffffff,
146- (int) rel->r_addend & 0xffffffff);
147+ (int) rel->r_addend & 0xffffffff,
148+ (int) stub_type);
149 }
150
151 return stub_name;
152@@ -3278,7 +3304,8 @@
153 const asection *sym_sec,
154 struct elf_link_hash_entry *hash,
155 const Elf_Internal_Rela *rel,
156- struct elf32_arm_link_hash_table *htab)
157+ struct elf32_arm_link_hash_table *htab,
158+ enum elf32_arm_stub_type stub_type)
159 {
160 struct elf32_arm_stub_hash_entry *stub_entry;
161 struct elf32_arm_link_hash_entry *h = (struct elf32_arm_link_hash_entry *) hash;
162@@ -3296,7 +3323,8 @@
163
164 if (h != NULL && h->stub_cache != NULL
165 && h->stub_cache->h == h
166- && h->stub_cache->id_sec == id_sec)
167+ && h->stub_cache->id_sec == id_sec
168+ && h->stub_cache->stub_type == stub_type)
169 {
170 stub_entry = h->stub_cache;
171 }
172@@ -3304,7 +3332,7 @@
173 {
174 char *stub_name;
175
176- stub_name = elf32_arm_stub_name (id_sec, sym_sec, h, rel);
177+ stub_name = elf32_arm_stub_name (id_sec, sym_sec, h, rel, stub_type);
178 if (stub_name == NULL)
179 return NULL;
180
181@@ -3464,7 +3492,7 @@
182 /* We have to do the a8 fixes last, as they are less aligned than
183 the other veneers. */
184 return TRUE;
185-
186+
187 /* Make a note of the offset within the stubs for this entry. */
188 stub_entry->stub_offset = stub_sec->size;
189 loc = stub_sec->contents + stub_entry->stub_offset;
190@@ -3499,17 +3527,17 @@
191 BFD_ASSERT ((data & 0xff00) == 0xd000);
192 data |= ((stub_entry->orig_insn >> 22) & 0xf) << 8;
193 }
194- put_thumb_insn (globals, stub_bfd, data, loc + size);
195+ bfd_put_16 (stub_bfd, data, loc + size);
196 size += 2;
197 }
198 break;
199
200 case THUMB32_TYPE:
201- put_thumb_insn (globals, stub_bfd,
202- (template_sequence[i].data >> 16) & 0xffff,
203- loc + size);
204- put_thumb_insn (globals, stub_bfd, template_sequence[i].data & 0xffff,
205- loc + size + 2);
206+ bfd_put_16 (stub_bfd,
207+ (template_sequence[i].data >> 16) & 0xffff,
208+ loc + size);
209+ bfd_put_16 (stub_bfd, template_sequence[i].data & 0xffff,
210+ loc + size + 2);
211 if (template_sequence[i].r_type != R_ARM_NONE)
212 {
213 stub_reloc_idx[nrelocs] = i;
214@@ -3519,8 +3547,8 @@
215 break;
216
217 case ARM_TYPE:
218- put_arm_insn (globals, stub_bfd, template_sequence[i].data,
219- loc + size);
220+ bfd_put_32 (stub_bfd, template_sequence[i].data,
221+ loc + size);
222 /* Handle cases where the target is encoded within the
223 instruction. */
224 if (template_sequence[i].r_type == R_ARM_JUMP24)
225@@ -3599,11 +3627,23 @@
226 }
227 else
228 {
229- _bfd_final_link_relocate (elf32_arm_howto_from_type
230- (template_sequence[stub_reloc_idx[i]].r_type), stub_bfd, stub_sec,
231- stub_sec->contents, stub_entry->stub_offset + stub_reloc_offset[i],
232- sym_value + stub_entry->target_addend,
233- template_sequence[stub_reloc_idx[i]].reloc_addend);
234+ Elf_Internal_Rela rel;
235+ bfd_boolean unresolved_reloc;
236+ char *error_message;
237+ bfd_vma points_to = sym_value + stub_entry->target_addend
238+ + template_sequence[stub_reloc_idx[i]].reloc_addend;
239+
240+ rel.r_offset = stub_entry->stub_offset + stub_reloc_offset[i];
241+ rel.r_info = ELF32_R_INFO (0,
242+ template_sequence[stub_reloc_idx[i]].r_type);
243+ rel.r_addend = 0;
244+
245+ elf32_arm_final_link_relocate (elf32_arm_howto_from_type
246+ (template_sequence[stub_reloc_idx[i]].r_type),
247+ stub_bfd, info->output_bfd, stub_sec, stub_sec->contents, &rel,
248+ points_to, info, stub_entry->target_section, "", stub_entry->st_type,
249+ (struct elf_link_hash_entry *) stub_entry->h, &unresolved_reloc,
250+ &error_message);
251 }
252
253 return TRUE;
254@@ -3728,6 +3768,7 @@
255 htab->stub_group = bfd_zmalloc (amt);
256 if (htab->stub_group == NULL)
257 return -1;
258+ htab->top_id = top_id;
259
260 /* We can't use output_bfd->section_count here to find the top output
261 section index as some sections may have been removed, and
262@@ -4009,7 +4050,7 @@
263 }
264
265 is_32bit_branch = is_b || is_bl || is_blx || is_bcc;
266-
267+
268 if (((base_vma + i) & 0xfff) == 0xffe
269 && insn_32bit
270 && is_32bit_branch
271@@ -4178,6 +4219,8 @@
272 a8_fixes[num_a8_fixes].orig_insn = insn;
273 a8_fixes[num_a8_fixes].stub_name = stub_name;
274 a8_fixes[num_a8_fixes].stub_type = stub_type;
275+ a8_fixes[num_a8_fixes].st_type =
276+ is_blx ? STT_FUNC : STT_ARM_TFUNC;
277
278 num_a8_fixes++;
279 }
280@@ -4193,11 +4236,11 @@
281 if (elf_section_data (section)->this_hdr.contents == NULL)
282 free (contents);
283 }
284-
285+
286 *a8_fixes_p = a8_fixes;
287 *num_a8_fixes_p = num_a8_fixes;
288 *a8_fix_table_size_p = a8_fix_table_size;
289-
290+
291 return FALSE;
292 }
293
294@@ -4345,7 +4388,7 @@
295 const char *sym_name;
296 char *stub_name;
297 const asection *id_sec;
298- unsigned char st_type;
299+ int st_type;
300 bfd_boolean created_stub = FALSE;
301
302 r_type = ELF32_R_TYPE (irela->r_info);
303@@ -4403,7 +4446,7 @@
304 /* This is an undefined symbol. It can never
305 be resolved. */
306 continue;
307-
308+
309 if (ELF_ST_TYPE (sym->st_info) != STT_SECTION)
310 sym_value = sym->st_value;
311 destination = (sym_value + irela->r_addend
312@@ -4493,7 +4536,7 @@
313 {
314 /* Determine what (if any) linker stub is needed. */
315 stub_type = arm_type_of_stub (info, section, irela,
316- st_type, hash,
317+ &st_type, hash,
318 destination, sym_sec,
319 input_bfd, sym_name);
320 if (stub_type == arm_stub_none)
321@@ -4504,7 +4547,7 @@
322
323 /* Get the name of this stub. */
324 stub_name = elf32_arm_stub_name (id_sec, sym_sec, hash,
325- irela);
326+ irela, stub_type);
327 if (!stub_name)
328 goto error_ret_free_internal;
329
330@@ -4703,7 +4746,7 @@
331 stub_entry->target_value = a8_fixes[i].offset;
332 stub_entry->target_addend = a8_fixes[i].addend;
333 stub_entry->orig_insn = a8_fixes[i].orig_insn;
334- stub_entry->st_type = STT_ARM_TFUNC;
335+ stub_entry->st_type = a8_fixes[i].st_type;
336
337 size = find_stub_size_and_template (a8_fixes[i].stub_type,
338 &template_sequence,
339@@ -6866,6 +6909,7 @@
340 ".tls_vars") == 0)
341 && ((r_type != R_ARM_REL32 && r_type != R_ARM_REL32_NOI)
342 || !SYMBOL_CALLS_LOCAL (info, h))
343+ && (!strstr (input_section->name, STUB_SUFFIX))
344 && (h == NULL
345 || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
346 || h->root.type != bfd_link_hash_undefweak)
347@@ -6990,7 +7034,6 @@
348 case R_ARM_PC24: /* Arm B/BL instruction. */
349 case R_ARM_PLT32:
350 {
351- bfd_signed_vma branch_offset;
352 struct elf32_arm_stub_hash_entry *stub_entry = NULL;
353
354 if (r_type == R_ARM_XPC25)
355@@ -7026,45 +7069,46 @@
356 || r_type == R_ARM_JUMP24
357 || r_type == R_ARM_PLT32)
358 {
359- bfd_vma from;
360-
361- /* If the call goes through a PLT entry, make sure to
362- check distance to the right destination address. */
363- if (h != NULL && splt != NULL && h->plt.offset != (bfd_vma) -1)
364- {
365- value = (splt->output_section->vma
366- + splt->output_offset
367- + h->plt.offset);
368- *unresolved_reloc_p = FALSE;
369- /* The PLT entry is in ARM mode, regardless of the
370- target function. */
371- sym_flags = STT_FUNC;
372- }
373+ enum elf32_arm_stub_type stub_type = arm_stub_none;
374+ struct elf32_arm_link_hash_entry *hash;
375
376- from = (input_section->output_section->vma
377- + input_section->output_offset
378- + rel->r_offset);
379- branch_offset = (bfd_signed_vma)(value - from);
380-
381- if (branch_offset > ARM_MAX_FWD_BRANCH_OFFSET
382- || branch_offset < ARM_MAX_BWD_BRANCH_OFFSET
383- || ((sym_flags == STT_ARM_TFUNC)
384- && (((r_type == R_ARM_CALL) && !globals->use_blx)
385- || (r_type == R_ARM_JUMP24)
386- || (r_type == R_ARM_PLT32) ))
387- )
388+ hash = (struct elf32_arm_link_hash_entry *) h;
389+ stub_type = arm_type_of_stub (info, input_section, rel,
390+ &sym_flags, hash,
391+ value, sym_sec,
392+ input_bfd, sym_name);
393+
394+ if (stub_type != arm_stub_none)
395 {
396 /* The target is out of reach, so redirect the
397 branch to the local stub for this function. */
398
399 stub_entry = elf32_arm_get_stub_entry (input_section,
400 sym_sec, h,
401- rel, globals);
402+ rel, globals,
403+ stub_type);
404 if (stub_entry != NULL)
405 value = (stub_entry->stub_offset
406 + stub_entry->stub_sec->output_offset
407 + stub_entry->stub_sec->output_section->vma);
408 }
409+ else
410+ {
411+ /* If the call goes through a PLT entry, make sure to
412+ check distance to the right destination address. */
413+ if (h != NULL
414+ && splt != NULL
415+ && h->plt.offset != (bfd_vma) -1)
416+ {
417+ value = (splt->output_section->vma
418+ + splt->output_offset
419+ + h->plt.offset);
420+ *unresolved_reloc_p = FALSE;
421+ /* The PLT entry is in ARM mode, regardless of the
422+ target function. */
423+ sym_flags = STT_FUNC;
424+ }
425+ }
426 }
427
428 /* The ARM ELF ABI says that this reloc is computed as: S - P + A
429@@ -7444,58 +7488,29 @@
430 }
431 }
432
433- /* Handle calls via the PLT. */
434- if (h != NULL && splt != NULL && h->plt.offset != (bfd_vma) -1)
435- {
436- value = (splt->output_section->vma
437- + splt->output_offset
438- + h->plt.offset);
439- if (globals->use_blx && r_type == R_ARM_THM_CALL)
440- {
441- /* If the Thumb BLX instruction is available, convert the
442- BL to a BLX instruction to call the ARM-mode PLT entry. */
443- lower_insn = (lower_insn & ~0x1000) | 0x0800;
444- sym_flags = STT_FUNC;
445- }
446- else
447- {
448- /* Target the Thumb stub before the ARM PLT entry. */
449- value -= PLT_THUMB_STUB_SIZE;
450- sym_flags = STT_ARM_TFUNC;
451- }
452- *unresolved_reloc_p = FALSE;
453- }
454-
455+ enum elf32_arm_stub_type stub_type = arm_stub_none;
456 if (r_type == R_ARM_THM_CALL || r_type == R_ARM_THM_JUMP24)
457 {
458 /* Check if a stub has to be inserted because the destination
459 is too far. */
460- bfd_vma from;
461- bfd_signed_vma branch_offset;
462- struct elf32_arm_stub_hash_entry *stub_entry = NULL;
463-
464- from = (input_section->output_section->vma
465- + input_section->output_offset
466- + rel->r_offset);
467- branch_offset = (bfd_signed_vma)(value - from);
468-
469- if ((!thumb2
470- && (branch_offset > THM_MAX_FWD_BRANCH_OFFSET
471- || (branch_offset < THM_MAX_BWD_BRANCH_OFFSET)))
472- ||
473- (thumb2
474- && (branch_offset > THM2_MAX_FWD_BRANCH_OFFSET
475- || (branch_offset < THM2_MAX_BWD_BRANCH_OFFSET)))
476- || ((sym_flags != STT_ARM_TFUNC)
477- && (((r_type == R_ARM_THM_CALL) && !globals->use_blx)
478- || r_type == R_ARM_THM_JUMP24)))
479+ struct elf32_arm_stub_hash_entry *stub_entry;
480+ struct elf32_arm_link_hash_entry *hash;
481+
482+ hash = (struct elf32_arm_link_hash_entry *) h;
483+
484+ stub_type = arm_type_of_stub (info, input_section, rel,
485+ &sym_flags, hash, value, sym_sec,
486+ input_bfd, sym_name);
487+
488+ if (stub_type != arm_stub_none)
489 {
490 /* The target is out of reach or we are changing modes, so
491 redirect the branch to the local stub for this
492 function. */
493 stub_entry = elf32_arm_get_stub_entry (input_section,
494 sym_sec, h,
495- rel, globals);
496+ rel, globals,
497+ stub_type);
498 if (stub_entry != NULL)
499 value = (stub_entry->stub_offset
500 + stub_entry->stub_sec->output_offset
501@@ -7512,6 +7527,33 @@
502 }
503 }
504
505+ /* Handle calls via the PLT. */
506+ if (stub_type == arm_stub_none
507+ && h != NULL
508+ && splt != NULL
509+ && h->plt.offset != (bfd_vma) -1)
510+ {
511+ value = (splt->output_section->vma
512+ + splt->output_offset
513+ + h->plt.offset);
514+
515+ if (globals->use_blx && r_type == R_ARM_THM_CALL)
516+ {
517+ /* If the Thumb BLX instruction is available, convert
518+ the BL to a BLX instruction to call the ARM-mode
519+ PLT entry. */
520+ lower_insn = (lower_insn & ~0x1000) | 0x0800;
521+ sym_flags = STT_FUNC;
522+ }
523+ else
524+ {
525+ /* Target the Thumb stub before the ARM PLT entry. */
526+ value -= PLT_THUMB_STUB_SIZE;
527+ sym_flags = STT_ARM_TFUNC;
528+ }
529+ *unresolved_reloc_p = FALSE;
530+ }
531+
532 relocation = value + signed_addend;
533
534 relocation -= (input_section->output_section->vma
535@@ -9298,11 +9340,26 @@
536 elf32_arm_final_link (bfd *abfd, struct bfd_link_info *info)
537 {
538 struct elf32_arm_link_hash_table *globals = elf32_arm_hash_table (info);
539+ asection *sec, *osec;
540
541 /* Invoke the regular ELF backend linker to do all the work. */
542 if (!bfd_elf_final_link (abfd, info))
543 return FALSE;
544
545+ /* Process stub sections (eg BE8 encoding, ...). */
546+ struct elf32_arm_link_hash_table *htab = elf32_arm_hash_table (info);
547+ int i;
548+ for(i=0; i<htab->top_id; i++) {
549+ sec = htab->stub_group[i].stub_sec;
550+ if (sec) {
551+ osec = sec->output_section;
552+ elf32_arm_write_section (abfd, info, sec, sec->contents);
553+ if (! bfd_set_section_contents (abfd, osec, sec->contents,
554+ sec->output_offset, sec->size))
555+ return FALSE;
556+ }
557+ }
558+
559 /* Write out any glue sections now that we have created all the
560 stubs. */
561 if (globals->bfd_of_glue_owner != NULL)
562@@ -12875,6 +12932,7 @@
563 sym.st_other = 0;
564 sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_NOTYPE);
565 sym.st_shndx = osi->sec_shndx;
566+ elf32_arm_section_map_add (osi->sec, names[type][1], offset);
567 return osi->func (osi->finfo, names[type], &sym, osi->sec, NULL) == 1;
568 }
569