* pe-dll.c (process_def_file): auto-export everything if
[deliverable/binutils-gdb.git] / ld / ldlang.c
index ae844beb5c4814dd2510291a75a024bad3365145..2106b3e90874f82e5ae22570c52e56ca28bac758 100644 (file)
@@ -1,11 +1,12 @@
 /* Linker command language support.
-   Copyright (C) 1991, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
+   Copyright (C) 1991, 92, 93, 94, 95, 96, 97, 1998
+   Free Software Foundation, Inc.
 
 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 1, or (at your option)
+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,
@@ -14,12 +15,14 @@ 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.  */
+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 "obstack.h"
 #include "bfdlink.h"
 
 #include "ld.h"
@@ -34,6 +37,8 @@ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307
 #include "ldfile.h"
 #include "fnmatch.h"
 
+#include <ctype.h>
+
 /* FORWARDS */
 static lang_statement_union_type *new_statement PARAMS ((enum statement_enum,
                                                         size_t,
@@ -68,6 +73,9 @@ static void init_os PARAMS ((lang_output_section_statement_type *s));
 static void exp_init_os PARAMS ((etree_type *));
 static void section_already_linked PARAMS ((bfd *, asection *, PTR));
 static boolean wildcardp PARAMS ((const char *));
+static lang_statement_union_type *wild_sort
+  PARAMS ((lang_wild_statement_type *, lang_input_statement_type *,
+          asection *));
 static void wild_section PARAMS ((lang_wild_statement_type *ptr,
                                  const char *section,
                                  lang_input_statement_type *file,
@@ -98,6 +106,7 @@ static void print_assignment
   PARAMS ((lang_assignment_statement_type *assignment,
           lang_output_section_statement_type *output_section));
 static void print_input_statement PARAMS ((lang_input_statement_type *statm));
+static boolean print_one_symbol PARAMS ((struct bfd_link_hash_entry *, PTR));
 static void print_input_section PARAMS ((lang_input_section_type *in));
 static void print_fill_statement PARAMS ((lang_fill_statement_type *fill));
 static void print_data_statement PARAMS ((lang_data_statement_type *data));
@@ -123,6 +132,7 @@ static bfd_vma size_input_section
           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));
@@ -131,6 +141,17 @@ static int topower PARAMS ((int));
 static void lang_set_startof PARAMS ((void));
 static void reset_memory_regions PARAMS ((void));
 static void lang_record_phdrs PARAMS ((void));
+static void lang_gc_wild_section
+  PARAMS ((lang_wild_statement_type *, const char *,
+          lang_input_statement_type *));
+static void lang_gc_wild_file
+  PARAMS ((lang_wild_statement_type *, const char *,
+          lang_input_statement_type *));
+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));
+                                       
 
 /* EXPORTS */
 lang_output_section_statement_type *abs_output_section;
@@ -142,6 +163,7 @@ boolean lang_has_input_file = false;
 boolean had_output_filename = false;
 boolean lang_float_flag = false;
 boolean delete_output_file_on_failure = false;
+struct lang_nocrossrefs *nocrossref_list;
 
 etree_type *base; /* Relocation base - or null */
 
@@ -406,8 +428,7 @@ lang_memory_region_type *
 lang_memory_region_lookup (name)
      CONST char *CONST name;
 {
-
-  lang_memory_region_type *p = lang_memory_region_list;
+  lang_memory_region_type *p;
 
   for (p = lang_memory_region_list;
        p != (lang_memory_region_type *) NULL;
@@ -445,6 +466,8 @@ lang_memory_region_lookup (name)
     *lang_memory_region_list_tail = new;
     lang_memory_region_list_tail = &new->next;
     new->origin = 0;
+    new->flags = 0;
+    new->not_flags = 0;
     new->length = ~(bfd_size_type)0;
     new->current = 0;
     new->had_full_message = false;
@@ -454,6 +477,31 @@ lang_memory_region_lookup (name)
 }
 
 
+lang_memory_region_type *
+lang_memory_default (section)
+     asection *section;
+{
+  lang_memory_region_type *p;
+
+  flagword sec_flags = section->flags;
+
+  /* Override SEC_DATA to mean a writable section.  */
+  if ((sec_flags & (SEC_ALLOC | SEC_READONLY | SEC_CODE)) == SEC_ALLOC)
+    sec_flags |= SEC_DATA;
+
+  for (p = lang_memory_region_list;
+       p != (lang_memory_region_type *) NULL;
+       p = p->next)
+    {
+      if ((p->flags & sec_flags) != 0
+         && (p->not_flags & sec_flags) == 0)
+       {
+         return p;
+       }
+    }
+  return lang_memory_region_lookup ("*default*");
+}
+
 lang_output_section_statement_type *
 lang_output_section_find (name)
      CONST char *CONST name;
@@ -512,14 +560,34 @@ lang_output_section_statement_lookup (name)
   return lookup;
 }
 
+static void
+lang_map_flags (flag)
+     flagword flag;
+{
+  if (flag & SEC_ALLOC)
+    minfo ("a");
+
+  if (flag & SEC_CODE)
+    minfo ("x");
+
+  if (flag & SEC_READONLY)
+    minfo ("r");
+
+  if (flag & SEC_DATA)
+    minfo ("w");
+
+  if (flag & SEC_LOAD)
+    minfo ("l");
+}
+
 void
 lang_map ()
 {
   lang_memory_region_type *m;
 
-  minfo ("\nMemory Configuration\n\n");
-  fprintf (config.map_file, "%-16s %-18s %-18s\n",
-          "Name", "Origin", "Length");
+  minfo (_("\nMemory Configuration\n\n"));
+  fprintf (config.map_file, "%-16s %-18s %-18s %s\n",
+          _("Name"), _("Origin"), _("Length"), _("Attributes"));
 
   for (m = lang_memory_region_list;
        m != (lang_memory_region_type *) NULL;
@@ -539,10 +607,29 @@ lang_map ()
          ++len;
        }
 
-      minfo ("0x%V\n", m->length);
+      minfo ("0x%V", m->length);
+      if (m->flags || m->not_flags)
+       {
+#ifndef BFD64
+         minfo ("        ");
+#endif
+         if (m->flags)
+           {
+             print_space ();
+             lang_map_flags (m->flags);
+           }
+
+         if (m->not_flags)
+           {
+             minfo (" !");
+             lang_map_flags (m->not_flags);
+           }
+       }
+
+      print_nl ();
     }
 
-  fprintf (config.map_file, "\nLinker script and memory map\n\n");
+  fprintf (config.map_file, _("\nLinker script and memory map\n\n"));
 
   print_statements ();
 }
@@ -559,7 +646,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"), DISCARD_SECTION_NAME);
 
   new = ((section_userdata_type *)
         stat_alloc (sizeof (section_userdata_type)));
