Binutils: Always skip only 1 byte for CIE version 1's return address register.
[deliverable/binutils-gdb.git] / ld / plugin.c
index 7ee45a2eccf0db032538508fc9aed5b963857d52..ea1a7f70645d339d8346b365f4b2a20f2686519d 100644 (file)
@@ -1,5 +1,5 @@
 /* Plugin control for the GNU linker.
-   Copyright (C) 2010-2015 Free Software Foundation, Inc.
+   Copyright (C) 2010-2019 Free Software Foundation, Inc.
 
    This file is part of the GNU Binutils.
 
@@ -29,8 +29,9 @@
 #include "ldexp.h"
 #include "ldlang.h"
 #include "ldfile.h"
-#include "plugin.h"
 #include "plugin-api.h"
+#include "../bfd/plugin.h"
+#include "plugin.h"
 #include "elf-bfd.h"
 #if HAVE_MMAP
 # include <sys/mman.h>
@@ -103,6 +104,7 @@ typedef struct plugin_input_file
   view_buffer_t view_buffer;
   char *name;
   int fd;
+  bfd_boolean use_mmap;
   off_t offset;
   off_t filesize;
 } plugin_input_file_t;
@@ -136,6 +138,11 @@ static struct bfd_link_callbacks plugin_callbacks;
    its own newly-added input files and libs to claim.  */
 bfd_boolean no_more_claiming = FALSE;
 
