Remove path name from test case
[binutils-gdb.git] / ld / ldlang.c
index 336eea913c7be36adcd697b2882f4c764bfbb5f8..566c2b8326ffe56e30048e5e9eb764ffe6ff1b08 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;
@@ -219,23 +227,39 @@ 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 && (r = memcmp (spec->name, name, pl)))
-    return r;
+
+  if (pl)
+    {
+      if (inputlen < pl)
+       return 1;
+
+      r = memcmp (spec->name, name, pl);
+      if (r)
+       return r;
+    }
+
   if (sl)
     {
-      size_t inputlen = strlen (name);
       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;
-  else if (nl > pl)
+
+  if (nl > pl)
     return fnmatch (spec->name + pl, name + pl, 0);
-  return name[nl];
+
+  if (inputlen >= nl)
+    return name[nl];
+
+  return 0;
 }
 
 static char *
@@ -364,98 +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 = spec_match (&sec->spec, 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;
-}
+  /* If filename is excluded we're done.  */
+  if (walk_wild_file_in_exclude_list (ptr->exclude_name_list, file))
+    return;
 
-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 };
+  /* 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;
 
-  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;
+         /* 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
@@ -510,7 +539,7 @@ get_init_priority (const asection *sec)
 /* Compare sections ASEC and BSEC according to SORT.  */
 
 static int