@@ -569,7 +656,7 @@ init_os (s)
     s->bfd_section = bfd_make_section (output_bfd, s->name);
   if (s->bfd_section == (asection *) NULL)
     {
-      einfo ("%P%F: output format %s cannot represent section called %s\n",
+      einfo (_("%P%F: output format %s cannot represent section called %s\n"),
             output_bfd->xvec->name, s->name);
     }
   s->bfd_section->output_section = s->bfd_section;
@@ -617,6 +704,7 @@ exp_init_os (exp)
       switch (exp->type.node_code)
        {
        case ADDR:
+       case LOADADDR:
        case SIZEOF:
          {
            lang_output_section_statement_type *os;
@@ -642,11 +730,12 @@ exp_init_os (exp)
 
 /*ARGSUSED*/
 static void
-section_already_linked (abfd, sec, ignore)
+section_already_linked (abfd, sec, data)
      bfd *abfd;
      asection *sec;
-     PTR ignore;
+     PTR data;
 {
+  lang_input_statement_type *entry = (lang_input_statement_type *) data;
   struct sec_link_once
     {
       struct sec_link_once *next;
@@ -657,6 +746,15 @@ section_already_linked (abfd, sec, ignore)
   const char *name;
   struct sec_link_once *l;
 
+  /* If we are only reading symbols from this object, then we want to
+     discard all sections.  */
+  if (entry->just_syms_flag)
+    {
+      sec->output_section = bfd_abs_section_ptr;
+      sec->output_offset = sec->vma;
+      return;
+    }
+
   flags = bfd_get_section_flags (abfd, sec);
 
   if ((flags & SEC_LINK_ONCE) == 0)
@@ -679,7 +777,7 @@ section_already_linked (abfd, sec, ignore)
              break;
 
            case SEC_LINK_DUPLICATES_ONE_ONLY:
-             einfo ("%P: %B: warning: ignoring duplicate section `%s'\n",
+             einfo (_("%P: %B: warning: ignoring duplicate section `%s'\n"),
                     abfd, name);
              break;
 
@@ -693,7 +791,7 @@ section_already_linked (abfd, sec, ignore)
            case SEC_LINK_DUPLICATES_SAME_SIZE:
              if (bfd_section_size (abfd, sec)
                  != bfd_section_size (l->sec->owner, l->sec))
-               einfo ("%P: %B: warning: duplicate section `%s' has different size\n",
+               einfo (_("%P: %B: warning: duplicate section `%s' has different size\n"),
                       abfd, name);
              break;
            }
@@ -720,7 +818,11 @@ section_already_linked (abfd, sec, ignore)
    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.
+   That lets us handle DOS filenames more naturally.  */
 
 static boolean
 wildcardp (pattern)
@@ -730,7 +832,6 @@ wildcardp (pattern)
 
   for (s = pattern; *s != '\0'; ++s)
     if (*s == '?'
-       || *s == '\\'
        || *s == '*'
        || *s == '[')
       return true;
@@ -784,10 +885,17 @@ wild_doit (ptr, section, output, file)
 
   if (section->output_section == NULL)
     {
+      boolean first;
       lang_input_section_type *new;
+      flagword flags;
 
       if (output->bfd_section == NULL)
-       init_os (output);
+       {
+         init_os (output);
+         first = true;
+       }
+      else
+       first = false;
 
       /* Add a section reference to the list */
       new = new_stat (lang_input_section, ptr);
@@ -796,23 +904,38 @@ wild_doit (ptr, section, output, file)
       new->ifile = file;
       section->output_section = output->bfd_section;
 
+      flags = section->flags;
+
       /* We don't copy the SEC_NEVER_LOAD flag from an input section
         to an output section, because we want to be able to include a
         SEC_NEVER_LOAD section in the middle of an otherwise loaded
         section (I don't know why we want to do this, but we do).
         build_link_order in ldwrite.c handles this case by turning
-        the embedded SEC_NEVER_LOAD section into a fill.
+        the embedded SEC_NEVER_LOAD section into a fill.  */
+
+      flags &= ~ SEC_NEVER_LOAD;
+
+      /* If final link, don't copy the SEC_LINK_ONCE flags, they've
+        already been processed.  One reason to do this is that on pe
+        format targets, .text$foo sections go into .text and it's odd
+        to see .text with SEC_LINK_ONCE set.  */
 
-        If final link, don't copy the SEC_LINK_ONCE flags, they've already
-        been processed.  One reason to do this is that on pe format targets,
-        .text$foo sections go into .text and it's odd to see .text with
-        SEC_LINK_ONCE set.  */
+      if (! link_info.relocateable)
+       flags &= ~ (SEC_LINK_ONCE | SEC_LINK_DUPLICATES);
 
-      section->output_section->flags |=
-       section->flags & (flagword) (~ (SEC_NEVER_LOAD
-                                       | (! link_info.relocateable
-                                          ? SEC_LINK_ONCE | SEC_LINK_DUPLICATES
-                                          : 0)));
+      /* If this is not the first input section, and the SEC_READONLY
+         flag is not currently set, then don't set it just because the
+         input section has it set.  */
+
+      if (! first && (section->output_section->flags & SEC_READONLY) == 0)
+       flags &= ~ SEC_READONLY;
+
+      section->output_section->flags |= flags;
+
+      /* If SEC_READONLY is not set in the input section, then clear
+         it from the output section.  */
+      if ((section->flags & SEC_READONLY) == 0)
+       section->output_section->flags &= ~SEC_READONLY;
 
       switch (output->sectype)
        {
@@ -839,6 +962,107 @@ wild_doit (ptr, section, output, file)
     }
 }
 
+/* Handle wildcard sorting.  This returns the lang_input_section which
+   should follow the one we are going to create for SECTION and FILE,
+   based on the sorting requirements of WILD.  It returns NULL if the
+   new section should just go at the end of the current list.  */
+
+static lang_statement_union_type *
+wild_sort (wild, file, section)
+     lang_wild_statement_type *wild;
+     lang_input_statement_type *file;
+     asection *section;
+{
+  const char *section_name;
+  lang_statement_union_type *l;
+
+  if (! wild->filenames_sorted && ! wild->sections_sorted)
+    return NULL;
+
+  section_name = bfd_get_section_name (file->the_bfd, section);
+  for (l = wild->children.head; l != NULL; l = l->next)
+    {
+      lang_input_section_type *ls;
+
+      if (l->header.type != lang_input_section_enum)
+       continue;
+      ls = &l->input_section;
+
+      /* Sorting by filename takes precedence over sorting by section
+         name.  */
+
+      if (wild->filenames_sorted)
+       {
+         const char *fn, *ln;
+         boolean fa, la;
+         int i;
+
+         /* The PE support for the .idata section as generated by
+             dlltool assumes that files will be sorted by the name of
+             the archive and then the name of the file within the
+             archive.  */
+
+         if (file->the_bfd != NULL
+             && bfd_my_archive (file->the_bfd) != NULL)
+           {
+             fn = bfd_get_filename (bfd_my_archive (file->the_bfd));
+             fa = true;
+           }
+         else
+           {
+             fn = file->filename;
+             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;
+           }
+         else
+           {
+             ln = ls->ifile->filename;
+             la = false;
+           }
+
+         i = strcmp (fn, ln);
+         if (i > 0)
+           continue;
+         else if (i < 0)
+           break;
+
+         if (fa || la)
+           {
+             if (fa)
+               fn = file->filename;
+             if (la)
+               ln = ls->ifile->filename;
+
+             i = strcmp (fn, ln);
+             if (i > 0)
+               continue;
+             else if (i < 0)
+               break;
+           }
+       }
+
+      /* Here either the files are not sorted by name, or we are
+         looking at the sections for this file.  */
+
+      if (wild->sections_sorted)
+       {
+         if (strcmp (section_name,
+                     bfd_get_section_name (ls->ifile->the_bfd,
+                                           ls->section))
+             < 0)
+           break;
+       }
+    }
+
+  return l;
+}
+
 /* Expand a wild statement for a particular FILE.  SECTION may be
    NULL, in which case it is a wild card.  */
 
@@ -883,8 +1107,49 @@ wild_section (ptr, section, file, output)
              else
                match = strcmp (section, name) == 0 ? true : false;
            }
+
          if (match)
-           wild_doit (&ptr->children, s, output, file);
+           {
+             lang_statement_union_type *before;
+
+             /* If the wild pattern was marked KEEP, the member sections
+                should be as well.  */
+             if (ptr->keep_sections)
+               s->flags |= SEC_KEEP;
+
+             before = wild_sort (ptr, file, s);
+
+             /* Here BEFORE points to the lang_input_section which
+                should follow the one we are about to add.  If BEFORE
+                is NULL, then the section should just go at the end
+                of the current list.  */
+
+             if (before == NULL)
+               wild_doit (&ptr->children, s, output, file);
+             else
+               {
+                 lang_statement_list_type list;
+                 lang_statement_union_type **pp;
+
+                 lang_list_init (&list);
+                 wild_doit (&list, s, output, file);
+
+                 /* If we are discarding the section, LIST.HEAD will
+                     be NULL.  */
+                 if (list.head != NULL)
+                   {
+                     ASSERT (list.head->next == NULL);
+
+                     for (pp = &ptr->children.head;
+                          *pp != before;
+                          pp = &(*pp)->next)
+                       ASSERT (*pp != NULL);
+
+                     list.head->next = *pp;
+                     *pp = list.head;
+                   }
+               }
+           }
        }
     }
 }
@@ -953,15 +1218,15 @@ load_symbols (entry, place)
        {
          char **p;
 
-         einfo ("%B: file not recognized: %E\n", entry->the_bfd);
-         einfo ("%B: matching formats:", entry->the_bfd);
+         einfo (_("%B: file not recognized: %E\n"), entry->the_bfd);
+         einfo (_("%B: matching formats:"), entry->the_bfd);
          for (p = matching; *p != NULL; p++)
            einfo (" %s", *p);
          einfo ("%F\n");
        }
       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);
 
       bfd_close (entry->the_bfd);
       entry->the_bfd = NULL;
@@ -1011,13 +1276,13 @@ load_symbols (entry, place)
          while (member != NULL)
            {
              if (! bfd_check_format (member, bfd_object))
-               einfo ("%F%B: object %B in archive is not object\n",
+               einfo (_("%F%B: object %B in archive is not object\n"),
                       entry->the_bfd, member);
              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);
+               einfo (_("%F%B: could not read symbols: %E\n"), member);
              member = bfd_openr_next_archived_file (entry->the_bfd,
                                                     member);
            }
@@ -1029,7 +1294,7 @@ load_symbols (entry, place)
     }
 
   if (! bfd_link_add_symbols (entry->the_bfd, &link_info))
