aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristophe Lyon <christophe.lyon@linaro.org>2024-09-06 17:10:02 +0000
committerChristophe Lyon <christophe.lyon@linaro.org>2024-09-11 15:34:32 +0000
commita77ccc81295f41b72f96db000d1aa44e4dc91254 (patch)
treefe8e072af55498a7d07c80b9c601bf6c0e7ea6fe
parent1628e02267448cd82e219a60a4ed37cfa18fd35a (diff)
downloadgdb-a77ccc81295f41b72f96db000d1aa44e4dc91254.zip
gdb-a77ccc81295f41b72f96db000d1aa44e4dc91254.tar.gz
gdb-a77ccc81295f41b72f96db000d1aa44e4dc91254.tar.bz2
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
-rw-r--r--bfd/elf32-arm.c7
-rw-r--r--ld/testsuite/ld-arm/arm-elf.exp1
-rw-r--r--ld/testsuite/ld-arm/farcall-missing-type-main-undefweak.s10
-rw-r--r--ld/testsuite/ld-arm/farcall-missing-type-undefweak.d11
4 files changed, 28 insertions, 1 deletions
diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c
index 7441ee2..17df8b3 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 5f380e3..7fa4520 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 0000000..cf72722
--- /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 0000000..b6e123f
--- /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}