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]

Re: relocations against weak and global syms (for ARM)


Would you like to test this patch for me?  Seems to behave correctly
on the few testcases I tried.

	* symbols.c (resolve_symbol_value): Resolve "sym +/- expr" to an
	O_symbol.  Simplify a +/- b code.
	(symbol_equated_reloc_p): New predicate function.
	* symbols.h (symbol_equated_reloc_p): Declare.
	* write.c (adjust_reloc_syms): Use symbol_equated_reloc_p.
	(write_relocs): Likewise.
	(write_object_file): Likewise.
	* config/tc-mips.c (md_estimate_size_before_relax): Likewise.

-- 
Alan Modra

Index: gas/symbols.c
===================================================================
RCS file: /cvs/src/src/gas/symbols.c,v
retrieving revision 1.29
diff -u -p -r1.29 symbols.c
--- symbols.c	2001/08/09 14:42:07	1.29
+++ symbols.c	2001/09/05 04:18:32
@@ -914,7 +914,10 @@ resolve_symbol_value (symp)
 	case O_symbol:
 	case O_symbol_rva:
 	  left = resolve_symbol_value (add_symbol);
+	  seg_left = S_GET_SEGMENT (add_symbol);
+
 	do_symbol:
+	  symp->sy_value.X_op_symbol = NULL;
 
 	  if (symp->sy_mri_common)
 	    {
@@ -933,8 +936,8 @@ resolve_symbol_value (symp)
 	      copy_symbol_attributes (symp, add_symbol);
 	    }
 
-	  /* If we have equated this symbol to an undefined symbol, we
-             keep X_op set to O_symbol, and we don't change
+	  /* If we have equated this symbol to an undefined or common
+	     symbol, keep X_op set to O_symbol, and don't change
              X_add_number.  This permits the routine which writes out
              relocation to detect this case, and convert the
              relocation to be against the symbol to which this symbol
@@ -943,21 +946,41 @@ resolve_symbol_value (symp)
 	    {
 	      if (finalize_syms)
 		{
-		  final_seg = S_GET_SEGMENT (add_symbol);
 		  symp->sy_value.X_op = O_symbol;
 		  symp->sy_value.X_add_symbol = add_symbol;
 		  symp->sy_value.X_add_number = final_val;
+		  /* Use X_op_symbol as a flag.  */
+		  symp->sy_value.X_op_symbol = add_symbol;
+		  final_seg = seg_left;
 		}
 	      final_val = 0;
 	      resolved = symbol_resolved_p (add_symbol);
 	      symp->sy_resolving = 0;
 	      goto exit_dont_set_value;
 	    }
+	  else if (finalize_syms && final_seg == expr_section
+		   && seg_left != expr_section)
+	    {
+	      /* If the symbol is an expression symbol, do similarly
+		 as for undefined and common syms above.  Handles
+		 "sym +/- expr" where "expr" cannot be evaluated
+		 immediately, and we want relocations to be against
+		 "sym", eg. because it is weak.  */
+	      symp->sy_value.X_op = O_symbol;
+	      symp->sy_value.X_add_symbol = add_symbol;
+	      symp->sy_value.X_add_number = final_val;
+	      symp->sy_value.X_op_symbol = add_symbol;
+	      final_seg = seg_left;
+	      final_val += symp->sy_frag->fr_address + left;
+	      resolved = symbol_resolved_p (add_symbol);
+	      symp->sy_resolving = 0;
+	      goto exit_dont_set_value;
+	    }
 	  else
 	    {
 	      final_val += symp->sy_frag->fr_address + left;
 	      if (final_seg == expr_section || final_seg == undefined_section)
-		final_seg = S_GET_SEGMENT (add_symbol);
+		final_seg = seg_left;
 	    }
 
 	  resolved = symbol_resolved_p (add_symbol);
@@ -1008,28 +1031,30 @@ resolve_symbol_value (symp)
 
 	  /* Simplify addition or subtraction of a constant by folding the
 	     constant into X_add_number.  */
-	  if (op == O_add || op == O_subtract)
+	  if (op == O_add)
 	    {
 	      if (seg_right == absolute_section)
 		{
-		  if (op == O_add)
-		    final_val += right;
-		  else
-		    final_val -= right;
-		  op = O_symbol;
-		  op_symbol = NULL;
+		  final_val += right;
 		  goto do_symbol;
 		}
-	      else if (seg_left == absolute_section && op == O_add)
+	      else if (seg_left == absolute_section)
 		{
-		  op = O_symbol;
 		  final_val += left;
 		  add_symbol = op_symbol;
 		  left = right;
-		  op_symbol = NULL;
+		  seg_left = seg_right;
 		  goto do_symbol;
 		}
 	    }
