]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - ld/ldlang.c
Revert "2.41 Release sources"
[thirdparty/binutils-gdb.git] / ld / ldlang.c
index e7bc9f2d268a46fc61753e8e42a1fff8b48875ad..f7760fed69bf2cf28d853f763bf976ffb54a9c02 100644 (file)
@@ -1,5 +1,5 @@
 /* Linker command language support.
-   Copyright (C) 1991-2022 Free Software Foundation, Inc.
+   Copyright (C) 1991-2023 Free Software Foundation, Inc.
 
    This file is part of the GNU Binutils.
 
@@ -27,7 +27,6 @@
 #include "obstack.h"
 #include "bfdlink.h"
 #include "ctf-api.h"
-
 #include "ld.h"
 #include "ldmain.h"
 #include "ldexp.h"
 #include "demangle.h"
 #include "hashtab.h"
 #include "elf-bfd.h"
+#include "bfdver.h"
+
 #if BFD_SUPPORTS_PLUGINS
 #include "plugin.h"
-#endif /* BFD_SUPPORTS_PLUGINS */
+#endif
 
 #ifndef offsetof
 #define offsetof(TYPE, MEMBER) ((size_t) & (((TYPE*) 0)->MEMBER))
@@ -59,6 +60,7 @@
 /* Local variables.  */
 static struct obstack stat_obstack;
 static struct obstack map_obstack;
+static struct obstack pt_obstack;
 
 #define obstack_chunk_alloc xmalloc
 #define obstack_chunk_free free
@@ -78,8 +80,13 @@ static unsigned int opb_shift = 0;
 /* Forward declarations.  */
 static void exp_init_os (etree_type *);
 static lang_input_statement_type *lookup_name (const char *);
+static bool wont_add_section_p (asection *,
+                               lang_output_section_statement_type *);
 static void insert_undefined (const char *);
 static bool sort_def_symbol (struct bfd_link_hash_entry *, void *);
+static lang_statement_union_type *new_statement (enum statement_enum type,
+                                               size_t size,
+                                               lang_statement_list_type *list);
 static void print_statement (lang_statement_union_type *,
                             lang_output_section_statement_type *);
 static void print_statement_list (lang_statement_union_type *,
@@ -127,6 +134,7 @@ bool lang_has_input_file = false;
 bool had_output_filename = false;
 bool lang_float_flag = false;
 bool delete_output_file_on_failure = false;
+bool enable_linker_version = false;
 struct lang_phdr *lang_phdr_list;
 struct lang_nocrossrefs *nocrossref_list;
 struct asneeded_minfo **asneeded_list_tail;
@@ -169,14 +177,91 @@ stat_alloc (size_t size)
   return obstack_alloc (&stat_obstack, size);
 }
 
+/* Code for handling simple wildcards without going through fnmatch,
+   which can be expensive because of charset translations etc.  */
+
+/* A simple wild is a literal string followed by a single '*',
+   where the literal part is at least 4 characters long.  */
+
+static bool
+is_simple_wild (const char *name)
+{
+  size_t len = strcspn (name, "*?[");
+  return len >= 4 && name[len] == '*' && name[len + 1] == '\0';
+}
+
+static bool
+match_simple_wild (const char *pattern, const char *name)
+{
+  /* The first four characters of the pattern are guaranteed valid
+     non-wildcard characters.  So we can go faster.  */
+  if (pattern[0] != name[0] || pattern[1] != name[1]
+      || pattern[2] != name[2] || pattern[3] != name[3])
+    return false;
+
+  pattern += 4;
+  name += 4;
+  while (*pattern != '*')
+    if (*name++ != *pattern++)
+      return false;
+
+  return true;
+}
+
 static int
 name_match (const char *pattern, const char *name)
 {
+  if (is_simple_wild (pattern))
+    return !match_simple_wild (pattern, name);
   if (wildcardp (pattern))
     return fnmatch (pattern, name, 0);
   return strcmp (pattern, name);
 }
 
