PR ld/17973 LTO file syms
[deliverable/binutils-gdb.git] / ld / ldlang.c
index 4768af7e0d5e50063b018500aede0489b3eadd44..ce333b426cd9370580bbe8d2870eb1cc85b4fd27 100644 (file)
@@ -1,5 +1,5 @@
 /* Linker command language support.
-   Copyright 1991-2013 Free Software Foundation, Inc.
+   Copyright (C) 1991-2015 Free Software Foundation, Inc.
 
    This file is part of the GNU Binutils.
 
@@ -40,6 +40,7 @@
 #include "demangle.h"
 #include "hashtab.h"
 #include "libbfd.h"
+#include "elf-bfd.h"
 #ifdef ENABLE_PLUGINS
 #include "plugin.h"
 #endif /* ENABLE_PLUGINS */
@@ -56,14 +57,13 @@ static struct obstack map_obstack;
 #define obstack_chunk_free free
 static const char *entry_symbol_default = "start";
 static bfd_boolean placed_commons = FALSE;
-static bfd_boolean stripped_excluded_sections = FALSE;
+static bfd_boolean map_head_is_link_order = FALSE;
 static lang_output_section_statement_type *default_common_section;
 static bfd_boolean map_option_f;
 static bfd_vma print_dot;
 static lang_input_statement_type *first_file;
 static const char *current_target;
 static lang_statement_list_type statement_list;
-static struct bfd_hash_table lang_definedness_table;
 static lang_statement_list_type *stat_save[10];
 static lang_statement_list_type **stat_save_ptr = &stat_save[0];
 static struct unique_sections *unique_section_list;
@@ -72,8 +72,6 @@ static struct asneeded_minfo *asneeded_list_head;
 /* Forward declarations.  */
 static void exp_init_os (etree_type *);
 static lang_input_statement_type *lookup_name (const char *);
-static struct bfd_hash_entry *lang_definedness_newfunc
- (struct bfd_hash_entry *, struct bfd_hash_table *, const char *);
 static void insert_undefined (const char *);
 static bfd_boolean sort_def_symbol (struct bfd_link_hash_entry *, void *);
 static void print_statement (lang_statement_union_type *,
@@ -87,6 +85,7 @@ static void lang_record_phdrs (void);
 static void lang_do_version_exports_section (void);
 static void lang_finalize_version_expr_head
   (struct bfd_elf_version_expr_head *);
+static void lang_do_memory_regions (void);
 
 /* Exported variables.  */
 const char *output_target;
@@ -112,8 +111,6 @@ struct asneeded_minfo **asneeded_list_tail;
     DEFINED() need to increment this at the start of the traversal.  */
 int lang_statement_iteration = 0;
 
-etree_type *base; /* Relocation base - or null */
-
 /* Return TRUE if the PATTERN argument is a wildcard pattern.
    Although backslashes are treated specially if a pattern contains
    wildcards, we do not consider the mere presence of a backslash to
@@ -1063,13 +1060,6 @@ new_afile (const char *name,
   p->flags.whole_archive = input_flags.whole_archive;
   p->flags.sysrooted = input_flags.sysrooted;
 
-  if (file_type == lang_input_file_is_l_enum
-      && name[0] == ':' && name[1] != '\0')
-    {
-      file_type = lang_input_file_is_search_file_enum;
-      name = name + 1;
-    }
-
   switch (file_type)
     {
     case lang_input_file_is_symbols_only_enum:
@@ -1083,7 +1073,13 @@ new_afile (const char *name,
       p->local_sym_name = name;
       break;
     case lang_input_file_is_l_enum:
-      p->filename = name;
+      if (name[0] == ':' && name[1] != '\0')
+        {
+          p->filename = name + 1;
+          p->flags.full_name_provided = TRUE;
+        }
+      else
+        p->filename = name;
       p->local_sym_name = concat ("-l", name, (const char *) NULL);
       p->flags.maybe_archive = TRUE;
       p->flags.real = TRUE;
@@ -1120,6 +1116,26 @@ lang_add_input_file (const char *name,
                     lang_input_file_enum_type file_type,
                     const char *target)
 {
+  if (name != NULL && *name == '=')
+    {
+      lang_input_statement_type *ret;
+      char *sysrooted_name
+       = concat (ld_sysroot, name + 1, (const char *) NULL);
+
+      /* We've now forcibly prepended the sysroot, making the input
+        file independent of the context.  Therefore, temporarily
+        force a non-sysrooted context for this statement, so it won't
+        get the sysroot prepended again when opened.  (N.B. if it's a
+        script, any child nodes with input files starting with "/"
+        will be handled as "sysrooted" as they'll be found to be
+        within the sysroot subdirectory.)  */
+      unsigned int outer_sysrooted = input_flags.sysrooted;
+      input_flags.sysrooted = 0;
+      ret = new_afile (sysrooted_name, file_type, target, TRUE);
+      input_flags.sysrooted = outer_sysrooted;
+      return ret;
+    }
+
   return new_afile (name, file_type, target, TRUE);
 }
 
