* ldlang.c (lang_size_sections_1): Don't check mem regions for
[deliverable/binutils-gdb.git] / ld / ldlang.c
index 3ff4d819b0a3192a79845dce46eb2e37f48bd871..7b026b0f6b969d574325b858e7a140fd0ba9f6e2 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
+   2001, 2002, 2003, 2004, 2005, 2006
    Free Software Foundation, Inc.
 
    This file is part of GLD, the Gnu Linker.
@@ -81,6 +81,7 @@ static void print_statement (lang_statement_union_type *,
 static void print_statement_list (lang_statement_union_type *,
                                  lang_output_section_statement_type *);
 static void print_statements (void);
+static void print_input_section (asection *);
 static bfd_boolean lang_one_common (struct bfd_link_hash_entry *, void *);
 static void lang_record_phdrs (void);
 static void lang_do_version_exports_section (void);
@@ -783,6 +784,7 @@ new_afile (const char *name,
   else
     {
       p = stat_alloc (sizeof (lang_input_statement_type));
+      p->header.type = lang_input_statement_enum;
       p->header.next = NULL;
     }
 
@@ -871,34 +873,72 @@ lang_add_input_file (const char *name,
 struct output_statement_hash_entry
 {
   struct bfd_hash_entry root;
-  lang_output_section_statement_type *entry;
+  lang_output_section_statement_type os;
 };
 
 /* The hash table.  */
 
 static struct bfd_hash_table output_statement_table;
 
-/* Support routines for the hash table used by lang_output_section_find_1,
+/* Support routines for the hash table used by lang_output_section_find,
    initialize the table, fill in an entry and remove the table.  */
 
 static struct bfd_hash_entry *
-output_statement_newfunc (struct bfd_hash_entry *entry ATTRIBUTE_UNUSED
+output_statement_newfunc (struct bfd_hash_entry *entry, 
                          struct bfd_hash_table *table,
-                         const char *string ATTRIBUTE_UNUSED)
+                         const char *string)
 {
-  struct output_statement_hash_entry *ret
-    = bfd_hash_allocate (table,
-                        sizeof (struct output_statement_hash_entry));
-  ret->entry = NULL;
-  return (struct bfd_hash_entry *) ret;
+  lang_output_section_statement_type **nextp;
+  struct output_statement_hash_entry *ret;
+
+  if (entry == NULL)
+    {
+      entry = bfd_hash_allocate (table, sizeof (*ret));
+      if (entry == NULL)
+       return entry;
+    }
+
+  entry = bfd_hash_newfunc (entry, table, string);
+  if (entry == NULL)
+    return entry;
+
+  ret = (struct output_statement_hash_entry *) entry;
+  memset (&ret->os, 0, sizeof (ret->os));
+  ret->os.header.type = lang_output_section_statement_enum;
+  ret->os.subsection_alignment = -1;
+  ret->os.section_alignment = -1;
+  ret->os.block_value = 1;
+  lang_list_init (&ret->os.children);
+  lang_statement_append (stat_ptr,
+                        (lang_statement_union_type *) &ret->os,
+                        &ret->os.header.next);
+
+  /* For every output section statement added to the list, except the
+     first one, lang_output_section_statement.tail points to the "next"
+     field of the last element of the list.  */
+  if (lang_output_section_statement.head != NULL)
+    ret->os.prev = (lang_output_section_statement_type *)
+      ((char *) lang_output_section_statement.tail
+       - offsetof (lang_output_section_statement_type, next));
+
+  /* GCC's strict aliasing rules prevent us from just casting the
+     address, so we store the pointer in a variable and cast that
+     instead.  */
+  nextp = &ret->os.next;
+  lang_statement_append (&lang_output_section_statement,
+                        (lang_statement_union_type *) &ret->os,
+                        (lang_statement_union_type **) nextp);
+  return &ret->root;
 }
 
 static void
 output_statement_table_init (void)
 {
-  if (! bfd_hash_table_init_n (&output_statement_table,
-                              output_statement_newfunc, 61))
-    einfo (_("%P%F: Failed to create hash table\n"));
+  if (!bfd_hash_table_init_n (&output_statement_table,
+                             output_statement_newfunc,
+                             sizeof (struct output_statement_hash_entry),
+                             61))
+    einfo (_("%P%F: can not create hash table: %E\n"));
 }
 
 static void
@@ -937,8 +977,10 @@ lang_init (void)
      of code-complexity here in ld, besides the initialization which just
      looks like other code here.  */
   if (!bfd_hash_table_init_n (&lang_definedness_table,
-                             lang_definedness_newfunc, 3))
-    einfo (_("%P%F: out of memory during initialization"));
+                             lang_definedness_newfunc,
+                             sizeof (struct lang_definedness_hash_entry),
+                             3))
+    einfo (_("%P%F: can not create hash table: %E\n"));
 }
 
 void
@@ -1028,96 +1070,79 @@ lang_memory_default (asection *section)
   return lang_memory_region_lookup (DEFAULT_MEMORY_REGION, FALSE);
 }
 
