From 8e868d8e839352168cc8fd7708613e0996a6113d Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Wed, 5 Aug 2009 12:36:14 +0000 Subject: [PATCH] bfd/ * elf32-arm.c (elf32_arm_stub_type): Add arm_stub_a8_veneer_lwm. (arm_build_one_stub): Build a8 veneers as a separate pass. (cortex_a8_erratum_scan): Add prev_num_a8_fixes and stub_changed_p parameters. Use them to check if we create a different a8 fixup than the previous pass. (elf32_arm_size_stubs): Move scope of stub_changed and prev_num_a8_fixes into main loop. (elf32_arm_build_stubs): Build a8 veneers in a second pass. ld/testsuite/ * ld-arm/cortex-a8-far-1.s: New. * ld-arm/cortex-a8-far-2.s: New. * ld-arm/cortex-a8-far.d: New. * ld-arm/arm-elf.exp: Add new test. --- bfd/ChangeLog | 11 ++++++ bfd/elf32-arm.c | 63 +++++++++++++++++++++++++++-------- ld/testsuite/ChangeLog | 7 ++++ ld/testsuite/ld-arm/arm-elf.exp | 4 +++ ld/testsuite/ld-arm/cortex-a8-far-1.s | 8 +++++ ld/testsuite/ld-arm/cortex-a8-far-2.s | 20 +++++++++++ ld/testsuite/ld-arm/cortex-a8-far.d | 40 ++++++++++++++++++++++ 7 files changed, 140 insertions(+), 13 deletions(-) create mode 100644 ld/testsuite/ld-arm/cortex-a8-far-1.s create mode 100644 ld/testsuite/ld-arm/cortex-a8-far-2.s create mode 100644 ld/testsuite/ld-arm/cortex-a8-far.d diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 50866fc313..577918ca0e 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,14 @@ +2009-08-05 Nathan Sidwell + + * elf32-arm.c (elf32_arm_stub_type): Add arm_stub_a8_veneer_lwm. + (arm_build_one_stub): Build a8 veneers as a separate pass. + (cortex_a8_erratum_scan): Add prev_num_a8_fixes and stub_changed_p + parameters. Use them to check if we create a different a8 fixup + than the previous pass. + (elf32_arm_size_stubs): Move scope of stub_changed and + prev_num_a8_fixes into main loop. + (elf32_arm_build_stubs): Build a8 veneers in a second pass. + 2009-08-04 Alan Modra * elf32-ppc.c (ppc_elf_relax_section): Correct conditions under diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c index 1e23626518..5aba3f360a 100644 --- a/bfd/elf32-arm.c +++ b/bfd/elf32-arm.c @@ -2228,6 +2228,8 @@ static const insn_sequence elf32_arm_stub_a8_veneer_blx[] = enum elf32_arm_stub_type { arm_stub_none, DEF_STUBS + /* Note the first a8_veneer type */ + arm_stub_a8_veneer_lwm = arm_stub_a8_veneer_b_cond }; #undef DEF_STUB @@ -3437,6 +3439,12 @@ arm_build_one_stub (struct bfd_hash_entry *gen_entry, htab = elf32_arm_hash_table (info); stub_sec = stub_entry->stub_sec; + if ((htab->fix_cortex_a8 < 0) + != (stub_entry->stub_type >= arm_stub_a8_veneer_lwm)) + /* We have to do the a8 fixes last, as they are less aligned than + the other veneers. */ + return TRUE; + /* Make a note of the offset within the stubs for this entry. */ stub_entry->stub_offset = stub_sec->size; loc = stub_sec->contents + stub_entry->stub_offset; @@ -3893,7 +3901,9 @@ cortex_a8_erratum_scan (bfd *input_bfd, unsigned int *num_a8_fixes_p, unsigned int *a8_fix_table_size_p, struct a8_erratum_reloc *a8_relocs, - unsigned int num_a8_relocs) + unsigned int num_a8_relocs, + unsigned prev_num_a8_fixes, + bfd_boolean *stub_changed_p) { asection *section; struct elf32_arm_link_hash_table *htab = elf32_arm_hash_table (info); @@ -4105,7 +4115,7 @@ cortex_a8_erratum_scan (bfd *input_bfd, if (((base_vma + i) & ~0xfff) == (target & ~0xfff)) { - char *stub_name; + char *stub_name = NULL; if (num_a8_fixes == a8_fix_table_size) { @@ -4115,9 +4125,28 @@ cortex_a8_erratum_scan (bfd *input_bfd, * a8_fix_table_size); } - stub_name = bfd_malloc (8 + 1 + 8 + 1); - if (stub_name != NULL) - sprintf (stub_name, "%x:%x", section->id, i); + if (num_a8_fixes < prev_num_a8_fixes) + { + /* If we're doing a subsequent scan, + check if we've found the same fix as + before, and try and reuse the stub + name. */ + stub_name = a8_fixes[num_a8_fixes].stub_name; + if ((a8_fixes[num_a8_fixes].section != section) + || (a8_fixes[num_a8_fixes].offset != i)) + { + free (stub_name); + stub_name = NULL; + *stub_changed_p = TRUE; + } + } + + if (!stub_name) + { + stub_name = bfd_malloc (8 + 1 + 8 + 1); + if (stub_name != NULL) + sprintf (stub_name, "%x:%x", section->id, i); + } a8_fixes[num_a8_fixes].input_bfd = input_bfd; a8_fixes[num_a8_fixes].section = section; @@ -4165,10 +4194,9 @@ elf32_arm_size_stubs (bfd *output_bfd, { bfd_size_type stub_group_size; bfd_boolean stubs_always_after_branch; - bfd_boolean stub_changed = 0; struct elf32_arm_link_hash_table *htab = elf32_arm_hash_table (info); struct a8_erratum_fix *a8_fixes = NULL; - unsigned int num_a8_fixes = 0, prev_num_a8_fixes = 0, a8_fix_table_size = 10; + unsigned int num_a8_fixes = 0, a8_fix_table_size = 10; struct a8_erratum_reloc *a8_relocs = NULL; unsigned int num_a8_relocs = 0, a8_reloc_table_size = 10, i; @@ -4223,9 +4251,10 @@ elf32_arm_size_stubs (bfd *output_bfd, bfd *input_bfd; unsigned int bfd_indx; asection *stub_sec; + bfd_boolean stub_changed = FALSE; + unsigned prev_num_a8_fixes = num_a8_fixes; num_a8_fixes = 0; - for (input_bfd = info->input_bfds, bfd_indx = 0; input_bfd != NULL; input_bfd = input_bfd->link_next, bfd_indx++) @@ -4452,6 +4481,7 @@ elf32_arm_size_stubs (bfd *output_bfd, { /* The proper stub has already been created. */ free (stub_name); + stub_entry->target_value = sym_value; break; } @@ -4548,18 +4578,21 @@ elf32_arm_size_stubs (bfd *output_bfd, if (htab->fix_cortex_a8) { /* Sort relocs which might apply to Cortex-A8 erratum. */ - qsort (a8_relocs, num_a8_relocs, sizeof (struct a8_erratum_reloc), + qsort (a8_relocs, num_a8_relocs, + sizeof (struct a8_erratum_reloc), &a8_reloc_compare); /* Scan for branches which might trigger Cortex-A8 erratum. */ if (cortex_a8_erratum_scan (input_bfd, info, &a8_fixes, &num_a8_fixes, &a8_fix_table_size, - a8_relocs, num_a8_relocs) != 0) + a8_relocs, num_a8_relocs, + prev_num_a8_fixes, &stub_changed) + != 0) goto error_ret_free_local; } } - if (htab->fix_cortex_a8 && num_a8_fixes != prev_num_a8_fixes) + if (prev_num_a8_fixes != num_a8_fixes) stub_changed = TRUE; if (!stub_changed) @@ -4598,8 +4631,6 @@ elf32_arm_size_stubs (bfd *output_bfd, /* Ask the linker to do its stuff. */ (*htab->layout_sections_again) (); - stub_changed = FALSE; - prev_num_a8_fixes = num_a8_fixes; } /* Add stubs for Cortex-A8 erratum fixes now. */ @@ -4696,6 +4727,12 @@ elf32_arm_build_stubs (struct bfd_link_info *info) /* Build the stubs as directed by the stub hash table. */ table = &htab->stub_hash_table; bfd_hash_traverse (table, arm_build_one_stub, info); + if (htab->fix_cortex_a8) + { + /* Place the cortex a8 stubs last. */ + htab->fix_cortex_a8 = -1; + bfd_hash_traverse (table, arm_build_one_stub, info); + } return TRUE; } diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog index 60ee1ec8dc..d63c14b47f 100644 --- a/ld/testsuite/ChangeLog +++ b/ld/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2009-08-05 Nathan Sidwell + + * ld-arm/cortex-a8-far-1.s: New. + * ld-arm/cortex-a8-far-2.s: New. + * ld-arm/cortex-a8-far.d: New. + * ld-arm/arm-elf.exp: Add new test. + 2009-08-02 H.J. Lu PR ld/6443 diff --git a/ld/testsuite/ld-arm/arm-elf.exp b/ld/testsuite/ld-arm/arm-elf.exp index de3628eb12..941ef50c69 100644 --- a/ld/testsuite/ld-arm/arm-elf.exp +++ b/ld/testsuite/ld-arm/arm-elf.exp @@ -205,6 +205,10 @@ set armelftests { "-EL -Ttext=0x8f00 --fix-cortex-a8" "-EL" {cortex-a8-thumb-target.s cortex-a8-fix-blx-rel.s} {{objdump -dr cortex-a8-fix-blx-rel-thumb.d}} "cortex-a8-fix-blx-rel-thumb"} + {"Cortex-A8 erratum fix, relocate bl.w and far call" + "-EL -Ttext=0x00 --fix-cortex-a8 --defsym far_fn1=0x80000000 --defsym far_fn2=0x80000004 --defsym far_fn=0x7fff0000 --defsym _start=0" "-EL" {cortex-a8-far-1.s cortex-a8-far-2.s} + {{objdump -dr cortex-a8-far.d}} + "cortex-a8-far"} {"Unwinding and -gc-sections" "-gc-sections" "" {gc-unwind.s} {{objdump -sj.data gc-unwind.d}} "gc-unwind"} diff --git a/ld/testsuite/ld-arm/cortex-a8-far-1.s b/ld/testsuite/ld-arm/cortex-a8-far-1.s new file mode 100644 index 0000000000..09d3583a93 --- /dev/null +++ b/ld/testsuite/ld-arm/cortex-a8-far-1.s @@ -0,0 +1,8 @@ + .syntax unified + .thumb + .globl two +two: + bl far_fn + .rept 0x200000 + .long 0 + .endr diff --git a/ld/testsuite/ld-arm/cortex-a8-far-2.s b/ld/testsuite/ld-arm/cortex-a8-far-2.s new file mode 100644 index 0000000000..22fd40f021 --- /dev/null +++ b/ld/testsuite/ld-arm/cortex-a8-far-2.s @@ -0,0 +1,20 @@ + .syntax unified + .thumb +three: + bl far_fn1 + bl far_fn2 + .rept 1016 + .long 0 + .endr + nop +label1: + eor.w r0, r1, r2 + beq.w label1 + + eor.w r0, r1, r2 + + eor.w r0, r1, r2 + b.w label1 + + eor.w r0, r1, r2 + eor.w r0, r1, r2 diff --git a/ld/testsuite/ld-arm/cortex-a8-far.d b/ld/testsuite/ld-arm/cortex-a8-far.d new file mode 100644 index 0000000000..3d9059d345 --- /dev/null +++ b/ld/testsuite/ld-arm/cortex-a8-far.d @@ -0,0 +1,40 @@ + +.*: file format .* + + +Disassembly of section \.text: + +00000000 : + 0: f000 c802 blx 800008 <__far_fn_from_thumb> + ... +#... +00800008 <__far_fn_from_thumb>: + 800008: e51ff004 ldr pc, \[pc, #-4\] ; 80000c <__far_fn_from_thumb\+0x4> + 80000c: 7fff0000 .word 0x7fff0000 + +00800010 : + 800010: f001 e806 blx 801020 <__far_fn1_from_thumb> + 800014: f001 e800 blx 801018 <__far_fn2_from_thumb> + ... + 800ff8: bf00 nop + +00800ffa : + 800ffa: ea81 0002 eor.w r0, r1, r2 + 800ffe: f000 b813 b.w 801028 <__far_fn1_from_thumb\+0x8> + 801002: ea81 0002 eor.w r0, r1, r2 + 801006: ea81 0002 eor.w r0, r1, r2 + 80100a: f7ff bff6 b.w 800ffa + 80100e: ea81 0002 eor.w r0, r1, r2 + 801012: ea81 0002 eor.w r0, r1, r2 + ... + +00801018 <__far_fn2_from_thumb>: + 801018: e51ff004 ldr pc, \[pc, #-4\] ; 80101c <__far_fn2_from_thumb\+0x4> + 80101c: 80000004 .word 0x80000004 + +00801020 <__far_fn1_from_thumb>: + 801020: e51ff004 ldr pc, \[pc, #-4\] ; 801024 <__far_fn1_from_thumb\+0x4> + 801024: 80000000 .word 0x80000000 + 801028: d001 beq.n 80102e <__far_fn1_from_thumb\+0xe> + 80102a: f7ff bfea b.w 801002 + 80102e: f7ff bfe4 b.w 800ffa -- 2.11.0