Run "make dep-am" and regenerate
[binutils-gdb.git] / ld / ldlang.c
index 7ef8838ae50407c71e0694e3e73c1783ee7814c4..d97a55b084c26995af33427c0ecb25e5cbfe7120 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
+   2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
    Free Software Foundation, Inc.
 
    This file is part of the GNU Binutils.
@@ -62,6 +62,8 @@ static const char *current_target;
 static const char *output_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];
 
 /* Forward declarations.  */
 static void exp_init_os (etree_type *);
@@ -132,7 +134,66 @@ stat_alloc (size_t size)
   return obstack_alloc (&stat_obstack, size);
 }
 
-bfd_boolean
+static int
+name_match (const char *pattern, const char *name)
+{
+  if (wildcardp (pattern))
+    return fnmatch (pattern, name, 0);
+  return strcmp (pattern, name);
+}
+
+/* If PATTERN is of the form archive:file, return a pointer to the
+   separator.  If not, return NULL.  */
+
+static char *
+archive_path (const char *pattern)
+{
+  char *p = NULL;
+
+  if (link_info.path_separator == 0)
+    return p;
+
+  p = strchr (pattern, link_info.path_separator);
+#ifdef HAVE_DOS_BASED_FILE_SYSTEM
+  if (p == NULL || link_info.path_separator != ':')
+    return p;
+
+  /* Assume a match on the second char is part of drive specifier,
+     as in "c:\silly.dos".  */
+  if (p == pattern + 1 && ISALPHA (*pattern))
+    p = strchr (p + 1, link_info.path_separator);
+#endif
+  return p;
+}
+
+/* Given that FILE_SPEC results in a non-NULL SEP result from archive_path,
+   return whether F matches FILE_SPEC.  */
+
+static bfd_boolean
+input_statement_is_archive_path (const char *file_spec, char *sep,
+                                lang_input_statement_type *f)
+{
+  bfd_boolean match = FALSE;
+
+  if ((*(sep + 1) == 0
+       || name_match (sep + 1, f->filename) == 0)
+      && ((sep != file_spec)
+         == (f->the_bfd != NULL && f->the_bfd->my_archive != NULL)))
+    {
+      match = TRUE;
+
+      if (sep != file_spec)
+       {
+         const char *aname = f->the_bfd->my_archive->filename;
+         *sep = 0;
+         match = name_match (file_spec, aname) == 0;
+         *sep = link_info.path_separator;
+       }
+    }
+  return match;
+}
+
+static bfd_boolean
 unique_section_p (const asection *sec)
 {
   struct unique_sections *unam;
@@ -145,12 +206,8 @@ unique_section_p (const asection *sec)
 
   secnam = sec->name;
   for (unam = unique_section_list; unam; unam = unam->next)
-    if (wildcardp (unam->name)
-       ? fnmatch (unam->name, secnam, 0) == 0
-       : strcmp (unam->name, secnam) == 0)
-      {
-       return TRUE;
-      }
+    if (name_match (unam->name, secnam) == 0)
+      return TRUE;
 
   return FALSE;
 }
@@ -170,42 +227,35 @@ walk_wild_consider_section (lang_wild_statement_type *ptr,
                            callback_t callback,
                            void *data)
 {
-  bfd_boolean skip = FALSE;
   struct name_list *list_tmp;
 
-  /* Don't process sections from files which were
-     excluded.  */
+  /* Don't process sections from files which were excluded.  */
   for (list_tmp = sec->spec.exclude_name_list;
        list_tmp;
        list_tmp = list_tmp->next)
     {
-      bfd_boolean is_wildcard = wildcardp (list_tmp->name);
-      if (is_wildcard)
-       skip = fnmatch (list_tmp->name, file->filename, 0) == 0;
-      else
-       skip = strcmp (list_tmp->name, file->filename) == 0;
+      char *p = archive_path (list_tmp->name);
 
-      /* If this file is part of an archive, and the archive is
-        excluded, exclude this file.  */
-      if (! skip && file->the_bfd != NULL
-         && file->the_bfd->my_archive != NULL
-         && file->the_bfd->my_archive->filename != NULL)
+      if (p != NULL)
        {
-         if (is_wildcard)
-           skip = fnmatch (list_tmp->name,
-                           file->the_bfd->my_archive->filename,
-                           0) == 0;
-         else
-           skip = strcmp (list_tmp->name,
-                          file->the_bfd->my_archive->filename) == 0;
+         if (input_statement_is_archive_path (list_tmp->name, p, file))
+           return;
        }
 
-      if (skip)
-       break;
+      else if (name_match (list_tmp->name, file->filename) == 0)
+       return;
+
+      /* FIXME: Perhaps remove the following at some stage?  Matching
+        unadorned archives like this was never documented and has
+        been superceded by the archive:path syntax.  */
+      else if (file->the_bfd != NULL
+              && file->the_bfd->my_archive != NULL
+              && name_match (list_tmp->name,
+                             file->the_bfd->my_archive->filename) == 0)
+       return;
     }
 
-  if (!skip)
-    (*callback) (ptr, sec, s, file, data);
+  (*callback) (ptr, sec, s, file, data);
 }
 
 /* Lowest common denominator routine that can handle everything correctly,
@@ -234,10 +284,7 @@ walk_wild_section_general (lang_wild_statement_type *ptr,
            {
              const char *sname = bfd_get_section_name (file->the_bfd, s);
 
-             if (wildcardp (sec->spec.name))
-               skip = fnmatch (sec->spec.name, sname, 0) != 0;
-             else
-               skip = strcmp (sec->spec.name, sname) != 0;
+             skip = name_match (sec->spec.name, sname) != 0;
            }
 
          if (!skip)
@@ -778,6 +825,7 @@ static void
 walk_wild (lang_wild_statement_type *s, callback_t callback, void *data)
 {
   const char *file_spec = s->filename;
+  char *p;
 
   if (file_spec == NULL)
     {
@@ -787,6 +835,14 @@ walk_wild (lang_wild_statement_type *s, callback_t callback, void *data)
          walk_wild_file (s, f, callback, data);
        }
     }
+  else if ((p = archive_path (file_spec)) != NULL)
+    {
+      LANG_FOR_EACH_INPUT_STATEMENT (f)
+       {
+         if (input_statement_is_archive_path (file_spec, p, f))
+           walk_wild_file (s, f, callback, data);
+       }
+    }
   else if (wildcardp (file_spec))
     {
       LANG_FOR_EACH_INPUT_STATEMENT (f)
@@ -869,6 +925,23 @@ lang_list_init (lang_statement_list_type *list)
   list->tail = &list->head;
 }
 
+void
+push_stat_ptr (lang_statement_list_type *new_ptr)
+{
+  if (stat_save_ptr >= stat_save + sizeof (stat_save) / sizeof (stat_save[0]))
+    abort ();
+  *stat_save_ptr++ = stat_ptr;
+  stat_ptr = new_ptr;
+}
+
+void
+pop_stat_ptr (void)
+{
+  if (stat_save_ptr <= stat_save)
+    abort ();
+  stat_ptr = *--stat_save_ptr;
+}
+
 /* Build a new statement node for the parse tree.  */
 
 static lang_statement_union_type *