@@ -1223,14 +1239,6 @@ lang_init (void)
 
   abs_output_section->bfd_section = bfd_abs_section_ptr;
 
-  /* The value "13" is ad-hoc, somewhat related to the expected number of
-     assignments in a linker script.  */
-  if (!bfd_hash_table_init_n (&lang_definedness_table,
-                             lang_definedness_newfunc,
-                             sizeof (struct lang_definedness_hash_entry),
-                             13))
-    einfo (_("%P%F: can not create hash table: %E\n"));
-
   asneeded_list_head = NULL;
   asneeded_list_tail = &asneeded_list_head;
 }
@@ -1238,8 +1246,6 @@ lang_init (void)
 void
 lang_finish (void)
 {
-  bfd_link_hash_table_free (link_info.output_bfd, link_info.hash);
-  bfd_hash_table_free (&lang_definedness_table);
   output_section_statement_table_free ();
 }
 
@@ -1300,7 +1306,9 @@ lang_memory_region_lookup (const char *const name, bfd_boolean create)
   new_region->name_list.name = xstrdup (name);
   new_region->name_list.next = NULL;
   new_region->next = NULL;
+  new_region->origin_exp = NULL;
   new_region->origin = 0;
+  new_region->length_exp = NULL;
   new_region->length = ~(bfd_size_type) 0;
   new_region->current = 0;
   new_region->last_os = NULL;
@@ -2124,6 +2132,8 @@ lang_map (void)
     }
   lang_statement_iteration++;
   print_statements ();
+
+  ldemul_extra_map_file_text (link_info.output_bfd, &link_info, config.map_file);
 }
 
 static bfd_boolean