-compare_section (sort_type sort, asection *asec, asection *bsec)
+compare_section (sort_type sort, asection *asec, asection *bsec, bool reversed)
 {
   int ret;
   int a_priority, b_priority;
@@ -525,7 +554,10 @@ compare_section (sort_type sort, asection *asec, asection *bsec)
       b_priority = get_init_priority (bsec);
       if (a_priority < 0 || b_priority < 0)
        goto sort_by_name;
-      ret = a_priority - b_priority;
+      if (reversed)
+       ret = b_priority - a_priority;
+      else
+       ret = a_priority - b_priority;
       if (ret)
        break;
       else
@@ -539,11 +571,17 @@ compare_section (sort_type sort, asection *asec, asection *bsec)
 
     case by_name:
     sort_by_name:
-      ret = strcmp (bfd_section_name (asec), bfd_section_name (bsec));
+      if (reversed)
+       ret = strcmp (bfd_section_name (bsec), bfd_section_name (asec));
+      else
+       ret = strcmp (bfd_section_name (asec), bfd_section_name (bsec));
       break;
 
     case by_name_alignment:
-      ret = strcmp (bfd_section_name (asec), bfd_section_name (bsec));
+      if (reversed)
+       ret = strcmp (bfd_section_name (bsec), bfd_section_name (asec));
+      else
+       ret = strcmp (bfd_section_name (asec), bfd_section_name (bsec));
       if (ret)
        break;
       /* Fall through.  */
@@ -618,7 +656,11 @@ wild_sort (lang_wild_statement_type *wild,
          else
            ln = sort_filename (lsec->owner);
 
-         i = filename_cmp (fn, ln);
+         if (wild->filenames_reversed)
+           i = filename_cmp (ln, fn);
+         else
+           i = filename_cmp (fn, ln);
+
          if (i > 0)
            { tree = &((*tree)->right); continue; }
          else if (i < 0)
@@ -631,7 +673,11 @@ wild_sort (lang_wild_statement_type *wild,
              if (la)
                ln = sort_filename (lsec->owner);
 
-             i = filename_cmp (fn, ln);
+             if (wild->filenames_reversed)
+               i = filename_cmp (ln, fn);
+             else
+               i = filename_cmp (fn, ln);
+             
              if (i > 0)
                { tree = &((*tree)->right); continue; }
              else if (i < 0)
@@ -643,7 +689,8 @@ wild_sort (lang_wild_statement_type *wild,
         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, sec->spec.reversed) < 0)
        tree = &((*tree)->left);
       else
        tree = &((*tree)->right);
@@ -670,6 +717,11 @@ output_section_callback_sort (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;
@@ -705,217 +757,143 @@ 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)
-    {
-      walk_wild_section_general (ptr, file, callback, data);
-      return;
-    }
-
-  for (s = file->the_bfd->sections; s != NULL; s = s->next)
+  for (; t; t = t->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);
-}
-
-/* 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.  */
-
-static bool
-wild_spec_can_overlap (const char *name1, const char *name2)
-{
-  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;
+  debug_prefix_tree_rec (ptroot, 2);
 }
 
 /* Like strcspn() but start to look from the end to beginning of
@@ -936,23 +914,14 @@ rstrcspn (const char *s, const char *reject)
   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;
 
@@ -969,152 +938,92 @@ analyze_walk_wild_section_handler (lang_wild_statement_type *ptr)
        sec->spec.namelen = sec->spec.prefixlen = sec->spec.suffixlen = 0;
     }
 
-  /* 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))
-       {
-         ++wild_name_count;
-         if (!is_simple_wild (sec->spec.name))
-           return;
-       }
-    }
+  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.  */
 
-  /* 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)
+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)
-    {
-      /* 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
+  for (l = s->matching_sections.head; l; l = l->header.next)
     {
-      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);
     }
 }
 
@@ -1244,6 +1153,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));
@@ -1421,6 +1340,7 @@ void
 lang_init (void)
 {
   obstack_begin (&stat_obstack, 1000);
+  obstack_init (&pt_obstack);
 
   stat_ptr = &statement_list;
 
@@ -1446,6 +1366,7 @@ void
 lang_finish (void)
 {
   output_section_statement_table_free ();
+  ldfile_remap_input_free ();
 }
 
 /*----------------------------------------------------------------------
@@ -1909,7 +1830,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;
     }
 
@@ -1928,13 +1849,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;
@@ -1987,6 +1908,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;
     }
@@ -2069,7 +1992,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;
        }
 
@@ -2292,8 +2217,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;
 
@@ -2393,6 +2319,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;
@@ -2409,13 +2337,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",
@@ -2443,7 +2373,7 @@ lang_map (void)
       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)
     {
@@ -2526,10 +2456,24 @@ 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");
 }
 
+static flagword
+get_os_init_flag (lang_output_section_statement_type * os)
+{
+  if (os != NULL)
+    switch (os->sectype)
+      {
+      case readonly_section: return SEC_READONLY;
+      case noload_section:   return SEC_NEVER_LOAD;
+      default: break;
+      }
+
+  return 0;
+}
+
 /* Make sure that all output sections mentioned in an expression are
    initialized.  */
 
@@ -2573,7 +2517,7 @@ exp_init_os (etree_type *exp)
 
            os = lang_output_section_find (exp->name.name);
            if (os != NULL && os->bfd_section == NULL)
-             init_os (os, 0);
+             init_os (os, get_os_init_flag (os));
          }
        }
       break;
