From f6cccc2cd840baa795beb501a7afc4453000095e Mon Sep 17 00:00:00 2001 From: Doug Kwan Date: Wed, 6 Jul 2011 17:58:42 +0000 Subject: [PATCH] 2011-07-05 Doug Kwan 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 | 16 +++++++++++ gold/arm.cc | 51 +++++++++++++++++------------------ gold/testsuite/Makefile.am | 14 ++++++++++ gold/testsuite/Makefile.in | 20 +++++++++++--- gold/testsuite/arm_unaligned_reloc.s | 44 ++++++++++++++++++++++++++++++ gold/testsuite/arm_unaligned_reloc.sh | 50 ++++++++++++++++++++++++++++++++++ 6 files changed, 166 insertions(+), 29 deletions(-) create mode 100644 gold/testsuite/arm_unaligned_reloc.s create mode 100755 gold/testsuite/arm_unaligned_reloc.sh diff --git a/gold/ChangeLog b/gold/ChangeLog index 65b0bb3..ec8e8f1 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,3 +1,19 @@ +2011-07-05 Doug Kwan + + 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 PR gold/12392 diff --git a/gold/arm.cc b/gold/arm.cc index 8fd20be..f652677 100644 --- a/gold/arm.cc +++ b/gold/arm.cc @@ -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(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(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(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(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(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(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(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); } diff --git a/gold/testsuite/Makefile.am b/gold/testsuite/Makefile.am index 2b90057..9792400 100644 --- a/gold/testsuite/Makefile.am +++ b/gold/testsuite/Makefile.am @@ -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 diff --git a/gold/testsuite/Makefile.in b/gold/testsuite/Makefile.in index 2dab4c3..5295c52 100644 --- a/gold/testsuite/Makefile.in +++ b/gold/testsuite/Makefile.in @@ -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 index 0000000..7677bff --- /dev/null +++ b/gold/testsuite/arm_unaligned_reloc.s @@ -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 index 0000000..496ee28 --- /dev/null +++ b/gold/testsuite/arm_unaligned_reloc.sh @@ -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 + +# 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 :$" +check arm_unaligned_reloc.stdout "^0000a001 :$" +check arm_unaligned_reloc.stdout "^ a001: 00009000 .*$" +check arm_unaligned_reloc.stdout "^0000a005 :" +check arm_unaligned_reloc.stdout "^ a005: ffffeffb .*$" +check arm_unaligned_reloc.stdout "^0000a009 :" +check arm_unaligned_reloc.stdout "^ a009: 00009000 .*$" + +exit 0 -- 2.7.4