@@ -2412,8 +2422,7 @@ lang_add_section (lang_statement_list_type *ptr,
 
   section->output_section = output->bfd_section;
 
-  if (!link_info.relocatable
-      && !stripped_excluded_sections)
+  if (!map_head_is_link_order)
     {
       asection *s = output->bfd_section->map_tail.s;
       output->bfd_section->map_tail.s = section;
@@ -2792,9 +2801,7 @@ load_symbols (lang_input_statement_type *entry,
       break;
 
     case bfd_object:
-#ifdef ENABLE_PLUGINS
       if (!entry->flags.reload)
-#endif
        ldlang_add_file (entry);
       if (trace_files || verbose)
        info_msg ("%I\n", entry);
@@ -3270,38 +3277,33 @@ open_input_bfds (lang_statement_union_type *s, enum open_bfd_mode mode)
            {
              lang_statement_union_type **os_tail;
              lang_statement_list_type add;
+             bfd *abfd;
 
              s->input_statement.target = current_target;
 
              /* 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.  Do the same for a rescan.  */
+                has been loaded already.  Do the same for a rescan.
+                Likewise reload --as-needed shared libs.  */
              if (mode != OPEN_BFD_NORMAL
 #ifdef ENABLE_PLUGINS
                  && ((mode & OPEN_BFD_RESCAN) == 0
                      || plugin_insert == NULL)
 #endif
-                 && !s->input_statement.flags.whole_archive
                  && s->input_statement.flags.loaded
-                 && s->input_statement.the_bfd != NULL
-                 && bfd_check_format (s->input_statement.the_bfd,
-                                      bfd_archive))
-               s->input_statement.flags.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.flags.loaded
-                      && s->input_statement.flags.add_DT_NEEDED_for_regular
-                      && s->input_statement.the_bfd != NULL
-                      && ((s->input_statement.the_bfd->flags) & DYNAMIC) != 0
-                      && plugin_should_reload (s->input_statement.the_bfd))
+                 && (abfd = s->input_statement.the_bfd) != NULL
+                 && ((bfd_get_format (abfd) == bfd_archive
+                      && !s->input_statement.flags.whole_archive)
+                     || (bfd_get_format (abfd) == bfd_object
+                         && ((abfd->flags) & DYNAMIC) != 0
+                         && s->input_statement.flags.add_DT_NEEDED_for_regular
+                         && bfd_get_flavour (abfd) == bfd_target_elf_flavour
+                         && (elf_dyn_lib_class (abfd) & DYN_AS_NEEDED) != 0)))
                {
                  s->input_statement.flags.loaded = FALSE;
                  s->input_statement.flags.reload = TRUE;
                }
-#endif
 
              os_tail = lang_output_section_statement.tail;
              lang_list_init (&add);
@@ -3354,65 +3356,6 @@ open_input_bfds (lang_statement_union_type *s, enum open_bfd_mode mode)
     einfo ("%F");
 }
 
-/* New-function for the definedness hash table.  */
-
-static struct bfd_hash_entry *
-lang_definedness_newfunc (struct bfd_hash_entry *entry,
-                         struct bfd_hash_table *table ATTRIBUTE_UNUSED,
-                         const char *name ATTRIBUTE_UNUSED)
-{
-  struct lang_definedness_hash_entry *ret
-    = (struct lang_definedness_hash_entry *) entry;
-
-  if (ret == NULL)
-    ret = (struct lang_definedness_hash_entry *)
-      bfd_hash_allocate (table, sizeof (struct lang_definedness_hash_entry));
-
-  if (ret == NULL)
-    einfo (_("%P%F: bfd_hash_allocate failed creating symbol %s\n"), name);
-
-  ret->by_object = 0;
-  ret->by_script = 0;
-  ret->iteration = 0;
-  return &ret->root;
-}
-
-/* Called during processing of linker script script expressions.
-   For symbols assigned in a linker script, return a struct describing
-   where the symbol is defined relative to the current expression,
-   otherwise return NULL.  */
-
-struct lang_definedness_hash_entry *
-lang_symbol_defined (const char *name)
-{
-  return ((struct lang_definedness_hash_entry *)
-         bfd_hash_lookup (&lang_definedness_table, name, FALSE, FALSE));
-}
-
-/* Update the definedness state of NAME.  */
-
-void
-lang_update_definedness (const char *name, struct bfd_link_hash_entry *h)
-{
-  struct lang_definedness_hash_entry *defentry
-    = (struct lang_definedness_hash_entry *)
-    bfd_hash_lookup (&lang_definedness_table, name, TRUE, FALSE);
-
-  if (defentry == NULL)
-    einfo (_("%P%F: bfd_hash_lookup failed creating symbol %s\n"), name);
-
-  /* If the symbol was already defined, and not by a script, then it
-     must be defined by an object file.  */
-  if (!defentry->by_script
-      && h->type != bfd_link_hash_undefined
-      && h->type != bfd_link_hash_common
-      && h->type != bfd_link_hash_new)
-    defentry->by_object = 1;
-
-  defentry->by_script = 1;
-  defentry->iteration = lang_statement_iteration;
-}
-
 /* Add the supplied name to the symbol table as an undefined reference.
    This is a two step process as the symbol table doesn't even exist at
    the time the ld command line is processed.  First we put the name
@@ -3920,10 +3863,6 @@ strip_excluded_output_sections (void)
              }
        }
 
-      /* TODO: Don't just junk map_head.s, turn them into link_orders.  */
-      output_section->map_head.link_order = NULL;
-      output_section->map_tail.link_order = NULL;
-
       if (exclude)
        {
          /* We don't set bfd_section to NULL since bfd_section of the
@@ -3935,10 +3874,42 @@ strip_excluded_output_sections (void)
          link_info.output_bfd->section_count--;
        }
     }
+}
+
+/* Called from ldwrite to clear out asection.map_head and
+   asection.map_tail for use as link_orders in ldwrite.
+   FIXME: Except for sh64elf.em which starts creating link_orders in
+   its after_allocation routine so needs to call it early.  */
+
+void
+lang_clear_os_map (void)
+{
+  lang_output_section_statement_type *os;
+
+  if (map_head_is_link_order)
+    return;
+
+  for (os = &lang_output_section_statement.head->output_section_statement;
+       os != NULL;
+       os = os->next)
+    {
+      asection *output_section;
+
+      if (os->constraint < 0)
+       continue;
+
+      output_section = os->bfd_section;
+      if (output_section == NULL)
+       continue;
+
+      /* TODO: Don't just junk map_head.s, turn them into link_orders.  */
+      output_section->map_head.link_order = NULL;
+      output_section->map_tail.link_order = NULL;
+    }
 
   /* Stop future calls to lang_add_section from messing with map_head
      and map_tail link_order fields.  */
-  stripped_excluded_sections = TRUE;
+  map_head_is_link_order = TRUE;
 }
 
 static void
@@ -4015,7 +3986,12 @@ print_assignment (lang_assignment_statement_type *assignment,
   osec = output_section->bfd_section;
   if (osec == NULL)
     osec = bfd_abs_section_ptr;
-  exp_fold_tree (tree, osec, &print_dot);
+
+  if (assignment->exp->type.node_class != etree_provide)
+    exp_fold_tree (tree, osec, &print_dot);
+  else
+    expld.result.valid_p = FALSE;
+
   if (expld.result.valid_p)
     {
       bfd_vma value;
@@ -4053,7 +4029,10 @@ print_assignment (lang_assignment_statement_type *assignment,
     }
   else
     {
-      minfo ("*undef*   ");
+      if (assignment->exp->type.node_class == etree_provide)
+        minfo ("[!provide]");
+      else
+        minfo ("*undef*   ");
 #ifdef BFD64
       minfo ("        ");
 #endif
@@ -4595,12 +4574,15 @@ size_input_section
 {
   lang_input_section_type *is = &((*this_ptr)->input_section);
   asection *i = is->section;
+  asection *o = output_section_statement->bfd_section;
 
-  if (i->sec_info_type != SEC_INFO_TYPE_JUST_SYMS
-      && (i->flags & SEC_EXCLUDE) == 0)
+  if (i->sec_info_type == SEC_INFO_TYPE_JUST_SYMS)
+    i->output_offset = i->vma - o->vma;
+  else if ((i->flags & SEC_EXCLUDE) != 0)
+    i->output_offset = dot - o->vma;
+  else
     {
       bfd_size_type alignment_needed;
-      asection *o;
 
       /* Align this section first to the input sections requirement,
         then to the output section's requirement.  If this alignment
@@ -4610,7 +4592,6 @@ size_input_section
       if (output_section_statement->subsection_alignment != -1)
        i->alignment_power = output_section_statement->subsection_alignment;
 
-      o = output_section_statement->bfd_section;
       if (o->alignment_power < i->alignment_power)
        o->alignment_power = i->alignment_power;
 
@@ -4623,17 +4604,12 @@ size_input_section
        }
 
       /* Remember where in the output section this input section goes.  */
-
       i->output_offset = dot - o->vma;
 
       /* Mark how big the output section must be to contain this now.  */
       dot += TO_ADDR (i->size);
       o->size = TO_SIZE (dot - o->vma);
     }
-  else
-    {
-      i->output_offset = i->vma - output_section_statement->bfd_section->vma;
-    }
 
   return dot;
 }
@@ -5214,7 +5190,7 @@ lang_size_sections_1
                  *relax = TRUE;
              }
            dot = size_input_section (prev, output_section_statement,
-                                     output_section_statement->fill, dot);
+                                     fill, dot);
          }
          break;
 
@@ -5986,7 +5962,7 @@ lang_common (void)
          for (power = 0; power <= 4; power++)
            bfd_link_hash_traverse (link_info.hash, lang_one_common, &power);
 
-         power = UINT_MAX;
+         power = (unsigned int) -1;
          bfd_link_hash_traverse (link_info.hash, lang_one_common, &power);
        }
     }
