This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[PATCH, ARM] Fix bl->blx conversion for object-local targets
- From: Julian Brown <julian at codesourcery dot com>
- To: <binutils at sourceware dot org>
- Date: Tue, 6 Nov 2012 19:05:43 +0000
- Subject: [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))
{