diff options
author | Nelson Chu <nelson.chu@sifive.com> | 2021-05-14 13:30:02 +0800 |
---|---|---|
committer | Nelson Chu <nelson.chu@sifive.com> | 2021-05-14 16:14:00 +0800 |
commit | 75f03fa77434ad49f1e7d333e0c93048639806e3 (patch) | |
tree | 255bbdb4f7134576323f89dd232753eb22fb6048 /bfd/elfnn-riscv.c | |
parent | ecf25064e87a3d2d59871b3ea7126fa0dee0001d (diff) | |
download | binutils-75f03fa77434ad49f1e7d333e0c93048639806e3.zip binutils-75f03fa77434ad49f1e7d333e0c93048639806e3.tar.gz binutils-75f03fa77434ad49f1e7d333e0c93048639806e3.tar.bz2 |
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.
Diffstat (limited to 'bfd/elfnn-riscv.c')
-rw-r--r-- | bfd/elfnn-riscv.c | 22 |
1 files changed, 16 insertions, 6 deletions
diff --git a/bfd/elfnn-riscv.c b/bfd/elfnn-riscv.c index a944b33..2068ede 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; |