Make the objfile constructor private
[deliverable/binutils-gdb.git] / ld / plugin.c
index 4384a460a573e4ed5eaf7e18756128c4f43775dd..e253e1aea4261b8a0a5a7fef877b6f709fda723b 100644 (file)
@@ -1,5 +1,5 @@
 /* Plugin control for the GNU linker.
-   Copyright (C) 2010-2018 Free Software Foundation, Inc.
+   Copyright (C) 2010-2019 Free Software Foundation, Inc.
 
    This file is part of the GNU Binutils.
 
@@ -23,6 +23,7 @@
 #include "bfd.h"
 #include "bfdlink.h"
 #include "bfdver.h"
+#include "ctf-api.h"
 #include "ld.h"
 #include "ldmain.h"
 #include "ldmisc.h"
@@ -243,7 +244,7 @@ plugin_opt_plugin (const char *plugin)
   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)
@@ -336,7 +337,7 @@ plugin_get_ir_dummy_bfd (const char *name, bfd *srctemplate)
        }
     }
 report_error:
-  einfo (_("could not create dummy IR bfd: %F%E\n"));
+  einfo (_("%F%P: could not create dummy IR bfd: %E\n"));
   return NULL;
 }
 
@@ -403,12 +404,6 @@ asymbol_from_plugin_symbol (bfd *abfd, asymbol *asym,
       flags = BSF_GLOBAL;
       section = bfd_com_section_ptr;
       asym->value = ldsym->size;
-      /* For ELF targets, set alignment of common symbol to 1.  */
-      if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
-       {
-         ((elf_symbol_type *) asym)->internal_elf_sym.st_shndx = SHN_COMMON;
-         ((elf_symbol_type *) asym)->internal_elf_sym.st_value = 1;
-       }
       break;
 
     default:
@@ -417,18 +412,24 @@ asymbol_from_plugin_symbol (bfd *abfd, asymbol *asym,
   asym->flags = flags;
   asym->section = section;
 
-  /* Visibility only applies on ELF targets.  */
   if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
     {
       elf_symbol_type *elfsym = elf_symbol_from (abfd, 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);
+
+      if (ldsym->def == LDPK_COMMON)
+       {
+         elfsym->internal_elf_sym.st_shndx = SHN_COMMON;
+         elfsym->internal_elf_sym.st_value = 1;
+       }
+
       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;
 
@@ -445,9 +446,7 @@ asymbol_from_plugin_symbol (bfd *abfd, asymbol *asym,
          visibility = STV_HIDDEN;
          break;
        }
-      elfsym->internal_elf_sym.st_other
-       = (visibility | (elfsym->internal_elf_sym.st_other
-                        & ~ELF_ST_VISIBILITY (-1)));
+      elfsym->internal_elf_sym.st_other |= visibility;
     }
 
   return LDPS_OK;
@@ -539,7 +538,7 @@ get_view (const void *handle, const void **viewp)
 
   /* 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.  */
@@ -625,8 +624,6 @@ 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 (bfd_link_relocatable (&link_info))
     return TRUE;
   if (blhe->non_ir_ref_dynamic
@@ -658,14 +655,76 @@ 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;
 }
 
+/* Return LTO kind string name that corresponds to IDX enum value.  */
+static const char *
+get_lto_kind (unsigned int idx)
+{
+  static char buffer[64];
+  const char *lto_kind_str[5] =
+  {
+    "DEF",
+    "WEAKDEF",
+    "UNDEF",
+    "WEAKUNDEF",
+    "COMMON"
+  };
+
+  if (idx < ARRAY_SIZE (lto_kind_str))
+    return lto_kind_str [idx];
+
+  sprintf (buffer, _("unknown LTO kind value %x"), idx);
+  return buffer;
+}
+
+/* Return LTO resolution string name that corresponds to IDX enum value.  */
+static const char *
+get_lto_resolution (unsigned int idx)
+{
+  static char buffer[64];
+  static const char *lto_resolution_str[10] =
+  {
+    "UNKNOWN",
+    "UNDEF",
+    "PREVAILING_DEF",
+    "PREVAILING_DEF_IRONLY",
+    "PREEMPTED_REG",
+    "PREEMPTED_IR",
+    "RESOLVED_IR",
+    "RESOLVED_EXEC",
+    "RESOLVED_DYN",
+    "PREVAILING_DEF_IRONLY_EXP",
+  };
+
+  if (idx < ARRAY_SIZE (lto_resolution_str))
+    return lto_resolution_str [idx];
+
+  sprintf (buffer, _("unknown LTO resolution value %x"), idx);
+  return buffer;
+}
+
+/* Return LTO visibility string name that corresponds to IDX enum value.  */
+static const char *
+get_lto_visibility (unsigned int idx)
+{
+  static char buffer[64];
+  const char *lto_visibility_str[4] =
+  {
+    "DEFAULT",
+    "PROTECTED",
+    "INTERNAL",
+    "HIDDEN"
+  };
+
+  if (idx < ARRAY_SIZE (lto_visibility_str))
+    return lto_visibility_str [idx];
+
+  sprintf (buffer, _("unknown LTO visibility value %x"), idx);
+  return buffer;
+}
+
 /* Get the symbol resolution info for a plugin-claimed input file.  */
 static enum ld_plugin_status
 get_symbols (const void *handle, int nsyms, struct ld_plugin_symbol *syms,
@@ -681,13 +740,32 @@ get_symbols (const void *handle, int nsyms, struct ld_plugin_symbol *syms,
       struct bfd_link_hash_entry *blhe;
       asection *owner_sec;
       int res;
+      struct bfd_link_hash_entry *h
+       = bfd_link_hash_lookup (link_info.hash, syms[n].name,
+                               FALSE, FALSE, TRUE);
+      enum { wrap_none, wrapper, wrapped } wrap_status = wrap_none;
 
-      if (syms[n].def != LDPK_UNDEF)
-       blhe = bfd_link_hash_lookup (link_info.hash, syms[n].name,
-                                    FALSE, FALSE, TRUE);
+      if (syms[n].def != LDPK_UNDEF && syms[n].def != LDPK_WEAKUNDEF)
+       {
+         blhe = h;
+         if (blhe && link_info.wrap_hash != NULL)
+           {
+             /* Check if a symbol is a wrapper symbol.  */
+             struct bfd_link_hash_entry *unwrap
+               = unwrap_hash_lookup (&link_info, (bfd *) abfd, blhe);
+             if (unwrap && unwrap != h)
+               wrap_status = wrapper;
+            }
+       }
       else
-       blhe = bfd_wrapped_link_hash_lookup (link_info.output_bfd, &link_info,
-                                            syms[n].name, FALSE, FALSE, TRUE);
+       {
+         blhe = bfd_wrapped_link_hash_lookup (link_info.output_bfd,
+                                              &link_info, syms[n].name,
+                                              FALSE, FALSE, TRUE);
+         /* Check if a symbol is a wrapped symbol.  */
+         if (blhe && blhe != h)
+           wrap_status = wrapped;
+       }
       if (!blhe)
        {
          /* The plugin is called to claim symbols in an archive element
@@ -723,7 +801,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);
        }
 
@@ -773,9 +851,11 @@ get_symbols (const void *handle, int nsyms, struct ld_plugin_symbol *syms,
          /* We need to know if the sym is referenced from non-IR files.  Or
             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_regular)
+            symbol is externally visible.  Also check for wrapper symbol.  */
+         if (blhe->non_ir_ref_regular || wrap_status == wrapper)
            res = LDPR_PREVAILING_DEF;
+         else if (wrap_status == wrapped)
+           res = LDPR_RESOLVED_IR;
          else if (is_visible_from_outside (&syms[n], blhe))
            res = def_ironly_exp;
        }
@@ -783,10 +863,12 @@ 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' "
-                "definition: %d, visibility: %d, resolution: %d\n"),
+       einfo (_("%P: %pB: symbol `%s' "
+                "definition: %s, visibility: %s, resolution: %s\n"),
               abfd, syms[n].name,
-              syms[n].def, syms[n].visibility, res);
+              get_lto_kind (syms[n].def),
+              get_lto_visibility (syms[n].visibility),
+              get_lto_resolution (res));
     }
   return LDPS_OK;
 }