-    einfo ("%F%B: could not read symbols: %E\n", entry->the_bfd);
+    einfo (_("%F%B: could not read symbols: %E\n"), entry->the_bfd);
 
   entry->loaded = true;
 }
@@ -1145,9 +1410,9 @@ open_output (name)
     {
       if (bfd_get_error () == bfd_error_invalid_target)
        {
-         einfo ("%P%F: target %s not found\n", output_target);
+         einfo (_("%P%F: target %s not found\n"), output_target);
        }
-      einfo ("%P%F: cannot open output file %s: %E\n", name);
+      einfo (_("%P%F: cannot open output file %s: %E\n"), name);
     }
 
   delete_output_file_on_failure = true;
@@ -1155,15 +1420,15 @@ open_output (name)
   /*  output->flags |= D_PAGED;*/
 
   if (! bfd_set_format (output, bfd_object))
-    einfo ("%P%F:%s: can not make object file: %E\n", name);
+    einfo (_("%P%F:%s: can not make object file: %E\n"), name);
   if (! bfd_set_arch_mach (output,
                           ldfile_output_architecture,
                           ldfile_output_machine))
-    einfo ("%P%F:%s: can not set architecture: %E\n", name);
+    einfo (_("%P%F:%s: can not set architecture: %E\n"), name);
 
   link_info.hash = bfd_link_hash_table_create (output);
   if (link_info.hash == (struct bfd_link_hash_table *) NULL)
-    einfo ("%P%F: can not create link hash table: %E\n");
+    einfo (_("%P%F: can not create link hash table: %E\n"));
 
   bfd_set_gp_size (output, g_switch_value);
   return output;
@@ -1350,7 +1615,7 @@ lang_place_undefineds ()
 
       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");
+       einfo (_("%P%F: bfd_link_hash_lookup failed: %E\n"));
       if (h->type == bfd_link_hash_new)
        {
          h->type = bfd_link_hash_undefined;
@@ -1473,7 +1738,7 @@ print_output_section_statement (output_section_statement)
 
              addr = exp_get_abs_int (output_section_statement->load_base, 0,
                                      "load base", lang_final_phase_enum);
-             minfo (" load address 0x%V", addr);
+             minfo (_(" load address 0x%V"), addr);
            }
        }
 
@@ -1602,7 +1867,7 @@ print_input_section (in)
                  --len;
                }
 
-             minfo ("%W (size before relaxing)\n", i->_raw_size);
+             minfo (_("%W (size before relaxing)\n"), i->_raw_size);
            }
 
          bfd_link_hash_traverse (link_info.hash, print_one_symbol, (PTR) i);
@@ -1655,6 +1920,10 @@ print_data_statement (data)
       size = QUAD_SIZE;
       name = "QUAD";
       break;
+    case SQUAD:
+      size = QUAD_SIZE;
+      name = "SQUAD";
+      break;
     }
 
   minfo ("0x%V %W %s 0x%v", addr, size, name, data->value);
@@ -1677,7 +1946,7 @@ static void
 print_address_statement (address)
      lang_address_statement_type *address;
 {
-  minfo ("Address of section %s set to ", address->section_name);
+  minfo (_("Address of section %s set to "), address->section_name);
   exp_print_tree (address->address);
   print_nl ();
 }
