Allow BFD to recognize macOS universal libraries
[deliverable/binutils-gdb.git] / bfd / elfnn-riscv.c
index 47d2c477036c909c799b7f452d4acba2b8145977..934704a87e78604b526f1a7c8f138a471bb46c5b 100644 (file)
@@ -1,5 +1,5 @@
 /* RISC-V-specific support for NN-bit ELF.
-   Copyright (C) 2011-2017 Free Software Foundation, Inc.
+   Copyright (C) 2011-2018 Free Software Foundation, Inc.
 
    Contributed by Andrew Waterman (andrew@sifive.com).
    Based on TILE-Gx and MIPS targets.
 #define ELF_MAXPAGESIZE                        0x1000
 #define ELF_COMMONPAGESIZE             0x1000
 
-/* The RISC-V linker needs to keep track of the number of relocs that it
-   decides to copy as dynamic relocs in check_relocs for each symbol.
-   This is so that it can later discard them if they are found to be
-   unnecessary.  We store the information in a field extending the
-   regular ELF linker hash table.  */
-
-struct riscv_elf_dyn_relocs
-{
-  struct riscv_elf_dyn_relocs *next;
-
-  /* The input section of the reloc.  */
-  asection *sec;
-
-  /* Total number of relocs copied for the input section.  */
-  bfd_size_type count;
-
-  /* Number of pc-relative relocs copied for the input section.  */
-  bfd_size_type pc_count;
-};
-
 /* RISC-V ELF linker hash entry.  */
 
 struct riscv_elf_link_hash_entry
@@ -82,7 +62,7 @@ struct riscv_elf_link_hash_entry
   struct elf_link_hash_entry elf;
 
   /* Track dynamic relocs copied for this symbol.  */
-  struct riscv_elf_dyn_relocs *dyn_relocs;
+  struct elf_dyn_relocs *dyn_relocs;
 
 #define GOT_UNKNOWN     0
 #define GOT_NORMAL      1
@@ -141,12 +121,13 @@ struct riscv_elf_link_hash_table
   (elf_hash_table_id ((struct elf_link_hash_table *) ((p)->hash)) \
   == RISCV_ELF_DATA ? ((struct riscv_elf_link_hash_table *) ((p)->hash)) : NULL)
 