+	  else if (op == O_subtract)
+	    {
+	      if (seg_right == absolute_section)
+		{
+		  final_val -= right;
+		  goto do_symbol;
+		}
+	    }
 
 	  /* Subtraction is permitted if both operands are in the same
 	     section.  Otherwise, both operands must be absolute.  We
@@ -2144,6 +2169,24 @@ symbol_equated_p (s)
   if (LOCAL_SYMBOL_CHECK (s))
     return 0;
   return s->sy_value.X_op == O_symbol;
+}
+
+/* Return whether a symbol is equated to another symbol, and should be
+   treated specially when writing out relocs.  */
+
+int
+symbol_equated_reloc_p (s)
+     symbolS *s;
+{
+  if (LOCAL_SYMBOL_CHECK (s))
+    return 0;
+  /* X_op_symbol, normally not used for O_symbol, is set by
+     resolve_symbol_value to flag expression syms that have been
+     equated.  */
+  return (s->sy_value.X_op == O_symbol
+	  && ((s->sy_resolved && s->sy_value.X_op_symbol != NULL)
+	      || ! S_IS_DEFINED (s)
+	      || S_IS_COMMON (s)));
 }
 
 /* Return whether a symbol has a constant value.  */
Index: gas/symbols.h
===================================================================
RCS file: /cvs/src/src/gas/symbols.h,v
retrieving revision 1.6
diff -u -p -r1.6 symbols.h
--- symbols.h	2001/05/22 10:23:48	1.6
+++ symbols.h	2001/09/05 04:18:33
@@ -185,6 +185,7 @@ extern void symbol_mark_resolved PARAMS 
 extern int symbol_resolved_p PARAMS ((symbolS *));
 extern int symbol_section_p PARAMS ((symbolS *));
 extern int symbol_equated_p PARAMS ((symbolS *));
+extern int symbol_equated_reloc_p PARAMS ((symbolS *));
 extern int symbol_constant_p PARAMS ((symbolS *));
 
 #ifdef BFD_ASSEMBLER
Index: gas/write.c
===================================================================
RCS file: /cvs/src/src/gas/write.c,v
retrieving revision 1.44
diff -u -p -r1.44 write.c
--- write.c	2001/08/01 01:44:25	1.44
+++ write.c	2001/09/05 04:18:35
@@ -769,8 +769,7 @@ adjust_reloc_syms (abfd, sec, xxx)
 
 	/* If this symbol is equated to an undefined symbol, convert
            the fixup to being against that symbol.  */
-	if (sym != NULL && symbol_equated_p (sym)
-	    && (! S_IS_DEFINED (sym) || S_IS_COMMON (sym)))
+	if (sym != NULL && symbol_equated_reloc_p (sym))
 	  {
 	    fixp->fx_offset += symbol_get_value_expression (sym)->X_add_number;
 	    sym = symbol_get_value_expression (sym)->X_add_symbol;
@@ -983,11 +982,10 @@ write_relocs (abfd, sec, xxx)
 	}
 
       /* If this is an undefined symbol which was equated to another
-         symbol, then use generate the reloc against the latter symbol
+         symbol, then generate the reloc against the latter symbol
          rather than the former.  */
       sym = fixp->fx_addsy;
-      while (symbol_equated_p (sym)
-	     && (! S_IS_DEFINED (sym) || S_IS_COMMON (sym)))
+      while (symbol_equated_reloc_p (sym))
 	{
 	  symbolS *n;
 
@@ -1059,8 +1057,7 @@ write_relocs (abfd, sec, xxx)
          symbol, then generate the reloc against the latter symbol
          rather than the former.  */
       sym = fixp->fx_addsy;
-      while (symbol_equated_p (sym)
-	     && (! S_IS_DEFINED (sym) || S_IS_COMMON (sym)))
+      while (symbol_equated_reloc_p (sym))
 	sym = symbol_get_value_expression (sym)->X_add_symbol;
       fixp->fx_addsy = sym;
 
@@ -1960,8 +1957,7 @@ write_object_file ()
 
 	  /* Skip symbols which were equated to undefined or common
              symbols.  */
-	  if (symbol_equated_p (symp)
-	      && (! S_IS_DEFINED (symp) || S_IS_COMMON (symp)))
+	  if (symbol_equated_reloc_p (symp))
 	    {
 	      symbol_remove (symp, &symbol_rootP, &symbol_lastP);
 	      continue;
Index: gas/config/tc-mips.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-mips.c,v
retrieving revision 1.71
diff -u -p -r1.71 tc-mips.c
--- tc-mips.c	2001/08/31 21:06:40	1.71
+++ tc-mips.c	2001/09/05 04:18:56
@@ -11076,8 +11076,7 @@ md_estimate_size_before_relax (fragp, se
       sym = fragp->fr_symbol;
 
       /* Handle the case of a symbol equated to another symbol.  */
-      while (symbol_equated_p (sym)
-	     && (! S_IS_DEFINED (sym) || S_IS_COMMON (sym)))
+      while (symbol_equated_reloc_p (sym))
 	{
 	  symbolS *n;
 


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