Don't emit vendor attribute section if there is no attribute to emit.
[deliverable/binutils-gdb.git] / ld / ldlang.c
index 1ac5eb1ee2d9f9ceafa09cb5855b4263589992a1..bddce6d81acc9dc8f24f9751b0ecb4b8ee3c65e5 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";
@@ -1777,11 +1793,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->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:
@@ -1792,6 +1810,7 @@ insert_os_after (lang_output_section_statement_type *after)
        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)
@@ -1875,6 +1894,8 @@ lang_insert_orphan (asection *s,
   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;
 
@@ -1912,6 +1933,181 @@ lang_insert_orphan (asection *s,
          /* 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.  */
@@ -1938,7 +2134,8 @@ lang_insert_orphan (asection *s,
        {
          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);
 
@@ -2754,6 +2951,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))
     {
@@ -2829,8 +3029,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:
@@ -6202,8 +6400,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"));
This page took 0.026764 seconds and 4 git commands to generate.