]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
arm: Handle undefweak with ST_BRANCH_UNKNOWN
authorChristophe Lyon <christophe.lyon@linaro.org>
Fri, 6 Sep 2024 17:10:02 +0000 (17:10 +0000)
committerChristophe Lyon <christophe.lyon@linaro.org>
Wed, 11 Sep 2024 15:34:32 +0000 (15:34 +0000)
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

bfd/elf32-arm.c
ld/testsuite/ld-arm/arm-elf.exp
ld/testsuite/ld-arm/farcall-missing-type-main-undefweak.s [new file with mode: 0644]
ld/testsuite/ld-arm/farcall-missing-type-undefweak.d [new file with mode: 0644]

index 7441ee2cc38a9ac08d228a67bb077a07de63bfab..17df8b30eb63f821c1c0db047d7d3484cd07ca1d 100644 (file)
@@ -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)
index 5f380e383d04b802b75bbfb9360c9c3f71411e9f..7fa4520fb15c9dc57d84414c2788ba9e977cda1b 100644 (file)
@@ -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 (file)
index 0000000..cf72722
--- /dev/null
@@ -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 (file)
index 0000000..b6e123f
--- /dev/null
@@ -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}