diff --git a/bfd/elfnn-loongarch.c b/bfd/elfnn-loongarch.c
index b657ddc5666..5d252bcccb9 100644
--- a/bfd/elfnn-loongarch.c
+++ b/bfd/elfnn-loongarch.c
@@ -1101,12 +1101,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;
@@ -1129,12 +1133,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;
@@ -4118,12 +4126,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 c09815703d5..e5fbe35c4fd 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
