s/boolean/bfd_boolean/ s/true/TRUE/ s/false/FALSE/. Simplify
[deliverable/binutils-gdb.git] / ld / ldlang.c
index 8bd0eea58330006ff15e8e26545d8009a4d84c62..c2a11627a3ae7538b5d0f0ce66c7ac99a89ebacd 100644 (file)
@@ -1,35 +1,37 @@
 /* Linker command language support.
-   Copyright (C) 1991, 92, 93, 94, 95, 96, 97, 98, 99, 2000
+   Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
+   2001, 2002
    Free Software Foundation, Inc.
 
-This file is part of GLD, the Gnu Linker.
+   This file is part of GLD, the Gnu Linker.
 
-GLD is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
+   GLD is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
 
-GLD is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+   GLD is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
 
-You should have received a copy of the GNU General Public License
-along with GLD; see the file COPYING.  If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA.  */
+   You should have received a copy of the GNU General Public License
+   along with GLD; see the file COPYING.  If not, write to the Free
+   Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA.  */
 
 #include "bfd.h"
 #include "sysdep.h"
 #include "libiberty.h"
+#include "safe-ctype.h"
 #include "obstack.h"
 #include "bfdlink.h"
 
 #include "ld.h"
 #include "ldmain.h"
-#include "ldgram.h"
 #include "ldexp.h"
 #include "ldlang.h"
+#include <ldgram.h>
 #include "ldlex.h"
 #include "ldmisc.h"
 #include "ldctor.h"
@@ -38,12 +40,13 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "fnmatch.h"
 #include "demangle.h"
 
-#include <ctype.h>
+#ifndef offsetof
+#define offsetof(TYPE,MEMBER) ((size_t)&(((TYPE*)0)->MEMBER))
+#endif
 
 /* FORWARDS */
-static lang_statement_union_type *new_statement PARAMS ((enum statement_enum,
-                                                        size_t,
-                                                        lang_statement_list_type*));
+static lang_statement_union_type *new_statement
+  PARAMS ((enum statement_enum, size_t, lang_statement_list_type *));
 
 /* LOCALS */
 static struct obstack stat_obstack;
@@ -52,9 +55,9 @@ static struct obstack stat_obstack;
 #define obstack_chunk_free free
 static const char *startup_file;
 static lang_statement_list_type input_file_chain;
-static boolean placed_commons = false;
+static bfd_boolean placed_commons = FALSE;
 static lang_output_section_statement_type *default_common_section;
-static boolean map_option_f;
+static bfd_boolean map_option_f;
 static bfd_vma print_dot;
 static lang_input_statement_type *first_file;
 static const char *current_target;
@@ -66,50 +69,77 @@ static void lang_for_each_statement_worker
   PARAMS ((void (*) (lang_statement_union_type *),
           lang_statement_union_type *));
 static lang_input_statement_type *new_afile
-  PARAMS ((const char *, lang_input_file_enum_type, const char *, boolean));
-static lang_memory_region_type *lang_memory_default PARAMS ((asection *));
-static void lang_map_flags PARAMS ((flagword));
-static void init_os PARAMS ((lang_output_section_statement_type *));
-static void exp_init_os PARAMS ((etree_type *));
-static void section_already_linked PARAMS ((bfd *, asection *, PTR));
+  PARAMS ((const char *, lang_input_file_enum_type, const char *,
+          bfd_boolean));
+static lang_memory_region_type *lang_memory_default
+  PARAMS ((asection *));
+static void lang_map_flags
+  PARAMS ((flagword));
+static void init_os
+  PARAMS ((lang_output_section_statement_type *));
+static void exp_init_os
+  PARAMS ((etree_type *));
+static void section_already_linked
+  PARAMS ((bfd *, asection *, PTR));
 static struct bfd_hash_entry *already_linked_newfunc
   PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
-static void already_linked_table_init PARAMS ((void));
-static void already_linked_table_free PARAMS ((void));
-static boolean wildcardp PARAMS ((const char *));
+static void already_linked_table_init
+  PARAMS ((void));
+static void already_linked_table_free
+  PARAMS ((void));
+static bfd_boolean wildcardp
+  PARAMS ((const char *));
 static lang_statement_union_type *wild_sort
-  PARAMS ((lang_wild_statement_type *, lang_input_statement_type *,
-          asection *));
+  PARAMS ((lang_wild_statement_type *, struct wildcard_list *,
+          lang_input_statement_type *, asection *));
 static void output_section_callback