@@ -858,7 +940,7 @@ message (int level, const char *format, ...)
       break;
     case LDPL_WARNING:
       {
-       char *newfmt = concat ("%P: warning: ", format, "\n",
+       char *newfmt = concat (_("%P: warning: "), format, "\n",
                               (const char *) NULL);
        vfinfo (stdout, newfmt, args, TRUE);
        free (newfmt);
@@ -868,8 +950,8 @@ message (int level, const char *format, ...)
     case LDPL_ERROR:
     default:
       {
-       char *newfmt = concat (level == LDPL_FATAL ? "%P%F" : "%P%X",
-                              ": error: ", format, "\n",
+       char *newfmt = concat (level == LDPL_FATAL ? "%F" : "%X",
+                              _("%P: error: "), format, "\n",
                               (const char *) NULL);
        fflush (stdout);
        vfinfo (stderr, newfmt, args, TRUE);
@@ -1014,14 +1096,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;
     }
 
@@ -1053,14 +1135,10 @@ plugin_call_claim_file (const struct ld_plugin_input_file *file, int *claimed)
     {
       if (curplug->claim_file_handler)
        {
-         off_t cur_offset;
          enum ld_plugin_status rv;
 
          called_plugin = curplug;
-         cur_offset = lseek (file->fd, 0, SEEK_CUR);
          rv = (*curplug->claim_file_handler) (file, claimed);
-         if (!*claimed)
-           lseek (file->fd, cur_offset, SEEK_SET);
          called_plugin = NULL;
          if (rv != LDPS_OK)
            set_plugin_error (curplug->name);
@@ -1080,7 +1158,7 @@ plugin_strdup (bfd *abfd, const char *str)
   strlength = strlen (str) + 1;
   copy = bfd_alloc (abfd, strlength);
   if (copy == NULL)
-    einfo (_("%P%F: plugin_strdup failed to allocate memory: %s\n"),
+    einfo (_("%F%P: plugin_strdup failed to allocate memory: %s\n"),
           bfd_get_error ());
   memcpy (copy, str, strlength);
   return copy;
@@ -1112,7 +1190,7 @@ plugin_object_p (bfd *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))
@@ -1126,12 +1204,6 @@ plugin_object_p (bfd *ibfd)
     }
 
   file.handle = input;
-  /* The plugin API expects that the file descriptor won't be closed
-     and reused as done by the bfd file cache.  So dup one.  */
-  file.fd = dup (file.fd);
-  if (file.fd < 0)
-    return NULL;
-
   input->abfd = abfd;
   input->view_buffer.addr = NULL;
   input->view_buffer.filesize = 0;
@@ -1145,7 +1217,7 @@ plugin_object_p (bfd *ibfd)
   claimed = 0;
 
   if (plugin_call_claim_file (&file, &claimed))
-    einfo (_("%P%F: %s: plugin reported error claiming file\n"),
+    einfo (_("%F%P: %s: plugin reported error claiming file\n"),
           plugin_error_plugin ());
 
   if (input->fd != -1 && !bfd_plugin_target_p (ibfd->xvec))
@@ -1333,30 +1405,36 @@ plugin_notice (struct bfd_link_info *info,
          ref = TRUE;
        }
 
-      /* Otherwise, it must be a new def.  */
-      else
+
+      /* 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.  */
+      else if (bfd_is_com_section (section))
        {
-         /* 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)))
+         if (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;
            }
+         ref = TRUE;
+       }
 
-         /* 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;
+      /* 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)))
+       {
+         h->type = bfd_link_hash_undefweak;
+         h->u.undef.abfd = sym_bfd;
        }
 
       if (ref)
This page took 0.03047 seconds and 4 git commands to generate.