Automatic date update in version.in
[deliverable/binutils-gdb.git] / ld / ldlang.c
index 294e6323012cc60323932e5a43c8864f72de0532..96daf0ef11d0fd6ca40f6be95e26bab44a77277b 100644 (file)
@@ -1,5 +1,5 @@
 /* Linker command language support.
 /* Linker command language support.
-   Copyright (C) 1991-2018 Free Software Foundation, Inc.
+   Copyright (C) 1991-2019 Free Software Foundation, Inc.
 
    This file is part of the GNU Binutils.
 
 
    This file is part of the GNU Binutils.
 
@@ -67,6 +67,12 @@ static bfd_boolean map_option_f;
 static bfd_vma print_dot;
 static lang_input_statement_type *first_file;
 static const char *current_target;
 static bfd_vma print_dot;
 static lang_input_statement_type *first_file;
 static const char *current_target;
+/* Header for list of statements corresponding to any files involved in the
+   link, either specified from the command-line or added implicitely (eg.
+   archive member used to resolved undefined symbol, wildcard statement from
+   linker script, etc.).  Next pointer is in next field of a
+   lang_statement_header_type (reached via header field in a
+   lang_statement_union).  */
 static lang_statement_list_type statement_list;
 static lang_statement_list_type *stat_save[10];
 static lang_statement_list_type **stat_save_ptr = &stat_save[0];
 static lang_statement_list_type statement_list;
 static lang_statement_list_type *stat_save[10];
 static lang_statement_list_type **stat_save_ptr = &stat_save[0];
@@ -95,9 +101,19 @@ static void lang_do_memory_regions (void);
 /* Exported variables.  */
 const char *output_target;
 lang_output_section_statement_type *abs_output_section;
 /* Exported variables.  */
 const char *output_target;
 lang_output_section_statement_type *abs_output_section;
-lang_statement_list_type lang_output_section_statement;
+lang_statement_list_type lang_os_list;
 lang_statement_list_type *stat_ptr = &statement_list;
 lang_statement_list_type *stat_ptr = &statement_list;
+/* Header for list of statements corresponding to files used in the final
+   executable.  This can be either object file specified on the command-line
+   or library member resolving an undefined reference.  Next pointer is in next
+   field of a lang_input_statement_type (reached via input_statement field in a
+   lang_statement_union).  */
 lang_statement_list_type file_chain = { NULL, NULL };
 lang_statement_list_type file_chain = { NULL, NULL };
+/* Header for list of statements corresponding to files specified on the
+   command-line for linking.  It thus contains real object files and archive
+   but not archive members.  Next pointer is in next_real_file field of a
+   lang_input_statement_type statement (reached via input_statement field in a
+   lang_statement_union).  */
 lang_statement_list_type input_file_chain;
 struct bfd_sym_chain entry_symbol = { NULL, NULL };
 const char *entry_section = ".text";
 lang_statement_list_type input_file_chain;
 struct bfd_sym_chain entry_symbol = { NULL, NULL };
 const char *entry_section = ".text";
@@ -1199,26 +1215,26 @@ output_section_statement_newfunc (struct bfd_hash_entry *entry,
   ret = (struct out_section_hash_entry *) entry;
   memset (&ret->s, 0, sizeof (ret->s));
   ret->s.header.type = lang_output_section_statement_enum;
   ret = (struct out_section_hash_entry *) entry;
   memset (&ret->s, 0, sizeof (ret->s));
   ret->s.header.type = lang_output_section_statement_enum;
-  ret->s.output_section_statement.subsection_alignment = -1;
-  ret->s.output_section_statement.section_alignment = -1;
+  ret->s.output_section_statement.subsection_alignment = NULL;
+  ret->s.output_section_statement.section_alignment = NULL;
   ret->s.output_section_statement.block_value = 1;
   lang_list_init (&ret->s.output_section_statement.children);
   lang_statement_append (stat_ptr, &ret->s, &ret->s.header.next);
 
   /* For every output section statement added to the list, except the
   ret->s.output_section_statement.block_value = 1;
   lang_list_init (&ret->s.output_section_statement.children);
   lang_statement_append (stat_ptr, &ret->s, &ret->s.header.next);
 
   /* For every output section statement added to the list, except the
-     first one, lang_output_section_statement.tail points to the "next"
+     first one, lang_os_list.tail points to the "next"
      field of the last element of the list.  */
      field of the last element of the list.  */
-  if (lang_output_section_statement.head != NULL)
+  if (lang_os_list.head != NULL)
     ret->s.output_section_statement.prev
       = ((lang_output_section_statement_type *)
     ret->s.output_section_statement.prev
       = ((lang_output_section_statement_type *)
-        ((char *) lang_output_section_statement.tail
+        ((char *) lang_os_list.tail
          - offsetof (lang_output_section_statement_type, next)));
 
   /* GCC's strict aliasing rules prevent us from just casting the
      address, so we store the pointer in a variable and cast that
      instead.  */
   nextp = &ret->s.output_section_statement.next;
          - offsetof (lang_output_section_statement_type, next)));
 
   /* GCC's strict aliasing rules prevent us from just casting the
      address, so we store the pointer in a variable and cast that
      instead.  */
   nextp = &ret->s.output_section_statement.next;
-  lang_statement_append (&lang_output_section_statement,
+  lang_statement_append (&lang_os_list,
                         &ret->s,
                         (lang_statement_union_type **) nextp);
   return &ret->root;
                         &ret->s,
                         (lang_statement_union_type **) nextp);
   return &ret->root;
@@ -1231,7 +1247,7 @@ output_section_statement_table_init (void)
                              output_section_statement_newfunc,
                              sizeof (struct out_section_hash_entry),
                              61))
                              output_section_statement_newfunc,
                              sizeof (struct out_section_hash_entry),
                              61))
-    einfo (_("%P%F: can not create hash table: %E\n"));
+    einfo (_("%F%P: can not create hash table: %E\n"));
 }
 
 static void
 }
 
 static void
@@ -1254,7 +1270,7 @@ lang_init (void)
   lang_list_init (stat_ptr);
 
   lang_list_init (&input_file_chain);
   lang_list_init (stat_ptr);
 
   lang_list_init (&input_file_chain);
-  lang_list_init (&lang_output_section_statement);
+  lang_list_init (&lang_os_list);
   lang_list_init (&file_chain);
   first_file = lang_add_input_file (NULL, lang_input_file_is_marker_enum,
                                    NULL);
   lang_list_init (&file_chain);
   first_file = lang_add_input_file (NULL, lang_input_file_is_marker_enum,
                                    NULL);
@@ -1315,13 +1331,13 @@ lang_memory_region_lookup (const char *const name, bfd_boolean create)
       if (strcmp (n->name, name) == 0)
        {
          if (create)
       if (strcmp (n->name, name) == 0)
        {
          if (create)
-           einfo (_("%P:%S: warning: redeclaration of memory region `%s'\n"),
+           einfo (_("%P:%pS: warning: redeclaration of memory region `%s'\n"),
                   NULL, name);
          return r;
        }
 
   if (!create && strcmp (name, DEFAULT_MEMORY_REGION))
                   NULL, name);
          return r;
        }
 
   if (!create && strcmp (name, DEFAULT_MEMORY_REGION))
-    einfo (_("%P:%S: warning: memory region `%s' not declared\n"),
+    einfo (_("%P:%pS: warning: memory region `%s' not declared\n"),
           NULL, name);
 
   new_region = (lang_memory_region_type *)
           NULL, name);
 
   new_region = (lang_memory_region_type *)
@@ -1358,7 +1374,7 @@ lang_memory_region_alias (const char *alias, const char *region_name)
      the default memory region.  */
   if (strcmp (region_name, DEFAULT_MEMORY_REGION) == 0
       || strcmp (alias, DEFAULT_MEMORY_REGION) == 0)
      the default memory region.  */
   if (strcmp (region_name, DEFAULT_MEMORY_REGION) == 0
       || strcmp (alias, DEFAULT_MEMORY_REGION) == 0)
-    einfo (_("%F%P:%S: error: alias for default memory region\n"), NULL);
+    einfo (_("%F%P:%pS: error: alias for default memory region\n"), NULL);
 
   /* Look for the target region and check if the alias is not already
      in use.  */
 
   /* Look for the target region and check if the alias is not already
      in use.  */
@@ -1369,14 +1385,14 @@ lang_memory_region_alias (const char *alias, const char *region_name)
        if (region == NULL && strcmp (n->name, region_name) == 0)
          region = r;
        if (strcmp (n->name, alias) == 0)
        if (region == NULL && strcmp (n->name, region_name) == 0)
          region = r;
        if (strcmp (n->name, alias) == 0)
-         einfo (_("%F%P:%S: error: redefinition of memory region "
+         einfo (_("%F%P:%pS: error: redefinition of memory region "
                   "alias `%s'\n"),
                 NULL, alias);
       }
 
   /* Check if the target region exists.  */
   if (region == NULL)
                   "alias `%s'\n"),
                 NULL, alias);
       }
 
   /* Check if the target region exists.  */
   if (region == NULL)
-    einfo (_("%F%P:%S: error: memory region `%s' "
+    einfo (_("%F%P:%pS: error: memory region `%s' "
             "for alias `%s' does not exist\n"),
           NULL, region_name, alias);
 
             "for alias `%s' does not exist\n"),
           NULL, region_name, alias);
 
