[binutils-gdb] LoongArch: Allow R_LARCH_PCALA_HI20 or R_LARCH_PCREL20_S2 against undefined weak symbols for static

liu & zhensong liuzhensong@sourceware.org
Fri Dec 27 09:53:52 GMT 2024


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

commit c1a964051be5471d91bfe7655155948ab9c653f8
Author: Xi Ruoyao <xry111@xry111.site>
Date:   Wed Dec 25 12:41:44 2024 +0800

    LoongArch: Allow R_LARCH_PCALA_HI20 or R_LARCH_PCREL20_S2 against undefined weak symbols for static PIE
    
    In a static PIE, undefined weak symbols should be just resolved to
    runtime address 0, like those symbols with non-default visibility.  This
    was silently broken in all prior Binutils releases with "-static-pie
    -mdirect-extern-access":
    
        $ cat t.c
        int x (void) __attribute__ ((weak));
    
        int
        main (void)
        {
          __builtin_printf("%p\n", x);
        }
        $ gcc t.c -static-pie -mdirect-extern-access
        $ ./a.out
        0x7ffff1d64000
    
    Since commit 4cb77761d687 ("LoongArch: Check PC-relative relocations for
    shared libraries), the situation has been improved: the linker errors
    out instead of silently producing a wrong output file.
    
    But logically, using -mdirect-extern-access for a static PIE perfectly
    makes sense, and we should not prevent that even if the programmer uses
    weak symbols.  Linux kernel is such an example, and Linux < 6.10 now
    fails to build with Binutils trunk.  (The silent breakage with prior
    Binutils releases was "benign" due to some blind luck.)
    
    While since the 6.10 release Linux has removed those potentially
    undefined weak symbols (due to performance issue), we still should
    support weak symbols in -mdirect-extern-access -static-pie and unbreak
    building old kernels.
    
    Link: https://lore.kernel.org/loongarch/20241206085810.112341-1-chenhuacai@loongson.cn/
    Signed-off-by: Xi Ruoyao <xry111@xry111.site>

Diff:
---
 bfd/elfnn-loongarch.c                              | 27 ++++++++++++++--------
 ld/testsuite/ld-loongarch-elf/ld-loongarch-elf.exp |  1 +
 .../ld-loongarch-elf/weak-undef-static-pie.d       | 13 +++++++++++
 .../ld-loongarch-elf/weak-undef-static-pie.s       |  8 +++++++
 4 files changed, 40 insertions(+), 9 deletions(-)

diff --git a/bfd/elfnn-loongarch.c b/bfd/elfnn-loongarch.c
index 4cf1512cefe..9d3c0eef5e3 100644
--- a/bfd/elfnn-loongarch.c
+++ b/bfd/elfnn-loongarch.c
@@ -1096,12 +1096,16 @@ loongarch_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
 
 	/* Since shared library global symbols interpose, any
 	   PC-relative relocations against external symbols
-	   should not be used to build shared libraries.  */
+	   should not be used to build shared libraries.
+	   In static PIE undefined weak symbols may be allowed
+	   by rewriting pcaddi to addi.w if addend is in [-2048, 2048).  */
 	case R_LARCH_PCREL20_S2:
 	  if (bfd_link_pic (info)
 	      && (sec->flags & SEC_ALLOC) != 0
 	      && (sec->flags & SEC_READONLY) != 0
-	      && ! LARCH_REF_LOCAL (info, h))
+	      && ! LARCH_REF_LOCAL (info, h)
+	      && (!info->nointerp
+		  || h->root.type != bfd_link_hash_undefweak))
 	    return bad_static_reloc (info, abfd, rel, sec, r_type, h, NULL);
 
 	  break;
@@ -1124,12 +1128,16 @@ loongarch_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
 	    }
 
 	  /* PC-relative relocations are allowed For first version
-	     medium cmodel function call.  */
+	     medium cmodel function call.  Those against undefined
+	     weak symbol are allowed for static PIE by rewritting
+	     pcalau12i to lu12i.w.  */
 	  if (h != NULL && !h->needs_plt
 	      && bfd_link_pic (info)
 	      && (sec->flags & SEC_ALLOC) != 0
 	      && (sec->flags & SEC_READONLY) != 0
-	      && ! LARCH_REF_LOCAL (info, h))
+	      && ! LARCH_REF_LOCAL (info, h)
+	      && (!info->nointerp
+		  || h->root.type != bfd_link_hash_undefweak))
 	    return bad_static_reloc (info, abfd, rel, sec, r_type, h, NULL);
 
 	  break;
