* config.bfd (sh*eb-*-linux*, sh*-*-linux*): Add the alternative
[deliverable/binutils-gdb.git] / ld / ldlang.c
index 968144a9d69428fec2c43545f07ffc3f599424cc..8ebd1bd2eaad389399db5d6089b99263e30a447f 100644 (file)
@@ -1,36 +1,37 @@
 /* Linker command language support.
    Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-   2001
+   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"
@@ -39,7 +40,9 @@ 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
@@ -93,10 +96,12 @@ 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 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
@@ -119,12 +124,12 @@ static void print_statement
 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 **, fill_type,
+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 **, lang_output_section_statement_type *,
-          fill_type, bfd_vma, boolean));
+          fill_type *, bfd_vma));
 static void lang_finish PARAMS ((void));
 static void ignore_bfd_errors PARAMS ((const char *, ...));
 static void lang_check PARAMS ((void));
@@ -133,10 +138,12 @@ 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));
 static void gc_section_callback
   PARAMS ((lang_wild_statement_type *, struct wildcard_list *, asection *,
           lang_input_statement_type *, PTR));
+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 *));
 static void lang_gc_sections_1 PARAMS ((lang_statement_union_type *));
@@ -152,6 +159,9 @@ 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));
+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, boolean *));
 
 typedef void (*callback_t) PARAMS ((lang_wild_statement_type *,
                                    struct wildcard_list *,
@@ -179,7 +189,8 @@ 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;
+struct bfd_sym_chain entry_symbol = { NULL, NULL };
+const char *entry_section = ".text";
 boolean entry_from_cmdline;
 boolean lang_has_input_file = false;
 boolean had_output_filename = false;
@@ -252,47 +263,59 @@ walk_wild_section (ptr, file, callback, data)
       struct wildcard_list *sec;
 
       sec = ptr->section_list;
-      do
+      if (sec == NULL)
+       (*callback) (ptr, sec, s, file, data);
+
+      while (sec != NULL)
        {
          boolean skip = false;
+         struct name_list *list_tmp;
 
-         if (sec != NULL)
+         /* Don't process sections from files which were
+            excluded.  */
+         for (list_tmp = sec->spec.exclude_name_list;
+              list_tmp;
+              list_tmp = list_tmp->next)
            {
-             struct name_list *list_tmp;
+             if (wildcardp (list_tmp->name))
+               skip = fnmatch (list_tmp->name, file->filename, 0) == 0;
+             else
+               skip = strcmp (list_tmp->name, file->filename) == 0;
 
-             /* 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 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->filename, 0) == 0;
+                   skip = fnmatch (list_tmp->name,
+                                   file->the_bfd->my_archive->filename,
+                                   0) == 0;
                  else
-                   skip = strcmp (list_tmp->name, file->filename) == 0;
-
-                 if (skip)
-                   break;
+                   skip = strcmp (list_tmp->name,
+                                  file->the_bfd->my_archive->filename) == 0;
                }
 
-             if (!skip && sec->spec.name != NULL)
-               {
-                 const char *sname = bfd_get_section_name (file->the_bfd, s);
+             if (skip)
+               break;
+           }
 
-                 if (wildcardp (sec->spec.name))
-                   skip = fnmatch (sec->spec.name, sname, 0) != 0;
-                 else
-                   skip = strcmp (sec->spec.name, sname) != 0;
-               }
+         if (!skip && sec->spec.name != NULL)
+           {
+             const char *sname = bfd_get_section_name (file->the_bfd, s);
+
+             if (wildcardp (sec->spec.name))
+               skip = fnmatch (sec->spec.name, sname, 0) != 0;
+             else
+               skip = strcmp (sec->spec.name, sname) != 0;
            }
 
          if (!skip)
            (*callback) (ptr, sec, s, file, data);
 
-         if (sec != NULL)
-           sec = sec->next;
+         sec = sec->next;
        }
-      while (sec != NULL);
     }
 }
 
@@ -377,7 +400,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);
 
@@ -602,6 +625,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)
@@ -707,7 +734,7 @@ 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;
 
@@ -723,6 +750,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,
@@ -939,8 +967,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;
     }
 
@@ -963,7 +990,7 @@ section_already_linked (abfd, sec, data)
      of having link once sections in the first place.
 
      Also, not merging link once sections in a relocatable link
-     causes trouble for MIPS ELF, which relies in link once semantics
+     causes trouble for MIPS ELF, which relies on link once semantics
      to handle the .reginfo section correctly.  */
 
   name = bfd_get_section_name (abfd, sec);
@@ -1012,13 +1039,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;
-         sec->kept_section = l->sec;
+
+         if (flags & SEC_GROUP)
+           bfd_discard_group (abfd, sec);
 
          return;
        }