@@ -1435,7 +1451,7 @@ lang_output_section_statement_lookup (const char *name,
   if (entry == NULL)
     {
       if (create)
   if (entry == NULL)
     {
       if (create)
-       einfo (_("%P%F: failed creating section `%s': %E\n"), name);
+       einfo (_("%F%P: failed creating section `%s': %E\n"), name);
       return NULL;
     }
 
       return NULL;
     }
 
@@ -1474,7 +1490,7 @@ lang_output_section_statement_lookup (const char *name,
                                             name));
       if (entry == NULL)
        {
                                             name));
       if (entry == NULL)
        {
-         einfo (_("%P%F: failed creating section `%s': %E\n"), name);
+         einfo (_("%F%P: failed creating section `%s': %E\n"), name);
          return NULL;
        }
       entry->root = last_ent->root;
          return NULL;
        }
       entry->root = last_ent->root;
@@ -1532,7 +1548,7 @@ lang_output_section_find_by_flags (const asection *sec,
 
   /* We know the first statement on this list is *ABS*.  May as well
      skip it.  */
 
   /* We know the first statement on this list is *ABS*.  May as well
      skip it.  */
-  first = &lang_output_section_statement.head->output_section_statement;
+  first = &lang_os_list.head->output_section_statement;
   first = first->next;
 
   /* First try for an exact match.  */
   first = first->next;
 
   /* First try for an exact match.  */
@@ -1760,8 +1776,7 @@ insert_os_after (lang_output_section_statement_type *after)
   lang_statement_union_type **assign = NULL;
   bfd_boolean ignore_first;
 
   lang_statement_union_type **assign = NULL;
   bfd_boolean ignore_first;
 
-  ignore_first
-    = after == &lang_output_section_statement.head->output_section_statement;
+  ignore_first = after == &lang_os_list.head->output_section_statement;
 
   for (where = &after->header.next;
        *where != NULL;
 
   for (where = &after->header.next;
        *where != NULL;
@@ -1777,11 +1792,13 @@ insert_os_after (lang_output_section_statement_type *after)
              ass = &(*where)->assignment_statement;
              if (ass->exp->type.node_class != etree_assert
                  && ass->exp->assign.dst[0] == '.'
              ass = &(*where)->assignment_statement;
              if (ass->exp->type.node_class != etree_assert
                  && ass->exp->assign.dst[0] == '.'
-                 && ass->exp->assign.dst[1] == 0
-                 && !ignore_first)
-               assign = where;
+                 && ass->exp->assign.dst[1] == 0)
+               {
+                 if (!ignore_first)
+                   assign = where;
+                 ignore_first = FALSE;
+               }
            }
            }
-         ignore_first = FALSE;
          continue;
        case lang_wild_statement_enum:
        case lang_input_section_enum:
          continue;
        case lang_wild_statement_enum:
        case lang_input_section_enum:
@@ -1792,6 +1809,7 @@ insert_os_after (lang_output_section_statement_type *after)
        case lang_padding_statement_enum:
        case lang_constructors_statement_enum:
          assign = NULL;
        case lang_padding_statement_enum:
        case lang_constructors_statement_enum:
          assign = NULL;
+         ignore_first = FALSE;
          continue;
        case lang_output_section_statement_enum:
          if (assign != NULL)
          continue;
        case lang_output_section_statement_enum:
          if (assign != NULL)
@@ -1844,8 +1862,7 @@ lang_insert_orphan (asection *s,
       || (s->flags & (SEC_LOAD | SEC_ALLOC)) == 0)
     address = exp_intop (0);
 
       || (s->flags & (SEC_LOAD | SEC_ALLOC)) == 0)
     address = exp_intop (0);
 
-  os_tail = ((lang_output_section_statement_type **)
-            lang_output_section_statement.tail);
+  os_tail = (lang_output_section_statement_type **) lang_os_list.tail;
   os = lang_enter_output_section_statement (secname, address, normal_section,
                                            NULL, NULL, NULL, constraint, 0);
 
   os = lang_enter_output_section_statement (secname, address, normal_section,
                                            NULL, NULL, NULL, constraint, 0);
 
@@ -1875,14 +1892,15 @@ lang_insert_orphan (asection *s,
   if (after != NULL && os->bfd_section != NULL)
     {
       asection *snew, *as;
   if (after != NULL && os->bfd_section != NULL)
     {
       asection *snew, *as;
+      bfd_boolean place_after = place->stmt == NULL;
+      bfd_boolean insert_after = TRUE;
 
       snew = os->bfd_section;
 
       /* Shuffle the bfd section list to make the output file look
         neater.  This is really only cosmetic.  */
       if (place->section == NULL
 
       snew = os->bfd_section;
 
       /* Shuffle the bfd section list to make the output file look
         neater.  This is really only cosmetic.  */
       if (place->section == NULL
-         && after != (&lang_output_section_statement.head
-                      ->output_section_statement))
+         && after != &lang_os_list.head->output_section_statement)
        {
          asection *bfd_section = after->bfd_section;
 
        {
          asection *bfd_section = after->bfd_section;
 
@@ -1912,6 +1930,181 @@ lang_insert_orphan (asection *s,
          /* Now tack it back on in the right place.  */
          bfd_section_list_append (link_info.output_bfd, snew);
        }
          /* Now tack it back on in the right place.  */
          bfd_section_list_append (link_info.output_bfd, snew);
        }
+      else if ((bfd_get_flavour (link_info.output_bfd)
+               == bfd_target_elf_flavour)
+              && (bfd_get_flavour (s->owner)
+                  == bfd_target_elf_flavour)
+              && ((elf_section_type (s) == SHT_NOTE
+                   && (s->flags & SEC_LOAD) != 0)
+                  || (elf_section_type (as) == SHT_NOTE
+                      && (as->flags & SEC_LOAD) != 0)))
+       {
+         /* Make sure that output note sections are grouped and sorted
+            by alignments when inserting a note section or insert a
+            section after a note section,  */
+         asection *sec;
+         /* A specific section after which the output note section
+            should be placed.  */
+         asection *after_sec;
+         /* True if we need to insert the orphan section after a
+            specific section to maintain output note section order.  */
+         bfd_boolean after_sec_note = FALSE;
+
+         static asection *first_orphan_note = NULL;
+
+         /* Group and sort output note section by alignments in
+            ascending order.  */
+         after_sec = NULL;
+         if (elf_section_type (s) == SHT_NOTE
+             && (s->flags & SEC_LOAD) != 0)
+           {
+             /* Search from the beginning for the last output note
+                section with equal or larger alignments.  NB: Don't
+                place orphan note section after non-note sections.  */
+
+             first_orphan_note = NULL;
+             for (sec = link_info.output_bfd->sections;
+                  (sec != NULL
+                   && !bfd_is_abs_section (sec));
+                  sec = sec->next)
+               if (sec != snew
+                   && elf_section_type (sec) == SHT_NOTE
+                   && (sec->flags & SEC_LOAD) != 0)
+                 {
+                   if (!first_orphan_note)
+                     first_orphan_note = sec;
+                   if (sec->alignment_power >= s->alignment_power)
+                     after_sec = sec;
+                 }
+               else if (first_orphan_note)
+                 {
+                   /* Stop if there is non-note section after the first
+                      orphan note section.  */
+                   break;
+                 }
+
+             /* If this will be the first orphan note section, it can
+                be placed at the default location.  */
+             after_sec_note = first_orphan_note != NULL;
+             if (after_sec == NULL && after_sec_note)
+               {
+                 /* If all output note sections have smaller
+                    alignments, place the section before all
+                    output orphan note sections.  */
+                 after_sec = first_orphan_note;
+                 insert_after = FALSE;
+               }
+           }
+         else if (first_orphan_note)
+           {
+             /* Don't place non-note sections in the middle of orphan
+                note sections.  */
+             after_sec_note = TRUE;
+             after_sec = as;
+             for (sec = as->next;
+                  (sec != NULL
+                   && !bfd_is_abs_section (sec));
+                  sec = sec->next)
+               if (elf_section_type (sec) == SHT_NOTE
+                   && (sec->flags & SEC_LOAD) != 0)
+                 after_sec = sec;
+           }
+
+         if (after_sec_note)
+           {
+             if (after_sec)
+               {
+                 /* Search forward to insert OS after AFTER_SEC output
+                    statement.  */
+                 lang_output_section_statement_type *stmt, *next;
+                 bfd_boolean found = FALSE;
+                 for (stmt = after; stmt != NULL; stmt = next)
+                   {
+                     next = stmt->next;
+                     if (insert_after)
+                       {
+                         if (stmt->bfd_section == after_sec)
+                           {
+                             place_after = TRUE;
+                             found = TRUE;
+                             after = stmt;
+                             break;
+                           }
+                       }
+                     else
+                       {
+                         /* If INSERT_AFTER is FALSE, place OS before
+                            AFTER_SEC output statement.  */
+                         if (next && next->bfd_section == after_sec)
+                           {
+                             place_after = TRUE;
+                             found = TRUE;
+                             after = stmt;
+                             break;
+                           }
+                       }
+                   }
+
+                 /* Search backward to insert OS after AFTER_SEC output
+                    statement.  */
+                 if (!found)
+                   for (stmt = after; stmt != NULL; stmt = stmt->prev)
+                     {
+                       if (insert_after)
+                         {
+                           if (stmt->bfd_section == after_sec)
+                             {
+                               place_after = TRUE;
+                               after = stmt;
+                               break;
+                             }
+                         }
+                       else
+                         {
+                           /* If INSERT_AFTER is FALSE, place OS before
+                              AFTER_SEC output statement.  */
+                           if (stmt->next->bfd_section == after_sec)
+                             {
+                               place_after = TRUE;
+                               after = stmt;
+                               break;
+                             }
+                         }
+                     }
+               }
+
+             if (after_sec == NULL
+                 || (insert_after && after_sec->next != snew)
+                 || (!insert_after && after_sec->prev != snew))
+               {
+                 /* Unlink the section.  */
+                 bfd_section_list_remove (link_info.output_bfd, snew);
+
+                 /* Place SNEW after AFTER_SEC.  If AFTER_SEC is NULL,
+                    prepend SNEW.  */
+                 if (after_sec)
+                   {
+                     if (insert_after)
+                       bfd_section_list_insert_after (link_info.output_bfd,
+                                                      after_sec, snew);
+                     else
+                       bfd_section_list_insert_before (link_info.output_bfd,
+                                                      after_sec, snew);
+                   }
+                 else
+                   bfd_section_list_prepend (link_info.output_bfd, snew);
+               }
+           }
+         else if (as != snew && as->prev != snew)
+           {
+             /* Unlink the section.  */
+             bfd_section_list_remove (link_info.output_bfd, snew);
+
+             /* Now tack it back on in the right place.  */
+             bfd_section_list_insert_before (link_info.output_bfd,
+                                             as, snew);
+           }
+       }
       else if (as != snew && as->prev != snew)
        {
          /* Unlink the section.  */
       else if (as != snew && as->prev != snew)
        {
          /* Unlink the section.  */
@@ -1938,7 +2131,8 @@ lang_insert_orphan (asection *s,
        {
          lang_output_section_statement_type *newly_added_os;
 
        {
          lang_output_section_statement_type *newly_added_os;
 
-         if (place->stmt == NULL)
+         /* Place OS after AFTER if AFTER_NOTE is TRUE.  */
+         if (place_after)
            {
              lang_statement_union_type **where = insert_os_after (after);
 
            {
              lang_statement_union_type **where = insert_os_after (after);
 
@@ -1980,8 +2174,7 @@ lang_insert_orphan (asection *s,
             assigning *os_tail = NULL, but possibly added it back in
             the same place when assigning *place->os_tail.  */
          if (*os_tail == NULL)
             assigning *os_tail = NULL, but possibly added it back in
             the same place when assigning *place->os_tail.  */
          if (*os_tail == NULL)
-           lang_output_section_statement.tail
-             = (lang_statement_union_type **) os_tail;
+           lang_os_list.tail = (lang_statement_union_type **) os_tail;
        }
     }
   return os;
        }
     }
   return os;
@@ -2016,8 +2209,8 @@ lang_print_asneeded (void)
        }
 
       if (m->ref != NULL)
        }
 
       if (m->ref != NULL)
-       minfo ("%B ", m->ref);
-      minfo ("(%T)\n", m->name);
+       minfo ("%pB ", m->ref);
+      minfo ("(%pT)\n", m->name);
     }
 }
 
     }
 }
 
@@ -2054,19 +2247,20 @@ lang_map (void)
          || file->flags.just_syms)
        continue;
 
          || file->flags.just_syms)
        continue;
 