@@ -2631,30 +2575,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);
@@ -2668,45 +2609,39 @@ 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 "
+                "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);
@@ -2717,6 +2652,42 @@ lang_add_section (lang_statement_list_type *ptr,
         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 (wont_add_section_p (section, output))
+    return;
+
+  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
      to an output section, because we want to be able to include a
      SEC_NEVER_LOAD section in the middle of an otherwise loaded
@@ -3504,6 +3475,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:
@@ -3550,17 +3525,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.  */
@@ -3569,7 +3547,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:
          {
@@ -3588,7 +3566,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
@@ -3675,7 +3653,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;
@@ -4237,6 +4215,9 @@ map_input_to_output_sections
                                        os);
          break;
        case lang_data_statement_enum:
+         if (os == NULL)
+           /* This should never happen.  */
+           FAIL ();
          /* Make sure that any sections mentioned in the expression
             are initialized.  */
          exp_init_os (s->data_statement.exp);
@@ -4283,7 +4264,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
@@ -4315,14 +4296,16 @@ map_input_to_output_sections
          if (os != NULL && os->bfd_section == NULL)
            init_os (os, 0);
          break;
+
        case lang_assignment_statement_enum:
          if (os != NULL && os->bfd_section == NULL)
-           init_os (os, 0);
+           init_os (os, get_os_init_flag (os));
 
          /* Make sure that any sections mentioned in the assignment
             are initialized.  */
          exp_init_os (s->assignment_statement.exp);
          break;
+
        case lang_address_statement_enum:
          /* Mark the specified section with the supplied address.
             If this section was actually a segment marker, then the
@@ -4352,6 +4335,8 @@ map_input_to_output_sections
          break;
        case lang_insert_statement_enum:
          break;
+       case lang_input_matcher_enum:
+         FAIL ();
        }
     }
 }
@@ -4501,21 +4486,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;
@@ -4526,6 +4545,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;
@@ -4672,6 +4693,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);
        }
 
@@ -4710,7 +4732,7 @@ 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;
 
@@ -4849,6 +4871,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
@@ -4904,6 +4970,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);
+           }
+       }
     }
 }
 
@@ -5064,10 +5168,14 @@ print_wild_statement (lang_wild_statement_type *w,
 
   if (w->filenames_sorted)
     minfo ("SORT_BY_NAME(");
+  if (w->filenames_reversed)
+    minfo ("REVERSE(");
   if (w->filename != NULL)
     minfo ("%s", w->filename);
   else
     minfo ("*");
+  if (w->filenames_reversed)
+    minfo (")");
   if (w->filenames_sorted)
     minfo (")");
 
@@ -5112,6 +5220,12 @@ print_wild_statement (lang_wild_statement_type *w,
          break;
        }
 
+      if (sec->spec.reversed)
+       {
+         minfo ("REVERSE(");
+         closing_paren++;
+       }
+
       if (sec->spec.exclude_name_list != NULL)
        {
          name_list *tmp;
@@ -5359,6 +5473,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)
@@ -5384,15 +5499,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;
@@ -5697,7 +5812,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,
@@ -5706,6 +5821,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)
@@ -5717,7 +5833,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;
 
@@ -5736,7 +5851,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)
                  {
@@ -5841,7 +5956,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.  */
@@ -5929,6 +6044,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);
@@ -6018,7 +6134,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,
@@ -6049,8 +6165,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;
 
@@ -6058,14 +6173,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)
              {
@@ -6088,10 +6202,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;
@@ -6100,29 +6213,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:
@@ -6143,8 +6254,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;
 
@@ -6152,8 +6262,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;
@@ -6165,9 +6274,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);
 
@@ -6178,11 +6285,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.  */
@@ -6195,7 +6302,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;
@@ -6204,11 +6311,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;
              }
@@ -6229,13 +6336,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:
@@ -6482,6 +6589,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)
@@ -6493,10 +6602,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;
@@ -6523,7 +6631,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;
@@ -6543,7 +6651,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;
@@ -6579,7 +6687,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;
@@ -6618,7 +6726,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);
@@ -7982,6 +8090,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)
 {
@@ -8014,20 +8156,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
@@ -8044,7 +8186,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.  */
@@ -8095,7 +8242,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)
            {
@@ -8115,6 +8262,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);
@@ -8128,17 +8277,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().
@@ -8185,6 +8334,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 ();
 
@@ -8195,6 +8349,12 @@ lang_process (void)
 
   ldemul_after_check_relocs ();
 
+  /* 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.  */
@@ -8296,12 +8456,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
@@ -8341,14 +8527,23 @@ lang_add_wild (struct wildcard_spec *filespec,
   if (filespec != NULL)
     {
       new_stmt->filename = filespec->name;
-      new_stmt->filenames_sorted = filespec->sorted == by_name;
+      new_stmt->filenames_sorted = (filespec->sorted == by_name || filespec->reversed);
       new_stmt->section_flag_list = filespec->section_flag_list;
       new_stmt->exclude_name_list = filespec->exclude_name_list;
+      new_stmt->filenames_reversed = filespec->reversed;
     }
   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
@@ -8433,6 +8628,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
@@ -8620,7 +8898,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;
@@ -8734,12 +9012,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,
@@ -9499,7 +9777,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)
@@ -9514,7 +9792,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)