@@ -1076,7 +1103,7 @@ already_linked_table_free ()
 /* 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
@@ -1098,7 +1125,7 @@ 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;
@@ -1194,6 +1221,10 @@ wild_doit (ptr, section, output, file)
          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)
@@ -1259,7 +1290,7 @@ wild_sort (wild, sec, file, section)
     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;
 
@@ -1372,31 +1403,31 @@ output_section_callback (ptr, sec, 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;
        }
     }
@@ -1462,7 +1493,7 @@ load_symbols (entry, place)
       bfd_error_type err;
       lang_statement_list_type *hold;
       boolean bad_load = true;
-      
+
       err = bfd_get_error ();
 
       /* See if the emulation has some special knowledge.  */
@@ -1484,7 +1515,7 @@ load_symbols (entry, place)
          einfo (_("%F%B: file not recognized: %E\n"), entry->the_bfd);
       else
        bad_load = false;
-      
+
       bfd_close (entry->the_bfd);
       entry->the_bfd = NULL;
 
@@ -1525,7 +1556,7 @@ load_symbols (entry, place)
     case bfd_archive:
       if (entry->whole_archive)
        {
-         bfd * member = NULL;
+         bfd *member = NULL;
          boolean loaded = true;
 
          for (;;)
@@ -1534,7 +1565,7 @@ load_symbols (entry, place)
 
              if (member == NULL)
                break;
-             
+
              if (! bfd_check_format (member, bfd_object))
                {
                  einfo (_("%F%B: member %B in archive is not an object\n"),
@@ -1590,7 +1621,7 @@ wild (s, target, output)
       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.  */ 
+            later get something which doesn't know where to put it.  */
          default_common_section = output;
        }
     }
@@ -1618,12 +1649,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;
 }
@@ -1761,6 +1787,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 *
@@ -1769,24 +1818,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?  */
@@ -1906,7 +1938,7 @@ open_input_bfds (s, force)
      lang_statement_union_type *s;
      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)
        {
@@ -1967,8 +1999,8 @@ open_input_bfds (s, force)
 
              if (add.head != NULL)
                {
-                 *add.tail = s->next;
-                 s->next = add.head;
+                 *add.tail = s->header.next;
+                 s->header.next = add.head;
                }
            }
          break;
@@ -2004,14 +2036,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)
@@ -2025,6 +2057,28 @@ ldlang_add_undef (name)
   ldlang_undef_chain_list_head = new;
 
   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
@@ -2040,17 +2094,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);
     }
 }
 
@@ -2062,12 +2106,13 @@ 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, target, output_section_statement);
+         break;
        case lang_constructors_statement_enum:
          map_input_to_output_sections (constructor_list.head,
                                        target,
@@ -2127,6 +2172,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;
@@ -2187,7 +2267,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*   ");
@@ -2306,7 +2396,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
@@ -2435,10 +2530,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 ();
 
@@ -2471,10 +2571,10 @@ print_wild_statement (w, os)
       if (sec->spec.exclude_name_list != NULL)
        {
          name_list *tmp;
-         minfo ("EXCLUDE_FILE ( %s", sec->spec.exclude_name_list->name);
+         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 (")");
+           minfo (" %s", tmp->name);
+         minfo (") ");
        }
       if (sec->spec.name != NULL)
        minfo ("%s", sec->spec.name);
@@ -2482,6 +2582,8 @@ print_wild_statement (w, os)
        minfo ("*");
       if (sec->spec.sorted)
        minfo (")");
+      if (sec->next)
+       minfo (" ");
     }
   minfo (")");
 
@@ -2513,7 +2615,7 @@ print_statement_list (s, os)
   while (s != NULL)
     {
       print_statement (s, os);
-      s = s->next;
+      s = s->header.next;
     }
 }
 
@@ -2619,94 +2721,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)
     {
+      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
     {
@@ -2777,11 +2885,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
@@ -2797,23 +2900,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;
     }
@@ -2821,20 +2924,20 @@ 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;
+     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)
        {
@@ -2857,7 +2960,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);
@@ -2895,6 +2998,8 @@ 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
@@ -2947,25 +3052,32 @@ 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;
 
+           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,
               since unallocated sections do not contribute to the region's
@@ -2991,37 +3103,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:
@@ -3082,10 +3181,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;
 
@@ -3113,12 +3212,10 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
                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:
@@ -3141,31 +3238,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;
@@ -3174,31 +3262,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;
        }
@@ -3207,17 +3298,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;
+     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)
        {
@@ -3280,8 +3407,8 @@ lang_do_assignments (s, output_section_statement, fill, dot)
            if (value.valid_p == false)
              einfo (_("%F%P: invalid data statement\n"));
          }