+/* Given an analyzed wildcard_spec SPEC, match it against NAME,
+   returns zero on a match, non-zero if there's no match.  */
+
+static int
+spec_match (const struct wildcard_spec *spec, const char *name)
+{
+  size_t nl = spec->namelen;
+  size_t pl = spec->prefixlen;
+  size_t sl = spec->suffixlen;
+  size_t inputlen = strlen (name);
+  int r;
+
+  if (pl)
+    {
+      if (inputlen < pl)
+       return 1;
+
+      r = memcmp (spec->name, name, pl);
+      if (r)
+       return r;
+    }
+
+  if (sl)
+    {
+      if (inputlen < sl)
+       return 1;
+
+      r = memcmp (spec->name + nl - sl, name + inputlen - sl, sl);
+      if (r)
+       return r;
+    }
+
+  if (nl == pl + sl + 1 && spec->name[pl] == '*')
+    return 0;
+
+  if (nl > pl)
+    return fnmatch (spec->name + pl, name + pl, 0);
+
+  if (inputlen >= nl)
+    return name[nl];
+
+  return 0;
+}
+
 static char *
 ldirname (const char *name)
 {
@@ -303,129 +388,103 @@ walk_wild_file_in_exclude_list (struct name_list *exclude_list,
   return false;
 }
 
-/* Try processing a section against a wildcard.  This just calls
-   the callback unless the filename exclusion list is present
-   and excludes the file.  It's hardly ever present so this
-   function is very fast.  */
+/* Add SECTION (from input FILE) to the list of matching sections
+   within PTR (the matching wildcard is SEC).  */
 
 static void
-walk_wild_consider_section (lang_wild_statement_type *ptr,
-                           lang_input_statement_type *file,
-                           asection *s,
-                           struct wildcard_list *sec,
-                           callback_t callback,
-                           void *data)
-{
-  /* Don't process sections from files which were excluded.  */
-  if (walk_wild_file_in_exclude_list (sec->spec.exclude_name_list, file))
-    return;
-
-  (*callback) (ptr, sec, s, file, data);
+add_matching_section (lang_wild_statement_type *ptr,
+                     struct wildcard_list *sec,
+                     asection *section,
+                     lang_input_statement_type *file)
+{
+  lang_input_matcher_type *new_section;
+  /* Add a section reference to the list.  */
+  new_section = new_stat (lang_input_matcher, &ptr->matching_sections);
+  new_section->section = section;
+  new_section->pattern = sec;
+  new_section->input_stmt = file;
 }
 
-/* Lowest common denominator routine that can handle everything correctly,
-   but slowly.  */
+/* Process section S (from input file FILE) in relation to wildcard
+   statement PTR.  We already know that a prefix of the name of S matches
+   some wildcard in PTR's wildcard list.  Here we check if the filename
+   matches as well (if it's specified) and if any of the wildcards in fact
+   does match.  */
 
 static void
-walk_wild_section_general (lang_wild_statement_type *ptr,
-                          lang_input_statement_type *file,
-                          callback_t callback,
-                          void *data)
+walk_wild_section_match (lang_wild_statement_type *ptr,
+                        lang_input_statement_type *file,
+                        asection *s)
 {
-  asection *s;
   struct wildcard_list *sec;
+  const char *file_spec = ptr->filename;
+  char *p;
 
-  for (s = file->the_bfd->sections; s != NULL; s = s->next)
+  /* Check if filenames match.  */
+  if (file_spec == NULL)
+    ;
+  else if ((p = archive_path (file_spec)) != NULL)
     {
-      sec = ptr->section_list;
-      if (sec == NULL)
-       (*callback) (ptr, sec, s, file, data);
-
-      while (sec != NULL)
-       {
-         bool skip = false;
-
-         if (sec->spec.name != NULL)
-           {
-             const char *sname = bfd_section_name (s);
-
-             skip = name_match (sec->spec.name, sname) != 0;
-           }
-
-         if (!skip)
-           walk_wild_consider_section (ptr, file, s, sec, callback, data);
-
-         sec = sec->next;
-       }
+      if (!input_statement_is_archive_path (file_spec, p, file))
+       return;
     }
-}
-
-/* Routines to find a single section given its name.  If there's more
-   than one section with that name, we report that.  */
-
-typedef struct
-{
-  asection *found_section;
-  bool multiple_sections_found;
-} section_iterator_callback_data;
-
-static bool
-section_iterator_callback (bfd *abfd ATTRIBUTE_UNUSED, asection *s, void *data)
-{
-  section_iterator_callback_data *d = (section_iterator_callback_data *) data;
-
-  if (d->found_section != NULL)
+  else if (wildcardp (file_spec))
     {
-      d->multiple_sections_found = true;
-      return true;
+      if (fnmatch (file_spec, file->filename, 0) != 0)
+       return;
+    }
+  else
+    {
+      /* XXX Matching against non-wildcard filename in wild statements
+        was done by going through lookup_name, which uses
+        ->local_sym_name to compare against, not ->filename.  We retain
+        this behaviour even though the above code paths use filename.
+        It would be more logical to use it here as well, in which
+        case the above wildcard() arm could be folded into this by using
+        name_match.  This would also solve the worry of what to do
+        about unset local_sym_name (in which case lookup_name simply adds
+        the input file again).  */
+      const char *filename = file->local_sym_name;
+      lang_input_statement_type *arch_is;
+      if (filename && filename_cmp (filename, file_spec) == 0)
+       ;
+      /* FIXME: see also walk_wild_file_in_exclude_list for why we
+        also check parents BFD (local_sym_)name to match input statements
+        with unadorned archive names.  */
+      else if (file->the_bfd
+              && file->the_bfd->my_archive
+              && (arch_is = bfd_usrdata (file->the_bfd->my_archive))
+              && arch_is->local_sym_name
+              && filename_cmp (arch_is->local_sym_name, file_spec) == 0)
+       ;
+      else
+       return;
     }
 
-  d->found_section = s;
-  return false;
-}
-
-static asection *
-find_section (lang_input_statement_type *file,
-             struct wildcard_list *sec,
-             bool *multiple_sections_found)
-{
-  section_iterator_callback_data cb_data = { NULL, false };
-
-  bfd_get_section_by_name_if (file->the_bfd, sec->spec.name,
-                             section_iterator_callback, &cb_data);
-  *multiple_sections_found = cb_data.multiple_sections_found;
-  return cb_data.found_section;
-}
-
-/* Code for handling simple wildcards without going through fnmatch,
-   which can be expensive because of charset translations etc.  */
-
-/* A simple wild is a literal string followed by a single '*',
-   where the literal part is at least 4 characters long.  */
-
-static bool
-is_simple_wild (const char *name)
-{
-  size_t len = strcspn (name, "*?[");
-  return len >= 4 && name[len] == '*' && name[len + 1] == '\0';
-}
-
-static bool
-match_simple_wild (const char *pattern, const char *name)
-{
-  /* The first four characters of the pattern are guaranteed valid
-     non-wildcard characters.  So we can go faster.  */
-  if (pattern[0] != name[0] || pattern[1] != name[1]
-      || pattern[2] != name[2] || pattern[3] != name[3])
-    return false;
+  /* If filename is excluded we're done.  */
+  if (walk_wild_file_in_exclude_list (ptr->exclude_name_list, file))
+    return;
 
-  pattern += 4;
-  name += 4;
-  while (*pattern != '*')
-    if (*name++ != *pattern++)
-      return false;
+  /* Check section name against each wildcard spec.  If there's no
+     wildcard all sections match.  */
+  sec = ptr->section_list;
+  if (sec == NULL)
+    add_matching_section (ptr, sec, s, file);
+  else
+    {
+      const char *sname = bfd_section_name (s);
+      for (; sec != NULL; sec = sec->next)
+       {
+         if (sec->spec.name != NULL
+             && spec_match (&sec->spec, sname) != 0)
+           continue;
 
-  return true;
+         /* Don't process sections from files which were excluded.  */
+         if (!walk_wild_file_in_exclude_list (sec->spec.exclude_name_list,
+                                              file))
+           add_matching_section (ptr, sec, s, file);
+       }
+    }
 }
 
 /* Return the numerical value of the init_priority attribute from
@@ -526,32 +585,95 @@ compare_section (sort_type sort, asection *asec, asection *bsec)
   return ret;
 }
 
-/* Build a Binary Search Tree to sort sections, unlike insertion sort
-   used in wild_sort(). BST is considerably faster if the number of
-   of sections are large.  */
+/* PE puts the sort key in the input statement.  */
+
+static const char *
+sort_filename (bfd *abfd)
+{
+  lang_input_statement_type *is = bfd_usrdata (abfd);
+  if (is->sort_key)
+    return is->sort_key;
+  return bfd_get_filename (abfd);
+}
+
+/* Handle wildcard sorting.  This returns the place in a binary search tree
+   where this FILE:SECTION should be inserted for wild statement WILD where
+   the spec SEC was the matching one.  The tree is later linearized.  */
 
 static lang_section_bst_type **
-wild_sort_fast (lang_wild_statement_type *wild,
-               struct wildcard_list *sec,
-               lang_input_statement_type *file ATTRIBUTE_UNUSED,
-               asection *section)
+wild_sort (lang_wild_statement_type *wild,
+          struct wildcard_list *sec,
+          lang_input_statement_type *file,
+          asection *section)
 {
   lang_section_bst_type **tree;
 
-  tree = &wild->tree;
   if (!wild->filenames_sorted
-      && (sec == NULL || sec->spec.sorted == none))
+      && (sec == NULL || sec->spec.sorted == none
+         || sec->spec.sorted == by_none))
     {
-      /* Append at the right end of tree.  */
-      while (*tree)
-       tree = &((*tree)->right);
-      return tree;
+      /* We might be called even if _this_ spec doesn't need sorting,
+         in which case we simply append at the right end of tree.  */
+      return wild->rightmost;
     }
 
+  tree = &wild->tree;
   while (*tree)
     {
+      /* Sorting by filename takes precedence over sorting by section
+        name.  */
+
+      if (wild->filenames_sorted)
+       {
+         const char *fn, *ln;
+         bool fa, la;
+         int i;
+         asection *lsec = (*tree)->section;
+
+         /* The PE support for the .idata section as generated by
+            dlltool assumes that files will be sorted by the name of
+            the archive and then the name of the file within the
+            archive.  */
+
+         fa = file->the_bfd->my_archive != NULL;
+         if (fa)
+           fn = sort_filename (file->the_bfd->my_archive);
+         else
+           fn = sort_filename (file->the_bfd);
+
+         la = lsec->owner->my_archive != NULL;
+         if (la)
+           ln = sort_filename (lsec->owner->my_archive);
+         else
+           ln = sort_filename (lsec->owner);
+
+         i = filename_cmp (fn, ln);
+         if (i > 0)
+           { tree = &((*tree)->right); continue; }
+         else if (i < 0)
+           { tree = &((*tree)->left); continue; }
+
+         if (fa || la)
+           {
+             if (fa)
+               fn = sort_filename (file->the_bfd);
+             if (la)
+               ln = sort_filename (lsec->owner);
+
+             i = filename_cmp (fn, ln);
+             if (i > 0)
+               { tree = &((*tree)->right); continue; }
+             else if (i < 0)
+               { tree = &((*tree)->left); continue; }
+           }
+       }
+
+      /* Here either the files are not sorted by name, or we are
+        looking at the sections for this file.  */
+
       /* Find the correct node to append this section.  */
-      if (compare_section (sec->spec.sorted, section, (*tree)->section) < 0)
+      if (sec && sec->spec.sorted != none && sec->spec.sorted != by_none
+         && compare_section (sec->spec.sorted, section, (*tree)->section) < 0)
        tree = &((*tree)->left);
       else
        tree = &((*tree)->right);
@@ -560,10 +682,10 @@ wild_sort_fast (lang_wild_statement_type *wild,
   return tree;
 }
 
-/* Use wild_sort_fast to build a BST to sort sections.  */
+/* Use wild_sort to build a BST to sort sections.  */
 
 static void
-output_section_callback_fast (lang_wild_statement_type *ptr,
+output_section_callback_sort (lang_wild_statement_type *ptr,
                              struct wildcard_list *sec,
                              asection *section,
                              lang_input_statement_type *file,
@@ -578,15 +700,24 @@ output_section_callback_fast (lang_wild_statement_type *ptr,
   if (unique_section_p (section, os))
     return;
 
+  /* Don't add sections to the tree when we already know that
+     lang_add_section won't do anything with it.  */
+  if (wont_add_section_p (section, os))
+    return;
+
   node = (lang_section_bst_type *) xmalloc (sizeof (lang_section_bst_type));
   node->left = 0;
   node->right = 0;
   node->section = section;
   node->pattern = ptr->section_list;
 
-  tree = wild_sort_fast (ptr, sec, file, section);
+  tree = wild_sort (ptr, sec, file, section);
   if (tree != NULL)
-    *tree = node;
+    {
+      *tree = node;
+      if (tree == ptr->rightmost)
+       ptr->rightmost = &node->right;
+    }
 }
 
 /* Convert a sorted sections' BST back to list form.  */
@@ -599,7 +730,8 @@ output_section_callback_tree_to_list (lang_wild_statement_type *ptr,
   if (tree->left)
     output_section_callback_tree_to_list (ptr, tree->left, output);
 
-  lang_add_section (&ptr->children, tree->section, tree->pattern, NULL,
+  lang_add_section (&ptr->children, tree->section, tree->pattern,
+                   ptr->section_flag_list,
                    (lang_output_section_statement_type *) output);
 
   if (tree->right)
@@ -608,384 +740,273 @@ output_section_callback_tree_to_list (lang_wild_statement_type *ptr,
   free (tree);
 }
 
-/* Specialized, optimized routines for handling different kinds of
-   wildcards */
-
-static void
-walk_wild_section_specs1_wild0 (lang_wild_statement_type *ptr,
-                               lang_input_statement_type *file,
-                               callback_t callback,
-                               void *data)
-{
-  /* We can just do a hash lookup for the section with the right name.
-     But if that lookup discovers more than one section with the name
-     (should be rare), we fall back to the general algorithm because
-     we would otherwise have to sort the sections to make sure they
-     get processed in the bfd's order.  */
-  bool multiple_sections_found;
-  struct wildcard_list *sec0 = ptr->handler_data[0];
-  asection *s0 = find_section (file, sec0, &multiple_sections_found);
-
-  if (multiple_sections_found)
-    walk_wild_section_general (ptr, file, callback, data);
-  else if (s0)
-    walk_wild_consider_section (ptr, file, s0, sec0, callback, data);
-}
+\f
+/* Sections are matched against wildcard statements via a prefix tree.
+   The prefix tree holds prefixes of all matching patterns (up to the first
+   wildcard character), and the wild statement from which those patterns
+   came.  When matching a section name against the tree we're walking through
+   the tree character by character.  Each statement we hit is one that
+   potentially matches.  This is checked by actually going through the
+   (glob) matching routines.
+
+   When the section name turns out to actually match we record that section
+   in the wild statements list of matching sections.  */
+
+/* A prefix can be matched by multiple statement, so we need a list of them.  */
+struct wild_stmt_list
+{
+  lang_wild_statement_type *stmt;
+  struct wild_stmt_list *next;
+};
 
-static void
-walk_wild_section_specs1_wild1 (lang_wild_statement_type *ptr,
-                               lang_input_statement_type *file,
-                               callback_t callback,
-                               void *data)
+/* The prefix tree itself.  */
+struct prefixtree
 {
-  asection *s;
-  struct wildcard_list *wildsec0 = ptr->handler_data[0];
+  /* The list of all children (linked via .next).  */
+  struct prefixtree *child;
+  struct prefixtree *next;
+  /* This tree node is responsible for the prefix of parent plus 'c'.  */
+  char c;
+  /* The statements that potentially can match this prefix.  */
+  struct wild_stmt_list *stmt;
+};
 
-  for (s = file->the_bfd->sections; s != NULL; s = s->next)
-    {
-      const char *sname = bfd_section_name (s);
-      bool skip = !match_simple_wild (wildsec0->spec.name, sname);
+/* We always have a root node in the prefix tree.  It corresponds to the
+   empty prefix.  E.g. a glob like "*" would sit in this root.  */
+static struct prefixtree the_root, *ptroot = &the_root;
 
-      if (!skip)
-       walk_wild_consider_section (ptr, file, s, wildsec0, callback, data);
-    }
-}
+/* Given a prefix tree in *TREE, corresponding to prefix P, find or
+   INSERT the tree node corresponding to prefix P+C.  */
 
-static void
-walk_wild_section_specs2_wild1 (lang_wild_statement_type *ptr,
-                               lang_input_statement_type *file,
-                               callback_t callback,
-                               void *data)
+static struct prefixtree *
+get_prefix_tree (struct prefixtree **tree, char c, bool insert)
 {
-  asection *s;
-  struct wildcard_list *sec0 = ptr->handler_data[0];
-  struct wildcard_list *wildsec1 = ptr->handler_data[1];
-  bool multiple_sections_found;
-  asection *s0 = find_section (file, sec0, &multiple_sections_found);
-
-  if (multiple_sections_found)
-    {
-      walk_wild_section_general (ptr, file, callback, data);
-      return;
-    }
+  struct prefixtree *t;
+  for (t = *tree; t; t = t->next)
+    if (t->c == c)
+      return t;
+  if (!insert)
+    return NULL;
+  t = (struct prefixtree *) obstack_alloc (&pt_obstack, sizeof *t);
+  t->child = NULL;
+  t->next = *tree;
+  t->c = c;
+  t->stmt = NULL;
+  *tree = t;
+  return t;
+}
 
-  /* Note that if the section was not found, s0 is NULL and
-     we'll simply never succeed the s == s0 test below.  */
-  for (s = file->the_bfd->sections; s != NULL; s = s->next)
-    {
-      /* Recall that in this code path, a section cannot satisfy more
-        than one spec, so if s == s0 then it cannot match
-        wildspec1.  */
-      if (s == s0)
-       walk_wild_consider_section (ptr, file, s, sec0, callback, data);
-      else
-       {
-         const char *sname = bfd_section_name (s);
-         bool skip = !match_simple_wild (wildsec1->spec.name, sname);
+/* Add STMT to the set of statements that can be matched by the prefix
+   corresponding to prefix tree T.  */
 
-         if (!skip)
-           walk_wild_consider_section (ptr, file, s, wildsec1, callback,
-                                       data);
-       }
-    }
+static void
+pt_add_stmt (struct prefixtree *t, lang_wild_statement_type *stmt)
+{
+  struct wild_stmt_list *sl, **psl;
+  sl = (struct wild_stmt_list *) obstack_alloc (&pt_obstack, sizeof *sl);
+  sl->stmt = stmt;
+  sl->next = NULL;
+  psl = &t->stmt;
+  while (*psl)
+    psl = &(*psl)->next;
+  *psl = sl;
 }
 
+/* Insert STMT into the global prefix tree.  */
+
 static void
-walk_wild_section_specs3_wild2 (lang_wild_statement_type *ptr,
-                               lang_input_statement_type *file,
-                               callback_t callback,
-                               void *data)
+insert_prefix_tree (lang_wild_statement_type *stmt)
 {
-  asection *s;
-  struct wildcard_list *sec0 = ptr->handler_data[0];
-  struct wildcard_list *wildsec1 = ptr->handler_data[1];
-  struct wildcard_list *wildsec2 = ptr->handler_data[2];
-  bool multiple_sections_found;
-  asection *s0 = find_section (file, sec0, &multiple_sections_found);
+  struct wildcard_list *sec;
+  struct prefixtree *t;
 
-  if (multiple_sections_found)
+  if (!stmt->section_list)
     {
-      walk_wild_section_general (ptr, file, callback, data);
+      /* If we have no section_list (no wildcards in the wild STMT),
+        then every section name will match, so add this to the root.  */
+      pt_add_stmt (ptroot, stmt);
       return;
     }
 
-  for (s = file->the_bfd->sections; s != NULL; s = s->next)
+  for (sec = stmt->section_list; sec; sec = sec->next)
     {
-      if (s == s0)
-       walk_wild_consider_section (ptr, file, s, sec0, callback, data);
-      else
+      const char *name = sec->spec.name ? sec->spec.name : "*";
+      char c;
+      t = ptroot;
+      for (; (c = *name); name++)
        {
-         const char *sname = bfd_section_name (s);
-         bool skip = !match_simple_wild (wildsec1->spec.name, sname);
-
-         if (!skip)
-           walk_wild_consider_section (ptr, file, s, wildsec1, callback, data);
-         else
-           {
-             skip = !match_simple_wild (wildsec2->spec.name, sname);
-             if (!skip)
-               walk_wild_consider_section (ptr, file, s, wildsec2, callback,
-                                           data);
-           }
+         if (c == '*' || c == '[' || c == '?')
+           break;
+         t = get_prefix_tree (&t->child, c, true);
        }
+      /* If we hit a glob character, the matching prefix is what we saw
+        until now.  If we hit the end of pattern (hence it's no glob) then
+        we can do better: we only need to record a match when a section name
+        completely matches, not merely a prefix, so record the trailing 0
+        as well.  */
+      if (!c)
+       t = get_prefix_tree (&t->child, 0, true);
+      pt_add_stmt (t, stmt);
     }
 }
 
+/* Dump T indented by INDENT spaces.  */
+
 static void
-walk_wild_section_specs4_wild2 (lang_wild_statement_type *ptr,
-                               lang_input_statement_type *file,
-                               callback_t callback,
-                               void *data)
+debug_prefix_tree_rec (struct prefixtree *t, int indent)
 {
-  asection *s;
-  struct wildcard_list *sec0 = ptr->handler_data[0];
-  struct wildcard_list *sec1 = ptr->handler_data[1];
-  struct wildcard_list *wildsec2 = ptr->handler_data[2];
-  struct wildcard_list *wildsec3 = ptr->handler_data[3];
-  bool multiple_sections_found;
-  asection *s0 = find_section (file, sec0, &multiple_sections_found), *s1;
-
-  if (multiple_sections_found)
-    {
-      walk_wild_section_general (ptr, file, callback, data);
-      return;
-    }
-
-  s1 = find_section (file, sec1, &multiple_sections_found);
-  if (multiple_sections_found)
+  for (; t; t = t->next)
     {
-      walk_wild_section_general (ptr, file, callback, data);
-      return;
-    }
-
-  for (s = file->the_bfd->sections; s != NULL; s = s->next)
-    {
-      if (s == s0)
-       walk_wild_consider_section (ptr, file, s, sec0, callback, data);
-      else
-       if (s == s1)
-         walk_wild_consider_section (ptr, file, s, sec1, callback, data);
-       else
-         {
-           const char *sname = bfd_section_name (s);
-           bool skip = !match_simple_wild (wildsec2->spec.name, sname);
-
-           if (!skip)
-             walk_wild_consider_section (ptr, file, s, wildsec2, callback,
-                                         data);
-           else
-             {
-               skip = !match_simple_wild (wildsec3->spec.name, sname);
-               if (!skip)
-                 walk_wild_consider_section (ptr, file, s, wildsec3,
-                                             callback, data);
-             }
-         }
+      struct wild_stmt_list *sl;
+      printf ("%*s %c", indent, "", t->c);
+      for (sl = t->stmt; sl; sl = sl->next)
+       {
+         struct wildcard_list *curr;
+         printf (" %p ", sl->stmt);
+         for (curr = sl->stmt->section_list; curr; curr = curr->next)
+           printf ("%s ", curr->spec.name ? curr->spec.name : "*");
+       }
+      printf ("\n");
+      debug_prefix_tree_rec (t->child, indent + 2);
     }
 }
 
+/* Dump the global prefix tree.  */
+
 static void
-walk_wild_section (lang_wild_statement_type *ptr,
-                  lang_input_statement_type *file,
-                  callback_t callback,
-                  void *data)
+debug_prefix_tree (void)
 {
-  if (file->flags.just_syms)
-    return;
-
-  (*ptr->walk_wild_section_handler) (ptr, file, callback, data);
+  debug_prefix_tree_rec (ptroot, 2);
 }
 
-/* Returns TRUE when name1 is a wildcard spec that might match
-   something name2 can match.  We're conservative: we return FALSE
-   only if the prefixes of name1 and name2 are different up to the
-   first wildcard character.  */
+/* Like strcspn() but start to look from the end to beginning of
+   S.  Returns the length of the suffix of S consisting entirely
+   of characters not in REJECT.  */
 
-static bool
-wild_spec_can_overlap (const char *name1, const char *name2)
+static size_t
+rstrcspn (const char *s, const char *reject)
 {
-  size_t prefix1_len = strcspn (name1, "?*[");
-  size_t prefix2_len = strcspn (name2, "?*[");
-  size_t min_prefix_len;
-
-  /* Note that if there is no wildcard character, then we treat the
-     terminating 0 as part of the prefix.  Thus ".text" won't match
-     ".text." or ".text.*", for example.  */
-  if (name1[prefix1_len] == '\0')
-    prefix1_len++;
-  if (name2[prefix2_len] == '\0')
-    prefix2_len++;
-
-  min_prefix_len = prefix1_len < prefix2_len ? prefix1_len : prefix2_len;
-
-  return memcmp (name1, name2, min_prefix_len) == 0;
+  size_t len = strlen (s), sufflen = 0;
+  while (len--)
+    {
+      char c = s[len];
+      if (strchr (reject, c) != 0)
+       break;
+      sufflen++;
+    }
+  return sufflen;
 }
 
-/* Select specialized code to handle various kinds of wildcard
-   statements.  */
+/* Analyze the wildcards in wild statement PTR to setup various
+   things for quick matching.  */
 
 static void
 analyze_walk_wild_section_handler (lang_wild_statement_type *ptr)
 {
-  int sec_count = 0;
-  int wild_name_count = 0;
   struct wildcard_list *sec;
-  int signature;
-  int data_counter;
-
-  ptr->walk_wild_section_handler = walk_wild_section_general;
-  ptr->handler_data[0] = NULL;
-  ptr->handler_data[1] = NULL;
-  ptr->handler_data[2] = NULL;
-  ptr->handler_data[3] = NULL;
+
   ptr->tree = NULL;
+  ptr->rightmost = &ptr->tree;
 
-  /* Count how many wildcard_specs there are, and how many of those
-     actually use wildcards in the name.  Also, bail out if any of the
-     wildcard names are NULL. (Can this actually happen?
-     walk_wild_section used to test for it.)  And bail out if any
-     of the wildcards are more complex than a simple string
-     ending in a single '*'.  */
   for (sec = ptr->section_list; sec != NULL; sec = sec->next)
     {
-      ++sec_count;
-      if (sec->spec.name == NULL)
-       return;
-      if (wildcardp (sec->spec.name))
+      if (sec->spec.name)
        {
-         ++wild_name_count;
-         if (!is_simple_wild (sec->spec.name))
-           return;
+         sec->spec.namelen = strlen (sec->spec.name);
+         sec->spec.prefixlen = strcspn (sec->spec.name, "?*[");
+         sec->spec.suffixlen = rstrcspn (sec->spec.name + sec->spec.prefixlen,
+                                         "?*]");
        }
+      else
+       sec->spec.namelen = sec->spec.prefixlen = sec->spec.suffixlen = 0;
     }
 
-  /* The zero-spec case would be easy to optimize but it doesn't
-     happen in practice.  Likewise, more than 4 specs doesn't
-     happen in practice.  */
-  if (sec_count == 0 || sec_count > 4)
+  insert_prefix_tree (ptr);
+}
+
+/* Match all sections from FILE against the global prefix tree,
+   and record them into each wild statement that has a match.  */
+
+static void
+resolve_wild_sections (lang_input_statement_type *file)
+{
+  asection *s;
+
+  if (file->flags.just_syms)
     return;
 
-  /* Check that no two specs can match the same section.  */
-  for (sec = ptr->section_list; sec != NULL; sec = sec->next)
+  for (s = file->the_bfd->sections; s != NULL; s = s->next)
     {
-      struct wildcard_list *sec2;
-      for (sec2 = sec->next; sec2 != NULL; sec2 = sec2->next)
+      const char *sname = bfd_section_name (s);
+      char c = 1;
+      struct prefixtree *t = ptroot;
+      //printf (" YYY consider %s of %s\n", sname, file->the_bfd->filename);
+      do
        {
-         if (wild_spec_can_overlap (sec->spec.name, sec2->spec.name))
-           return;
+         if (t->stmt)
+           {
+             struct wild_stmt_list *sl;
+             for (sl = t->stmt; sl; sl = sl->next)
+               {
+                 walk_wild_section_match (sl->stmt, file, s);
+                 //printf ("   ZZZ maybe place into %p\n", sl->stmt);
+               }
+           }
+         if (!c)
+           break;
+         c = *sname++;
+         t = get_prefix_tree (&t->child, c, false);
        }
+      while (t);
     }
-
-  signature = (sec_count << 8) + wild_name_count;
-  switch (signature)
-    {
-    case 0x0100:
-      ptr->walk_wild_section_handler = walk_wild_section_specs1_wild0;
-      break;
-    case 0x0101:
-      ptr->walk_wild_section_handler = walk_wild_section_specs1_wild1;
-      break;
-    case 0x0201:
-      ptr->walk_wild_section_handler = walk_wild_section_specs2_wild1;
-      break;
-    case 0x0302:
-      ptr->walk_wild_section_handler = walk_wild_section_specs3_wild2;
-      break;
-    case 0x0402:
-      ptr->walk_wild_section_handler = walk_wild_section_specs4_wild2;
-      break;
-    default:
-      return;
-    }
-
-  /* Now fill the data array with pointers to the specs, first the
-     specs with non-wildcard names, then the specs with wildcard
-     names.  It's OK to process the specs in different order from the
-     given order, because we've already determined that no section
-     will match more than one spec.  */
-  data_counter = 0;
-  for (sec = ptr->section_list; sec != NULL; sec = sec->next)
-    if (!wildcardp (sec->spec.name))
-      ptr->handler_data[data_counter++] = sec;
-  for (sec = ptr->section_list; sec != NULL; sec = sec->next)
-    if (wildcardp (sec->spec.name))
-      ptr->handler_data[data_counter++] = sec;
 }
 
-/* Handle a wild statement for a single file F.  */
+/* Match all sections from all input files against the global prefix tree.  */
 
 static void
-walk_wild_file (lang_wild_statement_type *s,
-               lang_input_statement_type *f,
-               callback_t callback,
-               void *data)
+resolve_wilds (void)
 {
-  if (walk_wild_file_in_exclude_list (s->exclude_name_list, f))
-    return;
-
-  if (f->the_bfd == NULL
-      || !bfd_check_format (f->the_bfd, bfd_archive))
-    walk_wild_section (s, f, callback, data);
-  else
+  LANG_FOR_EACH_INPUT_STATEMENT (f)
     {
-      bfd *member;
-
-      /* This is an archive file.  We must map each member of the
-        archive separately.  */
-      member = bfd_openr_next_archived_file (f->the_bfd, NULL);
-      while (member != NULL)
+      //printf("XXX   %s\n", f->filename);
+      if (f->the_bfd == NULL
+         || !bfd_check_format (f->the_bfd, bfd_archive))
+       resolve_wild_sections (f);
+      else
        {
-         /* When lookup_name is called, it will call the add_symbols
-            entry point for the archive.  For each element of the
-            archive which is included, BFD will call ldlang_add_file,
-            which will set the usrdata field of the member to the
-            lang_input_statement.  */
-         if (bfd_usrdata (member) != NULL)
-           walk_wild_section (s, bfd_usrdata (member), callback, data);
+         bfd *member;
 
-         member = bfd_openr_next_archived_file (f->the_bfd, member);
+         /* This is an archive file.  We must map each member of the
+            archive separately.  */
+         member = bfd_openr_next_archived_file (f->the_bfd, NULL);
+         while (member != NULL)
+           {
+             /* When lookup_name is called, it will call the add_symbols
+                entry point for the archive.  For each element of the
+                archive which is included, BFD will call ldlang_add_file,
+                which will set the usrdata field of the member to the
+                lang_input_statement.  */
+             if (bfd_usrdata (member) != NULL)
+               resolve_wild_sections (bfd_usrdata (member));
+
+             member = bfd_openr_next_archived_file (f->the_bfd, member);
+           }
        }
     }
 }
 
+/* For each input section that matches wild statement S calls
+   CALLBACK with DATA.  */
+
 static void
 walk_wild (lang_wild_statement_type *s, callback_t callback, void *data)
 {
-  const char *file_spec = s->filename;
-  char *p;
+  lang_statement_union_type *l;
 
-  if (file_spec == NULL)
+  for (l = s->matching_sections.head; l; l = l->header.next)
     {
-      /* Perform the iteration over all files in the list.  */
-      LANG_FOR_EACH_INPUT_STATEMENT (f)
-       {
-         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)
-       {
-         if (fnmatch (file_spec, f->filename, 0) == 0)
-           walk_wild_file (s, f, callback, data);
-       }
-    }
-  else
-    {
-      lang_input_statement_type *f;
-
-      /* Perform the iteration over a single file.  */
-      f = lookup_name (file_spec);
-      if (f)
-       walk_wild_file (s, f, callback, data);
+      (*callback) (s, l->input_matcher.pattern, l->input_matcher.section,
+                  l->input_matcher.input_stmt, data);
     }
 }
 
@@ -1115,6 +1136,16 @@ new_afile (const char *name,
 
   lang_has_input_file = true;
 
+  /* PR 30632: It is OK for name to be NULL.  For example
+     see the initialization of first_file in lang_init().  */
+  if (name != NULL)
+    {
+      name = ldfile_possibly_remap_input (name);
+      /* But if a name is remapped to NULL, it should be ignored.  */
+      if (name == NULL)
+       return NULL;
+    }
+
   p = new_stat (lang_input_statement, stat_ptr);
   memset (&p->the_bfd, 0,
          sizeof (*p) - offsetof (lang_input_statement_type, the_bfd));
@@ -1125,6 +1156,7 @@ new_afile (const char *name,
   p->flags.add_DT_NEEDED_for_regular = input_flags.add_DT_NEEDED_for_regular;
   p->flags.whole_archive = input_flags.whole_archive;
   p->flags.sysrooted = input_flags.sysrooted;
+  p->sort_key = NULL;
 
   switch (file_type)
     {
@@ -1291,6 +1323,7 @@ void
 lang_init (void)
 {
   obstack_begin (&stat_obstack, 1000);
+  obstack_init (&pt_obstack);
 
   stat_ptr = &statement_list;
 
@@ -1316,6 +1349,7 @@ void
 lang_finish (void)
 {
   output_section_statement_table_free ();
+  ldfile_remap_input_free ();
 }
 
 /*----------------------------------------------------------------------
@@ -1779,7 +1813,7 @@ output_prev_sec_find (lang_output_section_statement_type *os)
       if (lookup->constraint < 0)
        continue;
 
-      if (lookup->bfd_section != NULL && lookup->bfd_section->owner != NULL)
+      if (lookup->bfd_section != NULL)
        return lookup->bfd_section;
     }
 
@@ -1798,13 +1832,13 @@ output_prev_sec_find (lang_output_section_statement_type *os)
    image symbols.  */
 
 static lang_statement_union_type **
-insert_os_after (lang_output_section_statement_type *after)
+insert_os_after (lang_statement_union_type *after)
 {
   lang_statement_union_type **where;
   lang_statement_union_type **assign = NULL;
   bool ignore_first;
 
-  ignore_first = after == (void *) lang_os_list.head;
+  ignore_first = after == lang_os_list.head;
 
   for (where = &after->header.next;
        *where != NULL;
@@ -1857,6 +1891,8 @@ insert_os_after (lang_output_section_statement_type *after)
        case lang_group_statement_enum:
        case lang_insert_statement_enum:
          continue;
+       case lang_input_matcher_enum:
+         FAIL ();
        }
       break;
     }
@@ -1939,7 +1975,9 @@ lang_insert_orphan (asection *s,
          if (bfd_section == NULL)
            bfd_section = output_prev_sec_find (after);
 
-         if (bfd_section != NULL && bfd_section != snew)
+         if (bfd_section != NULL
+             && bfd_section->owner != NULL
+             && bfd_section != snew)
            place->section = &bfd_section->next;
        }
 
@@ -2162,8 +2200,9 @@ lang_insert_orphan (asection *s,
          /* Place OS after AFTER if AFTER_NOTE is TRUE.  */
          if (place_after)
            {
-             lang_statement_union_type **where = insert_os_after (after);
+             lang_statement_union_type **where;
 
+             where = insert_os_after ((lang_statement_union_type *) after);
              *add.tail = *where;
              *where = add.head;
 
@@ -2220,7 +2259,7 @@ lang_print_asneeded (void)
 
   for (m = asneeded_list_head; m != NULL; m = m->next)
     {
-      size_t len;
+      int len;
 
       minfo ("%s", m->soname);
       len = strlen (m->soname);
@@ -2230,11 +2269,7 @@ lang_print_asneeded (void)
          print_nl ();
          len = 0;
        }
-      while (len < 30)
-       {
-         print_space ();
-         ++len;
-       }
+      print_spaces (30 - len);
 
       if (m->ref != NULL)
        minfo ("%pB ", m->ref);
@@ -2267,6 +2302,8 @@ lang_map (void)
   lang_memory_region_type *m;
   bool dis_header_printed = false;
 
+  ldfile_print_input_remaps ();
+
   LANG_FOR_EACH_INPUT_STATEMENT (file)
     {
       asection *s;
@@ -2283,13 +2320,15 @@ lang_map (void)
            {
              if (! dis_header_printed)
                {
-                 fprintf (config.map_file, _("\nDiscarded input sections\n\n"));
+                 minfo (_("\nDiscarded input sections\n\n"));
                  dis_header_printed = true;
                }
 
              print_input_section (s, true);
            }
     }
+  if (config.print_map_discarded && ! dis_header_printed)
+    minfo (_("\nThere are no discarded input sections\n"));
 
   minfo (_("\nMemory Configuration\n\n"));
   fprintf (config.map_file, "%-16s %-18s %-18s %s\n",
@@ -2297,31 +2336,27 @@ lang_map (void)
 
   for (m = lang_memory_region_list; m != NULL; m = m->next)
     {
-      fprintf (config.map_file, "%-16s ", m->name_list.name);
+      fprintf (config.map_file, "%-16s", m->name_list.name);
 
-      minfo ("0x%V 0x%V", m->origin, m->length);
-      if (m->flags || m->not_flags)
-       {
-#ifndef BFD64
-         minfo ("        ");
-#endif
-         if (m->flags)
-           {
-             print_space ();
-             lang_map_flags (m->flags);
-           }
+      char buf[32];
+      bfd_sprintf_vma (link_info.output_bfd, buf, m->origin);
+      fprintf (config.map_file, " 0x%-16s", buf);
+      bfd_sprintf_vma (link_info.output_bfd, buf, m->length);
+      fprintf (config.map_file,
+              " 0x%*s", m->flags || m->not_flags ? -17 : 0, buf);
+      if (m->flags)
+       lang_map_flags (m->flags);
 
-         if (m->not_flags)
-           {
-             minfo (" !");
-             lang_map_flags (m->not_flags);
-           }
+      if (m->not_flags)
+       {
+         minfo ("!");
+         lang_map_flags (m->not_flags);
        }
 
       print_nl ();
     }
 
-  fprintf (config.map_file, _("\nLinker script and memory map\n\n"));
+  minfo (_("\nLinker script and memory map\n\n"));
 
   if (!link_info.reduce_memory_overheads)
     {
@@ -2404,7 +2439,7 @@ init_os (lang_output_section_statement_type *s, flagword flags)
 
   /* If supplied an alignment, set it.  */
   if (s->section_alignment != NULL)
-    s->bfd_section->alignment_power = exp_get_power (s->section_alignment,
+    s->bfd_section->alignment_power = exp_get_power (s->section_alignment, s,
                                                     "section alignment");
 }
 
@@ -2509,30 +2544,27 @@ lang_discard_section_p (asection *section)
       && (flags & SEC_DEBUGGING) != 0)
     discard = true;
 
+  /* Discard non-alloc sections if we are stripping section headers.  */
+  else if (config.no_section_header && (flags & SEC_ALLOC) == 0)
+    discard = true;
+
   return discard;
 }
 
-/* The wild routines.
-
-   These expand statements like *(.text) and foo.o to a list of
-   explicit actions, like foo.o(.text), bar.o(.text) and
-   foo.o(.text, .data).  */
+/* Return TRUE if SECTION is never going to be added to output statement
+   OUTPUT.  lang_add_section() definitely won't do anything with SECTION
+   if this returns TRUE.  It may do something (or not) if this returns FALSE.
 
-/* Add SECTION to the output section OUTPUT.  Do this by creating a
-   lang_input_section statement which is placed at PTR.  */
+   Can be used as early-out to filter matches.  This may set
+   output_section of SECTION, if it was unset, to the abs section in case
+   we discover SECTION to be always discarded.  This may also give
+   warning messages.  */
 
-void
-lang_add_section (lang_statement_list_type *ptr,
-                 asection *section,
-                 struct wildcard_list *pattern,
-                 struct flag_info *sflag_info,
-                 lang_output_section_statement_type *output)
+static bool
+wont_add_section_p (asection *section,
+                   lang_output_section_statement_type *output)
 {
-  flagword flags = section->flags;
-
   bool discard;
-  lang_input_section_type *new_section;
-  bfd *abfd = link_info.output_bfd;
 
   /* Is this section one we know should be discarded?  */
   discard = lang_discard_section_p (section);
@@ -2546,53 +2578,83 @@ lang_add_section (lang_statement_list_type *ptr,
     {
       if (section->output_section == NULL)
        {
-         /* This prevents future calls from assigning this section.  */
+         /* This prevents future calls from assigning this section or
+            warning about it again.  */
          section->output_section = bfd_abs_section_ptr;
        }
+      else if (bfd_is_abs_section (section->output_section))
+       ;
       else if (link_info.non_contiguous_regions_warnings)
        einfo (_("%P:%pS: warning: --enable-non-contiguous-regions makes "
-                "section `%pA' from '%pB' match /DISCARD/ clause.\n"),
+                "section `%pA' from `%pB' match /DISCARD/ clause.\n"),
               NULL, section, section->owner);
 
-      return;
-    }
-
-  if (sflag_info)
-    {
-      bool keep;
-
-      keep = bfd_lookup_section_flags (&link_info, sflag_info, section);
-      if (!keep)
-       return;
+      return true;
     }
 
   if (section->output_section != NULL)
     {
       if (!link_info.non_contiguous_regions)
-       return;
+       return true;
 
       /* SECTION has already been handled in a special way
         (eg. LINK_ONCE): skip it.  */
       if (bfd_is_abs_section (section->output_section))
-       return;
+       return true;
 
       /* Already assigned to the same output section, do not process
         it again, to avoid creating loops between duplicate sections
         later.  */
       if (section->output_section == output->bfd_section)
-       return;
+       return true;
+
+      if (link_info.non_contiguous_regions_warnings && output->bfd_section)
+       einfo (_("%P:%pS: warning: --enable-non-contiguous-regions may "
+                "change behaviour for section `%pA' from `%pB' (assigned to "
+                "%pA, but additional match: %pA)\n"),
+              NULL, section, section->owner, section->output_section,
+              output->bfd_section);
+
+      /* SECTION has already been assigned to an output section, but
+        the user allows it to be mapped to another one in case it
+        overflows. We'll later update the actual output section in
+        size_input_section as appropriate.  */
+    }
+
+  return false;
+}
+
+/* The wild routines.
+
+   These expand statements like *(.text) and foo.o to a list of
+   explicit actions, like foo.o(.text), bar.o(.text) and
+   foo.o(.text, .data).  */
+
+/* Add SECTION to the output section OUTPUT.  Do this by creating a
+   lang_input_section statement which is placed at PTR.  */
+
+void
+lang_add_section (lang_statement_list_type *ptr,
+                 asection *section,
+                 struct wildcard_list *pattern,
+                 struct flag_info *sflag_info,
+                 lang_output_section_statement_type *output)
+{
+  flagword flags = section->flags;
+
+  lang_input_section_type *new_section;
+  bfd *abfd = link_info.output_bfd;
 
-      if (link_info.non_contiguous_regions_warnings && output->bfd_section)
-       einfo (_("%P:%pS: warning: --enable-non-contiguous-regions may "
-                "change behaviour for section `%pA' from '%pB' (assigned to "
-                "%pA, but additional match: %pA)\n"),
-              NULL, section, section->owner, section->output_section,
-              output->bfd_section);
+  if (wont_add_section_p (section, output))
+    return;
 
-      /* SECTION has already been assigned to an output section, but
-        the user allows it to be mapped to another one in case it
-        overflows. We'll later update the actual output section in
-        size_input_section as appropriate.  */
+  if (sflag_info)
+    {
+      bool keep;
+
+      keep = bfd_lookup_section_flags (&link_info, sflag_info, section);
+      if (!keep)
+       return;
     }
 
   /* We don't copy the SEC_NEVER_LOAD flag from an input section
@@ -2723,113 +2785,17 @@ lang_add_section (lang_statement_list_type *ptr,
   new_section->pattern = pattern;
 }
 
-/* Handle wildcard sorting.  This returns the lang_input_section which
-   should follow the one we are going to create for SECTION and FILE,
-   based on the sorting requirements of WILD.  It returns NULL if the
-   new section should just go at the end of the current list.  */
-
-static lang_statement_union_type *
-wild_sort (lang_wild_statement_type *wild,
-          struct wildcard_list *sec,
-          lang_input_statement_type *file,
-          asection *section)
-{
-  lang_statement_union_type *l;
-
-  if (!wild->filenames_sorted
-      && (sec == NULL || sec->spec.sorted == none))
-    return NULL;
-
-  for (l = wild->children.head; l != NULL; l = l->header.next)
-    {
-      lang_input_section_type *ls;
-
-      if (l->header.type != lang_input_section_enum)
-       continue;
-      ls = &l->input_section;
-
-      /* Sorting by filename takes precedence over sorting by section
-        name.  */
-
-      if (wild->filenames_sorted)
-       {
-         const char *fn, *ln;
-         bool fa, la;
-         int i;
-
-         /* The PE support for the .idata section as generated by
-            dlltool assumes that files will be sorted by the name of
-            the archive and then the name of the file within the
-            archive.  */
-
-         if (file->the_bfd != NULL
-             && file->the_bfd->my_archive != NULL)
-           {
-             fn = bfd_get_filename (file->the_bfd->my_archive);
-             fa = true;
-           }
-         else
-           {
-             fn = file->filename;
-             fa = false;
-           }
-
-         if (ls->section->owner->my_archive != NULL)
-           {
-             ln = bfd_get_filename (ls->section->owner->my_archive);
-             la = true;
-           }
-         else
-           {
-             ln = bfd_get_filename (ls->section->owner);
-             la = false;
-           }
-
-         i = filename_cmp (fn, ln);
-         if (i > 0)
-           continue;
-         else if (i < 0)
-           break;
-
-         if (fa || la)
-           {
-             if (fa)
-               fn = file->filename;
-             if (la)
-               ln = bfd_get_filename (ls->section->owner);
-
-             i = filename_cmp (fn, ln);
-             if (i > 0)
-               continue;
-             else if (i < 0)
-               break;
-           }
-       }
-
-      /* Here either the files are not sorted by name, or we are
-        looking at the sections for this file.  */
-
-      if (sec != NULL
-         && sec->spec.sorted != none
-         && sec->spec.sorted != by_none)
-       if (compare_section (sec->spec.sorted, section, ls->section) < 0)
-         break;
-    }
-
-  return l;
-}
-
 /* Expand a wild statement for a particular FILE.  SECTION may be
-   NULL, in which case it is a wild card.  */
+   NULL, in which case it is a wild card.  This assumes that the
+   wild statement doesn't need any sorting (of filenames or sections).  */
 
 static void
-output_section_callback (lang_wild_statement_type *ptr,
-                        struct wildcard_list *sec,
-                        asection *section,
-                        lang_input_statement_type *file,
-                        void *output)
+output_section_callback_nosort (lang_wild_statement_type *ptr,
+                       struct wildcard_list *sec ATTRIBUTE_UNUSED,
+                       asection *section,
+                       lang_input_statement_type *file ATTRIBUTE_UNUSED,
+                       void *output)
 {
-  lang_statement_union_type *before;
   lang_output_section_statement_type *os;
 
   os = (lang_output_section_statement_type *) output;
@@ -2838,40 +2804,8 @@ output_section_callback (lang_wild_statement_type *ptr,
   if (unique_section_p (section, os))
     return;
 
-  before = wild_sort (ptr, sec, file, section);
-
-  /* Here BEFORE points to the lang_input_section which
-     should follow the one we are about to add.  If BEFORE
-     is NULL, then the section should just go at the end
-     of the current list.  */
-
-  if (before == NULL)
-    lang_add_section (&ptr->children, section, ptr->section_list,
-                     ptr->section_flag_list, os);
-  else
-    {
-      lang_statement_list_type list;
-      lang_statement_union_type **pp;
-
-      lang_list_init (&list);
-      lang_add_section (&list, section, ptr->section_list,
-                       ptr->section_flag_list, os);
-
-      /* If we are discarding the section, LIST.HEAD will
-        be NULL.  */
-      if (list.head != NULL)
-       {
-         ASSERT (list.head->header.next == NULL);
-
-         for (pp = &ptr->children.head;
-              *pp != before;
-              pp = &(*pp)->header.next)
-           ASSERT (*pp != NULL);
-
-         list.head->header.next = *pp;
-         *pp = list.head;
-       }
-    }
+  lang_add_section (&ptr->children, section, ptr->section_list,
+                   ptr->section_flag_list, os);
 }
 
 /* Check if all sections in a wild statement for a particular FILE
@@ -3182,23 +3116,22 @@ wild (lang_wild_statement_type *s,
 {
   struct wildcard_list *sec;
 
-  if (s->handler_data[0]
-      && s->handler_data[0]->spec.sorted == by_name
-      && !s->filenames_sorted)
+  if (s->filenames_sorted || s->any_specs_sorted)
     {
       lang_section_bst_type *tree;
 
-      walk_wild (s, output_section_callback_fast, output);
+      walk_wild (s, output_section_callback_sort, output);
 
       tree = s->tree;
       if (tree)
        {
          output_section_callback_tree_to_list (s, tree, output);
          s->tree = NULL;
+         s->rightmost = &s->tree;
        }
     }
   else
-    walk_wild (s, output_section_callback, output);
+    walk_wild (s, output_section_callback_nosort, output);
 
   if (default_common_section == NULL)
     for (sec = s->section_list; sec != NULL; sec = sec->next)
@@ -3511,6 +3444,10 @@ ldlang_open_output (lang_statement_union_type *statement)
        link_info.output_bfd->flags |= BFD_TRADITIONAL_FORMAT;
       else
        link_info.output_bfd->flags &= ~BFD_TRADITIONAL_FORMAT;
+      if (config.no_section_header)
+       link_info.output_bfd->flags |= BFD_NO_SECTION_HEADER;
+      else
+       link_info.output_bfd->flags &= ~BFD_NO_SECTION_HEADER;
       break;
 
     case lang_target_statement_enum:
@@ -3557,17 +3494,20 @@ static struct bfd_link_hash_entry *plugin_undefs = NULL;
 #endif
 
 static void
-open_input_bfds (lang_statement_union_type *s, enum open_bfd_mode mode)
+open_input_bfds (lang_statement_union_type *s,
+                lang_output_section_statement_type *os,
+                enum open_bfd_mode mode)
 {
   for (; s != NULL; s = s->header.next)
     {
       switch (s->header.type)
        {
        case lang_constructors_statement_enum:
-         open_input_bfds (constructor_list.head, mode);
+         open_input_bfds (constructor_list.head, os, mode);
          break;
        case lang_output_section_statement_enum:
-         open_input_bfds (s->output_section_statement.children.head, mode);
+         os = &s->output_section_statement;
+         open_input_bfds (os->children.head, os, mode);
          break;
        case lang_wild_statement_enum:
          /* Maybe we should load the file's symbols.  */
@@ -3576,7 +3516,7 @@ open_input_bfds (lang_statement_union_type *s, enum open_bfd_mode mode)
              && !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, mode);
+         open_input_bfds (s->wild_statement.children.head, os, mode);
          break;
        case lang_group_statement_enum:
          {
@@ -3595,7 +3535,7 @@ open_input_bfds (lang_statement_union_type *s, enum open_bfd_mode mode)
                plugin_insert_save = plugin_insert;
 #endif
                undefs = link_info.hash->undefs_tail;
-               open_input_bfds (s->group_statement.children.head,
+               open_input_bfds (s->group_statement.children.head, os,
                                 mode | OPEN_BFD_FORCE);
              }
            while (undefs != link_info.hash->undefs_tail
@@ -3682,7 +3622,7 @@ open_input_bfds (lang_statement_union_type *s, enum open_bfd_mode mode)
          break;
        case lang_assignment_statement_enum:
          if (s->assignment_statement.exp->type.node_class != etree_assert)
-           exp_fold_tree_no_dot (s->assignment_statement.exp);
+           exp_fold_tree_no_dot (s->assignment_statement.exp, os);
          break;
        default:
          break;
@@ -4156,22 +4096,25 @@ update_wild_statements (lang_statement_union_type *s)
                /* Don't sort .init/.fini sections.  */
                if (strcmp (sec->spec.name, ".init") != 0
                    && strcmp (sec->spec.name, ".fini") != 0)
-                 switch (sec->spec.sorted)
-                   {
-                   case none:
-                     sec->spec.sorted = sort_section;
-                     break;
-                   case by_name:
-                     if (sort_section == by_alignment)
-                       sec->spec.sorted = by_name_alignment;
-                     break;
-                   case by_alignment:
-                     if (sort_section == by_name)
-                       sec->spec.sorted = by_alignment_name;
-                     break;
-                   default:
-                     break;
-                   }
+                 {
+                   switch (sec->spec.sorted)
+                     {
+                       case none:
+                           sec->spec.sorted = sort_section;
+                           break;
+                       case by_name:
+                           if (sort_section == by_alignment)
+                             sec->spec.sorted = by_name_alignment;
+                           break;
+                       case by_alignment:
+                           if (sort_section == by_name)
+                             sec->spec.sorted = by_alignment_name;
+                           break;
+                       default:
+                           break;
+                     }
+                   s->wild_statement.any_specs_sorted = true;
+                 }
              break;
 
            case lang_constructors_statement_enum:
@@ -4287,7 +4230,7 @@ map_input_to_output_sections
                }
             else
               {
-                exp_fold_tree_no_dot (os->sectype_value);
+                exp_fold_tree_no_dot (os->sectype_value, os);
                 if (expld.result.valid_p)
                   type = expld.result.value;
                 else
@@ -4356,6 +4299,8 @@ map_input_to_output_sections
          break;
        case lang_insert_statement_enum:
          break;
+       case lang_input_matcher_enum:
+         FAIL ();
        }
     }
 }
@@ -4505,21 +4450,55 @@ process_insert_statements (lang_statement_union_type **start)
                      else
                        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;
+                     if (sec->owner == NULL)
+                       /* SEC is the absolute section, from the
+                          first dummy output section statement.  Add
+                          back the sections we trimmed off to the
+                          start of the bfd sections.  */
+                       sec = NULL;
+                     if (sec != NULL)
+                       last_sec->next = sec->next;
+                     else
+                       last_sec->next = link_info.output_bfd->sections;
+                     if (last_sec->next != NULL)
+                       last_sec->next->prev = last_sec;
                      else
                        link_info.output_bfd->section_last = last_sec;
                      first_sec->prev = sec;
-                     sec->next = first_sec;
+                     if (first_sec->prev != NULL)
+                       first_sec->prev->next = first_sec;
+                     else
+                       link_info.output_bfd->sections = first_sec;
                    }
                }
-
-             first_os = NULL;
-             last_os = NULL;
            }
 
-         ptr = insert_os_after (where);
+         lang_statement_union_type *after = (void *) where;
+         if (where == &lang_os_list.head->output_section_statement
+             && where->next == first_os)
+           {
+             /* PR30155.  Handle a corner case where the statement
+                list is something like the following:
+                . LOAD t.o
+                . .data           0x0000000000000000        0x0
+                .                 [0x0000000000000000]              b = .
+                .  *(.data)
+                .  .data          0x0000000000000000        0x0 t.o
+                .                 0x0000000000000000        0x4 LONG 0x0
+                . INSERT BEFORE .text.start
+                .                 [0x0000000000000004]              a = .
+                . .text.start     0x0000000000000000        0x0
+                .                 [0x0000000000000000]              c = .
+                . OUTPUT(a.out elf64-x86-64)
+                Here we do not want to allow insert_os_after to
+                choose a point inside the list we are moving.
+                That would lose the list.  Instead, let
+                insert_os_after work from the INSERT, which in this
+                particular example will result in inserting after
+                the assignment "a = .".  */
+             after = *s;
+           }
+         ptr = insert_os_after (after);
          /* Snip everything from the start of the list, up to and
             including the insert statement we are currently processing.  */
          first = *start;
@@ -4530,6 +4509,8 @@ process_insert_statements (lang_statement_union_type **start)
            statement_list.tail = s;
          *ptr = first;
          s = start;
+         first_os = NULL;
+         last_os = NULL;
          continue;
        }
       s = &(*s)->header.next;
@@ -4667,11 +4648,7 @@ print_output_section_statement
              print_nl ();
              len = 0;
            }
-         while (len < SECTION_NAME_MAP_LENGTH)
-           {
-             print_space ();
-             ++len;
-           }
+         print_spaces (SECTION_NAME_MAP_LENGTH - len);
 
          minfo ("0x%V %W", section->vma, TO_ADDR (section->size));
 
@@ -4680,6 +4657,7 @@ print_output_section_statement
 
          if (output_section_statement->update_dot_tree != NULL)
            exp_fold_tree (output_section_statement->update_dot_tree,
+                          output_section_statement,
                           bfd_abs_section_ptr, &print_dot);
        }
 
@@ -4694,13 +4672,11 @@ static void
 print_assignment (lang_assignment_statement_type *assignment,
                  lang_output_section_statement_type *output_section)
 {
-  unsigned int i;
   bool is_dot;
   etree_type *tree;
   asection *osec;
 
-  for (i = 0; i < SECTION_NAME_MAP_LENGTH; i++)
-    print_space ();
+  print_spaces (SECTION_NAME_MAP_LENGTH);
 
   if (assignment->exp->type.node_class == etree_assert)
     {
@@ -4720,10 +4696,12 @@ print_assignment (lang_assignment_statement_type *assignment,
     osec = bfd_abs_section_ptr;
 
   if (assignment->exp->type.node_class != etree_provide)
-    exp_fold_tree (tree, osec, &print_dot);
+    exp_fold_tree (tree, output_section, osec, &print_dot);
   else
     expld.result.valid_p = false;
 
+  char buf[32];
+  const char *str = buf;
   if (expld.result.valid_p)
     {
       bfd_vma value;
@@ -4737,7 +4715,9 @@ print_assignment (lang_assignment_statement_type *assignment,
          if (expld.result.section != NULL)
            value += expld.result.section->vma;
 
-         minfo ("0x%V", value);
+         buf[0] = '0';
+         buf[1] = 'x';
+         bfd_sprintf_vma (link_info.output_bfd, buf + 2, value);
          if (is_dot)
            print_dot = value;
        }
@@ -4755,25 +4735,26 @@ print_assignment (lang_assignment_statement_type *assignment,
              value += h->u.def.section->output_section->vma;
              value += h->u.def.section->output_offset;
 
-             minfo ("[0x%V]", value);
+             buf[0] = '[';
+             buf[1] = '0';
+             buf[2] = 'x';
+             bfd_sprintf_vma (link_info.output_bfd, buf + 3, value);
+             strcat (buf, "]");
            }
          else
-           minfo ("[unresolved]");
+           str = "[unresolved]";
        }
     }
   else
     {
       if (assignment->exp->type.node_class == etree_provide)
-       minfo ("[!provide]");
+       str = "[!provide]";
       else
-       minfo ("*undef*   ");
-#ifdef BFD64
-      minfo ("        ");
-#endif
+       str = "*undef*";
     }
   expld.assign_name = NULL;
 
-  minfo ("                ");
+  fprintf (config.map_file, "%-34s", str);
   exp_print_tree (assignment->exp);
   print_nl ();
 }
@@ -4797,10 +4778,7 @@ print_one_symbol (struct bfd_link_hash_entry *hash_entry, void *ptr)
        || hash_entry->type == bfd_link_hash_defweak)
       && sec == hash_entry->u.def.section)
     {
-      int i;
-
-      for (i = 0; i < SECTION_NAME_MAP_LENGTH; i++)
-       print_space ();
+      print_spaces (SECTION_NAME_MAP_LENGTH);
       minfo ("0x%V   ",
             (hash_entry->u.def.value
              + hash_entry->u.def.section->output_offset
@@ -4857,6 +4835,50 @@ print_all_symbols (asection *sec)
   obstack_free (&map_obstack, entries);
 }
 
+/* Returns TRUE if SYM is a symbol suitable for printing
+   in a linker map as a local symbol.  */
+
+static bool
+ld_is_local_symbol (asymbol * sym)
+{
+  const char * name = bfd_asymbol_name (sym);
+
+  if (name == NULL || *name == 0)
+    return false;
+
+  if (strcmp (name, "(null)") == 0)
+    return false;
+
+  /* Skip .Lxxx and such like.  */
+  if (bfd_is_local_label (link_info.output_bfd, sym))
+    return false;
+
+  /* FIXME: This is intended to skip ARM mapping symbols,
+     which for some reason are not excluded by bfd_is_local_label,
+     but maybe it is wrong for other architectures.
+     It would be better to fix bfd_is_local_label.  */  
+  if (*name == '$')
+    return false;
+
+  /* Some local symbols, eg _GLOBAL_OFFSET_TABLE_, are present
+     in the hash table, so do not print duplicates here.  */
+  struct bfd_link_hash_entry * h;
+  h = bfd_link_hash_lookup (link_info.hash, name, false /* create */, 
+                           false /* copy */, true /* follow */);
+  if (h == NULL)
+    return true;
+  
+  /* Symbols from the plugin owned BFD will not get their own
+     iteration of this function, but can be on the link_info
+     list.  So include them here.  */
+  if (h->u.def.section->owner != NULL
+      && ((bfd_get_file_flags (h->u.def.section->owner) & (BFD_LINKER_CREATED | BFD_PLUGIN))
+         == (BFD_LINKER_CREATED | BFD_PLUGIN)))
+    return true;
+
+  return false;
+}
+
 /* Print information about an input section to the map file.  */
 
 static void
@@ -4868,8 +4890,7 @@ print_input_section (asection *i, bool is_discarded)
 
   init_opb (i);
 
-  print_space ();
-  minfo ("%s", i->name);
+  minfo (" %s", i->name);
 
   len = 1 + strlen (i->name);
   if (len >= SECTION_NAME_MAP_LENGTH - 1)
@@ -4877,11 +4898,7 @@ print_input_section (asection *i, bool is_discarded)
       print_nl ();
       len = 0;
     }
-  while (len < SECTION_NAME_MAP_LENGTH)
-    {
-      print_space ();
-      ++len;
-    }
+  print_spaces (SECTION_NAME_MAP_LENGTH - len);
 
   if (i->output_section != NULL
       && i->output_section->owner == link_info.output_bfd)
@@ -4893,22 +4910,14 @@ print_input_section (asection *i, bool is_discarded)
        size = 0;
     }
 
-  minfo ("0x%V %W %pB\n", addr, TO_ADDR (size), i->owner);
+  char buf[32];
+  bfd_sprintf_vma (link_info.output_bfd, buf, addr);
+  minfo ("0x%s %W %pB\n", buf, TO_ADDR (size), i->owner);
 
   if (size != i->rawsize && i->rawsize != 0)
     {
-      len = SECTION_NAME_MAP_LENGTH + 3;
-#ifdef BFD64
-      len += 16;
-#else
-      len += 8;
-#endif
-      while (len > 0)
-       {
-         print_space ();
-         --len;
-       }
-
+      len = SECTION_NAME_MAP_LENGTH + 3 + strlen (buf);
+      print_spaces (len);
       minfo (_("%W (size before relaxing)\n"), TO_ADDR (i->rawsize));
     }
 
@@ -4925,6 +4934,44 @@ print_input_section (asection *i, bool is_discarded)
         later overlay is shorter than an earier one.  */
       if (addr + TO_ADDR (size) > print_dot)
        print_dot = addr + TO_ADDR (size);
+
+      if (config.print_map_locals)
+       {
+         long  storage_needed;
+
+         /* FIXME: It would be better to cache this table, rather
+            than recreating it for each output section.  */
+         /* FIXME: This call is not working for non-ELF based targets.
+            Find out why.  */
+         storage_needed = bfd_get_symtab_upper_bound (link_info.output_bfd);
+         if (storage_needed > 0)
+           {
+             asymbol **  symbol_table;
+             long        number_of_symbols;
+             long        j;
+
+             symbol_table = xmalloc (storage_needed);
+             number_of_symbols = bfd_canonicalize_symtab (link_info.output_bfd, symbol_table);
+
+             for (j = 0; j < number_of_symbols; j++)
+               {
+                 asymbol *     sym = symbol_table[j];
+                 bfd_vma       sym_addr = sym->value + i->output_section->vma;
+                 
+                 if (sym->section == i->output_section
+                     && (sym->flags & BSF_LOCAL) != 0
+                     && sym_addr >= addr
+                     && sym_addr < print_dot
+                     && ld_is_local_symbol (sym))
+                   {
+                     print_spaces (SECTION_NAME_MAP_LENGTH);
+                     minfo ("0x%V        (local) %s\n", sym_addr, bfd_asymbol_name (sym));
+                   }
+               }
+
+             free (symbol_table);
+           }
+       }
     }
 }
 
@@ -4942,14 +4989,12 @@ print_fill_statement (lang_fill_statement_type *fill)
 static void
 print_data_statement (lang_data_statement_type *data)
 {
-  int i;
   bfd_vma addr;
   bfd_size_type size;
   const char *name;
 
   init_opb (data->output_section);
-  for (i = 0; i < SECTION_NAME_MAP_LENGTH; i++)
-    print_space ();
+  print_spaces (SECTION_NAME_MAP_LENGTH);
 
   addr = data->output_offset;
   if (data->output_section != NULL)
@@ -5012,13 +5057,11 @@ print_address_statement (lang_address_statement_type *address)
 static void
 print_reloc_statement (lang_reloc_statement_type *reloc)
 {
-  int i;
   bfd_vma addr;
   bfd_size_type size;
 
   init_opb (reloc->output_section);
-  for (i = 0; i < SECTION_NAME_MAP_LENGTH; i++)
-    print_space ();
+  print_spaces (SECTION_NAME_MAP_LENGTH);
 
   addr = reloc->output_offset;
   if (reloc->output_section != NULL)
@@ -5050,11 +5093,7 @@ print_padding_statement (lang_padding_statement_type *s)
   minfo (" *fill*");
 
   len = sizeof " *fill*" - 1;
-  while (len < SECTION_NAME_MAP_LENGTH)
-    {
-      print_space ();
-      ++len;
-    }
+  print_spaces (SECTION_NAME_MAP_LENGTH - len);
 
   addr = s->output_offset;
   if (s->output_section != NULL)
@@ -5388,6 +5427,7 @@ size_input_section
       if (output_section_statement->subsection_alignment != NULL)
        i->alignment_power
          = exp_get_power (output_section_statement->subsection_alignment,
+                          output_section_statement,
                           "subsection alignment");
 
       if (o->alignment_power < i->alignment_power)
@@ -5413,15 +5453,15 @@ size_input_section
              if (dot + TO_ADDR (i->size) > end)
                {
                  if (i->flags & SEC_LINKER_CREATED)
-                   einfo (_("%F%P: Output section '%s' not large enough for the "
-                            "linker-created stubs section '%s'.\n"),
-                          i->output_section->name, i->name);
+                   einfo (_("%F%P: Output section `%pA' not large enough for "
+                            "the linker-created stubs section `%pA'.\n"),
+                          i->output_section, i);
 
                  if (i->rawsize && i->rawsize != i->size)
                    einfo (_("%F%P: Relaxation not supported with "
-                            "--enable-non-contiguous-regions (section '%s' "
-                            "would overflow '%s' after it changed size).\n"),
-                          i->name, i->output_section->name);
+                            "--enable-non-contiguous-regions (section `%pA' "
+                            "would overflow `%pA' after it changed size).\n"),
+                          i, i->output_section);
 
                  *removed = 1;
                  dot = end;
@@ -5726,7 +5766,7 @@ ldlang_check_relro_region (lang_statement_union_type *s)
 static bfd_vma
 lang_size_sections_1
   (lang_statement_union_type **prev,
-   lang_output_section_statement_type *output_section_statement,
+   lang_output_section_statement_type *current_os,
    fill_type *fill,
    bfd_vma dot,
    bool *relax,
@@ -5735,6 +5775,7 @@ lang_size_sections_1
   lang_statement_union_type *s;
   lang_statement_union_type *prev_s = NULL;
   bool removed_prev_s = false;
+  lang_output_section_statement_type *os = current_os;
 
   /* Size up the sections from their constituent parts.  */
   for (s = *prev; s != NULL; prev_s = s, s = s->header.next)
@@ -5746,7 +5787,6 @@ lang_size_sections_1
        case lang_output_section_statement_enum:
          {
            bfd_vma newdot, after, dotdelta;
-           lang_output_section_statement_type *os;
            lang_memory_region_type *r;
            int section_alignment = 0;
 
@@ -5765,7 +5805,7 @@ lang_size_sections_1
              os->addr_tree = exp_intop (0);
            if (os->addr_tree != NULL)
              {
-               exp_fold_tree (os->addr_tree, bfd_abs_section_ptr, &dot);
+               exp_fold_tree (os->addr_tree, os, bfd_abs_section_ptr, &dot);
 
                if (expld.result.valid_p)
                  {
@@ -5870,7 +5910,7 @@ lang_size_sections_1
                    section_alignment = os->bfd_section->alignment_power;
                  }
                else
-                 section_alignment = exp_get_power (os->section_alignment,
+                 section_alignment = exp_get_power (os->section_alignment, os,
                                                     "section alignment");
 
                /* Align to what the section needs.  */
@@ -5958,6 +5998,7 @@ lang_size_sections_1
                       statement.  */
                    if (os->lma_region != os->region)
                      section_alignment = exp_get_power (os->section_alignment,
+                                                        os,
                                                         "section alignment");
                    if (section_alignment > 0)
                      lma = align_power (lma, section_alignment);
@@ -6047,7 +6088,7 @@ lang_size_sections_1
            dot += dotdelta;
 
            if (os->update_dot_tree != 0)
-             exp_fold_tree (os->update_dot_tree, bfd_abs_section_ptr, &dot);
+             exp_fold_tree (os->update_dot_tree, os, bfd_abs_section_ptr, &dot);
 
            /* Update dot in the region ?
               We only do this if the section is going to be allocated,
@@ -6078,8 +6119,7 @@ lang_size_sections_1
          break;
 
        case lang_constructors_statement_enum:
-         dot = lang_size_sections_1 (&constructor_list.head,
-                                     output_section_statement,
+         dot = lang_size_sections_1 (&constructor_list.head, current_os,
                                      fill, dot, relax, check_regions);
          break;
 
@@ -6087,14 +6127,13 @@ lang_size_sections_1
          {
            unsigned int size = 0;
 
-           s->data_statement.output_offset =
-             dot - output_section_statement->bfd_section->vma;
-           s->data_statement.output_section =
-             output_section_statement->bfd_section;
+           s->data_statement.output_offset = dot - current_os->bfd_section->vma;
+           s->data_statement.output_section = current_os->bfd_section;
 
            /* We might refer to provided symbols in the expression, and
               need to mark them as needed.  */
-           exp_fold_tree (s->data_statement.exp, bfd_abs_section_ptr, &dot);
+           exp_fold_tree (s->data_statement.exp, os,
+                          bfd_abs_section_ptr, &dot);
 
            switch (s->data_statement.type)
              {
@@ -6117,10 +6156,9 @@ lang_size_sections_1
            if (size < TO_SIZE ((unsigned) 1))
              size = TO_SIZE ((unsigned) 1);
            dot += TO_ADDR (size);
-           if (!(output_section_statement->bfd_section->flags
-                 & SEC_FIXED_SIZE))
-             output_section_statement->bfd_section->size
-               = TO_SIZE (dot - output_section_statement->bfd_section->vma);
+           if (!(current_os->bfd_section->flags & SEC_FIXED_SIZE))
+             current_os->bfd_section->size
+               = TO_SIZE (dot - current_os->bfd_section->vma);
 
          }
          break;
@@ -6129,29 +6167,27 @@ lang_size_sections_1
          {
            int size;
 
-           s->reloc_statement.output_offset =
-             dot - output_section_statement->bfd_section->vma;
-           s->reloc_statement.output_section =
-             output_section_statement->bfd_section;
+           s->reloc_statement.output_offset
+             = dot - current_os->bfd_section->vma;
+           s->reloc_statement.output_section
+             = current_os->bfd_section;
            size = bfd_get_reloc_size (s->reloc_statement.howto);
            dot += TO_ADDR (size);
-           if (!(output_section_statement->bfd_section->flags
-                 & SEC_FIXED_SIZE))
-             output_section_statement->bfd_section->size
-               = TO_SIZE (dot - output_section_statement->bfd_section->vma);
+           if (!(current_os->bfd_section->flags & SEC_FIXED_SIZE))
+             current_os->bfd_section->size
+               = TO_SIZE (dot - current_os->bfd_section->vma);
          }
          break;
 
        case lang_wild_statement_enum:
          dot = lang_size_sections_1 (&s->wild_statement.children.head,
-                                     output_section_statement,
-                                     fill, dot, relax, check_regions);
+                                     current_os, fill, dot, relax,
+                                     check_regions);
          break;
 
        case lang_object_symbols_statement_enum:
-         link_info.create_object_symbols_section
-           = output_section_statement->bfd_section;
-         output_section_statement->bfd_section->flags |= SEC_KEEP;
+         link_info.create_object_symbols_section = current_os->bfd_section;
+         current_os->bfd_section->flags |= SEC_KEEP;
          break;
 
        case lang_output_statement_enum:
@@ -6172,8 +6208,7 @@ lang_size_sections_1
                if (again)
                  *relax = true;
              }
-           dot = size_input_section (prev, output_section_statement,
-                                     fill, &removed, dot);
+           dot = size_input_section (prev, current_os, fill, &removed, dot);
          }
          break;
 
@@ -6181,8 +6216,7 @@ lang_size_sections_1
          break;
 
        case lang_fill_statement_enum:
-         s->fill_statement.output_section =
-           output_section_statement->bfd_section;
+         s->fill_statement.output_section = current_os->bfd_section;
 
          fill = s->fill_statement.fill;
          break;
@@ -6194,9 +6228,7 @@ lang_size_sections_1
 
            expld.dataseg.relro = exp_seg_relro_none;
 
-           exp_fold_tree (tree,
-                          output_section_statement->bfd_section,
-                          &newdot);
+           exp_fold_tree (tree, os, current_os->bfd_section, &newdot);
 
            ldlang_check_relro_region (s);
 
@@ -6207,11 +6239,11 @@ lang_size_sections_1
                 || tree->type.node_class == etree_assign)
                && (tree->assign.dst [0] != '.'
                    || tree->assign.dst [1] != '\0'))
-             output_section_statement->update_dot = 1;
+             current_os->update_dot = 1;
 
-           if (!output_section_statement->ignored)
+           if (!current_os->ignored)
              {
-               if (output_section_statement == abs_output_section)
+               if (current_os == abs_output_section)
                  {
                    /* If we don't have an output section, then just adjust
                       the default memory address.  */
@@ -6224,7 +6256,7 @@ lang_size_sections_1
                       put the pad before when relaxing, in case the
                       assignment references dot.  */
                    insert_pad (&s->header.next, fill, TO_SIZE (newdot - dot),
-                               output_section_statement->bfd_section, dot);
+                               current_os->bfd_section, dot);
 
                    /* Don't neuter the pad below when relaxing.  */
                    s = s->header.next;
@@ -6233,11 +6265,11 @@ lang_size_sections_1
                       should have space allocated to it, unless the
                       user has explicitly stated that the section
                       should not be allocated.  */
-                   if (output_section_statement->sectype != noalloc_section
-                       && (output_section_statement->sectype != noload_section
+                   if (current_os->sectype != noalloc_section
+                       && (current_os->sectype != noload_section
                            || (bfd_get_flavour (link_info.output_bfd)
                                == bfd_target_elf_flavour)))
-                     output_section_statement->bfd_section->flags |= SEC_ALLOC;
+                     current_os->bfd_section->flags |= SEC_ALLOC;
                  }
                dot = newdot;
              }
@@ -6258,13 +6290,13 @@ lang_size_sections_1
             section.  bfd_set_section_contents will complain even for
             a pad size of zero.  */
          s->padding_statement.output_offset
-           = dot - output_section_statement->bfd_section->vma;
+           = dot - current_os->bfd_section->vma;
          break;
 
        case lang_group_statement_enum:
          dot = lang_size_sections_1 (&s->group_statement.children.head,
-                                     output_section_statement,
-                                     fill, dot, relax, check_regions);
+                                     current_os, fill, dot, relax,
+                                     check_regions);
          break;
 
        case lang_insert_statement_enum:
@@ -6511,6 +6543,8 @@ lang_do_assignments_1 (lang_statement_union_type *s,
                       bfd_vma dot,
                       bool *found_end)
 {
+  lang_output_section_statement_type *os = current_os;
+
   for (; s != NULL; s = s->header.next)
     {
       switch (s->header.type)
@@ -6522,10 +6556,9 @@ lang_do_assignments_1 (lang_statement_union_type *s,
 
        case lang_output_section_statement_enum:
          {
-           lang_output_section_statement_type *os;
            bfd_vma newdot;
 
-           os = &(s->output_section_statement);
+           os = &s->output_section_statement;
            os->after_end = *found_end;
            init_opb (os->bfd_section);
            newdot = dot;
@@ -6552,7 +6585,7 @@ lang_do_assignments_1 (lang_statement_union_type *s,
                      newdot += TO_ADDR (os->bfd_section->size);
 
                    if (os->update_dot_tree != NULL)
-                     exp_fold_tree (os->update_dot_tree,
+                     exp_fold_tree (os->update_dot_tree, os,
                                     bfd_abs_section_ptr, &newdot);
                  }
                dot = newdot;
@@ -6572,7 +6605,7 @@ lang_do_assignments_1 (lang_statement_union_type *s,
          break;
 
        case lang_data_statement_enum:
-         exp_fold_tree (s->data_statement.exp, bfd_abs_section_ptr, &dot);
+         exp_fold_tree (s->data_statement.exp, os, bfd_abs_section_ptr, &dot);
          if (expld.result.valid_p)
            {
              s->data_statement.value = expld.result.value;
@@ -6608,7 +6641,7 @@ lang_do_assignments_1 (lang_statement_union_type *s,
          break;
 
        case lang_reloc_statement_enum:
-         exp_fold_tree (s->reloc_statement.addend_exp,
+         exp_fold_tree (s->reloc_statement.addend_exp, os,
                         bfd_abs_section_ptr, &dot);
          if (expld.result.valid_p)
            s->reloc_statement.addend_value = expld.result.value;
@@ -6647,7 +6680,7 @@ lang_do_assignments_1 (lang_statement_union_type *s,
              if (strcmp (p, "end") == 0)
                *found_end = true;
            }
-         exp_fold_tree (s->assignment_statement.exp,
+         exp_fold_tree (s->assignment_statement.exp, os,
                         (current_os->bfd_section != NULL
                          ? current_os->bfd_section : bfd_und_section_ptr),
                         &dot);
@@ -7270,7 +7303,7 @@ lang_one_common (struct bfd_link_hash_entry *h, void *info)
       static bool header_printed;
       int len;
       char *name;
-      char buf[50];
+      char buf[32];
 
       if (!header_printed)
        {
@@ -7298,22 +7331,9 @@ lang_one_common (struct bfd_link_hash_entry *h, void *info)
          print_nl ();
          len = 0;
        }
-      while (len < 20)
-       {
-         print_space ();
-         ++len;
-       }
 
-      minfo ("0x");
       sprintf (buf, "%" PRIx64, (uint64_t) size);
-      minfo ("%s", buf);
-      len = strlen (buf);
-
-      while (len < 16)
-       {
-         print_space ();
-         ++len;
-       }
+      fprintf (config.map_file, "%*s0x%-16s", 20 - len, "", buf);
 
       minfo ("%pB\n", section->owner);
     }
@@ -8024,6 +8044,40 @@ lang_propagate_lma_regions (void)
     }
 }
 
+static void
+warn_non_contiguous_discards (void)
+{
+  LANG_FOR_EACH_INPUT_STATEMENT (file)
+    {
+      if ((file->the_bfd->flags & (BFD_LINKER_CREATED | DYNAMIC)) != 0
+         || file->flags.just_syms)
+       continue;
+
+      for (asection *s = file->the_bfd->sections; s != NULL; s = s->next)
+       if (s->output_section == NULL
+           && (s->flags & SEC_LINKER_CREATED) == 0)
+         einfo (_("%P: warning: --enable-non-contiguous-regions "
+                  "discards section `%pA' from `%pB'\n"),
+                s, file->the_bfd);
+    }
+}
+
+static void
+reset_one_wild (lang_statement_union_type *statement)
+{
+  if (statement->header.type == lang_wild_statement_enum)
+    {
+      lang_wild_statement_type *stmt = &statement->wild_statement;
+      lang_list_init (&stmt->matching_sections);
+    }
+}
+
+static void
+reset_resolved_wilds (void)
+{
+  lang_for_each_statement (reset_one_wild);
+}
+
 void
 lang_process (void)
 {
@@ -8056,20 +8110,20 @@ lang_process (void)
   /* Create a bfd for each input file.  */
   current_target = default_target;
   lang_statement_iteration++;
-  open_input_bfds (statement_list.head, OPEN_BFD_NORMAL);
+  open_input_bfds (statement_list.head, NULL, OPEN_BFD_NORMAL);
 
   /* Now that open_input_bfds has processed assignments and provide
      statements we can give values to symbolic origin/length now.  */
   lang_do_memory_regions (true);
 
+  ldemul_before_plugin_all_symbols_read ();
+
 #if BFD_SUPPORTS_PLUGINS
   if (link_info.lto_plugin_active)
     {
       lang_statement_list_type added;
       lang_statement_list_type files, inputfiles;
 
-      ldemul_before_plugin_all_symbols_read ();
-
       /* Now all files are read, let the plugin(s) decide if there
         are any more to be added to the link before we call the
         emulation's after_open hook.  We create a private list of
@@ -8086,7 +8140,12 @@ lang_process (void)
       link_info.lto_all_symbols_read = true;
       /* Open any newly added files, updating the file chains.  */
       plugin_undefs = link_info.hash->undefs_tail;
-      open_input_bfds (*added.tail, OPEN_BFD_NORMAL);
+      lang_output_section_statement_type *last_os = NULL;
+      if (lang_os_list.head != NULL)
+       last_os = ((lang_output_section_statement_type *)
+                  ((char *) lang_os_list.tail
+                   - offsetof (lang_output_section_statement_type, next)));
+      open_input_bfds (*added.tail, last_os, OPEN_BFD_NORMAL);
       if (plugin_undefs == link_info.hash->undefs_tail)
        plugin_undefs = NULL;
       /* Restore the global list pointer now they have all been added.  */
@@ -8137,7 +8196,7 @@ lang_process (void)
          /* Rescan archives in case new undefined symbols have appeared.  */
          files = file_chain;
          lang_statement_iteration++;
-         open_input_bfds (statement_list.head, OPEN_BFD_RESCAN);
+         open_input_bfds (statement_list.head, NULL, OPEN_BFD_RESCAN);
          lang_list_remove_tail (&file_chain, &files);
          while (files.head != NULL)
            {
@@ -8157,6 +8216,8 @@ lang_process (void)
              *insert = &files.head->input_statement;
              files.head = (lang_statement_union_type *) *iter;
              *iter = temp;
+             if (file_chain.tail == (lang_statement_union_type **) insert)
+               file_chain.tail = (lang_statement_union_type **) iter;
              if (my_arch != NULL)
                {
                  lang_input_statement_type *parent = bfd_usrdata (my_arch);
@@ -8170,17 +8231,17 @@ lang_process (void)
     }
 #endif /* BFD_SUPPORTS_PLUGINS */
 
-  /* Make sure that nobody has tried to add a symbol to this list
-     before now.  */
-  ASSERT (link_info.gc_sym_list == NULL);
+  struct bfd_sym_chain **sym = &link_info.gc_sym_list;
+  while (*sym)
+    sym = &(*sym)->next;
 
-  link_info.gc_sym_list = &entry_symbol;
+  *sym = &entry_symbol;
 
   if (entry_symbol.name == NULL)
     {
-      link_info.gc_sym_list = ldlang_undef_chain_list_head;
+      *sym = ldlang_undef_chain_list_head;
 
-      /* entry_symbol is normally initialied by a ENTRY definition in the
+      /* entry_symbol is normally initialised by an ENTRY definition in the
         linker script or the -e command line option.  But if neither of
         these have been used, the target specific backend may still have
         provided an entry symbol via a call to lang_default_entry().
@@ -8227,6 +8288,11 @@ lang_process (void)
   /* Size up the common data.  */
   lang_common ();
 
+  if (0)
+    debug_prefix_tree ();
+
+  resolve_wilds ();
+
   /* Remove unreferenced sections if asked to.  */
   lang_gc_sections ();
 
@@ -8237,7 +8303,15 @@ lang_process (void)
 
   ldemul_after_check_relocs ();
 
-  /* Update wild statements.  */
+  /* There might have been new sections created (e.g. as result of
+     checking relocs to need a .got, or suchlike), so to properly order
+     them into our lists of matching sections reset them here.  */
+  reset_resolved_wilds ();
+  resolve_wilds ();
+
+  /* Update wild statements in case the user gave --sort-section.
+     Note how the option might have come after the linker script and
+     so couldn't have been set when the wild statements were created.  */
   update_wild_statements (statement_list.head);
 
   /* Run through the contours of the script and attach input sections
@@ -8336,12 +8410,38 @@ lang_process (void)
   if (command_line.check_section_addresses)
     lang_check_section_addresses ();
 
+  if (link_info.non_contiguous_regions
+      && link_info.non_contiguous_regions_warnings)
+    warn_non_contiguous_discards ();
+
   /* Check any required symbols are known.  */
   ldlang_check_require_defined_symbols ();
 
   lang_end ();
 }
 
+void
+lang_add_version_string (void)
+{
+  if (! enable_linker_version)
+    return;
+
+  const char * str = "GNU ld ";
+  int len = strlen (str);
+  int i;
+
+  for (i = 0 ; i < len ; i++)
+    lang_add_data (BYTE, exp_intop (str[i]));
+
+  str = BFD_VERSION_STRING;
+  len = strlen (str);
+
+  for (i = 0 ; i < len ; i++)
+    lang_add_data (BYTE, exp_intop (str[i]));
+
+  lang_add_data (BYTE, exp_intop ('\0'));
+}
+
 /* EXPORTED TO YACC */
 
 void
@@ -8351,12 +8451,15 @@ lang_add_wild (struct wildcard_spec *filespec,
 {
   struct wildcard_list *curr, *next;
   lang_wild_statement_type *new_stmt;
+  bool any_specs_sorted = false;
 
   /* Reverse the list as the parser puts it back to front.  */
   for (curr = section_list, section_list = NULL;
        curr != NULL;
        section_list = curr, curr = next)
     {
+      if (curr->spec.sorted != none && curr->spec.sorted != by_none)
+       any_specs_sorted = true;
       next = curr->next;
       curr->next = section_list;
     }
@@ -8372,6 +8475,7 @@ lang_add_wild (struct wildcard_spec *filespec,
   new_stmt = new_stat (lang_wild_statement, stat_ptr);
   new_stmt->filename = NULL;
   new_stmt->filenames_sorted = false;
+  new_stmt->any_specs_sorted = any_specs_sorted;
   new_stmt->section_flag_list = NULL;
   new_stmt->exclude_name_list = NULL;
   if (filespec != NULL)
@@ -8384,7 +8488,15 @@ lang_add_wild (struct wildcard_spec *filespec,
   new_stmt->section_list = section_list;
   new_stmt->keep_sections = keep_sections;
   lang_list_init (&new_stmt->children);
+  lang_list_init (&new_stmt->matching_sections);
   analyze_walk_wild_section_handler (new_stmt);
+  if (0)
+    {
+      printf ("wild %s(", new_stmt->filename ? new_stmt->filename : "*");
+      for (curr = new_stmt->section_list; curr; curr = curr->next)
+       printf ("%s ", curr->spec.name ? curr->spec.name : "*");
+      printf (")\n");
+    }
 }
 
 void
@@ -8469,6 +8581,89 @@ lang_add_data (int type, union etree_union *exp)
   new_stmt->type = type;
 }
 
+void
+lang_add_string (const char *s)
+{
+  bfd_vma  len = strlen (s);
+  bfd_vma  i;
+  bool     escape = false;
+
+  /* Add byte expressions until end of string.  */
+  for (i = 0 ; i < len; i++)
+    {
+      char c = *s++;
+
+      if (escape)
+       {
+         switch (c)
+           {
+           default:
+             /* Ignore the escape.  */
+             break;
+
+           case 'n': c = '\n'; break;
+           case 'r': c = '\r'; break;
+           case 't': c = '\t'; break;
+         
+           case '0':
+           case '1':
+           case '2':
+           case '3':
+           case '4':
+           case '5':
+           case '6':
+           case '7':
+             /* We have an octal number.  */
+             {
+               unsigned int value = c - '0';
+
+               c = *s;
+               if ((c >= '0') && (c <= '7'))
+                 {
+                   value <<= 3;
+                   value += (c - '0');
+                   i++;
+                   s++;
+
+                   c = *s;
+                   if ((c >= '0') && (c <= '7'))
+                     {
+                       value <<= 3;
+                       value += (c - '0');
+                       i++;
+                       s++;
+                     }
+                 }
+
+               if (value > 0xff)
+                 {
+                   /* octal: \777 is treated as '\077' + '7' */
+                   value >>= 3;
+                   i--;
+                   s--;
+                 }
+
+               c = value;
+             }
+             break;
+           }
+
+         lang_add_data (BYTE, exp_intop (c));
+         escape = false;
+       }
+      else
+       {
+         if (c == '\\')
+           escape = true;
+         else
+           lang_add_data (BYTE, exp_intop (c));
+       }
+    }
+
+  /* Remeber to terminate the string.  */
+  lang_add_data (BYTE, exp_intop (0));
+}
+
 /* Create a new reloc statement.  RELOC is the BFD relocation type to
    generate.  HOWTO is the corresponding howto structure (we could
    look this up, but the caller has already done so).  SECTION is the
@@ -8656,7 +8851,7 @@ lang_new_phdr (const char *name,
   n = stat_alloc (sizeof (struct lang_phdr));
   n->next = NULL;
   n->name = name;
-  n->type = exp_get_vma (type, 0, "program header type");
+  n->type = exp_get_vma (type, NULL, 0, "program header type");
   n->filehdr = filehdr;
   n->phdrs = phdrs;
   n->at = at;
@@ -8770,12 +8965,12 @@ lang_record_phdrs (void)
       if (l->flags == NULL)
        flags = 0;
       else
-       flags = exp_get_vma (l->flags, 0, "phdr flags");
+       flags = exp_get_vma (l->flags, NULL, 0, "phdr flags");
 
       if (l->at == NULL)
        at = 0;
       else
-       at = exp_get_vma (l->at, 0, "phdr load address");
+       at = exp_get_vma (l->at, NULL, 0, "phdr load address");
 
       if (!bfd_record_phdr (link_info.output_bfd, l->type,
                            l->flags != NULL, flags, l->at != NULL,
@@ -9535,7 +9730,7 @@ lang_do_memory_regions (bool update_regions_p)
     {
       if (r->origin_exp)
        {
-         exp_fold_tree_no_dot (r->origin_exp);
+         exp_fold_tree_no_dot (r->origin_exp, NULL);
           if (update_regions_p)
             {
               if (expld.result.valid_p)
@@ -9550,7 +9745,7 @@ lang_do_memory_regions (bool update_regions_p)
        }
       if (r->length_exp)
        {
-         exp_fold_tree_no_dot (r->length_exp);
+         exp_fold_tree_no_dot (r->length_exp, NULL);
           if (update_regions_p)
             {
               if (expld.result.valid_p)
@@ -9677,16 +9872,16 @@ lang_ld_feature (char *str)
 /* Pretty print memory amount.  */
 
 static void
-lang_print_memory_size (bfd_vma sz)
+lang_print_memory_size (uint64_t sz)
 {
   if ((sz & 0x3fffffff) == 0)
-    printf ("%10" BFD_VMA_FMT "u GB", sz >> 30);
+    printf ("%10" PRIu64 " GB", sz >> 30);
   else if ((sz & 0xfffff) == 0)
-    printf ("%10" BFD_VMA_FMT "u MB", sz >> 20);
+    printf ("%10" PRIu64 " MB", sz >> 20);
   else if ((sz & 0x3ff) == 0)
-    printf ("%10" BFD_VMA_FMT "u KB", sz >> 10);
+    printf ("%10" PRIu64 " KB", sz >> 10);
   else
-    printf (" %10" BFD_VMA_FMT "u B", sz);
+    printf (" %10" PRIu64 " B", sz);
 }
 
 /* Implement --print-memory-usage: disply per region memory usage.  */
@@ -9703,7 +9898,7 @@ lang_print_memory_usage (void)
 
       printf ("%16s: ",r->name_list.name);
       lang_print_memory_size (used_length);
-      lang_print_memory_size ((bfd_vma) r->length);
+      lang_print_memory_size (r->length);
 
       if (r->length != 0)
        {