[binutils-gdb] LoongArch: overflow and underflow checks for R_LARCH_32_PCREL
liu zhensong
liuzhensong@sourceware.org
Mon May 26 06:59:55 GMT 2025
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=95d54e0c6e4c558e8f39c0167221e81b0eec6069
commit 95d54e0c6e4c558e8f39c0167221e81b0eec6069
Author: Lulu Cai <cailulu@loongson.cn>
Date: Tue May 20 19:38:12 2025 +0800
LoongArch: overflow and underflow checks for R_LARCH_32_PCREL
Relocation overflows can silently write incorrect value to
the file, so overflow checks are added to avoid this.
Diff:
---
bfd/elfnn-loongarch.c | 20 +++++++++++++++-----
bfd/elfxx-loongarch.c | 2 +-
ld/testsuite/ld-loongarch-elf/32_pcrel.s | 6 ++++++
ld/testsuite/ld-loongarch-elf/ld-loongarch-elf.exp | 2 ++
ld/testsuite/ld-loongarch-elf/overflow_32_pcrel.d | 4 ++++
ld/testsuite/ld-loongarch-elf/underflow_32_pcrel.d | 4 ++++
6 files changed, 32 insertions(+), 6 deletions(-)
diff --git a/bfd/elfnn-loongarch.c b/bfd/elfnn-loongarch.c
index faad512f339..5c504f2cad8 100644
--- a/bfd/elfnn-loongarch.c
+++ b/bfd/elfnn-loongarch.c
@@ -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;
}
diff --git a/bfd/elfxx-loongarch.c b/bfd/elfxx-loongarch.c
index 182617b38c1..6268c477feb 100644
--- a/bfd/elfxx-loongarch.c
+++ b/bfd/elfxx-loongarch.c
@@ -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
index 00000000000..3ef16debc8f
--- /dev/null
+++ b/ld/testsuite/ld-loongarch-elf/32_pcrel.s
@@ -0,0 +1,6 @@
+ .section sx,"a"
+x:
+ nop
+
+ .section sy,"a"
+ .4byte x-.
diff --git a/ld/testsuite/ld-loongarch-elf/ld-loongarch-elf.exp b/ld/testsuite/ld-loongarch-elf/ld-loongarch-elf.exp
index 0295be81562..2f09a69befb 100644
--- a/ld/testsuite/ld-loongarch-elf/ld-loongarch-elf.exp
+++ b/ld/testsuite/ld-loongarch-elf/ld-loongarch-elf.exp
@@ -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
index 00000000000..154dac9b286
--- /dev/null
+++ b/ld/testsuite/ld-loongarch-elf/overflow_32_pcrel.d
@@ -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
index 00000000000..a5396bc355f
--- /dev/null
+++ b/ld/testsuite/ld-loongarch-elf/underflow_32_pcrel.d
@@ -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'
More information about the Binutils-cvs
mailing list