From: Lulu Cai Date: Tue, 20 May 2025 11:38:12 +0000 (+0800) Subject: LoongArch: overflow and underflow checks for R_LARCH_32_PCREL X-Git-Tag: binutils-2_45~498 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=95d54e0c6e4c558e8f39c0167221e81b0eec6069;p=thirdparty%2Fbinutils-gdb.git 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 --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'