-          {
-            unsigned int size;
+         {
+           unsigned int size;
            switch (s->data_statement.type)
              {
              default:
@@ -3405,9 +3532,9 @@ lang_set_startof ()
       h = bfd_link_hash_lookup (link_info.hash, buf, false, false, true);
       if (h != NULL && h->type == bfd_link_hash_undefined)
        {
-          unsigned opb;
+         unsigned opb;
 
-          opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture,
+         opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture,
                                               ldfile_output_machine);
          h->type = bfd_link_hash_defined;
          if (s->_cooked_size != 0)
@@ -3432,15 +3559,16 @@ lang_finish ()
   else
     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";
+      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)
@@ -3453,7 +3581,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
     {
@@ -3462,7 +3590,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))
@@ -3474,12 +3602,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)))
@@ -3489,7 +3618,7 @@ lang_finish ()
            {
              if (warn)
                einfo (_("%P: warning: cannot find entry symbol %s; not setting start address\n"),
-                      entry_symbol);
+                      entry_symbol.name);
            }
        }
     }
@@ -3525,8 +3654,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)
@@ -3534,22 +3680,10 @@ lang_check ()
                   bfd_printable_name (input_bfd), input_bfd,
                   bfd_printable_name (output_bfd));
        }
-      else if (link_info.relocateable
-              /* 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).  */
-              && 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);
       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. */
+            private data of the output bfd.  */
 
          bfd_error_handler_type pfn = NULL;
 
@@ -3579,6 +3713,8 @@ lang_check ()
 static void
 lang_common ()
 {
+  if (command_line.inhibit_common_definition)
+    return;
   if (link_info.relocateable
       && ! command_line.force_common_definition)
     return;
@@ -3621,8 +3757,8 @@ lang_one_common (h, info)
   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)
@@ -3713,11 +3849,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)
                {
@@ -3739,18 +3871,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);
                }
            }
        }
@@ -3978,10 +4110,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;
@@ -3990,6 +4123,9 @@ 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;
 }
 
 /* If the wild pattern was marked KEEP, the member sections
@@ -4022,12 +4158,13 @@ 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);
+         break;
        case lang_constructors_statement_enum:
          lang_gc_sections_1 (constructor_list.head);
          break;
@@ -4047,25 +4184,16 @@ 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);
@@ -4102,6 +4230,10 @@ lang_process ()
   current_target = default_target;
   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 ();
 
   already_linked_table_free ();
@@ -4142,25 +4274,45 @@ 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.  */
+      boolean relax_again;
+
       do
        {
-         reset_memory_regions ();
+         lang_reset_memory_regions ();
 
          relax_again = false;
 
@@ -4172,23 +4324,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.  */
@@ -4202,7 +4348,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
@@ -4281,11 +4427,11 @@ lang_add_entry (name, cmdline)
      const char *name;
      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;
     }
 }
@@ -4318,13 +4464,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
@@ -4409,23 +4555,48 @@ lang_float (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;
 }
@@ -4707,12 +4878,6 @@ 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;
 
@@ -4728,24 +4893,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)
@@ -4755,16 +4914,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);
@@ -4774,9 +4930,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;
@@ -4789,7 +4942,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;
@@ -4799,15 +4952,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';
 
@@ -4830,62 +4985,57 @@ 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;
 {
   lang_memory_region_type *region;
-  lang_memory_region_type * default_region;
   lang_memory_region_type *lma_region;
   struct overlay_list *l;
   struct lang_nocrossref *nocrossref;
 
-  default_region = lang_memory_region_lookup ("*default*");
-
-  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;
 
-      /* Assign a region to the sections, if one has been specified.
-        Override the assignment of the default section, but not
-        other sections.  */
-      if (region != NULL &&
-         (l->os->region == NULL ||
-          l->os->region == default_region))
-       l->os->region = region;
-
-      /* We only set lma_region for the first overlay section, as
-        subsequent overlay sections will have load_base set relative
-        to the first section.  Also, don't set lma_region if
-        load_base is specified.  FIXME:  There should really be a test
-        that `AT ( LDADDR )' doesn't conflict with `AT >LMA_REGION'
-        rather than letting LDADDR simply override LMA_REGION.  */
-      if (lma_region != NULL && l->os->lma_region == NULL
-         && l->next == NULL && l->os->load_base == 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;
 
@@ -4903,13 +5053,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;
 }
@@ -4987,7 +5131,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;
@@ -4997,6 +5141,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;
@@ -5011,7 +5157,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
@@ -5052,6 +5198,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)
@@ -5088,8 +5244,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)
     ;
@@ -5135,7 +5296,7 @@ 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);
@@ -5145,7 +5306,7 @@ lang_do_version_exports_section ()
       p = contents;
       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;
        }
 
@@ -5156,7 +5317,7 @@ 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);
 }
This page took 0.049132 seconds and 4 git commands to generate.