This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH, ARM] Fix bl->blx conversion for object-local targets


Hi,

Gas has logic which is supposed to turn Thumb BL instructions into BLX
instructions when targeting local ARM symbols (and similarly for ARM BL
instructions targeting local Thumb symbols). Unfortunately this is
flawed at present, and can lead to incorrectly-encoded BLX instructions.

The attached patch fixes this. The condition inside the #ifdef is
moved lower down the function (otherwise the rounding-up of "value" to a
word boundary never triggers after BL->BLX conversions), and the code
which actually does the rounding is altered to match the comment -- I'm
pretty sure in this case the comment was correct, but the code was only
rounding up to a half-word boundary rather than a word boundary as
stated.

This bug manifested for me as a failure in GCC testing
(g++.dg/ipa/pr46984.C in Thumb-1 mode), but only because that test
happens to insert ARM-mode code (for a MI thunk) into Thumb output.

I've added a new test, which passes with the patch, and fails without.
No other regressions (gas tests), cross to ARM Linux. OK to apply?

(Incidentally, an orthogonal problem might be that the ARM1176 erratum
workaround described at:

  http://sourceware.org/ml/binutils/2011-07/msg00235.html

is not taken into account when performing this kind of conversion. I'm
not planning on tackling that issue though.)

Thanks,

Julian

ChangeLog

    gas/
    * config/tc-arm.c (md_apply_fix): Fix conversion of BL to BLX for
    local targets in Thumb mode.

    gas/testsuite/
    * gas/arm/bl-local-2.s: New test.
    * gas/arm/bl-local-2.d: New.
Index: gas/testsuite/gas/arm/bl-local-2.d
===================================================================
--- gas/testsuite/gas/arm/bl-local-2.d	(revision 0)
+++ gas/testsuite/gas/arm/bl-local-2.d	(revision 0)
@@ -0,0 +1,21 @@
+#name: bl local conversion to blx
+#objdump: -drw --prefix-addresses --show-raw-insn
+#as:
+
+
+.*:     file format .*
+
+
+Disassembly of section \.text:
+0+00 <[^>]+> e12fff1e 	bx	lr
+0+04 <[^>]+> 46c0      	nop			; \(mov r8, r8\)
+0+06 <[^>]+> f7ff effc 	blx	0+ <myfunction>
+0+0a <[^>]+> 46c0      	nop			; \(mov r8, r8\)
+0+0c <[^>]+> f7ff eff8 	blx	0+ <myfunction>
+0+10 <[^>]+> 46c0      	nop			; \(mov r8, r8\)
+0+12 <[^>]+> f7ff eff6 	blx	0+ <myfunction>
+0+16 <[^>]+> 46c0      	nop			; \(mov r8, r8\)
+0+18 <[^>]+> f7ff eff2 	blx	0+ <myfunction>
+0+1c <[^>]+> 4770      	bx	lr
+0+1e <[^>]+> 46c0      	nop			; \(mov r8, r8\)
+0+20 <[^>]+> fafffffd 	blx	0000001c <mythumbfunction>
Index: gas/testsuite/gas/arm/bl-local-2.s
===================================================================
--- gas/testsuite/gas/arm/bl-local-2.s	(revision 0)
+++ gas/testsuite/gas/arm/bl-local-2.s	(revision 0)
@@ -0,0 +1,41 @@
+	.arch armv5te
+
+	.text
+	.align 2
+	.code 32
+	.type myfunction, %function
+myfunction:
+	bx r14
+
+	.text
+	.align 2
+	.code 16
+	.thumb_func
+	.global caller
+	.type caller, %function
+caller:
+	nop
+	bl myfunction
+	nop
+	bl myfunction
+	nop
+	bl myfunction
+	nop
+	bl myfunction
+
+	.text
+	.align 2
+	.code 16
+	.type mythumbfunction, %function
+	.thumb_func
+mythumbfunction:
+	bx r14
+
+	.text
+	.align 2
+	.code 32
+	.global armcaller
+	.type armcaller, %function
+armcaller:
+	bl mythumbfunction
+
Index: gas/config/tc-arm.c
===================================================================
--- gas/config/tc-arm.c	(revision 393927)
+++ gas/config/tc-arm.c	(working copy)
@@ -22035,18 +22035,18 @@ md_apply_fix (fixS *	fixP,
 
     thumb_bl_common:
 
-#ifdef OBJ_ELF
-       if (EF_ARM_EABI_VERSION (meabi_flags) >= EF_ARM_EABI_VER4
-	   && fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX)
-	 fixP->fx_r_type = BFD_RELOC_THUMB_PCREL_BRANCH23;
-#endif
-
       if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX)
 	/* For a BLX instruction, make sure that the relocation is rounded up
 	   to a word boundary.  This follows the semantics of the instruction
 	   which specifies that bit 1 of the target address will come from bit
 	   1 of the base address.  */
-	value = (value + 1) & ~ 1;
+	value = (value + 3) & ~ 3;
+
+#ifdef OBJ_ELF
+       if (EF_ARM_EABI_VERSION (meabi_flags) >= EF_ARM_EABI_VER4
+	   && fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX)
+	 fixP->fx_r_type = BFD_RELOC_THUMB_PCREL_BRANCH23;
+#endif
 
       if ((value & ~0x3fffff) && ((value & ~0x3fffff) != ~0x3fffff))
 	{

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]