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]

ill formed relocations


Hi,
attached is a patch to fix some silent bad reloc generation on code like

        .long ~DUMMY_1 #wrong - undefined
        .long ~DUMMY_2 #wrong - .text
        .long ~DUMMY_3 #ok - absolute
DUMMY_2:
.set DUMMY_3, 6

we detect bad relocations with dyadic operators, but silently generate
broken ones with monadic operators. The resultant object file crashes
the linker (older linkers silently generate incorrect binaries).

built & tested on i686-pc-linux-gnu and powerpc-wrs-vxworks.

This work was supported by Wind River Systems

nathan
--
Dr Nathan Sidwell   ::   http://www.codesourcery.com   ::   CodeSourcery LLC
         'But that's a lie.' - 'Yes it is. What's your point?'
nathan@codesourcery.com : http://www.cs.bris.ac.uk/~nathan/ : nathan@acm.org

2002-11-29  Nathan Sidwell  <nathan@codesourcery.com>

	* symbols.c (report_op_error): New function, broken out of ...
	(resolve_symbol_value): ... here. Use for both monadic and dyadic
	operators.

Index: symbols.c
===================================================================
RCS file: /cvs/src/src/gas/symbols.c,v
retrieving revision 1.39
diff -c -3 -p -r1.39 symbols.c
*** symbols.c	20 Sep 2002 14:47:14 -0000	1.39
--- symbols.c	29 Nov 2002 16:08:00 -0000
*************** static long dollar_label_instance PARAMS
*** 66,71 ****
--- 66,72 ----
  static long fb_label_instance PARAMS ((long));
  
  static void print_binary PARAMS ((FILE *, const char *, expressionS *));
+ static void report_op_error PARAMS ((symbolS *, symbolS *, symbolS *));
  
  /* Return a pointer to a new symbol.  Die if we can't make a new
     symbol.  Fill in the symbol's values.  Add symbol to end of symbol
*************** verify_symbol_chain_2 (sym)
*** 837,842 ****
--- 838,900 ----
    verify_symbol_chain (p, n);
  }
  
+ static void
+ report_op_error (symp, left, right)
+      symbolS *symp;
+      symbolS *left, *right;
+ {
+   char *file;
+   unsigned int line;
+   segT seg_left = S_GET_SEGMENT (left);
+   segT seg_right = right ? S_GET_SEGMENT (right) : 0;
+   
+   if (expr_symbol_where (symp, &file, &line))
+     {
+       if (seg_left == undefined_section)
+ 	as_bad_where (file, line,
+ 		      _("undefined symbol `%s' in operation"),
+ 		      S_GET_NAME (left));
+       if (seg_right == undefined_section)
+ 	as_bad_where (file, line,
+ 		      _("undefined symbol `%s' in operation"),
+ 		      S_GET_NAME (right));
+       if (seg_left != undefined_section
+ 	  && seg_right != undefined_section)
+ 	{
+ 	  if (right)
+ 	    as_bad_where (file, line,
+ 			  _("invalid sections for operation on `%s' and `%s'"),
+ 			  S_GET_NAME (left), S_GET_NAME (right));
+ 	  else
+ 	    as_bad_where (file, line,
+ 			  _("invalid section for operation on `%s'"),
+ 			  S_GET_NAME (left));
+ 	}
+       
+     }
+   else
+     {
+       if (seg_left == undefined_section)
+ 	as_bad (_("undefined symbol `%s' in operation setting `%s'"),
+ 		S_GET_NAME (left), S_GET_NAME (symp));
+       if (seg_right == undefined_section)
+ 	as_bad (_("undefined symbol `%s' in operation setting `%s'"),
+ 		S_GET_NAME (right), S_GET_NAME (symp));
+       if (seg_left != undefined_section
+ 	  && seg_right != undefined_section)
+ 	{
+ 	  if (right)
+ 	    as_bad_where (file, line,
+ 			  _("invalid sections for operation on `%s' and `%s' setting `%s'"),
+ 			  S_GET_NAME (left), S_GET_NAME (right), S_GET_NAME (symp));
+ 	  else
+ 	    as_bad_where (file, line,
+ 			  _("invalid section for operation on `%s' setting `%s'"),
+ 			  S_GET_NAME (left), S_GET_NAME (symp));
+ 	}
+     }
+ }
+ 
  /* Resolve the value of a symbol.  This is called during the final
     pass over the symbol table to resolve any symbols with complex
     values.  */
*************** resolve_symbol_value (symp)
*** 1002,1007 ****
--- 1060,1076 ----
  	  left = resolve_symbol_value (add_symbol);
  	  seg_left = S_GET_SEGMENT (add_symbol);
  
