diff options
-rw-r--r-- | gold/ChangeLog | 20 | ||||
-rw-r--r-- | gold/arm.cc | 59 | ||||
-rw-r--r-- | gold/options.cc | 3 | ||||
-rw-r--r-- | gold/testsuite/Makefile.am | 27 | ||||
-rw-r--r-- | gold/testsuite/Makefile.in | 33 | ||||
-rw-r--r-- | gold/testsuite/arm_fix_v4bx.s | 15 | ||||
-rwxr-xr-x | gold/testsuite/arm_fix_v4bx.sh | 56 |
7 files changed, 178 insertions, 35 deletions
diff --git a/gold/ChangeLog b/gold/ChangeLog index 34b582f..47bd8a7 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,3 +1,23 @@ +2010-02-26 Doug Kwan <dougkwan@google.com> + + * arm.cc (Target_arm::scan_reloc_for_stub): Move code handling + R_ARM_V4BX to Target_arm::scan_reloc_section_for_stubs. + (Target_arm::scan_reloc_section_for_stubs): Instead of calling + scan_reloc_for_stub, do all processing of R_ARM_V4BX here. + * options.cc (General_options::General_options): Initialize member + fix_v4bx_. + * testsuite/Makefile.am (check_SCRIPTS): Add arm_fix_v4bx.sh + (check_DATA): Add arm_fix_v4bx.stdout, arm_fix_v4bx_interworking.stdout + and rm_no_fix_v4bx.stdout + (arm_fix_v4bx.stdout, arm_fix_v4bx, arm_fix_v4bx.o, + arm_fix_v4bx_interworking.stdout, arm_fix_v4bx_interworking, + arm_no_fix_v4bx.stdout, arm_no_fix_v4bx): New make rules. + (MOSTLYCLEANFILES): Add arm_fix_v4bx, arm_fix_v4bx_interworking + and arm_no_fix_v4bx. + * Makefile.in: Regenerate. + * testsuite/arm_fix_v4bx.s: New file. + * testsuite/arm_fix_v4bx.sh: Ditto. + 2010-02-24 Doug Kwan <dougkwan@google.com> * arm.cc (Target_arm::got_section): Make the .got section the first diff --git a/gold/arm.cc b/gold/arm.cc index 136fed6..dde2d08 100644 --- a/gold/arm.cc +++ b/gold/arm.cc @@ -9880,30 +9880,6 @@ Target_arm<big_endian>::scan_reloc_for_stub( const Arm_relobj<big_endian>* arm_relobj = Arm_relobj<big_endian>::as_arm_relobj(relinfo->object); - if (r_type == elfcpp::R_ARM_V4BX) - { - const uint32_t reg = (addend & 0xf); - if (this->fix_v4bx() == General_options::FIX_V4BX_INTERWORKING - && reg < 0xf) - { - // Try looking up an existing stub from a stub table. - Stub_table<big_endian>* stub_table = - arm_relobj->stub_table(relinfo->data_shndx); - gold_assert(stub_table != NULL); - - if (stub_table->find_arm_v4bx_stub(reg) == NULL) - { - // create a new stub and add it to stub table. - Arm_v4bx_stub* stub = - this->stub_factory().make_arm_v4bx_stub(reg); - gold_assert(stub != NULL); - stub_table->add_arm_v4bx_stub(stub); - } - } - - return; - } - bool target_is_thumb; Symbol_value<32> symval; if (gsym != NULL) @@ -10094,15 +10070,36 @@ Target_arm<big_endian>::scan_reloc_section_for_stubs( continue; } + // Create a v4bx stub if --fix-v4bx-interworking is used. if (r_type == elfcpp::R_ARM_V4BX) { - // Get the BX instruction. - typedef typename elfcpp::Swap<32, big_endian>::Valtype Valtype; - const Valtype* wv = reinterpret_cast<const Valtype*>(view + offset); - elfcpp::Elf_types<32>::Elf_Swxword insn = - elfcpp::Swap<32, big_endian>::readval(wv); - this->scan_reloc_for_stub(relinfo, r_type, NULL, 0, NULL, - insn, NULL); + if (this->fix_v4bx() == General_options::FIX_V4BX_INTERWORKING) + { + // Get the BX instruction. + typedef typename elfcpp::Swap<32, big_endian>::Valtype Valtype; + const Valtype* wv = + reinterpret_cast<const Valtype*>(view + offset); + elfcpp::Elf_types<32>::Elf_Swxword insn = + elfcpp::Swap<32, big_endian>::readval(wv); + const uint32_t reg = (insn & 0xf); + + if (reg < 0xf) + { + // Try looking up an existing stub from a stub table. + Stub_table<big_endian>* stub_table = + arm_object->stub_table(relinfo->data_shndx); + gold_assert(stub_table != NULL); + + if (stub_table->find_arm_v4bx_stub(reg) == NULL) + { + // create a new stub and add it to stub table. + Arm_v4bx_stub* stub = + this->stub_factory().make_arm_v4bx_stub(reg); + gold_assert(stub != NULL); + stub_table->add_arm_v4bx_stub(stub); + } + } + } continue; } diff --git a/gold/options.cc b/gold/options.cc index f377387..c6c8073 100644 --- a/gold/options.cc +++ b/gold/options.cc @@ -830,7 +830,8 @@ General_options::General_options() implicit_incremental_(false), excluded_libs_(), symbols_to_retain_(), - section_starts_() + section_starts_(), + fix_v4bx_(FIX_V4BX_NONE) { // Turn off option registration once construction is complete. gold::options::ready_to_register = false; diff --git a/gold/testsuite/Makefile.am b/gold/testsuite/Makefile.am index eaf5446..c9e2d1c 100644 --- a/gold/testsuite/Makefile.am +++ b/gold/testsuite/Makefile.am @@ -1529,4 +1529,31 @@ thumb2_bl_out_of_range.o: thumb_bl_in_range.s MOSTLYCLEANFILES += arm_bl_in_range arm_bl_out_of_range thumb_bl_in_range \ thumb_bl_out_of_range thumb2_bl_in_range thumb2_bl_out_of_range +check_SCRIPTS += arm_fix_v4bx.sh +check_DATA += arm_fix_v4bx.stdout arm_fix_v4bx_interworking.stdout \ + arm_no_fix_v4bx.stdout + +arm_fix_v4bx.stdout: arm_fix_v4bx + $(TEST_OBJDUMP) -D -j.text $< > $@ + +arm_fix_v4bx: arm_fix_v4bx.o + ../ld-new --fix-v4bx -o $@ $< + +arm_fix_v4bx.o: arm_fix_v4bx.s + $(TEST_AS) -o $@ $< + +arm_fix_v4bx_interworking.stdout: arm_fix_v4bx_interworking + $(TEST_OBJDUMP) -D -j.text $< > $@ + +arm_fix_v4bx_interworking: arm_fix_v4bx.o + ../ld-new --fix-v4bx-interworking -o $@ $< + +arm_no_fix_v4bx.stdout: arm_no_fix_v4bx + $(TEST_OBJDUMP) -D -j.text $< > $@ + +arm_no_fix_v4bx: arm_fix_v4bx.o + ../ld-new -o $@ $< + +MOSTLYCLEANFILES += arm_fix_v4bx arm_fix_v4bx_interworking arm_no_fix_v4bx + endif DEFAULT_TARGET_ARM diff --git a/gold/testsuite/Makefile.in b/gold/testsuite/Makefile.in index bbffd69..10730f3 100644 --- a/gold/testsuite/Makefile.in +++ b/gold/testsuite/Makefile.in @@ -323,20 +323,26 @@ check_PROGRAMS = object_unittest$(EXEEXT) binary_unittest$(EXEEXT) \ @DEFAULT_TARGET_X86_64_TRUE@ split_x86_64_4 split_x86_64_r @DEFAULT_TARGET_ARM_TRUE@am__append_38 = arm_abs_global.sh \ -@DEFAULT_TARGET_ARM_TRUE@ arm_branch_in_range.sh +@DEFAULT_TARGET_ARM_TRUE@ arm_branch_in_range.sh \ +@DEFAULT_TARGET_ARM_TRUE@ arm_fix_v4bx.sh @DEFAULT_TARGET_ARM_TRUE@am__append_39 = arm_abs_global.stdout \ @DEFAULT_TARGET_ARM_TRUE@ arm_bl_in_range.stdout \ @DEFAULT_TARGET_ARM_TRUE@ arm_bl_out_of_range.stdout \ @DEFAULT_TARGET_ARM_TRUE@ thumb_bl_in_range.stdout \ @DEFAULT_TARGET_ARM_TRUE@ thumb_bl_out_of_range.stdout \ @DEFAULT_TARGET_ARM_TRUE@ thumb2_bl_in_range.stdout \ -@DEFAULT_TARGET_ARM_TRUE@ thumb2_bl_out_of_range.stdout +@DEFAULT_TARGET_ARM_TRUE@ thumb2_bl_out_of_range.stdout \ +@DEFAULT_TARGET_ARM_TRUE@ arm_fix_v4bx.stdout \ +@DEFAULT_TARGET_ARM_TRUE@ arm_fix_v4bx_interworking.stdout \ +@DEFAULT_TARGET_ARM_TRUE@ arm_no_fix_v4bx.stdout @DEFAULT_TARGET_ARM_TRUE@am__append_40 = arm_abs_global \ @DEFAULT_TARGET_ARM_TRUE@ arm_bl_in_range arm_bl_out_of_range \ @DEFAULT_TARGET_ARM_TRUE@ thumb_bl_in_range \ @DEFAULT_TARGET_ARM_TRUE@ thumb_bl_out_of_range \ @DEFAULT_TARGET_ARM_TRUE@ thumb2_bl_in_range \ -@DEFAULT_TARGET_ARM_TRUE@ thumb2_bl_out_of_range +@DEFAULT_TARGET_ARM_TRUE@ thumb2_bl_out_of_range arm_fix_v4bx \ +@DEFAULT_TARGET_ARM_TRUE@ arm_fix_v4bx_interworking \ +@DEFAULT_TARGET_ARM_TRUE@ arm_no_fix_v4bx subdir = testsuite DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -3288,6 +3294,27 @@ uninstall-am: @DEFAULT_TARGET_ARM_TRUE@thumb2_bl_out_of_range.o: thumb_bl_in_range.s @DEFAULT_TARGET_ARM_TRUE@ $(TEST_AS) -o $@ -march=armv7-a $< +@DEFAULT_TARGET_ARM_TRUE@arm_fix_v4bx.stdout: arm_fix_v4bx +@DEFAULT_TARGET_ARM_TRUE@ $(TEST_OBJDUMP) -D -j.text $< > $@ + +@DEFAULT_TARGET_ARM_TRUE@arm_fix_v4bx: arm_fix_v4bx.o +@DEFAULT_TARGET_ARM_TRUE@ ../ld-new --fix-v4bx -o $@ $< + +@DEFAULT_TARGET_ARM_TRUE@arm_fix_v4bx.o: arm_fix_v4bx.s +@DEFAULT_TARGET_ARM_TRUE@ $(TEST_AS) -o $@ $< + +@DEFAULT_TARGET_ARM_TRUE@arm_fix_v4bx_interworking.stdout: arm_fix_v4bx_interworking +@DEFAULT_TARGET_ARM_TRUE@ $(TEST_OBJDUMP) -D -j.text $< > $@ + +@DEFAULT_TARGET_ARM_TRUE@arm_fix_v4bx_interworking: arm_fix_v4bx.o +@DEFAULT_TARGET_ARM_TRUE@ ../ld-new --fix-v4bx-interworking -o $@ $< + +@DEFAULT_TARGET_ARM_TRUE@arm_no_fix_v4bx.stdout: arm_no_fix_v4bx +@DEFAULT_TARGET_ARM_TRUE@ $(TEST_OBJDUMP) -D -j.text $< > $@ + +@DEFAULT_TARGET_ARM_TRUE@arm_no_fix_v4bx: arm_fix_v4bx.o +@DEFAULT_TARGET_ARM_TRUE@ ../ld-new -o $@ $< + # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: diff --git a/gold/testsuite/arm_fix_v4bx.s b/gold/testsuite/arm_fix_v4bx.s new file mode 100644 index 0000000..fc3aa2a --- /dev/null +++ b/gold/testsuite/arm_fix_v4bx.s @@ -0,0 +1,15 @@ + .syntax unified + .text + +# Align this to 256-byte boundary for easier address matching. + .align 8 + +# We do not want to run this file. We define _start here to avoid missing +# entry point. + + .global _start + .type _start, %function +_start: + bx r0 + bx r15 + .size _start, .-_start diff --git a/gold/testsuite/arm_fix_v4bx.sh b/gold/testsuite/arm_fix_v4bx.sh new file mode 100755 index 0000000..a331ff9 --- /dev/null +++ b/gold/testsuite/arm_fix_v4bx.sh @@ -0,0 +1,56 @@ +#!/bin/sh + +# arm_v4bx.sh -- a test case for --fix-v4bx and --fix-v4bx-interworking. + +# Copyright 2010 Free Software Foundation, Inc. +# Written by Doug Kwan <dougkwan@google.com>. + +# This file is part of gold. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +# MA 02110-1301, USA. + +# This file goes with arm_v4bx.s, an ARM assembly source file constructed to +# have test the handling of R_ARM_V4BX relocation. + +check() +{ + if ! grep -q "$2" "$1" + then + echo "Did not find expected instruction in $1:" + echo " $2" + echo "" + echo "Actual instructions below:" + cat "$1" + exit 1 + fi +} + +# Test --fix-v4bx +check arm_fix_v4bx.stdout ".*00: .* mov pc, r0" +check arm_fix_v4bx.stdout ".*04: .* mov pc, pc" + +# Test --fix-v4bx-interworking +check arm_fix_v4bx_interworking.stdout ".*00: .* b .*00 <.*>" +check arm_fix_v4bx_interworking.stdout ".*04: .* mov pc, pc" +check arm_fix_v4bx_interworking.stdout ".*00: .* tst r0, #1" +check arm_fix_v4bx_interworking.stdout ".*04: .* moveq pc, r0" +check arm_fix_v4bx_interworking.stdout ".*08: .* bx r0" + +# Test no fix. +check arm_no_fix_v4bx.stdout ".*00: .* bx r0" +check arm_no_fix_v4bx.stdout ".*04: .* bx pc" + +exit 0 |