@@ -944,7 +1017,7 @@ new_afile (const char *name,
       p->is_archive = TRUE;
       p->filename = name;
       p->real = TRUE;
-      p->local_sym_name = concat ("-l", name, NULL);
+      p->local_sym_name = concat ("-l", name, (const char *) NULL);
       p->just_syms_flag = FALSE;
       p->search_dirs_flag = TRUE;
       break;
@@ -977,10 +1050,8 @@ new_afile (const char *name,
       FAIL ();
     }
   p->the_bfd = NULL;
-  p->asymbols = NULL;
   p->next_real_file = NULL;
   p->next = NULL;
-  p->symbol_count = 0;
   p->dynamic = config.dynamic_link;
   p->add_needed = add_needed;
   p->as_needed = as_needed;
@@ -1095,7 +1166,7 @@ lang_init (void)
   first_file = lang_add_input_file (NULL, lang_input_file_is_marker_enum,
                                    NULL);
   abs_output_section =
-    lang_output_section_statement_lookup (BFD_ABS_SECTION_NAME);
+    lang_output_section_statement_lookup (BFD_ABS_SECTION_NAME, 0, TRUE);
 
   abs_output_section->bfd_section = bfd_abs_section_ptr;
 
@@ -1132,7 +1203,13 @@ lang_finish (void)
   In this case it is probably an error to create a region that has
   already been created.  If we are not inside a MEMORY block it is
   dubious to use an undeclared region name (except DEFAULT_MEMORY_REGION)
-  and so we issue a warning.  */
+  and so we issue a warning.
+  
+  Each region has at least one name.  The first name is either
+  DEFAULT_MEMORY_REGION or the name given in the MEMORY block.  You can add
+  alias names to an existing region within a script with
+  REGION_ALIAS (alias, region_name).  Each name corresponds to at most one
+  region.  */
 
 static lang_memory_region_type *lang_memory_region_list;
 static lang_memory_region_type **lang_memory_region_list_tail
@@ -1141,28 +1218,31 @@ static lang_memory_region_type **lang_memory_region_list_tail
 lang_memory_region_type *
 lang_memory_region_lookup (const char *const name, bfd_boolean create)
 {
-  lang_memory_region_type *p;
+  lang_memory_region_name *n;
+  lang_memory_region_type *r;
   lang_memory_region_type *new;
 
   /* NAME is NULL for LMA memspecs if no region was specified.  */
   if (name == NULL)
     return NULL;
 
-  for (p = lang_memory_region_list; p != NULL; p = p->next)
-    if (strcmp (p->name, name) == 0)
-      {
-       if (create)
-         einfo (_("%P:%S: warning: redeclaration of memory region '%s'\n"),
-                name);
-       return p;
-      }
+  for (r = lang_memory_region_list; r != NULL; r = r->next)
+    for (n = &r->name_list; n != NULL; n = n->next)
+      if (strcmp (n->name, name) == 0)
+        {
+          if (create)
+            einfo (_("%P:%S: warning: redeclaration of memory region `%s'\n"),
+                   name);
+          return r;
+        }
 
   if (!create && strcmp (name, DEFAULT_MEMORY_REGION))
-    einfo (_("%P:%S: warning: memory region %s not declared\n"), name);
+    einfo (_("%P:%S: warning: memory region `%s' not declared\n"), name);
 
   new = stat_alloc (sizeof (lang_memory_region_type));
 
-  new->name = xstrdup (name);
+  new->name_list.name = xstrdup (name);
+  new->name_list.next = NULL;
   new->next = NULL;
   new->origin = 0;
   new->length = ~(bfd_size_type) 0;
@@ -1178,8 +1258,50 @@ lang_memory_region_lookup (const char *const name, bfd_boolean create)
   return new;
 }
 
+void
+lang_memory_region_alias (const char * alias, const char * region_name)
+{
+  lang_memory_region_name * n;
+  lang_memory_region_type * r;
+  lang_memory_region_type * region;
+
+  /* The default region must be unique.  This ensures that it is not necessary
+     to iterate through the name list if someone wants the check if a region is
+     the default memory region.  */
+  if (strcmp (region_name, DEFAULT_MEMORY_REGION) == 0
+      || strcmp (alias, DEFAULT_MEMORY_REGION) == 0)
+    einfo (_("%F%P:%S: error: alias for default memory region\n"));
+
+  /* Look for the target region and check if the alias is not already
+     in use.  */
+  region = NULL;
+  for (r = lang_memory_region_list; r != NULL; r = r->next)
+    for (n = &r->name_list; n != NULL; n = n->next)
+      {
+        if (region == NULL && strcmp (n->name, region_name) == 0)
+          region = r;
+        if (strcmp (n->name, alias) == 0)
+          einfo (_("%F%P:%S: error: redefinition of memory region "
+                   "alias `%s'\n"),
+                 alias);
+      }
+
+  /* Check if the target region exists.  */
+  if (region == NULL)
+    einfo (_("%F%P:%S: error: memory region `%s' "
+             "for alias `%s' does not exist\n"),
+           region_name,
+           alias);
+
+  /* Add alias to region name list.  */
+  n = stat_alloc (sizeof (lang_memory_region_name));
+  n->name = xstrdup (alias);
+  n->next = region->name_list.next;
+  region->name_list.next = n;
+}
+
 static lang_memory_region_type *
-lang_memory_default (asection *section)
+lang_memory_default (asection * section)
 {
   lang_memory_region_type *p;
 
@@ -1200,45 +1322,25 @@ lang_memory_default (asection *section)
   return lang_memory_region_lookup (DEFAULT_MEMORY_REGION, FALSE);
 }
 
-lang_output_section_statement_type *
-lang_output_section_find (const char *const name)
-{
-  struct out_section_hash_entry *entry;
-  unsigned long hash;
+/* Find or create an output_section_statement with the given NAME.
+   If CONSTRAINT is non-zero match one with that constraint, otherwise
+   match any non-negative constraint.  If CREATE, always make a
+   new output_section_statement for SPECIAL CONSTRAINT.  */
 
-  entry = ((struct out_section_hash_entry *)
-          bfd_hash_lookup (&output_section_statement_table, name,
-                           FALSE, FALSE));
-  if (entry == NULL)
-    return NULL;
-
-  hash = entry->root.hash;
-  do
-    {
-      if (entry->s.output_section_statement.constraint != -1)
-       return &entry->s.output_section_statement;
-      entry = (struct out_section_hash_entry *) entry->root.next;
-    }
-  while (entry != NULL
-        && entry->root.hash == hash
-        && strcmp (name, entry->s.output_section_statement.name) == 0);
-
-  return NULL;
-}
-
-static lang_output_section_statement_type *
-lang_output_section_statement_lookup_1 (const char *const name, int constraint)
+lang_output_section_statement_type *
+lang_output_section_statement_lookup (const char *name,
+                                     int constraint,
+                                     bfd_boolean create)
 {
   struct out_section_hash_entry *entry;
-  struct out_section_hash_entry *last_ent;
-  unsigned long hash;
 
   entry = ((struct out_section_hash_entry *)
           bfd_hash_lookup (&output_section_statement_table, name,
-                           TRUE, FALSE));
+                           create, FALSE));
   if (entry == NULL)
     {
-      einfo (_("%P%F: failed creating section `%s': %E\n"), name);
+      if (create)
+       einfo (_("%P%F: failed creating section `%s': %E\n"), name);
       return NULL;
     }
 
