Fix an illegal memory access triggered when trying to examine an input file containin...
[deliverable/binutils-gdb.git] / bfd / elfnn-riscv.c
index 4ffe6a36e68f6c6c8e2301627dceedfef908f2db..46f0100ace3da966ee94932df17cfc1721266451 100644 (file)
@@ -1,5 +1,5 @@
 /* RISC-V-specific support for NN-bit ELF.
-   Copyright (C) 2011-2019 Free Software Foundation, Inc.
+   Copyright (C) 2011-2020 Free Software Foundation, Inc.
 
    Contributed by Andrew Waterman (andrew@sifive.com).
    Based on TILE-Gx and MIPS targets.
@@ -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
@@ -1986,10 +1987,11 @@ riscv_elf_relocate_section (bfd *output_bfd,
          break;
 
        case R_RISCV_CALL:
+       case R_RISCV_CALL_PLT:
          /* Handle a call to an undefined weak function.  This won't be
             relaxed, so we have to handle it here.  */
          if (h != NULL && h->root.type == bfd_link_hash_undefweak
-             && h->plt.offset == MINUS_ONE)
+             && (!bfd_link_pic (info) || h->plt.offset == MINUS_ONE))
            {
              /* We can use x0 as the base register.  */
              bfd_vma insn = bfd_get_32 (input_bfd,
@@ -2002,9 +2004,9 @@ riscv_elf_relocate_section (bfd *output_bfd,
            }
          /* Fall through.  */
 
-       case R_RISCV_CALL_PLT:
        case R_RISCV_JAL:
        case R_RISCV_RVC_JUMP:
+         /* This line has to match the check in _bfd_riscv_relax_section.  */
          if (bfd_link_pic (info) && h != NULL && h->plt.offset != MINUS_ONE)
            {
              /* Refer to the PLT entry.  */
@@ -2088,6 +2090,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 +2305,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 +2359,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 +2381,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;
@@ -3465,9 +3495,16 @@ _bfd_riscv_relax_call (bfd *abfd, asection *sec, asection *sym_sec,
   int rd, r_type, len = 4, rvc = elf_elfheader (abfd)->e_flags & EF_RISCV_RVC;
 
   /* If the call crosses section boundaries, an alignment directive could
-     cause the PC-relative offset to later increase.  */
-  if (VALID_UJTYPE_IMM (foff) && sym_sec->output_section != sec->output_section)
-    foff += (foff < 0 ? -max_alignment : max_alignment);
+     cause the PC-relative offset to later increase, so we need to add in the
+     max alignment of any section inclusive from the call to the target.
+     Otherwise, we only need to use the alignment of the current section.  */
+  if (VALID_UJTYPE_IMM (foff))
+    {
+      if (sym_sec->output_section == sec->output_section
+         && sym_sec->output_section != bfd_abs_section_ptr)
+       max_alignment = (bfd_vma) 1 << sym_sec->output_section->alignment_power;
+      foff += (foff < 0 ? -max_alignment : max_alignment);
+    }
 
   /* See if this function call can be shortened.  */
   if (!VALID_UJTYPE_IMM (foff) && !(!bfd_link_pic (link_info) && near_zero))
@@ -4092,7 +4129,9 @@ _bfd_riscv_relax_section (bfd *abfd, asection *sec,
              undefined_weak = TRUE;
            }
 
-         if (h->plt.offset != MINUS_ONE)
+         /* This line has to match the check in riscv_elf_relocate_section
+            in the R_RISCV_CALL[_PLT] case.  */
+         if (bfd_link_pic (info) && h->plt.offset != MINUS_ONE)
            {
              sym_sec = htab->elf.splt;
              symval = h->plt.offset;
This page took 0.026083 seconds and 4 git commands to generate.