From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 28377 invoked by alias); 20 Apr 2006 18:29:58 -0000 Received: (qmail 28358 invoked by uid 22791); 20 Apr 2006 18:29:57 -0000 X-Spam-Check-By: sourceware.org Received: from intranet.codesourcery.com (HELO mail.codesourcery.com) (65.74.133.6) by sourceware.org (qpsmtpd/0.31) with ESMTP; Thu, 20 Apr 2006 18:29:55 +0000 Received: (qmail 4331 invoked from network); 20 Apr 2006 18:29:53 -0000 Received: from unknown (HELO 81-178-240-244.dsl.pipex.com) (paul@127.0.0.2) by mail.codesourcery.com with ESMTPA; 20 Apr 2006 18:29:53 -0000 From: Paul Brook To: binutils@sourceware.org Subject: [patch] R_ARM_REL32 and Thumb functions. Date: Fri, 21 Apr 2006 03:05:00 -0000 User-Agent: KMail/1.9.1 MIME-Version: 1.0 Content-Type: Multipart/Mixed; boundary="Boundary-00=_eM9REBHeOCGPUMb" Message-Id: <200604201929.50393.paul@codesourcery.com> Mailing-List: contact binutils-help@sourceware.org; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: binutils-owner@sourceware.org X-SW-Source: 2006-04/txt/msg00293.txt.bz2 --Boundary-00=_eM9REBHeOCGPUMb Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline Content-length: 1460 The attached patch makes the R_ARM_REL32 relocation set the low bit of the value when the relocated symbol is a Thumb function, as required by the ARM EABI. I don't know if the current behavior is considered a bug or a feature for pre-EABI objects. For now I'm assuming bug, and making the change unconditionally. I can preserver the old behavior if anything depends on it. A slight complication is that gas will try and fold relative expressions at assembly time. This folding is done in generic code, so gets the value wrong. e.g. .thumb_func foo: .word foo - . Will be folded to zero by gas/expr.c:expr. I've [ab]used md_optimize_expr to prevent this happening. Initially I disabled the folding if either symbol was a Thumb function. However this ends up breaking the explicit cfi directives in libgcc, so I've only disabled the folding when the first symbol is a Thumb function. Tested with cross to arm-eabi. Ok? Paul 2006-04-20 Paul Brook bfd/ * elf32-arm.c (elf32_arm_final_link_relocate): Set thumb funciton bit for R_ARM_REL32. gas/ * config/tc-arm.c (arm_optimize_expr): New function. (md_apply_fix): Set thumb funciton bit for PC-relative relocations. * config/tc-arm.c (md_optimize_expr): Define (arm_optimize_expr): Add prototype. (TC_FORCE_RELOCATION_SUB_SAME): Define. ld/testsuite/ * ld-arm/arm-elf.exp: Add thumb-rel32. * ld-arm/thumb-rel32.d: New test. * ld-arm/thumb-rel32.s: New test. --Boundary-00=_eM9REBHeOCGPUMb Content-Type: text/x-diff; charset="us-ascii"; name="patch.rel32" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="patch.rel32" Content-length: 5142 Index: bfd/elf32-arm.c =================================================================== RCS file: /var/cvsroot/src-cvs/src/bfd/elf32-arm.c,v retrieving revision 1.70 diff -u -p -r1.70 elf32-arm.c --- bfd/elf32-arm.c 16 Mar 2006 12:20:15 -0000 1.70 +++ bfd/elf32-arm.c 20 Apr 2006 14:39:04 -0000 @@ -3277,6 +3277,8 @@ elf32_arm_final_link_relocate (reloc_how value -= (input_section->output_section->vma + input_section->output_offset + rel->r_offset); value += addend; + if (sym_flags == STT_ARM_TFUNC) + value |= 1; break; case R_ARM_PREL31: Index: gas/config/tc-arm.c =================================================================== RCS file: /var/cvsroot/src-cvs/src/gas/config/tc-arm.c,v retrieving revision 1.256 diff -u -p -r1.256 tc-arm.c --- gas/config/tc-arm.c 7 Apr 2006 15:11:19 -0000 1.256 +++ gas/config/tc-arm.c 20 Apr 2006 17:31:47 -0000 @@ -11491,6 +11491,29 @@ get_thumb32_insn (char * buf) return insn; } + +/* We usually want to set the low bit on the address of thumb function + symbols. In particular .word foo - . should have the low bit set. + Generic code tries to fold the difference of two symbols to + a constant. Prevent this and force a relocation when the first symbols + is a thumb function. */ +int +arm_optimize_expr (expressionS *l, operatorT op, expressionS *r) +{ + if (op == O_subtract + && l->X_op == O_symbol + && r->X_op == O_symbol + && THUMB_IS_FUNC (l->X_add_symbol)) + { + l->X_op = O_subtract; + l->X_op_symbol = r->X_add_symbol; + l->X_add_number -= r->X_add_number; + return 1; + } + /* Process as normal. */ + return 0; +} + void md_apply_fix (fixS * fixP, valueT * valP, @@ -12106,7 +12129,14 @@ md_apply_fix (fixS * fixP, case BFD_RELOC_ARM_TARGET1: case BFD_RELOC_ARM_ROSEGREL32: case BFD_RELOC_ARM_SBREL32: + if (fixP->fx_done || !seg->use_rela_p) + md_number_to_chars (buf, value, 4); + break; + case BFD_RELOC_32_PCREL: + /* Set the low bit of the value if the target is a thumb function. */ + if (fixP->fx_done && fixP->fx_addsy && THUMB_IS_FUNC(fixP->fx_addsy)) + value |= 1; if (fixP->fx_done || !seg->use_rela_p) md_number_to_chars (buf, value, 4); break; Index: gas/config/tc-arm.h =================================================================== RCS file: /var/cvsroot/src-cvs/src/gas/config/tc-arm.h,v retrieving revision 1.36 diff -u -p -r1.36 tc-arm.h --- gas/config/tc-arm.h 8 Oct 2005 17:07:16 -0000 1.36 +++ gas/config/tc-arm.h 20 Apr 2006 17:58:59 -0000 @@ -83,6 +83,9 @@ struct fix; arm_relax_frag(segment, fragp, stretch) extern int arm_relax_frag (asection *, struct frag *, long); +#define md_optimize_expr(l,o,r) arm_optimize_expr (l, o, r) +extern int arm_optimize_expr (expressionS *, operatorT, expressionS *); + #define md_cleanup() arm_cleanup () #define md_start_line_hook() arm_start_line_hook () @@ -148,6 +151,12 @@ extern void arm_md_end (void); || (FIX)->fx_r_type == BFD_RELOC_32 \ || TC_FORCE_RELOCATION (FIX)) +/* Force output of R_ARM_REL32 relocations against thumb function symbols. + This is needed to ensure the low bit is handled correctly. */ +#define TC_FORCE_RELOCATION_SUB_SAME(FIX, SEG) \ + (THUMB_IS_FUNC ((FIX)->fx_addsy) \ + || !SEG_NORMAL (SEG)) + #define TC_CONS_FIX_NEW cons_fix_new_arm #define MAX_MEM_FOR_RS_ALIGN_CODE 31 Index: ld/testsuite/ld-arm/arm-elf.exp =================================================================== RCS file: /var/cvsroot/src-cvs/src/ld/testsuite/ld-arm/arm-elf.exp,v retrieving revision 1.11 diff -u -p -r1.11 arm-elf.exp --- ld/testsuite/ld-arm/arm-elf.exp 7 Mar 2006 08:39:21 -0000 1.11 +++ ld/testsuite/ld-arm/arm-elf.exp 20 Apr 2006 14:47:23 -0000 @@ -119,6 +119,9 @@ set armelftests { {"Thumb entry point" "-T arm.ld" "" {thumb-entry.s} {{readelf -h thumb-entry.d}} "thumb-entry"} + {"thumb-rel32" "-static -T arm.ld" "" {thumb-rel32.s} + {{objdump -s thumb-rel32.d}} + "thumb-rel32"} } run_ld_link_tests $armelftests Index: ld/testsuite/ld-arm/thumb-rel32.d =================================================================== RCS file: ld/testsuite/ld-arm/thumb-rel32.d diff -N ld/testsuite/ld-arm/thumb-rel32.d --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ld/testsuite/ld-arm/thumb-rel32.d 20 Apr 2006 14:45:39 -0000 @@ -0,0 +1,7 @@ + +.*: file format.* + +Contents of section .text: + 8000 (00000009 fffffffd|09000000 fdffffff) .* +# Ignore .ARM.attributes section +#... Index: ld/testsuite/ld-arm/thumb-rel32.s =================================================================== RCS file: ld/testsuite/ld-arm/thumb-rel32.s diff -N ld/testsuite/ld-arm/thumb-rel32.s --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ld/testsuite/ld-arm/thumb-rel32.s 20 Apr 2006 16:36:07 -0000 @@ -0,0 +1,15 @@ + .text + .arch armv4t + .global _start + .type _start, %function + .thumb_func +_start: + .word bar - . + .word _start - . + .section .after, "ax", %progbits + .global bar + .type bar, %function + .thumb_func +bar: + .word 0 + .ident "GCC: (GNU) 4.1.0 (CodeSourcery ARM)" --Boundary-00=_eM9REBHeOCGPUMb--