@@ -1751,15 +2020,25 @@ print_wild_statement (w, os)
 {
   print_space ();
 
+  if (w->filenames_sorted)
+    minfo ("SORT(");
   if (w->filename != NULL)
     minfo ("%s", w->filename);
   else
     minfo ("*");
+  if (w->filenames_sorted)
+    minfo (")");
 
+  minfo ("(");
+  if (w->sections_sorted)
+    minfo ("SORT(");
   if (w->section_name != NULL)
-    minfo ("(%s)", w->section_name);
+    minfo ("%s", w->section_name);
   else
-    minfo ("(*)");
+    minfo ("*");
+  if (w->sections_sorted)
+    minfo (")");
+  minfo (")");
 
   print_nl ();
 
@@ -1804,7 +2083,7 @@ print_statement (s, os)
   switch (s->header.type)
     {
     default:
-      fprintf (config.map_file, "Fail with %d\n", s->header.type);
+      fprintf (config.map_file, _("Fail with %d\n"), s->header.type);
       FAIL ();
       break;
     case lang_constructors_statement_enum:
@@ -2030,7 +2309,7 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
           if (os->children.head == NULL
               || os->children.head->next != NULL
               || os->children.head->header.type != lang_input_section_enum)
-            einfo ("%P%X: Internal error on COFF shared library section %s",
+            einfo (_("%P%X: Internal error on COFF shared library section %s\n"),
                    os->name);
 
           input = os->children.head->input_section.section;
@@ -2053,13 +2332,39 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
           /* No address specified for this section, get one
              from the region specification
              */
-          if (os->region == (lang_memory_region_type *) NULL)
+          if (os->region == (lang_memory_region_type *) NULL
+              || (((bfd_get_section_flags (output_bfd, os->bfd_section)
+                   & (SEC_ALLOC | SEC_LOAD)) != 0)
+                  && os->region->name[0] == '*'
+                  && strcmp (os->region->name, "*default*") == 0))
           {
-            os->region = lang_memory_region_lookup ("*default*");
+            os->region = lang_memory_default (os->bfd_section);
           }
+
+          /* If a loadable section is using the default memory
+             region, and some non default memory regions were
+             defined, issue a warning.  */
+          if ((bfd_get_section_flags (output_bfd, os->bfd_section)
+               & (SEC_ALLOC | SEC_LOAD)) != 0
+              && ! link_info.relocateable
+              && strcmp (os->region->name, "*default*") == 0
+              && lang_memory_region_list != NULL
+              && (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));
+
           dot = os->region->current;
           if (os->section_alignment == -1)
-            dot = align_power (dot, os->bfd_section->alignment_power);
+            {
+              bfd_vma olddot;
+
+              olddot = dot;
+              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"),
+                       os->name, (unsigned int) (dot - olddot));
+            }
         }
         else
         {
@@ -2071,7 +2376,7 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
                              dot, &dot);
           if (r.valid == false)
           {
-            einfo ("%F%S: non constant address expression for section %s\n",
+            einfo (_("%F%S: non constant address expression for section %s\n"),
                    os->name);
           }
           dot = r.value + r.section->bfd_section->vma;
@@ -2115,7 +2420,7 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
             {
               if (os->addr_tree != (etree_type *) NULL)
                 {
-                  einfo ("%X%P: address 0x%v of %B section %s is not within region %s\n",
+                  einfo (_("%X%P: address 0x%v of %B section %s is not within region %s\n"),
                          os->region->current,
                          os->bfd_section->owner,
                          os->bfd_section->name,
@@ -2123,7 +2428,7 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
                 }
               else
                 {
-                  einfo ("%X%P: region %s is full (%B section %s)\n",
+                  einfo (_("%X%P: region %s is full (%B section %s)\n"),
                          os->region->name,
                          os->bfd_section->owner,
                          os->bfd_section->name);
@@ -2152,21 +2457,22 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
        output_section_statement->bfd_section;
 
        switch (s->data_statement.type)
-       {
-        case QUAD:
-        size = QUAD_SIZE;
-        break;
-       case LONG:
-        size = LONG_SIZE;
-        break;
-       case SHORT:
-        size = SHORT_SIZE;
-        break;
-       case BYTE:
-        size = BYTE_SIZE;
-        break;
+        {
+        case QUAD:
+        case SQUAD:
+          size = QUAD_SIZE;
+          break;
+        case LONG:
+          size = LONG_SIZE;
+          break;
+        case SHORT:
+          size = SHORT_SIZE;
+          break;
+        case BYTE:
+          size = BYTE_SIZE;
+          break;
+        }
 
-       }
        dot += size;
        output_section_statement->bfd_section->_raw_size += size;
        /* The output section gets contents, and then we inspect for
@@ -2224,7 +2530,7 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
            boolean again;
 
            if (! bfd_relax_section (i->owner, i, &link_info, &again))
-             einfo ("%P%F: can't relax section: %E\n");
+             einfo (_("%P%F: can't relax section: %E\n"));
            if (again)
              relax_again = true;
          }
@@ -2251,7 +2557,7 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
                      dot,
                      &newdot);
 
-       if (newdot != dot && !relax)
+       if (newdot != dot)
         {
           /* The assignment changed dot.  Insert a pad.  */
           if (output_section_statement == abs_output_section)
@@ -2260,7 +2566,7 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
                  the default memory address.  */
               lang_memory_region_lookup ("*default*")->current = newdot;
             }
-          else
+          else if (!relax)
             {
               lang_statement_union_type *new =
                 ((lang_statement_union_type *)
@@ -2385,11 +2691,12 @@ lang_do_assignments (s, output_section_statement, fill, dot)
                                   lang_final_phase_enum, dot, &dot);
            s->data_statement.value = value.value;
            if (value.valid == false)
-             einfo ("%F%P: invalid data statement\n");
+             einfo (_("%F%P: invalid data statement\n"));
          }
          switch (s->data_statement.type)
            {
            case QUAD:
+           case SQUAD:
              dot += QUAD_SIZE;
              break;
            case LONG:
@@ -2413,7 +2720,7 @@ lang_do_assignments (s, output_section_statement, fill, dot)
                                   lang_final_phase_enum, dot, &dot);
            s->reloc_statement.addend_value = value.value;
            if (value.valid == false)
-             einfo ("%F%P: invalid reloc statement\n");
+             einfo (_("%F%P: invalid reloc statement\n"));
          }
          dot += bfd_get_reloc_size (s->reloc_statement.howto);
          break;
@@ -2547,33 +2854,62 @@ 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);
     }
   else
     {
-      asection *ts;
+      bfd_vma val;
+      CONST char *send;
 
-      /* Can't find the entry symbol.  Use the first address in the
-        text section.  */
-      ts = bfd_get_section_by_name (output_bfd, ".text");
-      if (ts != (asection *) NULL)
+      /* We couldn't find the entry symbol.  Try parsing it as a
+         number.  */
+      val = bfd_scan_vma (entry_symbol, &send, 0);
+      if (*send == '\0')
        {
-         if (warn)
-           einfo ("%P: warning: cannot find entry symbol %s; defaulting to %V\n",
-                  entry_symbol, bfd_get_section_vma (output_bfd, ts));
-         if (! bfd_set_start_address (output_bfd,
-                                      bfd_get_section_vma (output_bfd, ts)))
-           einfo ("%P%F: can't set start address\n");
+         if (! bfd_set_start_address (output_bfd, val))
+           einfo (_("%P%F: can't set start address\n"));
        }
       else
        {
-         if (warn)
-           einfo ("%P: warning: cannot find entry symbol %s; not setting start address\n",
-                  entry_symbol);
+         asection *ts;
+
+         /* 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");
+         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));
+             if (! bfd_set_start_address (output_bfd,
+                                          bfd_get_section_vma (output_bfd,
+                                                               ts)))
+               einfo (_("%P%F: can't set start address\n"));
+           }
+         else
+           {
+             if (warn)
+               einfo (_("%P: warning: cannot find entry symbol %s; not setting start address\n"),
+                      entry_symbol);
+           }
        }
     }
 }
 
+/* This is a small function used when we want to ignore errors from
+   BFD.  */
+
+static void
+#ifdef ANSI_PROTOTYPES
+ignore_bfd_errors (const char *s, ...)
+#else
+ignore_bfd_errors (s)
+     const char *s;
+#endif
+{
+  /* Don't do anything.  */
+}
+
 /* Check that the architecture of all the input files is compatible
    with the output file.  Also call the backend to let it do any
    other checking that is needed.  */
@@ -2593,12 +2929,32 @@ lang_check ()
       compatible = bfd_arch_get_compatible (input_bfd,
                                            output_bfd);
       if (compatible == NULL)
-       einfo ("%P: warning: %s architecture of input file `%B' is incompatible with %s output\n",
-              bfd_printable_name (input_bfd), input_bfd,
-              bfd_printable_name (output_bfd));
-
+       {
+         if (command_line.warn_mismatch)
+           einfo (_("%P: warning: %s architecture of input file `%B' is incompatible with %s output\n"),
+                  bfd_printable_name (input_bfd), input_bfd,
+                  bfd_printable_name (output_bfd));
+       }
       else
-       bfd_merge_private_bfd_data (input_bfd, output_bfd);
+       {
+         bfd_error_handler_type pfn = NULL;
+
+         /* If we aren't supposed to warn about mismatched input
+             files, temporarily set the BFD error handler to a
+             function which will do nothing.  We still want to call
+             bfd_merge_private_bfd_data, since it may set up
+             information which is needed in the output file.  */
+         if (! command_line.warn_mismatch)
+           pfn = bfd_set_error_handler (ignore_bfd_errors);
+         if (! bfd_merge_private_bfd_data (input_bfd, output_bfd))
+           {
+             if (command_line.warn_mismatch)
+               einfo (_("%E%X: failed to merge target specific data of file %B\n"),
+                      input_bfd);
+           }
+         if (! command_line.warn_mismatch)
+           bfd_set_error_handler (pfn);
+       }
     }
 }
 
@@ -2649,8 +3005,8 @@ lang_one_common (h, info)
   section = h->u.c.p->section;
 
   /* Increase the size of the section.  */
-  section->_raw_size = ALIGN_N (section->_raw_size,
-                               (bfd_size_type) (1 << power_of_two));
+  section->_cooked_size = ALIGN_N (section->_cooked_size,
+                                  (bfd_size_type) (1 << power_of_two));
 
   /* Adjust the alignment if necessary.  */
   if (power_of_two > section->alignment_power)
@@ -2659,13 +3015,15 @@ lang_one_common (h, info)
   /* Change the symbol from common to defined.  */
   h->type = bfd_link_hash_defined;
   h->u.def.section = section;
-  h->u.def.value = section->_raw_size;
+  h->u.def.value = section->_cooked_size;
 
   /* Increase the size of the section.  */
-  section->_raw_size += size;
+  section->_cooked_size += size;
 
-  /* Make sure the section is allocated in memory.  */
+  /* Make sure the section is allocated in memory, and make sure that
+     it is no longer a common section.  */
   section->flags |= SEC_ALLOC;
+  section->flags &= ~ SEC_IS_COMMON;
 
   if (config.map_file != NULL)
     {
@@ -2676,8 +3034,8 @@ lang_one_common (h, info)
 
       if (! header_printed)
        {
-         minfo ("\nAllocating common symbols\n");
-         minfo ("Common symbol       size              file\n\n");
+         minfo (_("\nAllocating common symbols\n"));
+         minfo (_("Common symbol       size              file\n\n"));
          header_printed = true;
        }
 
@@ -2766,7 +3124,7 @@ lang_place_orphans ()
                          /* This message happens when using the
                              svr3.ifile linker script, so I have
                              disabled it.  */
-                         info_msg ("%P: no [COMMON] command, defaulting to .bss\n");
+                         info_msg (_("%P: no [COMMON] command, defaulting to .bss\n"));
 #endif
                          default_common_section =
                            lang_output_section_statement_lookup (".bss");
@@ -2793,38 +3151,43 @@ lang_place_orphans ()
 
 void
 lang_set_flags (ptr, flags)
-     int *ptr;
+     lang_memory_region_type *ptr;
      CONST char *flags;
 {
-  boolean state = false;
+  flagword *ptr_flags = &ptr->flags;
 
-  *ptr = 0;
+  ptr->flags = ptr->not_flags = 0;
   while (*flags)
     {
-      if (*flags == '!')
-       {
-         state = false;
-         flags++;
-       }
-      else
-       state = true;
       switch (*flags)
        {
-       case 'R':
-         /*      ptr->flag_read = state; */
+       case '!':
+         ptr_flags = (ptr_flags == &ptr->flags) ? &ptr->not_flags : &ptr->flags;
          break;
-       case 'W':
-         /*      ptr->flag_write = state; */
+
+       case 'A': case 'a':
+         *ptr_flags |= SEC_ALLOC;
          break;
-       case 'X':
-         /*      ptr->flag_executable= state;*/
+
+       case 'R': case 'r':
+         *ptr_flags |= SEC_READONLY;
          break;
-       case 'L':
-       case 'I':
-         /*      ptr->flag_loadable= state;*/
+
+       case 'W': case 'w':
+         *ptr_flags |= SEC_DATA;
          break;
+
+       case 'X': case 'x':
+         *ptr_flags |= SEC_CODE;
+         break;
+
+       case 'L': case 'l':
+       case 'I': case 'i':
+         *ptr_flags |= SEC_LOAD;
+         break;
+
        default:
-         einfo ("%P%F: invalid syntax in flags\n");
+         einfo (_("%P%F: invalid syntax in flags\n"));
          break;
        }
       flags++;
@@ -2923,7 +3286,7 @@ ldlang_add_file (entry)
      each backend which might set the SEC_LINK_ONCE flag.  If we do
      this, we should probably handle SEC_EXCLUDE in the same way.  */
 
-  bfd_map_over_sections (entry->the_bfd, section_already_linked, (PTR) NULL);
+  bfd_map_over_sections (entry->the_bfd, section_already_linked, (PTR) entry);
 }
 
 void
@@ -3037,6 +3400,192 @@ reset_memory_regions ()
     }
 }
 
+/* ??? At some point this traversal for GC should share code with the
+   traversal for manipulating the output file.  */
+
+/* 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.  */
+
+static void
+lang_gc_wild_section (ptr, section, file)
+     lang_wild_statement_type *ptr;
+     const char *section;
+     lang_input_statement_type *file;
+{
+  if (file->just_syms_flag == false)
+    {
+      register asection *s;
+      boolean wildcard;
+
+      if (section == NULL)
+       wildcard = false;
+      else
+       wildcard = wildcardp (section);
+
+      for (s = file->the_bfd->sections; s != NULL; s = s->next)
+       {
+         boolean match;
+
+         if (section == NULL)
+           match = true;
+         else
+           {
+             const char *name;
+
+             name = bfd_get_section_name (file->the_bfd, s);
+             if (wildcard)
+               match = fnmatch (section, name, 0) == 0 ? true : false;
+             else
+               match = strcmp (section, name) == 0 ? true : false;
+           }
+
+         if (match)
+           {
+             /* If the wild pattern was marked KEEP, the member sections
+                should be as well.  */
+             if (ptr->keep_sections)
+               s->flags |= SEC_KEEP;
+           }
+       }
+    }
+}
+
+/* Handle a wild statement for a single file F.  */
+
+static void
+lang_gc_wild_file (s, section, f)
+     lang_wild_statement_type *s;
+     const char *section;
+     lang_input_statement_type *f;
+{
+  if (f->the_bfd == NULL
+      || ! bfd_check_format (f->the_bfd, bfd_archive))
+    lang_gc_wild_section (s, section, f);
+  else
+    {
+      bfd *member;
+
+      /* This is an archive file.  We must map each member of the
+        archive separately.  */
+      member = bfd_openr_next_archived_file (f->the_bfd, (bfd *) NULL);
+      while (member != NULL)
+       {
+         /* When lookup_name is called, it will call the add_symbols
+            entry point for the archive.  For each element of the
+            archive which is included, BFD will call ldlang_add_file,
+            which will set the usrdata field of the member to the
+            lang_input_statement.  */
+         if (member->usrdata != NULL)
+           {
+             lang_gc_wild_section (s, section,
+                           (lang_input_statement_type *) member->usrdata);
+           }
+
+         member = bfd_openr_next_archived_file (f->the_bfd, member);
+       }
+    }
+}
+
+/* Handle a wild statement, marking it against GC.  SECTION or FILE or both
+   may be NULL, indicating that it is a wildcard.  */
+
+static void
+lang_gc_wild (s, section, file)
+     lang_wild_statement_type *s;
+     const char *section;
+     const char *file;
+{
+  lang_input_statement_type *f;
+
+  if (file == (char *) NULL)
+    {
+      /* Perform the iteration over all files in the list */
+      for (f = (lang_input_statement_type *) file_chain.head;
+          f != (lang_input_statement_type *) NULL;
+          f = (lang_input_statement_type *) f->next)
+       {
+         lang_gc_wild_file (s, section, f);
+       }
+    }
+  else if (wildcardp (file))
+    {
+      for (f = (lang_input_statement_type *) file_chain.head;
+          f != (lang_input_statement_type *) NULL;
+          f = (lang_input_statement_type *) f->next)
+       {
+         if (fnmatch (file, f->filename, FNM_FILE_NAME) == 0)
+           lang_gc_wild_file (s, section, f);
+       }
+    }
+  else
+    {
+      /* Perform the iteration over a single file */
+      f = lookup_name (file);
+      lang_gc_wild_file (s, section, f);
+    }
+}
+
+/* Iterate over sections marking them against GC.  */
+
+static void
+lang_gc_sections_1 (s)
+     lang_statement_union_type * s;
+{
+  for (; s != (lang_statement_union_type *) NULL; s = s->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);
+         break;
+       case lang_constructors_statement_enum:
+         lang_gc_sections_1 (constructor_list.head);
+         break;
+       case lang_output_section_statement_enum:
+         lang_gc_sections_1 (s->output_section_statement.children.head);
+         break;
+       case lang_group_statement_enum:
+         lang_gc_sections_1 (s->group_statement.children.head);
+         break;
+       }
+    }
+}
+
+static void
+lang_gc_sections ()
+{
+  struct bfd_link_hash_entry *h;
+  ldlang_undef_chain_list_type *ulist, fake_list_start;
+
+  /* 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.  */
+
+  fake_list_start.next = ldlang_undef_chain_list_head;
+  fake_list_start.name = entry_symbol;
+
+  for (ulist = &fake_list_start; ulist; ulist = ulist->next)
+    {
+      h = bfd_link_hash_lookup (link_info.hash, ulist->name, 
+                               false, false, false);
+
+      if (h != (struct bfd_link_hash_entry *) NULL
+          && (h->type == bfd_link_hash_defined
+              || h->type == bfd_link_hash_defweak)
+         && ! bfd_is_abs_section (h->u.def.section))
+       {
+         h->u.def.section->flags |= SEC_KEEP;
+       }
+    }
+
+  bfd_gc_sections (output_bfd, &link_info);
+}
+
 void
 lang_process ()
 {
@@ -3056,21 +3605,32 @@ lang_process ()
 
   ldemul_after_open ();
 
+  /* Make sure that we're not mixing architectures.  We call this
+     after all the input files have been opened, but before we do any
+     other processing, so that any operations merge_private_bfd_data
+     does on the output file will be known during the rest of the
+     link.  */
+  lang_check ();
+
   /* Build all sets based on the information gathered from the input
      files.  */
   ldctor_build_sets ();
 
+  /* Remove unreferenced sections if asked to.  */
+  if (command_line.gc_sections)
+    lang_gc_sections ();
+
   /* Size up the common data */
   lang_common ();
 
-  /* Run through the contours of the script and attatch input sections
+  /* Run through the contours of the script and attach input sections
      to the correct output sections
      */
   map_input_to_output_sections (statement_list.head, (char *) NULL,
                                (lang_output_section_statement_type *) NULL);
 
 
-  /* Find any sections not attatched explicitly and handle them */
+  /* Find any sections not attached explicitly and handle them */
   lang_place_orphans ();
 
   ldemul_before_allocation ();
@@ -3131,10 +3691,6 @@ lang_process ()
                       abs_output_section,
                       (fill_type) 0, (bfd_vma) 0);
 
-  /* Make sure that we're not mixing architectures */
-
-  lang_check ();
-
   /* Final stuffs */
 
   ldemul_finish ();
@@ -3144,9 +3700,13 @@ lang_process ()
 /* EXPORTED TO YACC */
 
 void
-lang_add_wild (section_name, filename)
-     CONST char *CONST section_name;
-     CONST char *CONST filename;
+lang_add_wild (section_name, sections_sorted, filename, filenames_sorted,
+              keep_sections)
+     const char *const section_name;
+     boolean sections_sorted;
+     const char *const filename;
+     boolean filenames_sorted;
+     boolean keep_sections;
 {
   lang_wild_statement_type *new = new_stat (lang_wild_statement,
                                            stat_ptr);
@@ -3160,7 +3720,10 @@ lang_add_wild (section_name, filename)
       lang_has_input_file = true;
     }
   new->section_name = section_name;
+  new->sections_sorted = sections_sorted;
   new->filename = filename;
+  new->filenames_sorted = filenames_sorted;
+  new->keep_sections = keep_sections;
   lang_list_init (&new->children);
 }
 
