2011-07-05 Doug Kwan <dougkwan@google.com>
authorDoug Kwan <dougkwan@google.com>
Wed, 6 Jul 2011 17:58:42 +0000 (17:58 +0000)
committerDoug Kwan <dougkwan@google.com>
Wed, 6 Jul 2011 17:58:42 +0000 (17:58 +0000)
PR gold/12771
* arm.cc (Arm_relocate_functions::abs8): Use int32_t for addend and
Arm_Address type for relocation result.
(Arm_relocate_functions::abs16): Use unaligned access.  Also fix
overflow check.
(Arm_relocate_functions::abs32): Use unaligned access.
(Arm_relocate_functions::rel32): Ditto.
(Arm_relocate_functions::prel31): Ditto.
(Arm_exidix_cantunwind::do_fixed_endian_write): Ditto.
* testsuite/Makefile.am: Add new test arm_unaligned_reloc for unaligned
static data relocations.
* testsuite/Makefile.in: Regnerate.
* testsuite/arm_unaligned_reloc.{s,sh}: New files.

gold/ChangeLog
gold/arm.cc
gold/testsuite/Makefile.am
gold/testsuite/Makefile.in
gold/testsuite/arm_unaligned_reloc.s [new file with mode: 0644]
gold/testsuite/arm_unaligned_reloc.sh [new file with mode: 0755]

index 65b0bb3cc053394b2bc992be4474f46d47e8f2e7..ec8e8f162b995c5f1b0d595dc0be81ce6bd71148 100644 (file)
@@ -1,3 +1,19 @@
+2011-07-05  Doug Kwan  <dougkwan@google.com>
+
+       PR gold/12771
+       * arm.cc (Arm_relocate_functions::abs8): Use int32_t for addend and
+       Arm_Address type for relocation result.
+       (Arm_relocate_functions::abs16): Use unaligned access.  Also fix
+       overflow check.
+       (Arm_relocate_functions::abs32): Use unaligned access.
+       (Arm_relocate_functions::rel32): Ditto.
+       (Arm_relocate_functions::prel31): Ditto.
+       (Arm_exidix_cantunwind::do_fixed_endian_write): Ditto.
+       * testsuite/Makefile.am: Add new test arm_unaligned_reloc for unaligned
+       static data relocations.
+       * testsuite/Makefile.in: Regnerate.
+       * testsuite/arm_unaligned_reloc.{s,sh}: New files.
+
 2011-07-05  Ian Lance Taylor  <iant@google.com>
 
        PR gold/12392
