This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH 3/4] ld: Add lang_size_relro_segment


Break lang_size_sections down into separate functions so that they can
also be used for text-only LOAD segment.  lang_size_relro_segment will
call lang_size_relro_segment_1 and lang_size_segment for both GNU_RELRO
segment and text-only LOAD segment.

	* ldlang.c (lang_size_segment): New function.
	(lang_size_relro_segment_1): Likewise.
	(lang_size_relro_segment): Likewise.
	(lang_size_sections): Rewrite to call lang_size_relro_segment.
---
 ld/ldlang.c | 174 ++++++++++++++++++++++++++++++++++++++----------------------
 1 file changed, 110 insertions(+), 64 deletions(-)

diff --git a/ld/ldlang.c b/ld/ldlang.c
index 2cb1647692..6bb9e472a2 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -5589,90 +5589,136 @@ one_lang_size_sections_pass (bfd_boolean *relax, bfd_boolean check_regions)
 			0, 0, relax, check_regions);
 }
 
-void
-lang_size_sections (bfd_boolean *relax, bfd_boolean check_regions)
+static bfd_boolean
+lang_size_segment (seg_align_type *seg)
 {
-  expld.phase = lang_allocating_phase_enum;
-  expld.dataseg.phase = exp_seg_none;
+  /* If XXX_SEGMENT_ALIGN XXX_SEGMENT_END pair was seen, check whether
+     a page could be saved in the data segment.  */
+  bfd_vma first, last;
 
-  one_lang_size_sections_pass (relax, check_regions);
-  if (expld.dataseg.phase == exp_seg_end_seen
-      && link_info.relro && expld.dataseg.relro_end)
+  first = -seg->base & (seg->pagesize - 1);
+  last = seg->end & (seg->pagesize - 1);
+  if (first && last
+      && ((seg->base & ~(seg->pagesize - 1))
+	  != (seg->end & ~(seg->pagesize - 1)))
+      && first + last <= seg->pagesize)
     {
-      bfd_vma initial_base, relro_end, desired_end;
-      asection *sec;
+      seg->phase = exp_seg_adjust;
+      return TRUE;
+    }
 
-      /* Compute the expected PT_GNU_RELRO segment end.  */
-      relro_end = ((expld.dataseg.relro_end + expld.dataseg.pagesize - 1)
-		   & ~(expld.dataseg.pagesize - 1));
+  seg->phase = exp_seg_done;
+  return FALSE;
+}
 