@@ -3180,21 +3743,6 @@ lang_section_start (name, address)
    called by ENTRY in a linker script.  Command line arguments take
    precedence.  */
 
-/* WINDOWS_NT.  When an entry point has been specified, we will also force
-   this symbol to be defined by calling ldlang_add_undef (equivalent to 
-   having switch -u entry_name on the command line).  The reason we do
-   this is so that the user doesn't have to because they would have to use
-   the -u switch if they were specifying an entry point other than 
-   _mainCRTStartup.  Specifically, if creating a windows application, entry
-   point _WinMainCRTStartup must be specified.
-     What I have found for non console applications (entry not _mainCRTStartup)
-   is that the .obj that contains mainCRTStartup is brought in since it is
-   the first encountered in libc.lib and it has other symbols in it which will
-   be pulled in by the link process.  To avoid this, adding -u with the entry
-   point name specified forces the correct .obj to be used.  We can avoid
-   making the user do this by always adding the entry point name as an
-   undefined symbol.  */
-
 void
 lang_add_entry (name, cmdline)
      CONST char *name;
@@ -3207,14 +3755,6 @@ lang_add_entry (name, cmdline)
       entry_symbol = name;
       entry_from_cmdline = cmdline;
     }
-#if 0 
-  /* don't do this yet.  It seems to work (the executables run), but the 
-     image created is very different from what I was getting before indicating
-     that something else is being pulled in.  When everything else is working,
-     then try to put this back in to see if it will do the right thing for
-     other more complicated applications */
-  ldlang_add_undef (name);
-#endif
 }
 
 void
