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]

Re: PATCH: PR ld/12380: Assertion in linker script failed twice


On Tue, Jan 11, 2011 at 11:57:59AM +1030, Alan Modra wrote:
> I believe the real problem is that we set lang_final_phase too soon,

Jakub, would you please cast your eye over this patch that touches
DATA_SEGMENT_ALIGN support?  I'm committing it as I'm reasonably
confident the patch is correct, but would appreciate your review.

	PR ld/12380
	* ldexp.h (enum phase_enum): Comment.  Add exp_dataseg_done.
	* ldexp.c (fold_unary <DATA_SEGMENT_END>): Rearrange code.  Test
	for exp_dataseg_done rather than expld.phase == lang_final_phase_enum
	to detect when we've finished sizing sections.
	(fold_binary <DATA_SEGMENT_ALIGN>): Likewise.
	(fold_binary <DATA_SEGMENT_RELRO_END>): Likewise.  Also test
	that we are not inside an output section statement.
	* ldlang.c (lang_size_sections): Set exp_dataseg_done on exit if
	not exp_dataseg_relro_adjust or exp_dataseg_adjust.  Don't set
	lang_final_phase_enum here.
	(lang_process): Set lang_final_phase_enum here.

Index: ld/ldexp.h
===================================================================
RCS file: /cvs/src/src/ld/ldexp.h,v
retrieving revision 1.25
diff -u -p -r1.25 ldexp.h
--- ld/ldexp.h	20 Dec 2010 13:00:13 -0000	1.25
+++ ld/ldexp.h	12 Jan 2011 06:22:23 -0000
@@ -103,12 +103,17 @@ typedef enum {
 union lang_statement_union;
 
 enum phase_enum {
+  /* We step through the first four states here as we see the
+     associated linker script tokens.  */
   exp_dataseg_none,
   exp_dataseg_align_seen,
   exp_dataseg_relro_seen,
   exp_dataseg_end_seen,
+  /* The last three states are final, and affect the value returned
+     by DATA_SEGMENT_ALIGN.  */
   exp_dataseg_relro_adjust,
-  exp_dataseg_adjust
+  exp_dataseg_adjust,
+  exp_dataseg_done
 };
 
 enum relro_enum {
Index: ld/ldexp.c
===================================================================
RCS file: /cvs/src/src/ld/ldexp.c,v
retrieving revision 1.89
diff -u -p -r1.89 ldexp.c
--- ld/ldexp.c	20 Dec 2010 13:00:13 -0000	1.89
+++ ld/ldexp.c	12 Jan 2011 08:15:23 -0000
@@ -259,20 +259,22 @@ fold_unary (etree_type *tree)
 	  break;
 
 	case DATA_SEGMENT_END:
-	  if (expld.phase != lang_first_phase_enum
-	      && expld.section == bfd_abs_section_ptr
-	      && (expld.dataseg.phase == exp_dataseg_align_seen
-		  || expld.dataseg.phase == exp_dataseg_relro_seen
-		  || expld.dataseg.phase == exp_dataseg_adjust
-		  || expld.dataseg.phase == exp_dataseg_relro_adjust
-		  || expld.phase == lang_final_phase_enum))
+	  if (expld.phase == lang_first_phase_enum
+	      || expld.section != bfd_abs_section_ptr)
 	    {
-	      if (expld.dataseg.phase == exp_dataseg_align_seen
-		  || expld.dataseg.phase == exp_dataseg_relro_seen)
-		{
-		  expld.dataseg.phase = exp_dataseg_end_seen;
-		  expld.dataseg.end = expld.result.value;
-		}
+	      expld.result.valid_p = FALSE;
+	    }
+	  else if (expld.dataseg.phase == exp_dataseg_align_seen
+		   || expld.dataseg.phase == exp_dataseg_relro_seen)
+	    {
+	      expld.dataseg.phase = exp_dataseg_end_seen;
+	      expld.dataseg.end = expld.result.value;
+	    }
+	  else if (expld.dataseg.phase == exp_dataseg_done
+		   || expld.dataseg.phase == exp_dataseg_adjust
+		   || expld.dataseg.phase == exp_dataseg_relro_adjust)
+	    {
+	      /* OK.  */
 	    }
 	  else
 	    expld.result.valid_p = FALSE;
@@ -402,12 +404,10 @@ fold_binary (etree_type *tree)
 
 	case DATA_SEGMENT_ALIGN:
 	  expld.dataseg.relro = exp_dataseg_relro_start;
-	  if (expld.phase != lang_first_phase_enum
-	      && expld.section == bfd_abs_section_ptr
-	      && (expld.dataseg.phase == exp_dataseg_none
-		  || expld.dataseg.phase == exp_dataseg_adjust
-		  || expld.dataseg.phase == exp_dataseg_relro_adjust
-		  || expld.phase == lang_final_phase_enum))
+	  if (expld.phase == lang_first_phase_enum
+	      || expld.section != bfd_abs_section_ptr)
+	    expld.result.valid_p = FALSE;
+	  else
 	    {
 	      bfd_vma maxpage = lhs.value;
 	      bfd_vma commonpage = expld.result.value;
@@ -415,10 +415,20 @@ fold_binary (etree_type *tree)
 	      expld.result.value = align_n (expld.dot, maxpage);
 	      if (expld.dataseg.phase == exp_dataseg_relro_adjust)
 		expld.result.value = expld.dataseg.base;
-	      else if (expld.dataseg.phase != exp_dataseg_adjust)
+	      else if (expld.dataseg.phase == exp_dataseg_adjust)
+		{
+		  if (commonpage < maxpage)
+		    expld.result.value += ((expld.dot + commonpage - 1)
+					   & (maxpage - commonpage));
+		}
+	      else
 		{
 		  expld.result.value += expld.dot & (maxpage - 1);
-		  if (expld.phase == lang_allocating_phase_enum)
+		  if (expld.dataseg.phase == exp_dataseg_done)
+		    {
+		      /* OK.  */
+		    }
+		  else if (expld.dataseg.phase == exp_dataseg_none)
 		    {
 		      expld.dataseg.phase = exp_dataseg_align_seen;
 		      expld.dataseg.min_base = expld.dot;
@@ -427,22 +437,21 @@ fold_binary (etree_type *tree)
 		      expld.dataseg.maxpagesize = maxpage;
 		      expld.dataseg.relro_end = 0;
 		    }
+		  else
+		    expld.result.valid_p = FALSE;
 		}
-	      else if (commonpage < maxpage)
-		expld.result.value += ((expld.dot + commonpage - 1)
-				       & (maxpage - commonpage));
 	    }
-	  else
-	    expld.result.valid_p = FALSE;
 	  break;
 
 	case DATA_SEGMENT_RELRO_END:
 	  expld.dataseg.relro = exp_dataseg_relro_end;
-	  if (expld.phase != lang_first_phase_enum
-	      && (expld.dataseg.phase == exp_dataseg_align_seen
-		  || expld.dataseg.phase == exp_dataseg_adjust
-		  || expld.dataseg.phase == exp_dataseg_relro_adjust
-		  || expld.phase == lang_final_phase_enum))
+	  if (expld.phase == lang_first_phase_enum
+	      || expld.section != bfd_abs_section_ptr)
+	    expld.result.valid_p = FALSE;
+	  else if (expld.dataseg.phase == exp_dataseg_align_seen
+		   || expld.dataseg.phase == exp_dataseg_adjust
+		   || expld.dataseg.phase == exp_dataseg_relro_adjust
+		   || expld.dataseg.phase == exp_dataseg_done)
 	    {
 	      if (expld.dataseg.phase == exp_dataseg_align_seen
 		  || expld.dataseg.phase == exp_dataseg_relro_adjust)
Index: ld/ldlang.c
===================================================================
RCS file: /cvs/src/src/ld/ldlang.c,v
retrieving revision 1.356
diff -u -p -r1.356 ldlang.c
--- ld/ldlang.c	10 Jan 2011 13:13:32 -0000	1.356
+++ ld/ldlang.c	12 Jan 2011 06:22:27 -0000
@@ -5425,9 +5425,11 @@ lang_size_sections (bfd_boolean *relax, 
 	  lang_reset_memory_regions ();
 	  one_lang_size_sections_pass (relax, check_regions);
 	}
+      else
+	expld.dataseg.phase = exp_dataseg_done;
     }
-
-  expld.phase = lang_final_phase_enum;
+  else
+    expld.dataseg.phase = exp_dataseg_done;
 }
 
 /* Worker function for lang_do_assignments.  Recursiveness goes here.  */
@@ -6520,7 +6522,7 @@ lang_process (void)
 
   /* Do all the assignments, now that we know the final resting places
      of all the symbols.  */
-
+  expld.phase = lang_final_phase_enum;
   lang_do_assignments ();
 
   ldemul_finish ();

-- 
Alan Modra
Australia Development Lab, IBM


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