@@ -4113,12 +4121,13 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 	case R_LARCH_PCALA_HI20:
 	  unresolved_reloc = false;
 
-	  /* If sym is hidden undefined weak, (sym + addend) should be
-	     resolved to runtime address (0 + addend).  */
+	  /* If sym is undef weak and it's hidden or we are doing a static
+	     link, (sym + addend) should be resolved to runtime address
+	     (0 + addend).  */
 	  resolve_pcrel_undef_weak =
-	    (is_undefweak
-	     && h
-	     && ELF_ST_VISIBILITY (h->other) != STV_DEFAULT);
+	    ((info->nointerp
+	      || (h && ELF_ST_VISIBILITY (h->other) != STV_DEFAULT))
+	     && is_undefweak);
 
 	  if (resolve_pcrel_undef_weak)
 	    pc = 0;
diff --git a/ld/testsuite/ld-loongarch-elf/ld-loongarch-elf.exp b/ld/testsuite/ld-loongarch-elf/ld-loongarch-elf.exp
index 35a3a4fc430..0b609c0245b 100644
--- a/ld/testsuite/ld-loongarch-elf/ld-loongarch-elf.exp
+++ b/ld/testsuite/ld-loongarch-elf/ld-loongarch-elf.exp
@@ -196,6 +196,7 @@ if [istarget "loongarch64-*-*"] {
     run_dump_test "relr-text-pie"
     run_dump_test "abssym_pie"
     run_dump_test "weak-undef-hidden-pie"
+    run_dump_test "weak-undef-static-pie"
   }
 
   run_dump_test "max_imm_b16"
diff --git a/ld/testsuite/ld-loongarch-elf/weak-undef-static-pie.d b/ld/testsuite/ld-loongarch-elf/weak-undef-static-pie.d
new file mode 100644
index 00000000000..d95aa122fce
--- /dev/null
+++ b/ld/testsuite/ld-loongarch-elf/weak-undef-static-pie.d
@@ -0,0 +1,13 @@
+#ld: -static -pie --no-dynamic-linker -z text -Ttext=0x1111222233334ff0
+#objdump: -d
+
+#...
+1111222233334ff0:[ 	]+159999a4[ 	]+lu12i.w[ 	]+\$a0,[ 	]+-209715
+1111222233334ff4:[ 	]+02f77405[ 	]+li.d[ 	]+\$a1,[ 	]+-547
+1111222233334ff8:[ 	]+17777765[ 	]+lu32i.d[ 	]+\$a1,[ 	]+-279621
+1111222233334ffc:[ 	]+032aa8a5[ 	]+lu52i.d[ 	]+\$a1,[ 	]+\$a1,[ 	]+-1366
+1111222233335000:[ 	]+00109484[ 	]+add.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+\$a1
+1111222233335004:[ 	]+029ffc06[ 	]+li.w[ 	]+\$a2,[ 	]+2047
+1111222233335008:[ 	]+02a00007[ 	]+li.w[ 	]+\$a3,[ 	]+-2048
+111122223333500c:[ 	]+4c000020[ 	]+ret
+#pass
diff --git a/ld/testsuite/ld-loongarch-elf/weak-undef-static-pie.s b/ld/testsuite/ld-loongarch-elf/weak-undef-static-pie.s
new file mode 100644
index 00000000000..d6b2c7a6c20
--- /dev/null
+++ b/ld/testsuite/ld-loongarch-elf/weak-undef-static-pie.s
@@ -0,0 +1,8 @@
+.weak undef
+
+.globl _start
+_start:
+  la.pcrel $a0, $a1, undef + 0xaaabbbbbcccccddd
+  pcaddi   $a2, undef + 0x7ff
+  pcaddi   $a3, undef - 0x800
+  ret


More information about the Binutils-cvs mailing list