@@ -3319,7 +3859,7 @@ lang_startup (name)
 {
   if (startup_file != (char *) NULL)
     {
-      einfo ("%P%Fmultiple STARTUP files\n");
+      einfo (_("%P%Fmultiple STARTUP files\n"));
     }
   first_file->filename = name;
   first_file->local_sym_name = name;
@@ -3336,12 +3876,14 @@ lang_float (maybe)
 }
 
 void
-lang_leave_output_section_statement (fill, memspec)
+lang_leave_output_section_statement (fill, memspec, phdrs)
      bfd_vma fill;
-     CONST char *memspec;
+     const char *memspec;
+     struct lang_output_section_phdr_list *phdrs;
 {
   current_section->fill = fill;
   current_section->region = lang_memory_region_lookup (memspec);
+  current_section->phdrs = phdrs;
   stat_ptr = &statement_list;
 }
 
@@ -3360,7 +3902,7 @@ lang_abs_symbol_at_beginning_of (secname, name)
 
   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");
+    einfo (_("%P%F: bfd_link_hash_lookup failed: %E\n"));
 
   if (h->type == bfd_link_hash_new
       || h->type == bfd_link_hash_undefined)
@@ -3394,7 +3936,7 @@ lang_abs_symbol_at_end_of (secname, name)
 
   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");