-static lang_output_section_statement_type *
-lang_output_section_find_1 (const char *const name, int constraint)
+lang_output_section_statement_type *
+lang_output_section_find (const char *const name)
 {
-  lang_output_section_statement_type *lookup;
   struct output_statement_hash_entry *entry;
   unsigned long hash;
 
   entry = ((struct output_statement_hash_entry *)
-          bfd_hash_lookup (&output_statement_table, name, FALSE,
-                           FALSE));
-  if (entry == NULL || (lookup = entry->entry) == NULL)
+          bfd_hash_lookup (&output_statement_table, name, FALSE, FALSE));
+  if (entry == NULL)
     return NULL;
 
   hash = entry->root.hash;
   do
     {
-      if (lookup->constraint != -1
-         && (constraint == 0
-             || (constraint == lookup->constraint
-                 && constraint != SPECIAL)))
-       return lookup;
+      if (entry->os.constraint != -1)
+       return &entry->os;
       entry = (struct output_statement_hash_entry *) entry->root.next;
-      lookup = entry ? entry->entry : NULL;
     }
   while (entry != NULL
         && entry->root.hash == hash
-        && strcmp (name, lookup->name) == 0);
+        && strcmp (name, entry->os.name) == 0);
 
   return NULL;
 }
 
-lang_output_section_statement_type *
-lang_output_section_find (const char *const name)
-{
-  return lang_output_section_find_1 (name, 0);
-}
-
 static lang_output_section_statement_type *
 lang_output_section_statement_lookup_1 (const char *const name, int constraint)
 {
-  lang_output_section_statement_type *lookup;
-  lang_output_section_statement_type **nextp;
+  struct output_statement_hash_entry *entry;
+  struct output_statement_hash_entry *last_ent;
+  unsigned long hash;
 
-  lookup = lang_output_section_find_1 (name, constraint);
-  if (lookup == NULL)
-    {
-      struct output_statement_hash_entry *entry;
-
-      lookup = new_stat (lang_output_section_statement, stat_ptr);
-      lookup->region = NULL;
-      lookup->lma_region = NULL;
-      lookup->fill = 0;
-      lookup->block_value = 1;
-      lookup->name = name;
-
-      lookup->next = NULL;
-      lookup->bfd_section = NULL;
-      lookup->processed = FALSE;
-      lookup->constraint = constraint;
-      lookup->ignored = FALSE;
-      lookup->sectype = normal_section;
-      lookup->addr_tree = NULL;
-      lang_list_init (&lookup->children);
-
-      lookup->memspec = NULL;
-      lookup->flags = 0;
-      lookup->subsection_alignment = -1;
-      lookup->section_alignment = -1;
-      lookup->load_base = NULL;
-      lookup->update_dot_tree = NULL;
-      lookup->phdrs = NULL;
+  entry = ((struct output_statement_hash_entry *)
+          bfd_hash_lookup (&output_statement_table, name, TRUE, FALSE));
+  if (entry == NULL)
+    {
+      einfo (_("%P%F: failed creating section `%s': %E\n"), name);
+      return NULL;
+    }
+
+  if (entry->os.name != NULL)
+    {
+      /* We have a section of this name, but it might not have the correct
+        constraint.  */
+      hash = entry->root.hash;
+      do
+       {
+         if (entry->os.constraint != -1
+             && (constraint == 0
+                 || (constraint == entry->os.constraint
+                     && constraint != SPECIAL)))
+           return &entry->os;
+         last_ent = entry;
+         entry = (struct output_statement_hash_entry *) entry->root.next;
+       }
+      while (entry != NULL
+            && entry->root.hash == hash
+            && strcmp (name, entry->os.name) == 0);
 
       entry = ((struct output_statement_hash_entry *)
-              bfd_hash_lookup (&output_statement_table, name, TRUE,
-                               FALSE));
+              output_statement_newfunc (NULL, &output_statement_table, name));
       if (entry == NULL)
-       einfo (_("%P%F: bfd_hash_lookup failed creating section `%s'\n"),
-              name);
-
-      entry->entry = lookup;
-
-      /* GCC's strict aliasing rules prevent us from just casting the
-        address, so we store the pointer in a variable and cast that
-        instead.  */
-      nextp = &lookup->next;
-      lang_statement_append (&lang_output_section_statement,
-                            (lang_statement_union_type *) lookup,
-                            (lang_statement_union_type **) nextp);
+       {
+         einfo (_("%P%F: failed creating section `%s': %E\n"), name);
+         return NULL;
+       }
+      entry->root = last_ent->root;
+      last_ent->root.next = &entry->root;
     }
-  return lookup;
+
+  entry->os.name = name;
+  entry->os.constraint = constraint;
+  return &entry->os;
 }
 
 lang_output_section_statement_type *
