RISC-V: Check the overflow for %pcrel_lo addend more strictly.
authorNelson Chu <nelson.chu@sifive.com>
Fri, 14 May 2021 05:30:02 +0000 (13:30 +0800)
committerNelson Chu <nelson.chu@sifive.com>
Fri, 14 May 2021 08:14:00 +0000 (16:14 +0800)
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/ChangeLog
bfd/elfnn-riscv.c
ld/ChangeLog
ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp
ld/testsuite/ld-riscv-elf/pcrel-lo-addend-2.d [deleted file]
ld/testsuite/ld-riscv-elf/pcrel-lo-addend-2.s [deleted file]
ld/testsuite/ld-riscv-elf/pcrel-lo-addend-2a.d [new file with mode: 0644]
ld/testsuite/ld-riscv-elf/pcrel-lo-addend-2a.s [new file with mode: 0644]
ld/testsuite/ld-riscv-elf/pcrel-lo-addend-2b.d [new file with mode: 0644]
ld/testsuite/ld-riscv-elf/pcrel-lo-addend-2b.s [new file with mode: 0644]

index 8dbe40c474d406706e4126c0c69d63d5912b7f42..b399aefd120efcfa7e5ef3e5a946156ab26ddf31 100644 (file)
@@ -1,3 +1,9 @@
+2021-05-14  Nelson Chu  <nelson.chu@sifive.com>
+
+       * 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.
+
 2021-05-13  Nelson Chu  <nelson.chu@sifive.com>
 
        * elfxx-riscv.c (check_implicit_always): The check_func, always add
index a944b3302274700791a303187ab8083745741a3f..2068edebdb6aa98cd61f395460d58a2ab125ebbe 100644 (file)
@@ -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;
index e9aae885988b39d2716a20a0f3d88993091deaa0..3969b8c80fa288861976e4b43c047c3068ce4ae1 100644 (file)
@@ -1,3 +1,12 @@
+2021-05-14  Nelson Chu  <nelson.chu@sifive.com>
+
+       * 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.
+
 2021-05-13  Fangrui Song  <maskray@google.com>
 
        PR 27834
index f3ff95cf96ec79c24fedee5823805e32cc6f62ec..319ac7e2b836ee0cdc10a2bb08f8f538df9395a7 100644 (file)
@@ -85,7 +85,8 @@ if [istarget "riscv*-*-*"] {
     run_dump_test "c-lui-2"
     run_dump_test "disas-jalr"
     run_dump_test "pcrel-lo-addend"
-    run_dump_test "pcrel-lo-addend-2"
+    run_dump_test "pcrel-lo-addend-2a"
+    run_dump_test "pcrel-lo-addend-2b"
     run_dump_test "restart-relax"
     run_dump_test "attr-merge-arch-01"
     run_dump_test "attr-merge-arch-02"
diff --git a/ld/testsuite/ld-riscv-elf/pcrel-lo-addend-2.d b/ld/testsuite/ld-riscv-elf/pcrel-lo-addend-2.d
deleted file mode 100644 (file)
index 895c6cc..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-#name: %pcrel_lo overflow with an addend
-#source: pcrel-lo-addend-2.s
-#as: -march=rv32ic
-#ld: -m[riscv_choose_ilp32_emul] --no-relax
-#error: .*dangerous relocation: %pcrel_lo overflow with an addend
diff --git a/ld/testsuite/ld-riscv-elf/pcrel-lo-addend-2.s b/ld/testsuite/ld-riscv-elf/pcrel-lo-addend-2.s
deleted file mode 100644 (file)
index b7f8212..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-       .text
-       .globl _start
-       .align 3
-_start:
-       nop
-       .LA0: auipc     a5,%pcrel_hi(ll)
-       lw      a0,%pcrel_lo(.LA0)(a5)
-       lw      a0,%pcrel_lo(.LA0+4)(a5)
-       ret
-       .globl ll
-       .data
-       .align 3
-       .zero 2024
-ll:
-       .word 0
-       .word 0
diff --git a/ld/testsuite/ld-riscv-elf/pcrel-lo-addend-2a.d b/ld/testsuite/ld-riscv-elf/pcrel-lo-addend-2a.d
new file mode 100644 (file)
index 0000000..cd50cbf
--- /dev/null
@@ -0,0 +1,5 @@
+#name: %pcrel_lo overflow with an addend (2a)
+#source: pcrel-lo-addend-2a.s
+#as: -march=rv32ic
+#ld: -m[riscv_choose_ilp32_emul] --no-relax
+#error: .*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
diff --git a/ld/testsuite/ld-riscv-elf/pcrel-lo-addend-2a.s b/ld/testsuite/ld-riscv-elf/pcrel-lo-addend-2a.s
new file mode 100644 (file)
index 0000000..1e36774
--- /dev/null
@@ -0,0 +1,16 @@
+       .text
+       .globl _start
+       .align 3
+_start:
+       nop
+       .LA0: auipc     a5,%pcrel_hi(ll)
+       lw      a0,%pcrel_lo(.LA0)(a5)
+       lw      a0,%pcrel_lo(.LA0+0x4)(a5)
+       ret
+       .globl ll
+       .data
+       .align 3
+       .zero 2024
+ll:
+       .word 0
+       .word 0
diff --git a/ld/testsuite/ld-riscv-elf/pcrel-lo-addend-2b.d b/ld/testsuite/ld-riscv-elf/pcrel-lo-addend-2b.d
new file mode 100644 (file)
index 0000000..d20f8c1
--- /dev/null
@@ -0,0 +1,5 @@
+#name: %pcrel_lo overflow with an addend (2b)
+#source: pcrel-lo-addend-2b.s
+#as: -march=rv32ic
+#ld: -m[riscv_choose_ilp32_emul] --no-relax
+#error: .*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
diff --git a/ld/testsuite/ld-riscv-elf/pcrel-lo-addend-2b.s b/ld/testsuite/ld-riscv-elf/pcrel-lo-addend-2b.s
new file mode 100644 (file)
index 0000000..9fd063f
--- /dev/null
@@ -0,0 +1,16 @@
+       .text
+       .globl _start
+       .align 3
+_start:
+       nop
+       .LA0: auipc     a5,%pcrel_hi(ll)
+       lw      a0,%pcrel_lo(.LA0)(a5)
+       lw      a0,%pcrel_lo(.LA0+0x1000)(a5)
+       ret
+       .globl ll
+       .data
+       .align 3
+       .zero 2024
+ll:
+       .word 0
+       .word 0