+ 	  /* By reducing these to the relevant dyadic operator, we get
+ 	     	!S -> S == 0 	permitted on anything,
+ 		-S -> 0 - S 	only permitted on absolute
+ 		~S -> S ^ ~0 	only permitted on absolute  */
+ 	  if (op != O_logical_not && seg_left != absolute_section
+ 	      && finalize_syms)
+ 	    report_op_error (symp, add_symbol, NULL);
+ 	    
+ 	  if (final_seg == expr_section || final_seg == undefined_section)
+ 	    final_seg = absolute_section;
+ 	  
  	  if (op == O_uminus)
  	    left = -left;
  	  else if (op == O_logical_not)
*************** resolve_symbol_value (symp)
*** 1010,1017 ****
  	    left = ~left;
  
  	  final_val += left + symp->sy_frag->fr_address;
- 	  if (final_seg == expr_section || final_seg == undefined_section)
- 	    final_seg = seg_left;
  
  	  resolved = symbol_resolved_p (add_symbol);
  	  break;
--- 1079,1084 ----
*************** resolve_symbol_value (symp)
*** 1077,1133 ****
  
  	     Don't emit messages unless we're finalizing the symbol value,
  	     otherwise we may get the same message multiple times.  */
! 	  if ((op == O_eq || op == O_ne)
! 	      || ((op == O_subtract
! 		   || op == O_lt || op == O_le || op == O_ge || op == O_gt)
! 		  && seg_left == seg_right
! 		  && (seg_left != undefined_section
! 		      || add_symbol == op_symbol))
! 	      || (seg_left == absolute_section
! 		  && seg_right == absolute_section))
! 	    {
! 	      if (final_seg == expr_section || final_seg == undefined_section)
! 		final_seg = absolute_section;
! 	    }
! 	  else if (finalize_syms)
! 	    {
! 	      char *file;
! 	      unsigned int line;
! 
! 	      if (expr_symbol_where (symp, &file, &line))
! 		{
! 		  if (seg_left == undefined_section)
! 		    as_bad_where (file, line,
! 				  _("undefined symbol `%s' in operation"),
! 				  S_GET_NAME (symp->sy_value.X_add_symbol));
! 		  if (seg_right == undefined_section)
! 		    as_bad_where (file, line,
! 				  _("undefined symbol `%s' in operation"),
! 				  S_GET_NAME (symp->sy_value.X_op_symbol));
! 		  if (seg_left != undefined_section
! 		      && seg_right != undefined_section)
! 		    as_bad_where (file, line,
! 				  _("invalid section for operation"));
! 		}
! 	      else
! 		{
! 		  if (seg_left == undefined_section)
! 		    as_bad (_("undefined symbol `%s' in operation setting `%s'"),
! 			    S_GET_NAME (symp->sy_value.X_add_symbol),
! 			    S_GET_NAME (symp));
! 		  if (seg_right == undefined_section)
! 		    as_bad (_("undefined symbol `%s' in operation setting `%s'"),
! 			    S_GET_NAME (symp->sy_value.X_op_symbol),
! 			    S_GET_NAME (symp));
! 		  if (seg_left != undefined_section
! 		      && seg_right != undefined_section)
! 		    as_bad (_("invalid section for operation setting `%s'"),
! 			    S_GET_NAME (symp));
! 		}
! 	      /* Prevent the error propagating.  */
! 	      if (final_seg == expr_section || final_seg == undefined_section)
! 		final_seg = absolute_section;
! 	    }
  
  	  /* Check for division by zero.  */
  	  if ((op == O_divide || op == O_modulus) && right == 0)
--- 1144,1162 ----
  
  	     Don't emit messages unless we're finalizing the symbol value,
  	     otherwise we may get the same message multiple times.  */
! 	  if (finalize_syms
! 	      && !(seg_left == absolute_section
! 		   && seg_right == absolute_section)
! 	      && !(op == O_eq || op == O_ne)
! 	      && !((op == O_subtract
! 		    || op == O_lt || op == O_le || op == O_ge || op == O_gt)
! 		   && seg_left == seg_right
! 		   && (seg_left != undefined_section
! 		       || add_symbol == op_symbol)))
! 	    report_op_error (symp, add_symbol, op_symbol);
! 	  
! 	  if (final_seg == expr_section || final_seg == undefined_section)
! 	    final_seg = absolute_section;
  
  	  /* Check for division by zero.  */
  	  if ((op == O_divide || op == O_modulus) && right == 0)

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