[binutils-gdb] arm: Handle undefweak with ST_BRANCH_UNKNOWN

Christophe Lyon clyon@sourceware.org
Wed Sep 11 15:34:55 GMT 2024


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=a77ccc81295f41b72f96db000d1aa44e4dc91254

commit a77ccc81295f41b72f96db000d1aa44e4dc91254
Author: Christophe Lyon <christophe.lyon@linaro.org>
Date:   Fri Sep 6 17:10:02 2024 +0000

    arm: Handle undefweak with ST_BRANCH_UNKNOWN
    
    A previous patch made ld fail early on Thumb-only where branch_type is
    ST_BRANCH_UNKNOWN.
    
    However, this fails erroneously when the target is undefweak: in that
    case the branch should be replaced by a branch to the next instruction
    (or nop.w on thumb2).  This patch accepts this case and restores the
    previous behaviour in such cases.
    
    This was reported by failures in the GCC testsuite, where we fail to
    link executables because __deregister_frame_info is undefweak:
    
    (__deregister_frame_info): Unknown destination type (ARM/Thumb) in ...crtbegin.o
    crtbegin.o: in function `__do_global_dtors_aux':
    crtstuff.c:(.text+0x52): dangerous relocation: unsupported relocation

Diff:
---
 bfd/elf32-arm.c                                           |  7 ++++++-
 ld/testsuite/ld-arm/arm-elf.exp                           |  1 +
 ld/testsuite/ld-arm/farcall-missing-type-main-undefweak.s | 10 ++++++++++
 ld/testsuite/ld-arm/farcall-missing-type-undefweak.d      | 11 +++++++++++
 4 files changed, 28 insertions(+), 1 deletion(-)

diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c
index 7441ee2cc38..17df8b30eb6 100644
--- a/bfd/elf32-arm.c
+++ b/bfd/elf32-arm.c
@@ -10512,7 +10512,12 @@ elf32_arm_final_link_relocate (reloc_howto_type *	    howto,
   if (using_thumb_only (globals)
       && (r_type == R_ARM_THM_CALL
 	  || r_type == R_ARM_THM_JUMP24)
-      && branch_type == ST_BRANCH_UNKNOWN)
+      && branch_type == ST_BRANCH_UNKNOWN
+      /* Exception to the rule above: a branch to an undefined weak
+	 symbol is turned into a jump to the next instruction unless a
+	 PLT entry will be created (see below).  */
+      && !(h && h->root.type == bfd_link_hash_undefweak
+	   && plt_offset == (bfd_vma) -1))
     {
       if (sym_sec != NULL
 	  && sym_sec->owner != NULL)
diff --git a/ld/testsuite/ld-arm/arm-elf.exp b/ld/testsuite/ld-arm/arm-elf.exp
index 5f380e383d0..7fa4520fb15 100644
--- a/ld/testsuite/ld-arm/arm-elf.exp
+++ b/ld/testsuite/ld-arm/arm-elf.exp
@@ -1208,6 +1208,7 @@ run_dump_test "attr-merge-wchar-42-nowarn"
 run_dump_test "attr-merge-wchar-44-nowarn"
 run_dump_test "farcall-section"
 run_dump_test "farcall-missing-type"
+run_dump_test "farcall-missing-type-undefweak"
 run_dump_test "attr-merge-unknown-1"
 run_dump_test "attr-merge-unknown-2"
 run_dump_test "attr-merge-unknown-2r"
diff --git a/ld/testsuite/ld-arm/farcall-missing-type-main-undefweak.s b/ld/testsuite/ld-arm/farcall-missing-type-main-undefweak.s
new file mode 100644
index 00000000000..cf72722144b
--- /dev/null
+++ b/ld/testsuite/ld-arm/farcall-missing-type-main-undefweak.s
@@ -0,0 +1,10 @@
+	.thumb
+	.cpu cortex-m33
+	.syntax unified
+	.global __start
+	.weak	bad
+	.type __start, function
+__start:
+	push	{r4, lr}
+	bl	bad
+	pop	{r4, pc}
diff --git a/ld/testsuite/ld-arm/farcall-missing-type-undefweak.d b/ld/testsuite/ld-arm/farcall-missing-type-undefweak.d
new file mode 100644
index 00000000000..b6e123fe1ab
--- /dev/null
+++ b/ld/testsuite/ld-arm/farcall-missing-type-undefweak.d
@@ -0,0 +1,11 @@
+#source: farcall-missing-type-main-undefweak.s
+#as:
+#ld:-T farcall-missing-type.ld
+#objdump: -dr
+#...
+Disassembly of section .text:
+
+.* <__start>:
+ +[0-9a-f]+:	.... .... 	push	{r4, lr}
+ +[0-9a-f]+:	.... .... 	nop.w
+ +[0-9a-f]+:	.... .... 	pop	{r4, pc}


More information about the Binutils-cvs mailing list