@@ -1246,20 +1348,29 @@ lang_output_section_statement_lookup_1 (const char *const name, int constraint)
     {
       /* We have a section of this name, but it might not have the correct
         constraint.  */
-      hash = entry->root.hash;
-      do
-       {
-         if (entry->s.output_section_statement.constraint != -1
-             && (constraint == 0
-                 || (constraint == entry->s.output_section_statement.constraint
-                     && constraint != SPECIAL)))
-           return &entry->s.output_section_statement;
-         last_ent = entry;
-         entry = (struct out_section_hash_entry *) entry->root.next;
-       }
-      while (entry != NULL
-            && entry->root.hash == hash
-            && strcmp (name, entry->s.output_section_statement.name) == 0);
+      struct out_section_hash_entry *last_ent;
+
+      name = entry->s.output_section_statement.name;
+      if (create && constraint == SPECIAL)
+       /* Not traversing to the end reverses the order of the second
+          and subsequent SPECIAL sections in the hash table chain,
+          but that shouldn't matter.  */
+       last_ent = entry;
+      else
+       do
+         {
+           if (constraint == entry->s.output_section_statement.constraint
+               || (constraint == 0
+                   && entry->s.output_section_statement.constraint >= 0))
+             return &entry->s.output_section_statement;
+           last_ent = entry;
+           entry = (struct out_section_hash_entry *) entry->root.next;
+         }
+       while (entry != NULL
+              && name == entry->s.output_section_statement.name);
+
+      if (!create)
+       return NULL;
 
       entry
        = ((struct out_section_hash_entry *)
@@ -1280,10 +1391,34 @@ lang_output_section_statement_lookup_1 (const char *const name, int constraint)
   return &entry->s.output_section_statement;
 }
 
+/* Find the next output_section_statement with the same name as OS.
+   If CONSTRAINT is non-zero, find one with that constraint otherwise
+   match any non-negative constraint.  */
+
 lang_output_section_statement_type *
-lang_output_section_statement_lookup (const char *const name)
+next_matching_output_section_statement (lang_output_section_statement_type *os,
+                                       int constraint)
 {
-  return lang_output_section_statement_lookup_1 (name, 0);
+  /* All output_section_statements are actually part of a
+     struct out_section_hash_entry.  */
+  struct out_section_hash_entry *entry = (struct out_section_hash_entry *)
+    ((char *) os
+     - offsetof (struct out_section_hash_entry, s.output_section_statement));
+  const char *name = os->name;
+
+  ASSERT (name == entry->root.string);
+  do
+    {
+      entry = (struct out_section_hash_entry *) entry->root.next;
+      if (entry == NULL
+         || name != entry->s.output_section_statement.name)
+       return NULL;
+    }
+  while (constraint != entry->s.output_section_statement.constraint
+        && (constraint != 0
+            || entry->s.output_section_statement.constraint < 0));
+
+  return &entry->s.output_section_statement;
 }
 
 /* A variant of lang_output_section_find used by place_orphan.
@@ -1312,7 +1447,8 @@ lang_output_section_find_by_flags (const asection *sec,
       if (look->bfd_section != NULL)
        {
          flags = look->bfd_section->flags;
-         if (match_type && !match_type (output_bfd, look->bfd_section,
+         if (match_type && !match_type (link_info.output_bfd,
+                                        look->bfd_section,
                                         sec->owner, sec))
            continue;
        }
@@ -1328,7 +1464,8 @@ lang_output_section_find_by_flags (const asection *sec,
       return found;
     }
 
-  if (sec->flags & SEC_CODE)
+  if ((sec->flags & SEC_CODE) != 0
+      && (sec->flags & SEC_ALLOC) != 0)
     {
       /* Try for a rw code section.  */
       for (look = first; look; look = look->next)
@@ -1337,7 +1474,8 @@ lang_output_section_find_by_flags (const asection *sec,
          if (look->bfd_section != NULL)
            {
              flags = look->bfd_section->flags;
-             if (match_type && !match_type (output_bfd, look->bfd_section,
+             if (match_type && !match_type (link_info.output_bfd,
+                                            look->bfd_section,
                                             sec->owner, sec))
                continue;
            }
@@ -1347,7 +1485,8 @@ lang_output_section_find_by_flags (const asection *sec,
            found = look;
        }
     }
-  else if (sec->flags & (SEC_READONLY | SEC_THREAD_LOCAL))
+  else if ((sec->flags & (SEC_READONLY | SEC_THREAD_LOCAL)) != 0
+          && (sec->flags & SEC_ALLOC) != 0)
     {
       /* .rodata can go after .text, .sdata2 after .rodata.  */
       for (look = first; look; look = look->next)
@@ -1356,7 +1495,8 @@ lang_output_section_find_by_flags (const asection *sec,
          if (look->bfd_section != NULL)
            {
              flags = look->bfd_section->flags;
-             if (match_type && !match_type (output_bfd, look->bfd_section,
+             if (match_type && !match_type (link_info.output_bfd,
+                                            look->bfd_section,
                                             sec->owner, sec))
                continue;
            }
@@ -1367,7 +1507,8 @@ lang_output_section_find_by_flags (const asection *sec,
            found = look;
        }
     }
-  else if (sec->flags & SEC_SMALL_DATA)
+  else if ((sec->flags & SEC_SMALL_DATA) != 0
+          && (sec->flags & SEC_ALLOC) != 0)
     {
       /* .sdata goes after .data, .sbss after .sdata.  */
       for (look = first; look; look = look->next)
@@ -1376,7 +1517,8 @@ lang_output_section_find_by_flags (const asection *sec,
          if (look->bfd_section != NULL)
            {
              flags = look->bfd_section->flags;
-             if (match_type && !match_type (output_bfd, look->bfd_section,
+             if (match_type && !match_type (link_info.output_bfd,
+                                            look->bfd_section,
                                             sec->owner, sec))
                continue;
            }
@@ -1388,7 +1530,8 @@ lang_output_section_find_by_flags (const asection *sec,
            found = look;
        }
     }
-  else if (sec->flags & SEC_HAS_CONTENTS)
+  else if ((sec->flags & SEC_HAS_CONTENTS) != 0
+          && (sec->flags & SEC_ALLOC) != 0)
     {
       /* .data goes after .rodata.  */
       for (look = first; look; look = look->next)
@@ -1397,7 +1540,8 @@ lang_output_section_find_by_flags (const asection *sec,
          if (look->bfd_section != NULL)
            {
              flags = look->bfd_section->flags;
-             if (match_type && !match_type (output_bfd, look->bfd_section,
+             if (match_type && !match_type (link_info.output_bfd,
+                                            look->bfd_section,
                                             sec->owner, sec))
                continue;
            }
@@ -1407,16 +1551,17 @@ lang_output_section_find_by_flags (const asection *sec,
            found = look;
        }
     }
-  else
+  else if ((sec->flags & SEC_ALLOC) != 0)
     {
-      /* .bss goes last.  */
+      /* .bss goes after any other alloc section.  */
       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,
+             if (match_type && !match_type (link_info.output_bfd,
+                                            look->bfd_section,
                                             sec->owner, sec))
                continue;
            }
@@ -1425,6 +1570,20 @@ lang_output_section_find_by_flags (const asection *sec,
            found = look;
        }
     }
+  else
+    {
+      /* non-alloc go last.  */
+      for (look = first; look; look = look->next)
+       {
+         flags = look->flags;
+         if (look->bfd_section != NULL)
+           flags = look->bfd_section->flags;
+         flags ^= sec->flags;
+         if (!(flags & SEC_DEBUGGING))
+           found = look;
+       }
+      return found;
+    }
 
   if (found || !match_type)
     return found;
@@ -1442,7 +1601,7 @@ output_prev_sec_find (lang_output_section_statement_type *os)
 
   for (lookup = os->prev; lookup != NULL; lookup = lookup->prev)
     {
-      if (lookup->constraint == -1)
+      if (lookup->constraint < 0)
        continue;
 
       if (lookup->bfd_section != NULL && lookup->bfd_section->owner != NULL)
@@ -1522,32 +1681,36 @@ insert_os_after (lang_output_section_statement_type *after)
 lang_output_section_statement_type *
 lang_insert_orphan (asection *s,
                    const char *secname,
+                   int constraint,
                    lang_output_section_statement_type *after,
                    struct orphan_save *place,
                    etree_type *address,
                    lang_statement_list_type *add_child)
 {
-  lang_statement_list_type *old;
   lang_statement_list_type add;
   const char *ps;
   lang_output_section_statement_type *os;
   lang_output_section_statement_type **os_tail;
 
-  /* Start building a list of statements for this section.
-     First save the current statement pointer.  */
-  old = stat_ptr;
-
   /* If we have found an appropriate place for the output section
      statements for this orphan, add them to our own private list,
      inserting them later into the global statement list.  */
   if (after != NULL)
     {
-      stat_ptr = &add;
-      lang_list_init (stat_ptr);
+      lang_list_init (&add);
+      push_stat_ptr (&add);
     }
 
+  if (link_info.relocatable || (s->flags & (SEC_LOAD | SEC_ALLOC)) == 0)
+    address = exp_intop (0);
+
+  os_tail = ((lang_output_section_statement_type **)
+            lang_output_section_statement.tail);
+  os = lang_enter_output_section_statement (secname, address, 0, NULL, NULL,
+                                           NULL, constraint);
+
   ps = NULL;
-  if (config.build_constructors)
+  if (config.build_constructors && *os_tail == os)
     {
       /* If the name of the section is representable in C, then create
         symbols to mark the start and the end of the section.  */
@@ -1560,42 +1723,30 @@ lang_insert_orphan (asection *s,
          etree_type *e_align;
 
          symname = (char *) xmalloc (ps - secname + sizeof "__start_" + 1);
-         symname[0] = bfd_get_symbol_leading_char (output_bfd);
+         symname[0] = bfd_get_symbol_leading_char (link_info.output_bfd);
          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_provide (symname,
-                                           exp_nameop (NAME, "."),
+                                           exp_unop (ABSOLUTE,
+                                                     exp_nameop (NAME, ".")),
                                            FALSE));
        }
     }
 
-  if (link_info.relocatable || (s->flags & (SEC_LOAD | SEC_ALLOC)) == 0)
-    address = exp_intop (0);
-
-  os_tail = ((lang_output_section_statement_type **)
-            lang_output_section_statement.tail);
-  os = lang_enter_output_section_statement (secname, address, 0, NULL, NULL,
-                                           NULL, 0);
-
   if (add_child == NULL)
     add_child = &os->children;
   lang_add_section (add_child, s, os);
 
   lang_leave_output_section_statement (0, "*default*", NULL, NULL);
 
-  if (config.build_constructors && *ps == '\0')
+  if (ps != NULL && *ps == '\0')
     {
       char *symname;
 
-      /* lang_leave_ouput_section_statement resets stat_ptr.
-        Put stat_ptr back where we want it.  */
-      if (after != NULL)
-       stat_ptr = &add;
-
       symname = (char *) xmalloc (ps - secname + sizeof "__stop_" + 1);
-      symname[0] = bfd_get_symbol_leading_char (output_bfd);
+      symname[0] = bfd_get_symbol_leading_char (link_info.output_bfd);
       sprintf (symname + (symname[0] != 0), "__stop_%s", secname);
       lang_add_assignment (exp_provide (symname,
                                        exp_nameop (NAME, "."),
@@ -1604,7 +1755,7 @@ lang_insert_orphan (asection *s,
 
   /* Restore the global list pointer.  */
   if (after != NULL)
-    stat_ptr = old;
+    pop_stat_ptr ();
 
   if (after != NULL && os->bfd_section != NULL)
     {
@@ -1632,7 +1783,7 @@ lang_insert_orphan (asection *s,
        }
 
       if (place->section == NULL)
-       place->section = &output_bfd->sections;
+       place->section = &link_info.output_bfd->sections;
 
       as = *place->section;
 
@@ -1641,18 +1792,18 @@ lang_insert_orphan (asection *s,
          /* Put the section at the end of the list.  */
 
          /* Unlink the section.  */
-         bfd_section_list_remove (output_bfd, snew);
+         bfd_section_list_remove (link_info.output_bfd, snew);
 
          /* Now tack it back on in the right place.  */
-         bfd_section_list_append (output_bfd, snew);
+         bfd_section_list_append (link_info.output_bfd, snew);
        }
       else if (as != snew && as->prev != snew)
        {
          /* Unlink the section.  */
-         bfd_section_list_remove (output_bfd, snew);
+         bfd_section_list_remove (link_info.output_bfd, snew);
 
          /* Now tack it back on in the right place.  */
-         bfd_section_list_insert_before (output_bfd, as, snew);
+         bfd_section_list_insert_before (link_info.output_bfd, as, snew);
        }
 
       /* Save the end of this list.  Further ophans of this type will
@@ -1690,8 +1841,8 @@ lang_insert_orphan (asection *s,
 
          /* Fix the global list pointer if we happened to tack our
             new list at the tail.  */
-         if (*old->tail == add.head)
-           old->tail = add.tail;
+         if (*stat_ptr->tail == add.head)
+           stat_ptr->tail = add.tail;
 
          /* Save the end of this list.  */
          place->stmt = add.tail;
@@ -1757,7 +1908,7 @@ lang_map (void)
 
       for (s = file->the_bfd->sections; s != NULL; s = s->next)
        if ((s->output_section == NULL
-            || s->output_section->owner != output_bfd)
+            || s->output_section->owner != link_info.output_bfd)
            && (s->flags & (SEC_LINKER_CREATED | SEC_KEEP)) == 0)
          {
            if (! dis_header_printed)
@@ -1779,7 +1930,7 @@ lang_map (void)
       char buf[100];
       int len;
 
-      fprintf (config.map_file, "%-16s ", m->name);
+      fprintf (config.map_file, "%-16s ", m->name_list.name);
 
       sprintf_vma (buf, m->origin);
       minfo ("0x%s ", buf);
@@ -1826,10 +1977,9 @@ lang_map (void)
 }
 
 static void
-init_map_userdata (abfd, sec, data)
-     bfd *abfd ATTRIBUTE_UNUSED;
-     asection *sec;
-     void *data ATTRIBUTE_UNUSED;
+init_map_userdata (bfd *abfd ATTRIBUTE_UNUSED,
+                  asection *sec,
+                  void *data ATTRIBUTE_UNUSED)
 {
   fat_section_userdata_type *new_data
     = ((fat_section_userdata_type *) (stat_alloc
@@ -1841,9 +1991,8 @@ init_map_userdata (abfd, sec, data)
 }
 
 static bfd_boolean
-sort_def_symbol (hash_entry, info)
-     struct bfd_link_hash_entry *hash_entry;
-     void *info ATTRIBUTE_UNUSED;
+sort_def_symbol (struct bfd_link_hash_entry *hash_entry,
+                void *info ATTRIBUTE_UNUSED)
 {
   if (hash_entry->type == bfd_link_hash_defined
       || hash_entry->type == bfd_link_hash_defweak)
@@ -1882,14 +2031,15 @@ init_os (lang_output_section_statement_type *s, asection *isec,
   if (strcmp (s->name, DISCARD_SECTION_NAME) == 0)
     einfo (_("%P%F: Illegal use of `%s' section\n"), DISCARD_SECTION_NAME);
 
-  s->bfd_section = bfd_get_section_by_name (output_bfd, s->name);
+  if (s->constraint != SPECIAL)
+    s->bfd_section = bfd_get_section_by_name (link_info.output_bfd, s->name);
   if (s->bfd_section == NULL)
-    s->bfd_section = bfd_make_section_with_flags (output_bfd, s->name,
-                                                 flags);
+    s->bfd_section = bfd_make_section_anyway_with_flags (link_info.output_bfd,
+                                                        s->name, flags);
   if (s->bfd_section == NULL)
     {
       einfo (_("%P%F: output format %s cannot represent section called %s\n"),
-            output_bfd->xvec->name, s->name);
+            link_info.output_bfd->xvec->name, s->name);
     }
   s->bfd_section->output_section = s->bfd_section;
   s->bfd_section->output_offset = 0;
@@ -1916,7 +2066,7 @@ init_os (lang_output_section_statement_type *s, asection *isec,
 
   if (isec)
     bfd_init_private_section_data (isec->owner, isec,
-                                  output_bfd, s->bfd_section,
+                                  link_info.output_bfd, s->bfd_section,
                                   &link_info);
 }
 
@@ -2423,8 +2573,6 @@ load_symbols (lang_input_statement_type *entry,
       && ! bfd_check_format_matches (entry->the_bfd, bfd_object, &matching))
     {
       bfd_error_type err;
-      lang_statement_list_type *hold;
-      bfd_boolean bad_load = TRUE;
       bfd_boolean save_ldlang_sysrooted_script;
       bfd_boolean save_as_needed, save_add_needed;
 
@@ -2446,9 +2594,7 @@ load_symbols (lang_input_statement_type *entry,
        }
       else if (err != bfd_error_file_not_recognized
               || place == NULL)
-         einfo (_("%F%B: file not recognized: %E\n"), entry->the_bfd);
-      else
-       bad_load = FALSE;
+       einfo (_("%F%B: file not recognized: %E\n"), entry->the_bfd);
 
       bfd_close (entry->the_bfd);
       entry->the_bfd = NULL;
@@ -2456,8 +2602,7 @@ load_symbols (lang_input_statement_type *entry,
       /* Try to interpret the file as a linker script.  */
       ldfile_open_command_file (entry->filename);
 
-      hold = stat_ptr;
-      stat_ptr = place;
+      push_stat_ptr (place);
       save_ldlang_sysrooted_script = ldlang_sysrooted_script;
       ldlang_sysrooted_script = entry->sysrooted;
       save_as_needed = as_needed;
@@ -2476,9 +2621,9 @@ load_symbols (lang_input_statement_type *entry,
       ldlang_sysrooted_script = save_ldlang_sysrooted_script;
       as_needed = save_as_needed;
       add_needed = save_add_needed;
-      stat_ptr = hold;
+      pop_stat_ptr ();
 
-      return ! bad_load;
+      return TRUE;
     }
 
   if (ldemul_recognized_file (entry))
@@ -2693,6 +2838,13 @@ closest_target_match (const bfd_target *target, void *data)
   if (target->flavour != original->flavour)
     return 0;
 
+  /* Ignore generic big and little endian elf vectors.  */
+  if (strcmp (target->name, "elf32-big") == 0
+      || strcmp (target->name, "elf64-big") == 0
+      || strcmp (target->name, "elf32-little") == 0
+      || strcmp (target->name, "elf64-little") == 0)
+    return 0;
+
   /* If we have not found a potential winner yet, then record this one.  */
   if (winner == NULL)
     {
@@ -2763,11 +2915,9 @@ lang_get_output_target (void)
 
 /* Open the output file.  */
 
-static bfd *
+static void
 open_output (const char *name)
 {
-  bfd *output;
-
   output_target = lang_get_output_target ();
 
   /* Has the user requested a particular endianness on the command
@@ -2819,9 +2969,9 @@ open_output (const char *name)
        }
     }
 
-  output = bfd_openw (name, output_target);
+  link_info.output_bfd = bfd_openw (name, output_target);
 
-  if (output == NULL)
+  if (link_info.output_bfd == NULL)
     {
       if (bfd_get_error () == bfd_error_invalid_target)
        einfo (_("%P%F: target %s not found\n"), output_target);
@@ -2831,19 +2981,18 @@ open_output (const char *name)
 
   delete_output_file_on_failure = TRUE;
 
-  if (! bfd_set_format (output, bfd_object))
+  if (! bfd_set_format (link_info.output_bfd, bfd_object))
     einfo (_("%P%F:%s: can not make object file: %E\n"), name);
-  if (! bfd_set_arch_mach (output,
+  if (! bfd_set_arch_mach (link_info.output_bfd,
                           ldfile_output_architecture,
                           ldfile_output_machine))
     einfo (_("%P%F:%s: can not set architecture: %E\n"), name);
 
-  link_info.hash = bfd_link_hash_table_create (output);
+  link_info.hash = bfd_link_hash_table_create (link_info.output_bfd);
   if (link_info.hash == NULL)
     einfo (_("%P%F: can not create hash table: %E\n"));
 
-  bfd_set_gp_size (output, g_switch_value);
-  return output;
+  bfd_set_gp_size (link_info.output_bfd, g_switch_value);
 }
 
 static void
@@ -2852,21 +3001,21 @@ ldlang_open_output (lang_statement_union_type *statement)
   switch (statement->header.type)
     {
     case lang_output_statement_enum:
-      ASSERT (output_bfd == NULL);
-      output_bfd = open_output (statement->output_statement.name);
+      ASSERT (link_info.output_bfd == NULL);
+      open_output (statement->output_statement.name);
       ldemul_set_output_arch ();
       if (config.magic_demand_paged && !link_info.relocatable)
-       output_bfd->flags |= D_PAGED;
+       link_info.output_bfd->flags |= D_PAGED;
       else
-       output_bfd->flags &= ~D_PAGED;
+       link_info.output_bfd->flags &= ~D_PAGED;
       if (config.text_read_only)
-       output_bfd->flags |= WP_TEXT;
+       link_info.output_bfd->flags |= WP_TEXT;
       else
-       output_bfd->flags &= ~WP_TEXT;
+       link_info.output_bfd->flags &= ~WP_TEXT;
       if (link_info.traditional_format)
-       output_bfd->flags |= BFD_TRADITIONAL_FORMAT;
+       link_info.output_bfd->flags |= BFD_TRADITIONAL_FORMAT;
       else
-       output_bfd->flags &= ~BFD_TRADITIONAL_FORMAT;
+       link_info.output_bfd->flags &= ~BFD_TRADITIONAL_FORMAT;
       break;
 
     case lang_target_statement_enum:
@@ -2919,7 +3068,8 @@ open_input_bfds (lang_statement_union_type *s, bfd_boolean force)
        case lang_wild_statement_enum:
          /* Maybe we should load the file's symbols.  */
          if (s->wild_statement.filename
-             && ! wildcardp (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);
          break;
@@ -2945,6 +3095,7 @@ open_input_bfds (lang_statement_union_type *s, bfd_boolean force)
        case lang_input_statement_enum:
          if (s->input_statement.real)
            {
+             lang_statement_union_type **os_tail;
              lang_statement_list_type add;
 
              s->input_statement.target = current_target;
@@ -2960,6 +3111,7 @@ open_input_bfds (lang_statement_union_type *s, bfd_boolean force)
                                       bfd_archive))
                s->input_statement.loaded = FALSE;
 
+             os_tail = lang_output_section_statement.tail;
              lang_list_init (&add);
 
              if (! load_symbols (&s->input_statement, &add))
@@ -2967,8 +3119,25 @@ open_input_bfds (lang_statement_union_type *s, bfd_boolean force)
 
              if (add.head != NULL)
                {
-                 *add.tail = s->header.next;
-                 s->header.next = add.head;
+                 /* If this was a script with output sections then
+                    tack any added statements on to the end of the
+                    list.  This avoids having to reorder the output
+                    section statement list.  Very likely the user
+                    forgot -T, and whatever we do here will not meet
+                    naive user expectations.  */
+                 if (os_tail != lang_output_section_statement.tail)
+                   {
+                     einfo (_("%P: warning: %s contains output sections;"
+                              " did you forget -T?\n"),
+                            s->input_statement.filename);
+                     *stat_ptr->tail = add.head;
+                     stat_ptr->tail = add.tail;
+                   }
+                 else
+                   {
+                     *add.tail = s->header.next;
+                     s->header.next = add.head;
+                   }
                }
            }
          break;
@@ -3078,7 +3247,7 @@ ldlang_add_undef (const char *const name)
 
   new->name = xstrdup (name);
 
-  if (output_bfd != NULL)
+  if (link_info.output_bfd != NULL)
     insert_undefined (new->name);
 }
 
@@ -3123,28 +3292,28 @@ check_input_sections
   for (; s != (lang_statement_union_type *) NULL; s = s->header.next)
     {
       switch (s->header.type)
-      {
-      case lang_wild_statement_enum:
-       walk_wild (&s->wild_statement, check_section_callback,
-                  output_section_statement);
-       if (! output_section_statement->all_input_readonly)
-         return;
-       break;
-      case lang_constructors_statement_enum:
-       check_input_sections (constructor_list.head,
-                             output_section_statement);
-       if (! output_section_statement->all_input_readonly)
-         return;
-       break;
-      case lang_group_statement_enum:
-       check_input_sections (s->group_statement.children.head,
-                             output_section_statement);
-       if (! output_section_statement->all_input_readonly)
-         return;
-       break;
-      default:
-       break;
-      }
+       {
+       case lang_wild_statement_enum:
+         walk_wild (&s->wild_statement, check_section_callback,
+                    output_section_statement);
+         if (! output_section_statement->all_input_readonly)
+           return;
+         break;
+       case lang_constructors_statement_enum:
+         check_input_sections (constructor_list.head,
+                               output_section_statement);
+         if (! output_section_statement->all_input_readonly)
+           return;
+         break;
+       case lang_group_statement_enum:
+         check_input_sections (s->group_statement.children.head,
+                               output_section_statement);
+         if (! output_section_statement->all_input_readonly)
+           return;
+         break;
+       default:
+         break;
+       }
     }
 }
 
@@ -3302,7 +3471,6 @@ map_input_to_output_sections
          break;
        case lang_address_statement_enum:
          /* Mark the specified section with the supplied address.
-
             If this section was actually a segment marker, then the
             directive is ignored if the linker script explicitly
             processed the segment marker.  Originally, the linker
@@ -3316,7 +3484,7 @@ map_input_to_output_sections
            {
              lang_output_section_statement_type *aos
                = (lang_output_section_statement_lookup
-                  (s->address_statement.section_name));
+                  (s->address_statement.section_name, 0, TRUE));
 
              if (aos->bfd_section == NULL)
                init_os (aos, NULL, 0);
@@ -3341,6 +3509,7 @@ process_insert_statements (void)
   lang_statement_union_type **s;
   lang_output_section_statement_type *first_os = NULL;
   lang_output_section_statement_type *last_os = NULL;
+  lang_output_section_statement_type *os;
 
   /* "start of list" is actually the statement immediately after
      the special abs_section output statement, so that it isn't
@@ -3352,7 +3521,16 @@ process_insert_statements (void)
        {
          /* Keep pointers to the first and last output section
             statement in the sequence we may be about to move.  */
-         last_os = &(*s)->output_section_statement;
+         os = &(*s)->output_section_statement;
+
+         ASSERT (last_os == NULL || last_os->next == os);
+         last_os = os;
+
+         /* Set constraint negative so that lang_output_section_find
+            won't match this output section statement.  At this
+            stage in linking constraint has values in the range
+            [-1, ONLY_IN_RW].  */
+         last_os->constraint = -2 - last_os->constraint;
          if (first_os == NULL)
            first_os = last_os;
        }
@@ -3360,30 +3538,20 @@ process_insert_statements (void)
        {
          lang_insert_statement_type *i = &(*s)->insert_statement;
          lang_output_section_statement_type *where;
-         lang_output_section_statement_type *os;
          lang_statement_union_type **ptr;
          lang_statement_union_type *first;
 
          where = lang_output_section_find (i->where);
          if (where != NULL && i->is_before)
            {
-             do 
+             do
                where = where->prev;
-             while (where != NULL && where->constraint == -1);
+             while (where != NULL && where->constraint < 0);
            }
          if (where == NULL)
            {
-             einfo (_("%X%P: %s not found for insert\n"), i->where);
-             continue;
-           }
-         /* You can't insert into the list you are moving.  */
-         for (os = first_os; os != NULL; os = os->next)
-           if (os == where || os == last_os)
-             break;
-         if (os == where)
-           {
-             einfo (_("%X%P: %s not found for insert\n"), i->where);
-             continue;
+             einfo (_("%F%P: %s not found for insert\n"), i->where);
+             return;
            }
 
          /* Deal with reordering the output section statement list.  */
@@ -3420,6 +3588,7 @@ process_insert_statements (void)
              last_sec = NULL;
              for (os = first_os; os != NULL; os = os->next)
                {
+                 os->constraint = -2 - os->constraint;
                  if (os->bfd_section != NULL
                      && os->bfd_section->owner != NULL)
                    {
@@ -3446,17 +3615,17 @@ process_insert_statements (void)
                      if (first_sec->prev != NULL)
                        first_sec->prev->next = last_sec->next;
                      else
-                       output_bfd->sections = last_sec->next;
+                       link_info.output_bfd->sections = last_sec->next;
                      if (last_sec->next != NULL)
                        last_sec->next->prev = first_sec->prev;
                      else
-                       output_bfd->section_last = first_sec->prev;
+                       link_info.output_bfd->section_last = first_sec->prev;
                      /* Add back.  */
                      last_sec->next = sec->next;
                      if (sec->next != NULL)
                        sec->next->prev = last_sec;
                      else
-                       output_bfd->section_last = last_sec;
+                       link_info.output_bfd->section_last = last_sec;
                      first_sec->prev = sec;
                      sec->next = first_sec;
                    }
@@ -3480,6 +3649,14 @@ process_insert_statements (void)
          s = &lang_output_section_statement.head;
        }
     }
+
+  /* Undo constraint twiddling.  */
+  for (os = first_os; os != NULL; os = os->next)
+    {
+      os->constraint = -2 - os->constraint;
+      if (os == last_os)
+       break;
+    }
 }
 
 /* An output section might have been removed after its statement was
@@ -3507,7 +3684,7 @@ strip_excluded_output_sections (void)
       asection *output_section;
       bfd_boolean exclude;
 
-      if (os->constraint == -1)
+      if (os->constraint < 0)
        continue;
 
       output_section = os->bfd_section;
@@ -3516,7 +3693,7 @@ strip_excluded_output_sections (void)
 
       exclude = (output_section->rawsize == 0
                 && (output_section->flags & SEC_KEEP) == 0
-                && !bfd_section_removed_from_list (output_bfd,
+                && !bfd_section_removed_from_list (link_info.output_bfd,
                                                    output_section));
 
       /* Some sections have not yet been sized, notably .gnu.version,
@@ -3548,8 +3725,8 @@ strip_excluded_output_sections (void)
              && !os->update_dot_tree)
            os->ignored = TRUE;
          output_section->flags |= SEC_EXCLUDE;
-         bfd_section_list_remove (output_bfd, output_section);
-         output_bfd->section_count--;
+         bfd_section_list_remove (link_info.output_bfd, output_section);
+         link_info.output_bfd->section_count--;
        }
     }
 
@@ -3589,6 +3766,10 @@ print_output_section_statement
 
          if (section->vma != section->lma)
            minfo (_(" load address 0x%V"), section->lma);
+
+         if (output_section_statement->update_dot_tree != NULL)
+           exp_fold_tree (output_section_statement->update_dot_tree,
+                          bfd_abs_section_ptr, &print_dot);
        }
 
       print_nl ();
@@ -3726,10 +3907,10 @@ print_assignment (lang_assignment_statement_type *assignment,
 static void
 print_input_statement (lang_input_statement_type *statm)
 {
-  if (statm->filename != NULL)
-    {
-      fprintf (config.map_file, "LOAD %s\n", statm->filename);
-    }
+  if (statm->filename != NULL
+      && (statm->the_bfd == NULL
+         || (statm->the_bfd->flags & BFD_LINKER_CREATED) == 0))
+    fprintf (config.map_file, "LOAD %s\n", statm->filename);
 }
 
 /* Print all symbols defined in a particular section.  This is called
@@ -3799,7 +3980,8 @@ print_input_section (asection *i)
       ++len;
     }
 
-  if (i->output_section != NULL && i->output_section->owner == output_bfd)
+  if (i->output_section != NULL
+      && i->output_section->owner == link_info.output_bfd)
     addr = i->output_section->vma + i->output_offset;
   else
     {
@@ -3826,14 +4008,19 @@ print_input_section (asection *i)
       minfo (_("%W (size before relaxing)\n"), i->rawsize);
     }
 
-  if (i->output_section != NULL && i->output_section->owner == output_bfd)
+  if (i->output_section != NULL
+      && i->output_section->owner == link_info.output_bfd)
     {
       if (link_info.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);
+      /* Update print_dot, but make sure that we do not move it
+        backwards - this could happen if we have overlays and a
+        later overlay is shorter than an earier one.  */
+      if (addr + TO_ADDR (size) > print_dot)
+       print_dot = addr + TO_ADDR (size);
     }
 }
 
@@ -4180,8 +4367,8 @@ insert_pad (lang_statement_union_type **ptr,
       /* Use the existing pad statement.  */
     }
   else if ((pad = *ptr) != NULL
-      && pad->header.type == lang_padding_statement_enum
-      && pad->padding_statement.output_section == output_section)
+          && pad->header.type == lang_padding_statement_enum
+          && pad->padding_statement.output_section == output_section)
     {
       /* Use the existing pad statement.  */
     }
@@ -4300,15 +4487,15 @@ lang_check_section_addresses (void)
   bfd_size_type amt;
   lang_memory_region_type *m;
 
-  if (bfd_count_sections (output_bfd) <= 1)
+  if (bfd_count_sections (link_info.output_bfd) <= 1)
     return;
 
-  amt = bfd_count_sections (output_bfd) * sizeof (asection *);
+  amt = bfd_count_sections (link_info.output_bfd) * sizeof (asection *);
   sections = xmalloc (amt);
 
   /* Scan all sections in the output list.  */
   count = 0;
-  for (s = output_bfd->sections; s != NULL; s = s->next)
+  for (s = link_info.output_bfd->sections; s != NULL; s = s->next)
     {
       /* Only consider loadable sections with real contents.  */
       if (IGNORE_SECTION (s) || s->size == 0)
@@ -4326,7 +4513,7 @@ lang_check_section_addresses (void)
 
   spp = sections;
   s = *spp++;
-  s_start = bfd_section_lma (output_bfd, s);
+  s_start = bfd_section_lma (link_info.output_bfd, s);
   s_end = s_start + TO_ADDR (s->size) - 1;
   for (count--; count; count--)
     {
@@ -4337,7 +4524,7 @@ lang_check_section_addresses (void)
       os_start = s_start;
       os_end = s_end;
       s = *spp++;
-      s_start = bfd_section_lma (output_bfd, s);
+      s_start = bfd_section_lma (link_info.output_bfd, s);
       s_end = s_start + TO_ADDR (s->size) - 1;
 
       /* Look for an overlap.  */
@@ -4358,8 +4545,8 @@ lang_check_section_addresses (void)
      a bfd_vma quantity in decimal.  */
   for (m = lang_memory_region_list; m; m = m->next)
     if (m->had_full_message)
-      einfo (_("%X%P: region %s overflowed by %ld bytes\n"),
-            m->name, (long)(m->current - (m->origin + m->length)));
+      einfo (_("%X%P: region `%s' overflowed by %ld bytes\n"),
+            m->name_list.name, (long)(m->current - (m->origin + m->length)));
 
 }
 
@@ -4381,21 +4568,21 @@ os_region_check (lang_output_section_statement_type *os,
     {
       if (tree != NULL)
        {
-         einfo (_("%X%P: address 0x%v of %B section %s"
-                  " is not within region %s\n"),
+         einfo (_("%X%P: address 0x%v of %B section `%s'"
+                  " is not within region `%s'\n"),
                 region->current,
                 os->bfd_section->owner,
                 os->bfd_section->name,
-                region->name);
+                region->name_list.name);
        }
       else if (!region->had_full_message)
        {
          region->had_full_message = TRUE;
 
-         einfo (_("%X%P: %B section %s will not fit in region %s\n"),
+         einfo (_("%X%P: %B section `%s' will not fit in region `%s'\n"),
                 os->bfd_section->owner,
                 os->bfd_section->name,
-                region->name);
+                region->name_list.name);
        }
     }
 }
@@ -4445,8 +4632,10 @@ lang_size_sections_1
               address from the input section.  FIXME: This is COFF
               specific; it would be cleaner if there were some other way
               to do this, but nothing simple comes to mind.  */
-           if ((bfd_get_flavour (output_bfd) == bfd_target_ecoff_flavour
-                || bfd_get_flavour (output_bfd) == bfd_target_coff_flavour)
+           if (((bfd_get_flavour (link_info.output_bfd)
+                 == bfd_target_ecoff_flavour)
+                || (bfd_get_flavour (link_info.output_bfd)
+                    == bfd_target_coff_flavour))
                && (os->bfd_section->flags & SEC_COFF_SHARED_LIBRARY) != 0)
              {
                asection *input;
@@ -4482,8 +4671,8 @@ lang_size_sections_1
                       from the region specification.  */
                    if (os->region == NULL
                        || ((os->bfd_section->flags & (SEC_ALLOC | SEC_LOAD))
-                           && os->region->name[0] == '*'
-                           && strcmp (os->region->name,
+                           && os->region->name_list.name[0] == '*'
+                           && strcmp (os->region->name_list.name,
                                       DEFAULT_MEMORY_REGION) == 0))
                      {
                        os->region = lang_memory_default (os->bfd_section);
@@ -4496,10 +4685,10 @@ lang_size_sections_1
                        && !IGNORE_SECTION (os->bfd_section)
                        && ! link_info.relocatable
                        && check_regions
-                       && strcmp (os->region->name,
+                       && strcmp (os->region->name_list.name,
                                   DEFAULT_MEMORY_REGION) == 0
                        && lang_memory_region_list != NULL
-                       && (strcmp (lang_memory_region_list->name,
+                       && (strcmp (lang_memory_region_list->name_list.name,
                                    DEFAULT_MEMORY_REGION) != 0
                            || lang_memory_region_list->next != NULL)
                        && expld.phase != lang_mark_phase_enum)
@@ -4516,12 +4705,12 @@ lang_size_sections_1
                        if (command_line.check_section_addresses)
                          einfo (_("%P%F: error: no memory region specified"
                                   " for loadable section `%s'\n"),
-                                bfd_get_section_name (output_bfd,
+                                bfd_get_section_name (link_info.output_bfd,
                                                       os->bfd_section));
                        else
                          einfo (_("%P: warning: no memory region specified"
                                   " for loadable section `%s'\n"),
-                                bfd_get_section_name (output_bfd,
+                                bfd_get_section_name (link_info.output_bfd,
                                                       os->bfd_section));
                      }
 
@@ -4546,7 +4735,12 @@ lang_size_sections_1
                             os->name, (unsigned long) (newdot - savedot));
                  }
 
-               bfd_set_section_vma (0, os->bfd_section, newdot);
+               /* PR 6945: Do not update the vma's of output sections
+                  when performing a relocatable link on COFF objects.  */
+               if (! link_info.relocatable
+                   || (bfd_get_flavour (link_info.output_bfd)
+                       != bfd_target_coff_flavour))
+                 bfd_set_section_vma (0, os->bfd_section, newdot);
 
                os->bfd_section->output_offset = 0;
              }
@@ -4587,9 +4781,7 @@ lang_size_sections_1
                bfd_vma lma = exp_get_abs_int (os->load_base, 0, "load base");
                os->bfd_section->lma = lma;
              }
-           else if (os->region != NULL
-                    && os->lma_region != NULL
-                    && os->lma_region != os->region)
+           else if (os->lma_region != NULL)
              {
                bfd_vma lma = os->lma_region->current;
 
@@ -4694,7 +4886,8 @@ lang_size_sections_1
                  os_region_check (os, os->region, os->addr_tree,
                                   os->bfd_section->vma);
 
-               if (os->lma_region != NULL && os->lma_region != os->region)
+               if (os->lma_region != NULL && os->lma_region != os->region
+                   && (os->bfd_section->flags & SEC_LOAD))
                  {
                    os->lma_region->current
                      = os->bfd_section->lma + TO_ADDR (os->bfd_section->size);
@@ -4983,17 +5176,23 @@ lang_size_sections (bfd_boolean *relax, bfd_boolean check_regions)
     {
       /* If DATA_SEGMENT_ALIGN DATA_SEGMENT_RELRO_END pair was seen, try
         to put expld.dataseg.relro on a (common) page boundary.  */
-      bfd_vma old_min_base, relro_end, maxpage;
+      bfd_vma min_base, old_base, relro_end, maxpage;
 
       expld.dataseg.phase = exp_dataseg_relro_adjust;
-      old_min_base = expld.dataseg.min_base;
       maxpage = expld.dataseg.maxpagesize;
+      /* MIN_BASE is the absolute minimum address we are allowed to start the
+        read-write segment (byte before will be mapped read-only).  */
+      min_base = (expld.dataseg.min_base + maxpage - 1) & ~(maxpage - 1);
+      /* OLD_BASE is the address for a feasible minimum address which will
+        still not cause a data overlap inside MAXPAGE causing file offset skip
+        by MAXPAGE.  */
+      old_base = expld.dataseg.base;
       expld.dataseg.base += (-expld.dataseg.relro_end
                             & (expld.dataseg.pagesize - 1));
       /* Compute the expected PT_GNU_RELRO segment end.  */
-      relro_end = (expld.dataseg.relro_end + expld.dataseg.pagesize - 1)
-                 & ~(expld.dataseg.pagesize - 1);
-      if (old_min_base + maxpage < expld.dataseg.base)
+      relro_end = ((expld.dataseg.relro_end + expld.dataseg.pagesize - 1)
+                  & ~(expld.dataseg.pagesize - 1));
+      if (min_base + maxpage < expld.dataseg.base)
        {
          expld.dataseg.base -= maxpage;
          relro_end -= maxpage;
@@ -5004,13 +5203,14 @@ lang_size_sections (bfd_boolean *relax, bfd_boolean check_regions)
        {
          /* The alignment of sections between DATA_SEGMENT_ALIGN
             and DATA_SEGMENT_RELRO_END caused huge padding to be
-            inserted at DATA_SEGMENT_RELRO_END.  Try some other base.  */
+            inserted at DATA_SEGMENT_RELRO_END.  Try to start a bit lower so
+            that the section alignments will fit in.  */
          asection *sec;
          unsigned int max_alignment_power = 0;
 
          /* Find maximum alignment power of sections between
             DATA_SEGMENT_ALIGN and DATA_SEGMENT_RELRO_END.  */
-         for (sec = output_bfd->sections; sec; sec = sec->next)
+         for (sec = link_info.output_bfd->sections; sec; sec = sec->next)
            if (sec->vma >= expld.dataseg.base
                && sec->vma < expld.dataseg.relro_end
                && sec->alignment_power > max_alignment_power)
@@ -5018,8 +5218,7 @@ lang_size_sections (bfd_boolean *relax, bfd_boolean check_regions)
 
          if (((bfd_vma) 1 << max_alignment_power) < expld.dataseg.pagesize)
            {
-             if (expld.dataseg.base - (1 << max_alignment_power)
-                 < old_min_base)
+             if (expld.dataseg.base - (1 << max_alignment_power) < old_base)
                expld.dataseg.base += expld.dataseg.pagesize;
              expld.dataseg.base -= (1 << max_alignment_power);
              lang_reset_memory_regions ();
@@ -5084,6 +5283,9 @@ lang_do_assignments_1 (lang_statement_union_type *s,
                    || (os->bfd_section->flags & SEC_THREAD_LOCAL) == 0
                    || link_info.relocatable)
                  dot += TO_ADDR (os->bfd_section->size);
+
+               if (os->update_dot_tree != NULL)
+                 exp_fold_tree (os->update_dot_tree, bfd_abs_section_ptr, &dot);
              }
          }
          break;
@@ -5209,13 +5411,13 @@ lang_set_startof (void)
   if (link_info.relocatable)
     return;
 
-  for (s = output_bfd->sections; s != NULL; s = s->next)
+  for (s = link_info.output_bfd->sections; s != NULL; s = s->next)
     {
       const char *secname;
       char *buf;
       struct bfd_link_hash_entry *h;
 
-      secname = bfd_get_section_name (output_bfd, s);
+      secname = bfd_get_section_name (link_info.output_bfd, s);
       buf = xmalloc (10 + strlen (secname));
 
       sprintf (buf, ".startof.%s", secname);
@@ -5223,7 +5425,7 @@ lang_set_startof (void)
       if (h != NULL && h->type == bfd_link_hash_undefined)
        {
          h->type = bfd_link_hash_defined;
-         h->u.def.value = bfd_get_section_vma (output_bfd, s);
+         h->u.def.value = bfd_get_section_vma (link_info.output_bfd, s);
          h->u.def.section = bfd_abs_section_ptr;
        }
 
@@ -5247,7 +5449,7 @@ lang_end (void)
   bfd_boolean warn;
 
   if ((link_info.relocatable && !link_info.gc_sections)
-      || link_info.shared)
+      || (link_info.shared && !link_info.executable))
     warn = entry_from_cmdline;
   else
     warn = TRUE;
@@ -5278,10 +5480,10 @@ lang_end (void)
       bfd_vma val;
 
       val = (h->u.def.value
-            + bfd_get_section_vma (output_bfd,
+            + bfd_get_section_vma (link_info.output_bfd,
                                    h->u.def.section->output_section)
             + h->u.def.section->output_offset);
-      if (! bfd_set_start_address (output_bfd, val))
+      if (! bfd_set_start_address (link_info.output_bfd, val))
        einfo (_("%P%F:%s: can't set start address\n"), entry_symbol.name);
     }
   else
@@ -5294,7 +5496,7 @@ lang_end (void)
       val = bfd_scan_vma (entry_symbol.name, &send, 0);
       if (*send == '\0')
        {
-         if (! bfd_set_start_address (output_bfd, val))
+         if (! bfd_set_start_address (link_info.output_bfd, val))
            einfo (_("%P%F: can't set start address\n"));
        }
       else
@@ -5303,17 +5505,17 @@ lang_end (void)
 
          /* Can't find the entry symbol, and it's not a number.  Use
             the first address in the text section.  */
-         ts = bfd_get_section_by_name (output_bfd, entry_section);
+         ts = bfd_get_section_by_name (link_info.output_bfd, entry_section);
          if (ts != NULL)
            {
              if (warn)
                einfo (_("%P: warning: cannot find entry symbol %s;"
                         " defaulting to %V\n"),
                       entry_symbol.name,
-                      bfd_get_section_vma (output_bfd, ts));
-             if (! bfd_set_start_address (output_bfd,
-                                          bfd_get_section_vma (output_bfd,
-                                                               ts)))
+                      bfd_get_section_vma (link_info.output_bfd, ts));
+             if (!(bfd_set_start_address
+                   (link_info.output_bfd,
+                    bfd_get_section_vma (link_info.output_bfd, ts))))
                einfo (_("%P%F: can't set start address\n"));
            }
          else
@@ -5354,7 +5556,7 @@ lang_check (void)
     {
       input_bfd = file->input_statement.the_bfd;
       compatible
-       = bfd_arch_get_compatible (input_bfd, output_bfd,
+       = bfd_arch_get_compatible (input_bfd, link_info.output_bfd,
                                   command_line.accept_unknown_input_arch);
 
       /* In general it is not possible to perform a relocatable
@@ -5365,13 +5567,14 @@ lang_check (void)
         relocs for other link purposes than a final link).  */
       if ((link_info.relocatable || link_info.emitrelocations)
          && (compatible == NULL
-             || bfd_get_flavour (input_bfd) != bfd_get_flavour (output_bfd))
+             || (bfd_get_flavour (input_bfd)
+                 != bfd_get_flavour (link_info.output_bfd)))
          && (bfd_get_file_flags (input_bfd) & HAS_RELOC) != 0)
        {
          einfo (_("%P%F: Relocatable linking with relocations from"
                   " format %s (%B) to format %s (%B) is not supported\n"),
                 bfd_get_target (input_bfd), input_bfd,
-                bfd_get_target (output_bfd), output_bfd);
+                bfd_get_target (link_info.output_bfd), link_info.output_bfd);
          /* einfo with %F exits.  */
        }
 
@@ -5381,7 +5584,7 @@ lang_check (void)
            einfo (_("%P%X: %s architecture of input file `%B'"
                     " is incompatible with %s output\n"),
                   bfd_printable_name (input_bfd), input_bfd,
-                  bfd_printable_name (output_bfd));
+                  bfd_printable_name (link_info.output_bfd));
        }
       else if (bfd_count_sections (input_bfd))
        {
@@ -5397,7 +5600,7 @@ lang_check (void)
             information which is needed in the output file.  */
          if (! command_line.warn_mismatch)
            pfn = bfd_set_error_handler (ignore_bfd_errors);
-         if (! bfd_merge_private_bfd_data (input_bfd, output_bfd))
+         if (! bfd_merge_private_bfd_data (input_bfd, link_info.output_bfd))
            {
              if (command_line.warn_mismatch)
                einfo (_("%P%X: failed to merge target specific data"
@@ -5411,7 +5614,7 @@ lang_check (void)
 
 /* Look through all the global common symbols and attach them to the
    correct section.  The -sort-common command line switch may be used
-   to roughly sort the entries by size.  */
+   to roughly sort the entries by alignment.  */
 
 static void
 lang_common (void)
@@ -5426,10 +5629,24 @@ lang_common (void)
     bfd_link_hash_traverse (link_info.hash, lang_one_common, NULL);
   else
     {
-      int power;
+      unsigned int power;
+
+      if (config.sort_common == sort_descending)
+       {
+         for (power = 4; power > 0; power--)
+           bfd_link_hash_traverse (link_info.hash, lang_one_common, &power);
 
-      for (power = 4; power >= 0; power--)
-       bfd_link_hash_traverse (link_info.hash, lang_one_common, &power);
+         power = 0;
+         bfd_link_hash_traverse (link_info.hash, lang_one_common, &power);
+       }
+      else
+       {
+         for (power = 0; power <= 4; power++)
+           bfd_link_hash_traverse (link_info.hash, lang_one_common, &power);
+
+         power = UINT_MAX;
+         bfd_link_hash_traverse (link_info.hash, lang_one_common, &power);
+       }
     }
 }
 
@@ -5448,32 +5665,17 @@ lang_one_common (struct bfd_link_hash_entry *h, void *info)
   size = h->u.c.size;
   power_of_two = h->u.c.p->alignment_power;
 
-  if (config.sort_common
-      && power_of_two < (unsigned int) *(int *) info)
+  if (config.sort_common == sort_descending
+      && power_of_two < *(unsigned int *) info)
+    return TRUE;
+  else if (config.sort_common == sort_ascending
+          && power_of_two > *(unsigned int *) info)
     return TRUE;
 
   section = h->u.c.p->section;
-
-  /* Increase the size of the section to align the common sym.  */
-  section->size += ((bfd_vma) 1 << (power_of_two + opb_shift)) - 1;
-  section->size &= (- (bfd_vma) 1 << (power_of_two + opb_shift));
-
-  /* Adjust the alignment if necessary.  */
-  if (power_of_two > section->alignment_power)
-    section->alignment_power = power_of_two;
-
-  /* Change the symbol from common to defined.  */
-  h->type = bfd_link_hash_defined;
-  h->u.def.section = section;
-  h->u.def.value = section->size;
-
-  /* Increase the size of the section.  */
-  section->size += size;
-
-  /* Make sure the section is allocated in memory, and make sure that
-     it is no longer a common section.  */
-  section->flags |= SEC_ALLOC;
-  section->flags &= ~SEC_IS_COMMON;
+  if (!bfd_define_common_symbol (link_info.output_bfd, &link_info, h))
+    einfo (_("%P%F: Could not define common symbol `%T': %E\n"),
+          h->root.string);
 
   if (config.map_file != NULL)
     {
@@ -5489,7 +5691,7 @@ lang_one_common (struct bfd_link_hash_entry *h, void *info)
          header_printed = TRUE;
        }
 
-      name = bfd_demangle (output_bfd, h->root.string,
+      name = bfd_demangle (link_info.output_bfd, h->root.string,
                           DMGL_ANSI | DMGL_PARAMS);
       if (name == NULL)
        {
@@ -5565,23 +5767,29 @@ lang_place_orphans (void)
                      || command_line.force_common_definition)
                    {
                      if (default_common_section == NULL)
-                       {
-                         default_common_section =
-                           lang_output_section_statement_lookup (".bss");
-
-                       }
+                       default_common_section
+                         = lang_output_section_statement_lookup (".bss", 0,
+                                                                 TRUE);
                      lang_add_section (&default_common_section->children, s,
                                        default_common_section);
                    }
                }
-             else if (ldemul_place_orphan (s))
-               ;
              else
                {
-                 lang_output_section_statement_type *os;
+                 const char *name = s->name;
+                 int constraint = 0;
+
+                 if (config.unique_orphan_sections || unique_section_p (s))
+                   constraint = SPECIAL;
 
-                 os = lang_output_section_statement_lookup (s->name);
-                 lang_add_section (&os->children, s, os);
+                 if (!ldemul_place_orphan (s, name, constraint))
+                   {
+                     lang_output_section_statement_type *os;
+                     os = lang_output_section_statement_lookup (name,
+                                                                constraint,
+                                                                TRUE);
+                     lang_add_section (&os->children, s, os);
+                   }
                }
            }
        }
@@ -5664,7 +5872,7 @@ 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 != output_bfd);
+  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;
@@ -5727,11 +5935,9 @@ lang_enter_output_section_statement (const char *output_section_statement_name,
 {
   lang_output_section_statement_type *os;
 
-   os = lang_output_section_statement_lookup_1 (output_section_statement_name,
-                                               constraint);
-   current_section = os;
-
-  /* Make next things chain into subchain of this.  */
+  os = lang_output_section_statement_lookup (output_section_statement_name,
+                                            constraint, TRUE);
+  current_section = os;
 
   if (os->addr_tree == NULL)
     {
@@ -5743,7 +5949,9 @@ lang_enter_output_section_statement (const char *output_section_statement_name,
   else
     os->flags = SEC_NEVER_LOAD;
   os->block_value = 1;
-  stat_ptr = &os->children;
+
+  /* Make next things chain into subchain of this.  */
+  push_stat_ptr (&os->children);
 
   os->subsection_alignment =
     topower (exp_get_value_int (subalign, -1, "subsection alignment"));
@@ -5786,7 +5994,7 @@ lang_reset_memory_regions (void)
       os->processed_lma = FALSE;
     }
 
-  for (o = output_bfd->sections; o != NULL; o = o->next)
+  for (o = link_info.output_bfd->sections; o != NULL; o = o->next)
     {
       /* Save the last size for possible use by bfd_relax_section.  */
       o->rawsize = o->size;
@@ -5858,7 +6066,7 @@ lang_gc_sections (void)
     }
 
   if (link_info.gc_sections)
-    bfd_gc_sections (output_bfd, &link_info);
+    bfd_gc_sections (link_info.output_bfd, &link_info);
 }
 
 /* Worker for lang_find_relro_sections_1.  */
@@ -5873,7 +6081,7 @@ find_relro_section_callback (lang_wild_statement_type *ptr ATTRIBUTE_UNUSED,
   /* Discarded, excluded and ignored sections effectively have zero
      size.  */
   if (section->output_section != NULL
-      && section->output_section->owner == output_bfd
+      && section->output_section->owner == link_info.output_bfd
       && (section->output_section->flags & SEC_EXCLUDE) == 0
       && !IGNORE_SECTION (section)
       && section->size != 0)
@@ -6043,10 +6251,10 @@ lang_process (void)
         sections, so that GCed sections are not merged, but before
         assigning dynamic symbols, since removing whole input sections
         is hard then.  */
-      bfd_merge_sections (output_bfd, &link_info);
+      bfd_merge_sections (link_info.output_bfd, &link_info);
 
       /* Look for a text section and set the readonly attribute in it.  */
-      found = bfd_get_section_by_name (output_bfd, ".text");
+      found = bfd_get_section_by_name (link_info.output_bfd, ".text");
 
       if (found != NULL)
        {
@@ -6108,8 +6316,7 @@ lang_process (void)
   ldemul_finish ();
 
   /* Make sure that the section addresses make sense.  */
-  if (! link_info.relocatable
-      && command_line.check_section_addresses)
+  if (command_line.check_section_addresses)
     lang_check_section_addresses ();
 
   lang_end ();
@@ -6350,9 +6557,18 @@ lang_leave_output_section_statement (fill_type *fill, const char *memspec,
                    memspec, lma_memspec,
                    current_section->load_base != NULL,
                    current_section->addr_tree != NULL);
+
+  /* If this section has no load region or base, but has the same
+     region as the previous section, then propagate the previous
+     section's load region.  */
+
+  if (!current_section->lma_region && !current_section->load_base
+      && current_section->region == current_section->prev->region)
+    current_section->lma_region = current_section->prev->lma_region;
+  
   current_section->fill = fill;
   current_section->phdrs = phdrs;
-  stat_ptr = &statement_list;
+  pop_stat_ptr ();
 }
 
 /* Create an absolute symbol with the given name with the value of the
@@ -6376,11 +6592,11 @@ lang_abs_symbol_at_beginning_of (const char *secname, const char *name)
 
       h->type = bfd_link_hash_defined;
 
-      sec = bfd_get_section_by_name (output_bfd, secname);
+      sec = bfd_get_section_by_name (link_info.output_bfd, secname);
       if (sec == NULL)
        h->u.def.value = 0;
       else
-       h->u.def.value = bfd_get_section_vma (output_bfd, sec);
+       h->u.def.value = bfd_get_section_vma (link_info.output_bfd, sec);
 
       h->u.def.section = bfd_abs_section_ptr;
     }
@@ -6407,11 +6623,11 @@ lang_abs_symbol_at_end_of (const char *secname, const char *name)
 
       h->type = bfd_link_hash_defined;
 
-      sec = bfd_get_section_by_name (output_bfd, secname);
+      sec = bfd_get_section_by_name (link_info.output_bfd, secname);
       if (sec == NULL)
        h->u.def.value = 0;
       else
-       h->u.def.value = (bfd_get_section_vma (output_bfd, sec)
+       h->u.def.value = (bfd_get_section_vma (link_info.output_bfd, sec)
                          + TO_ADDR (sec->size));
 
       h->u.def.section = bfd_abs_section_ptr;
@@ -6469,7 +6685,7 @@ lang_enter_group (void)
 
   g = new_stat (lang_group_statement, stat_ptr);
   lang_list_init (&g->children);
-  stat_ptr = &g->children;
+  push_stat_ptr (&g->children);
 }
 
 /* Leave a group.  This just resets stat_ptr to start writing to the
@@ -6480,7 +6696,7 @@ lang_enter_group (void)
 void
 lang_leave_group (void)
 {
-  stat_ptr = &statement_list;
+  pop_stat_ptr ();
 }
 
 /* Add a new program header.  This is called for each entry in a PHDRS
@@ -6539,7 +6755,7 @@ lang_record_phdrs (void)
        {
          lang_output_section_phdr_list *pl;
 
-         if (os->constraint == -1)
+         if (os->constraint < 0)
            continue;
 
          pl = os->phdrs;
@@ -6552,6 +6768,10 @@ lang_record_phdrs (void)
                  || (os->bfd_section->flags & SEC_ALLOC) == 0)
                continue;
 
+             /* Don't add orphans to PT_INTERP header.  */
+             if (l->type == 3)
+               continue;
+
              if (last == NULL)
                {
                  lang_output_section_statement_type * tmp_os;
@@ -6605,7 +6825,7 @@ lang_record_phdrs (void)
       else
        at = exp_get_vma (l->at, 0, "phdr load address");
 
-      if (! bfd_record_phdr (output_bfd, l->type,
+      if (! bfd_record_phdr (link_info.output_bfd, l->type,
                             l->flags != NULL, flags, l->at != NULL,
                             at, l->filehdr, l->phdrs, c, secs))
        einfo (_("%F%P: bfd_record_phdr failed: %E\n"));
@@ -6620,7 +6840,7 @@ lang_record_phdrs (void)
     {
       lang_output_section_phdr_list *pl;
 
-      if (os->constraint == -1
+      if (os->constraint < 0
          || os->bfd_section == NULL)
        continue;
 
@@ -6868,55 +7088,55 @@ lang_vers_match (struct bfd_elf_version_expr_head *head,
        java_sym = sym;
     }
 
-  if (head->htab && (prev == NULL || prev->symbol))
+  if (head->htab && (prev == NULL || prev->literal))
     {
       struct bfd_elf_version_expr e;
 
       switch (prev ? prev->mask : 0)
        {
-         case 0:
-           if (head->mask & BFD_ELF_VERSION_C_TYPE)
-             {
-               e.symbol = sym;
-               expr = htab_find (head->htab, &e);
-               while (expr && strcmp (expr->symbol, sym) == 0)
-                 if (expr->mask == BFD_ELF_VERSION_C_TYPE)
-                   goto out_ret;
-                 else
-                   expr = expr->next;
-             }
-           /* Fallthrough */
-         case BFD_ELF_VERSION_C_TYPE:
-           if (head->mask & BFD_ELF_VERSION_CXX_TYPE)
-             {
-               e.symbol = cxx_sym;
-               expr = htab_find (head->htab, &e);
-               while (expr && strcmp (expr->symbol, cxx_sym) == 0)
-                 if (expr->mask == BFD_ELF_VERSION_CXX_TYPE)
-                   goto out_ret;
-                 else
-                   expr = expr->next;
-             }
-           /* Fallthrough */
-         case BFD_ELF_VERSION_CXX_TYPE:
-           if (head->mask & BFD_ELF_VERSION_JAVA_TYPE)
-             {
-               e.symbol = java_sym;
-               expr = htab_find (head->htab, &e);
-               while (expr && strcmp (expr->symbol, java_sym) == 0)
-                 if (expr->mask == BFD_ELF_VERSION_JAVA_TYPE)
-                   goto out_ret;
-                 else
-                   expr = expr->next;
-             }
-           /* Fallthrough */
-         default:
-           break;
+       case 0:
+         if (head->mask & BFD_ELF_VERSION_C_TYPE)
+           {
+             e.pattern = sym;
+             expr = htab_find (head->htab, &e);
+             while (expr && strcmp (expr->pattern, sym) == 0)
+               if (expr->mask == BFD_ELF_VERSION_C_TYPE)
+                 goto out_ret;
+               else
+                 expr = expr->next;
+           }
+         /* Fallthrough */
+       case BFD_ELF_VERSION_C_TYPE:
+         if (head->mask & BFD_ELF_VERSION_CXX_TYPE)
+           {
+             e.pattern = cxx_sym;
+             expr = htab_find (head->htab, &e);
+             while (expr && strcmp (expr->pattern, cxx_sym) == 0)
+               if (expr->mask == BFD_ELF_VERSION_CXX_TYPE)
+                 goto out_ret;
+               else
+                 expr = expr->next;
+           }
+         /* Fallthrough */
+       case BFD_ELF_VERSION_CXX_TYPE:
+         if (head->mask & BFD_ELF_VERSION_JAVA_TYPE)
+           {
+             e.pattern = java_sym;
+             expr = htab_find (head->htab, &e);
+             while (expr && strcmp (expr->pattern, java_sym) == 0)
+               if (expr->mask == BFD_ELF_VERSION_JAVA_TYPE)
+                 goto out_ret;
+               else
+                 expr = expr->next;
+           }
+         /* Fallthrough */
+       default:
+         break;
        }
     }
 
   /* Finally, try the wildcards.  */
-  if (prev == NULL || prev->symbol)
+  if (prev == NULL || prev->literal)
     expr = head->remaining;
   else
     expr = prev->next;
@@ -6940,7 +7160,7 @@ lang_vers_match (struct bfd_elf_version_expr_head *head,
        break;
     }
 
-out_ret:
+ out_ret:
   if (cxx_sym != sym)
     free ((char *) cxx_sym);
   if (java_sym != sym)
@@ -6949,7 +7169,7 @@ out_ret:
 }
 
 /* Return NULL if the PATTERN argument is a glob pattern, otherwise,
-   return a string pointing to the symbol name.  */
+   return a pointer to the symbol name with any backslash quotes removed.  */
 
 static const char *
 realsymbol (const char *pattern)
@@ -6962,22 +7182,24 @@ realsymbol (const char *pattern)
     {
       /* It is a glob pattern only if there is no preceding
         backslash.  */
-      if (! backslash && (*p == '?' || *p == '*' || *p == '['))
-       {
-         free (symbol);
-         return NULL;
-       }
-
       if (backslash)
        {
          /* Remove the preceding backslash.  */
          *(s - 1) = *p;
+         backslash = FALSE;
          changed = TRUE;
        }
       else
-       *s++ = *p;
+       {
+         if (*p == '?' || *p == '*' || *p == '[')
+           {
+             free (symbol);
+             return NULL;
+           }
 
-      backslash = *p == '\\';
+         *s++ = *p;
+         backslash = *p == '\\';
+       }
     }
 
   if (changed)
@@ -7006,10 +7228,15 @@ lang_new_vers_pattern (struct bfd_elf_version_expr *orig,
 
   ret = xmalloc (sizeof *ret);
   ret->next = orig;
-  ret->pattern = literal_p ? NULL : new;
   ret->symver = 0;
   ret->script = 0;
-  ret->symbol = literal_p ? new : realsymbol (new);
+  ret->literal = TRUE;
+  ret->pattern = literal_p ? new : realsymbol (new);
+  if (ret->pattern == NULL)
+    {
+      ret->pattern = new;
+      ret->literal = FALSE;
+    }
 
   if (lang == NULL || strcasecmp (lang, "C") == 0)
     ret->mask = BFD_ELF_VERSION_C_TYPE;
@@ -7053,7 +7280,7 @@ version_expr_head_hash (const void *p)
 {
   const struct bfd_elf_version_expr *e = p;
 
-  return htab_hash_string (e->symbol);
+  return htab_hash_string (e->pattern);
 }
 
 static int
@@ -7062,7 +7289,7 @@ version_expr_head_eq (const void *p1, const void *p2)
   const struct bfd_elf_version_expr *e1 = p1;
   const struct bfd_elf_version_expr *e2 = p2;
 
-  return strcmp (e1->symbol, e2->symbol) == 0;
+  return strcmp (e1->pattern, e2->pattern) == 0;
 }
 
 static void
@@ -7074,7 +7301,7 @@ lang_finalize_version_expr_head (struct bfd_elf_version_expr_head *head)
 
   for (e = head->list; e; e = e->next)
     {
-      if (e->symbol)
+      if (e->literal)
        count++;
       head->mask |= e->mask;
     }
@@ -7088,7 +7315,7 @@ lang_finalize_version_expr_head (struct bfd_elf_version_expr_head *head)
       for (e = head->list; e; e = next)
        {
          next = e->next;
-         if (!e->symbol)
+         if (!e->literal)
            {
              *remaining_loc = e;
              remaining_loc = &e->next;
@@ -7113,14 +7340,14 @@ lang_finalize_version_expr_head (struct bfd_elf_version_expr_head *head)
                      last = e1;
                      e1 = e1->next;
                    }
-                 while (e1 && strcmp (e1->symbol, e->symbol) == 0);
+                 while (e1 && strcmp (e1->pattern, e->pattern) == 0);
 
                  if (last == NULL)
                    {
                      /* This is a duplicate.  */
                      /* FIXME: Memory leak.  Sometimes pattern is not
                         xmalloced alone, but in larger chunk of memory.  */
-                     /* free (e->symbol); */
+                     /* free (e->pattern); */
                      free (e);
                    }
                  else
@@ -7184,18 +7411,18 @@ lang_register_vers_node (const char *name,
        {
          struct bfd_elf_version_expr *e2;
 
-         if (t->locals.htab && e1->symbol)
+         if (t->locals.htab && e1->literal)
            {
              e2 = htab_find (t->locals.htab, e1);
-             while (e2 && strcmp (e1->symbol, e2->symbol) == 0)
+             while (e2 && strcmp (e1->pattern, e2->pattern) == 0)
                {
                  if (e1->mask == e2->mask)
                    einfo (_("%X%P: duplicate expression `%s'"
-                            " in version information\n"), e1->symbol);
+                            " in version information\n"), e1->pattern);
                  e2 = e2->next;
                }
            }
-         else if (!e1->symbol)
+         else if (!e1->literal)
            for (e2 = t->locals.remaining; e2 != NULL; e2 = e2->next)
              if (strcmp (e1->pattern, e2->pattern) == 0
                  && e1->mask == e2->mask)
@@ -7210,19 +7437,19 @@ lang_register_vers_node (const char *name,
        {
          struct bfd_elf_version_expr *e2;
 
-         if (t->globals.htab && e1->symbol)
+         if (t->globals.htab && e1->literal)
            {
              e2 = htab_find (t->globals.htab, e1);
-             while (e2 && strcmp (e1->symbol, e2->symbol) == 0)
+             while (e2 && strcmp (e1->pattern, e2->pattern) == 0)
                {
                  if (e1->mask == e2->mask)
                    einfo (_("%X%P: duplicate expression `%s'"
                             " in version information\n"),
-                          e1->symbol);
+                          e1->pattern);
                  e2 = e2->next;
                }
            }
-         else if (!e1->symbol)
+         else if (!e1->literal)
            for (e2 = t->globals.remaining; e2 != NULL; e2 = e2->next)
              if (strcmp (e1->pattern, e2->pattern) == 0
                  && e1->mask == e2->mask)