-static void
-riscv_info_to_howto_rela (bfd *abfd ATTRIBUTE_UNUSED,
+static bfd_boolean
+riscv_info_to_howto_rela (bfd *abfd,
                          arelent *cache_ptr,
                          Elf_Internal_Rela *dst)
 {
-  cache_ptr->howto = riscv_elf_rtype_to_howto (ELFNN_R_TYPE (dst->r_info));
+  cache_ptr->howto = riscv_elf_rtype_to_howto (abfd, ELFNN_R_TYPE (dst->r_info));
+  return cache_ptr->howto != NULL;
 }
 
 static void
@@ -195,13 +176,13 @@ riscv_make_plt_header (bfd_vma gotplt_addr, bfd_vma addr, uint32_t *entry)
   bfd_vma gotplt_offset_low = RISCV_PCREL_LOW_PART (gotplt_addr, addr);
 
   /* auipc  t2, %hi(.got.plt)
-     sub    t1, t1, t3               # shifted .got.plt offset + hdr size + 12
+     sub    t1, t1, t3              # shifted .got.plt offset + hdr size + 12
      l[w|d] t3, %lo(.got.plt)(t2)    # _dl_runtime_resolve
      addi   t1, t1, -(hdr size + 12) # shifted .got.plt offset
      addi   t0, t2, %lo(.got.plt)    # &.got.plt
      srli   t1, t1, log2(16/PTRSIZE) # .got.plt offset
-     l[w|d] t0, PTRSIZE(t0)          # link map
-     jr     t3 */
+     l[w|d] t0, PTRSIZE(t0)         # link map
+     jr            t3 */
 
   entry[0] = RISCV_UTYPE (AUIPC, X_T2, gotplt_offset_high);
   entry[1] = RISCV_RTYPE (SUB, X_T1, X_T1, X_T3);
@@ -398,14 +379,14 @@ riscv_elf_copy_indirect_symbol (struct bfd_link_info *info,
     {
       if (edir->dyn_relocs != NULL)
        {
-         struct riscv_elf_dyn_relocs **pp;
-         struct riscv_elf_dyn_relocs *p;
+         struct elf_dyn_relocs **pp;
+         struct elf_dyn_relocs *p;
 
          /* Add reloc counts against the indirect sym to the direct sym
             list.  Merge any entries against the same section.  */
          for (pp = &eind->dyn_relocs; (p = *pp) != NULL; )
            {
-             struct riscv_elf_dyn_relocs *q;
+             struct elf_dyn_relocs *q;
 
              for (q = edir->dyn_relocs; q != NULL; q = q->next)
                if (q->sec == p->sec)
@@ -444,7 +425,7 @@ riscv_elf_record_tls_type (bfd *abfd, struct elf_link_hash_entry *h,
   if ((*new_tls_type & GOT_NORMAL) && (*new_tls_type & ~GOT_NORMAL))
     {
       (*_bfd_error_handler)
-       (_("%B: `%s' accessed both as normal and thread local symbol"),
+       (_("%pB: `%s' accessed both as normal and thread local symbol"),
         abfd, h ? h->root.root.string : "<local>");
       return FALSE;
     }
@@ -487,11 +468,13 @@ riscv_elf_record_got_reference (bfd *abfd, struct bfd_link_info *info,
 static bfd_boolean
 bad_static_reloc (bfd *abfd, unsigned r_type, struct elf_link_hash_entry *h)
 {
+  reloc_howto_type * r = riscv_elf_rtype_to_howto (abfd, r_type);
+
   (*_bfd_error_handler)
-    (_("%B: relocation %s against `%s' can not be used when making a shared "
+    (_("%pB: relocation %s against `%s' can not be used when making a shared "
        "object; recompile with -fPIC"),
-      abfd, riscv_elf_rtype_to_howto (r_type)->name,
-      h != NULL ? h->root.root.string : "a local symbol");
+     abfd, r ? r->name : _("<unknown>"),
+     h != NULL ? h->root.root.string : "a local symbol");
   bfd_set_error (bfd_error_bad_value);
   return FALSE;
 }
@@ -530,7 +513,7 @@ riscv_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
 
       if (r_symndx >= NUM_SHDR_ENTRIES (symtab_hdr))
        {
-         (*_bfd_error_handler) (_("%B: bad symbol index: %d"),
+         (*_bfd_error_handler) (_("%pB: bad symbol index: %d"),
                                 abfd, r_symndx);
          return FALSE;
        }
@@ -644,9 +627,11 @@ riscv_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
             may need to keep relocations for symbols satisfied by a
             dynamic library if we manage to avoid copy relocs for the
             symbol.  */
+         reloc_howto_type * r = riscv_elf_rtype_to_howto (abfd, r_type);
+
          if ((bfd_link_pic (info)
               && (sec->flags & SEC_ALLOC) != 0
-              && (! riscv_elf_rtype_to_howto (r_type)->pc_relative
+              && ((r != NULL && ! r->pc_relative)
                   || (h != NULL
                       && (! info->symbolic
                           || h->root.type == bfd_link_hash_defweak
@@ -657,8 +642,8 @@ riscv_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
                  && (h->root.type == bfd_link_hash_defweak
                      || !h->def_regular)))
            {
-             struct riscv_elf_dyn_relocs *p;
-             struct riscv_elf_dyn_relocs **head;
+             struct elf_dyn_relocs *p;
+             struct elf_dyn_relocs **head;
 
              /* When creating a shared object, we must copy these
                 relocs into the output file.  We create a reloc
@@ -697,14 +682,14 @@ riscv_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
                    s = sec;
 
                  vpp = &elf_section_data (s)->local_dynrel;
-                 head = (struct riscv_elf_dyn_relocs **) vpp;
+                 head = (struct elf_dyn_relocs **) vpp;
                }
 
              p = *head;
              if (p == NULL || p->sec != sec)
                {
                  bfd_size_type amt = sizeof *p;
-                 p = ((struct riscv_elf_dyn_relocs *)
+                 p = ((struct elf_dyn_relocs *)
                       bfd_alloc (htab->elf.dynobj, amt));
                  if (p == NULL)
                    return FALSE;
@@ -716,7 +701,7 @@ riscv_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
                }
 
              p->count += 1;
-             p->pc_count += riscv_elf_rtype_to_howto (r_type)->pc_relative;
+             p->pc_count += r == NULL ? 0 : r->pc_relative;
            }
 
          break;
@@ -762,7 +747,7 @@ riscv_elf_gc_mark_hook (asection *sec,
 static asection *
 readonly_dynrelocs (struct elf_link_hash_entry *h)
 {
-  struct riscv_elf_dyn_relocs *p;
+  struct elf_dyn_relocs *p;
 
   for (p = riscv_elf_hash_entry (h)->dyn_relocs; p != NULL; p = p->next)
     {
@@ -786,7 +771,6 @@ riscv_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
 {
   struct riscv_elf_link_hash_table *htab;
   struct riscv_elf_link_hash_entry * eh;
-  struct riscv_elf_dyn_relocs *p;
   bfd *dynobj;
   asection *s, *srel;
 
@@ -861,17 +845,9 @@ riscv_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
       return TRUE;
     }
 
-  eh = (struct riscv_elf_link_hash_entry *) h;
-  for (p = eh->dyn_relocs; p != NULL; p = p->next)
-    {
-      s = p->sec->output_section;
-      if (s != NULL && (s->flags & SEC_READONLY) != 0)
-       break;
-    }
-
-  /* If we didn't find any dynamic relocs in read-only sections, then
+  /* If we don't find any dynamic relocs in read-only sections, then
      we'll be keeping the dynamic relocs and avoiding the copy reloc.  */
-  if (p == NULL)
+  if (!readonly_dynrelocs (h))
     {
       h->non_got_ref = 0;
       return TRUE;
@@ -891,6 +867,7 @@ riscv_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
      to copy the initial value out of the dynamic object and into the
      runtime process image.  We need to remember the offset into the
      .rel.bss section we are going to use.  */
+  eh = (struct riscv_elf_link_hash_entry *) h;
   if (eh->tls_type & ~GOT_NORMAL)
     {
       s = htab->sdyntdata;
@@ -924,7 +901,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
   struct bfd_link_info *info;
   struct riscv_elf_link_hash_table *htab;
   struct riscv_elf_link_hash_entry *eh;
-  struct riscv_elf_dyn_relocs *p;
+  struct elf_dyn_relocs *p;
 
   if (h->root.type == bfd_link_hash_indirect)
     return TRUE;
@@ -1024,7 +1001,8 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
       else
        {
          s->size += RISCV_ELF_WORD_BYTES;
-         if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, bfd_link_pic (info), h))
+         if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, bfd_link_pic (info), h)
+             && ! UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))
            htab->elf.srelgot->size += sizeof (ElfNN_External_Rela);
        }
     }
@@ -1045,7 +1023,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
     {
       if (SYMBOL_CALLS_LOCAL (info, h))
        {
-         struct riscv_elf_dyn_relocs **pp;
+         struct elf_dyn_relocs **pp;
 
          for (pp = &eh->dyn_relocs; (p = *pp) != NULL; )
            {
@@ -1063,7 +1041,8 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
       if (eh->dyn_relocs != NULL
          && h->root.type == bfd_link_hash_undefweak)
        {
-         if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
+         if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
+             || UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))
            eh->dyn_relocs = NULL;
 
          /* Make sure undefined weak symbols are output as a dynamic
@@ -1137,7 +1116,7 @@ maybe_set_textrel (struct elf_link_hash_entry *h, void *info_p)
 
       info->flags |= DF_TEXTREL;
       info->callbacks->minfo
-       (_("%B: dynamic relocation against `%T' in read-only section `%A'\n"),
+       (_("%pB: dynamic relocation against `%pT' in read-only section `%pA'\n"),
         sec->owner, h->root.root.string, sec);
 
       /* Not an error, just cut short the traversal.  */
@@ -1187,7 +1166,7 @@ riscv_elf_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
 
       for (s = ibfd->sections; s != NULL; s = s->next)
        {
-         struct riscv_elf_dyn_relocs *p;
+         struct elf_dyn_relocs *p;
 
          for (p = elf_section_data (s)->local_dynrel; p != NULL; p = p->next)
            {
@@ -1529,14 +1508,14 @@ typedef struct
 
 typedef struct riscv_pcrel_lo_reloc
 {
-  asection *                     input_section;
-  struct bfd_link_info *         info;
-  reloc_howto_type *             howto;
-  const Elf_Internal_Rela *      reloc;
-  bfd_vma                        addr;
-  const char *                   name;
-  bfd_byte *                     contents;
-  struct riscv_pcrel_lo_reloc *  next;
+  asection *                    input_section;
+  struct bfd_link_info *        info;
+  reloc_howto_type *            howto;
+  const Elf_Internal_Rela *     reloc;
+  bfd_vma                       addr;
+  const char *                  name;
+  bfd_byte *                    contents;
+  struct riscv_pcrel_lo_reloc *         next;
 } riscv_pcrel_lo_reloc;
 
 typedef struct
@@ -1672,12 +1651,12 @@ 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)
-        {
+       {
          ((*r->info->callbacks->reloc_overflow)
           (r->info, NULL, r->name, r->howto->name, (bfd_vma) 0,
            input_bfd, r->input_section, r->reloc->r_offset));
          return TRUE;
-        }
+       }
 
       perform_relocation (r->howto, r->reloc, entry->value, r->input_section,
                          input_bfd, r->contents);
@@ -1752,10 +1731,12 @@ riscv_elf_relocate_section (bfd *output_bfd,
       bfd_boolean unresolved_reloc, is_ie = FALSE;
       bfd_vma pc = sec_addr (input_section) + rel->r_offset;
       int r_type = ELFNN_R_TYPE (rel->r_info), tls_type;
-      reloc_howto_type *howto = riscv_elf_rtype_to_howto (r_type);
+      reloc_howto_type *howto = riscv_elf_rtype_to_howto (input_bfd, r_type);
       const char *msg = NULL;
+      bfd_boolean resolved_to_zero;
 
-      if (r_type == R_RISCV_GNU_VTINHERIT || r_type == R_RISCV_GNU_VTENTRY)
+      if (howto == NULL
+         || r_type == R_RISCV_GNU_VTINHERIT || r_type == R_RISCV_GNU_VTENTRY)
        continue;
 
       /* This is a final link.  */
@@ -1807,6 +1788,9 @@ riscv_elf_relocate_section (bfd *output_bfd,
            name = bfd_section_name (input_bfd, sec);
        }
 
+      resolved_to_zero = (h != NULL
+                         && UNDEFWEAK_NO_DYNAMIC_RELOC (info, h));
+
       switch (r_type)
        {
        case R_RISCV_NONE:
@@ -1916,9 +1900,11 @@ riscv_elf_relocate_section (bfd *output_bfd,
                                                howto,
                                                input_bfd);
          r_type = ELFNN_R_TYPE (rel->r_info);
-         howto = riscv_elf_rtype_to_howto (r_type);
-         if (!riscv_record_pcrel_hi_reloc (&pcrel_relocs, pc,
-                                           relocation, absolute))
+         howto = riscv_elf_rtype_to_howto (input_bfd, r_type);
+         if (howto == NULL)
+           r = bfd_reloc_notsupported;
+         else if (!riscv_record_pcrel_hi_reloc (&pcrel_relocs, pc,
+                                                relocation, absolute))
            r = bfd_reloc_overflow;
          break;
 
@@ -1945,8 +1931,24 @@ riscv_elf_relocate_section (bfd *output_bfd,
          }
          break;
 
-       case R_RISCV_CALL_PLT:
        case R_RISCV_CALL:
+         /* 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)
+           {
+             /* We can use x0 as the base register.  */
+             bfd_vma insn = bfd_get_32 (input_bfd,
+                                        contents + rel->r_offset + 4);
+             insn &= ~(OP_MASK_RS1 << OP_SH_RS1);
+             bfd_put_32 (input_bfd, insn, contents + rel->r_offset + 4);
+             /* Set the relocation value so that we get 0 after the pc
+                relative adjustment.  */
+             relocation = sec_addr (input_section) + rel->r_offset;
+           }
+         /* Fall through.  */
+
+       case R_RISCV_CALL_PLT:
        case R_RISCV_JAL:
        case R_RISCV_RVC_JUMP:
          if (bfd_link_pic (info) && h != NULL && h->plt.offset != MINUS_ONE)
@@ -2012,15 +2014,27 @@ riscv_elf_relocate_section (bfd *output_bfd,
                                                howto,
                                                input_bfd);
          r_type = ELFNN_R_TYPE (rel->r_info);
-         howto = riscv_elf_rtype_to_howto (r_type);
-         if (!riscv_record_pcrel_hi_reloc (&pcrel_relocs, pc,
-                                           relocation + rel->r_addend,
-                                           absolute))
+         howto = riscv_elf_rtype_to_howto (input_bfd, r_type);
+         if (howto == NULL)
+           r = bfd_reloc_notsupported;
+         else if (!riscv_record_pcrel_hi_reloc (&pcrel_relocs, pc,
+                                                relocation + rel->r_addend,
+                                                absolute))
            r = bfd_reloc_overflow;
          break;
 
        case R_RISCV_PCREL_LO12_I:
        case R_RISCV_PCREL_LO12_S:
+         /* Addends are not allowed, because then riscv_relax_delete_bytes
+            would have to search through all relocs to update the addends.
+            Also, riscv_resolve_pcrel_lo_relocs does not support addends
+            when searching for a matching hi reloc.  */
+         if (rel->r_addend)
+           {
+             r = bfd_reloc_dangerous;
+             break;
+           }
+
          if (riscv_record_pcrel_lo_reloc (&pcrel_relocs, input_section, info,
                                           howto, rel, relocation, name,
                                           contents))
@@ -2040,7 +2054,8 @@ riscv_elf_relocate_section (bfd *output_bfd,
 
          if ((bfd_link_pic (info)
               && (h == NULL
-                  || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+                  || (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+                      && !resolved_to_zero)
                   || h->root.type != bfd_link_hash_undefweak)
               && (! howto->pc_relative
                   || !SYMBOL_CALLS_LOCAL (info, h)))
@@ -2136,7 +2151,7 @@ riscv_elf_relocate_section (bfd *output_bfd,
                }
 
              /* The GOT entries have not been initialized yet.  Do it
-                now, and emit any relocations.  */
+                now, and emit any relocations.  */
              if ((bfd_link_pic (info) || indx != 0)
                  && (h == NULL
                      || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
@@ -2231,10 +2246,11 @@ riscv_elf_relocate_section (bfd *output_bfd,
                                      rel->r_offset) != (bfd_vma) -1)
        {
          (*_bfd_error_handler)
-           (_("%B(%A+%#Lx): unresolvable %s relocation against symbol `%s'"),
+           (_("%pB(%pA+%#" PRIx64 "): "
+              "unresolvable %s relocation against symbol `%s'"),
             input_bfd,
             input_section,
-            rel->r_offset,
+            (uint64_t) rel->r_offset,
             howto->name,
             h->root.root.string);
          continue;
@@ -2262,25 +2278,30 @@ riscv_elf_relocate_section (bfd *output_bfd,
          break;
 
        case bfd_reloc_outofrange:
-         msg = _("internal error: out of range error");
+         msg = _("%X%P: internal error: out of range error\n");
          break;
 
        case bfd_reloc_notsupported:
-         msg = _("internal error: unsupported relocation error");
+         msg = _("%X%P: internal error: unsupported relocation error\n");
          break;
 
        case bfd_reloc_dangerous:
-         msg = _("internal error: dangerous relocation");
+         info->callbacks->reloc_dangerous
+           (info, "%pcrel_lo with addend", input_bfd, input_section,
+            rel->r_offset);
          break;
 
        default:
-         msg = _("internal error: unknown error");
+         msg = _("%X%P: internal error: unknown error\n");
          break;
        }
 
       if (msg)
-       info->callbacks->warning
-         (info, msg, name, input_bfd, input_section, rel->r_offset);
+       info->callbacks->einfo (msg);
+
+      /* 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;
       goto out;
     }
 
@@ -2358,7 +2379,8 @@ riscv_elf_finish_dynamic_symbol (bfd *output_bfd,
     }
 
   if (h->got.offset != (bfd_vma) -1
-      && !(riscv_elf_hash_entry (h)->tls_type & (GOT_TLS_GD | GOT_TLS_IE)))
+      && !(riscv_elf_hash_entry (h)->tls_type & (GOT_TLS_GD | GOT_TLS_IE))
+      && !UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))
     {
       asection *sgot;
       asection *srela;
@@ -2372,15 +2394,15 @@ riscv_elf_finish_dynamic_symbol (bfd *output_bfd,
 
       rela.r_offset = sec_addr (sgot) + (h->got.offset &~ (bfd_vma) 1);
 
-      /* If this is a -Bsymbolic link, and the symbol is defined
-        locally, we just want to emit a RELATIVE reloc.  Likewise if
+      /* If this is a local symbol reference, we just want to emit a RELATIVE
+        reloc.  This can happen if it is a -Bsymbolic link, or a pie link, or
         the symbol was forced to be local because of a version file.
         The entry in the global offset table will already have been
         initialized in the relocate_section function.  */
       if (bfd_link_pic (info)
-         && (info->symbolic || h->dynindx == -1)
-         && h->def_regular)
+         && SYMBOL_REFERENCES_LOCAL (info, h))
        {
+         BFD_ASSERT((h->got.offset & 1) != 0);
          asection *sec = h->root.u.def.section;
          rela.r_info = ELFNN_R_INFO (0, R_RISCV_RELATIVE);
          rela.r_addend = (h->root.u.def.value
@@ -2389,6 +2411,7 @@ riscv_elf_finish_dynamic_symbol (bfd *output_bfd,
        }
       else
        {
+         BFD_ASSERT((h->got.offset & 1) == 0);
          BFD_ASSERT (h->dynindx != -1);
          rela.r_info = ELFNN_R_INFO (h->dynindx, R_RISCV_NN);
          rela.r_addend = 0;
@@ -2517,7 +2540,7 @@ riscv_elf_finish_dynamic_sections (bfd *output_bfd,
       if (bfd_is_abs_section (output_section))
        {
          (*_bfd_error_handler)
-           (_("discarded output section: `%A'"), htab->elf.sgotplt);
+           (_("discarded output section: `%pA'"), htab->elf.sgotplt);
          return FALSE;
        }
 
@@ -2595,7 +2618,7 @@ _bfd_riscv_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
   if (strcmp (bfd_get_target (ibfd), bfd_get_target (obfd)) != 0)
     {
       (*_bfd_error_handler)
-       (_("%B: ABI is incompatible with that of the selected emulation:\n"
+       (_("%pB: ABI is incompatible with that of the selected emulation:\n"
           "  target emulation `%s' does not match `%s'"),
         ibfd, bfd_get_target (ibfd), bfd_get_target (obfd));
       return FALSE;
@@ -2615,7 +2638,15 @@ _bfd_riscv_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
   if ((old_flags ^ new_flags) & EF_RISCV_FLOAT_ABI)
     {
       (*_bfd_error_handler)
-       (_("%B: can't link hard-float modules with soft-float modules"), ibfd);
+       (_("%pB: can't link hard-float modules with soft-float modules"), ibfd);
+      goto fail;
+    }
+
+  /* Disallow linking RVE and non-RVE.  */
+  if ((old_flags ^ new_flags) & EF_RISCV_RVE)
+    {
+      (*_bfd_error_handler)
+       (_("%pB: can't link RVE with other target"), ibfd);
       goto fail;
     }
 
@@ -2632,7 +2663,8 @@ fail:
 /* Delete some bytes from a section while relaxing.  */
 
 static bfd_boolean
-riscv_relax_delete_bytes (bfd *abfd, asection *sec, bfd_vma addr, size_t count)
+riscv_relax_delete_bytes (bfd *abfd, asection *sec, bfd_vma addr, size_t count,
+                         struct bfd_link_info *link_info)
 {
   unsigned int i, symcount;
   bfd_vma toaddr = sec->size;
@@ -2666,10 +2698,16 @@ riscv_relax_delete_bytes (bfd *abfd, asection *sec, bfd_vma addr, size_t count)
 
          /* If the symbol *spans* the bytes we just deleted (i.e. its
             *end* is in the moved bytes but its *start* isn't), then we
-            must adjust its size.  */
-         if (sym->st_value <= addr
-             && sym->st_value + sym->st_size > addr
-             && sym->st_value + sym->st_size <= toaddr)
+            must adjust its size.
+
+            This test needs to use the original value of st_value, otherwise
+            we might accidentally decrease size when deleting bytes right
+            before the symbol.  But since deleted relocs can't span across
+            symbols, we can't have both a st_value and a st_size decrease,
+            so it is simpler to just use an else.  */
+         else if (sym->st_value <= addr
+                  && sym->st_value + sym->st_size > addr
+                  && sym->st_value + sym->st_size <= toaddr)
            sym->st_size -= count;
        }
     }
@@ -2682,6 +2720,34 @@ riscv_relax_delete_bytes (bfd *abfd, asection *sec, bfd_vma addr, size_t count)
     {
       struct elf_link_hash_entry *sym_hash = sym_hashes[i];
 
+      /* The '--wrap SYMBOL' option is causing a pain when the object file,
+        containing the definition of __wrap_SYMBOL, includes a direct
+        call to SYMBOL as well. Since both __wrap_SYMBOL and SYMBOL reference
+        the same symbol (which is __wrap_SYMBOL), but still exist as two
+        different symbols in 'sym_hashes', we don't want to adjust
+        the global symbol __wrap_SYMBOL twice.  */
+      /* The same problem occurs with symbols that are versioned_hidden, as
+        foo becomes an alias for foo@BAR, and hence they need the same
+        treatment.  */
+      if (link_info->wrap_hash != NULL
+         || sym_hash->versioned == versioned_hidden)
+       {
+         struct elf_link_hash_entry **cur_sym_hashes;
+
+         /* Loop only over the symbols which have already been checked.  */
+         for (cur_sym_hashes = sym_hashes; cur_sym_hashes < &sym_hashes[i];
+              cur_sym_hashes++)
+           {
+             /* If the current symbol is identical to 'sym_hash', that means
+                the symbol was already adjusted (or at least checked).  */
+             if (*cur_sym_hashes == sym_hash)
+               break;
+           }
+         /* Don't adjust the symbol again.  */
+         if (cur_sym_hashes < &sym_hashes[i])
+           continue;
+       }
+
       if ((sym_hash->root.type == bfd_link_hash_defined
           || sym_hash->root.type == bfd_link_hash_defweak)
          && sym_hash->root.u.def.section == sec)
@@ -2692,9 +2758,9 @@ riscv_relax_delete_bytes (bfd *abfd, asection *sec, bfd_vma addr, size_t count)
            sym_hash->root.u.def.value -= count;
 
          /* As above, adjust the size if needed.  */
-         if (sym_hash->root.u.def.value <= addr
-             && sym_hash->root.u.def.value + sym_hash->size > addr
-             && sym_hash->root.u.def.value + sym_hash->size <= toaddr)
+         else if (sym_hash->root.u.def.value <= addr
+                  && sym_hash->root.u.def.value + sym_hash->size > addr
+                  && sym_hash->root.u.def.value + sym_hash->size <= toaddr)
            sym_hash->size -= count;
        }
     }
@@ -2914,7 +2980,8 @@ _bfd_riscv_relax_call (bfd *abfd, asection *sec, asection *sym_sec,
 
   /* Delete unnecessary JALR.  */
   *again = TRUE;
-  return riscv_relax_delete_bytes (abfd, sec, rel->r_offset + len, 8 - len);
+  return riscv_relax_delete_bytes (abfd, sec, rel->r_offset + len, 8 - len,
+                                  link_info);
 }
 
 /* Traverse all output sections and return the max alignment.  */
@@ -2992,7 +3059,8 @@ _bfd_riscv_relax_lui (bfd *abfd,
          /* We can delete the unnecessary LUI and reloc.  */
          rel->r_info = ELFNN_R_INFO (0, R_RISCV_NONE);
          *again = TRUE;
-         return riscv_relax_delete_bytes (abfd, sec, rel->r_offset, 4);
+         return riscv_relax_delete_bytes (abfd, sec, rel->r_offset, 4,
+                                          link_info);
 
        default:
          abort ();
@@ -3019,7 +3087,8 @@ _bfd_riscv_relax_lui (bfd *abfd,
       rel->r_info = ELFNN_R_INFO (ELFNN_R_SYM (rel->r_info), R_RISCV_RVC_LUI);
 
       *again = TRUE;
-      return riscv_relax_delete_bytes (abfd, sec, rel->r_offset + 2, 2);
+      return riscv_relax_delete_bytes (abfd, sec, rel->r_offset + 2, 2,
+                                      link_info);
     }
 
   return TRUE;
@@ -3059,7 +3128,7 @@ _bfd_riscv_relax_tls_le (bfd *abfd,
       /* We can delete the unnecessary instruction and reloc.  */
       rel->r_info = ELFNN_R_INFO (0, R_RISCV_NONE);
       *again = TRUE;
-      return riscv_relax_delete_bytes (abfd, sec, rel->r_offset, 4);
+      return riscv_relax_delete_bytes (abfd, sec, rel->r_offset, 4, link_info);
 
     default:
       abort ();
@@ -3071,7 +3140,7 @@ _bfd_riscv_relax_tls_le (bfd *abfd,
 static bfd_boolean
 _bfd_riscv_relax_align (bfd *abfd, asection *sec,
                        asection *sym_sec,
-                       struct bfd_link_info *link_info ATTRIBUTE_UNUSED,
+                       struct bfd_link_info *link_info,
                        Elf_Internal_Rela *rel,
                        bfd_vma symval,
                        bfd_vma max_alignment ATTRIBUTE_UNUSED,
@@ -3094,10 +3163,11 @@ _bfd_riscv_relax_align (bfd *abfd, asection *sec,
   /* Make sure there are enough NOPs to actually achieve the alignment.  */
   if (rel->r_addend < nop_bytes)
     {
-      (*_bfd_error_handler)
-       (_("%B(%A+0x%lx): %d bytes required for alignment "
-          "to %d-byte boundary, but only %d present"),
-          abfd, sym_sec, rel->r_offset, nop_bytes, alignment, rel->r_addend);
+      _bfd_error_handler
+       (_("%pB(%pA+%#" PRIx64 "): %" PRId64 " bytes required for alignment "
+          "to %" PRId64 "-byte boundary, but only %" PRId64 " present"),
+        abfd, sym_sec, (uint64_t) rel->r_offset,
+        (int64_t) nop_bytes, (int64_t) alignment, (int64_t) rel->r_addend);
       bfd_set_error (bfd_error_bad_value);
       return FALSE;
     }
@@ -3119,7 +3189,7 @@ _bfd_riscv_relax_align (bfd *abfd, asection *sec,
 
   /* Delete the excess bytes.  */
   return riscv_relax_delete_bytes (abfd, sec, rel->r_offset + nop_bytes,
-                                  rel->r_addend - nop_bytes);
+                                  rel->r_addend - nop_bytes, link_info);
 }
 
 /* Relax PC-relative references to GP-relative references.  */
@@ -3142,7 +3212,8 @@ _bfd_riscv_relax_pc  (bfd *abfd,
 
   /* Chain the _LO relocs to their cooresponding _HI reloc to compute the
    * actual target address.  */
-  riscv_pcgp_hi_reloc hi_reloc = {0};
+  riscv_pcgp_hi_reloc hi_reloc;
+  memset (&hi_reloc, 0, sizeof (hi_reloc));
   switch (ELFNN_R_TYPE (rel->r_info))
     {
     case R_RISCV_PCREL_LO12_I:
@@ -3160,10 +3231,10 @@ _bfd_riscv_relax_pc  (bfd *abfd,
        symval = hi_reloc.hi_addr;
        sym_sec = hi_reloc.sym_sec;
        if (!riscv_use_pcgp_hi_reloc(pcgp_relocs, hi->hi_sec_off))
-         (*_bfd_error_handler)
-          (_("%B(%A+0x%lx): Unable to clear RISCV_PCREL_HI20 reloc"
-             "for cooresponding RISCV_PCREL_LO12 reloc"),
-           abfd, sec, rel->r_offset);
+         _bfd_error_handler
+           (_("%pB(%pA+%#" PRIx64 "): Unable to clear RISCV_PCREL_HI20 reloc "
+              "for corresponding RISCV_PCREL_LO12 reloc"),
+            abfd, sec, (uint64_t) rel->r_offset);
       }
       break;
 
@@ -3175,7 +3246,7 @@ _bfd_riscv_relax_pc  (bfd *abfd,
       /* If the cooresponding lo relocation has already been seen then it's not
        * safe to relax this relocation.  */
       if (riscv_find_pcgp_lo_reloc (pcgp_relocs, rel->r_offset))
-        return TRUE;
+       return TRUE;
 
       break;
 
@@ -3215,7 +3286,7 @@ _bfd_riscv_relax_pc  (bfd *abfd,
          return riscv_delete_pcgp_lo_reloc (pcgp_relocs, rel->r_offset, 4);
 
        case R_RISCV_PCREL_HI20:
-          riscv_record_pcgp_hi_reloc (pcgp_relocs,
+         riscv_record_pcgp_hi_reloc (pcgp_relocs,
                                      rel->r_offset,
                                      rel->r_addend,
                                      symval,
@@ -3240,7 +3311,7 @@ static bfd_boolean
 _bfd_riscv_relax_delete (bfd *abfd,
                         asection *sec,
                         asection *sym_sec ATTRIBUTE_UNUSED,
-                        struct bfd_link_info *link_info ATTRIBUTE_UNUSED,
+                        struct bfd_link_info *link_info,
                         Elf_Internal_Rela *rel,
                         bfd_vma symval ATTRIBUTE_UNUSED,
                         bfd_vma max_alignment ATTRIBUTE_UNUSED,
@@ -3248,7 +3319,8 @@ _bfd_riscv_relax_delete (bfd *abfd,
                         bfd_boolean *again ATTRIBUTE_UNUSED,
                         riscv_pcgp_relocs *pcgp_relocs ATTRIBUTE_UNUSED)
 {
-  if (!riscv_relax_delete_bytes(abfd, sec, rel->r_offset, rel->r_addend))
+  if (!riscv_relax_delete_bytes(abfd, sec, rel->r_offset, rel->r_addend,
+                               link_info))
     return FALSE;
   rel->r_info = ELFNN_R_INFO(0, R_RISCV_NONE);
   return TRUE;
@@ -3344,7 +3416,7 @@ _bfd_riscv_relax_section (bfd *abfd, asection *sec,
          i++;
        }
       else if (info->relax_pass == 1 && type == R_RISCV_DELETE)
-        relax_func = _bfd_riscv_relax_delete;
+       relax_func = _bfd_riscv_relax_delete;
       else if (info->relax_pass == 2 && type == R_RISCV_ALIGN)
        relax_func = _bfd_riscv_relax_align;
       else
@@ -3381,8 +3453,14 @@ _bfd_riscv_relax_section (bfd *abfd, asection *sec,
            {
              BFD_ASSERT (isym->st_shndx < elf_numsections (abfd));
              sym_sec = elf_elfsections (abfd)[isym->st_shndx]->bfd_section;
+#if 0
+             /* The purpose of this code is unknown.  It breaks linker scripts
+                for embedded development that place sections at address zero.
+                This code is believed to be unnecessary.  Disabling it but not
+                yet removing it, in case something breaks.  */
              if (sec_addr (sym_sec) == 0)
                continue;
+#endif
              symval = sec_addr (sym_sec) + isym->st_value;
            }
        }
@@ -3552,9 +3630,9 @@ riscv_elf_object_p (bfd *abfd)
 #define elf_backend_finish_dynamic_sections  riscv_elf_finish_dynamic_sections
 #define elf_backend_gc_mark_hook            riscv_elf_gc_mark_hook
 #define elf_backend_plt_sym_val                     riscv_elf_plt_sym_val
-#define elf_backend_grok_prstatus            riscv_elf_grok_prstatus
-#define elf_backend_grok_psinfo              riscv_elf_grok_psinfo
-#define elf_backend_object_p                 riscv_elf_object_p
+#define elf_backend_grok_prstatus           riscv_elf_grok_prstatus
+#define elf_backend_grok_psinfo                     riscv_elf_grok_psinfo
+#define elf_backend_object_p                riscv_elf_object_p
 #define elf_info_to_howto_rel               NULL
 #define elf_info_to_howto                   riscv_info_to_howto_rela
 #define bfd_elfNN_bfd_relax_section         _bfd_riscv_relax_section
This page took 0.040799 seconds and 4 git commands to generate.