This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
ill formed relocations
- From: Nathan Sidwell <nathan at codesourcery dot com>
- To: Binutils <binutils at sources dot redhat dot com>
- Date: Fri, 29 Nov 2002 16:48:30 +0000
- Subject: 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)