-      for (s = file->the_bfd->sections; s != NULL; s = s->next)
-       if ((s->output_section == NULL
-            || s->output_section->owner != link_info.output_bfd)
-           && (s->flags & (SEC_LINKER_CREATED | SEC_KEEP)) == 0)
-         {
-           if (!dis_header_printed)
-             {
-               fprintf (config.map_file, _("\nDiscarded input sections\n\n"));
-               dis_header_printed = TRUE;
-             }
+      if (config.print_map_discarded)
+       for (s = file->the_bfd->sections; s != NULL; s = s->next)
+         if ((s->output_section == NULL
+              || s->output_section->owner != link_info.output_bfd)
+             && (s->flags & (SEC_LINKER_CREATED | SEC_KEEP)) == 0)
+           {
+             if (! dis_header_printed)
+               {
+                 fprintf (config.map_file, _("\nDiscarded input sections\n\n"));
+                 dis_header_printed = TRUE;
+               }
 
 
-           print_input_section (s, TRUE);
-         }
+             print_input_section (s, TRUE);
+           }
     }
 
   minfo (_("\nMemory Configuration\n\n"));
     }
 
   minfo (_("\nMemory Configuration\n\n"));
@@ -2118,6 +2312,7 @@ lang_map (void)
       obstack_begin (&map_obstack, 1000);
       bfd_link_hash_traverse (link_info.hash, sort_def_symbol, 0);
     }
       obstack_begin (&map_obstack, 1000);
       bfd_link_hash_traverse (link_info.hash, sort_def_symbol, 0);
     }
+  expld.phase = lang_fixed_phase_enum;
   lang_statement_iteration++;
   print_statements ();
 
   lang_statement_iteration++;
   print_statements ();
 
@@ -2164,7 +2359,7 @@ static void
 init_os (lang_output_section_statement_type *s, flagword flags)
 {
   if (strcmp (s->name, DISCARD_SECTION_NAME) == 0)
 init_os (lang_output_section_statement_type *s, flagword flags)
 {
   if (strcmp (s->name, DISCARD_SECTION_NAME) == 0)
-    einfo (_("%P%F: Illegal use of `%s' section\n"), DISCARD_SECTION_NAME);
+    einfo (_("%F%P: illegal use of `%s' section\n"), DISCARD_SECTION_NAME);
 
   if (s->constraint != SPECIAL)
     s->bfd_section = bfd_get_section_by_name (link_info.output_bfd, s->name);
 
   if (s->constraint != SPECIAL)
     s->bfd_section = bfd_get_section_by_name (link_info.output_bfd, s->name);
@@ -2173,7 +2368,7 @@ init_os (lang_output_section_statement_type *s, flagword flags)
                                                         s->name, flags);
   if (s->bfd_section == NULL)
     {
                                                         s->name, flags);
   if (s->bfd_section == NULL)
     {
-      einfo (_("%P%F: output format %s cannot represent section"
+      einfo (_("%F%P: output format %s cannot represent section"
               " called %s: %E\n"),
             link_info.output_bfd->xvec->name, s->name);
     }
               " called %s: %E\n"),
             link_info.output_bfd->xvec->name, s->name);
     }
@@ -2193,8 +2388,9 @@ init_os (lang_output_section_statement_type *s, flagword flags)
     exp_init_os (s->load_base);
 
   /* If supplied an alignment, set it.  */
     exp_init_os (s->load_base);
 
   /* If supplied an alignment, set it.  */
-  if (s->section_alignment != -1)
-    s->bfd_section->alignment_power = s->section_alignment;
+  if (s->section_alignment != NULL)
+    s->bfd_section->alignment_power = exp_get_power (s->section_alignment,
+                                                    "section alignment");
 }
 
 /* Make sure that all output sections mentioned in an expression are
 }
 
 /* Make sure that all output sections mentioned in an expression are
@@ -2207,6 +2403,7 @@ exp_init_os (etree_type *exp)
     {
     case etree_assign:
     case etree_provide:
     {
     case etree_assign:
     case etree_provide:
+    case etree_provided:
       exp_init_os (exp->assign.src);
       break;
 
       exp_init_os (exp->assign.src);
       break;
 
@@ -2378,6 +2575,7 @@ lang_add_section (lang_statement_list_type *ptr,
     {
     case normal_section:
     case overlay_section:
     {
     case normal_section:
     case overlay_section:
+    case first_overlay_section:
       break;
     case noalloc_section:
       flags &= ~SEC_ALLOC;
       break;
     case noalloc_section:
       flags &= ~SEC_ALLOC;
@@ -2752,6 +2950,9 @@ load_symbols (lang_input_statement_type *entry,
   if (entry->flags.missing_file)
     return TRUE;
 
   if (entry->flags.missing_file)
     return TRUE;
 
+  if (trace_files || verbose)
+    info_msg ("%pI\n", entry);
+
   if (!bfd_check_format (entry->the_bfd, bfd_archive)
       && !bfd_check_format_matches (entry->the_bfd, bfd_object, &matching))
     {
   if (!bfd_check_format (entry->the_bfd, bfd_archive)
       && !bfd_check_format_matches (entry->the_bfd, bfd_object, &matching))
     {
@@ -2769,15 +2970,15 @@ load_symbols (lang_input_statement_type *entry,
        {
          char **p;
 
        {
          char **p;
 
-         einfo (_("%B: file not recognized: %E\n"), entry->the_bfd);
-         einfo (_("%B: matching formats:"), entry->the_bfd);
+         einfo (_("%P: %pB: file not recognized: %E;"
+                  " 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)
          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%P: %pB: file not recognized: %E\n"), entry->the_bfd);
 
       bfd_close (entry->the_bfd);
       entry->the_bfd = NULL;
 
       bfd_close (entry->the_bfd);
       entry->the_bfd = NULL;
@@ -2827,8 +3028,6 @@ load_symbols (lang_input_statement_type *entry,
     case bfd_object:
       if (!entry->flags.reload)
        ldlang_add_file (entry);
     case bfd_object:
       if (!entry->flags.reload)
        ldlang_add_file (entry);
-      if (trace_files || verbose)
-       info_msg ("%I\n", entry);
       break;
 
     case bfd_archive:
       break;
 
     case bfd_archive:
@@ -2850,7 +3049,7 @@ load_symbols (lang_input_statement_type *entry,
 
              if (!bfd_check_format (member, bfd_object))
                {
 
              if (!bfd_check_format (member, bfd_object))
                {
-                 einfo (_("%F%B: member %B in archive is not an object\n"),
+                 einfo (_("%F%P: %pB: member %pB in archive is not an object\n"),
                         entry->the_bfd, member);
                  loaded = FALSE;
                }
                         entry->the_bfd, member);
                  loaded = FALSE;
                }
@@ -2865,7 +3064,7 @@ load_symbols (lang_input_statement_type *entry,
                 substitute BFD for us.  */
              if (!bfd_link_add_symbols (subsbfd, &link_info))
                {
                 substitute BFD for us.  */
              if (!bfd_link_add_symbols (subsbfd, &link_info))
                {
-                 einfo (_("%F%B: error adding symbols: %E\n"), member);
+                 einfo (_("%F%P: %pB: error adding symbols: %E\n"), member);
                  loaded = FALSE;
                }
            }
                  loaded = FALSE;
                }
            }
