[PATCH][GOLD] Fix problem in V4BX code.

Doug Kwan (關振德) dougkwan@google.com
Fri Feb 26 23:43:00 GMT 2010


Hi,

     This fixes two problem in the V4BX code.  The first is that NULL
is passed to an integral argument of Target_arm::scan_reloc_for_stub
and that causes a build breakage when gold is build by gcc trunk.  I
rearrange the code a little to make it more efficient.   The second
problem is that General_options::fix_v4bx_ is not initalized.  That
causes V4BX fix-up to be turned on randomly when neither of --fix-v4bx
nor --fix-v4bx-interworking is specified.   I also added regression
tests for the V4BX options.

-Doug

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.
-------------- next part --------------
Index: gold/arm.cc
===================================================================
RCS file: /cvs/src/src/gold/arm.cc,v
retrieving revision 1.88
diff -u -u -p -r1.88 arm.cc
--- gold/arm.cc	25 Feb 2010 05:11:26 -0000	1.88
+++ gold/arm.cc	26 Feb 2010 22:42:31 -0000
@@ -9880,30 +9880,6 @@ Target_arm<big_endian>::scan_reloc_for_s
   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_secti
 	    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;
 	}
 
Index: gold/options.cc
===================================================================
RCS file: /cvs/src/src/gold/options.cc,v
retrieving revision 1.99
diff -u -u -p -r1.99 options.cc
--- gold/options.cc	22 Jan 2010 19:43:00 -0000	1.99
+++ gold/options.cc	26 Feb 2010 22:42:31 -0000
@@ -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;
Index: gold/testsuite/Makefile.am
===================================================================
RCS file: /cvs/src/src/gold/testsuite/Makefile.am,v
retrieving revision 1.123
diff -u -u -p -r1.123 Makefile.am
--- gold/testsuite/Makefile.am	22 Feb 2010 06:26:07 -0000	1.123
+++ gold/testsuite/Makefile.am	26 Feb 2010 22:42:31 -0000
@@ -1529,4 +1529,31 @@ thumb2_bl_out_of_range.o: thumb_bl_in_ra
 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
Index: gold/testsuite/Makefile.in
===================================================================
RCS file: /cvs/src/src/gold/testsuite/Makefile.in,v
retrieving revision 1.129
diff -u -u -p -r1.129 Makefile.in
--- gold/testsuite/Makefile.in	22 Feb 2010 06:26:07 -0000	1.129
+++ gold/testsuite/Makefile.in	26 Feb 2010 22:42:31 -0000
@@ -323,20 +323,26 @@ check_PROGRAMS = object_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:
Index: gold/testsuite/arm_fix_v4bx.s
===================================================================
RCS file: gold/testsuite/arm_fix_v4bx.s
diff -N gold/testsuite/arm_fix_v4bx.s
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gold/testsuite/arm_fix_v4bx.s	26 Feb 2010 22:42:31 -0000
@@ -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
Index: gold/testsuite/arm_fix_v4bx.sh
===================================================================
RCS file: gold/testsuite/arm_fix_v4bx.sh
diff -N gold/testsuite/arm_fix_v4bx.sh
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gold/testsuite/arm_fix_v4bx.sh	26 Feb 2010 22:42:31 -0000
@@ -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


More information about the Binutils mailing list