@@ -1133,7 +1158,8 @@ lang_output_section_statement_lookup (const char *const name)
 
 lang_output_section_statement_type *
 lang_output_section_find_by_flags (const asection *sec,
-                                  lang_output_section_statement_type **exact)
+                                  lang_output_section_statement_type **exact,
+                                  lang_match_sec_type_func match_type)
 {
   lang_output_section_statement_type *first, *look, *found;
   flagword flags;
@@ -1149,7 +1175,12 @@ lang_output_section_find_by_flags (const asection *sec,
     {
       flags = look->flags;
       if (look->bfd_section != NULL)
-       flags = look->bfd_section->flags;
+       {
+         flags = look->bfd_section->flags;
+         if (match_type && !match_type (output_bfd, look->bfd_section,
+                                        sec->owner, sec))
+           continue;
+       }
       flags ^= sec->flags;
       if (!(flags & (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY
                     | SEC_CODE | SEC_SMALL_DATA | SEC_THREAD_LOCAL)))
@@ -1157,7 +1188,8 @@ lang_output_section_find_by_flags (const asection *sec,
     }
   if (found != NULL)
     {
-      *exact = found;
+      if (exact != NULL)
+       *exact = found;
       return found;
     }
 
@@ -1168,40 +1200,51 @@ lang_output_section_find_by_flags (const asection *sec,
        {
          flags = look->flags;
          if (look->bfd_section != NULL)
-           flags = look->bfd_section->flags;
+           {
+             flags = look->bfd_section->flags;
+             if (match_type && !match_type (output_bfd, look->bfd_section,
+                                            sec->owner, sec))
+               continue;
+           }
          flags ^= sec->flags;
          if (!(flags & (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD
                         | SEC_CODE | SEC_SMALL_DATA | SEC_THREAD_LOCAL)))
            found = look;
        }
-      return found;
     }
-
-  if (sec->flags & (SEC_READONLY | SEC_THREAD_LOCAL))
+  else if (sec->flags & (SEC_READONLY | SEC_THREAD_LOCAL))
     {
       /* .rodata can go after .text, .sdata2 after .rodata.  */
       for (look = first; look; look = look->next)
        {
          flags = look->flags;
          if (look->bfd_section != NULL)
-           flags = look->bfd_section->flags;
+           {
+             flags = look->bfd_section->flags;
+             if (match_type && !match_type (output_bfd, look->bfd_section,
+                                            sec->owner, sec))
+               continue;
+           }
          flags ^= sec->flags;
          if (!(flags & (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD
                         | SEC_READONLY))
              && !(look->flags & (SEC_SMALL_DATA | SEC_THREAD_LOCAL)))
            found = look;
        }
-      return found;
     }
-
-  if (sec->flags & SEC_SMALL_DATA)
+  else if (sec->flags & SEC_SMALL_DATA)
     {
       /* .sdata goes after .data, .sbss after .sdata.  */
       for (look = first; look; look = look->next)
        {
          flags = look->flags;
          if (look->bfd_section != NULL)
-           flags = look->bfd_section->flags;
+           {
+             flags = look->bfd_section->flags;
+             if (match_type && !match_type (output_bfd, look->bfd_section,
+                                            sec->owner, sec))
+               continue;
+           }
          flags ^= sec->flags;
          if (!(flags & (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD
                         | SEC_THREAD_LOCAL))
@@ -1209,37 +1252,49 @@ lang_output_section_find_by_flags (const asection *sec,
                  && !(sec->flags & SEC_HAS_CONTENTS)))
            found = look;
        }
-      return found;
     }
-
-  if (sec->flags & SEC_HAS_CONTENTS)
+  else if (sec->flags & SEC_HAS_CONTENTS)
     {
       /* .data goes after .rodata.  */
       for (look = first; look; look = look->next)
        {
          flags = look->flags;
          if (look->bfd_section != NULL)
-           flags = look->bfd_section->flags;
+           {
+             flags = look->bfd_section->flags;
+             if (match_type && !match_type (output_bfd, look->bfd_section,
+                                            sec->owner, sec))
+               continue;
+           }
          flags ^= sec->flags;
          if (!(flags & (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD
                         | SEC_SMALL_DATA | SEC_THREAD_LOCAL)))
            found = look;
        }
-      return found;
     }
-
-  /* .bss goes last.  */
-  for (look = first; look; look = look->next)
+  else
     {
-      flags = look->flags;
-      if (look->bfd_section != NULL)
-       flags = look->bfd_section->flags;
-      flags ^= sec->flags;
-      if (!(flags & SEC_ALLOC))
-       found = look;
+      /* .bss goes last.  */
+      for (look = first; look; look = look->next)
+       {
+         flags = look->flags;
+         if (look->bfd_section != NULL)
+           {
+             flags = look->bfd_section->flags;
+             if (match_type && !match_type (output_bfd, look->bfd_section,
+                                            sec->owner, sec))
+               continue;
+           }
+         flags ^= sec->flags;
+         if (!(flags & SEC_ALLOC))
+           found = look;
+       }
     }
 
-  return found;
+  if (found || !match_type)
+    return found;
+
+  return lang_output_section_find_by_flags (sec, NULL, NULL);
 }
 
 /* Find the last output section before given output statement.
@@ -1248,28 +1303,22 @@ lang_output_section_find_by_flags (const asection *sec,
 static asection *
 output_prev_sec_find (lang_output_section_statement_type *os)
 {
-  asection *s = (asection *) NULL;
   lang_output_section_statement_type *lookup;
 
-  for (lookup = &lang_output_section_statement.head->output_section_statement;
-       lookup != NULL;
-       lookup = lookup->next)
+  for (lookup = os->prev; lookup != NULL; lookup = lookup->prev)
     {
       if (lookup->constraint == -1)
        continue;
-      if (lookup == os)
-       return s;
 
       if (lookup->bfd_section != NULL && lookup->bfd_section->owner != NULL)
-       s = lookup->bfd_section;
+       return lookup->bfd_section;
     }
 
   return NULL;
 }
 
 lang_output_section_statement_type *
-lang_insert_orphan (lang_input_statement_type *file,
-                   asection *s,
+lang_insert_orphan (asection *s,
                    const char *secname,
                    lang_output_section_statement_type *after,
                    struct orphan_save *place,
@@ -1340,7 +1389,7 @@ lang_insert_orphan (lang_input_statement_type *file,
 
   if (add_child == NULL)
     add_child = &os->children;
-  lang_add_section (add_child, s, os, file);
+  lang_add_section (add_child, s, os);
 
   lang_leave_output_section_statement (0, "*default*", NULL, NULL);
 
@@ -1423,13 +1472,20 @@ lang_insert_orphan (lang_input_statement_type *file,
            {
              lang_statement_union_type **where;
              lang_statement_union_type **assign = NULL;
+             bfd_boolean ignore_first;
 
              /* Look for a suitable place for the new statement list.
                 The idea is to skip over anything that might be inside
                 a SECTIONS {} statement in a script, before we find
                 another output_section_statement.  Assignments to "dot"
                 before an output section statement are assumed to
-                belong to it.  */
+                belong to it.  An exception to this rule is made for
+                the first assignment to dot, otherwise we might put an
+                orphan before . = . + SIZEOF_HEADERS or similar
+                assignments that set the initial address.  */
+
+             ignore_first = after == (&lang_output_section_statement.head
+                                      ->output_section_statement);
              for (where = &after->header.next;
                   *where != NULL;
                   where = &(*where)->header.next)
@@ -1443,9 +1499,11 @@ lang_insert_orphan (lang_input_statement_type *file,
                          ass = &(*where)->assignment_statement;
                          if (ass->exp->type.node_class != etree_assert
                              && ass->exp->assign.dst[0] == '.'
-                             && ass->exp->assign.dst[1] == 0)
+                             && ass->exp->assign.dst[1] == 0
+                             && !ignore_first)
                            assign = where;
                        }
+                     ignore_first = FALSE;
                      continue;
                    case lang_wild_statement_enum:
                    case lang_input_section_enum:
@@ -1494,7 +1552,12 @@ lang_insert_orphan (lang_input_statement_type *file,
          /* Do the same for the list of output section statements.  */
          newly_added_os = *os_tail;
          *os_tail = NULL;
+         newly_added_os->prev = (lang_output_section_statement_type *)
+           ((char *) place->os_tail
+            - offsetof (lang_output_section_statement_type, next));
          newly_added_os->next = *place->os_tail;
+         if (newly_added_os->next != NULL)
+           newly_added_os->next->prev = newly_added_os;
          *place->os_tail = newly_added_os;
          place->os_tail = &newly_added_os->next;
 
@@ -1534,8 +1597,31 @@ void
 lang_map (void)
 {
   lang_memory_region_type *m;
+  bfd_boolean dis_header_printed = FALSE;
   bfd *p;
 
+  LANG_FOR_EACH_INPUT_STATEMENT (file)
+    {
+      asection *s;
+
+      if ((file->the_bfd->flags & (BFD_LINKER_CREATED | DYNAMIC)) != 0
+         || file->just_syms_flag)
+       continue;
+
+      for (s = file->the_bfd->sections; s != NULL; s = s->next)
+       if (s->output_section == NULL
+           || s->output_section->owner != output_bfd)
+         {
+           if (! dis_header_printed)
+             {
+               fprintf (config.map_file, _("\nDiscarded input sections\n\n"));
+               dis_header_printed = TRUE;
+             }
+
+           print_input_section (s);
+         }
+    }
+
   minfo (_("\nMemory Configuration\n\n"));
   fprintf (config.map_file, "%-16s %-18s %-18s %s\n",
           _("Name"), _("Origin"), _("Length"), _("Attributes"));
@@ -1638,7 +1724,7 @@ sort_def_symbol (hash_entry, info)
 /* Initialize an output section.  */
 
 static void
-init_os (lang_output_section_statement_type *s)
+init_os (lang_output_section_statement_type *s, asection *isec)
 {
   if (s->bfd_section != NULL)
     return;
@@ -1655,9 +1741,6 @@ init_os (lang_output_section_statement_type *s)
             output_bfd->xvec->name, s->name);
     }
   s->bfd_section->output_section = s->bfd_section;
-
-  /* We initialize an output sections output offset to minus its own
-     vma to allow us to output a section through itself.  */
   s->bfd_section->output_offset = 0;
   if (!command_line.reduce_memory_overheads)
     {
@@ -1675,6 +1758,15 @@ init_os (lang_output_section_statement_type *s)
 
   if (s->load_base != NULL)
     exp_init_os (s->load_base);
+
+  /* If supplied an alignment, set it.  */
+  if (s->section_alignment != -1)
+    s->bfd_section->alignment_power = s->section_alignment;
+
+  if (isec)
+    bfd_init_private_section_data (isec->owner, isec,
+                                  output_bfd, s->bfd_section,
+                                  &link_info);
 }
 
 /* Make sure that all output sections mentioned in an expression are
@@ -1720,7 +1812,7 @@ exp_init_os (etree_type *exp)
 
            os = lang_output_section_find (exp->name.name);
            if (os != NULL && os->bfd_section == NULL)
-             init_os (os);
+             init_os (os, NULL);
          }
        }
       break;
@@ -1760,8 +1852,7 @@ section_already_linked (bfd *abfd, asection *sec, void *data)
 void
 lang_add_section (lang_statement_list_type *ptr,
                  asection *section,
-                 lang_output_section_statement_type *output,
-                 lang_input_statement_type *file)
+                 lang_output_section_statement_type *output)
 {
   flagword flags = section->flags;
   bfd_boolean discard;
@@ -1797,7 +1888,7 @@ lang_add_section (lang_statement_list_type *ptr,
       flagword flags;
 
       if (output->bfd_section == NULL)
-       init_os (output);
+       init_os (output, section);
 
       first = ! output->bfd_section->linker_has_input;
       output->bfd_section->linker_has_input = 1;
@@ -1819,7 +1910,6 @@ lang_add_section (lang_statement_list_type *ptr,
       new = new_stat (lang_input_section, ptr);
 
       new->section = section;
-      new->ifile = file;
       section->output_section = output->bfd_section;
 
       flags = section->flags;
@@ -1892,10 +1982,6 @@ lang_add_section (lang_statement_list_type *ptr,
       if (section->alignment_power > output->bfd_section->alignment_power)
        output->bfd_section->alignment_power = section->alignment_power;
 
-      /* If supplied an alignment, then force it.  */
-      if (output->section_alignment != -1)
-       output->bfd_section->alignment_power = output->section_alignment;
-
       if (bfd_get_arch (section->owner) == bfd_arch_tic54x
          && (section->flags & SEC_TIC54X_BLOCK) != 0)
        {
@@ -1999,15 +2085,14 @@ wild_sort (lang_wild_statement_type *wild,
              fa = FALSE;
            }
 
-         if (ls->ifile->the_bfd != NULL
-             && bfd_my_archive (ls->ifile->the_bfd) != NULL)
+         if (bfd_my_archive (ls->section->owner) != NULL)
            {
-             ln = bfd_get_filename (bfd_my_archive (ls->ifile->the_bfd));
+             ln = bfd_get_filename (bfd_my_archive (ls->section->owner));
              la = TRUE;
            }
          else
            {
-             ln = ls->ifile->filename;
+             ln = ls->section->owner->filename;
              la = FALSE;
            }
 
@@ -2022,7 +2107,7 @@ wild_sort (lang_wild_statement_type *wild,
              if (fa)
                fn = file->filename;
              if (la)
-               ln = ls->ifile->filename;
+               ln = ls->section->owner->filename;
 
              i = strcmp (fn, ln);
              if (i > 0)
@@ -2068,8 +2153,7 @@ output_section_callback (lang_wild_statement_type *ptr,
 
   if (before == NULL)
     lang_add_section (&ptr->children, section,
-                     (lang_output_section_statement_type *) output,
-                     file);
+                     (lang_output_section_statement_type *) output);
   else
     {
       lang_statement_list_type list;
@@ -2077,8 +2161,7 @@ output_section_callback (lang_wild_statement_type *ptr,
 
       lang_list_init (&list);
       lang_add_section (&list, section,
-                       (lang_output_section_statement_type *) output,
-                       file);
+                       (lang_output_section_statement_type *) output);
 
       /* If we are discarding the section, LIST.HEAD will
         be NULL.  */
@@ -2240,6 +2323,7 @@ load_symbols (lang_input_statement_type *entry,
       lang_statement_list_type *hold;
       bfd_boolean bad_load = TRUE;
       bfd_boolean save_ldlang_sysrooted_script;
+      bfd_boolean save_as_needed, save_add_needed;
 
       err = bfd_get_error ();
 
@@ -2273,6 +2357,10 @@ load_symbols (lang_input_statement_type *entry,
       stat_ptr = place;
       save_ldlang_sysrooted_script = ldlang_sysrooted_script;
       ldlang_sysrooted_script = entry->sysrooted;
+      save_as_needed = as_needed;
+      as_needed = entry->as_needed;
+      save_add_needed = add_needed;
+      add_needed = entry->add_needed;
 
       ldfile_assumed_script = TRUE;
       parser_input = input_script;
@@ -2283,6 +2371,8 @@ load_symbols (lang_input_statement_type *entry,
       ldfile_assumed_script = FALSE;
 
       ldlang_sysrooted_script = save_ldlang_sysrooted_script;
+      as_needed = save_as_needed;
+      add_needed = save_add_needed;
       stat_ptr = hold;
 
       return ! bad_load;
@@ -2368,17 +2458,15 @@ wild (lang_wild_statement_type *s,
 
   walk_wild (s, output_section_callback, output);
 
-  for (sec = s->section_list; sec != NULL; sec = sec->next)
-    {
-      if (default_common_section != NULL)
-       break;
+  if (default_common_section == NULL)
+    for (sec = s->section_list; sec != NULL; sec = sec->next)
       if (sec->spec.name != NULL && strcmp (sec->spec.name, "COMMON") == 0)
        {
          /* Remember the section that common is going to in case we
             later get something which doesn't know where to put it.  */
          default_common_section = output;
+         break;
        }
-    }
 }
 
 /* Return TRUE iff target is the sought target.  */
@@ -2633,7 +2721,7 @@ open_output (const char *name)
 
   link_info.hash = bfd_link_hash_table_create (output);
   if (link_info.hash == NULL)
-    einfo (_("%P%F: can not create link hash table: %E\n"));
+    einfo (_("%P%F: can not create hash table: %E\n"));
 
   bfd_set_gp_size (output, g_switch_value);
   return output;
@@ -3063,7 +3151,7 @@ map_input_to_output_sections
             are initialized.  */
          exp_init_os (s->data_statement.exp);
          if (os != NULL && os->bfd_section == NULL)
-           init_os (os);
+           init_os (os, NULL);
          /* The output section gets contents, and then we inspect for
             any flags set in the input script which override any ALLOC.  */
          os->bfd_section->flags |= SEC_HAS_CONTENTS;
@@ -3077,11 +3165,11 @@ map_input_to_output_sections
        case lang_padding_statement_enum:
        case lang_input_statement_enum:
          if (os != NULL && os->bfd_section == NULL)
-           init_os (os);
+           init_os (os, NULL);
          break;
        case lang_assignment_statement_enum:
          if (os != NULL && os->bfd_section == NULL)
-           init_os (os);
+           init_os (os, NULL);
 
          /* Make sure that any sections mentioned in the assignment
             are initialized.  */
@@ -3109,7 +3197,7 @@ map_input_to_output_sections
                   (s->address_statement.section_name));
              
              if (aos->bfd_section == NULL)
-               init_os (aos);
+               init_os (aos, NULL);
              aos->addr_tree = s->address_statement.address;
            }
          break;
@@ -3416,68 +3504,64 @@ print_all_symbols (sec)
 /* Print information about an input section to the map file.  */
 
 static void
-print_input_section (lang_input_section_type *in)
+print_input_section (asection *i)
 {
-  asection *i = in->section;
   bfd_size_type size = i->size;
+  int len;
+  bfd_vma addr;
 
   init_opb ();
-  if (size != 0)
-    {
-      int len;
-      bfd_vma addr;
 
-      print_space ();
-      minfo ("%s", i->name);
+  print_space ();
+  minfo ("%s", i->name);
 
-      len = 1 + strlen (i->name);
-      if (len >= SECTION_NAME_MAP_LENGTH - 1)
-       {
-         print_nl ();
-         len = 0;
-       }
-      while (len < SECTION_NAME_MAP_LENGTH)
-       {
-         print_space ();
-         ++len;
-       }
+  len = 1 + strlen (i->name);
+  if (len >= SECTION_NAME_MAP_LENGTH - 1)
+    {
+      print_nl ();
+      len = 0;
+    }
+  while (len < SECTION_NAME_MAP_LENGTH)
+    {
+      print_space ();
+      ++len;
+    }
 
-      if (i->output_section != NULL && (i->flags & SEC_EXCLUDE) == 0)
-       addr = i->output_section->vma + i->output_offset;
-      else
-       {
-         addr = print_dot;
-         size = 0;
-       }
+  if (i->output_section != NULL && i->output_section->owner == output_bfd)
+    addr = i->output_section->vma + i->output_offset;
+  else
+    {
+      addr = print_dot;
+      size = 0;
+    }
 
-      minfo ("0x%V %W %B\n", addr, TO_ADDR (size), i->owner);
+  minfo ("0x%V %W %B\n", addr, TO_ADDR (size), i->owner);
 
-      if (size != i->rawsize && i->rawsize != 0)
-       {
-         len = SECTION_NAME_MAP_LENGTH + 3;
+  if (size != i->rawsize && i->rawsize != 0)
+    {
+      len = SECTION_NAME_MAP_LENGTH + 3;
 #ifdef BFD64
-         len += 16;
+      len += 16;
 #else
-         len += 8;
+      len += 8;
 #endif
-         while (len > 0)
-           {
-             print_space ();
-             --len;
-           }
-
-         minfo (_("%W (size before relaxing)\n"), i->rawsize);
+      while (len > 0)
+       {
+         print_space ();
+         --len;
        }
 
-      if (i->output_section != NULL && (i->flags & SEC_EXCLUDE) == 0)
-       {
-         if (command_line.reduce_memory_overheads)
-           bfd_link_hash_traverse (link_info.hash, print_one_symbol, i);
-         else
-           print_all_symbols (i);
+      minfo (_("%W (size before relaxing)\n"), i->rawsize);
+    }
 
-         print_dot = addr + TO_ADDR (size);
-       }
+  if (i->output_section != NULL && i->output_section->owner == output_bfd)
+    {
+      if (command_line.reduce_memory_overheads)
+       bfd_link_hash_traverse (link_info.hash, print_one_symbol, i);
+      else
+       print_all_symbols (i);
+
+      print_dot = addr + TO_ADDR (size);
     }
 }
 
@@ -3504,7 +3588,7 @@ print_data_statement (lang_data_statement_type *data)
   for (i = 0; i < SECTION_NAME_MAP_LENGTH; i++)
     print_space ();
 
-  addr = data->output_vma;
+  addr = data->output_offset;
   if (data->output_section != NULL)
     addr += data->output_section->vma;
 
@@ -3571,7 +3655,7 @@ print_reloc_statement (lang_reloc_statement_type *reloc)
   for (i = 0; i < SECTION_NAME_MAP_LENGTH; i++)
     print_space ();
 
-  addr = reloc->output_vma;
+  addr = reloc->output_offset;
   if (reloc->output_section != NULL)
     addr += reloc->output_section->vma;
 
@@ -3738,7 +3822,7 @@ print_statement (lang_statement_union_type *s,
       print_reloc_statement (&s->reloc_statement);
       break;
     case lang_input_section_enum:
-      print_input_section (&s->input_section);
+      print_input_section (s->input_section.section);
       break;
     case lang_padding_statement_enum:
       print_padding_statement (&s->padding_statement);
@@ -3856,7 +3940,8 @@ size_input_section
   lang_input_section_type *is = &((*this_ptr)->input_section);
   asection *i = is->section;
 
-  if (!is->ifile->just_syms_flag && (i->flags & SEC_EXCLUDE) == 0)
+  if (!((lang_input_statement_type *) i->owner->usrdata)->just_syms_flag
+      && (i->flags & SEC_EXCLUDE) == 0)
     {
       unsigned int alignment_needed;
       asection *o;
@@ -4095,6 +4180,8 @@ lang_size_sections_1
              }
            else
              {
+               int align;
+
                if (os->addr_tree == NULL)
                  {
                    /* No address specified for this section, get one
@@ -4111,7 +4198,8 @@ lang_size_sections_1
                    /* If a loadable section is using the default memory
                       region, and some non default memory regions were
                       defined, issue an error message.  */
-                   if (!IGNORE_SECTION (os->bfd_section)
+                   if (!os->ignored
+                       && !IGNORE_SECTION (os->bfd_section)
                        && ! link_info.relocatable
                        && check_regions
                        && strcmp (os->region->name,
@@ -4144,27 +4232,25 @@ lang_size_sections_1
                      }
 
                    newdot = os->region->current;
-
-                   if (os->section_alignment == -1)
-                     {
-                       bfd_vma savedot = newdot;
-                       newdot = align_power (newdot,
-                                             os->bfd_section->alignment_power);
-
-                       if (newdot != savedot
-                           && config.warn_section_align
-                           && expld.phase != lang_mark_phase_enum)
-                         einfo (_("%P: warning: changing start of section"
-                                  " %s by %lu bytes\n"),
-                                os->name, (unsigned long) (newdot - savedot));
-                     }
+                   align = os->bfd_section->alignment_power;
                  }
+               else
+                 align = os->section_alignment;
 
-               /* The section starts here.
-                  First, align to what the section needs.  */
+               /* Align to what the section needs.  */
+               if (align > 0)
+                 {
+                   bfd_vma savedot = newdot;
+                   newdot = align_power (newdot, align);
 
-               if (os->section_alignment != -1)
-                 newdot = align_power (newdot, os->section_alignment);
+                   if (newdot != savedot
+                       && (config.warn_section_align
+                           || os->addr_tree != NULL)
+                       && expld.phase != lang_mark_phase_enum)
+                     einfo (_("%P: warning: changing start of section"
+                              " %s by %lu bytes\n"),
+                            os->name, (unsigned long) (newdot - savedot));
+                 }
 
                bfd_set_section_vma (0, os->bfd_section, newdot);
 
@@ -4251,7 +4337,7 @@ lang_size_sections_1
          {
            unsigned int size = 0;
 
-           s->data_statement.output_vma =
+           s->data_statement.output_offset =
              dot - output_section_statement->bfd_section->vma;
            s->data_statement.output_section =
              output_section_statement->bfd_section;
@@ -4289,7 +4375,7 @@ lang_size_sections_1
          {
            int size;
 
-           s->reloc_statement.output_vma =
+           s->reloc_statement.output_offset =
              dot - output_section_statement->bfd_section->vma;
            s->reloc_statement.output_section =
              output_section_statement->bfd_section;
@@ -4457,6 +4543,7 @@ lang_size_sections (bfd_boolean *relax, bfd_boolean check_regions)
          expld.dataseg.base -= maxpage;
          relro_end -= maxpage;
        }
+      lang_reset_memory_regions ();
       one_lang_size_sections_pass (relax, check_regions);
       if (expld.dataseg.relro_end > relro_end)
        {
@@ -4480,6 +4567,7 @@ lang_size_sections (bfd_boolean *relax, bfd_boolean check_regions)
                  < old_min_base)
                expld.dataseg.base += expld.dataseg.pagesize;
              expld.dataseg.base -= (1 << max_alignment_power);
+             lang_reset_memory_regions ();
              one_lang_size_sections_pass (relax, check_regions);
            }
        }
@@ -4500,6 +4588,7 @@ lang_size_sections (bfd_boolean *relax, bfd_boolean check_regions)
          && first + last <= expld.dataseg.pagesize)
        {
          expld.dataseg.phase = exp_dataseg_adjust;
+         lang_reset_memory_regions ();
          one_lang_size_sections_pass (relax, check_regions);
        }
     }
@@ -5019,17 +5108,17 @@ lang_place_orphans (void)
 
                        }
                      lang_add_section (&default_common_section->children, s,
-                                       default_common_section, file);
+                                       default_common_section);
                    }
                }
-             else if (ldemul_place_orphan (file, s))
+             else if (ldemul_place_orphan (s))
                ;
              else
                {
                  lang_output_section_statement_type *os;
 
                  os = lang_output_section_statement_lookup (s->name);
-                 lang_add_section (&os->children, s, os, file);
+                 lang_add_section (&os->children, s, os);
                }
            }
        }
@@ -5177,10 +5266,9 @@ lang_enter_output_section_statement (const char *output_section_statement_name,
 {
   lang_output_section_statement_type *os;
 
-  current_section =
-   os =
-    lang_output_section_statement_lookup_1 (output_section_statement_name,
-                                           constraint);
+   os = lang_output_section_statement_lookup_1 (output_section_statement_name,
+                                               constraint);
+   current_section = os;
 
   /* Make next things chain into subchain of this.  */
 
@@ -5208,9 +5296,9 @@ lang_enter_output_section_statement (const char *output_section_statement_name,
 void
 lang_final (void)
 {
-  lang_output_statement_type *new =
-    new_stat (lang_output_statement, stat_ptr);
+  lang_output_statement_type *new;
 
+  new = new_stat (lang_output_statement, stat_ptr);
   new->name = output_filename;
 }
 
@@ -5329,6 +5417,37 @@ lang_gc_sections (void)
     bfd_gc_sections (output_bfd, &link_info);
 }
 
+/* Relax all sections until bfd_relax_section gives up.  */
+
+static void
+relax_sections (void)
+{
+  /* Keep relaxing until bfd_relax_section gives up.  */
+  bfd_boolean relax_again;
+
+  do
+    {
+      relax_again = FALSE; 
+
+      /* Note: pe-dll.c does something like this also.  If you find
+        you need to change this code, you probably need to change
+        pe-dll.c also.  DJ  */
+
+      /* Do all the assignments with our current guesses as to
+        section sizes.  */
+      lang_do_assignments ();
+
+      /* We must do this after lang_do_assignments, because it uses
+        size.  */
+      lang_reset_memory_regions ();
+
+      /* Perform another relax pass - this time we know where the
+        globals are, so can make a better guess.  */
+      lang_size_sections (&relax_again, FALSE);
+    }
+  while (relax_again);
+}
+
 void
 lang_process (void)
 {
@@ -5425,38 +5544,17 @@ lang_process (void)
   /* Now run around and relax if we can.  */
   if (command_line.relax)
     {
-      /* Keep relaxing until bfd_relax_section gives up.  */
-      bfd_boolean relax_again;
-
-      do
-       {
-         relax_again = FALSE;
-
-         /* Note: pe-dll.c does something like this also.  If you find
-            you need to change this code, you probably need to change
-            pe-dll.c also.  DJ  */
-
-         /* Do all the assignments with our current guesses as to
-            section sizes.  */
-         lang_do_assignments ();
+      /* We may need more than one relaxation pass.  */
+      int i = link_info.relax_pass;
 
-         /* We must do this after lang_do_assignments, because it uses
-            size.  */
-         lang_reset_memory_regions ();
-
-         /* Perform another relax pass - this time we know where the
-            globals are, so can make a better guess.  */
-         lang_size_sections (&relax_again, FALSE);
+      /* The backend can use it to determine the current pass.  */
+      link_info.relax_pass = 0;
 
-         /* If the normal relax is done and the relax finalize pass
-            is not performed yet, we perform another relax pass.  */
-         if (!relax_again && link_info.need_relax_finalize)
-           {
-             link_info.need_relax_finalize = FALSE;
-             relax_again = TRUE;
-           }
+      while (i--)
+       {
+         relax_sections ();
+         link_info.relax_pass++;
        }
-      while (relax_again);
 
       /* Final extra sizing to report errors.  */
       lang_do_assignments ();
@@ -5572,11 +5670,10 @@ lang_default_entry (const char *name)
 void
 lang_add_target (const char *name)
 {
-  lang_target_statement_type *new = new_stat (lang_target_statement,
-                                             stat_ptr);
+  lang_target_statement_type *new;
 
+  new = new_stat (lang_target_statement, stat_ptr);
   new->target = name;
-
 }
 
 void
@@ -5597,22 +5694,20 @@ lang_add_map (const char *name)
 void
 lang_add_fill (fill_type *fill)
 {
-  lang_fill_statement_type *new = new_stat (lang_fill_statement,
-                                           stat_ptr);
+  lang_fill_statement_type *new;
 
+  new = new_stat (lang_fill_statement, stat_ptr);
   new->fill = fill;
 }
 
 void
 lang_add_data (int type, union etree_union *exp)
 {
+  lang_data_statement_type *new;
 
-  lang_data_statement_type *new = new_stat (lang_data_statement,
-                                           stat_ptr);
-
+  new = new_stat (lang_data_statement, stat_ptr);
   new->exp = exp;
   new->type = type;
-
 }
 
 /* Create a new reloc statement.  RELOC is the BFD relocation type to
@@ -5639,15 +5734,15 @@ lang_add_reloc (bfd_reloc_code_real_type reloc,
 
   p->addend_value = 0;
   p->output_section = NULL;
-  p->output_vma = 0;
+  p->output_offset = 0;
 }
 
 lang_assignment_statement_type *
 lang_add_assignment (etree_type *exp)
 {
-  lang_assignment_statement_type *new = new_stat (lang_assignment_statement,
-                                                 stat_ptr);
+  lang_assignment_statement_type *new;
 
+  new = new_stat (lang_assignment_statement, stat_ptr);
   new->exp = exp;
   return new;
 }
@@ -5655,7 +5750,7 @@ lang_add_assignment (etree_type *exp)
 void
 lang_add_attribute (enum statement_enum attribute)
 {
-  new_statement (attribute, sizeof (lang_statement_union_type), stat_ptr);
+  new_statement (attribute, sizeof (lang_statement_header_type), stat_ptr);
 }
 
 void
This page took 0.039018 seconds and 4 git commands to generate.