@@ -6218,11 +6194,11 @@ ldlang_add_file (lang_input_statement_type *entry)
 
   /* The BFD linker needs to have a list of all input BFDs involved in
      a link.  */
-  ASSERT (entry->the_bfd->link_next == NULL);
+  ASSERT (entry->the_bfd->link.next == NULL);
   ASSERT (entry->the_bfd != link_info.output_bfd);
 
   *link_info.input_bfds_tail = entry->the_bfd;
-  link_info.input_bfds_tail = &entry->the_bfd->link_next;
+  link_info.input_bfds_tail = &entry->the_bfd->link.next;
   entry->the_bfd->usrdata = entry;
   bfd_set_gp_size (entry->the_bfd, g_switch_value);
 
@@ -6319,7 +6295,6 @@ lang_final (void)
 
   new_stmt = new_stat (lang_output_statement, stat_ptr);
   new_stmt->name = output_filename;
-
 }
 
 /* Reset the current counters in the regions.  */
@@ -6649,7 +6624,7 @@ lang_process (void)
   open_input_bfds (statement_list.head, OPEN_BFD_NORMAL);
 
 #ifdef ENABLE_PLUGINS
-  if (plugin_active_plugins_p ())
+  if (link_info.lto_plugin_active)
     {
       lang_statement_list_type added;
       lang_statement_list_type files, inputfiles;
@@ -6668,7 +6643,6 @@ 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.  */
-      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);
@@ -6734,14 +6708,16 @@ lang_process (void)
   /* PR 13683: We must rerun the assignments prior to running garbage
      collection in order to make sure that all symbol aliases are resolved.  */
   lang_do_assignments (lang_mark_phase_enum);