+    einfo (_("%P%F: bfd_link_hash_lookup failed: %E\n"));
 
   if (h->type == bfd_link_hash_new
       || h->type == bfd_link_hash_undefined)
@@ -3499,22 +4041,6 @@ lang_new_phdr (name, type, filehdr, phdrs, at, flags)
   *pp = n;
 }
 
-/* Record that a section should be placed in a phdr.  */
-
-void
-lang_section_in_phdr (name)
-     const char *name;
-{
-  struct lang_output_section_phdr_list *n;
-
-  n = ((struct lang_output_section_phdr_list *)
-       stat_alloc (sizeof (struct lang_output_section_phdr_list)));
-  n->name = name;
-  n->used = false;
-  n->next = current_section->phdrs;
-  current_section->phdrs = n;
-}
-
 /* Record the program header information in the output BFD.  FIXME: We
    should not be calling an ELF specific function here.  */
 
@@ -3528,7 +4054,7 @@ lang_record_phdrs ()
   lang_statement_union_type *u;
 
   alc = 10;
-  secs = xmalloc (alc * sizeof (asection *));
+  secs = (asection **) xmalloc (alc * sizeof (asection *));
   last = NULL;
   for (l = lang_phdr_list; l != NULL; l = l->next)
     {
@@ -3568,7 +4094,8 @@ lang_record_phdrs ()
                  if (c >= alc)
                    {
                      alc *= 2;
-                     secs = xrealloc (secs, alc * sizeof (asection *));
+                     secs = ((asection **)
+                             xrealloc (secs, alc * sizeof (asection *)));
                    }
                  secs[c] = os->bfd_section;
                  ++c;
@@ -3594,7 +4121,7 @@ lang_record_phdrs ()
                             flags,
                             l->at == NULL ? false : true,
                             at, l->filehdr, l->phdrs, c, secs))
-       einfo ("%F%P: bfd_record_phdr failed: %E\n");
+       einfo (_("%F%P: bfd_record_phdr failed: %E\n"));
     }
 
   free (secs);
@@ -3613,7 +4140,339 @@ lang_record_phdrs ()
           pl != NULL;
           pl = pl->next)
        if (! pl->used && strcmp (pl->name, "NONE") != 0)
-         einfo ("%X%P: section `%s' assigned to non-existent phdr `%s'\n",
+         einfo (_("%X%P: section `%s' assigned to non-existent phdr `%s'\n"),
                 u->output_section_statement.name, pl->name);
     }
 }