@@ -2879,7 +3078,7 @@ load_symbols (lang_input_statement_type *entry,
   if (bfd_link_add_symbols (entry->the_bfd, &link_info))
     entry->flags.loaded = TRUE;
   else
   if (bfd_link_add_symbols (entry->the_bfd, &link_info))
     entry->flags.loaded = TRUE;
   else
-    einfo (_("%F%B: error adding symbols: %E\n"), entry->the_bfd);
+    einfo (_("%F%P: %pB: error adding symbols: %E\n"), entry->the_bfd);
 
   return entry->flags.loaded;
 }
 
   return entry->flags.loaded;
 }
@@ -3167,23 +3366,23 @@ open_output (const char *name)
   if (link_info.output_bfd == NULL)
     {
       if (bfd_get_error () == bfd_error_invalid_target)
   if (link_info.output_bfd == NULL)
     {
       if (bfd_get_error () == bfd_error_invalid_target)
-       einfo (_("%P%F: target %s not found\n"), output_target);
+       einfo (_("%F%P: target %s not found\n"), output_target);
 
 
-      einfo (_("%P%F: cannot open output file %s: %E\n"), name);
+      einfo (_("%F%P: cannot open output file %s: %E\n"), name);
     }
 
   delete_output_file_on_failure = TRUE;
 
   if (!bfd_set_format (link_info.output_bfd, bfd_object))
     }
 
   delete_output_file_on_failure = TRUE;
 
   if (!bfd_set_format (link_info.output_bfd, bfd_object))
-    einfo (_("%P%F:%s: can not make object file: %E\n"), name);
+    einfo (_("%F%P: %s: can not make object file: %E\n"), name);
   if (!bfd_set_arch_mach (link_info.output_bfd,
                           ldfile_output_architecture,
                           ldfile_output_machine))
   if (!bfd_set_arch_mach (link_info.output_bfd,
                           ldfile_output_architecture,
                           ldfile_output_machine))
-    einfo (_("%P%F:%s: can not set architecture: %E\n"), name);
+    einfo (_("%F%P: %s: can not set architecture: %E\n"), name);
 
   link_info.hash = bfd_link_hash_table_create (link_info.output_bfd);
   if (link_info.hash == NULL)
 
   link_info.hash = bfd_link_hash_table_create (link_info.output_bfd);
   if (link_info.hash == NULL)
-    einfo (_("%P%F: can not create hash table: %E\n"));
+    einfo (_("%F%P: can not create hash table: %E\n"));
 
   bfd_set_gp_size (link_info.output_bfd, g_switch_value);
 }
 
   bfd_set_gp_size (link_info.output_bfd, g_switch_value);
 }
@@ -3322,7 +3521,7 @@ open_input_bfds (lang_statement_union_type *s, enum open_bfd_mode mode)
                  s->input_statement.flags.reload = TRUE;
                }
 
                  s->input_statement.flags.reload = TRUE;
                }
 
-             os_tail = lang_output_section_statement.tail;
+             os_tail = lang_os_list.tail;
              lang_list_init (&add);
 
              if (!load_symbols (&s->input_statement, &add))
              lang_list_init (&add);
 
              if (!load_symbols (&s->input_statement, &add))
@@ -3336,7 +3535,7 @@ open_input_bfds (lang_statement_union_type *s, enum open_bfd_mode mode)
                     section statement list.  Very likely the user
                     forgot -T, and whatever we do here will not meet
                     naive user expectations.  */
                     section statement list.  Very likely the user
                     forgot -T, and whatever we do here will not meet
                     naive user expectations.  */
