summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gold/ChangeLog20
-rw-r--r--gold/arm.cc59
-rw-r--r--gold/options.cc3
-rw-r--r--gold/testsuite/Makefile.am27
-rw-r--r--gold/testsuite/Makefile.in33
-rw-r--r--gold/testsuite/arm_fix_v4bx.s15
-rwxr-xr-xgold/testsuite/arm_fix_v4bx.sh56
7 files changed, 178 insertions, 35 deletions
diff --git a/gold/ChangeLog b/gold/ChangeLog
index 34b582ffa6c..47bd8a791e9 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 136fed63078..dde2d083c0d 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 f377387ed23..c6c8073683a 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 eaf54467198..c9e2d1c4532 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 bbffd69c86d..10730f3098a 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 00000000000..fc3aa2a852e
--- /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 00000000000..a331ff97836
--- /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