Use "switch_to_thread" more thoroughly on gdbserver
[external/binutils.git] / ld / plugin.c
index ffa0dd3..9abeaf0 100644 (file)
@@ -1,5 +1,5 @@
 /* Plugin control for the GNU linker.
-   Copyright (C) 2010-2016 Free Software Foundation, Inc.
+   Copyright (C) 2010-2017 Free Software Foundation, Inc.
 
    This file is part of the GNU Binutils.
 
@@ -430,6 +430,8 @@ asymbol_from_plugin_symbol (bfd *abfd, asymbol *asym,
        default:
          einfo (_("%P%F: unknown ELF symbol visibility: %d!\n"),
                 ldsym->visibility);
+         return LDPS_ERR;
+
        case LDPV_DEFAULT:
          visibility = STV_DEFAULT;
          break;
@@ -627,7 +629,9 @@ is_visible_from_outside (struct ld_plugin_symbol *lsym,
 
   if (bfd_link_relocatable (&link_info))
     return TRUE;
-  if (link_info.export_dynamic || bfd_link_dll (&link_info))
+  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,
@@ -770,7 +774,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;
@@ -1049,9 +1053,14 @@ 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);
@@ -1188,6 +1197,7 @@ plugin_object_p (bfd *ibfd)
 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;
@@ -1256,9 +1266,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,
@@ -1273,6 +1284,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;
@@ -1288,13 +1300,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.  */
@@ -1309,24 +1325,17 @@ 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.  */
       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.  */
-         if (bfd_is_com_section (section))
-           h->non_ir_ref = TRUE;
-
          /* 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
@@ -1341,6 +1350,21 @@ plugin_notice (struct bfd_link_info *info,
              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;
        }
     }