-                 if (os_tail != lang_output_section_statement.tail)
+                 if (os_tail != lang_os_list.tail)
                    {
                      einfo (_("%P: warning: %s contains output sections;"
                               " did you forget -T?\n"),
                    {
                      einfo (_("%P: warning: %s contains output sections;"
                               " did you forget -T?\n"),
@@ -3407,11 +3606,12 @@ insert_undefined (const char *name)
 
   h = bfd_link_hash_lookup (link_info.hash, name, TRUE, FALSE, TRUE);
   if (h == NULL)
 
   h = bfd_link_hash_lookup (link_info.hash, name, TRUE, FALSE, TRUE);
   if (h == NULL)
-    einfo (_("%P%F: bfd_link_hash_lookup failed: %E\n"));
+    einfo (_("%F%P: 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;
   if (h->type == bfd_link_hash_new)
     {
       h->type = bfd_link_hash_undefined;
       h->u.undef.abfd = NULL;
+      h->non_ir_ref_regular = TRUE;
       if (is_elf_hash_table (link_info.hash))
        ((struct elf_link_hash_entry *) h)->mark = 1;
       bfd_link_add_undef (link_info.hash, h);
       if (is_elf_hash_table (link_info.hash))
        ((struct elf_link_hash_entry *) h)->mark = 1;
       bfd_link_add_undef (link_info.hash, h);
@@ -3476,7 +3676,7 @@ ldlang_check_require_defined_symbols (void)
       if (h == NULL
          || (h->type != bfd_link_hash_defined
              && h->type != bfd_link_hash_defweak))
       if (h == NULL
          || (h->type != bfd_link_hash_defined
              && h->type != bfd_link_hash_defweak))
-       einfo(_("%P%X: required symbol `%s' not defined\n"), ptr->name);
+       einfo(_("%X%P: required symbol `%s' not defined\n"), ptr->name);
     }
 }
 
     }
 }
 
@@ -3542,7 +3742,9 @@ update_wild_statements (lang_statement_union_type *s)
            case lang_wild_statement_enum:
              for (sec = s->wild_statement.section_list; sec != NULL;
                   sec = sec->next)
            case lang_wild_statement_enum:
              for (sec = s->wild_statement.section_list; sec != NULL;
                   sec = sec->next)
-               {
+               /* Don't sort .init/.fini sections.  */
+               if (strcmp (sec->spec.name, ".init") != 0
+                   && strcmp (sec->spec.name, ".fini") != 0)
                  switch (sec->spec.sorted)
                    {
                    case none:
                  switch (sec->spec.sorted)
                    {
                    case none:
@@ -3559,7 +3761,6 @@ update_wild_statements (lang_statement_union_type *s)
                    default:
                      break;
                    }
                    default:
                      break;
                    }
-               }
              break;
 
            case lang_constructors_statement_enum:
              break;
 
            case lang_constructors_statement_enum:
@@ -3567,11 +3768,8 @@ update_wild_statements (lang_statement_union_type *s)
              break;
 
            case lang_output_section_statement_enum:
              break;
 
            case lang_output_section_statement_enum:
-             /* Don't sort .init/.fini sections.  */
-             if (strcmp (s->output_section_statement.name, ".init") != 0
-                 && strcmp (s->output_section_statement.name, ".fini") != 0)
-               update_wild_statements
-                 (s->output_section_statement.children.head);
+             update_wild_statements
+               (s->output_section_statement.children.head);
              break;
 
            case lang_group_statement_enum:
              break;
 
            case lang_group_statement_enum:
@@ -3645,6 +3843,7 @@ map_input_to_output_sections
            {
            case normal_section:
            case overlay_section:
            {
            case normal_section:
            case overlay_section:
+           case first_overlay_section:
              break;
            case noalloc_section:
              flags = SEC_HAS_CONTENTS;
              break;
            case noalloc_section:
              flags = SEC_HAS_CONTENTS;
@@ -3717,21 +3916,26 @@ map_input_to_output_sections
    start of the list and places them after the output section
    statement specified by the insert.  This operation is complicated
    by the fact that we keep a doubly linked list of output section
    start of the list and places them after the output section
    statement specified by the insert.  This operation is complicated
    by the fact that we keep a doubly linked list of output section
-   statements as well as the singly linked list of all statements.  */
+   statements as well as the singly linked list of all statements.
+   FIXME someday: Twiddling with the list not only moves statements
+   from the user's script but also input and group statements that are
+   built from command line object files and --start-group.  We only
+   get away with this because the list pointers used by file_chain
+   and input_file_chain are not reordered, and processing via
+   statement_list after this point mostly ignores input statements.
+   One exception is the map file, where LOAD and START GROUP/END GROUP
+   can end up looking odd.  */
 
 static void
 
 static void
-process_insert_statements (void)
+process_insert_statements (lang_statement_union_type **start)
 {
   lang_statement_union_type **s;
   lang_output_section_statement_type *first_os = NULL;
   lang_output_section_statement_type *last_os = NULL;
   lang_output_section_statement_type *os;
 
 {
   lang_statement_union_type **s;
   lang_output_section_statement_type *first_os = NULL;
   lang_output_section_statement_type *last_os = NULL;
   lang_output_section_statement_type *os;
 
-  /* "start of list" is actually the statement immediately after
-     the special abs_section output statement, so that it isn't
-     reordered.  */
-  s = &lang_output_section_statement.head;
-  while (*(s = &(*s)->header.next) != NULL)
+  s = start;
+  while (*s != NULL)
     {
       if ((*s)->header.type == lang_output_section_statement_enum)
        {
     {
       if ((*s)->header.type == lang_output_section_statement_enum)
        {
@@ -3750,6 +3954,18 @@ process_insert_statements (void)
          if (first_os == NULL)
            first_os = last_os;
        }
          if (first_os == NULL)
            first_os = last_os;
        }
+      else if ((*s)->header.type == lang_group_statement_enum)
+       {
+         /* A user might put -T between --start-group and
+            --end-group.  One way this odd construct might arise is
+            from a wrapper around ld to change library search
+            behaviour.  For example:
+            #! /bin/sh
+            exec real_ld --start-group "$@" --end-group
+            This isn't completely unreasonable so go looking inside a
+            group statement for insert statements.  */
+         process_insert_statements (&(*s)->group_statement.children.head);
+       }
       else if ((*s)->header.type == lang_insert_statement_enum)
        {
          lang_insert_statement_type *i = &(*s)->insert_statement;
       else if ((*s)->header.type == lang_insert_statement_enum)
        {
          lang_insert_statement_type *i = &(*s)->insert_statement;
@@ -3781,8 +3997,7 @@ process_insert_statements (void)
              if (last_os->next == NULL)
                {
                  next = &first_os->prev->next;
              if (last_os->next == NULL)
                {
                  next = &first_os->prev->next;
-                 lang_output_section_statement.tail
-                   = (lang_statement_union_type **) next;
+                 lang_os_list.tail = (lang_statement_union_type **) next;
                }
              else
                last_os->next->prev = first_os->prev;
                }
              else
                last_os->next->prev = first_os->prev;
@@ -3791,8 +4006,7 @@ process_insert_statements (void)
              if (where->next == NULL)
                {
                  next = &last_os->next;
              if (where->next == NULL)
                {
                  next = &last_os->next;
-                 lang_output_section_statement.tail
-                   = (lang_statement_union_type **) next;
+                 lang_os_list.tail = (lang_statement_union_type **) next;
                }
              else
                where->next->prev = last_os;
                }
              else
                where->next->prev = last_os;
@@ -3852,18 +4066,19 @@ process_insert_statements (void)
            }
 
          ptr = insert_os_after (where);
            }
 
          ptr = insert_os_after (where);
-         /* Snip everything after the abs_section output statement we
-            know is at the start of the list, up to and including
-            the insert statement we are currently processing.  */
-         first = lang_output_section_statement.head->header.next;
-         lang_output_section_statement.head->header.next = (*s)->header.next;
-         /* Add them back where they belong.  */
+         /* Snip everything from the start of the list, up to and
+            including the insert statement we are currently processing.  */
+         first = *start;
+         *start = (*s)->header.next;
+         /* Add them back where they belong, minus the insert.  */
          *s = *ptr;
          if (*s == NULL)
            statement_list.tail = s;
          *ptr = first;
          *s = *ptr;
          if (*s == NULL)
            statement_list.tail = s;
          *ptr = first;
-         s = &lang_output_section_statement.head;
+         s = start;
+         continue;
        }
        }
+      s = &(*s)->header.next;
     }
 
   /* Undo constraint twiddling.  */
     }
 
   /* Undo constraint twiddling.  */
@@ -3893,7 +4108,7 @@ strip_excluded_output_sections (void)
       lang_reset_memory_regions ();
     }
 
       lang_reset_memory_regions ();
     }
 
-  for (os = &lang_output_section_statement.head->output_section_statement;
+  for (os = &lang_os_list.head->output_section_statement;
        os != NULL;
        os = os->next)
     {
        os != NULL;
        os = os->next)
     {
@@ -3944,9 +4159,7 @@ strip_excluded_output_sections (void)
 }
 
 /* Called from ldwrite to clear out asection.map_head and
 }
 
 /* Called from ldwrite to clear out asection.map_head and
-   asection.map_tail for use as link_orders in ldwrite.
-   FIXME: Except for sh64elf.em which starts creating link_orders in
-   its after_allocation routine so needs to call it early.  */
+   asection.map_tail for use as link_orders in ldwrite.  */
 
 void
 lang_clear_os_map (void)
 
 void
 lang_clear_os_map (void)
@@ -3956,7 +4169,7 @@ lang_clear_os_map (void)
   if (map_head_is_link_order)
     return;
 
   if (map_head_is_link_order)
     return;
 
-  for (os = &lang_output_section_statement.head->output_section_statement;
+  for (os = &lang_os_list.head->output_section_statement;
        os != NULL;
        os = os->next)
     {
        os != NULL;
        os = os->next)
     {
@@ -4045,9 +4258,7 @@ print_assignment (lang_assignment_statement_type *assignment,
       const char *dst = assignment->exp->assign.dst;
 
       is_dot = (dst[0] == '.' && dst[1] == 0);
       const char *dst = assignment->exp->assign.dst;
 
       is_dot = (dst[0] == '.' && dst[1] == 0);
-      if (!is_dot)
-       expld.assign_name = dst;
-      tree = assignment->exp->assign.src;
+      tree = assignment->exp;
     }
 
   osec = output_section->bfd_section;
     }
 
   osec = output_section->bfd_section;
@@ -4082,7 +4293,9 @@ print_assignment (lang_assignment_statement_type *assignment,
 
          h = bfd_link_hash_lookup (link_info.hash, assignment->exp->assign.dst,
                                    FALSE, FALSE, TRUE);
 
          h = bfd_link_hash_lookup (link_info.hash, assignment->exp->assign.dst,
                                    FALSE, FALSE, TRUE);
-         if (h)
+         if (h != NULL
+             && (h->type == bfd_link_hash_defined
+                 || h->type == bfd_link_hash_defweak))
            {
              value = h->u.def.value;
              value += h->u.def.section->output_section->vma;
            {
              value = h->u.def.value;
              value += h->u.def.section->output_section->vma;
@@ -4141,7 +4354,7 @@ print_one_symbol (struct bfd_link_hash_entry *hash_entry, void *ptr)
              + hash_entry->u.def.section->output_offset
              + hash_entry->u.def.section->output_section->vma));
 
              + hash_entry->u.def.section->output_offset
              + hash_entry->u.def.section->output_section->vma));
 
-      minfo ("             %T\n", hash_entry->root.string);
+      minfo ("             %pT\n", hash_entry->root.string);
     }
 
   return TRUE;
     }
 
   return TRUE;
@@ -4229,7 +4442,7 @@ print_input_section (asection *i, bfd_boolean is_discarded)
        size = 0;
     }
 
        size = 0;
     }
 
-  minfo ("0x%V %W %B\n", addr, size, i->owner);
+  minfo ("0x%V %W %pB\n", addr, size, i->owner);
 
   if (size != i->rawsize && i->rawsize != 0)
     {
 
   if (size != i->rawsize && i->rawsize != 0)
     {
@@ -4674,8 +4887,9 @@ insert_pad (lang_statement_union_type **ptr,
     }
   pad->padding_statement.output_offset = dot - output_section->vma;
   pad->padding_statement.size = alignment_needed;
     }
   pad->padding_statement.output_offset = dot - output_section->vma;
   pad->padding_statement.size = alignment_needed;
-  output_section->size = TO_SIZE (dot + TO_ADDR (alignment_needed)
-                                 - output_section->vma);
+  if (!(output_section->flags & SEC_FIXED_SIZE))
+    output_section->size = TO_SIZE (dot + TO_ADDR (alignment_needed)
+                                   - output_section->vma);
 }
 
 /* Work out how much this section will move the dot point.  */
 }
 
 /* Work out how much this section will move the dot point.  */
@@ -4705,8 +4919,10 @@ size_input_section
         is greater than any seen before, then record it too.  Perform
         the alignment by inserting a magic 'padding' statement.  */
 
         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;
+      if (output_section_statement->subsection_alignment != NULL)
+       i->alignment_power
+         = exp_get_power (output_section_statement->subsection_alignment,
+                          "subsection alignment");
 
       if (o->alignment_power < i->alignment_power)
        o->alignment_power = i->alignment_power;
 
       if (o->alignment_power < i->alignment_power)
        o->alignment_power = i->alignment_power;
@@ -4724,7 +4940,8 @@ size_input_section
 
       /* Mark how big the output section must be to contain this now.  */
       dot += TO_ADDR (i->size);
 
       /* Mark how big the output section must be to contain this now.  */
       dot += TO_ADDR (i->size);
-      o->size = TO_SIZE (dot - o->vma);
+      if (!(o->flags & SEC_FIXED_SIZE))
+       o->size = TO_SIZE (dot - o->vma);
     }
 
   return dot;
     }
 
   return dot;
