From 75f03fa77434ad49f1e7d333e0c93048639806e3 Mon Sep 17 00:00:00 2001 From: Nelson Chu Date: Fri, 14 May 2021 13:30:02 +0800 Subject: RISC-V: Check the overflow for %pcrel_lo addend more strictly. The %pcrel_lo addend may causes the overflow, and need more than one %pcrel_hi values. But there may be only one auipc, shared by those %pcrel_lo with addends. However, the existing check method in the riscv_resolve_pcrel_lo_relocs, may not be able to work for some special/corner cases. Consider the testcases pcrel-lo-addend-2b. Before applying this patch, I can compile it successfully. But in fact the addend cause the value of %pcrel_hi to be different. This patch try to check the value of %pcrel_hi directly, to make sure it won't be changed. Otherwise, linker will report the following errors, (.text+0xa): dangerous relocation: %pcrel_lo overflow with an addend, the value of %pcrel_hi is 0x1000 without any addend, but may be 0x2000 after adding the %pcrel_lo addend The toolchain regressions, rv64gc-linux/rv64gc-elf/rv32gc-linux/rv32i-elf, pass expectedly and looks fine. bfd/ * elfnn-riscv.c (riscv_resolve_pcrel_lo_relocs): Check the values of %pcrel_hi, before and after adding the addend. Make sure the value won't be changed, otherwise, report dangerous error. ld/ * testsuite/ld-riscv-elf/ld-riscv-elf.exp: Updated. * testsuite/ld-riscv-elf/pcrel-lo-addend-2a.d: Renamed from pcrel-lo-addend-2. * testsuite/ld-riscv-elf/pcrel-lo-addend-2a.s: Likewise. * testsuite/ld-riscv-elf/pcrel-lo-addend-2b.d: New testcase. * testsuite/ld-riscv-elf/pcrel-lo-addend-2b.s: Likewise. --- bfd/elfnn-riscv.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) (limited to 'bfd/elfnn-riscv.c') diff --git a/bfd/elfnn-riscv.c b/bfd/elfnn-riscv.c index a944b330227..2068edebdb6 100644 --- a/bfd/elfnn-riscv.c +++ b/bfd/elfnn-riscv.c @@ -1883,13 +1883,23 @@ riscv_resolve_pcrel_lo_relocs (riscv_pcrel_relocs *p) riscv_pcrel_hi_reloc search = {r->addr, 0}; riscv_pcrel_hi_reloc *entry = htab_find (p->hi_relocs, &search); if (entry == NULL - /* Check for overflow into bit 11 when adding reloc addend. */ - || (!(entry->value & 0x800) - && ((entry->value + r->reloc->r_addend) & 0x800))) + /* Check the overflow when adding reloc addend. */ + || (RISCV_CONST_HIGH_PART (entry->value) + != RISCV_CONST_HIGH_PART (entry->value + r->reloc->r_addend))) { - char *string = (entry == NULL - ? "%pcrel_lo missing matching %pcrel_hi" - : "%pcrel_lo overflow with an addend"); + char *string; + if (entry == NULL) + string = _("%pcrel_lo missing matching %pcrel_hi"); + else if (asprintf (&string, + _("%%pcrel_lo overflow with an addend, the " + "value of %%pcrel_hi is 0x%" PRIx64 " without " + "any addend, but may be 0x%" PRIx64 " after " + "adding the %%pcrel_lo addend"), + (int64_t) RISCV_CONST_HIGH_PART (entry->value), + (int64_t) RISCV_CONST_HIGH_PART + (entry->value + r->reloc->r_addend)) == -1) + string = _("%pcrel_lo overflow with an addend"); + (*r->info->callbacks->reloc_dangerous) (r->info, string, input_bfd, r->input_section, r->reloc->r_offset); return true; -- cgit v1.2.3-65-gdbad