This is the mail archive of the binutils@sources.redhat.com 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]

ldexp.c:fold_binary bugfix


This patch fixes a bug in fold_binary where we did a subtraction with
arguments swapped without negating the result.  I've also split out
some code from exp_fold_tree into separate functions.

	* ldexp.c (fold_unary): New.  Split out from exp_fold_tree.
	(fold_binary): Correct abs - non-abs case.
	(fold_trinary): New.  Split out from exp_fold_tree.

Applying mainline and 2.13 branch.

-- 
Alan Modra
IBM OzLabs - Linux Technology Centre

Index: ld/ldexp.c
===================================================================
RCS file: /cvs/src/src/ld/ldexp.c,v
retrieving revision 1.19
diff -u -p -r1.19 ldexp.c
--- ld/ldexp.c	2 Sep 2002 17:03:29 -0000	1.19
+++ ld/ldexp.c	25 Sep 2002 01:12:20 -0000
@@ -50,11 +50,21 @@ static etree_value_type new_rel
   PARAMS ((bfd_vma, char *, lang_output_section_statement_type *section));
 static etree_value_type new_rel_from_section
   PARAMS ((bfd_vma value, lang_output_section_statement_type *section));
+static etree_value_type fold_unary
+  PARAMS ((etree_type *tree,
+	   lang_output_section_statement_type *current_section,
+	   lang_phase_type allocation_done,
+	   bfd_vma dot, bfd_vma *dotp));
 static etree_value_type fold_binary
   PARAMS ((etree_type *tree,
 	   lang_output_section_statement_type *current_section,
 	   lang_phase_type allocation_done,
 	   bfd_vma dot, bfd_vma *dotp));