-      /* Adjust by the offset arg of DATA_SEGMENT_RELRO_END.  */
-      desired_end = relro_end - expld.dataseg.relro_offset;
+static bfd_vma
+lang_size_relro_segment_1 (seg_align_type *seg)
+{
+  bfd_vma relro_end, desired_end;
+  asection *sec;
 
-      /* For sections in the relro segment..  */
-      for (sec = link_info.output_bfd->section_last; sec; sec = sec->prev)
-	if ((sec->flags & SEC_ALLOC) != 0
-	    && 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, end, bump;
-
-	    end = start = sec->vma;
-	    if (!IS_TBSS (sec))
-	      end += TO_ADDR (sec->size);
-	    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;
-	    start &= ~(((bfd_vma) 1 << sec->alignment_power) - 1);
-	    /* This is now the desired end for the previous section.  */
-	    desired_end = start;
-	  }
+  /* Compute the expected PT_GNU_RELRO/PT_LOAD segment end.  */
+  relro_end = ((seg->relro_end + seg->pagesize - 1)
+	       & ~(seg->pagesize - 1));
+
+  /* Adjust by the offset arg of XXX_SEGMENT_RELRO_END.  */
+  desired_end = relro_end - seg->relro_offset;
+
+  /* For sections in the relro segment..  */
+  for (sec = link_info.output_bfd->section_last; sec; sec = sec->prev)
+    if ((sec->flags & SEC_ALLOC) != 0
+	&& sec->vma >= seg->base
+	&& sec->vma < seg->relro_end - seg->relro_offset)
+      {
+	/* Where do we want to put this section so that it ends as
+	   desired?  */
+	bfd_vma start, end, bump;
+
+	end = start = sec->vma;
+	if (!IS_TBSS (sec))
+	  end += TO_ADDR (sec->size);
+	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;
+	start &= ~(((bfd_vma) 1 << sec->alignment_power) - 1);
+	/* This is now the desired end for the previous section.  */
+	desired_end = start;
+      }
+
+  seg->phase = exp_seg_relro_adjust;
+  ASSERT (desired_end >= seg->base);
+  seg->base = desired_end;
+  return relro_end;
+}
+
+static bfd_boolean
+lang_size_relro_segment (bfd_boolean *relax, bfd_boolean check_regions)
+{
+  bfd_boolean do_reset = FALSE;
+  bfd_boolean do_data_relro;
+  bfd_vma data_initial_base, data_relro_end;
+
+  if (link_info.relro && expld.dataseg.relro_end)
+    {
+      do_data_relro = TRUE;
+      data_initial_base = expld.dataseg.base;
+      data_relro_end = lang_size_relro_segment_1 (&expld.dataseg);
+    }
+  else
+    {
+      do_data_relro = FALSE;
+      data_initial_base = data_relro_end = 0;
+    }
 
-      expld.dataseg.phase = exp_seg_relro_adjust;
-      ASSERT (desired_end >= expld.dataseg.base);
-      initial_base = expld.dataseg.base;
-      expld.dataseg.base = desired_end;
+  if (do_data_relro)
+    {
       lang_reset_memory_regions ();
       one_lang_size_sections_pass (relax, check_regions);
 
-      if (expld.dataseg.relro_end > relro_end)
+      /* Assignments to dot, or to output section address in a user
+	 script have increased padding over the original.  Revert.  */
+      if (do_data_relro && expld.dataseg.relro_end > data_relro_end)
 	{
-	  /* 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);
+	  expld.dataseg.base = data_initial_base;;
+	  do_reset = TRUE;
 	}
-
-      link_info.relro_start = expld.dataseg.base;
-      link_info.relro_end = expld.dataseg.relro_end;
     }
-  else if (expld.dataseg.phase == exp_seg_end_seen)
+
+  if (!do_data_relro && lang_size_segment (&expld.dataseg))
+    do_reset = TRUE;
+
+  return do_reset;
+}
+
+void
+lang_size_sections (bfd_boolean *relax, bfd_boolean check_regions)
+{
+  expld.phase = lang_allocating_phase_enum;
+  expld.dataseg.phase = exp_seg_none;
+
+  one_lang_size_sections_pass (relax, check_regions);
+
+  if (expld.dataseg.phase != exp_seg_end_seen)
+    expld.dataseg.phase = exp_seg_done;
+
+  if (expld.dataseg.phase == exp_seg_end_seen)
     {
-      /* If DATA_SEGMENT_ALIGN DATA_SEGMENT_END pair was seen, check whether
-	 a page could be saved in the data segment.  */
-      bfd_vma first, last;
+      bfd_boolean do_reset
+	= lang_size_relro_segment (relax, check_regions);
 
-      first = -expld.dataseg.base & (expld.dataseg.pagesize - 1);
-      last = expld.dataseg.end & (expld.dataseg.pagesize - 1);
-      if (first && last
-	  && ((expld.dataseg.base & ~(expld.dataseg.pagesize - 1))
-	      != (expld.dataseg.end & ~(expld.dataseg.pagesize - 1)))
-	  && first + last <= expld.dataseg.pagesize)
+      if (do_reset)
 	{
-	  expld.dataseg.phase = exp_seg_adjust;
 	  lang_reset_memory_regions ();
 	  one_lang_size_sections_pass (relax, check_regions);
 	}
-      else
-	expld.dataseg.phase = exp_seg_done;
+
+      if (link_info.relro && expld.dataseg.relro_end)
+	{
+	  link_info.relro_start = expld.dataseg.base;
+	  link_info.relro_end = expld.dataseg.relro_end;
+	}
     }
-  else
-    expld.dataseg.phase = exp_seg_done;
 }
 
 static lang_output_section_statement_type *current_section;
-- 
2.13.6


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]