Support arch-dependent fill
[deliverable/binutils-gdb.git] / ld / ldlang.c
index 76b02f4766586f4af33dabdf6b0220bd4b07f5a4..24fd7da957f59bc052bfdc8344f97fd7999103be 100644 (file)
@@ -1,6 +1,6 @@
 /* Linker command language support.
    Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-   2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
+   2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
    Free Software Foundation, Inc.
 
    This file is part of the GNU Binutils.
@@ -86,13 +86,6 @@ static void print_statement_list (lang_statement_union_type *,
 static void print_statements (void);
 static void print_input_section (asection *, bfd_boolean);
 static bfd_boolean lang_one_common (struct bfd_link_hash_entry *, void *);
-#ifdef ENABLE_PLUGINS
-static void lang_list_insert_after (lang_statement_list_type *destlist,
-                                   lang_statement_list_type *srclist,
-                                   lang_statement_union_type **field);
-static void lang_list_remove_tail (lang_statement_list_type *destlist,
-                                  lang_statement_list_type *origlist);
-#endif /* ENABLE_PLUGINS */
 static void lang_record_phdrs (void);
 static void lang_do_version_exports_section (void);
 static void lang_finalize_version_expr_head
@@ -244,6 +237,9 @@ walk_wild_consider_section (lang_wild_statement_type *ptr,
 {
   struct name_list *list_tmp;
 
+  /* Propagate the section_flag_info from the wild statement to the section.  */
+  s->section_flag_info = ptr->section_flag_list;
+
   /* Don't process sections from files which were excluded.  */
   for (list_tmp = sec->spec.exclude_name_list;
        list_tmp;
@@ -1137,6 +1133,7 @@ new_afile (const char *name,
 #ifdef ENABLE_PLUGINS
   p->claimed = FALSE;
   p->claim_archive = FALSE;
+  p->reload = FALSE;
 #endif /* ENABLE_PLUGINS */
 
   lang_statement_append (&input_file_chain,
@@ -1586,8 +1583,14 @@ lang_output_section_find_by_flags (const asection *sec,
            }
          flags ^= sec->flags;
          if (!(flags & (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD
-                        | SEC_READONLY))
-             && !(look->flags & (SEC_SMALL_DATA | SEC_THREAD_LOCAL)))
+                        | SEC_READONLY | SEC_SMALL_DATA))
+             || (!(flags & (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD
+                            | SEC_READONLY))
+                 && !(look->flags & SEC_SMALL_DATA))
+             || (!(flags & (SEC_THREAD_LOCAL | SEC_ALLOC))
+                 && (look->flags & SEC_THREAD_LOCAL)
+                 && (!(flags & SEC_LOAD)
+                     || (look->flags & SEC_LOAD))))
            found = look;
        }
     }
@@ -2101,9 +2104,6 @@ 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)
     {
@@ -2260,8 +2260,11 @@ lang_add_section (lang_statement_list_type *ptr,
                  lang_output_section_statement_type *output)
 {
   flagword flags = section->flags;
+  struct flag_info *sflag_info = section->section_flag_info;
+
   bfd_boolean discard;
   lang_input_section_type *new_section;
+  bfd *abfd = link_info.output_bfd;
 
   /* Discard sections marked with SEC_EXCLUDE.  */
   discard = (flags & SEC_EXCLUDE) != 0;
@@ -2287,6 +2290,28 @@ lang_add_section (lang_statement_list_type *ptr,
       return;
     }
 
+  if (sflag_info)
+    {
+      if (sflag_info->flags_initialized == FALSE)
+       bfd_lookup_section_flags (&link_info, sflag_info);
+
+      if (sflag_info->only_with_flags != 0
+         && sflag_info->not_with_flags != 0
+          && ((sflag_info->not_with_flags & flags) != 0
+              || (sflag_info->only_with_flags & flags)
+                   != sflag_info->only_with_flags))
+       return;
+
+      if (sflag_info->only_with_flags != 0
+         && (sflag_info->only_with_flags & flags)
+              != sflag_info->only_with_flags)
+       return;
+
+      if (sflag_info->not_with_flags != 0
+          && (sflag_info->not_with_flags & flags) != 0)
+       return;
+    }
+
   if (section->output_section != NULL)
     return;
 
@@ -2756,7 +2781,10 @@ load_symbols (lang_input_statement_type *entry,
       break;
 
     case bfd_object:
-      ldlang_add_file (entry);
+#ifdef ENABLE_PLUGINS
+      if (!entry->reload)
+#endif
+       ldlang_add_file (entry);
       if (trace_files || trace_file_tries)
        info_msg ("%I\n", entry);
       break;
@@ -3023,7 +3051,7 @@ lang_get_output_target (void)
 
   /* No - has the current target been set to something other than
      the default?  */
-  if (current_target != default_target)
+  if (current_target != default_target && current_target != NULL)
     return current_target;
 
   /* No - can we determine the format of the first input file?  */
@@ -3174,26 +3202,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:
          {
@@ -3206,7 +3245,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);
          }
@@ -3225,13 +3265,30 @@ 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,
                                       bfd_archive))
                s->input_statement.loaded = FALSE;
