RISC-V: Report unresolved relocation error via linker's callback function.
authorJim Wilson <jimw@sifive.com>
Thu, 17 Oct 2019 22:38:27 +0000 (15:38 -0700)
committerJim Wilson <jimw@sifive.com>
Thu, 17 Oct 2019 22:38:27 +0000 (15:38 -0700)
Two patches from Nelson Chu.

It is better to use the linker's callback functions to handle the link time
error when relocating.  The unresolved relocation error can be regarded as
an unsupported relocation.  To make user easier to understand different errors,
we need to extend the current error message format of the callback function
since the format is fixed.

bfd/
* elfnn-riscv.c (riscv_elf_relocate_section): Use asprintf to extend
the error message if needed, and then store the result into the
`msg_buf`.  Finally, remember to free the unused `msg_buf`.  All error
message for the dangerous relocation should be set before we call the
callback function.  If we miss the error message since linker runs out
of memory, we should set the default error message for the error.

ld/
* testsuite/ld-riscv-elf/lib-nopic-01a.s: Create the shared library
lib-nopic-01a.so, it will be linked with lib-nopic-01b.s.
* testsuite/ld-riscv-elf/lib-nopic-01b.s: Add new test for the
unresolved relocation.  Link the non-pic code into a shared library
may cause the error.
* testsuite/ld-riscv-elf/lib-nopic-01b.d: Likewise.
* testsuite/ld-riscv-elf/ld-riscv-elf.exp: Run the new test only when
the shared library is supported.

R_RISCV_CALL, R_RISCV_JAL and R_RISCV_RVC_JUMP are pc-relative relocation.
For now, we do not allow the object with these relocation links into a shared
library since the referenced symbols may be loaded to the places that too far
from the pc.  We can improve the error message for these unsupported relocation
to notice user that they should recompile their code with `fPIC`.

bfd/
* elfnn-riscv.c (riscv_elf_relocate_section): Report the error message
that user should recompile their code with `fPIC` when linking non-pic
code into shared library.

ld/
* testsuite/ld-riscv-elf/lib-nopic-01b.d: Update the error message.

Change-Id: Ib3347a0a6fa1c2b20a9647c314d5bec2c322ff04

bfd/ChangeLog
bfd/elfnn-riscv.c
ld/ChangeLog
ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp
ld/testsuite/ld-riscv-elf/lib-nopic-01a.s [new file with mode: 0644]
ld/testsuite/ld-riscv-elf/lib-nopic-01b.d [new file with mode: 0644]
ld/testsuite/ld-riscv-elf/lib-nopic-01b.s [new file with mode: 0644]

index 74cdda4ffaaba8cf8ff172ac9b2e7860bb1d0fd7..b29b2ee98d1f923427692fcc6437dcce9ac0b7d0 100644 (file)
@@ -1,3 +1,16 @@
+2019-10-17  Nelson Chu  <nelson.chu@sifive.com>
+
+       * elfnn-riscv.c (riscv_elf_relocate_section): Report the error message
+       that user should recompile their code with `fPIC` when linking non-pic
+       code into shared library.
+
+       * elfnn-riscv.c (riscv_elf_relocate_section): Use asprintf to extend
+       the error message if needed, and then store the result into the
+       `msg_buf`.  Finally, remember to free the unused `msg_buf`.  All error
+       message for the dangerous relocation should be set before we call the
+       callback function.  If we miss the error message since linker runs out
+       of memory, we should set the default error message for the error.
+
 2019-10-16  Alan Modra  <amodra@gmail.com>
 
        PR 13616
