* configure.ac: Separate cases disabling Java and Java libraries
[deliverable/binutils-gdb.git] / ld / ldlang.c
index 4fe80a8f6ca8bf44fb79251d6e61152dbc3e3529..2c07fa4d358c9344d644d76961a5d65b67b0bb91 100644 (file)
@@ -23,6 +23,7 @@
 #include "sysdep.h"
 #include "bfd.h"
 #include "libiberty.h"
+#include "filenames.h"
 #include "safe-ctype.h"
 #include "obstack.h"
 #include "bfdlink.h"
@@ -108,7 +109,6 @@ bfd_boolean delete_output_file_on_failure = FALSE;
 struct lang_phdr *lang_phdr_list;
 struct lang_nocrossrefs *nocrossref_list;
 bfd_boolean missing_file = FALSE;
-int ld_compatibility;
 
  /* Functions that traverse the linker script and might evaluate
     DEFINED() need to increment this.  */
@@ -1127,6 +1127,10 @@ new_afile (const char *name,
   p->whole_archive = whole_archive;
   p->loaded = FALSE;
   p->missing_file = FALSE;
+#ifdef ENABLE_PLUGINS
+  p->claimed = FALSE;
+  p->claim_archive = FALSE;
+#endif /* ENABLE_PLUGINS */
 
   lang_statement_append (&input_file_chain,
                         (lang_statement_union_type *) p,
@@ -1809,7 +1813,7 @@ lang_insert_orphan (asection *s,
          sprintf (symname + (symname[0] != 0), "__start_%s", secname);
          e_align = exp_unop (ALIGN_K,
                              exp_intop ((bfd_vma) 1 << s->alignment_power));
-         lang_add_assignment (exp_assop ('=', ".", e_align));
+         lang_add_assignment (exp_assign (".", e_align));
          lang_add_assignment (exp_provide (symname,
                                            exp_unop (ABSOLUTE,
                                                      exp_nameop (NAME, ".")),
@@ -2090,6 +2094,9 @@ static bfd_boolean
 sort_def_symbol (struct bfd_link_hash_entry *hash_entry,
                 void *info ATTRIBUTE_UNUSED)
 {
+  if (hash_entry->type == bfd_link_hash_warning)
+    hash_entry = (struct bfd_link_hash_entry *) hash_entry->u.i.link;
+
   if (hash_entry->type == bfd_link_hash_defined
       || hash_entry->type == bfd_link_hash_defweak)
     {
@@ -2444,7 +2451,7 @@ wild_sort (lang_wild_statement_type *wild,
              la = FALSE;
            }
 
-         i = strcmp (fn, ln);
+         i = filename_cmp (fn, ln);
          if (i > 0)
            continue;
          else if (i < 0)
@@ -2457,7 +2464,7 @@ wild_sort (lang_wild_statement_type *wild,
              if (la)
                ln = ls->section->owner->filename;
 
-             i = strcmp (fn, ln);
+             i = filename_cmp (fn, ln);
              if (i > 0)
                continue;
              else if (i < 0)
@@ -2570,7 +2577,7 @@ lookup_name (const char *name)
       const char *filename = search->local_sym_name;
 
       if (filename != NULL
-         && strcmp (filename, name) == 0)
+         && filename_cmp (filename, name) == 0)
        break;
     }
 
@@ -2637,7 +2644,7 @@ check_excluded_libs (bfd *abfd)
          return;
        }
 
-      if (strncmp (lib->name, filename, len) == 0
+      if (filename_ncmp (lib->name, filename, len) == 0
          && (filename[len] == '\0'
              || (filename[len] == '.' && filename[len + 1] == 'a'
                  && filename[len + 2] == '\0')))
@@ -3160,26 +3167,37 @@ init_opb (void)
 
 /* Open all the input files.  */
 
+enum open_bfd_mode
+  {
+    OPEN_BFD_NORMAL = 0,
+    OPEN_BFD_FORCE = 1,
+    OPEN_BFD_RESCAN = 2
+  };
+#ifdef ENABLE_PLUGINS
+static lang_input_statement_type *plugin_insert = NULL;
+#endif
+
 static void
-open_input_bfds (lang_statement_union_type *s, bfd_boolean force)
+open_input_bfds (lang_statement_union_type *s, enum open_bfd_mode mode)
 {
   for (; s != NULL; s = s->header.next)
     {
       switch (s->header.type)
        {
        case lang_constructors_statement_enum:
-         open_input_bfds (constructor_list.head, force);
+         open_input_bfds (constructor_list.head, mode);
          break;
        case lang_output_section_statement_enum:
-         open_input_bfds (s->output_section_statement.children.head, force);
+         open_input_bfds (s->output_section_statement.children.head, mode);
          break;
        case lang_wild_statement_enum:
          /* Maybe we should load the file's symbols.  */
-         if (s->wild_statement.filename
+         if ((mode & OPEN_BFD_RESCAN) == 0
+             && s->wild_statement.filename
              && !wildcardp (s->wild_statement.filename)
              && !archive_path (s->wild_statement.filename))
            lookup_name (s->wild_statement.filename);
-         open_input_bfds (s->wild_statement.children.head, force);
+         open_input_bfds (s->wild_statement.children.head, mode);
          break;
        case lang_group_statement_enum:
          {
@@ -3192,7 +3210,8 @@ open_input_bfds (lang_statement_union_type *s, bfd_boolean force)
            do
              {
                undefs = link_info.hash->undefs_tail;
-               open_input_bfds (s->group_statement.children.head, TRUE);
+               open_input_bfds (s->group_statement.children.head,
+                                mode | OPEN_BFD_FORCE);
              }
            while (undefs != link_info.hash->undefs_tail);
          }
@@ -3211,8 +3230,12 @@ open_input_bfds (lang_statement_union_type *s, bfd_boolean force)
              /* If we are being called from within a group, and this
                 is an archive which has already been searched, then
                 force it to be researched unless the whole archive
-                has been loaded already.  */
-             if (force
+                has been loaded already.  Do the same for a rescan.  */
+             if (mode != OPEN_BFD_NORMAL
+#ifdef ENABLE_PLUGINS
+                 && ((mode & OPEN_BFD_RESCAN) == 0
+                     || plugin_insert == NULL)
+#endif
                  && !s->input_statement.whole_archive
                  && s->input_statement.loaded
                  && bfd_check_format (s->input_statement.the_bfd,
@@ -3248,9 +3271,17 @@ open_input_bfds (lang_statement_union_type *s, bfd_boolean force)
                    }
                }
            }
+#ifdef ENABLE_PLUGINS
+         /* If we have found the point at which a plugin added new
+            files, clear plugin_insert to enable archive rescan.  */
+         if (&s->input_statement == plugin_insert)
+           plugin_insert = NULL;
+#endif
          break;
        case lang_assignment_statement_enum:
-         exp_fold_tree_no_dot (s->assignment_statement.exp);
+         if (s->assignment_statement.exp->assign.hidden)
+           /* This is from a --defsym on the command line.  */
+           exp_fold_tree_no_dot (s->assignment_statement.exp);
          break;
        default:
          break;
@@ -5738,6 +5769,11 @@ lang_check (void)
 
   for (file = file_chain.head; file != NULL; file = file->input_statement.next)
     {
+#ifdef ENABLE_PLUGINS
+      /* Don't check format of files claimed by plugin.  */
+      if (file->input_statement.claimed)
+       continue;
+#endif /* ENABLE_PLUGINS */
       input_bfd = file->input_statement.the_bfd;
       compatible
        = bfd_arch_get_compatible (input_bfd, link_info.output_bfd,
@@ -6249,6 +6285,10 @@ lang_gc_sections (void)
       LANG_FOR_EACH_INPUT_STATEMENT (f)
        {
          asection *sec;
+#ifdef ENABLE_PLUGINS
+         if (f->claimed)
+           continue;
+#endif
          for (sec = f->the_bfd->sections; sec != NULL; sec = sec->next)
            if ((sec->flags & SEC_DEBUGGING) == 0)
              sec->flags &= ~SEC_EXCLUDE;
@@ -6390,6 +6430,72 @@ lang_relax_sections (bfd_boolean need_layout)
     }
 }
 
+#ifdef ENABLE_PLUGINS
+/* Find the insert point for the plugin's replacement files.  We
+   place them after the first claimed real object file, or if the
+   first claimed object is an archive member, after the last real
+   object file immediately preceding the archive.  In the event
+   no objects have been claimed at all, we return the first dummy
+   object file on the list as the insert point; that works, but
+   the callee must be careful when relinking the file_chain as it
+   is not actually on that chain, only the statement_list and the
+   input_file list; in that case, the replacement files must be
+   inserted at the head of the file_chain.  */
+
+static lang_input_statement_type *
+find_replacements_insert_point (void)
+{
+  lang_input_statement_type *claim1, *lastobject;
+  lastobject = &input_file_chain.head->input_statement;
+  for (claim1 = &file_chain.head->input_statement;
+       claim1 != NULL;
+       claim1 = &claim1->next->input_statement)
+    {
+      if (claim1->claimed)
+       return claim1->claim_archive ? lastobject : claim1;
+      /* Update lastobject if this is a real object file.  */
+      if (claim1->the_bfd && (claim1->the_bfd->my_archive == NULL))
+       lastobject = claim1;
+    }
+  /* No files were claimed by the plugin.  Choose the last object
+     file found on the list (maybe the first, dummy entry) as the
+     insert point.  */
+  return lastobject;
+}
+
+/* Insert SRCLIST into DESTLIST after given element by chaining
+   on FIELD as the next-pointer.  (Counterintuitively does not need
+   a pointer to the actual after-node itself, just its chain field.)  */
+
+static void
+lang_list_insert_after (lang_statement_list_type *destlist,
+                       lang_statement_list_type *srclist,
+                       lang_statement_union_type **field)
+{
+  *(srclist->tail) = *field;
+  *field = srclist->head;
+  if (destlist->tail == field)
+    destlist->tail = srclist->tail;
+}
+
+/* Detach new nodes added to DESTLIST since the time ORIGLIST
+   was taken as a copy of it and leave them in ORIGLIST.  */
+
+static void
+lang_list_remove_tail (lang_statement_list_type *destlist,
+                      lang_statement_list_type *origlist)
+{
+  union lang_statement_union **savetail;
+  /* Check that ORIGLIST really is an earlier state of DESTLIST.  */
+  ASSERT (origlist->head == destlist->head);
+  savetail = origlist->tail;
+  origlist->head = *(savetail);
+  origlist->tail = destlist->tail;
+  destlist->tail = savetail;
+  *savetail = NULL;
+}
+#endif /* ENABLE_PLUGINS */
+
 void
 lang_process (void)
 {
@@ -6413,24 +6519,62 @@ lang_process (void)
 
   /* Create a bfd for each input file.  */
   current_target = default_target;
-  open_input_bfds (statement_list.head, FALSE);
+  open_input_bfds (statement_list.head, OPEN_BFD_NORMAL);
 
 #ifdef ENABLE_PLUGINS
+  if (plugin_active_plugins_p ())
     {
-      union lang_statement_union **listend;
+      lang_statement_list_type added;
+      lang_statement_list_type files, inputfiles;
+
       /* Now all files are read, let the plugin(s) decide if there
         are any more to be added to the link before we call the
-        emulation's after_open hook.  */
-      listend = statement_list.tail;
-      ASSERT (!*listend);
+        emulation's after_open hook.  We create a private list of
+        input statements for this purpose, which we will eventually
+        insert into the global statment list after the first claimed
+        file.  */
+      added = *stat_ptr;
+      /* We need to manipulate all three chains in synchrony.  */
+      files = file_chain;
+      inputfiles = input_file_chain;
       if (plugin_call_all_symbols_read ())
        einfo (_("%P%F: %s: plugin reported error after all symbols read\n"),
               plugin_error_plugin ());
-      /* If any new files were added, they will be on the end of the
-        statement list, and we can open them now by getting open_input_bfds
-        to carry on from where it ended last time.  */
-      if (*listend)
-       open_input_bfds (*listend, FALSE);
+      /* Open any newly added files, updating the file chains.  */
+      open_input_bfds (added.head, OPEN_BFD_NORMAL);
+      /* Restore the global list pointer now they have all been added.  */
+      lang_list_remove_tail (stat_ptr, &added);
+      /* And detach the fresh ends of the file lists.  */
+      lang_list_remove_tail (&file_chain, &files);
+      lang_list_remove_tail (&input_file_chain, &inputfiles);
+      /* Were any new files added?  */
+      if (added.head != NULL)
+       {
+         /* If so, we will insert them into the statement list immediately
+            after the first input file that was claimed by the plugin.  */
+         plugin_insert = find_replacements_insert_point ();
+         /* If a plugin adds input files without having claimed any, we
+            don't really have a good idea where to place them.  Just putting
+            them at the start or end of the list is liable to leave them
+            outside the crtbegin...crtend range.  */
+         ASSERT (plugin_insert != NULL);
+         /* Splice the new statement list into the old one.  */
+         lang_list_insert_after (stat_ptr, &added,
+                                 &plugin_insert->header.next);
+         /* Likewise for the file chains.  */
+         lang_list_insert_after (&input_file_chain, &inputfiles,
+                                 &plugin_insert->next_real_file);
+         /* We must be careful when relinking file_chain; we may need to
+            insert the new files at the head of the list if the insert
+            point chosen is the dummy first input file.  */
+         if (plugin_insert->filename)
+           lang_list_insert_after (&file_chain, &files, &plugin_insert->next);
+         else
+           lang_list_insert_after (&file_chain, &files, &file_chain.head);
+
+         /* Rescan archives in case new undefined symbols have appeared.  */
+         open_input_bfds (statement_list.head, OPEN_BFD_RESCAN);
+       }
     }
 #endif /* ENABLE_PLUGINS */
 
@@ -7229,7 +7373,7 @@ lang_leave_overlay (etree_type *lma_expr,
      overlay region.  */
   if (overlay_list != NULL)
     overlay_list->os->update_dot_tree
-      = exp_assop ('=', ".", exp_binop ('+', overlay_vma, overlay_max));
+      = exp_assign (".", exp_binop ('+', overlay_vma, overlay_max));
 
   l = overlay_list;
   while (l != NULL)
@@ -7292,19 +7436,29 @@ lang_vers_match (struct bfd_elf_version_expr_head *head,
                 struct bfd_elf_version_expr *prev,
                 const char *sym)
 {
+  const char *c_sym;
   const char *cxx_sym = sym;
   const char *java_sym = sym;
   struct bfd_elf_version_expr *expr = NULL;
+  enum demangling_styles curr_style;
+
+  curr_style = CURRENT_DEMANGLING_STYLE;
+  cplus_demangle_set_style (no_demangling);
+  c_sym = bfd_demangle (link_info.output_bfd, sym, DMGL_NO_OPTS);
+  if (!c_sym)
+    c_sym = sym;
+  cplus_demangle_set_style (curr_style);
 
   if (head->mask & BFD_ELF_VERSION_CXX_TYPE)
     {
-      cxx_sym = cplus_demangle (sym, DMGL_PARAMS | DMGL_ANSI);
+      cxx_sym = bfd_demangle (link_info.output_bfd, sym,
+                             DMGL_PARAMS | DMGL_ANSI);
       if (!cxx_sym)
        cxx_sym = sym;
     }
   if (head->mask & BFD_ELF_VERSION_JAVA_TYPE)
     {
-      java_sym = cplus_demangle (sym, DMGL_JAVA);
+      java_sym = bfd_demangle (link_info.output_bfd, sym, DMGL_JAVA);
       if (!java_sym)
        java_sym = sym;
     }
@@ -7318,10 +7472,10 @@ lang_vers_match (struct bfd_elf_version_expr_head *head,
        case 0:
          if (head->mask & BFD_ELF_VERSION_C_TYPE)
            {
-             e.pattern = sym;
+             e.pattern = c_sym;
              expr = (struct bfd_elf_version_expr *)
                   htab_find ((htab_t) head->htab, &e);
-             while (expr && strcmp (expr->pattern, sym) == 0)
+             while (expr && strcmp (expr->pattern, c_sym) == 0)
                if (expr->mask == BFD_ELF_VERSION_C_TYPE)
                  goto out_ret;
                else
@@ -7379,12 +7533,14 @@ lang_vers_match (struct bfd_elf_version_expr_head *head,
       else if (expr->mask == BFD_ELF_VERSION_CXX_TYPE)
        s = cxx_sym;
       else
-       s = sym;
+       s = c_sym;
       if (fnmatch (expr->pattern, s, 0) == 0)
        break;
     }
 
  out_ret:
+  if (c_sym != sym)
+    free ((char *) c_sym);
   if (cxx_sym != sym)
     free ((char *) cxx_sym);
   if (java_sym != sym)
@@ -7845,3 +8001,32 @@ lang_append_dynamic_list_cpp_new (void)
 
   lang_append_dynamic_list (dynamic);
 }
+
+/* Scan a space and/or comma separated string of features.  */
+
+void
+lang_ld_feature (char *str)
+{
+  char *p, *q;
+
+  p = str;
+  while (*p)
+    {
+      char sep;
+      while (*p == ',' || ISSPACE (*p))
+       ++p;
+      if (!*p)
+       break;
+      q = p + 1;
+      while (*q && *q != ',' && !ISSPACE (*q))
+       ++q;
+      sep = *q;
+      *q = 0;
+      if (strcasecmp (p, "SANE_EXPR") == 0)
+       config.sane_expr = TRUE;
+      else
+       einfo (_("%X%P: unknown feature `%s'\n"), p);
+      *q = sep;
+      p = q;
+    }
+}
This page took 0.030347 seconds and 4 git commands to generate.