-  PARAMS ((lang_wild_statement_type *, asection *,
+  PARAMS ((lang_wild_statement_type *, struct wildcard_list *, asection *,
           lang_input_statement_type *, PTR));
-static lang_input_statement_type *lookup_name PARAMS ((const char *));
-static void load_symbols
+static lang_input_statement_type *lookup_name
+  PARAMS ((const char *));
+static bfd_boolean load_symbols
   PARAMS ((lang_input_statement_type *, lang_statement_list_type *));
 static void wild
-  PARAMS ((lang_wild_statement_type *, const char *, const char *,
+  PARAMS ((lang_wild_statement_type *,
           const char *, lang_output_section_statement_type *));
-static bfd *open_output PARAMS ((const char *));
-static void ldlang_open_output PARAMS ((lang_statement_union_type *));
-static void open_input_bfds PARAMS ((lang_statement_union_type *, boolean));
-static void lang_reasonable_defaults PARAMS ((void));
-static void lang_place_undefineds PARAMS ((void));
+static bfd *open_output
+  PARAMS ((const char *));
+static void ldlang_open_output
+  PARAMS ((lang_statement_union_type *));
+static void open_input_bfds
+  PARAMS ((lang_statement_union_type *, bfd_boolean));
+static void lang_reasonable_defaults
+  PARAMS ((void));
+static void insert_undefined
+  PARAMS ((const char *));
+static void lang_place_undefineds
+  PARAMS ((void));
 static void map_input_to_output_sections
   PARAMS ((lang_statement_union_type *, const char *,
           lang_output_section_statement_type *));
+static void strip_excluded_output_sections
+  PARAMS ((void));
 static void print_output_section_statement
   PARAMS ((lang_output_section_statement_type *));
 static void print_assignment
   PARAMS ((lang_assignment_statement_type *,
           lang_output_section_statement_type *));
-static void print_input_statement PARAMS ((lang_input_statement_type *));
-static boolean print_one_symbol PARAMS ((struct bfd_link_hash_entry *, PTR));
-static void print_input_section PARAMS ((lang_input_section_type *));
-static void print_fill_statement PARAMS ((lang_fill_statement_type *));
-static void print_data_statement PARAMS ((lang_data_statement_type *));
-static void print_address_statement PARAMS ((lang_address_statement_type *));
-static void print_reloc_statement PARAMS ((lang_reloc_statement_type *));
-static void print_padding_statement PARAMS ((lang_padding_statement_type *));
+static void print_input_statement
+  PARAMS ((lang_input_statement_type *));
+static bfd_boolean print_one_symbol
+  PARAMS ((struct bfd_link_hash_entry *, PTR));
+static void print_input_section
+  PARAMS ((lang_input_section_type *));
+static void print_fill_statement
+  PARAMS ((lang_fill_statement_type *));
+static void print_data_statement
+  PARAMS ((lang_data_statement_type *));
+static void print_address_statement
+  PARAMS ((lang_address_statement_type *));
+static void print_reloc_statement
+  PARAMS ((lang_reloc_statement_type *));
+static void print_padding_statement
+  PARAMS ((lang_padding_statement_type *));
 static void print_wild_statement
   PARAMS ((lang_wild_statement_type *, lang_output_section_statement_type *));
 static void print_group
@@ -118,90 +148,117 @@ static void print_statement
   PARAMS ((lang_statement_union_type *, lang_output_section_statement_type *));
 static void print_statement_list
   PARAMS ((lang_statement_union_type *, lang_output_section_statement_type *));
-static void print_statements PARAMS ((void));
-static bfd_vma insert_pad
-  PARAMS ((lang_statement_union_type **this_ptr, fill_type fill,
-          unsigned int power, asection *output_section_statement,
-          bfd_vma dot));
+static void print_statements
+  PARAMS ((void));
+static void insert_pad
+  PARAMS ((lang_statement_union_type **, fill_type *,
+          unsigned int, asection *, bfd_vma));
 static bfd_vma size_input_section
-  PARAMS ((lang_statement_union_type **this_ptr,
-          lang_output_section_statement_type *output_section_statement,
-          fill_type fill, bfd_vma dot, boolean relax));
-static void lang_finish PARAMS ((void));
-static void ignore_bfd_errors PARAMS ((const char *, ...));
-static void lang_check PARAMS ((void));
-static void lang_common PARAMS ((void));
-static boolean lang_one_common PARAMS ((struct bfd_link_hash_entry *, PTR));
-static void lang_place_orphans PARAMS ((void));
-static int topower PARAMS ((int));
-static void lang_set_startof PARAMS ((void));
-static void reset_memory_regions PARAMS ((void));
+  PARAMS ((lang_statement_union_type **, lang_output_section_statement_type *,
+          fill_type *, bfd_vma));
+static void lang_finish
+  PARAMS ((void));
+static void ignore_bfd_errors
+  PARAMS ((const char *, ...));
+static void lang_check
+  PARAMS ((void));
+static void lang_common
+  PARAMS ((void));
+static bfd_boolean lang_one_common
+  PARAMS ((struct bfd_link_hash_entry *, PTR));
+static void lang_place_orphans
+  PARAMS ((void));
+static int topower
+  PARAMS ((int));
+static void lang_set_startof
+  PARAMS ((void));
 static void gc_section_callback
-  PARAMS ((lang_wild_statement_type *, asection *,
+  PARAMS ((lang_wild_statement_type *, struct wildcard_list *, asection *,
           lang_input_statement_type *, PTR));
-static void lang_record_phdrs PARAMS ((void));
+static void lang_get_regions
+  PARAMS ((struct memory_region_struct **, struct memory_region_struct **,
+          const char *, const char *, int));
+static void lang_record_phdrs
+  PARAMS ((void));
 static void lang_gc_wild
-  PARAMS ((lang_wild_statement_type *, const char *, const char *));
-static void lang_gc_sections_1 PARAMS ((lang_statement_union_type *));
-static void lang_gc_sections PARAMS ((void));
+  PARAMS ((lang_wild_statement_type *));
+static void lang_gc_sections_1
+  PARAMS ((lang_statement_union_type *));
+static void lang_gc_sections
+  PARAMS ((void));
 static int lang_vers_match_lang_c
   PARAMS ((struct bfd_elf_version_expr *, const char *));
 static int lang_vers_match_lang_cplusplus
   PARAMS ((struct bfd_elf_version_expr *, const char *));
 static int lang_vers_match_lang_java
   PARAMS ((struct bfd_elf_version_expr *, const char *));
-static void lang_do_version_exports_section PARAMS ((void));
-static void lang_check_section_addresses PARAMS ((void));
+static void lang_do_version_exports_section
+  PARAMS ((void));
+static void lang_check_section_addresses
+  PARAMS ((void));
 static void os_region_check
   PARAMS ((lang_output_section_statement_type *,
           struct memory_region_struct *, etree_type *, bfd_vma));
-
-typedef void (*callback_t) PARAMS ((lang_wild_statement_type *,
-                                   asection *, lang_input_statement_type *,
-                                   PTR));
+static bfd_vma lang_size_sections_1
+  PARAMS ((lang_statement_union_type *, lang_output_section_statement_type *,
+          lang_statement_union_type **, fill_type *, bfd_vma, bfd_boolean *));
+typedef void (*callback_t)
+  PARAMS ((lang_wild_statement_type *, struct wildcard_list *, asection *,
+          lang_input_statement_type *, PTR));
 static void walk_wild
-  PARAMS ((lang_wild_statement_type *, const char *, const char *,
-        callback_t, PTR));
+  PARAMS ((lang_wild_statement_type *, callback_t, PTR));
 static void walk_wild_section
-  PARAMS ((lang_wild_statement_type *, const char *,
-          lang_input_statement_type *, callback_t, PTR));
+  PARAMS ((lang_wild_statement_type *, lang_input_statement_type *,
+          callback_t, PTR));
 static void walk_wild_file
-  PARAMS ((lang_wild_statement_type *, const char *,
-          lang_input_statement_type *, callback_t, PTR));
-
-static int    get_target PARAMS ((const bfd_target *, PTR));
-static void   stricpy PARAMS ((char *, char *));
-static void   strcut PARAMS ((char *, char *));
-static int    name_compare PARAMS ((char *, char *));
-static int    closest_target_match PARAMS ((const bfd_target *, PTR));
-static char * get_first_input_target PARAMS ((void));
+  PARAMS ((lang_wild_statement_type *, lang_input_statement_type *,
+          callback_t, PTR));
+static int get_target
+  PARAMS ((const bfd_target *, PTR));
+static void stricpy
+  PARAMS ((char *, char *));
+static void strcut
+  PARAMS ((char *, char *));
+static int name_compare
+  PARAMS ((char *, char *));
+static int closest_target_match
+  PARAMS ((const bfd_target *, PTR));
+static char * get_first_input_target
+  PARAMS ((void));
 
 /* EXPORTS */
 lang_output_section_statement_type *abs_output_section;
 lang_statement_list_type lang_output_section_statement;
 lang_statement_list_type *stat_ptr = &statement_list;
 lang_statement_list_type file_chain = { NULL, NULL };
-const char *entry_symbol = NULL;
-boolean entry_from_cmdline;
-boolean lang_has_input_file = false;
-boolean had_output_filename = false;
-boolean lang_float_flag = false;
-boolean delete_output_file_on_failure = false;
+struct bfd_sym_chain entry_symbol = { NULL, NULL };
+const char *entry_section = ".text";
+bfd_boolean entry_from_cmdline;
+bfd_boolean lang_has_input_file = FALSE;
+bfd_boolean had_output_filename = FALSE;
+bfd_boolean lang_float_flag = FALSE;
+bfd_boolean delete_output_file_on_failure = FALSE;
 struct lang_nocrossrefs *nocrossref_list;
+struct unique_sections *unique_section_list;
 
 etree_type *base; /* Relocation base - or null */
 
-#if defined(__STDC__) || defined(ALMOST_STDC)
+#if defined (__STDC__) || defined (ALMOST_STDC)
 #define cat(a,b) a##b
 #else
 #define cat(a,b) a/**/b
 #endif
 
-#define new_stat(x,y) (cat(x,_type)*) new_statement(cat(x,_enum), sizeof(cat(x,_type)),y)
+/* Don't beautify the line below with "innocent" whitespace, it breaks
+   the K&R C preprocessor!  */
+#define new_stat(x, y) \
+  (cat (x,_type)*) new_statement (cat (x,_enum), sizeof (cat (x,_type)), y)
 
-#define outside_section_address(q) ((q)->output_offset + (q)->output_section->vma)
+#define outside_section_address(q) \
+  ((q)->output_offset + (q)->output_section->vma)
 
-#define outside_symbol_address(q) ((q)->value + outside_section_address(q->section))
+#define outside_symbol_address(q) \
+  ((q)->value + outside_section_address (q->section))
 
 #define SECTION_NAME_MAP_LENGTH (16)
 
@@ -212,63 +269,94 @@ stat_alloc (size)
   return obstack_alloc (&stat_obstack, size);
 }
 
+bfd_boolean
+unique_section_p (secnam)
+     const char *secnam;
+{
+  struct unique_sections *unam;
+
+  for (unam = unique_section_list; unam; unam = unam->next)
+    if (wildcardp (unam->name)
+       ? fnmatch (unam->name, secnam, 0) == 0
+       : strcmp (unam->name, secnam) == 0)
+      {
+       return TRUE;
+      }
+
+  return FALSE;
+}
+
 /* Generic traversal routines for finding matching sections.  */
 
 static void
-walk_wild_section (ptr, section, file, callback, data)
+walk_wild_section (ptr, file, callback, data)
      lang_wild_statement_type *ptr;
-     const char *section;
      lang_input_statement_type *file;
      callback_t callback;
      PTR data;
 {
-  /* Don't process sections from files which were excluded.  */
-  if (ptr->exclude_filename_list != NULL)
-    {
-      struct name_list *list_tmp;
-      for (list_tmp = ptr->exclude_filename_list; list_tmp; list_tmp = list_tmp->next)
-       {
-         boolean match;
-
-         if (wildcardp (list_tmp->name))
-           match = fnmatch (list_tmp->name, file->filename, 0) == 0 ? true : false;
-         else
-           match = strcmp (list_tmp->name, file->filename) == 0 ? true : false;
+  asection *s;
 
-         if (match)
-           return;
-       }
-    }
+  if (file->just_syms_flag)
+    return;
 
-  if (file->just_syms_flag == false)
+  for (s = file->the_bfd->sections; s != NULL; s = s->next)
     {
-      register asection *s;
-      boolean wildcard;
+      struct wildcard_list *sec;
 
-      if (section == NULL)
-       wildcard = false;
-      else
-       wildcard = wildcardp (section);
+      sec = ptr->section_list;
+      if (sec == NULL)
+       (*callback) (ptr, sec, s, file, data);
 
-      for (s = file->the_bfd->sections; s != NULL; s = s->next)
+      while (sec != NULL)
        {
-         boolean match;
+         bfd_boolean skip = FALSE;
+         struct name_list *list_tmp;
+
+         /* Don't process sections from files which were
+            excluded.  */
+         for (list_tmp = sec->spec.exclude_name_list;
+              list_tmp;
+              list_tmp = list_tmp->next)
+           {
+             if (wildcardp (list_tmp->name))
+               skip = fnmatch (list_tmp->name, file->filename, 0) == 0;
+             else
+               skip = strcmp (list_tmp->name, file->filename) == 0;
 
-         if (section == NULL)
-           match = true;
-         else
+             /* If this file is part of an archive, and the archive is
+                excluded, exclude this file.  */
+             if (! skip && file->the_bfd != NULL
+                 && file->the_bfd->my_archive != NULL
+                 && file->the_bfd->my_archive->filename != NULL)
+               {
+                 if (wildcardp (list_tmp->name))
+                   skip = fnmatch (list_tmp->name,
+                                   file->the_bfd->my_archive->filename,
+                                   0) == 0;
+                 else
+                   skip = strcmp (list_tmp->name,
+                                  file->the_bfd->my_archive->filename) == 0;
+               }
+
+             if (skip)
+               break;
+           }
+
+         if (!skip && sec->spec.name != NULL)
            {
-             const char *name;
+             const char *sname = bfd_get_section_name (file->the_bfd, s);
 
-             name = bfd_get_section_name (file->the_bfd, s);
-             if (wildcard)
-               match = fnmatch (section, name, 0) == 0 ? true : false;
+             if (wildcardp (sec->spec.name))
+               skip = fnmatch (sec->spec.name, sname, 0) != 0;
              else
-               match = strcmp (section, name) == 0 ? true : false;
+               skip = strcmp (sec->spec.name, sname) != 0;
            }
 
-         if (match)
-           (*callback) (ptr, s, file, data);
+         if (!skip)
+           (*callback) (ptr, sec, s, file, data);
+
+         sec = sec->next;
        }
     }
 }
@@ -276,16 +364,15 @@ walk_wild_section (ptr, section, file, callback, data)
 /* Handle a wild statement for a single file F.  */
 
 static void
-walk_wild_file (s, section, f, callback, data)
+walk_wild_file (s, f, callback, data)
      lang_wild_statement_type *s;
-     const char *section;
      lang_input_statement_type *f;
      callback_t callback;
      PTR data;
 {
   if (f->the_bfd == NULL
       || ! bfd_check_format (f->the_bfd, bfd_archive))
-    walk_wild_section (s, section, f, callback, data);
+    walk_wild_section (s, f, callback, data);
   else
     {
       bfd *member;
@@ -302,7 +389,7 @@ walk_wild_file (s, section, f, callback, data)
             lang_input_statement.  */
          if (member->usrdata != NULL)
            {
-             walk_wild_section (s, section,
+             walk_wild_section (s,
                                 (lang_input_statement_type *) member->usrdata,
                                 callback, data);
            }
@@ -313,27 +400,27 @@ walk_wild_file (s, section, f, callback, data)
 }
 
 static void
-walk_wild (s, section, file, callback, data)
+walk_wild (s, callback, data)
      lang_wild_statement_type *s;
-     const char *section;
-     const char *file;
      callback_t callback;
      PTR data;
 {
-  if (file == (char *) NULL)
+  const char *file_spec = s->filename;
+
+  if (file_spec == NULL)
     {
       /* Perform the iteration over all files in the list.  */
       LANG_FOR_EACH_INPUT_STATEMENT (f)
        {
-         walk_wild_file (s, section, f, callback, data);
+         walk_wild_file (s, f, callback, data);
        }
     }
-  else if (wildcardp (file))
+  else if (wildcardp (file_spec))
     {
       LANG_FOR_EACH_INPUT_STATEMENT (f)
        {
-         if (fnmatch (file, f->filename, FNM_FILE_NAME) == 0)
-           walk_wild_file (s, section, f, callback, data);
+         if (fnmatch (file_spec, f->filename, FNM_FILE_NAME) == 0)
+           walk_wild_file (s, f, callback, data);
        }
     }
   else
@@ -341,8 +428,9 @@ walk_wild (s, section, file, callback, data)
       lang_input_statement_type *f;
 
       /* Perform the iteration over a single file.  */
-      f = lookup_name (file);
-      walk_wild_file (s, section, f, callback, data);
+      f = lookup_name (file_spec);
+      if (f)
+       walk_wild_file (s, f, callback, data);
     }
 }
 
@@ -354,7 +442,7 @@ lang_for_each_statement_worker (func, s)
      void (*func) PARAMS ((lang_statement_union_type *));
      lang_statement_union_type *s;
 {
-  for (; s != (lang_statement_union_type *) NULL; s = s->next)
+  for (; s != (lang_statement_union_type *) NULL; s = s->header.next)
     {
       func (s);
 
@@ -436,7 +524,7 @@ new_statement (type, size, list)
 
    We can be supplied with requests for input files more than once;
    they may, for example be split over serveral lines like foo.o(.text)
-   foo.o(.data) etc, so when asked for a file we check that we havn't
+   foo.o(.data) etc, so when asked for a file we check that we haven't
    got it already so we don't duplicate the bfd.  */
 
 static lang_input_statement_type *
@@ -444,7 +532,7 @@ new_afile (name, file_type, target, add_to_list)
      const char *name;
      lang_input_file_enum_type file_type;
      const char *target;
-     boolean add_to_list;
+     bfd_boolean add_to_list;
 {
   lang_input_statement_type *p;
 
@@ -457,57 +545,57 @@ new_afile (name, file_type, target, add_to_list)
       p->header.next = NULL;
     }
 
-  lang_has_input_file = true;
+  lang_has_input_file = TRUE;
   p->target = target;
   switch (file_type)
     {
     case lang_input_file_is_symbols_only_enum:
       p->filename = name;
-      p->is_archive = false;
-      p->real = true;
+      p->is_archive = FALSE;
+      p->real = TRUE;
       p->local_sym_name = name;
-      p->just_syms_flag = true;
-      p->search_dirs_flag = false;
+      p->just_syms_flag = TRUE;
+      p->search_dirs_flag = FALSE;
       break;
     case lang_input_file_is_fake_enum:
       p->filename = name;
-      p->is_archive = false;
-      p->real = false;
+      p->is_archive = FALSE;
+      p->real = FALSE;
       p->local_sym_name = name;
-      p->just_syms_flag = false;
-      p->search_dirs_flag = false;
+      p->just_syms_flag = FALSE;
+      p->search_dirs_flag = FALSE;
       break;
     case lang_input_file_is_l_enum:
-      p->is_archive = true;
+      p->is_archive = TRUE;
       p->filename = name;
-      p->real = true;
+      p->real = TRUE;
       p->local_sym_name = concat ("-l", name, (const char *) NULL);
-      p->just_syms_flag = false;
-      p->search_dirs_flag = true;
+      p->just_syms_flag = FALSE;
+      p->search_dirs_flag = TRUE;
       break;
     case lang_input_file_is_marker_enum:
       p->filename = name;
-      p->is_archive = false;
-      p->real = false;
+      p->is_archive = FALSE;
+      p->real = FALSE;
       p->local_sym_name = name;
-      p->just_syms_flag = false;
-      p->search_dirs_flag = true;
+      p->just_syms_flag = FALSE;
+      p->search_dirs_flag = TRUE;
       break;
     case lang_input_file_is_search_file_enum:
       p->filename = name;
-      p->is_archive = false;
-      p->real = true;
+      p->is_archive = FALSE;
+      p->real = TRUE;
       p->local_sym_name = name;
-      p->just_syms_flag = false;
-      p->search_dirs_flag = true;
+      p->just_syms_flag = FALSE;
+      p->search_dirs_flag = TRUE;
       break;
     case lang_input_file_is_file_enum:
       p->filename = name;
-      p->is_archive = false;
-      p->real = true;
+      p->is_archive = FALSE;
+      p->real = TRUE;
       p->local_sym_name = name;
-      p->just_syms_flag = false;
-      p->search_dirs_flag = false;
+      p->just_syms_flag = FALSE;
+      p->search_dirs_flag = FALSE;
       break;
     default:
       FAIL ();
@@ -519,7 +607,7 @@ new_afile (name, file_type, target, add_to_list)
   p->symbol_count = 0;
   p->dynamic = config.dynamic_link;
   p->whole_archive = whole_archive;
-  p->loaded = false;
+  p->loaded = FALSE;
   lang_statement_append (&input_file_chain,
                         (lang_statement_union_type *) p,
                         &p->next_real_file);
@@ -532,8 +620,8 @@ lang_add_input_file (name, file_type, target)
      lang_input_file_enum_type file_type;
      const char *target;
 {
-  lang_has_input_file = true;
-  return new_afile (name, file_type, target, true);
+  lang_has_input_file = TRUE;
+  return new_afile (name, file_type, target, TRUE);
 }
 
 /* Build enough state so that the parser can build its tree.  */
@@ -579,6 +667,10 @@ lang_memory_region_lookup (name)
 {
   lang_memory_region_type *p;
 
+  /* NAME is NULL for LMA memspecs if no region was specified.  */
+  if (name == NULL)
+    return NULL;
+
   for (p = lang_memory_region_list;
        p != (lang_memory_region_type *) NULL;
        p = p->next)
@@ -609,7 +701,7 @@ lang_memory_region_lookup (name)
     lang_memory_region_type *new =
     (lang_memory_region_type *) stat_alloc (sizeof (lang_memory_region_type));
 
-    new->name = buystring (name);
+    new->name = xstrdup (name);
     new->next = (lang_memory_region_type *) NULL;
 
     *lang_memory_region_list_tail = new;
@@ -619,7 +711,7 @@ lang_memory_region_lookup (name)
     new->not_flags = 0;
     new->length = ~(bfd_size_type) 0;
     new->current = 0;
-    new->had_full_message = false;
+    new->had_full_message = FALSE;
 
     return new;
   }
@@ -684,13 +776,13 @@ lang_output_section_statement_lookup (name)
        new_stat (lang_output_section_statement, stat_ptr);
       lookup->region = (lang_memory_region_type *) NULL;
       lookup->lma_region = (lang_memory_region_type *) NULL;
-      lookup->fill = 0;
+      lookup->fill = (fill_type *) 0;
       lookup->block_value = 1;
       lookup->name = name;
 
       lookup->next = (lang_statement_union_type *) NULL;
       lookup->bfd_section = (asection *) NULL;
-      lookup->processed = false;
+      lookup->processed = FALSE;
       lookup->sectype = normal_section;
       lookup->addr_tree = (etree_type *) NULL;
       lang_list_init (&lookup->children);
@@ -700,6 +792,7 @@ lang_output_section_statement_lookup (name)
       lookup->subsection_alignment = -1;
       lookup->section_alignment = -1;
       lookup->load_base = (union etree_union *) NULL;
+      lookup->update_dot_tree = NULL;
       lookup->phdrs = NULL;
 
       lang_statement_append (&lang_output_section_statement,
@@ -795,7 +888,7 @@ init_os (s)
     return;
 
   if (strcmp (s->name, DISCARD_SECTION_NAME) == 0)
-    einfo (_("%P%F: Illegal use of `%s' section"), DISCARD_SECTION_NAME);
+    einfo (_("%P%F: Illegal use of `%s' section\n"), DISCARD_SECTION_NAME);
 
   new = ((section_userdata_type *)
         stat_alloc (sizeof (section_userdata_type)));
@@ -916,8 +1009,7 @@ section_already_linked (abfd, sec, data)
      discard all sections.  */
   if (entry->just_syms_flag)
     {
-      sec->output_section = bfd_abs_section_ptr;
-      sec->output_offset = sec->vma;
+      bfd_link_just_syms (sec, &link_info);
       return;
     }
 
@@ -926,28 +1018,28 @@ section_already_linked (abfd, sec, data)
   if ((flags & SEC_LINK_ONCE) == 0)
     return;
 
-  /* FIXME: When doing a relocateable link, we may have trouble
+  /* FIXME: When doing a relocatable link, we may have trouble
      copying relocations in other sections that refer to local symbols
      in the section being discarded.  Those relocations will have to
      be converted somehow; as of this writing I'm not sure that any of
      the backends handle that correctly.
 
      It is tempting to instead not discard link once sections when
-     doing a relocateable link (technically, they should be discarded
+     doing a relocatable link (technically, they should be discarded
      whenever we are building constructors).  However, that fails,
      because the linker winds up combining all the link once sections
      into a single large link once section, which defeats the purpose
      of having link once sections in the first place.
 
-     Also, not merging link once sections in a relocateable link
-     causes trouble for MIPS ELF, which relies in link once semantics
+     Also, not merging link once sections in a relocatable link
+     causes trouble for MIPS ELF, which relies on link once semantics
      to handle the .reginfo section correctly.  */
 
   name = bfd_get_section_name (abfd, sec);
 
   already_linked_list =
     ((struct already_linked_hash_entry *)
-     bfd_hash_lookup (&already_linked_table, name, true, false));
+     bfd_hash_lookup (&already_linked_table, name, TRUE, FALSE));
 
   for (l = already_linked_list->entry; l != NULL; l = l->next)
     {
@@ -989,14 +1081,13 @@ section_already_linked (abfd, sec, data)
              break;
            }
 
-         /* Set the output_section field so that wild_doit does not
-            create a lang_input_section structure for this section.
-            Since there might be a symbol in the section being
-            discarded, we must retain a pointer to the section which
-            we are really going to use.  */
+         /* Set the output_section field so that lang_add_section
+            does not create a lang_input_section structure for this
+            section.  */
          sec->output_section = bfd_abs_section_ptr;
-         if (sec->comdat != NULL)
-           sec->comdat->sec = l->sec;
+
+         if (flags & SEC_GROUP)
+           bfd_discard_group (abfd, sec);
 
          return;
        }
@@ -1051,13 +1142,13 @@ already_linked_table_free ()
    explicit actions, like foo.o(.text), bar.o(.text) and
    foo.o(.text, .data).  */
 
-/* Return true if the PATTERN argument is a wildcard pattern.
+/* Return TRUE if the PATTERN argument is a wildcard pattern.
    Although backslashes are treated specially if a pattern contains
    wildcards, we do not consider the mere presence of a backslash to
-   be enough to cause the the pattern to be treated as a wildcard.
+   be enough to cause the pattern to be treated as a wildcard.
    That lets us handle DOS filenames more naturally.  */
 
-static boolean
+static bfd_boolean
 wildcardp (pattern)
      const char *pattern;
 {
@@ -1067,8 +1158,8 @@ wildcardp (pattern)
     if (*s == '?'
        || *s == '*'
        || *s == '[')
-      return true;
-  return false;
+      return TRUE;
+  return FALSE;
 }
 
 /* Add SECTION to the output section OUTPUT.  Do this by creating a
@@ -1076,35 +1167,36 @@ wildcardp (pattern)
    input file which holds SECTION.  */
 
 void
-wild_doit (ptr, section, output, file)
+lang_add_section (ptr, section, output, file)
      lang_statement_list_type *ptr;
      asection *section;
      lang_output_section_statement_type *output;
      lang_input_statement_type *file;
 {
   flagword flags;
-  boolean discard;
+  bfd_boolean discard;
 
   flags = bfd_get_section_flags (section->owner, section);
 
-  discard = false;
+  discard = FALSE;
 
-  /* If we are doing a final link, discard sections marked with
-     SEC_EXCLUDE.  */
-  if (! link_info.relocateable
-      && (flags & SEC_EXCLUDE) != 0)
-    discard = true;
+  /* Discard sections marked with SEC_EXCLUDE if we are doing a final
+     link.  Discard debugging sections marked with SEC_EXCLUDE on a
+     relocatable link too.  */
+  if ((flags & SEC_EXCLUDE) != 0
+      && ((flags & SEC_DEBUGGING) != 0 || !link_info.relocateable))
+    discard = TRUE;
 
   /* Discard input sections which are assigned to a section named
      DISCARD_SECTION_NAME.  */
   if (strcmp (output->name, DISCARD_SECTION_NAME) == 0)
-    discard = true;
+    discard = TRUE;
 
   /* Discard debugging sections if we are stripping debugging
      information.  */
   if ((link_info.strip == strip_debugger || link_info.strip == strip_all)
       && (flags & SEC_DEBUGGING) != 0)
-    discard = true;
+    discard = TRUE;
 
   if (discard)
     {
@@ -1118,17 +1210,15 @@ wild_doit (ptr, section, output, file)
 
   if (section->output_section == NULL)
     {
-      boolean first;
+      bfd_boolean first;
       lang_input_section_type *new;
       flagword flags;
 
       if (output->bfd_section == NULL)
-       {
-         init_os (output);
-         first = true;
-       }
-      else
-       first = false;
+       init_os (output);
+
+      first = ! output->bfd_section->linker_has_input;
+      output->bfd_section->linker_has_input = 1;
 
       /* Add a section reference to the list.  */
       new = new_stat (lang_input_section, ptr);
@@ -1163,8 +1253,26 @@ wild_doit (ptr, section, output, file)
       if (! first && (section->output_section->flags & SEC_READONLY) == 0)
        flags &= ~ SEC_READONLY;
 
+      /* Keep SEC_MERGE and SEC_STRINGS only if they are the same.  */
+      if (! first
+         && ((section->output_section->flags & (SEC_MERGE | SEC_STRINGS))
+             != (flags & (SEC_MERGE | SEC_STRINGS))
+             || ((flags & SEC_MERGE)
+                 && section->output_section->entsize != section->entsize)))
+       {
+         section->output_section->flags &= ~ (SEC_MERGE | SEC_STRINGS);
+         flags &= ~ (SEC_MERGE | SEC_STRINGS);
+       }
+
+      /* For now make .tbss normal section.  */
+      if ((flags & SEC_THREAD_LOCAL) && ! link_info.relocateable)
+       flags |= SEC_LOAD;
+
       section->output_section->flags |= flags;
 
+      if (flags & SEC_MERGE)
+       section->output_section->entsize = section->entsize;
+
       /* If SEC_READONLY is not set in the input section, then clear
          it from the output section.  */
       if ((section->flags & SEC_READONLY) == 0)
@@ -1212,19 +1320,20 @@ wild_doit (ptr, section, output, file)
    new section should just go at the end of the current list.  */
 
 static lang_statement_union_type *
-wild_sort (wild, file, section)
+wild_sort (wild, sec, file, section)
      lang_wild_statement_type *wild;
+     struct wildcard_list *sec;
      lang_input_statement_type *file;
      asection *section;
 {
   const char *section_name;
   lang_statement_union_type *l;
 
-  if (! wild->filenames_sorted && ! wild->sections_sorted)
+  if (!wild->filenames_sorted && (sec == NULL || !sec->spec.sorted))
     return NULL;
 
   section_name = bfd_get_section_name (file->the_bfd, section);
-  for (l = wild->children.head; l != NULL; l = l->next)
+  for (l = wild->children.head; l != NULL; l = l->header.next)
     {
       lang_input_section_type *ls;
 
@@ -1238,7 +1347,7 @@ wild_sort (wild, file, section)
       if (wild->filenames_sorted)
        {
          const char *fn, *ln;
-         boolean fa, la;
+         bfd_boolean fa, la;
          int i;
 
          /* The PE support for the .idata section as generated by
@@ -1250,24 +1359,24 @@ wild_sort (wild, file, section)
              && bfd_my_archive (file->the_bfd) != NULL)
            {
              fn = bfd_get_filename (bfd_my_archive (file->the_bfd));
-             fa = true;
+             fa = TRUE;
            }
          else
            {
              fn = file->filename;
-             fa = false;
+             fa = FALSE;
            }
 
          if (ls->ifile->the_bfd != NULL
              && bfd_my_archive (ls->ifile->the_bfd) != NULL)
            {
              ln = bfd_get_filename (bfd_my_archive (ls->ifile->the_bfd));
-             la = true;
+             la = TRUE;
            }
          else
            {
              ln = ls->ifile->filename;
-             la = false;
+             la = FALSE;
            }
 
          i = strcmp (fn, ln);
@@ -1294,7 +1403,7 @@ wild_sort (wild, file, section)
       /* Here either the files are not sorted by name, or we are
          looking at the sections for this file.  */
 
-      if (wild->sections_sorted)
+      if (sec != NULL && sec->spec.sorted)
        {
          if (strcmp (section_name,
                      bfd_get_section_name (ls->ifile->the_bfd,
@@ -1311,20 +1420,25 @@ wild_sort (wild, file, section)
    NULL, in which case it is a wild card.  */
 
 static void
-output_section_callback (ptr, section, file, output)
+output_section_callback (ptr, sec, section, file, output)
      lang_wild_statement_type *ptr;
+     struct wildcard_list *sec;
      asection *section;
      lang_input_statement_type *file;
      PTR output;
 {
   lang_statement_union_type *before;
 
+  /* Exclude sections that match UNIQUE_SECTION_LIST.  */
+  if (unique_section_p (bfd_get_section_name (file->the_bfd, section)))
+    return;
+
   /* If the wild pattern was marked KEEP, the member sections
      should be as well.  */
   if (ptr->keep_sections)
     section->flags |= SEC_KEEP;
 
-  before = wild_sort (ptr, file, section);
+  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
@@ -1332,31 +1446,31 @@ output_section_callback (ptr, section, file, output)
      of the current list.  */
 
   if (before == NULL)
-    wild_doit (&ptr->children, section,
-              (lang_output_section_statement_type *) output,
-              file);
+    lang_add_section (&ptr->children, section,
+                     (lang_output_section_statement_type *) output,
+                     file);
   else
     {
       lang_statement_list_type list;
       lang_statement_union_type **pp;
 
       lang_list_init (&list);
-      wild_doit (&list, section,
-                (lang_output_section_statement_type *) output,
-                file);
+      lang_add_section (&list, section,
+                       (lang_output_section_statement_type *) output,
+                       file);
 
       /* If we are discarding the section, LIST.HEAD will
         be NULL.  */
       if (list.head != NULL)
        {
-         ASSERT (list.head->next == NULL);
+         ASSERT (list.head->header.next == NULL);
 
          for (pp = &ptr->children.head;
               *pp != before;
-              pp = &(*pp)->next)
+              pp = &(*pp)->header.next)
            ASSERT (*pp != NULL);
 
-         list.head->next = *pp;
+         list.head->header.next = *pp;
          *pp = list.head;
        }
     }
@@ -1386,7 +1500,7 @@ lookup_name (name)
 
   if (search == (lang_input_statement_type *) NULL)
     search = new_afile (name, lang_input_file_is_file_enum, default_target,
-                       false);
+                       FALSE);
 
   /* If we have already added this file, or this file is not real
      (FIXME: can that ever actually happen?) or the name is NULL
@@ -1396,14 +1510,15 @@ lookup_name (name)
       || search->filename == (const char *) NULL)
     return search;
 
-  load_symbols (search, (lang_statement_list_type *) NULL);
+  if (! load_symbols (search, (lang_statement_list_type *) NULL))
+    return NULL;
 
   return search;
 }
 
 /* Get the symbols for an input file.  */
 
-static void
+static bfd_boolean
 load_symbols (entry, place)
      lang_input_statement_type *entry;
      lang_statement_list_type *place;
@@ -1411,7 +1526,7 @@ load_symbols (entry, place)
   char **matching;
 
   if (entry->loaded)
-    return;
+    return TRUE;
 
   ldfile_open_file (entry);
 
@@ -1420,8 +1535,14 @@ load_symbols (entry, place)
     {
       bfd_error_type err;
       lang_statement_list_type *hold;
+      bfd_boolean bad_load = TRUE;
 
       err = bfd_get_error ();
+
+      /* See if the emulation has some special knowledge.  */
+      if (ldemul_unrecognized_file (entry))
+       return TRUE;
+
       if (err == bfd_error_file_ambiguously_recognized)
        {
          char **p;
@@ -1434,35 +1555,31 @@ load_symbols (entry, place)
        }
       else if (err != bfd_error_file_not_recognized
               || place == NULL)
-       einfo (_("%F%B: file not recognized: %E\n"), entry->the_bfd);
+         einfo (_("%F%B: file not recognized: %E\n"), entry->the_bfd);
+      else
+       bad_load = FALSE;
 
       bfd_close (entry->the_bfd);
       entry->the_bfd = NULL;
 
-      /* See if the emulation has some special knowledge.  */
-
-      if (ldemul_unrecognized_file (entry))
-       return;
-
       /* Try to interpret the file as a linker script.  */
-
       ldfile_open_command_file (entry->filename);
 
       hold = stat_ptr;
       stat_ptr = place;
 
-      ldfile_assumed_script = true;
+      ldfile_assumed_script = TRUE;
       parser_input = input_script;
       yyparse ();
-      ldfile_assumed_script = false;
+      ldfile_assumed_script = FALSE;
 
       stat_ptr = hold;
 
-      return;
+      return ! bad_load;
     }
 
   if (ldemul_recognized_file (entry))
-    return;
+    return TRUE;
 
   /* We don't call ldlang_add_file for an archive.  Instead, the
      add_symbols entry point will call ldlang_add_file, via the
@@ -1482,60 +1599,78 @@ load_symbols (entry, place)
     case bfd_archive:
       if (entry->whole_archive)
        {
-         bfd *member = bfd_openr_next_archived_file (entry->the_bfd,
-                                                     (bfd *) NULL);
-         while (member != NULL)
+         bfd *member = NULL;
+         bfd_boolean loaded = TRUE;
+
+         for (;;)
            {
+             member = bfd_openr_next_archived_file (entry->the_bfd, member);
+
+             if (member == NULL)
+               break;
+
              if (! bfd_check_format (member, bfd_object))
-               einfo (_("%F%B: object %B in archive is not object\n"),
-                      entry->the_bfd, member);
+               {
+                 einfo (_("%F%B: member %B in archive is not an object\n"),
+                        entry->the_bfd, member);
+                 loaded = FALSE;
+               }
+
              if (! ((*link_info.callbacks->add_archive_element)
                     (&link_info, member, "--whole-archive")))
                abort ();
+
              if (! bfd_link_add_symbols (member, &link_info))
-               einfo (_("%F%B: could not read symbols: %E\n"), member);
-             member = bfd_openr_next_archived_file (entry->the_bfd,
-                                                    member);
+               {
+                 einfo (_("%F%B: could not read symbols: %E\n"), member);
+                 loaded = FALSE;
+               }
            }
 
-         entry->loaded = true;
-
-         return;
+         entry->loaded = loaded;
+         return loaded;
        }
+      break;
     }
 
-  if (! bfd_link_add_symbols (entry->the_bfd, &link_info))
+  if (bfd_link_add_symbols (entry->the_bfd, &link_info))
+    entry->loaded = TRUE;
+  else
     einfo (_("%F%B: could not read symbols: %E\n"), entry->the_bfd);
 
-  entry->loaded = true;
+  return entry->loaded;
 }
 
-/* Handle a wild statement.  SECTION or FILE or both may be NULL,
-   indicating that it is a wildcard.  Separate lang_input_section
-   statements are created for each part of the expansion; they are
-   added after the wild statement S.  OUTPUT is the output section.  */
+/* Handle a wild statement.  S->FILENAME or S->SECTION_LIST or both
+   may be NULL, indicating that it is a wildcard.  Separate
+   lang_input_section statements are created for each part of the
+   expansion; they are added after the wild statement S.  OUTPUT is
+   the output section.  */
 
 static void
-wild (s, section, file, target, output)
+wild (s, target, output)
      lang_wild_statement_type *s;
-     const char *section;
-     const char *file;
      const char *target ATTRIBUTE_UNUSED;
      lang_output_section_statement_type *output;
 {
-  walk_wild (s, section, file, output_section_callback, (PTR) output);
+  struct wildcard_list *sec;
+
+  walk_wild (s, output_section_callback, (PTR) output);
 
-  if (section != (char *) NULL
-      && strcmp (section, "COMMON") == 0
-      && default_common_section == NULL)
+  for (sec = s->section_list; sec != NULL; sec = sec->next)
     {
-      /* Remember the section that common is going to in case we later
-         get something which doesn't know where to put it.  */
-      default_common_section = output;
+      if (default_common_section != NULL)
+       break;
+      if (sec->spec.name != NULL && strcmp (sec->spec.name, "COMMON") == 0)
+       {
+         /* Remember the section that common is going to in case we
+            later get something which doesn't know where to put it.  */
+         default_common_section = output;
+       }
     }
 }
 
-/* Return true iff target is the sought target.  */
+/* Return TRUE iff target is the sought target.  */
 
 static int
 get_target (target, data)
@@ -1557,12 +1692,7 @@ stricpy (dest, src)
   char c;
 
   while ((c = *src++) != 0)
-    {
-      if (isupper ((unsigned char) c))
-       c = tolower (c);
-
-      *dest++ = c;
-    }
+    *dest++ = TOLOWER (c);
 
   *dest = 0;
 }
@@ -1664,7 +1794,8 @@ closest_target_match (target, data)
 
   /* Oh dear, we now have two potential candidates for a successful match.
      Compare their names and choose the better one.  */
-  if (name_compare (target->name, original->name) > name_compare (winner->name, original->name))
+  if (name_compare (target->name, original->name)
+      > name_compare (winner->name, original->name))
     winner = target;
 
   /* Keep on searching until wqe have checked them all.  */
@@ -1699,6 +1830,29 @@ get_first_input_target ()
   return target;
 }
 
+const char *
+lang_get_output_target ()
+{
+  const char *target;
+
+  /* Has the user told us which output format to use?  */
+  if (output_target != (char *) NULL)
+    return output_target;
+
+  /* No - has the current target been set to something other than
+     the default?  */
+  if (current_target != default_target)
+    return current_target;
+
+  /* No - can we determine the format of the first input file?  */
+  target = get_first_input_target ();
+  if (target != NULL)
+    return target;
+
+  /* Failed - use the default output target.  */
+  return default_target;
+}
+
 /* Open the output file.  */
 
 static bfd *
@@ -1707,24 +1861,7 @@ open_output (name)
 {
   bfd *output;
 
-  /* Has the user told us which output format to use?  */
-  if (output_target == (char *) NULL)
-    {
-      /* No - has the current target been set to something other than
-         the default?  */
-      if (current_target != default_target)
-       output_target = current_target;
-
-      /* No - can we determine the format of the first input file?  */
-      else
-       {
-         output_target = get_first_input_target ();
-
-         /* Failed - use the default output target.  */
-         if (output_target == NULL)
-           output_target = default_target;
-       }
-    }
+  output_target = lang_get_output_target ();
 
   /* Has the user requested a particular endianness on the command
      line?  */
@@ -1760,7 +1897,8 @@ open_output (name)
                  /* Try to find a target as similar as possible to
                     the default target, but which has the desired
                     endian characteristic.  */
-                 (void) bfd_search_for_target (closest_target_match, (PTR) target);
+                 (void) bfd_search_for_target (closest_target_match,
+                                               (PTR) target);
 
                  /* Oh dear - we could not find any targets that
                     satisfy our requirements.  */
@@ -1783,7 +1921,7 @@ open_output (name)
       einfo (_("%P%F: cannot open output file %s: %E\n"), name);
     }
 
-  delete_output_file_on_failure = true;
+  delete_output_file_on_failure = TRUE;
 
 #if 0
   output->flags |= D_PAGED;
@@ -1841,9 +1979,9 @@ ldlang_open_output (statement)
 static void
 open_input_bfds (s, force)
      lang_statement_union_type *s;
-     boolean force;
+     bfd_boolean force;
 {
-  for (; s != (lang_statement_union_type *) NULL; s = s->next)
+  for (; s != (lang_statement_union_type *) NULL; s = s->header.next)
     {
       switch (s->header.type)
        {
@@ -1871,7 +2009,7 @@ open_input_bfds (s, force)
            do
              {
                undefs = link_info.hash->undefs_tail;
-               open_input_bfds (s->group_statement.children.head, true);
+               open_input_bfds (s->group_statement.children.head, TRUE);
              }
            while (undefs != link_info.hash->undefs_tail);
          }
@@ -1895,16 +2033,17 @@ open_input_bfds (s, force)
                  && s->input_statement.loaded
                  && bfd_check_format (s->input_statement.the_bfd,
                                       bfd_archive))
-               s->input_statement.loaded = false;
+               s->input_statement.loaded = FALSE;
 
              lang_list_init (&add);
 
-             load_symbols (&s->input_statement, &add);
+             if (! load_symbols (&s->input_statement, &add))
+               config.make_executable = FALSE;
 
              if (add.head != NULL)
                {
-                 *add.tail = s->next;
-                 s->next = add.head;
+                 *add.tail = s->header.next;
+                 s->header.next = add.head;
                }
            }
          break;
@@ -1926,7 +2065,7 @@ lang_reasonable_defaults ()
 
   default_common_section = lang_output_section_statement_lookup (".bss");
 
-  if (placed_commons == false)
+  if (!placed_commons)
     {
       lang_wild_statement_type *new =
       new_stat (lang_wild_statement,
@@ -1940,14 +2079,14 @@ lang_reasonable_defaults ()
 }
 
 /* Add the supplied name to the symbol table as an undefined reference.
-   Remove items from the chain as we open input bfds.  */
-typedef struct ldlang_undef_chain_list
-{
-  struct ldlang_undef_chain_list *next;
-  char *name;
-}                       ldlang_undef_chain_list_type;
+   This is a two step process as the symbol table doesn't even exist at
+   the time the ld command line is processed.  First we put the name
+   on a list, then, once the output file has been opened, transfer the
+   name to the symbol table.  */
+
+typedef struct bfd_sym_chain ldlang_undef_chain_list_type;
 
-static ldlang_undef_chain_list_type *ldlang_undef_chain_list_head;
+#define ldlang_undef_chain_list_head entry_symbol.next
 
 void
 ldlang_add_undef (name)
@@ -1960,7 +2099,29 @@ ldlang_add_undef (name)
   new->next = ldlang_undef_chain_list_head;
   ldlang_undef_chain_list_head = new;
 
-  new->name = buystring (name);
+  new->name = xstrdup (name);
+
+  if (output_bfd != NULL)
+    insert_undefined (new->name);
+}
+
+/* Insert NAME as undefined in the symbol table.  */
+
+static void
+insert_undefined (name)
+     const char *name;
+{
+  struct bfd_link_hash_entry *h;
+
+  h = bfd_link_hash_lookup (link_info.hash, name, TRUE, FALSE, TRUE);
+  if (h == (struct bfd_link_hash_entry *) NULL)
+    einfo (_("%P%F: bfd_link_hash_lookup failed: %E\n"));
+  if (h->type == bfd_link_hash_new)
+    {
+      h->type = bfd_link_hash_undefined;
+      h->u.undef.abfd = NULL;
+      bfd_link_add_undef (link_info.hash, h);
+    }
 }
 
 /* Run through the list of undefineds created above and place them
@@ -1976,17 +2137,7 @@ lang_place_undefineds ()
        ptr != (ldlang_undef_chain_list_type *) NULL;
        ptr = ptr->next)
     {
-      struct bfd_link_hash_entry *h;
-
-      h = bfd_link_hash_lookup (link_info.hash, ptr->name, true, false, true);
-      if (h == (struct bfd_link_hash_entry *) NULL)
-       einfo (_("%P%F: bfd_link_hash_lookup failed: %E\n"));
-      if (h->type == bfd_link_hash_new)
-       {
-         h->type = bfd_link_hash_undefined;
-         h->u.undef.abfd = NULL;
-         bfd_link_add_undef (link_info.hash, h);
-       }
+      insert_undefined (ptr->name);
     }
 }
 
@@ -1998,16 +2149,12 @@ map_input_to_output_sections (s, target, output_section_statement)
      const char *target;
      lang_output_section_statement_type *output_section_statement;
 {
-  for (; s != (lang_statement_union_type *) NULL; s = s->next)
+  for (; s != (lang_statement_union_type *) NULL; s = s->header.next)
     {
       switch (s->header.type)
        {
-
        case lang_wild_statement_enum:
-         wild (&s->wild_statement, s->wild_statement.section_name,
-               s->wild_statement.filename, target,
-               output_section_statement);
-
+         wild (&s->wild_statement, target, output_section_statement);
          break;
        case lang_constructors_statement_enum:
          map_input_to_output_sections (constructor_list.head,
@@ -2068,6 +2215,41 @@ map_input_to_output_sections (s, target, output_section_statement)
     }
 }
 
+/* An output section might have been removed after its statement was
+   added.  For example, ldemul_before_allocation can remove dynamic
+   sections if they turn out to be not needed.  Clean them up here.  */
+
+static void
+strip_excluded_output_sections ()
+{
+  lang_statement_union_type *u;
+
+  for (u = lang_output_section_statement.head;
+       u != NULL;
+       u = u->output_section_statement.next)
+    {
+      lang_output_section_statement_type *os;
+      asection *s;
+
+      os = &u->output_section_statement;
+      s = os->bfd_section;
+      if (s != NULL && (s->flags & SEC_EXCLUDE) != 0)
+       {
+         asection **p;
+
+         os->bfd_section = NULL;
+
+         for (p = &output_bfd->sections; *p; p = &(*p)->next)
+           if (*p == s)
+             {
+               bfd_section_list_remove (output_bfd, p);
+               output_bfd->section_count--;
+               break;
+             }
+       }
+    }
+}
+
 static void
 print_output_section_statement (output_section_statement)
      lang_output_section_statement_type *output_section_statement;
@@ -2128,7 +2310,17 @@ print_assignment (assignment, output_section)
   result = exp_fold_tree (assignment->exp->assign.src, output_section,
                          lang_final_phase_enum, print_dot, &print_dot);
   if (result.valid_p)
-    minfo ("0x%V", result.value + result.section->bfd_section->vma);
+    {
+      const char *dst;
+      bfd_vma value;
+
+      value = result.value + result.section->bfd_section->vma;
+      dst = assignment->exp->assign.dst;
+
+      minfo ("0x%V", value);
+      if (dst[0] == '.' && dst[1] == 0)
+       print_dot = value;
+    }
   else
     {
       minfo ("*undef*   ");
@@ -2157,7 +2349,7 @@ print_input_statement (statm)
 /* Print all symbols defined in a particular section.  This is called
    via bfd_link_hash_traverse.  */
 
-static boolean
+static bfd_boolean
 print_one_symbol (hash_entry, ptr)
      struct bfd_link_hash_entry *hash_entry;
      PTR ptr;
@@ -2180,7 +2372,7 @@ print_one_symbol (hash_entry, ptr)
       minfo ("             %T\n", hash_entry->root.string);
     }
 
-  return true;
+  return TRUE;
 }
 
 /* Print information about an input section to the map file.  */
@@ -2247,7 +2439,12 @@ static void
 print_fill_statement (fill)
      lang_fill_statement_type *fill;
 {
-  fprintf (config.map_file, " FILL mask 0x%x\n", fill->fill);
+  size_t size;
+  unsigned char *p;
+  fputs (" FILL mask 0x", config.map_file);
+  for (p = fill->fill->data, size = fill->fill->size; size != 0; p++, size--)
+    fprintf (config.map_file, "%02x", *p);
+  fputs ("\n", config.map_file);
 }
 
 static void
@@ -2376,10 +2573,15 @@ print_padding_statement (s)
   addr = s->output_offset;
   if (s->output_section != NULL)
     addr += s->output_section->vma;
-  minfo ("0x%V %W", addr, s->size);
+  minfo ("0x%V %W ", addr, s->size);
 
-  if (s->fill != 0)
-    minfo (" %u", s->fill);
+  if (s->fill->size != 0)
+    {
+      size_t size;
+      unsigned char *p;
+      for (p = s->fill->data, size = s->fill->size; size != 0; p++, size--)
+       fprintf (config.map_file, "%02x", *p);
+    }
 
   print_nl ();
 
@@ -2391,18 +2593,12 @@ print_wild_statement (w, os)
      lang_wild_statement_type *w;
      lang_output_section_statement_type *os;
 {
+  struct wildcard_list *sec;
+
   print_space ();
 
   if (w->filenames_sorted)
     minfo ("SORT(");
-  if (w->exclude_filename_list != NULL)
-    {
-      name_list *tmp;
-      minfo ("EXCLUDE_FILE ( %s", w->exclude_filename_list->name);
-      for (tmp = w->exclude_filename_list->next; tmp; tmp = tmp->next)
-       minfo (", %s", tmp->name);
-      minfo (")");
-    }
   if (w->filename != NULL)
     minfo ("%s", w->filename);
   else
@@ -2411,14 +2607,27 @@ print_wild_statement (w, os)
     minfo (")");
 
   minfo ("(");
-  if (w->sections_sorted)
-    minfo ("SORT(");
-  if (w->section_name != NULL)
-    minfo ("%s", w->section_name);
-  else
-    minfo ("*");
-  if (w->sections_sorted)
-    minfo (")");
+  for (sec = w->section_list; sec; sec = sec->next)
+    {
+      if (sec->spec.sorted)
+       minfo ("SORT(");
+      if (sec->spec.exclude_name_list != NULL)
+       {
+         name_list *tmp;
+         minfo ("EXCLUDE_FILE(%s", sec->spec.exclude_name_list->name);
+         for (tmp = sec->spec.exclude_name_list->next; tmp; tmp = tmp->next)
+           minfo (" %s", tmp->name);
+         minfo (") ");
+       }
+      if (sec->spec.name != NULL)
+       minfo ("%s", sec->spec.name);
+      else
+       minfo ("*");
+      if (sec->spec.sorted)
+       minfo (")");
+      if (sec->next)
+       minfo (" ");
+    }
   minfo (")");
 
   print_nl ();
@@ -2449,7 +2658,7 @@ print_statement_list (s, os)
   while (s != NULL)
     {
       print_statement (s, os);
-      s = s->next;
+      s = s->header.next;
     }
 }
 
@@ -2555,94 +2764,100 @@ dprint_statement (s, n)
       while (s && --n >= 0)
        {
          print_statement (s, abs_output_section);
-         s = s->next;
+         s = s->header.next;
        }
     }
 
   config.map_file = map_save;
 }
 
-static bfd_vma
-insert_pad (this_ptr, fill, power, output_section_statement, dot)
-     lang_statement_union_type **this_ptr;
-     fill_type fill;
-     unsigned int power;
-     asection *output_section_statement;
+static void
+insert_pad (ptr, fill, alignment_needed, output_section, dot)
+     lang_statement_union_type **ptr;
+     fill_type *fill;
+     unsigned int alignment_needed;
+     asection *output_section;
      bfd_vma dot;
 {
-  /* Align this section first to the
-     input sections requirement, then
-     to the output section's requirement.
-     If this alignment is > than any seen before,
-     then record it too. Perform the alignment by
-     inserting a magic 'padding' statement.  */
-
-  unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture,
-                                               ldfile_output_machine);
-  unsigned int alignment_needed = align_power (dot, power) - dot;
-
-  if (alignment_needed != 0)
+  static fill_type zero_fill = { 1, { 0 } };
+  lang_statement_union_type *pad;
+
+  pad = ((lang_statement_union_type *)
+        ((char *) ptr - offsetof (lang_statement_union_type, header.next)));
+  if (ptr != &statement_list.head
+      && pad->header.type == lang_padding_statement_enum
+      && pad->padding_statement.output_section == output_section)
     {
-      lang_statement_union_type *new =
-       ((lang_statement_union_type *)
-        stat_alloc (sizeof (lang_padding_statement_type)));
-
-      /* Link into existing chain.  */
-      new->header.next = *this_ptr;
-      *this_ptr = new;
-      new->header.type = lang_padding_statement_enum;
-      new->padding_statement.output_section = output_section_statement;
-      new->padding_statement.output_offset =
-       dot - output_section_statement->vma;
-      new->padding_statement.fill = fill;
-      new->padding_statement.size = alignment_needed * opb;
+      /* Use the existing pad statement.  The above test on output
+        section is probably redundant, but it doesn't hurt to check.  */
     }
-
-  /* Remember the most restrictive alignment.  */
-  if (power > output_section_statement->alignment_power)
+  else
     {
-      output_section_statement->alignment_power = power;
+      /* Make a new padding statement, linked into existing chain.  */
+      pad = ((lang_statement_union_type *)
+            stat_alloc (sizeof (lang_padding_statement_type)));
+      pad->header.next = *ptr;
+      *ptr = pad;
+      pad->header.type = lang_padding_statement_enum;
+      pad->padding_statement.output_section = output_section;
+      if (fill == (fill_type *) 0)
+       fill = &zero_fill;
+      pad->padding_statement.fill = fill;
     }
-  output_section_statement->_raw_size += alignment_needed * opb;
-
-  return dot + alignment_needed;
+  pad->padding_statement.output_offset = dot - output_section->vma;
+  pad->padding_statement.size = alignment_needed;
+  output_section->_raw_size += alignment_needed;
 }
 
 /* Work out how much this section will move the dot point.  */
 
 static bfd_vma
-size_input_section (this_ptr, output_section_statement, fill, dot, relax)
+size_input_section (this_ptr, output_section_statement, fill, dot)
      lang_statement_union_type **this_ptr;
      lang_output_section_statement_type *output_section_statement;
-     fill_type fill;
+     fill_type *fill;
      bfd_vma dot;
-     boolean relax ATTRIBUTE_UNUSED;
 {
   lang_input_section_type *is = &((*this_ptr)->input_section);
   asection *i = is->section;
-  unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture,
-                                               ldfile_output_machine);
 
-  if (is->ifile->just_syms_flag == false)
+  if (!is->ifile->just_syms_flag)
     {
+      unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture,
+                                                   ldfile_output_machine);
+      unsigned int alignment_needed;
+      asection *o;
+
+      /* Align this section first to the input sections requirement,
+        then to the output section's requirement.  If this alignment
+        is greater than any seen before, then record it too.  Perform
+        the alignment by inserting a magic 'padding' statement.  */
+
       if (output_section_statement->subsection_alignment != -1)
-       i->alignment_power =
-       output_section_statement->subsection_alignment;
+       i->alignment_power = output_section_statement->subsection_alignment;
 
-      dot = insert_pad (this_ptr, fill, i->alignment_power,
-                       output_section_statement->bfd_section, dot);
+      o = output_section_statement->bfd_section;
+      if (o->alignment_power < i->alignment_power)
+       o->alignment_power = i->alignment_power;
+
+      alignment_needed = align_power (dot, i->alignment_power) - dot;
+
+      if (alignment_needed != 0)
+       {
+         insert_pad (this_ptr, fill, alignment_needed * opb, o, dot);
+         dot += alignment_needed;
+       }
 
       /* Remember where in the output section this input section goes.  */
 
-      i->output_offset = dot - output_section_statement->bfd_section->vma;
+      i->output_offset = dot - o->vma;
 
       /* Mark how big the output section must be to contain this now.  */
       if (i->_cooked_size != 0)
        dot += i->_cooked_size / opb;
       else
        dot += i->_raw_size / opb;
-      output_section_statement->bfd_section->_raw_size =
-       (dot - output_section_statement->bfd_section->vma) * opb;
+      o->_raw_size = (dot - o->vma) * opb;
     }
   else
     {
@@ -2653,7 +2868,8 @@ size_input_section (this_ptr, output_section_statement, fill, dot, relax)
 }
 
 #define IGNORE_SECTION(bfd, s) \
-  (((bfd_get_section_flags (bfd, s) & (SEC_ALLOC | SEC_LOAD)) != (SEC_ALLOC | SEC_LOAD)) \
+  (((bfd_get_section_flags (bfd, s) & (SEC_ALLOC | SEC_LOAD))  \
+    != (SEC_ALLOC | SEC_LOAD))                                 \
    || bfd_section_size (bfd, s) == 0)
 
 /* Check to see if any allocated sections overlap with other allocated
@@ -2712,11 +2928,6 @@ _("%X%P: section %s [%V -> %V] overlaps section %s [%V -> %V]\n"),
     }
 }
 
-/* This variable indicates whether bfd_relax_section should be called
-   again.  */
-
-static boolean relax_again;
-
 /* Make sure the new address is within the region.  We explicitly permit the
    current address to be at the exact end of the region when the address is
    non-zero, in case the region is at the end of addressable memory and the
@@ -2732,23 +2943,23 @@ os_region_check (os, region, tree, base)
   if ((region->current < region->origin
        || (region->current - region->origin > region->length))
       && ((region->current != region->origin + region->length)
-           || base == 0))
+         || base == 0))
     {
       if (tree != (etree_type *) NULL)
-        {
-          einfo (_("%X%P: address 0x%v of %B section %s is not within region %s\n"),
-                 region->current,
-                 os->bfd_section->owner,
-                 os->bfd_section->name,
-                 region->name);
-        }
+       {
+         einfo (_("%X%P: address 0x%v of %B section %s is not within region %s\n"),
+                region->current,
+                os->bfd_section->owner,
+                os->bfd_section->name,
+                region->name);
+       }
       else
-        {
-          einfo (_("%X%P: region %s is full (%B section %s)\n"),
-                 region->name,
-                 os->bfd_section->owner,
-                 os->bfd_section->name);
-        }
+       {
+         einfo (_("%X%P: region %s is full (%B section %s)\n"),
+                region->name,
+                os->bfd_section->owner,
+                os->bfd_section->name);
+       }
       /* Reset the region pointer.  */
       region->current = region->origin;
     }
@@ -2756,28 +2967,29 @@ os_region_check (os, region, tree, base)
 
 /* Set the sizes for all the output sections.  */
 
-bfd_vma
-lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
+static bfd_vma
+lang_size_sections_1 (s, output_section_statement, prev, fill, dot, relax)
      lang_statement_union_type *s;
      lang_output_section_statement_type *output_section_statement;
      lang_statement_union_type **prev;
-     fill_type fill;
+     fill_type *fill;
      bfd_vma dot;
-     boolean relax;
+     bfd_boolean *relax;
 {
   unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture,
                                                ldfile_output_machine);
 
   /* Size up the sections from their constituent parts.  */
-  for (; s != (lang_statement_union_type *) NULL; s = s->next)
+  for (; s != (lang_statement_union_type *) NULL; s = s->header.next)
     {
       switch (s->header.type)
        {
        case lang_output_section_statement_enum:
          {
            bfd_vma after;
-           lang_output_section_statement_type *os = &s->output_section_statement;
+           lang_output_section_statement_type *os;
 
+           os = &s->output_section_statement;
            if (os->bfd_section == NULL)
              /* This section was never actually created.  */
              break;
@@ -2791,7 +3003,7 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
                asection *input;
 
                if (os->children.head == NULL
-                   || os->children.head->next != NULL
+                   || os->children.head->header.next != NULL
                    || os->children.head->header.type != lang_input_section_enum)
                  einfo (_("%P%X: Internal error on COFF shared library section %s\n"),
                         os->name);
@@ -2829,13 +3041,17 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
                       defined, issue a warning.  */
                    if ((bfd_get_section_flags (output_bfd, os->bfd_section)
                         & (SEC_ALLOC | SEC_LOAD)) != 0
+                       && (bfd_get_section_flags (output_bfd, os->bfd_section)
+                           & SEC_NEVER_LOAD) == 0
                        && ! link_info.relocateable
                        && strcmp (os->region->name, "*default*") == 0
                        && lang_memory_region_list != NULL
-                       && (strcmp (lang_memory_region_list->name, "*default*") != 0
+                       && (strcmp (lang_memory_region_list->name,
+                                   "*default*") != 0
                            || lang_memory_region_list->next != NULL))
                      einfo (_("%P: warning: no memory region specified for section `%s'\n"),
-                            bfd_get_section_name (output_bfd, os->bfd_section));
+                            bfd_get_section_name (output_bfd,
+                                                  os->bfd_section));
 
                    dot = os->region->current;
 
@@ -2844,7 +3060,8 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
                        bfd_vma olddot;
 
                        olddot = dot;
-                       dot = align_power (dot, os->bfd_section->alignment_power);
+                       dot = align_power (dot,
+                                          os->bfd_section->alignment_power);
 
                        if (dot != olddot && config.warn_section_align)
                          einfo (_("%P: warning: changing start of section %s by %u bytes\n"),
@@ -2859,11 +3076,10 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
                                       abs_output_section,
                                       lang_allocating_phase_enum,
                                       dot, &dot);
-                   if (r.valid_p == false)
-                     {
-                       einfo (_("%F%S: non constant address expression for section %s\n"),
-                              os->name);
-                     }
+                   if (!r.valid_p)
+                     einfo (_("%F%S: non constant address expression for section %s\n"),
+                            os->name);
+
                    dot = r.value + r.section->bfd_section->vma;
                  }
 
@@ -2878,24 +3094,31 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
                os->bfd_section->output_offset = 0;
              }
 
-           (void) lang_size_sections (os->children.head, os,
-                                      &os->children.head,
-                                      os->fill, dot, relax);
+           lang_size_sections_1 (os->children.head, os, &os->children.head,
+                                 os->fill, dot, relax);
 
            /* Put the section within the requested block size, or
               align at the block boundary.  */
-           after = ALIGN_N (os->bfd_section->vma
+           after = align_n (os->bfd_section->vma
                             + os->bfd_section->_raw_size / opb,
-                            /* The coercion here is important, see ld.h.  */
                             (bfd_vma) os->block_value);
 
            if (bfd_is_abs_section (os->bfd_section))
              ASSERT (after == os->bfd_section->vma);
+           else if ((os->bfd_section->flags & SEC_HAS_CONTENTS) == 0
+                    && (os->bfd_section->flags & SEC_THREAD_LOCAL)
+                    && ! link_info.relocateable)
+             os->bfd_section->_raw_size = 0;
            else
              os->bfd_section->_raw_size =
                (after - os->bfd_section->vma) * opb;
+
            dot = os->bfd_section->vma + os->bfd_section->_raw_size / opb;
-           os->processed = true;
+           os->processed = TRUE;
+
+           if (os->update_dot_tree != 0)
+             exp_fold_tree (os->update_dot_tree, abs_output_section,
+                            lang_allocating_phase_enum, dot, &dot);
 
            /* Update dot in the region ?
               We only do this if the section is going to be allocated,
@@ -2922,37 +3145,24 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
                if (os->lma_region == NULL && os->load_base == NULL)
                  os->lma_region = os->region;
 
-               if (os->lma_region != NULL)
+               if (os->lma_region != NULL && os->lma_region != os->region)
                  {
-                   if (os->load_base != NULL)
-                     {
-                       einfo (_("%X%P: use an absolute load address or a load memory region, not both\n"));
-                     }
-                   else
-                     {
-                       /* Don't allocate twice.  */
-                       if (os->lma_region != os->region)
-                         {
-                           /* Set load_base, which will be handled later.  */
-                           os->load_base =
-                             exp_intop (os->lma_region->current);
-                           os->lma_region->current +=
-                             os->bfd_section->_raw_size / opb;
-                           os_region_check (os, os->lma_region, NULL,
-                                            os->bfd_section->lma);
-                         }
-                     }
+                   /* Set load_base, which will be handled later.  */
+                   os->load_base = exp_intop (os->lma_region->current);
+                   os->lma_region->current +=
+                     os->bfd_section->_raw_size / opb;
+                   os_region_check (os, os->lma_region, NULL,
+                                    os->bfd_section->lma);
                  }
              }
          }
          break;
 
        case lang_constructors_statement_enum:
-         dot = lang_size_sections (constructor_list.head,
-                                   output_section_statement,
-                                   &s->wild_statement.children.head,
-                                   fill,
-                                   dot, relax);
+         dot = lang_size_sections_1 (constructor_list.head,
+                                     output_section_statement,
+                                     &s->wild_statement.children.head,
+                                     fill, dot, relax);
          break;
 
        case lang_data_statement_enum:
@@ -3013,10 +3223,10 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
 
        case lang_wild_statement_enum:
 
-         dot = lang_size_sections (s->wild_statement.children.head,
-                                   output_section_statement,
-                                   &s->wild_statement.children.head,
-                                   fill, dot, relax);
+         dot = lang_size_sections_1 (s->wild_statement.children.head,
+                                     output_section_statement,
+                                     &s->wild_statement.children.head,
+                                     fill, dot, relax);
 
          break;
 
@@ -3039,17 +3249,15 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
              }
            else
              {
-               boolean again;
+               bfd_boolean again;
 
                if (! bfd_relax_section (i->owner, i, &link_info, &again))
                  einfo (_("%P%F: can't relax section: %E\n"));
                if (again)
-                 relax_again = true;
+                 *relax = TRUE;
              }
-           dot = size_input_section (prev,
-                                     output_section_statement,
-                                     output_section_statement->fill,
-                                     dot, relax);
+           dot = size_input_section (prev, output_section_statement,
+                                     output_section_statement->fill, dot);
          }
          break;
        case lang_input_statement_enum:
@@ -3072,31 +3280,22 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
 
            if (newdot != dot)
              {
-               /* The assignment changed dot.  Insert a pad.  */
                if (output_section_statement == abs_output_section)
                  {
                    /* If we don't have an output section, then just adjust
                       the default memory address.  */
                    lang_memory_region_lookup ("*default*")->current = newdot;
                  }
-               else if (!relax)
+               else
                  {
-                   lang_statement_union_type *new =
-                     ((lang_statement_union_type *)
-                      stat_alloc (sizeof (lang_padding_statement_type)));
-
-                   /* Link into existing chain.  */
-                   new->header.next = *prev;
-                   *prev = new;
-                   new->header.type = lang_padding_statement_enum;
-                   new->padding_statement.output_section =
-                     output_section_statement->bfd_section;
-                   new->padding_statement.output_offset =
-                     dot - output_section_statement->bfd_section->vma;
-                   new->padding_statement.fill = fill;
-                   new->padding_statement.size = (newdot - dot) * opb;
-                   output_section_statement->bfd_section->_raw_size +=
-                     new->padding_statement.size;
+                   /* Insert a pad after this statement.  We can't
+                      put the pad before when relaxing, in case the
+                      assignment references dot.  */
+                   insert_pad (&s->header.next, fill, (newdot - dot) * opb,
+                               output_section_statement->bfd_section, dot);
+
+                   /* Don't neuter the pad below when relaxing.  */
+                   s = s->header.next;
                  }
 
                dot = newdot;
@@ -3105,31 +3304,34 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
          break;
 
        case lang_padding_statement_enum:
-         /* If we are relaxing, and this is not the first pass, some
-            padding statements may have been inserted during previous
-            passes.  We may have to move the padding statement to a new
-            location if dot has a different value at this point in this
-            pass than it did at this point in the previous pass.  */
-         s->padding_statement.output_offset =
-           dot - output_section_statement->bfd_section->vma;
-         dot += s->padding_statement.size / opb;
-         output_section_statement->bfd_section->_raw_size +=
-           s->padding_statement.size;
+         /* If this is the first time lang_size_sections is called,
+            we won't have any padding statements.  If this is the
+            second or later passes when relaxing, we should allow
+            padding to shrink.  If padding is needed on this pass, it
+            will be added back in.  */
+         s->padding_statement.size = 0;
+
+         /* Make sure output_offset is valid.  If relaxation shrinks
+            the section and this pad isn't needed, it's possible to
+            have output_offset larger than the final size of the
+            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;
          break;
 
        case lang_group_statement_enum:
-         dot = lang_size_sections (s->group_statement.children.head,
-                                   output_section_statement,
-                                   &s->group_statement.children.head,
-                                   fill, dot, relax);
+         dot = lang_size_sections_1 (s->group_statement.children.head,
+                                     output_section_statement,
+                                     &s->group_statement.children.head,
+                                     fill, dot, relax);
          break;
 
        default:
          FAIL ();
          break;
 
-         /* This can only get here when relaxing is turned on.  */
-
+         /* We can only get here when relaxing is turned on.  */
        case lang_address_statement_enum:
          break;
        }
@@ -3138,17 +3340,53 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
   return dot;
 }
 
+bfd_vma
+lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
+     lang_statement_union_type *s;
+     lang_output_section_statement_type *output_section_statement;
+     lang_statement_union_type **prev;
+     fill_type *fill;
+     bfd_vma dot;
+     bfd_boolean *relax;
+{
+  bfd_vma result;
+
+  exp_data_seg.phase = exp_dataseg_none;
+  result = lang_size_sections_1 (s, output_section_statement, prev, fill,
+                                dot, relax);
+  if (exp_data_seg.phase == exp_dataseg_end_seen)
+    {
+      /* If DATA_SEGMENT_ALIGN DATA_SEGMENT_END pair was seen, check whether
+        a page could be saved in the data segment.  */
+      bfd_vma first, last;
+
+      first = -exp_data_seg.base & (exp_data_seg.pagesize - 1);
+      last = exp_data_seg.end & (exp_data_seg.pagesize - 1);
+      if (first && last
+         && ((exp_data_seg.base & ~(exp_data_seg.pagesize - 1))
+             != (exp_data_seg.end & ~(exp_data_seg.pagesize - 1)))
+         && first + last <= exp_data_seg.pagesize)
+       {
+         exp_data_seg.phase = exp_dataseg_adjust;
+         result = lang_size_sections_1 (s, output_section_statement, prev,
+                                        fill, dot, relax);
+       }
+    }
+
+  return result;
+}
+
 bfd_vma
 lang_do_assignments (s, output_section_statement, fill, dot)
      lang_statement_union_type *s;
      lang_output_section_statement_type *output_section_statement;
-     fill_type fill;
+     fill_type *fill;
      bfd_vma dot;
 {
   unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture,
                                                ldfile_output_machine);
 
-  for (; s != (lang_statement_union_type *) NULL; s = s->next)
+  for (; s != (lang_statement_union_type *) NULL; s = s->header.next)
     {
       switch (s->header.type)
        {
@@ -3161,9 +3399,9 @@ lang_do_assignments (s, output_section_statement, fill, dot)
 
        case lang_output_section_statement_enum:
          {
-           lang_output_section_statement_type *os =
-             &(s->output_section_statement);
+           lang_output_section_statement_type *os;
 
+           os = &(s->output_section_statement);
            if (os->bfd_section != NULL)
              {
                dot = os->bfd_section->vma;
@@ -3208,11 +3446,11 @@ lang_do_assignments (s, output_section_statement, fill, dot)
                                   abs_output_section,
                                   lang_final_phase_enum, dot, &dot);
            s->data_statement.value = value.value;
-           if (value.valid_p == false)
+           if (!value.valid_p)
              einfo (_("%F%P: invalid data statement\n"));
          }
-          {
-            unsigned int size;
+         {
+           unsigned int size;
            switch (s->data_statement.type)
              {
              default:
@@ -3245,7 +3483,7 @@ lang_do_assignments (s, output_section_statement, fill, dot)
                                   abs_output_section,
                                   lang_final_phase_enum, dot, &dot);
            s->reloc_statement.addend_value = value.value;
-           if (value.valid_p == false)
+           if (!value.valid_p)
              einfo (_("%F%P: invalid reloc statement\n"));
          }
          dot += bfd_get_reloc_size (s->reloc_statement.howto) / opb;
@@ -3324,7 +3562,7 @@ lang_set_startof ()
       buf = xmalloc (10 + strlen (secname));
 
       sprintf (buf, ".startof.%s", secname);
-      h = bfd_link_hash_lookup (link_info.hash, buf, false, false, true);
+      h = bfd_link_hash_lookup (link_info.hash, buf, FALSE, FALSE, TRUE);
       if (h != NULL && h->type == bfd_link_hash_undefined)
        {
          h->type = bfd_link_hash_defined;
@@ -3333,11 +3571,13 @@ lang_set_startof ()
        }
 
       sprintf (buf, ".sizeof.%s", secname);
-      h = bfd_link_hash_lookup (link_info.hash, buf, false, false, true);
+      h = bfd_link_hash_lookup (link_info.hash, buf, FALSE, FALSE, TRUE);
       if (h != NULL && h->type == bfd_link_hash_undefined)
        {
-          unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture,
-                                                       ldfile_output_machine);
+         unsigned opb;
+
+         opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture,
+                                              ldfile_output_machine);
          h->type = bfd_link_hash_defined;
          if (s->_cooked_size != 0)
            h->u.def.value = s->_cooked_size / opb;
@@ -3354,22 +3594,23 @@ static void
 lang_finish ()
 {
   struct bfd_link_hash_entry *h;
-  boolean warn;
+  bfd_boolean warn;
 
   if (link_info.relocateable || link_info.shared)
-    warn = false;
+    warn = FALSE;
   else
-    warn = true;
+    warn = TRUE;
 
-  if (entry_symbol == (char *) NULL)
+  if (entry_symbol.name == (const char *) NULL)
     {
       /* No entry has been specified.  Look for start, but don't warn
         if we don't find it.  */
-      entry_symbol = "start";
-      warn = false;
+      entry_symbol.name = "start";
+      warn = FALSE;
     }
 
-  h = bfd_link_hash_lookup (link_info.hash, entry_symbol, false, false, true);
+  h = bfd_link_hash_lookup (link_info.hash, entry_symbol.name,
+                           FALSE, FALSE, TRUE);
   if (h != (struct bfd_link_hash_entry *) NULL
       && (h->type == bfd_link_hash_defined
          || h->type == bfd_link_hash_defweak)
@@ -3382,7 +3623,7 @@ lang_finish ()
                                    h->u.def.section->output_section)
             + h->u.def.section->output_offset);
       if (! bfd_set_start_address (output_bfd, val))
-       einfo (_("%P%F:%s: can't set start address\n"), entry_symbol);
+       einfo (_("%P%F:%s: can't set start address\n"), entry_symbol.name);
     }
   else
     {
@@ -3391,7 +3632,7 @@ lang_finish ()
 
       /* We couldn't find the entry symbol.  Try parsing it as a
          number.  */
-      val = bfd_scan_vma (entry_symbol, &send, 0);
+      val = bfd_scan_vma (entry_symbol.name, &send, 0);
       if (*send == '\0')
        {
          if (! bfd_set_start_address (output_bfd, val))
@@ -3403,12 +3644,13 @@ lang_finish ()
 
          /* Can't find the entry symbol, and it's not a number.  Use
             the first address in the text section.  */
-         ts = bfd_get_section_by_name (output_bfd, ".text");
+         ts = bfd_get_section_by_name (output_bfd, entry_section);
          if (ts != (asection *) NULL)
            {
              if (warn)
                einfo (_("%P: warning: cannot find entry symbol %s; defaulting to %V\n"),
-                      entry_symbol, bfd_get_section_vma (output_bfd, ts));
+                      entry_symbol.name,
+                      bfd_get_section_vma (output_bfd, ts));
              if (! bfd_set_start_address (output_bfd,
                                           bfd_get_section_vma (output_bfd,
                                                                ts)))
@@ -3418,7 +3660,7 @@ lang_finish ()
            {
              if (warn)
                einfo (_("%P: warning: cannot find entry symbol %s; not setting start address\n"),
-                      entry_symbol);
+                      entry_symbol.name);
            }
        }
     }
@@ -3454,8 +3696,25 @@ lang_check ()
        file = file->input_statement.next)
     {
       input_bfd = file->input_statement.the_bfd;
-      compatible = bfd_arch_get_compatible (input_bfd,
-                                           output_bfd);
+      compatible = bfd_arch_get_compatible (input_bfd, output_bfd);
+
+      /* In general it is not possible to perform a relocatable
+        link between differing object formats when the input
+        file has relocations, because the relocations in the
+        input format may not have equivalent representations in
+        the output format (and besides BFD does not translate
+        relocs for other link purposes than a final link).  */
+      if ((link_info.relocateable || link_info.emitrelocations)
+         && (compatible == NULL
+             || bfd_get_flavour (input_bfd) != bfd_get_flavour (output_bfd))
+         && (bfd_get_file_flags (input_bfd) & HAS_RELOC) != 0)
+       {
+         einfo (_("%P%F: Relocatable linking with relocations from format %s (%B) to format %s (%B) is not supported\n"),
+                bfd_get_target (input_bfd), input_bfd,
+                bfd_get_target (output_bfd), output_bfd);
+         /* einfo with %F exits.  */
+       }
+
       if (compatible == NULL)
        {
          if (command_line.warn_mismatch)
@@ -3463,8 +3722,11 @@ lang_check ()
                   bfd_printable_name (input_bfd), input_bfd,
                   bfd_printable_name (output_bfd));
        }
-      else
+      else if (bfd_count_sections (input_bfd))
        {
+         /* If the input bfd has no contents, it shouldn't set the
+            private data of the output bfd.  */
+
          bfd_error_handler_type pfn = NULL;
 
          /* If we aren't supposed to warn about mismatched input
@@ -3493,6 +3755,8 @@ lang_check ()
 static void
 lang_common ()
 {
+  if (command_line.inhibit_common_definition)
+    return;
   if (link_info.relocateable
       && ! command_line.force_common_definition)
     return;
@@ -3511,7 +3775,7 @@ lang_common ()
 
 /* Place one common symbol in the correct section.  */
 
-static boolean
+static bfd_boolean
 lang_one_common (h, info)
      struct bfd_link_hash_entry *h;
      PTR info;
@@ -3523,20 +3787,20 @@ lang_one_common (h, info)
                                                ldfile_output_machine);
 
   if (h->type != bfd_link_hash_common)
-    return true;
+    return TRUE;
 
   size = h->u.c.size;
   power_of_two = h->u.c.p->alignment_power;
 
   if (config.sort_common
       && power_of_two < (unsigned int) *(int *) info)
-    return true;
+    return TRUE;
 
   section = h->u.c.p->section;
 
   /* Increase the size of the section.  */
-  section->_cooked_size = ALIGN_N ((section->_cooked_size + opb - 1) / opb,
-                                  (bfd_size_type) (1 << power_of_two)) * opb;
+  section->_cooked_size = align_n ((section->_cooked_size + opb - 1) / opb,
+                                  (bfd_vma) 1 << power_of_two) * opb;
 
   /* Adjust the alignment if necessary.  */
   if (power_of_two > section->alignment_power)
@@ -3557,7 +3821,7 @@ lang_one_common (h, info)
 
   if (config.map_file != NULL)
     {
-      static boolean header_printed;
+      static bfd_boolean header_printed;
       int len;
       char *name;
       char buf[50];
@@ -3566,7 +3830,7 @@ lang_one_common (h, info)
        {
          minfo (_("\nAllocating common symbols\n"));
          minfo (_("Common symbol       size              file\n\n"));
-         header_printed = true;
+         header_printed = TRUE;
        }
 
       name = demangle (h->root.string);
@@ -3602,7 +3866,7 @@ lang_one_common (h, info)
       minfo ("%B\n", section->owner);
     }
 
-  return true;
+  return TRUE;
 }
 
 /* Run through the input files and ensure that every input section has
@@ -3627,11 +3891,7 @@ lang_place_orphans ()
 
              if (file->just_syms_flag)
                {
-                 /* We are only retrieving symbol values from this
-                     file.  We want the symbols to act as though the
-                     values in the file are absolute.  */
-                 s->output_section = bfd_abs_section_ptr;
-                 s->output_offset = s->vma;
+                 abort ();
                }
              else if (strcmp (s->name, "COMMON") == 0)
                {
@@ -3653,18 +3913,18 @@ lang_place_orphans ()
                            lang_output_section_statement_lookup (".bss");
 
                        }
-                     wild_doit (&default_common_section->children, s,
-                                default_common_section, file);
+                     lang_add_section (&default_common_section->children, s,
+                                       default_common_section, file);
                    }
                }
              else if (ldemul_place_orphan (file, s))
                ;
              else
                {
-                 lang_output_section_statement_type *os =
-                 lang_output_section_statement_lookup (s->name);
+                 lang_output_section_statement_type *os;
 
-                 wild_doit (&os->children, s, os, file);
+                 os = lang_output_section_statement_lookup (s->name);
+                 lang_add_section (&os->children, s, os, file);
                }
            }
        }