+
+/* Record a list of sections which may not be cross referenced.  */
+
+void
+lang_add_nocrossref (l)
+     struct lang_nocrossref *l;
+{
+  struct lang_nocrossrefs *n;
+
+  n = (struct lang_nocrossrefs *) xmalloc (sizeof *n);
+  n->next = nocrossref_list;
+  n->list = l;
+  nocrossref_list = n;
+
+  /* Set notice_all so that we get informed about all symbols.  */
+  link_info.notice_all = true;
+}
+\f
+/* Overlay handling.  We handle overlays with some static variables.  */
+
+/* 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 *next;
+  lang_output_section_statement_type *os;
+};
+
+static struct overlay_list *overlay_list;
+
+/* Start handling an overlay.  */
+
+void
+lang_enter_overlay (vma_expr, lma_expr, nocrossrefs)
+     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);
+
+  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.  */
+
+void
+lang_enter_overlay_section (name)
+     const char *name;
+{
+  struct overlay_list *n;
+  etree_type *size;
+
+  lang_enter_output_section_statement (name, overlay_vma, normal_section,
+                                      0, 0, 0, overlay_lma);
+
+  /* If this is the first section, then base the VMA and LMA 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);
+    }
+
+  /* Remember the section.  */
+  n = (struct overlay_list *) xmalloc (sizeof *n);
+  n->os = current_section;
+  n->next = overlay_list;
+  overlay_list = n;
+
+  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;
+  else
+    overlay_max = exp_binop (MAX_K, overlay_max, size);
+}
+
+/* Finish a section in an overlay.  There isn't any special to do
+   here.  */
+
+void
+lang_leave_overlay_section (fill, phdrs)
+     bfd_vma fill;
+     struct lang_output_section_phdr_list *phdrs;
+{
+  const char *name;
+  char *clean, *s2;
+  const char *s1;
+  char *buf;
+
+  name = current_section->name;
+
+  lang_leave_output_section_statement (fill, "*default*", phdrs);
+
+  /* Define the magic symbols.  */
+
+  clean = xmalloc (strlen (name) + 1);
+  s2 = clean;
+  for (s1 = name; *s1 != '\0'; s1++)
+    if (isalnum ((unsigned char) *s1) || *s1 == '_')
+      *s2++ = *s1;
+  *s2 = '\0';
+
+  buf = xmalloc (strlen (clean) + sizeof "__load_start_");
+  sprintf (buf, "__load_start_%s", clean);
+  lang_add_assignment (exp_assop ('=', buf,
+                                 exp_nameop (LOADADDR, name)));
+
+  buf = xmalloc (strlen (clean) + sizeof "__load_stop_");
+  sprintf (buf, "__load_stop_%s", clean);
+  lang_add_assignment (exp_assop ('=', buf,
+                                 exp_binop ('+',
+                                            exp_nameop (LOADADDR, name),
+                                            exp_nameop (SIZEOF, name))));
+
+  free (clean);
+}
+
+/* Finish an overlay.  If there are any overlay wide settings, this
+   looks through all the sections in the overlay and sets them.  */
+
+void
+lang_leave_overlay (fill, memspec, phdrs)
+     bfd_vma fill;
+     const char *memspec;
+     struct lang_output_section_phdr_list *phdrs;
+{
+  lang_memory_region_type *region;
+  struct overlay_list *l;
+  struct lang_nocrossref *nocrossref;
+
+  if (memspec == NULL)
+    region = NULL;
+  else
+    region = lang_memory_region_lookup (memspec);
+
+  nocrossref = NULL;
+
+  l = overlay_list;
+  while (l != NULL)
+    {
+      struct overlay_list *next;
+
+      if (fill != 0 && l->os->fill == 0)
+       l->os->fill = fill;
+      if (region != NULL && l->os->region == NULL)
+       l->os->region = region;
+      if (phdrs != NULL && l->os->phdrs == NULL)
+       l->os->phdrs = phdrs;
+
+      if (overlay_nocrossrefs)
+       {
+         struct lang_nocrossref *nc;
+
+         nc = (struct lang_nocrossref *) xmalloc (sizeof *nc);
+         nc->name = l->os->name;
+         nc->next = nocrossref;
+         nocrossref = nc;
+       }
+
+      next = l->next;
+      free (l);
+      l = next;
+    }
+
+  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;
+}
+\f
+/* Version handling.  This is only useful for ELF.  */
+
+/* This global variable holds the version tree that we build.  */
+
+struct bfd_elf_version_tree *lang_elf_version_info;
+
+/* This is called for each variable name or match expression.  */
+
+struct bfd_elf_version_expr *
+lang_new_vers_regex (orig, new)
+     struct bfd_elf_version_expr *orig;
+     const char *new;
+{
+  struct bfd_elf_version_expr *ret;
+
+  ret = (struct bfd_elf_version_expr *) xmalloc (sizeof *ret);
+  ret->next = orig;
+  ret->match = new;
+  return ret;
+}
+
+/* This is called for each set of variable names and match
+   expressions.  */
+
+struct bfd_elf_version_tree *
+lang_new_vers_node (globals, locals)
+     struct bfd_elf_version_expr *globals;
+     struct bfd_elf_version_expr *locals;
+{
+  struct bfd_elf_version_tree *ret;
+
+  ret = (struct bfd_elf_version_tree *) xmalloc (sizeof *ret);
+  ret->next = NULL;
+  ret->name = NULL;
+  ret->vernum = 0;
+  ret->globals = globals;
+  ret->locals = locals;
+  ret->deps = NULL;
+  ret->name_indx = (unsigned int) -1;
+  ret->used = 0;
+  return ret;
+}
+
+/* This static variable keeps track of version indices.  */
+
+static int version_index;
+
+/* This is called when we know the name and dependencies of the
+   version.  */
+
+void
+lang_register_vers_node (name, version, deps)
+     const char *name;
+     struct bfd_elf_version_tree *version;
+     struct bfd_elf_version_deps *deps;
+{
+  struct bfd_elf_version_tree *t, **pp;
+  struct bfd_elf_version_expr *e1;
+
+  /* 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)
+      einfo (_("%X%P: duplicate version tag `%s'\n"), name);
+
+  /* Check the global and local match names, and make sure there
+     aren't any duplicates.  */
+
+  for (e1 = version->globals; e1 != NULL; e1 = e1->next)
+    {
+      for (t = lang_elf_version_info; t != NULL; t = t->next)
+       {
+         struct bfd_elf_version_expr *e2;
+
+         for (e2 = t->locals; e2 != NULL; e2 = e2->next)
+           if (strcmp (e1->match, e2->match) == 0)
+             einfo (_("%X%P: duplicate expression `%s' in version information\n"),
+                    e1->match);
+       }
+    }
+
+  for (e1 = version->locals; e1 != NULL; e1 = e1->next)
+    {
+      for (t = lang_elf_version_info; t != NULL; t = t->next)
+       {
+         struct bfd_elf_version_expr *e2;
+
+         for (e2 = t->globals; e2 != NULL; e2 = e2->next)
+           if (strcmp (e1->match, e2->match) == 0)
+             einfo (_("%X%P: duplicate expression `%s' in version information\n"),
+                    e1->match);
+       }
+    }
+
+  version->deps = deps;
+  version->name = name;
+  ++version_index;
+  version->vernum = version_index;
+
+  for (pp = &lang_elf_version_info; *pp != NULL; pp = &(*pp)->next)
+    ;
+  *pp = version;
+}
+
+/* This is called when we see a version dependency.  */
+
+struct bfd_elf_version_deps *
+lang_add_vers_depend (list, name)
+     struct bfd_elf_version_deps *list;
+     const char *name;
+{
+  struct bfd_elf_version_deps *ret;
+  struct bfd_elf_version_tree *t;
+
+  ret = (struct bfd_elf_version_deps *) xmalloc (sizeof *ret);
+  ret->next = list;
+
+  for (t = lang_elf_version_info; t != NULL; t = t->next)
+    {
+      if (strcmp (t->name, name) == 0)
+       {
+         ret->version_needed = t;
+         return ret;
+       }
+    }
+
+  einfo (_("%X%P: unable to find version dependency `%s'\n"), name);
+
+  return ret;
+}
This page took 0.044308 seconds and 4 git commands to generate.