This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
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;