index 8fd20be6b8959bfe760d8d09e8b2b3c10c82bcf1..f65267795a7c5b1b30c7347dc94a15e04bb172e3 100644 (file)
@@ -3215,11 +3215,10 @@ class Arm_relocate_functions : public Relocate_functions<32, big_endian>
        const Symbol_value<32>* psymval)
   {
     typedef typename elfcpp::Swap<8, big_endian>::Valtype Valtype;
-    typedef typename elfcpp::Swap<32, big_endian>::Valtype Reltype;
     Valtype* wv = reinterpret_cast<Valtype*>(view);
     Valtype val = elfcpp::Swap<8, big_endian>::readval(wv);
-    Reltype addend = utils::sign_extend<8>(val);
-    Reltype x = psymval->value(object, addend);
+    int32_t addend = utils::sign_extend<8>(val);
+    Arm_address x = psymval->value(object, addend);
     val = utils::bit_select(val, x, 0xffU);
     elfcpp::Swap<8, big_endian>::writeval(wv, val);
 
@@ -3277,15 +3276,17 @@ class Arm_relocate_functions : public Relocate_functions<32, big_endian>
        const Sized_relobj_file<32, big_endian>* object,
        const Symbol_value<32>* psymval)
   {
-    typedef typename elfcpp::Swap<16, big_endian>::Valtype Valtype;
+    typedef typename elfcpp::Swap_unaligned<16, big_endian>::Valtype Valtype;
     typedef typename elfcpp::Swap<32, big_endian>::Valtype Reltype;
-    Valtype* wv = reinterpret_cast<Valtype*>(view);
-    Valtype val = elfcpp::Swap<16, big_endian>::readval(wv);
-    Reltype addend = utils::sign_extend<16>(val);
-    Reltype x = psymval->value(object, addend);
+    Valtype val = elfcpp::Swap_unaligned<16, big_endian>::readval(view);
+    int32_t addend = utils::sign_extend<16>(val);
+    Arm_address x = psymval->value(object, addend);
     val = utils::bit_select(val, x, 0xffffU);
-    elfcpp::Swap<16, big_endian>::writeval(wv, val);
-    return (utils::has_signed_unsigned_overflow<16>(x)
+    elfcpp::Swap_unaligned<16, big_endian>::writeval(view, val);
+
+    // R_ARM_ABS16 permits signed or unsigned results.
+    int signed_x = static_cast<int32_t>(x);
+    return ((signed_x < -32768 || signed_x > 65536)
            ? This::STATUS_OVERFLOW
            : This::STATUS_OKAY);
   }
@@ -3297,11 +3298,10 @@ class Arm_relocate_functions : public Relocate_functions<32, big_endian>
        const Symbol_value<32>* psymval,
        Arm_address thumb_bit)
   {
-    typedef typename elfcpp::Swap<32, big_endian>::Valtype Valtype;
-    Valtype* wv = reinterpret_cast<Valtype*>(view);
-    Valtype addend = elfcpp::Swap<32, big_endian>::readval(wv);
+    typedef typename elfcpp::Swap_unaligned<32, big_endian>::Valtype Valtype;
+    Valtype addend = elfcpp::Swap_unaligned<32, big_endian>::readval(view);
     Valtype x = psymval->value(object, addend) | thumb_bit;
-    elfcpp::Swap<32, big_endian>::writeval(wv, x);
+    elfcpp::Swap_unaligned<32, big_endian>::writeval(view, x);
     return This::STATUS_OKAY;
   }
 
@@ -3313,11 +3313,10 @@ class Arm_relocate_functions : public Relocate_functions<32, big_endian>
        Arm_address address,
        Arm_address thumb_bit)
   {
-    typedef typename elfcpp::Swap<32, big_endian>::Valtype Valtype;
-    Valtype* wv = reinterpret_cast<Valtype*>(view);
-    Valtype addend = elfcpp::Swap<32, big_endian>::readval(wv);
+    typedef typename elfcpp::Swap_unaligned<32, big_endian>::Valtype Valtype;
+    Valtype addend = elfcpp::Swap_unaligned<32, big_endian>::readval(view);
     Valtype x = (psymval->value(object, addend) | thumb_bit) - address;
-    elfcpp::Swap<32, big_endian>::writeval(wv, x);
+    elfcpp::Swap_unaligned<32, big_endian>::writeval(view, x);
     return This::STATUS_OKAY;
   }
 
@@ -3435,13 +3434,12 @@ class Arm_relocate_functions : public Relocate_functions<32, big_endian>
         Arm_address address,
         Arm_address thumb_bit)
   {
-    typedef typename elfcpp::Swap<32, big_endian>::Valtype Valtype;
-    Valtype* wv = reinterpret_cast<Valtype*>(view);
-    Valtype val = elfcpp::Swap<32, big_endian>::readval(wv);
+    typedef typename elfcpp::Swap_unaligned<32, big_endian>::Valtype Valtype;
+    Valtype val = elfcpp::Swap_unaligned<32, big_endian>::readval(view);
     Valtype addend = utils::sign_extend<31>(val);
     Valtype x = (psymval->value(object, addend) | thumb_bit) - address;
     val = utils::bit_select(val, x, 0x7fffffffU);
-    elfcpp::Swap<32, big_endian>::writeval(wv, val);
+    elfcpp::Swap_unaligned<32, big_endian>::writeval(view, val);
     return (utils::has_overflow<31>(x) ?
            This::STATUS_OVERFLOW : This::STATUS_OKAY);
   }
@@ -5221,8 +5219,7 @@ Arm_exidx_cantunwind::do_fixed_endian_write(Output_file* of)
   const section_size_type oview_size = 8;
   unsigned char* const oview = of->get_output_view(offset, oview_size);
   
-  typedef typename elfcpp::Swap<32, big_endian>::Valtype Valtype;
-  Valtype* wv = reinterpret_cast<Valtype*>(oview);
+  typedef typename elfcpp::Swap_unaligned<32, big_endian>::Valtype Valtype;
 
   Output_section* os = this->relobj_->output_section(this->shndx_);
   gold_assert(os != NULL);
