]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
LoongArch: overflow and underflow checks for R_LARCH_32_PCREL
authorLulu Cai <cailulu@loongson.cn>
Tue, 20 May 2025 11:38:12 +0000 (19:38 +0800)
committercailulu <cailulu@loongson.cn>
Mon, 26 May 2025 06:59:42 +0000 (14:59 +0800)
Relocation overflows can silently write incorrect value to
the file, so overflow checks are added to avoid this.

bfd/elfnn-loongarch.c
bfd/elfxx-loongarch.c
ld/testsuite/ld-loongarch-elf/32_pcrel.s [new file with mode: 0644]
ld/testsuite/ld-loongarch-elf/ld-loongarch-elf.exp
ld/testsuite/ld-loongarch-elf/overflow_32_pcrel.d [new file with mode: 0644]
ld/testsuite/ld-loongarch-elf/underflow_32_pcrel.d [new file with mode: 0644]

index faad512f3396b09fdd8106daca0cd455b5a5cff2..5c504f2cad8990535ec804fdc7862d2ca6585b15 100644 (file)
@@ -2933,11 +2933,21 @@ perform_relocation (const Elf_Internal_Rela *rel, asection *input_section,
       {
        value -= sec_addr (input_section) + rel->r_offset;
        value += rel->r_addend;
-       bfd_vma word = bfd_get (howto->bitsize, input_bfd,
-                               contents + rel->r_offset);
-       word = (word & ~howto->dst_mask) | (value & howto->dst_mask);
-       bfd_put (howto->bitsize, input_bfd, word, contents + rel->r_offset);
-       r = bfd_reloc_ok;
+       /* Check overflow.  */
+       if (ELFNN_R_TYPE (rel->r_info) == R_LARCH_32_PCREL)
+         {
+           r = loongarch_reloc_rewrite_imm_insn (rel, input_section,
+                                                 howto, input_bfd,
+                                                 contents, value);
+         }
+       else
+         {
+           bfd_vma word = bfd_get (howto->bitsize, input_bfd,
+                                   contents + rel->r_offset);
+           word = (word & ~howto->dst_mask) | (value & howto->dst_mask);
+           bfd_put (howto->bitsize, input_bfd, word, contents + rel->r_offset);
+           r = bfd_reloc_ok;
+         }
        break;
       }
 
index 182617b38c1071dd0ffa2cb34d8f089520c870a2..6268c477feb176d0442407efe7625c356424f3a1 100644 (file)
@@ -1390,7 +1390,7 @@ static loongarch_reloc_howto_type loongarch_howto_table[] =
         0xffffffff,                            /* dst_mask */
         false,                                 /* pcrel_offset */
         BFD_RELOC_LARCH_32_PCREL,              /* bfd_reloc_code_real_type */
-        NULL,                                  /* adjust_reloc_bits */
+        reloc_sign_bits,                       /* adjust_reloc_bits */
         NULL),                                 /* larch_reloc_type_name */
 
   /* The paired relocation may be relaxed.  */
diff --git a/ld/testsuite/ld-loongarch-elf/32_pcrel.s b/ld/testsuite/ld-loongarch-elf/32_pcrel.s
new file mode 100644 (file)
index 0000000..3ef16de
--- /dev/null
@@ -0,0 +1,6 @@
+       .section sx,"a"
+x:
+       nop
+
+       .section sy,"a"
+       .4byte x-.
index 0295be815623cf0af167f5acf8f56449fca35531..2f09a69befb820a0c586ecb757461c4363ae8e9d 100644 (file)
@@ -200,6 +200,8 @@ if [istarget "loongarch64-*-*"] {
     run_dump_test "bad_pcrel20_s2_global"
     run_dump_test "bad_pcrel20_s2_weak"
     run_dump_test "weak-undef-hidden-shared"
+    run_dump_test "overflow_32_pcrel"
+    run_dump_test "underflow_32_pcrel"
   }
 
   if [check_pie_support] {
diff --git a/ld/testsuite/ld-loongarch-elf/overflow_32_pcrel.d b/ld/testsuite/ld-loongarch-elf/overflow_32_pcrel.d
new file mode 100644 (file)
index 0000000..154dac9
--- /dev/null
@@ -0,0 +1,4 @@
+#source: 32_pcrel.s
+#as: -mthin-add-sub
+#ld: -shared --section-start=sx=0x80001000 --section-start=sy=0x1000
+#error: .*relocation truncated to fit: R_LARCH_32_PCREL against `x'
diff --git a/ld/testsuite/ld-loongarch-elf/underflow_32_pcrel.d b/ld/testsuite/ld-loongarch-elf/underflow_32_pcrel.d
new file mode 100644 (file)
index 0000000..a5396bc
--- /dev/null
@@ -0,0 +1,4 @@
+#source: 32_pcrel.s
+#as: -mthin-add-sub
+#ld: -shared --section-start=sx=0x1000 --section-start=sy=0x80001001
+#error: .*relocation truncated to fit: R_LARCH_32_PCREL against `x'