+static etree_value_type fold_trinary
+  PARAMS ((etree_type *tree,
+	   lang_output_section_statement_type *current_section,
+	   lang_phase_type allocation_done,
+	   bfd_vma dot, bfd_vma *dotp));
 static etree_value_type fold_name
   PARAMS ((etree_type *tree,
 	   lang_output_section_statement_type *current_section,
@@ -247,6 +257,93 @@ new_rel_from_section (value, section)
 }
 
 static etree_value_type
+fold_unary (tree, current_section, allocation_done, dot, dotp)
+     etree_type *tree;
+     lang_output_section_statement_type *current_section;
+     lang_phase_type allocation_done;
+     bfd_vma dot;
+     bfd_vma *dotp;
+{
+  etree_value_type result;
+
+  result = exp_fold_tree (tree->unary.child,
+			  current_section,
+			  allocation_done, dot, dotp);
+  if (result.valid_p)
+    {
+      switch (tree->type.node_code)
+	{
+	case ALIGN_K:
+	  if (allocation_done != lang_first_phase_enum)
+	    result = new_rel_from_section (align_n (dot, result.value),
+					   current_section);
+	  else
+	    result.valid_p = false;
+	  break;
+
+	case ABSOLUTE:
+	  if (allocation_done != lang_first_phase_enum)
+	    {
+	      result.value += result.section->bfd_section->vma;
+	      result.section = abs_output_section;
+	    }
+	  else
+	    result.valid_p = false;
+	  break;
+
+	case '~':
+	  make_abs (&result);
+	  result.value = ~result.value;
+	  break;
+
+	case '!':
+	  make_abs (&result);
+	  result.value = !result.value;
+	  break;
+
+	case '-':
+	  make_abs (&result);
+	  result.value = -result.value;
+	  break;
+
+	case NEXT:
+	  /* Return next place aligned to value.  */
+	  if (allocation_done == lang_allocating_phase_enum)
+	    {
+	      make_abs (&result);
+	      result.value = align_n (dot, result.value);
+	    }
+	  else
+	    result.valid_p = false;
+	  break;
+
+	case DATA_SEGMENT_END:
+	  if (allocation_done != lang_first_phase_enum
+	      && current_section == abs_output_section
+	      && (exp_data_seg.phase == exp_dataseg_align_seen
+		  || exp_data_seg.phase == exp_dataseg_adjust
+		  || allocation_done != lang_allocating_phase_enum))
+	    {
+	      if (exp_data_seg.phase == exp_dataseg_align_seen)
+		{
+		  exp_data_seg.phase = exp_dataseg_end_seen;
+		  exp_data_seg.end = result.value;
+		}
+	    }
+	  else
+	    result.valid_p = false;
+	  break;
+
+	default:
+	  FAIL ();
+	  break;
+	}
+    }
+
+  return result;
+}
+
+static etree_value_type
 fold_binary (tree, current_section, allocation_done, dot, dotp)
      etree_type *tree;
      lang_output_section_statement_type *current_section;
@@ -279,15 +376,14 @@ fold_binary (tree, current_section, allo
 	      && (tree->type.node_code == '+'
 		  || tree->type.node_code == '-'))
 	    {
-	      etree_value_type hold;
-
-	      /* If there is only one absolute term, make sure it is the
-		 second one.  */
 	      if (other.section != abs_output_section)
 		{
-		  hold = result;
-		  result = other;
-		  other = hold;
+		  /* Keep the section of the other term.  */
+		  if (tree->type.node_code == '+')
+		    other.value = result.value + other.value;
+		  else
+		    other.value = result.value - other.value;
+		  return other;
 		}
 	    }
 	  else if (result.section != other.section
@@ -382,6 +478,28 @@ fold_binary (tree, current_section, allo
   return result;
 }
 
+static etree_value_type
+fold_trinary (tree, current_section, allocation_done, dot, dotp)
+     etree_type *tree;
+     lang_output_section_statement_type *current_section;
+     lang_phase_type allocation_done;
+     bfd_vma dot;
+     bfd_vma *dotp;
+{
+  etree_value_type result;
+
+  result = exp_fold_tree (tree->trinary.cond, current_section,
+			  allocation_done, dot, dotp);
+  if (result.valid_p)
+    result = exp_fold_tree ((result.value
+			     ? tree->trinary.lhs
+			     : tree->trinary.rhs),
+			    current_section,
+			    allocation_done, dot, dotp);
+
+  return result;
+}
+
 etree_value_type
 invalid ()
 {
@@ -584,95 +702,18 @@ exp_fold_tree (tree, current_section, al
       break;
 
     case etree_unary:
-      result = exp_fold_tree (tree->unary.child,
-			      current_section,
-			      allocation_done, dot, dotp);
-      if (result.valid_p)
-	{
-	  switch (tree->type.node_code)
-	    {
-	    case ALIGN_K:
-	      if (allocation_done != lang_first_phase_enum)
-		result = new_rel_from_section (align_n (dot, result.value),
-					       current_section);
-	      else
-		result.valid_p = false;
-	      break;
-
-	    case ABSOLUTE:
-	      if (allocation_done != lang_first_phase_enum)
-		{
-		  result.value += result.section->bfd_section->vma;
-		  result.section = abs_output_section;
-		}
-	      else
-		result.valid_p = false;
-	      break;
-
-	    case '~':
-	      make_abs (&result);
-	      result.value = ~result.value;
-	      break;
-
-	    case '!':
-	      make_abs (&result);
-	      result.value = !result.value;
-	      break;
-
-	    case '-':
-	      make_abs (&result);
-	      result.value = -result.value;
-	      break;
-
-	    case NEXT:
-	      /* Return next place aligned to value.  */
-	      if (allocation_done == lang_allocating_phase_enum)
-		{
-		  make_abs (&result);
-		  result.value = align_n (dot, result.value);
-		}
-	      else
-		result.valid_p = false;
-	      break;
-
-	    case DATA_SEGMENT_END:
-	      if (allocation_done != lang_first_phase_enum
-		  && current_section == abs_output_section
-		  && (exp_data_seg.phase == exp_dataseg_align_seen
-		      || exp_data_seg.phase == exp_dataseg_adjust
-		      || allocation_done != lang_allocating_phase_enum))
-		{
-		  if (exp_data_seg.phase == exp_dataseg_align_seen)
-		    {
-		      exp_data_seg.phase = exp_dataseg_end_seen;
-		      exp_data_seg.end = result.value;
-		    }
-		}
-	      else
-		result.valid_p = false;
-	      break;
-
-	    default:
-	      FAIL ();
-	      break;
-	    }
-	}
-      break;
-
-    case etree_trinary:
-      result = exp_fold_tree (tree->trinary.cond, current_section,
-			      allocation_done, dot, dotp);
-      if (result.valid_p)
-	result = exp_fold_tree ((result.value
-				 ? tree->trinary.lhs
-				 : tree->trinary.rhs),
-				current_section,
-				allocation_done, dot, dotp);
+      result = fold_unary (tree, current_section, allocation_done,
+			   dot, dotp);
       break;
 
     case etree_binary:
       result = fold_binary (tree, current_section, allocation_done,
 			    dot, dotp);
+      break;
+
+    case etree_trinary:
+      result = fold_trinary (tree, current_section, allocation_done,
+			     dot, dotp);
       break;
 
     case etree_assign:


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