@@ -5263,8 +5260,10 @@ Arm_exidx_cantunwind::do_fixed_endian_write(Output_file* of)
   uint32_t prel31_offset = output_address - this->address();
   if (utils::has_overflow<31>(offset))
     gold_error(_("PREL31 overflow in EXIDX_CANTUNWIND entry"));
-  elfcpp::Swap<32, big_endian>::writeval(wv, prel31_offset & 0x7fffffffU);
-  elfcpp::Swap<32, big_endian>::writeval(wv + 1, elfcpp::EXIDX_CANTUNWIND);
+  elfcpp::Swap_unaligned<32, big_endian>::writeval(oview,
+                                                  prel31_offset & 0x7fffffffU);
+  elfcpp::Swap_unaligned<32, big_endian>::writeval(oview + 4,
+                                                  elfcpp::EXIDX_CANTUNWIND);
 
   of->write_output_view(this->offset(), oview_size, oview);
 }
index 2b90057c17361293a3670d04c1611bcbf6ea65b5..97924001dccbbbdd253e3dd827ac84bec7970d98 100644 (file)
@@ -2343,6 +2343,20 @@ pr12826_1.o: pr12826_1.s
 pr12826_2.o: pr12826_2.s
        $(TEST_AS) -o $@ $<
 
+check_SCRIPTS += arm_unaligned_reloc.sh
+check_DATA += arm_unaligned_reloc.stdout
+
+arm_unaligned_reloc.stdout: arm_unaligned_reloc
+       $(TEST_OBJDUMP) -D $< > $@
+
+arm_unaligned_reloc: arm_unaligned_reloc.o ../ld-new
+       ../ld-new -o $@ $<
+
+arm_unaligned_reloc.o: arm_unaligned_reloc.s
+       $(TEST_AS) -o $@ $<
+
+MOSTLYCLEANFILES += arm_unaligned_reloc
+
 endif DEFAULT_TARGET_ARM
 
 endif NATIVE_OR_CROSS_LINKER
index 2dab4c3a95989390b0e37db2e90ec2badbda7963..5295c52998ade347ca9769454b681d7b5bed9567 100644 (file)
@@ -492,7 +492,8 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \
 @DEFAULT_TARGET_ARM_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ arm_attr_merge.sh \
 @DEFAULT_TARGET_ARM_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ arm_cortex_a8.sh \
 @DEFAULT_TARGET_ARM_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ arm_exidx_test.sh \
-@DEFAULT_TARGET_ARM_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ pr12826.sh
+@DEFAULT_TARGET_ARM_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ pr12826.sh \
+@DEFAULT_TARGET_ARM_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ arm_unaligned_reloc.sh
 @DEFAULT_TARGET_ARM_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@am__append_65 = arm_abs_global.stdout \
 @DEFAULT_TARGET_ARM_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ arm_bl_in_range.stdout \
 @DEFAULT_TARGET_ARM_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ arm_bl_out_of_range.stdout \
@@ -520,7 +521,8 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \
 @DEFAULT_TARGET_ARM_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ arm_cortex_a8_local.stdout \
 @DEFAULT_TARGET_ARM_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ arm_cortex_a8_local_reloc.stdout \
 @DEFAULT_TARGET_ARM_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ arm_exidx_test.stdout \
-@DEFAULT_TARGET_ARM_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ pr12826.stdout
+@DEFAULT_TARGET_ARM_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ pr12826.stdout \
+@DEFAULT_TARGET_ARM_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ arm_unaligned_reloc.stdout
 @DEFAULT_TARGET_ARM_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@am__append_66 = arm_abs_global \
 @DEFAULT_TARGET_ARM_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ arm_bl_in_range \
 @DEFAULT_TARGET_ARM_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ arm_bl_out_of_range \
@@ -546,7 +548,8 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \
 @DEFAULT_TARGET_ARM_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ arm_cortex_a8_bl \
 @DEFAULT_TARGET_ARM_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ arm_cortex_a8_blx \
 @DEFAULT_TARGET_ARM_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ arm_cortex_a8_local \