+#if HAVE_MMAP && HAVE_GETPAGESIZE
+/* Page size used by mmap.  */
+static off_t plugin_pagesize;
+#endif
+
 /* List of tags to set in the constant leading part of the tv array. */
 static const enum ld_plugin_tag tv_header_tags[] =
 {
@@ -167,6 +174,8 @@ static bfd_boolean plugin_notice (struct bfd_link_info *,
                                  struct bfd_link_hash_entry *,
                                  bfd *, asection *, bfd_vma, flagword);
 
+static const bfd_target * plugin_object_p (bfd *);
+
 #if !defined (HAVE_DLFCN_H) && defined (HAVE_WINDOWS_H)
 
 #define RTLD_NOW 0     /* Dummy value.  */
@@ -227,13 +236,26 @@ void
 plugin_opt_plugin (const char *plugin)
 {
   plugin_t *newplug;
+  plugin_t *curplug = plugins_list;
 
   newplug = xmalloc (sizeof *newplug);
   memset (newplug, 0, sizeof *newplug);
   newplug->name = plugin;
   newplug->dlhandle = dlopen (plugin, RTLD_NOW);
   if (!newplug->dlhandle)
-    einfo (_("%P%F: %s: error loading plugin: %s\n"), plugin, dlerror ());
+    einfo (_("%F%P: %s: error loading plugin: %s\n"), plugin, dlerror ());
+
+  /* Check if plugin has been loaded already.  */
+  while (curplug)
+    {
+      if (newplug->dlhandle == curplug->dlhandle)
+       {
+         einfo (_("%P: %s: duplicated plugin\n"), plugin);
+         free (newplug);
+         return;
+       }
+      curplug = curplug->next;
+    }
 
   /* Chain on end, so when we run list it is in command-line order.  */
   *plugins_tail_chain_ptr = newplug;
@@ -285,17 +307,24 @@ static bfd *
 plugin_get_ir_dummy_bfd (const char *name, bfd *srctemplate)
 {
   bfd *abfd;
+  bfd_boolean bfd_plugin_target;
 
   bfd_use_reserved_id = 1;
+  bfd_plugin_target = bfd_plugin_target_p (srctemplate->xvec);
   abfd = bfd_create (concat (name, IRONLY_SUFFIX, (const char *) NULL),
-                    srctemplate);
+                    bfd_plugin_target ? link_info.output_bfd : srctemplate);
   if (abfd != NULL)
     {
       abfd->flags |= BFD_LINKER_CREATED | BFD_PLUGIN;
-      bfd_set_arch_info (abfd, bfd_get_arch_info (srctemplate));
-      bfd_set_gp_size (abfd, bfd_get_gp_size (srctemplate));
-      if (bfd_make_writable (abfd)
-         && bfd_copy_private_bfd_data (srctemplate, abfd))
+      if (!bfd_make_writable (abfd))
+       goto report_error;
+      if (!bfd_plugin_target)
+       {
+         bfd_set_arch_info (abfd, bfd_get_arch_info (srctemplate));
+         bfd_set_gp_size (abfd, bfd_get_gp_size (srctemplate));
+         if (!bfd_copy_private_bfd_data (srctemplate, abfd))
+           goto report_error;
+       }
        {
          flagword flags;
 
@@ -306,7 +335,8 @@ plugin_get_ir_dummy_bfd (const char *name, bfd *srctemplate)
            return abfd;
        }
     }
-  einfo (_("could not create dummy IR bfd: %F%E\n"));
+report_error:
+  einfo (_("%F%P: could not create dummy IR bfd: %E\n"));
   return NULL;
 }
 
@@ -394,12 +424,14 @@ asymbol_from_plugin_symbol (bfd *abfd, asymbol *asym,
       unsigned char visibility;
 
       if (!elfsym)
-       einfo (_("%P%F: %s: non-ELF symbol in ELF BFD!\n"), asym->name);
+       einfo (_("%F%P: %s: non-ELF symbol in ELF BFD!\n"), asym->name);
       switch (ldsym->visibility)
        {
        default:
-         einfo (_("%P%F: unknown ELF symbol visibility: %d!\n"),
+         einfo (_("%F%P: unknown ELF symbol visibility: %d!\n"),
                 ldsym->visibility);
+         return LDPS_ERR;
+
        case LDPV_DEFAULT:
          visibility = STV_DEFAULT;
          break;
@@ -498,35 +530,52 @@ get_view (const void *handle, const void **viewp)
   plugin_input_file_t *input = (plugin_input_file_t *) handle;
   char *buffer;
   size_t size = input->filesize;
+  off_t offset = input->offset;
+#if HAVE_MMAP && HAVE_GETPAGESIZE
+  off_t bias;
+#endif
 
   ASSERT (called_plugin);
 
   /* FIXME: einfo should support %lld.  */
   if ((off_t) size != input->filesize)
-    einfo (_("%P%F: unsupported input file size: %s (%ld bytes)\n"),
+    einfo (_("%F%P: unsupported input file size: %s (%ld bytes)\n"),
           input->name, (long) input->filesize);
 
   /* Check the cached view buffer.  */
   if (input->view_buffer.addr != NULL
       && input->view_buffer.filesize == size
-      && input->view_buffer.offset == input->offset)
+      && input->view_buffer.offset == offset)
     {
       *viewp = input->view_buffer.addr;
       return LDPS_OK;
     }
 
   input->view_buffer.filesize = size;
-  input->view_buffer.offset = input->offset;
+  input->view_buffer.offset = offset;
 
 #if HAVE_MMAP
-  buffer = mmap (NULL, size, PROT_READ, MAP_PRIVATE, input->fd,
-                input->offset);
-  if (buffer == MAP_FAILED)
+# if HAVE_GETPAGESIZE
+  bias = offset % plugin_pagesize;
+  offset -= bias;
+  size += bias;
+# endif
+  buffer = mmap (NULL, size, PROT_READ, MAP_PRIVATE, input->fd, offset);
+  if (buffer != MAP_FAILED)
+    {
+      input->use_mmap = TRUE;
+# if HAVE_GETPAGESIZE
+      buffer += bias;
+# endif
+    }
+  else
 #endif
     {
       char *p;
 
-      if (lseek (input->fd, input->offset, SEEK_SET) < 0)
+      input->use_mmap = FALSE;
+
+      if (lseek (input->fd, offset, SEEK_SET) < 0)
        return LDPS_ERR;
 
       buffer = bfd_alloc (input->abfd, size);
@@ -576,11 +625,11 @@ static inline bfd_boolean
 is_visible_from_outside (struct ld_plugin_symbol *lsym,
                         struct bfd_link_hash_entry *blhe)
 {
-  struct bfd_sym_chain *sym;
-
-  if (link_info.relocatable)
+  if (bfd_link_relocatable (&link_info))
     return TRUE;
-  if (link_info.export_dynamic || !link_info.executable)
+  if (blhe->non_ir_ref_dynamic
+      || link_info.export_dynamic
+      || bfd_link_dll (&link_info))
     {
       /* Check if symbol is hidden by version script.  */
       if (bfd_hide_sym_by_version (link_info.version_info,
@@ -607,11 +656,6 @@ is_visible_from_outside (struct ld_plugin_symbol *lsym,
              || lsym->visibility == LDPV_PROTECTED);
     }
 
-  for (sym = &entry_symbol; sym != NULL; sym = sym->next)
-    if (sym->name
-       && strcmp (sym->name, blhe->root.string) == 0)
-      return TRUE;
-
   return FALSE;
 }
 
@@ -639,7 +683,24 @@ get_symbols (const void *handle, int nsyms, struct ld_plugin_symbol *syms,
                                             syms[n].name, FALSE, FALSE, TRUE);
       if (!blhe)
        {
-         res = LDPR_UNKNOWN;
+         /* The plugin is called to claim symbols in an archive element
+            from plugin_object_p.  But those symbols aren't needed to
+            create output.  They are defined and referenced only within
+            IR.  */
+         switch (syms[n].def)
+           {
+           default:
+             abort ();
+           case LDPK_UNDEF:
+           case LDPK_WEAKUNDEF:
+             res = LDPR_UNDEF;
+             break;
+           case LDPK_DEF:
+           case LDPK_WEAKDEF:
+           case LDPK_COMMON:
+             res = LDPR_PREVAILING_DEF_IRONLY;
+             break;
+           }
          goto report_symbol;
        }
 
@@ -655,7 +716,7 @@ get_symbols (const void *handle, int nsyms, struct ld_plugin_symbol *syms,
          && blhe->type != bfd_link_hash_common)
        {
          /* We should not have a new, indirect or warning symbol here.  */
-         einfo ("%P%F: %s: plugin symbol table corrupt (sym type %d)\n",
+         einfo (_("%F%P: %s: plugin symbol table corrupt (sym type %d)\n"),
                 called_plugin->name, blhe->type);
        }
 
@@ -706,7 +767,7 @@ get_symbols (const void *handle, int nsyms, struct ld_plugin_symbol *syms,
             even potentially-referenced, perhaps in a future final link if
             this is a partial one, perhaps dynamically at load-time if the
             symbol is externally visible.  */
-         if (blhe->non_ir_ref)
+         if (blhe->non_ir_ref_regular)
            res = LDPR_PREVAILING_DEF;
          else if (is_visible_from_outside (&syms[n], blhe))
            res = def_ironly_exp;
@@ -715,7 +776,7 @@ get_symbols (const void *handle, int nsyms, struct ld_plugin_symbol *syms,
     report_symbol:
       syms[n].resolution = res;
       if (report_plugin_symbols)
-       einfo (_("%P: %B: symbol `%s' "
+       einfo (_("%P: %pB: symbol `%s' "
                 "definition: %d, visibility: %d, resolution: %d\n"),
               abfd, syms[n].name,
               syms[n].def, syms[n].visibility, res);
@@ -739,10 +800,14 @@ get_symbols_v2 (const void *handle, int nsyms, struct ld_plugin_symbol *syms)
 static enum ld_plugin_status
 add_input_file (const char *pathname)
 {
+  lang_input_statement_type *is;
+
   ASSERT (called_plugin);
-  if (!lang_add_input_file (xstrdup (pathname), lang_input_file_is_file_enum,
-                           NULL))
+  is = lang_add_input_file (xstrdup (pathname), lang_input_file_is_file_enum,
+                           NULL);
+  if (!is)
     return LDPS_ERR;
+  is->flags.lto_output = 1;
   return LDPS_OK;
 }
 
@@ -750,10 +815,14 @@ add_input_file (const char *pathname)
 static enum ld_plugin_status
 add_input_library (const char *pathname)
 {
+  lang_input_statement_type *is;
+
   ASSERT (called_plugin);
-  if (!lang_add_input_file (xstrdup (pathname), lang_input_file_is_l_enum,
-                           NULL))
+  is = lang_add_input_file (xstrdup (pathname), lang_input_file_is_l_enum,
+                           NULL);
+  if (!is)
     return LDPS_ERR;
+  is->flags.lto_output = 1;
   return LDPS_OK;
 }
 
@@ -781,18 +850,24 @@ message (int level, const char *format, ...)
       putchar ('\n');
       break;
     case LDPL_WARNING:
-      vfinfo (stdout, format, args, TRUE);
-      putchar ('\n');
+      {
+       char *newfmt = concat (_("%P: warning: "), format, "\n",
+                              (const char *) NULL);
+       vfinfo (stdout, newfmt, args, TRUE);
+       free (newfmt);
+      }
       break;
     case LDPL_FATAL:
     case LDPL_ERROR:
     default:
       {
-       char *newfmt = ACONCAT ((level == LDPL_FATAL ? "%P%F: " : "%P%X: ",
-                                format, "\n", (const char *) NULL));
+       char *newfmt = concat (level == LDPL_FATAL ? "%F" : "%X",
+                              _("%P: error: "), format, "\n",
+                              (const char *) NULL);
        fflush (stdout);
        vfinfo (stderr, newfmt, args, TRUE);
        fflush (stderr);
+       free (newfmt);
       }
       break;
     }
@@ -827,11 +902,10 @@ set_tv_header (struct ld_plugin_tv *tv)
          TVU(val) = major * 100 + minor;
          break;
        case LDPT_LINKER_OUTPUT:
-         TVU(val) = (link_info.relocatable
-                     ? LDPO_REL
-                     : (link_info.executable
-                        ? (link_info.pie ? LDPO_PIE : LDPO_EXEC)
-                        : LDPO_DYN));
+         TVU(val) = (bfd_link_relocatable (&link_info) ? LDPO_REL
+                     : bfd_link_pde (&link_info) ? LDPO_EXEC
+                     : bfd_link_pie (&link_info) ? LDPO_PIE
+                     : LDPO_DYN);
          break;
        case LDPT_OUTPUT_NAME:
          TVU(string) = output_filename;
@@ -933,14 +1007,14 @@ plugin_load_plugins (void)
       if (!onloadfn)
        onloadfn = (ld_plugin_onload) dlsym (curplug->dlhandle, "_onload");
       if (!onloadfn)
-        einfo (_("%P%F: %s: error loading plugin: %s\n"),
+       einfo (_("%F%P: %s: error loading plugin: %s\n"),
               curplug->name, dlerror ());
       set_tv_plugin_args (curplug, &my_tv[tv_header_size]);
       called_plugin = curplug;
       rv = (*onloadfn) (my_tv);
       called_plugin = NULL;
       if (rv != LDPS_OK)
-       einfo (_("%P%F: %s: plugin error: %d\n"), curplug->name, rv);
+       einfo (_("%F%P: %s: plugin error: %d\n"), curplug->name, rv);
       curplug = curplug->next;
     }
 
@@ -954,6 +1028,12 @@ plugin_load_plugins (void)
   link_info.notice_all = TRUE;
   link_info.lto_plugin_active = TRUE;
   link_info.callbacks = &plugin_callbacks;
+
+  register_ld_plugin_object_p (plugin_object_p);
+
+#if HAVE_MMAP && HAVE_GETPAGESIZE
+  plugin_pagesize = getpagesize ();
+#endif
 }
 
 /* Call 'claim file' hook for all plugins.  */
@@ -962,13 +1042,12 @@ plugin_call_claim_file (const struct ld_plugin_input_file *file, int *claimed)
 {
   plugin_t *curplug = plugins_list;
   *claimed = FALSE;
-  if (no_more_claiming)
-    return 0;
   while (curplug && !*claimed)
     {
       if (curplug->claim_file_handler)
        {
          enum ld_plugin_status rv;
+
          called_plugin = curplug;
          rv = (*curplug->claim_file_handler) (file, claimed);
          called_plugin = NULL;
@@ -980,76 +1059,142 @@ plugin_call_claim_file (const struct ld_plugin_input_file *file, int *claimed)
   return plugin_error_p () ? -1 : 0;
 }
 
-void
-plugin_maybe_claim (struct ld_plugin_input_file *file,
-                   lang_input_statement_type *entry)
+/* Duplicates a character string with memory attached to ABFD.  */
+
+static char *
+plugin_strdup (bfd *abfd, const char *str)
 {
-  int claimed = 0;
+  size_t strlength;
+  char *copy;
+  strlength = strlen (str) + 1;
+  copy = bfd_alloc (abfd, strlength);
+  if (copy == NULL)
+    einfo (_("%F%P: plugin_strdup failed to allocate memory: %s\n"),
+          bfd_get_error ());
+  memcpy (copy, str, strlength);
+  return copy;
+}
+
+static const bfd_target *
+plugin_object_p (bfd *ibfd)
+{
+  int claimed;
   plugin_input_file_t *input;
-  size_t namelength;
+  struct ld_plugin_input_file file;
+  bfd *abfd;
+
+  /* Don't try the dummy object file.  */
+  if ((ibfd->flags & BFD_PLUGIN) != 0)
+    return NULL;
+
+  if (ibfd->plugin_format != bfd_plugin_unknown)
+    {
+      if (ibfd->plugin_format == bfd_plugin_yes)
+       return ibfd->plugin_dummy_bfd->xvec;
+      else
+       return NULL;
+    }
 
   /* We create a dummy BFD, initially empty, to house whatever symbols
      the plugin may want to add.  */
-  bfd *abfd = plugin_get_ir_dummy_bfd (entry->the_bfd->filename,
-                                      entry->the_bfd);
+  abfd = plugin_get_ir_dummy_bfd (ibfd->filename, ibfd);
 
   input = bfd_alloc (abfd, sizeof (*input));
   if (input == NULL)
-    einfo (_("%P%F: plugin failed to allocate memory for input: %s\n"),
+    einfo (_("%F%P: plugin failed to allocate memory for input: %s\n"),
           bfd_get_error ());
 
+  if (!bfd_plugin_open_input (ibfd, &file))
+    return NULL;
+
+  if (file.name == ibfd->filename)
+    {
+      /* We must copy filename attached to ibfd if it is not an archive
+        member since it may be freed by bfd_close below.  */
+      file.name = plugin_strdup (abfd, file.name);
+    }
+
+  file.handle = input;
   input->abfd = abfd;
   input->view_buffer.addr = NULL;
   input->view_buffer.filesize = 0;
   input->view_buffer.offset = 0;
-  input->fd = file->fd;
-  input->offset  = file->offset;
-  input->filesize = file->filesize;
-  namelength = strlen (entry->the_bfd->filename) + 1;
-  input->name = bfd_alloc (abfd, namelength);
-  if (input->name == NULL)
-    einfo (_("%P%F: plugin failed to allocate memory for input filename: %s\n"),
-          bfd_get_error ());
-  memcpy (input->name, entry->the_bfd->filename, namelength);
+  input->fd = file.fd;
+  input->use_mmap = FALSE;
+  input->offset = file.offset;
+  input->filesize = file.filesize;
+  input->name = plugin_strdup (abfd, ibfd->filename);
 
-  file->handle = input;
+  claimed = 0;
 
-  if (plugin_call_claim_file (file, &claimed))
-    einfo (_("%P%F: %s: plugin reported error claiming file\n"),
+  if (plugin_call_claim_file (&file, &claimed))
+    einfo (_("%F%P: %s: plugin reported error claiming file\n"),
           plugin_error_plugin ());
 
-  if (input->fd != -1 && bfd_check_format (entry->the_bfd, bfd_object))
+  if (input->fd != -1 && !bfd_plugin_target_p (ibfd->xvec))
     {
-      /* FIXME: fd belongs to us, not the plugin.  IR for GCC plugin,
-        which doesn't need fd after plugin_call_claim_file, is
-        stored in bfd_object file.  Since GCC plugin before GCC 5
-        doesn't call release_input_file, we close it here.  IR for
-        LLVM plugin, which needs fd after plugin_call_claim_file and
-        calls release_input_file after it is done, is stored in
-        non-bfd_object file.  This scheme doesn't work when a plugin
-        needs fd and its IR is stored in bfd_object file.  */
-      close (file->fd);
+      /* FIXME: fd belongs to us, not the plugin.  GCC plugin, which
+        doesn't need fd after plugin_call_claim_file, doesn't use
+        BFD plugin target vector.  Since GCC plugin doesn't call
+        release_input_file, we close it here.  LLVM plugin, which
+        needs fd after plugin_call_claim_file and calls
+        release_input_file after it is done, uses BFD plugin target
+        vector.  This scheme doesn't work when a plugin needs fd and
+        doesn't use BFD plugin target vector neither.  */
+      close (input->fd);
       input->fd = -1;
     }
 
   if (claimed)
     {
-      /* Discard the real file's BFD and substitute the dummy one.  */
-
-      /* BFD archive handling caches elements so we can't call
-        bfd_close for archives.  */
-      if (entry->the_bfd->my_archive == NULL)
-       bfd_close (entry->the_bfd);
-      entry->the_bfd = abfd;
-      entry->flags.claimed = TRUE;
-      bfd_make_readable (entry->the_bfd);
+      ibfd->plugin_format = bfd_plugin_yes;
+      ibfd->plugin_dummy_bfd = abfd;
+      bfd_make_readable (abfd);
+      return abfd->xvec;
     }
   else
     {
+#if HAVE_MMAP
+      if (input->use_mmap)
+       {
+         /* If plugin didn't claim the file, unmap the buffer.  */
+         char *addr = input->view_buffer.addr;
+         off_t size = input->view_buffer.filesize;
+# if HAVE_GETPAGESIZE
+         off_t bias = input->view_buffer.offset % plugin_pagesize;
+         size += bias;
+         addr -= bias;
+# endif
+         munmap (addr, size);
+       }
+#endif
+
       /* If plugin didn't claim the file, we don't need the dummy bfd.
         Can't avoid speculatively creating it, alas.  */
+      ibfd->plugin_format = bfd_plugin_no;
       bfd_close_all_done (abfd);
-      entry->flags.claimed = FALSE;
+      return NULL;
+    }
+}
+
+void
+plugin_maybe_claim (lang_input_statement_type *entry)
+{
+  ASSERT (entry->header.type == lang_input_statement_enum);
+  if (plugin_object_p (entry->the_bfd))
+    {
+      bfd *abfd = entry->the_bfd->plugin_dummy_bfd;
+
+      /* Discard the real file's BFD and substitute the dummy one.  */
+
+      /* We can't call bfd_close on archives.  BFD archive handling
+        caches elements, and add_archive_element keeps pointers to
+        the_bfd and the_bfd->filename in a lang_input_statement_type
+        linker script statement.  */
+      if (entry->the_bfd->my_archive == NULL)
+       bfd_close (entry->the_bfd);
+      entry->the_bfd = abfd;
+      entry->flags.claimed = 1;
     }
 }
 
@@ -1104,9 +1249,10 @@ plugin_call_cleanup (void)
 /* To determine which symbols should be resolved LDPR_PREVAILING_DEF
    and which LDPR_PREVAILING_DEF_IRONLY, we notice all the symbols as
    the linker adds them to the linker hash table.  Mark those
-   referenced from a non-IR file with non_ir_ref.  We have to
-   notice_all symbols, because we won't necessarily know until later
-   which ones will be contributed by IR files.  */
+   referenced from a non-IR file with non_ir_ref_regular or
+   non_ir_ref_dynamic as appropriate.  We have to notice_all symbols,
+   because we won't necessarily know until later which ones will be
+   contributed by IR files.  */
 static bfd_boolean
 plugin_notice (struct bfd_link_info *info,
               struct bfd_link_hash_entry *h,
@@ -1121,6 +1267,7 @@ plugin_notice (struct bfd_link_info *info,
   if (h != NULL)
     {
       bfd *sym_bfd;
+      bfd_boolean ref = FALSE;
 
       if (h->type == bfd_link_hash_warning)
        h = h->u.i.link;
@@ -1136,13 +1283,17 @@ plugin_notice (struct bfd_link_info *info,
        {
          /* ??? Some of this is questionable.  See comments in
             _bfd_generic_link_add_one_symbol for case IND.  */
-         if (h->type != bfd_link_hash_new)
+         if (h->type != bfd_link_hash_new
+             || inh->type == bfd_link_hash_new)
            {
-             h->non_ir_ref = TRUE;
-             inh->non_ir_ref = TRUE;
+             if ((abfd->flags & DYNAMIC) == 0)
+               inh->non_ir_ref_regular = TRUE;
+             else
+               inh->non_ir_ref_dynamic = TRUE;
            }
-         else if (inh->type == bfd_link_hash_new)
-           inh->non_ir_ref = TRUE;
+
+         if (h->type != bfd_link_hash_new)
+           ref = TRUE;
        }
 
       /* Nothing to do here for warning symbols.  */
@@ -1157,28 +1308,46 @@ plugin_notice (struct bfd_link_info *info,
       else if (bfd_is_und_section (section))
        {
          /* Replace the undefined dummy bfd with the real one.  */
-         if ((h->type == bfd_link_hash_undefined
-              || h->type == bfd_link_hash_undefweak)
-             && (h->u.undef.abfd == NULL
-                 || (h->u.undef.abfd->flags & BFD_PLUGIN) != 0))
-           h->u.undef.abfd = abfd;
-         h->non_ir_ref = TRUE;
+          if ((h->type == bfd_link_hash_undefined
+               || h->type == bfd_link_hash_undefweak)
+              && (h->u.undef.abfd == NULL
+                  || (h->u.undef.abfd->flags & BFD_PLUGIN) != 0))
+            h->u.undef.abfd = abfd;
+         ref = TRUE;
        }
 
-      /* Otherwise, it must be a new def.  Ensure any symbol defined
-        in an IR dummy BFD takes on a new value from a real BFD.
-        Weak symbols are not normally overridden by a new weak
-        definition, and strong symbols will normally cause multiple
-        definition errors.  Avoid this by making the symbol appear
-        to be undefined.  */
-      else if (((h->type == bfd_link_hash_defweak
-                || h->type == bfd_link_hash_defined)
-               && is_ir_dummy_bfd (sym_bfd = h->u.def.section->owner))
-              || (h->type == bfd_link_hash_common
-                  && is_ir_dummy_bfd (sym_bfd = h->u.c.p->section->owner)))
+      /* Otherwise, it must be a new def.  */
+      else
        {
-         h->type = bfd_link_hash_undefweak;
-         h->u.undef.abfd = sym_bfd;
+         /* Ensure any symbol defined in an IR dummy BFD takes on a
+            new value from a real BFD.  Weak symbols are not normally
+            overridden by a new weak definition, and strong symbols
+            will normally cause multiple definition errors.  Avoid
+            this by making the symbol appear to be undefined.  */
+         if (((h->type == bfd_link_hash_defweak
+               || h->type == bfd_link_hash_defined)
+              && is_ir_dummy_bfd (sym_bfd = h->u.def.section->owner))
+             || (h->type == bfd_link_hash_common
+                 && is_ir_dummy_bfd (sym_bfd = h->u.c.p->section->owner)))
+           {
+             h->type = bfd_link_hash_undefweak;
+             h->u.undef.abfd = sym_bfd;
+           }
+
+         /* A common symbol should be merged with other commons or
+            defs with the same name.  In particular, a common ought
+            to be overridden by a def in a -flto object.  In that
+            sense a common is also a ref.  */
+         if (bfd_is_com_section (section))
+           ref = TRUE;
+       }
+
+      if (ref)
+       {
+         if ((abfd->flags & DYNAMIC) == 0)
+           h->non_ir_ref_regular = TRUE;
+         else
+           h->non_ir_ref_dynamic = TRUE;
        }
     }
 
This page took 0.078836 seconds and 4 git commands to generate.