@@ -4954,7 +5171,7 @@ os_region_check (lang_output_section_statement_type *os,
     {
       if (tree != NULL)
        {
     {
       if (tree != NULL)
        {
-         einfo (_("%X%P: address 0x%v of %B section `%s'"
+         einfo (_("%X%P: address 0x%v of %pB section `%s'"
                   " is not within region `%s'\n"),
                 region->current,
                 os->bfd_section->owner,
                   " is not within region `%s'\n"),
                 region->current,
                 os->bfd_section->owner,
@@ -4965,7 +5182,7 @@ os_region_check (lang_output_section_statement_type *os,
        {
          region->had_full_message = TRUE;
 
        {
          region->had_full_message = TRUE;
 
-         einfo (_("%X%P: %B section `%s' will not fit in region `%s'\n"),
+         einfo (_("%X%P: %pB section `%s' will not fit in region `%s'\n"),
                 os->bfd_section->owner,
                 os->bfd_section->name,
                 region->name_list.name);
                 os->bfd_section->owner,
                 os->bfd_section->name,
                 region->name_list.name);
@@ -5046,7 +5263,7 @@ lang_size_sections_1
                      dot += expld.result.section->vma;
                  }
                else if (expld.phase != lang_mark_phase_enum)
                      dot += expld.result.section->vma;
                  }
                else if (expld.phase != lang_mark_phase_enum)
-                 einfo (_("%F%S: non constant or forward reference"
+                 einfo (_("%F%P:%pS: non constant or forward reference"
                           " address expression for section %s\n"),
                         os->addr_tree, os->name);
              }
                           " address expression for section %s\n"),
                         os->addr_tree, os->name);
              }
@@ -5071,14 +5288,15 @@ lang_size_sections_1
                    || os->children.head->header.next != NULL
                    || (os->children.head->header.type
                        != lang_input_section_enum))
                    || os->children.head->header.next != NULL
                    || (os->children.head->header.type
                        != lang_input_section_enum))
-                 einfo (_("%P%X: Internal error on COFF shared library"
+                 einfo (_("%X%P: internal error on COFF shared library"
                           " section %s\n"), os->name);
 
                input = os->children.head->input_section.section;
                bfd_set_section_vma (os->bfd_section->owner,
                                     os->bfd_section,
                                     bfd_section_vma (input->owner, input));
                           " section %s\n"), os->name);
 
                input = os->children.head->input_section.section;
                bfd_set_section_vma (os->bfd_section->owner,
                                     os->bfd_section,
                                     bfd_section_vma (input->owner, input));
-               os->bfd_section->size = input->size;
+               if (!(os->bfd_section->flags & SEC_FIXED_SIZE))
+                 os->bfd_section->size = input->size;
                break;
              }
 
                break;
              }
 
@@ -5129,7 +5347,7 @@ lang_size_sections_1
                           overridden by the using the --no-check-sections
                           switch.  */
                        if (command_line.check_section_addresses)
                           overridden by the using the --no-check-sections
                           switch.  */
                        if (command_line.check_section_addresses)
-                         einfo (_("%P%F: error: no memory region specified"
+                         einfo (_("%F%P: error: no memory region specified"
                                   " for loadable section `%s'\n"),
                                 bfd_get_section_name (link_info.output_bfd,
                                                       os->bfd_section));
                                   " for loadable section `%s'\n"),
                                 bfd_get_section_name (link_info.output_bfd,
                                                       os->bfd_section));
@@ -5144,7 +5362,8 @@ lang_size_sections_1
                    section_alignment = os->bfd_section->alignment_power;
                  }
                else
                    section_alignment = os->bfd_section->alignment_power;
                  }
                else
-                 section_alignment = os->section_alignment;
+                 section_alignment = exp_get_power (os->section_alignment,
+                                                    "section alignment");
 
                /* Align to what the section needs.  */
                if (section_alignment > 0)
 
                /* Align to what the section needs.  */
                if (section_alignment > 0)
@@ -5193,7 +5412,9 @@ lang_size_sections_1
                          + os->block_value - 1)
                         & - (bfd_vma) os->block_value);
 
                          + os->block_value - 1)
                         & - (bfd_vma) os->block_value);
 
-               os->bfd_section->size = TO_SIZE (after - os->bfd_section->vma);
+               if (!(os->bfd_section->flags & SEC_FIXED_SIZE))
+                 os->bfd_section->size = TO_SIZE (after
+                                                  - os->bfd_section->vma);
              }
 
            /* Set section lma.  */
              }
 
            /* Set section lma.  */
@@ -5220,7 +5441,8 @@ lang_size_sections_1
                       only align according to the value in the output
                       statement.  */
                    if (os->lma_region != os->region)
                       only align according to the value in the output
                       statement.  */
                    if (os->lma_region != os->region)
-                     section_alignment = os->section_alignment;
+                     section_alignment = exp_get_power (os->section_alignment,
+                                                        "section alignment");
                    if (section_alignment > 0)
                      lma = align_power (lma, section_alignment);
                  }
                    if (section_alignment > 0)
                      lma = align_power (lma, section_alignment);
                  }
@@ -5285,13 +5507,14 @@ lang_size_sections_1
               important, if an orphan section is placed after an
               otherwise empty output section that has an explicit lma
               set, we want that lma reflected in the orphans lma.  */
               important, if an orphan section is placed after an
               otherwise empty output section that has an explicit lma
               set, we want that lma reflected in the orphans lma.  */
-           if (!IGNORE_SECTION (os->bfd_section)
-               && (os->bfd_section->size != 0
-                   || (r->last_os == NULL
-                       && os->bfd_section->vma != os->bfd_section->lma)
-                   || (r->last_os != NULL
-                       && dot >= (r->last_os->output_section_statement
-                                  .bfd_section->vma)))
+           if (((!IGNORE_SECTION (os->bfd_section)
+                 && (os->bfd_section->size != 0
+                     || (r->last_os == NULL
+                         && os->bfd_section->vma != os->bfd_section->lma)
+                     || (r->last_os != NULL
+                         && dot >= (r->last_os->output_section_statement
+                                    .bfd_section->vma))))
+                || os->sectype == first_overlay_section)
                && os->lma_region == NULL
                && !bfd_link_relocatable (&link_info))
              r->last_os = s;
                && os->lma_region == NULL
                && !bfd_link_relocatable (&link_info))
              r->last_os = s;
@@ -5378,8 +5601,10 @@ lang_size_sections_1
            if (size < TO_SIZE ((unsigned) 1))
              size = TO_SIZE ((unsigned) 1);
            dot += TO_ADDR (size);
            if (size < TO_SIZE ((unsigned) 1))
              size = TO_SIZE ((unsigned) 1);
            dot += TO_ADDR (size);
-           output_section_statement->bfd_section->size
-             = TO_SIZE (dot - output_section_statement->bfd_section->vma);
+           if (!(output_section_statement->bfd_section->flags
+                 & SEC_FIXED_SIZE))
+             output_section_statement->bfd_section->size
+               = TO_SIZE (dot - output_section_statement->bfd_section->vma);
 
          }
          break;
 
          }
          break;
@@ -5394,8 +5619,10 @@ lang_size_sections_1
              output_section_statement->bfd_section;
            size = bfd_get_reloc_size (s->reloc_statement.howto);
            dot += TO_ADDR (size);
              output_section_statement->bfd_section;
            size = bfd_get_reloc_size (s->reloc_statement.howto);
            dot += TO_ADDR (size);
-           output_section_statement->bfd_section->size
-             = TO_SIZE (dot - output_section_statement->bfd_section->vma);
+           if (!(output_section_statement->bfd_section->flags
+                 & SEC_FIXED_SIZE))
+             output_section_statement->bfd_section->size
+               = TO_SIZE (dot - output_section_statement->bfd_section->vma);
          }
          break;
 
          }
          break;
 
@@ -5406,8 +5633,9 @@ lang_size_sections_1
          break;
 
        case lang_object_symbols_statement_enum:
          break;
 
        case lang_object_symbols_statement_enum:
-         link_info.create_object_symbols_section =
-           output_section_statement->bfd_section;
+         link_info.create_object_symbols_section
+           = output_section_statement->bfd_section;
+         output_section_statement->bfd_section->flags |= SEC_KEEP;
          break;
 
        case lang_output_statement_enum:
          break;
 
        case lang_output_statement_enum:
@@ -5424,7 +5652,7 @@ lang_size_sections_1
                bfd_boolean again;
 
                if (!bfd_relax_section (i->owner, i, &link_info, &again))
                bfd_boolean again;
 
                if (!bfd_relax_section (i->owner, i, &link_info, &again))
-                 einfo (_("%P%F: can't relax section: %E\n"));
+                 einfo (_("%F%P: can't relax section: %E\n"));
                if (again)
                  *relax = TRUE;
              }
                if (again)
                  *relax = TRUE;
              }
@@ -6083,6 +6311,24 @@ undef_start_stop (struct bfd_link_hash_entry *h)
       || strcmp (h->u.def.section->name,
                 h->u.def.section->output_section->name) != 0)
     {
       || strcmp (h->u.def.section->name,
                 h->u.def.section->output_section->name) != 0)
     {
+      asection *sec = bfd_get_section_by_name (link_info.output_bfd,
+                                              h->u.def.section->name);
+      if (sec != NULL)
+       {
+         /* When there are more than one input sections with the same
+            section name, SECNAME, linker picks the first one to define
+            __start_SECNAME and __stop_SECNAME symbols.  When the first
+            input section is removed by comdat group, we need to check
+            if there is still an output section with section name
+            SECNAME.  */
+         asection *i;
+         for (i = sec->map_head.s; i != NULL; i = i->map_head.s)
+           if (strcmp (h->u.def.section->name, i->name) == 0)
+             {
+               h->u.def.section = i;
+               return;
+             }
+       }
       h->type = bfd_link_hash_undefined;
       h->u.undef.abfd = NULL;
     }
       h->type = bfd_link_hash_undefined;
       h->u.undef.abfd = NULL;
     }