-  expld.phase = lang_first_phase_enum;
 
-  /* Remove unreferenced sections if asked to.  */
-  lang_gc_sections ();
+  lang_do_memory_regions();
+  expld.phase = lang_first_phase_enum;
 
   /* Size up the common data.  */
   lang_common ();
 
+  /* Remove unreferenced sections if asked to.  */
+  lang_gc_sections ();
+
   /* Update wild statements.  */
   update_wild_statements (statement_list.head);
 
@@ -7997,6 +7973,37 @@ lang_do_version_exports_section (void)
                           lang_new_vers_node (greg, lreg), NULL);
 }
 
+/* Evaluate LENGTH and ORIGIN parts of MEMORY spec */
+
+static void
+lang_do_memory_regions (void)
+{
+  lang_memory_region_type *r = lang_memory_region_list;
+
+  for (; r != NULL; r = r->next)
+    {
+      if (r->origin_exp)
+      {
+        exp_fold_tree_no_dot (r->origin_exp);
+        if (expld.result.valid_p)
+          {
+            r->origin = expld.result.value;
+            r->current = r->origin;
+          }
+        else
+          einfo (_("%F%P: invalid origin for memory region %s\n"), r->name_list.name);
+      }
+      if (r->length_exp)
+      {
+        exp_fold_tree_no_dot (r->length_exp);
+        if (expld.result.valid_p)
+          r->length = expld.result.value;
+        else
+          einfo (_("%F%P: invalid length for memory region %s\n"), r->name_list.name);
+      }
+    }
+}
+
 void
 lang_add_unique (const char *name)
 {
This page took 0.028985 seconds and 4 git commands to generate.