x86: drop stale Mem enumerator
[deliverable/binutils-gdb.git] / ld / ldlang.c
index 0041f57116d75b49f3c83f796759aff7284be3b9..3f25b363d0c22818dcb869f75361be6c9c082cd5 100644 (file)
@@ -1,5 +1,5 @@
 /* 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.
 
@@ -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;
+/* 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];
@@ -97,7 +103,17 @@ const char *output_target;
 lang_output_section_statement_type *abs_output_section;
 lang_statement_list_type lang_output_section_statement;
 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 };
+/* 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";
@@ -1879,6 +1895,7 @@ lang_insert_orphan (asection *s,
     {
       asection *snew, *as;
       bfd_boolean place_after = place->stmt == NULL;
+      bfd_boolean insert_after = TRUE;
 
       snew = os->bfd_section;
 
@@ -1934,7 +1951,9 @@ lang_insert_orphan (asection *s,
          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;
+         bfd_boolean after_sec_note = FALSE;
+
+         static asection *first_orphan_note = NULL;
 
          /* Group and sort output note section by alignments in
             ascending order.  */
@@ -1942,11 +1961,12 @@ lang_insert_orphan (asection *s,
          if (elf_section_type (s) == SHT_NOTE
              && (s->flags & SEC_LOAD) != 0)
            {
-             /* Search forward for the last output note section
-                with equal or larger alignments.  */
-             asection *first_note = NULL;
+             /* 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.  */
 
-             for (sec = as;
+             first_orphan_note = NULL;
+             for (sec = link_info.output_bfd->sections;
                   (sec != NULL
                    && !bfd_is_abs_section (sec));
                   sec = sec->next)
@@ -1954,52 +1974,34 @@ lang_insert_orphan (asection *s,
                    && elf_section_type (sec) == SHT_NOTE
                    && (sec->flags & SEC_LOAD) != 0)
                  {
-                   if (!first_note)
-                     first_note = sec;
+                   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 (after_sec)
-               after_sec_note = TRUE;
-             else
+             /* 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)
                {
-                 /* Search backward for the first output note section
-                    as well as the last output note section with equal
-                    or larger alignments.  */
-                 after_sec = NULL;
-                 for (sec = as;
-                      (sec != NULL
-                       && !bfd_is_abs_section (sec));
-                      sec = sec->prev)
-                   if (sec != snew
-                       && elf_section_type (sec) == SHT_NOTE
-                       && (sec->flags & SEC_LOAD) != 0)
-                     {
-                       first_note = sec;
-                       if (!after_sec
-                           && sec->alignment_power >= s->alignment_power)
-                         after_sec = sec;
-                     }
-
-                 /* If this will be the first note section, it can be
-                    placed at the default location.  */
-                 after_sec_note = first_note != NULL;
-                 if (after_sec == NULL && after_sec_note)
-                   {
-                     /* If all output note sections have smaller
-                        alignments, place the section before all
-                        output note sections.  AFTER_SEC will be
-                        NULL if FIRST_NOTE is the first output
-                        section.  */
-                     after_sec = first_note->prev;
-                   }
+                 /* 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
+         else if (first_orphan_note)
            {
-             /* Don't place non-note sections in the middle of note
-                sections.  */
+             /* Don't place non-note sections in the middle of orphan
+                note sections.  */
              after_sec_note = TRUE;
              after_sec = as;
              for (sec = as->next;
@@ -2015,20 +2017,68 @@ lang_insert_orphan (asection *s,
            {
              if (after_sec)
                {
-                 /* Insert OS after AFTER_SEC output statement.  */
-                 lang_output_section_statement_type *stmt;
-                 for (stmt = after;
-                      stmt != NULL;
-                      stmt = stmt->next)
-                   if (stmt->bfd_section == 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)
                      {
-                       place_after = TRUE;
-                       after = stmt;
-                       break;
+                       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 || after_sec->next != snew)
+             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);
@@ -2036,8 +2086,14 @@ lang_insert_orphan (asection *s,
                  /* Place SNEW after AFTER_SEC.  If AFTER_SEC is NULL,
                     prepend SNEW.  */
                  if (after_sec)
-                   bfd_section_list_insert_after (link_info.output_bfd,
-                                                  after_sec, snew);
+                   {
+                     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);
                }
@@ -2195,19 +2251,20 @@ lang_map (void)
          || 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"));
@@ -2259,6 +2316,7 @@ lang_map (void)
       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 ();
 
@@ -2521,6 +2579,7 @@ lang_add_section (lang_statement_list_type *ptr,
     {
     case normal_section:
     case overlay_section:
+    case first_overlay_section:
       break;
     case noalloc_section:
       flags &= ~SEC_ALLOC;
@@ -2895,6 +2954,9 @@ load_symbols (lang_input_statement_type *entry,
   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))
     {
@@ -2970,8 +3032,6 @@ load_symbols (lang_input_statement_type *entry,
     case bfd_object:
       if (!entry->flags.reload)
        ldlang_add_file (entry);
-      if (trace_files || verbose)
-       info_msg ("%pI\n", entry);
       break;
 
     case bfd_archive:
@@ -3686,7 +3746,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)
-               {
+               /* 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:
@@ -3703,7 +3765,6 @@ update_wild_statements (lang_statement_union_type *s)
                    default:
                      break;
                    }
-               }
              break;
 
            case lang_constructors_statement_enum:
@@ -3711,11 +3772,8 @@ update_wild_statements (lang_statement_union_type *s)
              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:
@@ -3789,6 +3847,7 @@ map_input_to_output_sections
            {
            case normal_section:
            case overlay_section:
+           case first_overlay_section:
              break;
            case noalloc_section:
              flags = SEC_HAS_CONTENTS;
@@ -4187,9 +4246,7 @@ print_assignment (lang_assignment_statement_type *assignment,
       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;
@@ -4224,7 +4281,9 @@ print_assignment (lang_assignment_statement_type *assignment,
 
          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;
@@ -5436,13 +5495,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.  */
-           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;
@@ -5561,8 +5621,9 @@ lang_size_sections_1
          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:
@@ -6343,8 +6404,10 @@ lang_end (void)
     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))
     einfo (_("%F%P: gc-sections requires either an entry or "
             "an undefined symbol\n"));
@@ -8232,7 +8295,7 @@ lang_leave_overlay (etree_type *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;
This page took 0.031055 seconds and 4 git commands to generate.