@@ -6170,10 +6416,12 @@ lang_end (void)
     warn = TRUE;
 
   /* Force the user to specify a root when generating a relocatable with
     warn = TRUE;
 
   /* Force the user to specify a root when generating a relocatable with
-     --gc-sections.  */
-  if (link_info.gc_sections && bfd_link_relocatable (&link_info)
+     --gc-sections, unless --gc-keep-exported was also given.  */
+  if (bfd_link_relocatable (&link_info)
+      && link_info.gc_sections
+      && !link_info.gc_keep_exported
       && !(entry_from_cmdline || undef_from_cmdline))
       && !(entry_from_cmdline || undef_from_cmdline))
-    einfo (_("%P%F: gc-sections requires either an entry or "
+    einfo (_("%F%P: gc-sections requires either an entry or "
             "an undefined symbol\n"));
 
   if (entry_symbol.name == NULL)
             "an undefined symbol\n"));
 
   if (entry_symbol.name == NULL)
@@ -6198,7 +6446,7 @@ lang_end (void)
                                    h->u.def.section->output_section)
             + h->u.def.section->output_offset);
       if (!bfd_set_start_address (link_info.output_bfd, val))
                                    h->u.def.section->output_section)
             + h->u.def.section->output_offset);
       if (!bfd_set_start_address (link_info.output_bfd, val))
-       einfo (_("%P%F:%s: can't set start address\n"), entry_symbol.name);
+       einfo (_("%F%P: %s: can't set start address\n"), entry_symbol.name);
     }
   else
     {
     }
   else
     {
@@ -6211,7 +6459,7 @@ lang_end (void)
       if (*send == '\0')
        {
          if (!bfd_set_start_address (link_info.output_bfd, val))
       if (*send == '\0')
        {
          if (!bfd_set_start_address (link_info.output_bfd, val))
-           einfo (_("%P%F: can't set start address\n"));
+           einfo (_("%F%P: can't set start address\n"));
        }
       else
        {
        }
       else
        {
@@ -6230,7 +6478,7 @@ lang_end (void)
              if (!(bfd_set_start_address
                    (link_info.output_bfd,
                     bfd_get_section_vma (link_info.output_bfd, ts))))
              if (!(bfd_set_start_address
                    (link_info.output_bfd,
                     bfd_get_section_vma (link_info.output_bfd, ts))))
-               einfo (_("%P%F: can't set start address\n"));
+               einfo (_("%F%P: can't set start address\n"));
            }
          else
            {
            }
          else
            {
@@ -6289,8 +6537,8 @@ lang_check (void)
                  != bfd_get_flavour (link_info.output_bfd)))
          && (bfd_get_file_flags (input_bfd) & HAS_RELOC) != 0)
        {
                  != bfd_get_flavour (link_info.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"),
+         einfo (_("%F%P: relocatable linking with relocations from"
+                  " format %s (%pB) to format %s (%pB) is not supported\n"),
                 bfd_get_target (input_bfd), input_bfd,
                 bfd_get_target (link_info.output_bfd), link_info.output_bfd);
          /* einfo with %F exits.  */
                 bfd_get_target (input_bfd), input_bfd,
                 bfd_get_target (link_info.output_bfd), link_info.output_bfd);
          /* einfo with %F exits.  */
@@ -6299,7 +6547,7 @@ lang_check (void)
       if (compatible == NULL)
        {
          if (command_line.warn_mismatch)
       if (compatible == NULL)
        {
          if (command_line.warn_mismatch)
-           einfo (_("%P%X: %s architecture of input file `%B'"
+           einfo (_("%X%P: %s architecture of input file `%pB'"
                     " is incompatible with %s output\n"),
                   bfd_printable_name (input_bfd), input_bfd,
                   bfd_printable_name (link_info.output_bfd));
                     " is incompatible with %s output\n"),
                   bfd_printable_name (input_bfd), input_bfd,
                   bfd_printable_name (link_info.output_bfd));
@@ -6321,8 +6569,8 @@ lang_check (void)
          if (!bfd_merge_private_bfd_data (input_bfd, &link_info))
            {
              if (command_line.warn_mismatch)
          if (!bfd_merge_private_bfd_data (input_bfd, &link_info))
            {
              if (command_line.warn_mismatch)
-               einfo (_("%P%X: failed to merge target specific data"
-                        " of file %B\n"), input_bfd);
+               einfo (_("%X%P: failed to merge target specific data"
+                        " of file %pB\n"), input_bfd);
            }
          if (!command_line.warn_mismatch)
            bfd_set_error_handler (pfn);
            }
          if (!command_line.warn_mismatch)
            bfd_set_error_handler (pfn);
@@ -6392,7 +6640,7 @@ lang_one_common (struct bfd_link_hash_entry *h, void *info)
 
   section = h->u.c.p->section;
   if (!bfd_define_common_symbol (link_info.output_bfd, &link_info, h))
 
   section = h->u.c.p->section;
   if (!bfd_define_common_symbol (link_info.output_bfd, &link_info, h))
-    einfo (_("%P%F: Could not define common symbol `%T': %E\n"),
+    einfo (_("%F%P: could not define common symbol `%pT': %E\n"),
           h->root.string);
 
   if (config.map_file != NULL)
           h->root.string);
 
   if (config.map_file != NULL)
@@ -6448,7 +6696,7 @@ lang_one_common (struct bfd_link_hash_entry *h, void *info)
          ++len;
        }
 
          ++len;
        }
 
-      minfo ("%B\n", section->owner);
+      minfo ("%pB\n", section->owner);
     }
 
   return TRUE;
     }
 
   return TRUE;
@@ -6479,7 +6727,7 @@ ldlang_place_orphan (asection *s)
       int constraint = 0;
 
       if (config.orphan_handling == orphan_handling_error)
       int constraint = 0;
 
       if (config.orphan_handling == orphan_handling_error)
-       einfo (_("%X%P: error: unplaced orphan section `%A' from `%B'.\n"),
+       einfo (_("%X%P: error: unplaced orphan section `%pA' from `%pB'\n"),
               s, s->owner);
 
       if (config.unique_orphan_sections || unique_section_p (s, NULL))
               s, s->owner);
 
       if (config.unique_orphan_sections || unique_section_p (s, NULL))
@@ -6497,8 +6745,8 @@ ldlang_place_orphan (asection *s)
        }
 
       if (config.orphan_handling == orphan_handling_warn)
        }
 
       if (config.orphan_handling == orphan_handling_warn)
-       einfo (_("%P: warning: orphan section `%A' from `%B' being "
-                "placed in section `%s'.\n"),
+       einfo (_("%P: warning: orphan section `%pA' from `%pB' being "
+                "placed in section `%s'\n"),
               s, s->owner, os->name);
     }
 }
               s, s->owner, os->name);
     }
 }
@@ -6588,7 +6836,7 @@ lang_set_flags (lang_memory_region_type *ptr, const char *flags, int invert)
          break;
 
        default:
          break;
 
        default:
-         einfo (_("%P%F: invalid character %c (%d) in flags\n"),
+         einfo (_("%F%P: invalid character %c (%d) in flags\n"),
                 *flags, *flags);
          break;
        }
                 *flags, *flags);
          break;
        }
@@ -6664,25 +6912,6 @@ lang_add_output (const char *name, int from_script)
     }
 }
 
     }
 }
 