+#ifdef ENABLE_PLUGINS
+             /* When rescanning, reload --as-needed shared libs.  */
+             else if ((mode & OPEN_BFD_RESCAN) != 0
+                      && plugin_insert == NULL
+                      && s->input_statement.loaded
+                      && s->input_statement.add_DT_NEEDED_for_regular
+                      && ((s->input_statement.the_bfd->flags) & DYNAMIC) != 0
+                      && plugin_should_reload (s->input_statement.the_bfd))
+               {
+                 s->input_statement.loaded = FALSE;
+                 s->input_statement.reload = TRUE;
+               }
+#endif
 
              os_tail = lang_output_section_statement.tail;
              lang_list_init (&add);
@@ -3262,6 +3319,12 @@ 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:
          if (s->assignment_statement.exp->assign.hidden)
@@ -4033,9 +4096,8 @@ print_assignment (lang_assignment_statement_type *assignment,
          if (h)
            {
              value = h->u.def.value;
-
-             if (expld.result.section != NULL)
-               value += expld.result.section->vma;
+             value += h->u.def.section->output_section->vma;
+             value += h->u.def.section->output_offset;
 
              minfo ("[0x%V]", value);
            }
@@ -4534,11 +4596,11 @@ dprint_statement (lang_statement_union_type *s, int n)
 static void
 insert_pad (lang_statement_union_type **ptr,
            fill_type *fill,
-           unsigned int alignment_needed,
+           bfd_size_type alignment_needed,
            asection *output_section,
            bfd_vma dot)
 {
-  static fill_type zero_fill = { 1, { 0 } };
+  static fill_type zero_fill;
   lang_statement_union_type *pad = NULL;
 
   if (ptr != &statement_list.head)
@@ -4589,7 +4651,7 @@ size_input_section
   if (!((lang_input_statement_type *) i->owner->usrdata)->just_syms_flag
       && (i->flags & SEC_EXCLUDE) == 0)
     {
-      unsigned int alignment_needed;
+      bfd_size_type alignment_needed;
       asection *o;
 
       /* Align this section first to the input sections requirement,
@@ -5591,8 +5653,9 @@ lang_do_assignments_1 (lang_statement_union_type *s,
 }
 
 void
-lang_do_assignments (void)
+lang_do_assignments (lang_phase_type phase)
 {
+  expld.phase = phase;
   lang_statement_iteration++;
   lang_do_assignments_1 (statement_list.head, abs_output_section, NULL, 0);
 }
@@ -6270,6 +6333,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;
@@ -6384,7 +6451,7 @@ lang_relax_sections (bfd_boolean need_layout)
 
              /* Do all the assignments with our current guesses as to
                 section sizes.  */
-             lang_do_assignments ();
+             lang_do_assignments (lang_assigning_phase_enum);
 
              /* We must do this after lang_do_assignments, because it uses
                 size.  */
@@ -6405,7 +6472,7 @@ lang_relax_sections (bfd_boolean need_layout)
   if (need_layout)
     {
       /* Final extra sizing to report errors.  */
-      lang_do_assignments ();
+      lang_do_assignments (lang_assigning_phase_enum);
       lang_reset_memory_regions ();
       lang_size_sections (NULL, TRUE);
     }
@@ -6443,6 +6510,38 @@ find_replacements_insert_point (void)
      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
@@ -6468,13 +6567,14 @@ 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 ())
     {
       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.  We create a private list of
@@ -6489,7 +6589,8 @@ lang_process (void)
        einfo (_("%P%F: %s: plugin reported error after all symbols read\n"),
               plugin_error_plugin ());
       /* Open any newly added files, updating the file chains.  */
-      open_input_bfds (added.head, FALSE);
+      link_info.loading_lto_outputs = TRUE;
+      open_input_bfds (*added.tail, 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.  */
@@ -6500,24 +6601,28 @@ lang_process (void)
        {
          /* If so, we will insert them into the statement list immediately
             after the first input file that was claimed by the plugin.  */
-         lang_input_statement_type *claim1 = find_replacements_insert_point ();
+         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 (claim1 != NULL);
-         /* Splice the new statement list into the old one after claim1.  */
-         lang_list_insert_after (stat_ptr, &added, &claim1->header.next);
+         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,
-                                 &claim1->next_real_file);
+                                 &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 (claim1->filename)
-           lang_list_insert_after (&file_chain, &files, &claim1->next);
+         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 */
@@ -6610,8 +6715,7 @@ lang_process (void)
 
   /* Do all the assignments, now that we know the final resting places
      of all the symbols.  */
-  expld.phase = lang_final_phase_enum;
-  lang_do_assignments ();
+  lang_do_assignments (lang_final_phase_enum);
 
   ldemul_finish ();
 
@@ -6655,10 +6759,12 @@ lang_add_wild (struct wildcard_spec *filespec,
   new_stmt = new_stat (lang_wild_statement, stat_ptr);
   new_stmt->filename = NULL;
   new_stmt->filenames_sorted = FALSE;
+  new_stmt->section_flag_list = NULL;
   if (filespec != NULL)
     {
       new_stmt->filename = filespec->name;
       new_stmt->filenames_sorted = filespec->sorted == by_name;
+      new_stmt->section_flag_list = filespec->section_flag_list;
     }
   new_stmt->section_list = section_list;
   new_stmt->keep_sections = keep_sections;
@@ -6856,11 +6962,13 @@ lang_leave_output_section_statement (fill_type *fill, const char *memspec,
                    current_section->load_base != NULL,
                    current_section->addr_tree != NULL);
 
-  /* If this section has no load region or base, but has the same
+  /* If this section has no load region or base, but uses the same
      region as the previous section, then propagate the previous
      section's load region.  */
 
-  if (!current_section->lma_region && !current_section->load_base
+  if (current_section->lma_region == NULL
+      && current_section->load_base == NULL
+      && current_section->addr_tree == NULL
       && current_section->region == current_section->prev->region)
     current_section->lma_region = current_section->prev->lma_region;
 
@@ -6941,40 +7049,6 @@ lang_statement_append (lang_statement_list_type *list,
   list->tail = field;
 }
 
-#ifdef ENABLE_PLUGINS
-/* 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 */
-
 /* Set the output format type.  -oformat overrides scripts.  */
 
 void
@@ -7401,10 +7475,6 @@ lang_leave_overlay (etree_type *lma_expr,
 \f
 /* Version handling.  This is only useful for ELF.  */
 
-/* This global variable holds the version tree that we build.  */
-
-struct bfd_elf_version_tree *lang_elf_version_info;
-
 /* If PREV is NULL, return first version pattern matching particular symbol.
    If PREV is non-NULL, return first version pattern matching particular
    symbol after PREV (previously returned by lang_vers_match).  */
@@ -7746,8 +7816,8 @@ lang_register_vers_node (const char *name,
   if (name == NULL)
     name = "";
 
-  if ((name[0] == '\0' && lang_elf_version_info != NULL)
-      || (lang_elf_version_info && lang_elf_version_info->name[0] == '\0'))
+  if (link_info.version_info != NULL
+      && (name[0] == '\0' || link_info.version_info->name[0] == '\0'))
     {
       einfo (_("%X%P: anonymous version tag cannot be combined"
               " with other version tags\n"));
@@ -7756,7 +7826,7 @@ lang_register_vers_node (const char *name,
     }
 
   /* Make sure this node has a unique name.  */
-  for (t = lang_elf_version_info; t != NULL; t = t->next)
+  for (t = link_info.version_info; t != NULL; t = t->next)
     if (strcmp (t->name, name) == 0)
       einfo (_("%X%P: duplicate version tag `%s'\n"), name);
 
@@ -7768,7 +7838,7 @@ lang_register_vers_node (const char *name,
 
   for (e1 = version->globals.list; e1 != NULL; e1 = e1->next)
     {
-      for (t = lang_elf_version_info; t != NULL; t = t->next)
+      for (t = link_info.version_info; t != NULL; t = t->next)
        {
          struct bfd_elf_version_expr *e2;
 
@@ -7795,7 +7865,7 @@ lang_register_vers_node (const char *name,
 
   for (e1 = version->locals.list; e1 != NULL; e1 = e1->next)
     {
-      for (t = lang_elf_version_info; t != NULL; t = t->next)
+      for (t = link_info.version_info; t != NULL; t = t->next)
        {
          struct bfd_elf_version_expr *e2;
 
@@ -7831,7 +7901,7 @@ lang_register_vers_node (const char *name,
   else
     version->vernum = 0;
 
-  for (pp = &lang_elf_version_info; *pp != NULL; pp = &(*pp)->next)
+  for (pp = &link_info.version_info; *pp != NULL; pp = &(*pp)->next)
     ;
   *pp = version;
 }
@@ -7847,7 +7917,7 @@ lang_add_vers_depend (struct bfd_elf_version_deps *list, const char *name)
   ret = (struct bfd_elf_version_deps *) xmalloc (sizeof *ret);
   ret->next = list;
 
-  for (t = lang_elf_version_info; t != NULL; t = t->next)
+  for (t = link_info.version_info; t != NULL; t = t->next)
     {
       if (strcmp (t->name, name) == 0)
        {
This page took 0.050651 seconds and 4 git commands to generate.