Don't generate PLT relocations for now binding
[deliverable/binutils-gdb.git] / ld / ldlang.c
index 3a4257cc59d608d0ccef81e2a62725148462cd2a..c96c21fd4ee0dd2e513408d3049560478bf1a632 100644 (file)
@@ -5382,55 +5382,51 @@ lang_size_sections (bfd_boolean *relax, bfd_boolean check_regions)
   if (expld.dataseg.phase == exp_dataseg_end_seen
       && link_info.relro && expld.dataseg.relro_end)
     {
-      /* If DATA_SEGMENT_ALIGN DATA_SEGMENT_RELRO_END pair was seen, try
-        to put expld.dataseg.relro_end on a (common) page boundary.  */
-      bfd_vma min_base, relro_end, maxpage;
+      bfd_vma initial_base, relro_end, desired_end;
+      asection *sec;
 
-      expld.dataseg.phase = exp_dataseg_relro_adjust;
-      maxpage = expld.dataseg.maxpagesize;
-      /* MIN_BASE is the absolute minimum address we are allowed to start the
-        read-write segment (byte before will be mapped read-only).  */
-      min_base = (expld.dataseg.min_base + maxpage - 1) & ~(maxpage - 1);
-      expld.dataseg.base += (-expld.dataseg.relro_end
-                            & (expld.dataseg.pagesize - 1));
       /* Compute the expected PT_GNU_RELRO segment end.  */
       relro_end = ((expld.dataseg.relro_end + expld.dataseg.pagesize - 1)
                   & ~(expld.dataseg.pagesize - 1));
-      if (min_base + maxpage < expld.dataseg.base)
-       {
-         expld.dataseg.base -= maxpage;
-         relro_end -= maxpage;
-       }
+
+      /* Adjust by the offset arg of DATA_SEGMENT_RELRO_END.  */
+      desired_end = relro_end - expld.dataseg.relro_offset;
+
+      /* For sections in the relro segment..  */
+      for (sec = link_info.output_bfd->section_last; sec; sec = sec->prev)
+       if (!IGNORE_SECTION (sec)
+           && sec->vma >= expld.dataseg.base
+           && sec->vma < expld.dataseg.relro_end - expld.dataseg.relro_offset)
+         {
+           /* Where do we want to put this section so that it ends as
+              desired?  */
+           bfd_vma start = sec->vma;
+           bfd_vma end = start + sec->size;
+           bfd_vma bump = desired_end - end;
+           /* We'd like to increase START by BUMP, but we must heed
+              alignment so the increase might be less than optimum.  */
+           start += bump & ~(((bfd_vma) 1 << sec->alignment_power) - 1);
+           /* This is now the desired end for the previous section.  */
+           desired_end = start;
+         }
+
+      expld.dataseg.phase = exp_dataseg_relro_adjust;
+      ASSERT (desired_end >= expld.dataseg.base);
+      initial_base = expld.dataseg.base;
+      expld.dataseg.base = desired_end;
       lang_reset_memory_regions ();
       one_lang_size_sections_pass (relax, check_regions);
+
       if (expld.dataseg.relro_end > relro_end)
        {
-         /* The alignment of sections between DATA_SEGMENT_ALIGN
-            and DATA_SEGMENT_RELRO_END can cause excessive padding to
-            be inserted at DATA_SEGMENT_RELRO_END.  Try to start a
-            bit lower so that the section alignments will fit in.  */
-         asection *sec;
-         unsigned int max_alignment_power = 0;
-
-         /* Find maximum alignment power of sections between
-            DATA_SEGMENT_ALIGN and DATA_SEGMENT_RELRO_END.  */
-         for (sec = link_info.output_bfd->sections; sec; sec = sec->next)
-           if (sec->vma >= expld.dataseg.base
-               && sec->vma < expld.dataseg.relro_end
-               && sec->alignment_power > max_alignment_power)
-             max_alignment_power = sec->alignment_power;
-
-         if (((bfd_vma) 1 << max_alignment_power) < expld.dataseg.pagesize)
-           {
-             /* Aligning the adjusted base guarantees the padding
-                between sections won't change.  This is better than
-                simply subtracting 1 << max_alignment_power which is
-                what we used to do here.  */
-             expld.dataseg.base &= ~((1 << max_alignment_power) - 1);
-             lang_reset_memory_regions ();
-             one_lang_size_sections_pass (relax, check_regions);
-           }
+         /* Assignments to dot, or to output section address in a
+            user script have increased padding over the original.
+            Revert.  */
+         expld.dataseg.base = initial_base;
+         lang_reset_memory_regions ();
+         one_lang_size_sections_pass (relax, check_regions);
        }
+
       link_info.relro_start = expld.dataseg.base;
       link_info.relro_end = expld.dataseg.relro_end;
     }
@@ -6125,10 +6121,18 @@ lang_set_flags (lang_memory_region_type *ptr, const char *flags, int invert)
   flagword *ptr_flags;
 
   ptr_flags = invert ? &ptr->not_flags : &ptr->flags;
+
   while (*flags)
     {
       switch (*flags)
        {
+         /* PR 17900: An exclamation mark in the attributes reverses
+            the sense of any of the attributes that follow.  */
+       case '!':
+         invert = ! invert;
+         ptr_flags = invert ? &ptr->not_flags : &ptr->flags;
+         break;
+
        case 'A': case 'a':
          *ptr_flags |= SEC_ALLOC;
          break;
@@ -6151,7 +6155,7 @@ lang_set_flags (lang_memory_region_type *ptr, const char *flags, int invert)
          break;
 
        default:
-         einfo (_("%P%F: invalid syntax in flags\n"));
+         einfo (_("%P%F: invalid character %c (%d) in flags\n"), * flags, * flags);
          break;
        }
       flags++;
@@ -6624,7 +6628,7 @@ lang_process (void)
   open_input_bfds (statement_list.head, OPEN_BFD_NORMAL);
 
 #ifdef ENABLE_PLUGINS
-  if (plugin_active_plugins_p ())
+  if (link_info.lto_plugin_active)
     {
       lang_statement_list_type added;
       lang_statement_list_type files, inputfiles;
@@ -6643,7 +6647,6 @@ lang_process (void)
        einfo (_("%P%F: %s: plugin reported error after all symbols read\n"),
               plugin_error_plugin ());
       /* Open any newly added files, updating the file chains.  */
-      link_info.loading_lto_outputs = TRUE;
       open_input_bfds (*added.tail, OPEN_BFD_NORMAL);
       /* Restore the global list pointer now they have all been added.  */
       lang_list_remove_tail (stat_ptr, &added);
@@ -6684,6 +6687,22 @@ lang_process (void)
   link_info.gc_sym_list = &entry_symbol;
   if (entry_symbol.name == NULL)
     link_info.gc_sym_list = ldlang_undef_chain_list_head;
+  if (link_info.init_function != NULL)
+    {
+      struct bfd_sym_chain *sym
+       = (struct bfd_sym_chain *) stat_alloc (sizeof (*sym));
+      sym->next = link_info.gc_sym_list;
+      sym->name = link_info.init_function;
+      link_info.gc_sym_list = sym;
+    }
+  if (link_info.fini_function != NULL)
+    {
+      struct bfd_sym_chain *sym
+       = (struct bfd_sym_chain *) stat_alloc (sizeof (*sym));
+      sym->next = link_info.gc_sym_list;
+      sym->name = link_info.fini_function;
+      link_info.gc_sym_list = sym;
+    }
 
   ldemul_after_open ();
   if (config.map_file != NULL)
This page took 0.025891 seconds and 4 git commands to generate.