@@ -3806,10 +4066,10 @@ lang_add_output (name, from_script)
      int from_script;
 {
   /* Make -o on command line override OUTPUT in script.  */
-  if (had_output_filename == false || !from_script)
+  if (!had_output_filename || !from_script)
     {
       output_filename = name;
-      had_output_filename = true;
+      had_output_filename = TRUE;
     }
 }
 
@@ -3892,10 +4152,11 @@ lang_final ()
 
 /* Reset the current counters in the regions.  */
 
-static void
-reset_memory_regions ()
+void
+lang_reset_memory_regions ()
 {
   lang_memory_region_type *p = lang_memory_region_list;
+  asection *o;
 
   for (p = lang_memory_region_list;
        p != (lang_memory_region_type *) NULL;
@@ -3904,34 +4165,33 @@ reset_memory_regions ()
       p->old_length = (bfd_size_type) (p->current - p->origin);
       p->current = p->origin;
     }
+
+  for (o = output_bfd->sections; o != NULL; o = o->next)
+    o->_raw_size = 0;
 }
 
-/* Expand a wild statement for a particular FILE, marking its sections KEEP
-   as needed.  SECTION may be NULL, in which case it is a wild card.  */
+/* If the wild pattern was marked KEEP, the member sections
+   should be as well.  */
 
 static void