index 4ffe6a36e68f6c6c8e2301627dceedfef908f2db..6be209e23989c62f85dcaaef11ae6ab05fba7b67 100644 (file)
@@ -1787,6 +1787,7 @@ riscv_elf_relocate_section (bfd *output_bfd,
       int r_type = ELFNN_R_TYPE (rel->r_info), tls_type;
       reloc_howto_type *howto = riscv_elf_rtype_to_howto (input_bfd, r_type);
       const char *msg = NULL;
+      char *msg_buf = NULL;
       bfd_boolean resolved_to_zero;
 
       if (howto == NULL
@@ -2088,6 +2089,7 @@ riscv_elf_relocate_section (bfd *output_bfd,
               || (h != NULL && h->type == STT_SECTION))
              && rel->r_addend)
            {
+             msg = _("%pcrel_lo section symbol with an addend");
              r = bfd_reloc_dangerous;
              break;
            }
@@ -2302,24 +2304,42 @@ riscv_elf_relocate_section (bfd *output_bfd,
          && _bfd_elf_section_offset (output_bfd, info, input_section,
                                      rel->r_offset) != (bfd_vma) -1)
        {
-         (*_bfd_error_handler)
-           (_("%pB(%pA+%#" PRIx64 "): "
-              "unresolvable %s relocation against symbol `%s'"),
-            input_bfd,
-            input_section,
-            (uint64_t) rel->r_offset,
-            howto->name,
-            h->root.root.string);
-
-         bfd_set_error (bfd_error_bad_value);
-         ret = FALSE;
-         goto out;
+         switch (r_type)
+           {
+           case R_RISCV_CALL:
+           case R_RISCV_JAL:
+           case R_RISCV_RVC_JUMP:
+             if (asprintf (&msg_buf,
+                           _("%%X%%P: relocation %s against `%s' can "
+                             "not be used when making a shared object; "
+                             "recompile with -fPIC\n"),
+                           howto->name,
+                           h->root.root.string) == -1)
+               msg_buf = NULL;
+             break;
+
+           default:
+             if (asprintf (&msg_buf,
+                           _("%%X%%P: unresolvable %s relocation against "
+                             "symbol `%s'\n"),
+                           howto->name,
+                           h->root.root.string) == -1)
+               msg_buf = NULL;
+             break;
+           }
+
+         msg = msg_buf;
+         r = bfd_reloc_notsupported;
        }
 
       if (r == bfd_reloc_ok)
        r = perform_relocation (howto, rel, relocation, input_section,
                                input_bfd, contents);
 
+      /* We should have already detected the error and set message before.
+        If the error message isn't set since the linker runs out of memory
+        or we don't set it before, then we should set the default message
+        with the "internal error" string here.  */
       switch (r)
        {
        case bfd_reloc_ok:
@@ -2338,17 +2358,21 @@ riscv_elf_relocate_section (bfd *output_bfd,
          break;
 
        case bfd_reloc_outofrange:
-         msg = _("%X%P: internal error: out of range error\n");
+         if (msg == NULL)
+           msg = _("%X%P: internal error: out of range error\n");
          break;
 
        case bfd_reloc_notsupported:
-         msg = _("%X%P: internal error: unsupported relocation error\n");
+         if (msg == NULL)
+           msg = _("%X%P: internal error: unsupported relocation error\n");
          break;
 
        case bfd_reloc_dangerous:
+         /* The error message should already be set.  */
+         if (msg == NULL)
+           msg = _("dangerous relocation error");
          info->callbacks->reloc_dangerous
-           (info, "%pcrel_lo section symbol with an addend", input_bfd,
-            input_section, rel->r_offset);
+           (info, msg, input_bfd, input_section, rel->r_offset);
          break;
 
        default:
@@ -2356,9 +2380,14 @@ riscv_elf_relocate_section (bfd *output_bfd,
          break;
        }
 
-      if (msg)
+      /* Do not report error message for the dangerous relocation again.  */
+      if (msg && r != bfd_reloc_dangerous)
        info->callbacks->einfo (msg);
 
+      /* Free the unused `msg_buf` if needed.  */
+      if (msg_buf)
+       free (msg_buf);
+
       /* We already reported the error via a callback, so don't try to report
         it again by returning false.  That leads to spurious errors.  */
       ret = TRUE;
index f51e6466e68e4604a14a5898da1ed4534d8f9cda..8fc2ceee9d0d6aafe3d423ad8be96b13b8640597 100644 (file)
@@ -1,3 +1,16 @@
+2019-10-17  Nelson Chu  <nelson.chu@sifive.com>
+
+       * testsuite/ld-riscv-elf/lib-nopic-01b.d: Update the error message.
+
+       * testsuite/ld-riscv-elf/lib-nopic-01a.s: Create the shared library
+       lib-nopic-01a.so, it will be linked with lib-nopic-01b.s.
+       * testsuite/ld-riscv-elf/lib-nopic-01b.s: Add new test for the
+       unresolved relocation.  Link the non-pic code into a shared library
+       may cause the error.
+       * testsuite/ld-riscv-elf/lib-nopic-01b.d: Likewise.
+       * testsuite/ld-riscv-elf/ld-riscv-elf.exp: Run the new test only when
+       the shared library is supported.
+
 2019-10-16  Alan Modra  <amodra@gmail.com>
 
        PR 13616
index c994a57c48ac2f2122b697001351aab96330a60a..0a7ac5945e856f2f7bd65c70e94566f982772d5e 100644 (file)
@@ -71,4 +71,11 @@ if [istarget "riscv*-*-*"] {
                                    [list "readelf --syms gp-test.sd"] \
                                    "gp-test-${abi}"]]
     }
+
+    run_ld_link_tests {
+       { "Link non-pic code into a shared library (setup)"
+           "-shared" "" "" {lib-nopic-01a.s}
+           {} "lib-nopic-01a.so" }
+    }
+    run_dump_test "lib-nopic-01b"
 }
diff --git a/ld/testsuite/ld-riscv-elf/lib-nopic-01a.s b/ld/testsuite/ld-riscv-elf/lib-nopic-01a.s
new file mode 100644 (file)
index 0000000..c95cda0
--- /dev/null
@@ -0,0 +1,9 @@
+        .option nopic
+       .text
+       .align  1
+       .globl  func1
+       .type   func1, @function
+func1:
+       call    func2
+       jr      ra
+       .size   func1, .-func1
diff --git a/ld/testsuite/ld-riscv-elf/lib-nopic-01b.d b/ld/testsuite/ld-riscv-elf/lib-nopic-01b.d
new file mode 100644 (file)
index 0000000..0d758a4
--- /dev/null
@@ -0,0 +1,5 @@
+#name: link non-pic code into a shared library
+#source: lib-nopic-01b.s
+#as:
+#ld: -shared tmpdir/lib-nopic-01a.so
+#error: .*relocation R_RISCV_CALL against `func1' can not be used when making a shared object; recompile with -fPIC
diff --git a/ld/testsuite/ld-riscv-elf/lib-nopic-01b.s b/ld/testsuite/ld-riscv-elf/lib-nopic-01b.s
new file mode 100644 (file)
index 0000000..97fe137
--- /dev/null
@@ -0,0 +1,9 @@
+        .option nopic
+       .text
+       .align  1
+       .globl  func2
+       .type   func2, @function
+func2:
+       call    func1
+       jr      ra
+       .size   func2, .-func2