-static int
-topower (int x)
-{
-  unsigned int i = 1;
-  int l;
-
-  if (x < 0)
-    return -1;
-
-  for (l = 0; l < 32; l++)
-    {
-      if (i >= (unsigned int) x)
-       return l;
-      i <<= 1;
-    }
-
-  return 0;
-}
-
 lang_output_section_statement_type *
 lang_enter_output_section_statement (const char *output_section_statement_name,
                                     etree_type *address_exp,
 lang_output_section_statement_type *
 lang_enter_output_section_statement (const char *output_section_statement_name,
                                     etree_type *address_exp,
@@ -6715,13 +6944,11 @@ lang_enter_output_section_statement (const char *output_section_statement_name,
 
   os->align_lma_with_input = align_with_input == ALIGN_WITH_INPUT;
   if (os->align_lma_with_input && align != NULL)
 
   os->align_lma_with_input = align_with_input == ALIGN_WITH_INPUT;
   if (os->align_lma_with_input && align != NULL)
-    einfo (_("%F%P:%S: error: align with input and explicit align specified\n"),
+    einfo (_("%F%P:%pS: error: align with input and explicit align specified\n"),
           NULL);
 
           NULL);
 
-  os->subsection_alignment =
-    topower (exp_get_value_int (subalign, -1, "subsection alignment"));
-  os->section_alignment =
-    topower (exp_get_value_int (align, -1, "section alignment"));
+  os->subsection_alignment = subalign;
+  os->section_alignment = align;
 
   os->load_base = ebase;
   return os;
 
   os->load_base = ebase;
   return os;
@@ -6751,7 +6978,7 @@ lang_reset_memory_regions (void)
       p->last_os = NULL;
     }
 
       p->last_os = NULL;
     }
 
-  for (os = &lang_output_section_statement.head->output_section_statement;
+  for (os = &lang_os_list.head->output_section_statement;
        os != NULL;
        os = os->next)
     {
        os != NULL;
        os = os->next)
     {
@@ -6763,7 +6990,8 @@ lang_reset_memory_regions (void)
     {
       /* Save the last size for possible use by bfd_relax_section.  */
       o->rawsize = o->size;
     {
       /* Save the last size for possible use by bfd_relax_section.  */
       o->rawsize = o->size;
-      o->size = 0;
+      if (!(o->flags & SEC_FIXED_SIZE))
+       o->size = 0;
     }
 }
 
     }
 }
 
@@ -7043,7 +7271,8 @@ find_rescan_insertion (lang_input_statement_type *add)
   for (iter = before ? &before->next : &file_chain.head->input_statement.next;
        *iter != NULL;
        iter = &(*iter)->input_statement.next)
   for (iter = before ? &before->next : &file_chain.head->input_statement.next;
        *iter != NULL;
        iter = &(*iter)->input_statement.next)
-    if ((*iter)->input_statement.the_bfd->my_archive == NULL)
+    if (!(*iter)->input_statement.flags.claim_archive
+       && (*iter)->input_statement.the_bfd->my_archive == NULL)
       break;
 
   return iter;
       break;
 
   return iter;
@@ -7129,7 +7358,7 @@ lang_propagate_lma_regions (void)
 {
   lang_output_section_statement_type *os;
 
 {
   lang_output_section_statement_type *os;
 
-  for (os = &lang_output_section_statement.head->output_section_statement;
+  for (os = &lang_os_list.head->output_section_statement;
        os != NULL;
        os = os->next)
     {
        os != NULL;
        os = os->next)
     {
@@ -7161,12 +7390,15 @@ lang_process (void)
   lang_place_undefineds ();
 
   if (!bfd_section_already_linked_table_init ())
   lang_place_undefineds ();
 
   if (!bfd_section_already_linked_table_init ())
-    einfo (_("%P%F: Failed to create hash table\n"));
+    einfo (_("%F%P: can not create hash table: %E\n"));
 
   /* Create a bfd for each input file.  */
   current_target = default_target;
   lang_statement_iteration++;
   open_input_bfds (statement_list.head, OPEN_BFD_NORMAL);
 
   /* Create a bfd for each input file.  */
   current_target = default_target;
   lang_statement_iteration++;
   open_input_bfds (statement_list.head, OPEN_BFD_NORMAL);
+  /* open_input_bfds also handles assignments, so we can give values
+     to symbolic origin/length now.  */
+  lang_do_memory_regions ();
 
 #ifdef ENABLE_PLUGINS
   if (link_info.lto_plugin_active)
 
 #ifdef ENABLE_PLUGINS
   if (link_info.lto_plugin_active)
@@ -7185,7 +7417,7 @@ lang_process (void)
       files = file_chain;
       inputfiles = input_file_chain;
       if (plugin_call_all_symbols_read ())
       files = file_chain;
       inputfiles = input_file_chain;
       if (plugin_call_all_symbols_read ())
-       einfo (_("%P%F: %s: plugin reported error after all symbols read\n"),
+       einfo (_("%F%P: %s: plugin reported error after all symbols read\n"),
               plugin_error_plugin ());
       /* Open any newly added files, updating the file chains.  */
       open_input_bfds (*added.tail, OPEN_BFD_NORMAL);
               plugin_error_plugin ());
       /* Open any newly added files, updating the file chains.  */
       open_input_bfds (*added.tail, OPEN_BFD_NORMAL);
@@ -7309,8 +7541,6 @@ lang_process (void)
   /* PR 13683: We must rerun the assignments prior to running garbage
      collection in order to make sure that all symbol aliases are resolved.  */
   lang_do_assignments (lang_mark_phase_enum);
   /* PR 13683: We must rerun the assignments prior to running garbage
      collection in order to make sure that all symbol aliases are resolved.  */
   lang_do_assignments (lang_mark_phase_enum);
-
-  lang_do_memory_regions();
   expld.phase = lang_first_phase_enum;
 
   /* Size up the common data.  */
   expld.phase = lang_first_phase_enum;
 
   /* Size up the common data.  */
@@ -7332,7 +7562,9 @@ lang_process (void)
   lang_statement_iteration++;
   map_input_to_output_sections (statement_list.head, NULL, NULL);
 
   lang_statement_iteration++;
   map_input_to_output_sections (statement_list.head, NULL, NULL);
 
-  process_insert_statements ();
+  /* Start at the statement immediately after the special abs_section
+     output statement, so that it isn't reordered.  */
+  process_insert_statements (&lang_os_list.head->header.next);
 
   /* Find any sections not attached explicitly and handle them.  */
   lang_place_orphans ();
 
   /* Find any sections not attached explicitly and handle them.  */
   lang_place_orphans ();
@@ -7395,8 +7627,11 @@ lang_process (void)
   /* Fix any __start, __stop, .startof. or .sizeof. symbols.  */
   lang_finalize_start_stop ();
 
   /* Fix any __start, __stop, .startof. or .sizeof. symbols.  */
   lang_finalize_start_stop ();
 
-  /* Do all the assignments, now that we know the final resting places
-     of all the symbols.  */
+  /* Do all the assignments again, to report errors.  Assignment
+     statements are processed multiple times, updating symbols; In
+     open_input_bfds, lang_do_assignments, and lang_size_sections.
+     Since lang_relax_sections calls lang_do_assignments, symbols are
+     also updated in ldemul_after_allocation.  */
   lang_do_assignments (lang_final_phase_enum);
 
   ldemul_finish ();
   lang_do_assignments (lang_final_phase_enum);
 
   ldemul_finish ();
@@ -7589,7 +7824,7 @@ lang_startup (const char *name)
 {
   if (first_file->filename != NULL)
     {
 {
   if (first_file->filename != NULL)
     {
-      einfo (_("%P%F: multiple STARTUP files\n"));
+      einfo (_("%F%P: multiple STARTUP files\n"));
     }
   first_file->filename = name;
   first_file->local_sym_name = name;
     }
   first_file->filename = name;
   first_file->local_sym_name = name;
@@ -7635,7 +7870,7 @@ lang_get_regions (lang_memory_region_type **region,
     *region = lang_memory_region_lookup (memspec, FALSE);
 
   if (have_lma && lma_memspec != 0)
     *region = lang_memory_region_lookup (memspec, FALSE);
 
   if (have_lma && lma_memspec != 0)
-    einfo (_("%X%P:%S: section has both a load address and a load region\n"),
+    einfo (_("%X%P:%pS: section has both a load address and a load region\n"),
           NULL);
 }
 
           NULL);
 }
 
@@ -7737,7 +7972,7 @@ lang_new_phdr (const char *name,
   n = (struct lang_phdr *) stat_alloc (sizeof (struct lang_phdr));
   n->next = NULL;
   n->name = name;
   n = (struct lang_phdr *) stat_alloc (sizeof (struct lang_phdr));
   n->next = NULL;
   n->name = name;
-  n->type = exp_get_value_int (type, 0, "program header type");
+  n->type = exp_get_vma (type, 0, "program header type");
   n->filehdr = filehdr;
   n->phdrs = phdrs;
   n->at = at;
   n->filehdr = filehdr;
   n->phdrs = phdrs;
   n->at = at;
@@ -7750,7 +7985,7 @@ lang_new_phdr (const char *name,
        && (*pp)->type == 1
        && !((*pp)->filehdr || (*pp)->phdrs))
       {
        && (*pp)->type == 1
        && !((*pp)->filehdr || (*pp)->phdrs))
       {
-       einfo (_("%X%P:%S: PHDRS and FILEHDR are not supported"
+       einfo (_("%X%P:%pS: PHDRS and FILEHDR are not supported"
                 " when prior PT_LOAD headers lack them\n"), NULL);
        hdrs = FALSE;
       }
                 " when prior PT_LOAD headers lack them\n"), NULL);
        hdrs = FALSE;
       }
@@ -7781,7 +8016,7 @@ lang_record_phdrs (void)
       bfd_vma at;
 
       c = 0;
       bfd_vma at;
 
       c = 0;
-      for (os = &lang_output_section_statement.head->output_section_statement;
+      for (os = &lang_os_list.head->output_section_statement;
           os != NULL;
           os = os->next)
        {
           os != NULL;
           os = os->next)
        {
@@ -7867,7 +8102,7 @@ lang_record_phdrs (void)
   free (secs);
 
   /* Make sure all the phdr assignments succeeded.  */
   free (secs);
 
   /* Make sure all the phdr assignments succeeded.  */
-  for (os = &lang_output_section_statement.head->output_section_statement;
+  for (os = &lang_os_list.head->output_section_statement;
        os != NULL;
        os = os->next)
     {
        os != NULL;
        os = os->next)
     {
@@ -8074,7 +8309,7 @@ lang_leave_overlay (etree_type *lma_expr,
       if (l->next == 0)
        {
          l->os->load_base = lma_expr;
       if (l->next == 0)
        {
          l->os->load_base = lma_expr;
-         l->os->sectype = normal_section;
+         l->os->sectype = first_overlay_section;
        }
       if (phdrs != NULL && l->os->phdrs == NULL)
        l->os->phdrs = phdrs;
        }
       if (phdrs != NULL && l->os->phdrs == NULL)
        l->os->phdrs = phdrs;
This page took 0.06786 seconds and 4 git commands to generate.