-gc_section_callback (ptr, section, file, data)
+gc_section_callback (ptr, sec, section, file, data)
      lang_wild_statement_type *ptr;
+     struct wildcard_list *sec ATTRIBUTE_UNUSED;
      asection *section;
      lang_input_statement_type *file ATTRIBUTE_UNUSED;
      PTR data ATTRIBUTE_UNUSED;
 {
-  /* If the wild pattern was marked KEEP, the member sections
-     should be as well.  */
   if (ptr->keep_sections)
     section->flags |= SEC_KEEP;
 }
 
-/* Handle a wild statement, marking it against GC.  SECTION or FILE or both
-   may be NULL, indicating that it is a wildcard.  */
+/* Handle a wild statement, marking it against GC.  */
 
 static void
-lang_gc_wild (s, section, file)
+lang_gc_wild (s)
      lang_wild_statement_type *s;
-     const char *section;
-     const char *file;
 {
-  walk_wild (s, section, file, gc_section_callback, NULL);
+  walk_wild (s, gc_section_callback, NULL);
 }
 
 /* Iterate over sections marking them against GC.  */
@@ -3940,14 +4200,12 @@ static void
 lang_gc_sections_1 (s)
      lang_statement_union_type *s;
 {
-  for (; s != (lang_statement_union_type *) NULL; s = s->next)
+  for (; s != (lang_statement_union_type *) NULL; s = s->header.next)
     {
       switch (s->header.type)
        {
        case lang_wild_statement_enum:
-         lang_gc_wild (&s->wild_statement,
-                       s->wild_statement.section_name,
-                       s->wild_statement.filename);
+         lang_gc_wild (&s->wild_statement);
          break;
        case lang_constructors_statement_enum:
          lang_gc_sections_1 (constructor_list.head);
@@ -3968,28 +4226,19 @@ static void
 lang_gc_sections ()
 {
   struct bfd_link_hash_entry *h;
-  ldlang_undef_chain_list_type *ulist, fake_list_start;
+  ldlang_undef_chain_list_type *ulist;
 
   /* Keep all sections so marked in the link script.  */
 
   lang_gc_sections_1 (statement_list.head);
 
-  /* Keep all sections containing symbols undefined on the command-line.
-     Handle the entry symbol at the same time.  */
-
-  if (entry_symbol != NULL)
-    {
-      fake_list_start.next = ldlang_undef_chain_list_head;
-      fake_list_start.name = (char *) entry_symbol;
-      ulist = &fake_list_start;
-    }
-  else
-    ulist = ldlang_undef_chain_list_head;
+  /* Keep all sections containing symbols undefined on the command-line,
+     and the section containing the entry symbol.  */
 
-  for (; ulist; ulist = ulist->next)
+  for (ulist = link_info.gc_sym_list; ulist; ulist = ulist->next)
     {
       h = bfd_link_hash_lookup (link_info.hash, ulist->name,
-                               false, false, false);
+                               FALSE, FALSE, FALSE);
 
       if (h != (struct bfd_link_hash_entry *) NULL
          && (h->type == bfd_link_hash_defined
@@ -4021,7 +4270,11 @@ lang_process ()
 
   /* Create a bfd for each input file.  */
   current_target = default_target;
-  open_input_bfds (statement_list.head, false);
+  open_input_bfds (statement_list.head, FALSE);
+
+  link_info.gc_sym_list = &entry_symbol;
+  if (entry_symbol.name == NULL)
+    link_info.gc_sym_list = ldlang_undef_chain_list_head;
 
   ldemul_after_open ();
 
@@ -4046,6 +4299,12 @@ lang_process ()
   if (command_line.gc_sections)
     lang_gc_sections ();
 
+  /* If there were any SEC_MERGE sections, finish their merging, so that
+     section sizes can be computed.  This has to be done after GC of sections,
+     so that GCed sections are not merged, but before assigning output
+     sections, since removing whole input sections is hard then.  */
+  bfd_merge_sections (output_bfd, &link_info);
+
   /* Size up the common data.  */
   lang_common ();
 
@@ -4057,27 +4316,47 @@ lang_process ()
   /* Find any sections not attached explicitly and handle them.  */
   lang_place_orphans ();
 
+  if (! link_info.relocateable)
+    {
+      /* Look for a text section and set the readonly attribute in it.  */
+      asection *found = bfd_get_section_by_name (output_bfd, ".text");
+
+      if (found != (asection *) NULL)
+       {
+         if (config.text_read_only)
+           found->flags |= SEC_READONLY;
+         else
+           found->flags &= ~SEC_READONLY;
+       }
+    }
+
+  /* Do anything special before sizing sections.  This is where ELF
+     and other back-ends size dynamic sections.  */
   ldemul_before_allocation ();
 
+  if (!link_info.relocateable)
+    strip_excluded_output_sections ();
+
   /* We must record the program headers before we try to fix the
      section positions, since they will affect SIZEOF_HEADERS.  */
   lang_record_phdrs ();
 
+  /* Size up the sections.  */
+  lang_size_sections (statement_list.head,
+                     abs_output_section,
+                     &statement_list.head, 0, (bfd_vma) 0, NULL);
+
   /* Now run around and relax if we can.  */
   if (command_line.relax)
     {
-      /* First time round is a trial run to get the 'worst case'
-        addresses of the objects if there was no relaxing.  */
-      lang_size_sections (statement_list.head,
-                         abs_output_section,
-                         &(statement_list.head), 0, (bfd_vma) 0, false);
-
       /* Keep relaxing until bfd_relax_section gives up.  */
+      bfd_boolean relax_again;
+
       do
        {
-         reset_memory_regions ();
+         lang_reset_memory_regions ();
 
-         relax_again = false;
+         relax_again = FALSE;
 
          /* Note: pe-dll.c does something like this also.  If you find
             you need to change this code, you probably need to change
@@ -4087,23 +4366,17 @@ lang_process ()
             section sizes.  */
          lang_do_assignments (statement_list.head,
                               abs_output_section,
-                              (fill_type) 0, (bfd_vma) 0);
+                              (fill_type *) 0, (bfd_vma) 0);
 
          /* Perform another relax pass - this time we know where the
-            globals are, so can make better guess.  */
+            globals are, so can make better guess.  */
          lang_size_sections (statement_list.head,
                              abs_output_section,
-                             &(statement_list.head), 0, (bfd_vma) 0, true);
+                             &statement_list.head, 0, (bfd_vma) 0,
+                             &relax_again);
        }
       while (relax_again);
     }
-  else
-    {
-      /* Size up the sections.  */
-      lang_size_sections (statement_list.head,
-                         abs_output_section,
-                         &(statement_list.head), 0, (bfd_vma) 0, false);
-    }
 
   /* See if anything special should be done now we know how big
      everything is.  */
@@ -4117,7 +4390,7 @@ lang_process ()
 
   lang_do_assignments (statement_list.head,
                       abs_output_section,
-                      (fill_type) 0, (bfd_vma) 0);
+                      (fill_type *) 0, (bfd_vma) 0);
 
   /* Make sure that the section addresses make sense.  */
   if (! link_info.relocateable
@@ -4133,32 +4406,44 @@ lang_process ()
 /* EXPORTED TO YACC */
 
 void
-lang_add_wild (section_name, sections_sorted, filename, filenames_sorted,
-              keep_sections, exclude_filename_list)
-     const char *const section_name;
-     boolean sections_sorted;
-     const char *const filename;
-     boolean filenames_sorted;
-     boolean keep_sections;
-     struct name_list *exclude_filename_list;
-{
-  lang_wild_statement_type *new = new_stat (lang_wild_statement,
-                                           stat_ptr);
+lang_add_wild (filespec, section_list, keep_sections)
+     struct wildcard_spec *filespec;
+     struct wildcard_list *section_list;
+     bfd_boolean keep_sections;
+{
+  struct wildcard_list *curr, *next;
+  lang_wild_statement_type *new;
+
+  /* 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.name != NULL && strcmp (curr->spec.name, "COMMON") == 0)
+       placed_commons = TRUE;
+
+      next = curr->next;
+      curr->next = section_list;
+    }
 
-  if (section_name != (char *) NULL && strcmp (section_name, "COMMON") == 0)
+  if (filespec != NULL && filespec->name != NULL)
     {
-      placed_commons = true;
+      if (strcmp (filespec->name, "*") == 0)
+       filespec->name = NULL;
+      else if (! wildcardp (filespec->name))
+       lang_has_input_file = TRUE;
     }
-  if (filename != NULL && ! wildcardp (filename))
+
+  new = new_stat (lang_wild_statement, stat_ptr);
+  new->filename = NULL;
+  new->filenames_sorted = FALSE;
+  if (filespec != NULL)
     {
-      lang_has_input_file = true;
+      new->filename = filespec->name;
+      new->filenames_sorted = filespec->sorted;
     }
-  new->section_name = section_name;
-  new->sections_sorted = sections_sorted;
-  new->filename = filename;
-  new->filenames_sorted = filenames_sorted;
+  new->section_list = section_list;
   new->keep_sections = keep_sections;
-  new->exclude_filename_list = exclude_filename_list;
   lang_list_init (&new->children);
 }
 
@@ -4167,8 +4452,9 @@ lang_section_start (name, address)
      const char *name;
      etree_type *address;
 {
-  lang_address_statement_type *ad = new_stat (lang_address_statement, stat_ptr);
+  lang_address_statement_type *ad;
 
+  ad = new_stat (lang_address_statement, stat_ptr);
   ad->section_name = name;
   ad->address = address;
 }
@@ -4181,13 +4467,13 @@ lang_section_start (name, address)
 void
 lang_add_entry (name, cmdline)
      const char *name;
-     boolean cmdline;
+     bfd_boolean cmdline;
 {
-  if (entry_symbol == NULL
+  if (entry_symbol.name == NULL
       || cmdline
       || ! entry_from_cmdline)
     {
-      entry_symbol = name;
+      entry_symbol.name = name;
       entry_from_cmdline = cmdline;
     }
 }
@@ -4212,7 +4498,7 @@ lang_add_map (name)
       switch (*name)
        {
        case 'F':
-         map_option_f = true;
+         map_option_f = TRUE;
          break;
        }
       name++;
@@ -4220,13 +4506,13 @@ lang_add_map (name)
 }
 
 void
-lang_add_fill (exp)
-     int exp;
+lang_add_fill (fill)
+     fill_type *fill;
 {
   lang_fill_statement_type *new = new_stat (lang_fill_statement,
                                            stat_ptr);
 
-  new->fill = exp;
+  new->fill = fill;
 }
 
 void
@@ -4299,35 +4585,60 @@ lang_startup (name)
     }
   first_file->filename = name;
   first_file->local_sym_name = name;
-  first_file->real = true;
+  first_file->real = TRUE;
 
   startup_file = name;
 }
 
 void
 lang_float (maybe)
-     boolean maybe;
+     bfd_boolean maybe;
 {
   lang_float_flag = maybe;
 }
 
+
+/* Work out the load- and run-time regions from a script statement, and
+   store them in *LMA_REGION and *REGION respectively.
+
+   MEMSPEC is the name of the run-time region, or "*default*" if the
+   statement didn't specify one.  LMA_MEMSPEC is the name of the
+   load-time region, or null if the statement didn't specify one.
+   HAVE_LMA_P is TRUE if the statement had an explicit load address.
+
+   It is an error to specify both a load region and a load address.  */
+
+static void
+lang_get_regions (region, lma_region, memspec, lma_memspec, have_lma_p)
+     struct memory_region_struct **region, **lma_region;
+     const char *memspec, *lma_memspec;
+     int have_lma_p;
+{
+  *lma_region = lang_memory_region_lookup (lma_memspec);
+
+  /* If no runtime region has been given, but the load region has
+     been, use the load region.  */
+  if (lma_memspec != 0 && strcmp (memspec, "*default*") == 0)
+    *region = *lma_region;
+  else
+    *region = lang_memory_region_lookup (memspec);
+
+  if (have_lma_p && lma_memspec != 0)
+    einfo (_("%X%P:%S: section has both a load address and a load region\n"));
+}
+
 void
 lang_leave_output_section_statement (fill, memspec, phdrs, lma_memspec)
-     bfd_vma fill;
+     fill_type *fill;
      const char *memspec;
      struct lang_output_section_phdr_list *phdrs;
      const char *lma_memspec;
 {
+  lang_get_regions (&current_section->region,
+                   &current_section->lma_region,
+                   memspec, lma_memspec,
+                   current_section->load_base != 0);
   current_section->fill = fill;
-  current_section->region = lang_memory_region_lookup (memspec);
-  if (strcmp (lma_memspec, "*default*") != 0)
-    {
-      current_section->lma_region = lang_memory_region_lookup (lma_memspec);
-      /* If no runtime region has been given, but the load region has
-         been, use the load region.  */
-      if (strcmp (memspec, "*default*") == 0)
-        current_section->region = lang_memory_region_lookup (lma_memspec);
-    }
   current_section->phdrs = phdrs;
   stat_ptr = &statement_list;
 }
@@ -4344,7 +4655,7 @@ lang_abs_symbol_at_beginning_of (secname, name)
 {
   struct bfd_link_hash_entry *h;
 
-  h = bfd_link_hash_lookup (link_info.hash, name, true, true, true);
+  h = bfd_link_hash_lookup (link_info.hash, name, TRUE, TRUE, TRUE);
   if (h == (struct bfd_link_hash_entry *) NULL)
     einfo (_("%P%F: bfd_link_hash_lookup failed: %E\n"));
 
@@ -4377,7 +4688,7 @@ lang_abs_symbol_at_end_of (secname, name)
 {
   struct bfd_link_hash_entry *h;
 
-  h = bfd_link_hash_lookup (link_info.hash, name, true, true, true);
+  h = bfd_link_hash_lookup (link_info.hash, name, TRUE, TRUE, TRUE);
   if (h == (struct bfd_link_hash_entry *) NULL)
     einfo (_("%P%F: bfd_link_hash_lookup failed: %E\n"));
 
@@ -4463,8 +4774,8 @@ void
 lang_new_phdr (name, type, filehdr, phdrs, at, flags)
      const char *name;
      etree_type *type;
-     boolean filehdr;
-     boolean phdrs;
+     bfd_boolean filehdr;
+     bfd_boolean phdrs;
      etree_type *at;
      etree_type *flags;
 {
@@ -4543,7 +4854,7 @@ lang_record_phdrs ()
                    }
                  secs[c] = os->bfd_section;
                  ++c;
-                 pl->used = true;
+                 pl->used = TRUE;
                }
            }
        }
@@ -4561,9 +4872,7 @@ lang_record_phdrs ()
                          lang_final_phase_enum);
 
       if (! bfd_record_phdr (output_bfd, l->type,
-                            l->flags == NULL ? false : true,
-                            flags,
-                            l->at == NULL ? false : true,
+                            l->flags != NULL, flags, l->at != NULL,
                             at, l->filehdr, l->phdrs, c, secs))
        einfo (_("%F%P: bfd_record_phdr failed: %E\n"));
     }
@@ -4603,7 +4912,7 @@ lang_add_nocrossref (l)
   nocrossref_list = n;
 
   /* Set notice_all so that we get informed about all symbols.  */
-  link_info.notice_all = true;
+  link_info.notice_all = TRUE;
 }
 \f
 /* Overlay handling.  We handle overlays with some static variables.  */
@@ -4611,19 +4920,12 @@ lang_add_nocrossref (l)
 /* The overlay virtual address.  */
 static etree_type *overlay_vma;
 
-/* The overlay load address.  */
-static etree_type *overlay_lma;
-
-/* Whether nocrossrefs is set for this overlay.  */
-static int overlay_nocrossrefs;
-
 /* An expression for the maximum section size seen so far.  */
 static etree_type *overlay_max;
 
 /* A list of all the sections in this overlay.  */
 
-struct overlay_list
-{
+struct overlay_list {
   struct overlay_list *next;
   lang_output_section_statement_type *os;
 };
@@ -4633,24 +4935,18 @@ static struct overlay_list *overlay_list;
 /* Start handling an overlay.  */
 
 void
-lang_enter_overlay (vma_expr, lma_expr, nocrossrefs)
+lang_enter_overlay (vma_expr)
      etree_type *vma_expr;
-     etree_type *lma_expr;
-     int nocrossrefs;
 {
   /* The grammar should prevent nested overlays from occurring.  */
-  ASSERT (overlay_vma == NULL
-         && overlay_lma == NULL
-         && overlay_list == NULL
-         && overlay_max == NULL);
+  ASSERT (overlay_vma == NULL && overlay_max == NULL);
 
   overlay_vma = vma_expr;
-  overlay_lma = lma_expr;
-  overlay_nocrossrefs = nocrossrefs;
 }
 
 /* Start a section in an overlay.  We handle this by calling
-   lang_enter_output_section_statement with the correct VMA and LMA.  */
+   lang_enter_output_section_statement with the correct VMA.
+   lang_leave_overlay sets up the LMA and memory regions.  */
 
 void
 lang_enter_overlay_section (name)
@@ -4660,16 +4956,13 @@ lang_enter_overlay_section (name)
   etree_type *size;
 
   lang_enter_output_section_statement (name, overlay_vma, normal_section,
-                                      0, 0, 0, overlay_lma);
+                                      0, 0, 0, 0);
 
-  /* If this is the first section, then base the VMA and LMA of future
+  /* If this is the first section, then base the VMA of future
      sections on this one.  This will work correctly even if `.' is
      used in the addresses.  */
   if (overlay_list == NULL)
-    {
-      overlay_vma = exp_nameop (ADDR, name);
-      overlay_lma = exp_nameop (LOADADDR, name);
-    }
+    overlay_vma = exp_nameop (ADDR, name);
 
   /* Remember the section.  */
   n = (struct overlay_list *) xmalloc (sizeof *n);
@@ -4679,9 +4972,6 @@ lang_enter_overlay_section (name)
 
   size = exp_nameop (SIZEOF, name);
 
-  /* Adjust the LMA for the next section.  */
-  overlay_lma = exp_binop ('+', overlay_lma, size);
-
   /* Arrange to work out the maximum section end address.  */
   if (overlay_max == NULL)
     overlay_max = size;
@@ -4694,7 +4984,7 @@ lang_enter_overlay_section (name)
 
 void
 lang_leave_overlay_section (fill, phdrs)
-     bfd_vma fill;
+     fill_type *fill;
      struct lang_output_section_phdr_list *phdrs;
 {
   const char *name;
@@ -4704,15 +4994,17 @@ lang_leave_overlay_section (fill, phdrs)
 
   name = current_section->name;
 
-  lang_leave_output_section_statement (fill, "*default*",
-                                       phdrs, "*default*");
+  /* For now, assume that "*default*" is the run-time memory region and
+     that no load-time region has been specified.  It doesn't really
+     matter what we say here, since lang_leave_overlay will override it.  */
+  lang_leave_output_section_statement (fill, "*default*", phdrs, 0);
 
   /* Define the magic symbols.  */
 
   clean = xmalloc (strlen (name) + 1);
   s2 = clean;
   for (s1 = name; *s1 != '\0'; s1++)
-    if (isalnum ((unsigned char) *s1) || *s1 == '_')
+    if (ISALNUM (*s1) || *s1 == '_')
       *s2++ = *s1;
   *s2 = '\0';
 
@@ -4735,8 +5027,10 @@ lang_leave_overlay_section (fill, phdrs)
    looks through all the sections in the overlay and sets them.  */
 
 void
-lang_leave_overlay (fill, memspec, phdrs, lma_memspec)
-     bfd_vma fill;
+lang_leave_overlay (lma_expr, nocrossrefs, fill, memspec, phdrs, lma_memspec)
+     etree_type *lma_expr;
+     int nocrossrefs;
+     fill_type *fill;
      const char *memspec;
      struct lang_output_section_phdr_list *phdrs;
      const char *lma_memspec;
@@ -4746,33 +5040,44 @@ lang_leave_overlay (fill, memspec, phdrs, lma_memspec)
   struct overlay_list *l;
   struct lang_nocrossref *nocrossref;
 
-  if (memspec == NULL)
-    region = NULL;
-  else
-    region = lang_memory_region_lookup (memspec);
-
-  if (lma_memspec == NULL)
-    lma_region = NULL;
-  else
-    lma_region = lang_memory_region_lookup (lma_memspec);
+  lang_get_regions (&region, &lma_region,
+                   memspec, lma_memspec,
+                   lma_expr != 0);
 
   nocrossref = NULL;
 
+  /* After setting the size of the last section, set '.' to end of the
+     overlay region.  */
+  if (overlay_list != NULL)
+    overlay_list->os->update_dot_tree
+      = exp_assop ('=', ".", exp_binop ('+', overlay_vma, overlay_max));
+
   l = overlay_list;
   while (l != NULL)
     {
       struct overlay_list *next;
 
-      if (fill != 0 && l->os->fill == 0)
+      if (fill != (fill_type *) 0 && l->os->fill == (fill_type *) 0)
        l->os->fill = fill;
-      if (region != NULL && l->os->region == NULL)
-       l->os->region = region;
-      if (lma_region != NULL && l->os->lma_region == NULL)
-       l->os->lma_region = lma_region;
+
+      l->os->region = region;
+      l->os->lma_region = lma_region;
+
+      /* The first section has the load address specified in the
+        OVERLAY statement.  The rest are worked out from that.
+        The base address is not needed (and should be null) if
+        an LMA region was specified.  */
+      if (l->next == 0)
+       l->os->load_base = lma_expr;
+      else if (lma_region == 0)
+       l->os->load_base = exp_binop ('+',
+                                     exp_nameop (LOADADDR, l->next->os->name),
+                                     exp_nameop (SIZEOF, l->next->os->name));
+
       if (phdrs != NULL && l->os->phdrs == NULL)
        l->os->phdrs = phdrs;
 
-      if (overlay_nocrossrefs)
+      if (nocrossrefs)
        {
          struct lang_nocrossref *nc;
 
@@ -4790,13 +5095,7 @@ lang_leave_overlay (fill, memspec, phdrs, lma_memspec)
   if (nocrossref != NULL)
     lang_add_nocrossref (nocrossref);
 
-  /* Update . for the end of the overlay.  */
-  lang_add_assignment (exp_assop ('=', ".",
-                                 exp_binop ('+', overlay_vma, overlay_max)));
-
   overlay_vma = NULL;
-  overlay_lma = NULL;
-  overlay_nocrossrefs = 0;
   overlay_list = NULL;
   overlay_max = NULL;
 }
@@ -4832,7 +5131,7 @@ lang_vers_match_lang_cplusplus (expr, sym)
   if (!alt_sym)
     {
       /* cplus_demangle (also) returns NULL when it is not a C++ symbol.
-        Should we early out false in this case?  */
+        Should we early out FALSE in this case?  */
       result = fnmatch (expr->pattern, sym, 0) == 0;
     }
   else
@@ -4859,7 +5158,7 @@ lang_vers_match_lang_java (expr, sym)
   if (!alt_sym)
     {
       /* cplus_demangle (also) returns NULL when it is not a Java symbol.
-        Should we early out false in this case?  */
+        Should we early out FALSE in this case?  */
       result = fnmatch (expr->pattern, sym, 0) == 0;
     }
   else
@@ -4874,7 +5173,7 @@ lang_vers_match_lang_java (expr, sym)
 /* This is called for each variable name or match expression.  */
 
 struct bfd_elf_version_expr *
-lang_new_vers_regex (orig, new, lang)
+lang_new_vers_pattern (orig, new, lang)
      struct bfd_elf_version_expr *orig;
      const char *new;
      const char *lang;
@@ -4884,6 +5183,8 @@ lang_new_vers_regex (orig, new, lang)
   ret = (struct bfd_elf_version_expr *) xmalloc (sizeof *ret);
   ret->next = orig;
   ret->pattern = new;
+  ret->symver = 0;
+  ret->script = 0;
 
   if (lang == NULL || strcasecmp (lang, "C") == 0)
     ret->match = lang_vers_match_lang_c;
@@ -4898,7 +5199,7 @@ lang_new_vers_regex (orig, new, lang)
       ret->match = lang_vers_match_lang_c;
     }
 
-  return ret;
+  return ldemul_new_vers_pattern (ret);
 }
 
 /* This is called for each set of variable names and match
@@ -4939,6 +5240,16 @@ lang_register_vers_node (name, version, deps)
   struct bfd_elf_version_tree *t, **pp;
   struct bfd_elf_version_expr *e1;
 
+  if (name == NULL)
+    name = "";
+
+  if ((name[0] == '\0' && lang_elf_version_info != NULL)
+      || (lang_elf_version_info && lang_elf_version_info->name[0] == '\0'))
+    {
+      einfo (_("%X%P: anonymous version tag cannot be combined with other version tags\n"));
+      return;
+    }
+
   /* Make sure this node has a unique name.  */
   for (t = lang_elf_version_info; t != NULL; t = t->next)
     if (strcmp (t->name, name) == 0)
@@ -4975,8 +5286,13 @@ lang_register_vers_node (name, version, deps)
 
   version->deps = deps;
   version->name = name;
-  ++version_index;
-  version->vernum = version_index;
+  if (name[0] != '\0')
+    {
+      ++version_index;
+      version->vernum = version_index;
+    }
+  else
+    version->vernum = 0;
 
   for (pp = &lang_elf_version_info; *pp != NULL; pp = &(*pp)->next)
     ;
@@ -5022,17 +5338,17 @@ lang_do_version_exports_section ()
       bfd_size_type len;
 
       if (sec == NULL)
-        continue;
+       continue;
 
       len = bfd_section_size (is->the_bfd, sec);
       contents = xmalloc (len);
       if (!bfd_get_section_contents (is->the_bfd, sec, contents, 0, len))
-       einfo (_("%X%P: unable to read .exports section contents"), sec);
+       einfo (_("%X%P: unable to read .exports section contents\n"), sec);
 
       p = contents;
-      while (p < contents+len)
+      while (p < contents + len)
        {
-         greg = lang_new_vers_regex (greg, p, NULL);
+         greg = lang_new_vers_pattern (greg, p, NULL);
          p = strchr (p, '\0') + 1;
        }
 
@@ -5043,7 +5359,23 @@ lang_do_version_exports_section ()
        bfd_get_section_flags (is->the_bfd, sec) | SEC_EXCLUDE);
     }
 
-  lreg = lang_new_vers_regex (NULL, "*", NULL);
+  lreg = lang_new_vers_pattern (NULL, "*", NULL);
   lang_register_vers_node (command_line.version_exports_section,
                           lang_new_vers_node (greg, lreg), NULL);
 }
+
+void
+lang_add_unique (name)
+     const char *name;
+{
+  struct unique_sections *ent;
+
+  for (ent = unique_section_list; ent; ent = ent->next)
+    if (strcmp (ent->name, name) == 0)
+      return;
+
+  ent = (struct unique_sections *) xmalloc (sizeof *ent);
+  ent->name = xstrdup (name);
+  ent->next = unique_section_list;
+  unique_section_list = ent;
+}
This page took 0.068202 seconds and 4 git commands to generate.