This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[PATCH] Improved branches to weak symbols
- From: Daniel Gutson <dgutson at codesourcery dot com>
- To: binutils at sourceware dot org
- Date: Thu, 13 Aug 2009 17:41:19 -0300
- Subject: [PATCH] Improved branches to weak symbols
Hi,
the attached patch improves the instructions to generate when
branching to weak symbols.
Rather than jumping to the next instruction, NOPs are generated, and
selected according to the architecture.
Please let me know if OK to commit.
Thanks!
Daniel.
-----
bfd/
* elf32-arm.c (arch_has_thumb2_nop): New function.
(arch_has_arm_nop): New function.
(elf32_arm_final_link_relocate): NOP opcodes changed.
ld/testsuite/
* ld-arm/callweak.d: Opcodes updated.
* ld-arm/callweak.s: Architecture specified.
* ld-arm/callweak-2.d: New test case.
* ld-arm/callweak-2.s: New file.
--
Daniel Gutson
CodeSourcery
www.codesourcery.com
Index: bfd/elf32-arm.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-arm.c,v
retrieving revision 1.209
diff -u -p -r1.209 elf32-arm.c
--- bfd/elf32-arm.c 10 Aug 2009 15:56:30 -0000 1.209
+++ bfd/elf32-arm.c 13 Aug 2009 20:37:52 -0000
@@ -2987,6 +2987,26 @@ using_thumb2 (struct elf32_arm_link_hash
return arch == TAG_CPU_ARCH_V6T2 || arch >= TAG_CPU_ARCH_V7;
}
+/* Determine what kind of NOPs are available. */
+
+static bfd_boolean
+arch_has_arm_nop (struct elf32_arm_link_hash_table *globals)
+{
+ const int arch = bfd_elf_get_obj_attr_int (globals->obfd, OBJ_ATTR_PROC,
+ Tag_CPU_arch);
+ return arch == TAG_CPU_ARCH_V6T2
+ || arch == TAG_CPU_ARCH_V6K
+ || arch == TAG_CPU_ARCH_V7;
+}
+
+static bfd_boolean
+arch_has_thumb2_nop (struct elf32_arm_link_hash_table *globals)
+{
+ const int arch = bfd_elf_get_obj_attr_int (globals->obfd, OBJ_ATTR_PROC,
+ Tag_CPU_arch);
+ return arch == TAG_CPU_ARCH_V6T2 || arch == TAG_CPU_ARCH_V7;
+}
+
static bfd_boolean
arm_stub_is_thumb (enum elf32_arm_stub_type stub_type)
{
@@ -7073,13 +7093,19 @@ elf32_arm_final_link_relocate (reloc_how
/* A branch to an undefined weak symbol is turned into a jump to
the next instruction unless a PLT entry will be created.
- Do the same for local undefined symbols. */
+ Do the same for local undefined symbols.
+ The jump to the next instruction is optimized as a NOP depending
+ on the architecture. */
if (h ? (h->root.type == bfd_link_hash_undefweak
&& !(splt != NULL && h->plt.offset != (bfd_vma) -1))
: bfd_is_und_section (sym_sec))
{
- value = (bfd_get_32 (input_bfd, hit_data) & 0xf0000000)
- | 0x0affffff;
+ value = (bfd_get_32 (input_bfd, hit_data) & 0xf0000000);
+
+ if (arch_has_arm_nop (globals))
+ value |= 0x0320f000;
+ else
+ value |= 0x01a00000; /* Using pre-UAL nop: mov r0, r0. */
}
else
{
@@ -7324,15 +7350,25 @@ elf32_arm_final_link_relocate (reloc_how
bfd_vma check;
bfd_signed_vma signed_check;
int bitsize;
- int thumb2 = using_thumb2 (globals);
+ const int thumb2 = using_thumb2 (globals);
/* A branch to an undefined weak symbol is turned into a jump to
- the next instruction unless a PLT entry will be created. */
+ the next instruction unless a PLT entry will be created.
+ The jump to the next instruction is optimized as a NOP.W for
+ Thumb-2 enabled architectures. */
if (h && h->root.type == bfd_link_hash_undefweak
&& !(splt != NULL && h->plt.offset != (bfd_vma) -1))
{
- bfd_put_16 (input_bfd, 0xe000, hit_data);
- bfd_put_16 (input_bfd, 0xbf00, hit_data + 2);
+ if (arch_has_thumb2_nop (globals))
+ {
+ bfd_put_16 (input_bfd, 0xf3af, hit_data);
+ bfd_put_16 (input_bfd, 0x8000, hit_data + 2);
+ }
+ else
+ {
+ bfd_put_16 (input_bfd, 0xe000, hit_data);
+ bfd_put_16 (input_bfd, 0xbf00, hit_data + 2);
+ }
return bfd_reloc_ok;
}
Index: ld/testsuite/ld-arm/arm-elf.exp
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-arm/arm-elf.exp,v
retrieving revision 1.61
diff -u -p -r1.61 arm-elf.exp
--- ld/testsuite/ld-arm/arm-elf.exp 6 Aug 2009 13:05:24 -0000 1.61
+++ ld/testsuite/ld-arm/arm-elf.exp 13 Aug 2009 20:37:57 -0000
@@ -229,6 +229,9 @@ set armelftests {
{"callweak" "-static -T arm.ld" "" {callweak.s}
{{objdump -dr callweak.d}}
"callweak"}
+ {"callweak-2" "-static -T arm.ld" "" {callweak-2.s}
+ {{objdump -dr callweak-2.d}}
+ "callweak-2"}
}
run_ld_link_tests $armelftests
Index: ld/testsuite/ld-arm/callweak-2.d
===================================================================
RCS file: ld/testsuite/ld-arm/callweak-2.d
diff -N ld/testsuite/ld-arm/callweak-2.d
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-arm/callweak-2.d 13 Aug 2009 20:37:57 -0000
@@ -0,0 +1,15 @@
+
+.*: file format.*
+
+Disassembly of section .far:
+
+12340000 <[^>]*>:
+12340000: e320f000 nop \{0\}
+12340004: 0320f000 nopeq \{0\}
+
+12340008 <[^>]*>:
+12340008: f3af 8000 nop.w
+1234000c: 2000 movs r0, #0
+1234000e: f3af 8000 nop.w
+12340012: 4770 bx lr
+
Index: ld/testsuite/ld-arm/callweak-2.s
===================================================================
RCS file: ld/testsuite/ld-arm/callweak-2.s
diff -N ld/testsuite/ld-arm/callweak-2.s
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-arm/callweak-2.s 13 Aug 2009 20:37:57 -0000
@@ -0,0 +1,17 @@
+ .syntax unified
+ .arch armv6t2
+ .weak bar
+ .section .far, "ax", %progbits
+ .global _start
+ .type _start, %function
+_start:
+ bl bar
+ bleq bar
+ .thumb
+ .type foo, %function
+ .thumb_func
+foo:
+ bl bar
+ movs r0, #0
+ bl bar
+ bx lr
Index: ld/testsuite/ld-arm/callweak.d
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-arm/callweak.d,v
retrieving revision 1.1
diff -u -p -r1.1 callweak.d
--- ld/testsuite/ld-arm/callweak.d 25 Jul 2007 14:39:48 -0000 1.1
+++ ld/testsuite/ld-arm/callweak.d 13 Aug 2009 20:37:57 -0000
@@ -4,8 +4,8 @@
Disassembly of section .far:
12340000 <[^>]*>:
-12340000: eaffffff b 12340004 <[^>]*>
-12340004: 0affffff beq 12340008 <[^>]*>
+12340000: e1a00000 nop ; \(mov r0, r0\)
+12340004: 01a00000 moveq r0, r0
12340008 <[^>]*>:
12340008: e000 b.n 1234000c <[^>]*>
Index: ld/testsuite/ld-arm/callweak.s
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-arm/callweak.s,v
retrieving revision 1.1
diff -u -p -r1.1 callweak.s
--- ld/testsuite/ld-arm/callweak.s 25 Jul 2007 14:39:48 -0000 1.1
+++ ld/testsuite/ld-arm/callweak.s 13 Aug 2009 20:37:57 -0000
@@ -1,4 +1,5 @@
.syntax unified
+ .arch armv6
.weak bar
.section .far, "ax", %progbits
.global _start