-@DEFAULT_TARGET_ARM_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ arm_cortex_a8_local_reloc
+@DEFAULT_TARGET_ARM_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ arm_cortex_a8_local_reloc \
+@DEFAULT_TARGET_ARM_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ arm_unaligned_reloc
 subdir = testsuite
 DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
@@ -3529,6 +3532,8 @@ arm_exidx_test.sh.log: arm_exidx_test.sh
        @p='arm_exidx_test.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
 pr12826.sh.log: pr12826.sh
        @p='pr12826.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
+arm_unaligned_reloc.sh.log: arm_unaligned_reloc.sh
+       @p='arm_unaligned_reloc.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
 object_unittest.log: object_unittest$(EXEEXT)
        @p='object_unittest$(EXEEXT)'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
 binary_unittest.log: binary_unittest$(EXEEXT)
@@ -5121,6 +5126,15 @@ uninstall-am:
 @DEFAULT_TARGET_ARM_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@pr12826_2.o: pr12826_2.s
 @DEFAULT_TARGET_ARM_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ $(TEST_AS) -o $@ $<
 
+@DEFAULT_TARGET_ARM_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@arm_unaligned_reloc.stdout: arm_unaligned_reloc
+@DEFAULT_TARGET_ARM_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ $(TEST_OBJDUMP) -D $< > $@
+
+@DEFAULT_TARGET_ARM_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@arm_unaligned_reloc: arm_unaligned_reloc.o ../ld-new
+@DEFAULT_TARGET_ARM_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ ../ld-new -o $@ $<
+
+@DEFAULT_TARGET_ARM_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@arm_unaligned_reloc.o: arm_unaligned_reloc.s
+@DEFAULT_TARGET_ARM_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ $(TEST_AS) -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_unaligned_reloc.s b/gold/testsuite/arm_unaligned_reloc.s
new file mode 100644 (file)
index 0000000..7677bff
--- /dev/null
@@ -0,0 +1,44 @@
+       .syntax unified
+
+       .global _start
+       .type   _start, %function
+       .text
+_start:
+       bx      lr
+       .size   _start,.-_start
+
+       .section        .data.0,"aw",%progbits
+       .align  12
+       .type   x, %object
+       .size   x, 4
+x:
+       .word   1
+
+       .section        .data.1,"aw",%progbits
+       .align  2
+
+# This causes following relocations to be unaligned.
+       .global padding
+       .type   padding, %object
+       .size   padding, 1
+padding:
+       .byte   0
+
+       .global abs32
+       .type   abs32, %object
+       .size   abs32, 4
+abs32:
+       .word   x
+
+       .global rel32
+       .type   rel32, %object
+       .size   rel32, 4
+rel32:
+       .word   x - .
+
+       .global abs16
+       .type   abs16, %object
+       .size   abs16, 2
+abs16:
+       .short  x
+       .short  0
diff --git a/gold/testsuite/arm_unaligned_reloc.sh b/gold/testsuite/arm_unaligned_reloc.sh
new file mode 100755 (executable)
index 0000000..496ee28
--- /dev/null
@@ -0,0 +1,50 @@
+#!/bin/sh
+
+# arm_unaligned_reloc.sh -- test ARM unaligned static data relocations.
+
+# Copyright 2011 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 the assembler source file arm_unaligned_reloc.s,
+# that is assembled and linked as a dummy executable.  We want to check
+# it is okay to do unaligned static data relocations.
+
+check()
+{
+    if ! grep -q -e "$2" "$1"
+    then
+       echo "Did not find pattern \"$2\" in $1:"
+       echo "   $2"
+       echo ""
+       echo "Actual disassembly below:"
+       cat "$1"
+       exit 1
+    fi
+}
+
+check arm_unaligned_reloc.stdout "^00009000 <x>:$"
+check arm_unaligned_reloc.stdout "^0000a001 <abs32>:$"
+check arm_unaligned_reloc.stdout "^    a001:   00009000 .*$"
+check arm_unaligned_reloc.stdout "^0000a005 <rel32>:"
+check arm_unaligned_reloc.stdout "^    a005:   ffffeffb .*$"
+check arm_unaligned_reloc.stdout "^0000a009 <abs16>:"
+check arm_unaligned_reloc.stdout "^    a009:   00009000 .*$"
+
+exit 0