* symbols.c (resolve_symbol_value): Don't change X_add_number for
an equated symbol. * write.c (write_relocs): Avoid looping on equated symbols. Adjust fx_offset by X_add_number for each symbol. * config/obj-coff.c (do_relocs_for): Avoid looping on equated symbols. (fixup_segment): Add a loop to track down equated symbols and adjust fx_offset appropriately.
This commit is contained in:
parent
bcb686ca09
commit
3569064fb5
@ -1,3 +1,14 @@
|
||||
Mon Feb 3 12:35:54 1997 Ian Lance Taylor <ian@cygnus.com>
|
||||
|
||||
* symbols.c (resolve_symbol_value): Don't change X_add_number for
|
||||
an equated symbol.
|
||||
* write.c (write_relocs): Avoid looping on equated symbols.
|
||||
Adjust fx_offset by X_add_number for each symbol.
|
||||
* config/obj-coff.c (do_relocs_for): Avoid looping on equated
|
||||
symbols.
|
||||
(fixup_segment): Add a loop to track down equated symbols and
|
||||
adjust fx_offset appropriately.
|
||||
|
||||
Fri Jan 31 15:21:02 1997 Jeffrey A Law (law@cygnus.com)
|
||||
|
||||
* config/tc-mn10200.c (md_relax_table): Add entries to allow
|
||||
|
168
gas/symbols.c
168
gas/symbols.c
@ -639,7 +639,35 @@ resolve_symbol_value (symp)
|
||||
|
||||
symp->sy_resolving = 1;
|
||||
|
||||
reduce:
|
||||
/* Simplify addition or subtraction of a constant by folding the
|
||||
constant into X_add_number. */
|
||||
if (symp->sy_value.X_op == O_add
|
||||
|| symp->sy_value.X_op == O_subtract)
|
||||
{
|
||||
resolve_symbol_value (symp->sy_value.X_add_symbol);
|
||||
resolve_symbol_value (symp->sy_value.X_op_symbol);
|
||||
if (S_GET_SEGMENT (symp->sy_value.X_op_symbol) == absolute_section)
|
||||
{
|
||||
right = S_GET_VALUE (symp->sy_value.X_op_symbol);
|
||||
if (symp->sy_value.X_op == O_add)
|
||||
symp->sy_value.X_add_number += right;
|
||||
else
|
||||
symp->sy_value.X_add_number -= right;
|
||||
symp->sy_value.X_op = O_symbol;
|
||||
symp->sy_value.X_op_symbol = NULL;
|
||||
}
|
||||
else if ((S_GET_SEGMENT (symp->sy_value.X_add_symbol)
|
||||
== absolute_section)
|
||||
&& symp->sy_value.X_op == O_add)
|
||||
{
|
||||
left = S_GET_VALUE (symp->sy_value.X_add_symbol);
|
||||
symp->sy_value.X_add_symbol = symp->sy_value.X_op_symbol;
|
||||
symp->sy_value.X_add_number += left;
|
||||
symp->sy_value.X_op = O_symbol;
|
||||
symp->sy_value.X_op_symbol = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
switch (symp->sy_value.X_op)
|
||||
{
|
||||
case O_absent:
|
||||
@ -668,22 +696,26 @@ resolve_symbol_value (symp)
|
||||
if (symp->sy_value.X_add_number == 0)
|
||||
copy_symbol_attributes (symp, symp->sy_value.X_add_symbol);
|
||||
|
||||
S_SET_VALUE (symp,
|
||||
(symp->sy_value.X_add_number
|
||||
+ symp->sy_frag->fr_address
|
||||
+ S_GET_VALUE (symp->sy_value.X_add_symbol)));
|
||||
if (S_GET_SEGMENT (symp) == expr_section
|
||||
|| S_GET_SEGMENT (symp) == undefined_section)
|
||||
S_SET_SEGMENT (symp,
|
||||
S_GET_SEGMENT (symp->sy_value.X_add_symbol));
|
||||
|
||||
/* If we have equated this symbol to an undefined symbol, we
|
||||
keep X_op set to O_symbol. 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 is equated. */
|
||||
if (! S_IS_DEFINED (symp) || S_IS_COMMON (symp))
|
||||
keep X_op set to O_symbol, and we 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
|
||||
is equated. */
|
||||
if (! S_IS_DEFINED (symp->sy_value.X_add_symbol)
|
||||
|| S_IS_COMMON (symp->sy_value.X_add_symbol))
|
||||
symp->sy_value.X_op = O_symbol;
|
||||
else
|
||||
{
|
||||
S_SET_VALUE (symp,
|
||||
(symp->sy_value.X_add_number
|
||||
+ symp->sy_frag->fr_address
|
||||
+ S_GET_VALUE (symp->sy_value.X_add_symbol)));
|
||||
if (S_GET_SEGMENT (symp) == expr_section
|
||||
|| S_GET_SEGMENT (symp) == undefined_section)
|
||||
S_SET_SEGMENT (symp,
|
||||
S_GET_SEGMENT (symp->sy_value.X_add_symbol));
|
||||
}
|
||||
|
||||
resolved = symp->sy_value.X_add_symbol->sy_resolved;
|
||||
break;
|
||||
@ -708,39 +740,6 @@ resolve_symbol_value (symp)
|
||||
resolved = symp->sy_value.X_add_symbol->sy_resolved;
|
||||
break;
|
||||
|
||||
case O_add:
|
||||
resolve_symbol_value (symp->sy_value.X_add_symbol);
|
||||
resolve_symbol_value (symp->sy_value.X_op_symbol);
|
||||
seg_left = S_GET_SEGMENT (symp->sy_value.X_add_symbol);
|
||||
seg_right = S_GET_SEGMENT (symp->sy_value.X_op_symbol);
|
||||
/* This case comes up with PIC support. */
|
||||
{
|
||||
symbolS *s_left = symp->sy_value.X_add_symbol;
|
||||
symbolS *s_right = symp->sy_value.X_op_symbol;
|
||||
|
||||
if (seg_left == absolute_section)
|
||||
{
|
||||
symbolS *t;
|
||||
segT ts;
|
||||
t = s_left;
|
||||
s_left = s_right;
|
||||
s_right = t;
|
||||
ts = seg_left;
|
||||
seg_left = seg_right;
|
||||
seg_right = ts;
|
||||
}
|
||||
if (seg_right == absolute_section
|
||||
&& s_right->sy_resolved)
|
||||
{
|
||||
symp->sy_value.X_add_number += S_GET_VALUE (s_right);
|
||||
symp->sy_value.X_op_symbol = 0;
|
||||
symp->sy_value.X_add_symbol = s_left;
|
||||
symp->sy_value.X_op = O_symbol;
|
||||
goto reduce;
|
||||
}
|
||||
}
|
||||
/* fall through */
|
||||
|
||||
case O_multiply:
|
||||
case O_divide:
|
||||
case O_modulus:
|
||||
@ -750,6 +749,7 @@ resolve_symbol_value (symp)
|
||||
case O_bit_or_not:
|
||||
case O_bit_exclusive_or:
|
||||
case O_bit_and:
|
||||
case O_add:
|
||||
case O_subtract:
|
||||
case O_eq:
|
||||
case O_ne:
|
||||
@ -763,38 +763,50 @@ resolve_symbol_value (symp)
|
||||
resolve_symbol_value (symp->sy_value.X_op_symbol);
|
||||
seg_left = S_GET_SEGMENT (symp->sy_value.X_add_symbol);
|
||||
seg_right = S_GET_SEGMENT (symp->sy_value.X_op_symbol);
|
||||
if (seg_left != seg_right
|
||||
&& seg_left != undefined_section
|
||||
&& seg_right != undefined_section)
|
||||
{
|
||||
char *file;
|
||||
unsigned int line;
|
||||
|
||||
if (expr_symbol_where (symp, &file, &line))
|
||||
as_bad_where
|
||||
(file, line,
|
||||
"illegal operation on symbols in different sections");
|
||||
else
|
||||
as_bad
|
||||
("%s set to illegal operation on symbols in different sections",
|
||||
S_GET_NAME (symp));
|
||||
}
|
||||
if ((S_GET_SEGMENT (symp->sy_value.X_add_symbol)
|
||||
!= absolute_section)
|
||||
&& symp->sy_value.X_op != O_subtract)
|
||||
{
|
||||
char *file;
|
||||
unsigned int line;
|
||||
|
||||
if (expr_symbol_where (symp, &file, &line))
|
||||
as_bad_where (file, line,
|
||||
"illegal operation on non-absolute symbols");
|
||||
else
|
||||
as_bad ("%s set to illegal operation on non-absolute symbols",
|
||||
S_GET_NAME (symp));
|
||||
}
|
||||
left = S_GET_VALUE (symp->sy_value.X_add_symbol);
|
||||
right = S_GET_VALUE (symp->sy_value.X_op_symbol);
|
||||
|
||||
/* Subtraction is permitted if both operands are in the same
|
||||
section. Otherwise, both operands must be absolute. We
|
||||
already handled the case of addition or subtraction of a
|
||||
constant above. This will probably need to be changed
|
||||
for an object file format which supports arbitrary
|
||||
expressions, such as IEEE-695. */
|
||||
if ((seg_left != absolute_section
|
||||
|| seg_right != absolute_section)
|
||||
&& (symp->sy_value.X_op != O_subtract
|
||||
|| seg_left != seg_right))
|
||||
{
|
||||
char *file;
|
||||
unsigned int line;
|
||||
|
||||
if (expr_symbol_where (symp, &file, &line))
|
||||
{
|
||||
if (seg_left == undefined_section
|
||||
|| seg_right == undefined_section)
|
||||
as_bad_where (file, line,
|
||||
"undefined symbol %s in operation",
|
||||
(seg_left == undefined_section
|
||||
? S_GET_NAME (symp->sy_value.X_add_symbol)
|
||||
: S_GET_NAME (symp->sy_value.X_op_symbol)));
|
||||
else
|
||||
as_bad_where (file, line, "invalid section for operation");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (seg_left == undefined_section
|
||||
|| seg_right == undefined_section)
|
||||
as_bad ("undefined symbol %s in operation setting %s",
|
||||
(seg_left == undefined_section
|
||||
? S_GET_NAME (symp->sy_value.X_add_symbol)
|
||||
: S_GET_NAME (symp->sy_value.X_op_symbol)),
|
||||
S_GET_NAME (symp));
|
||||
else
|
||||
as_bad ("invalid section for operation setting %s",
|
||||
S_GET_NAME (symp));
|
||||
}
|
||||
}
|
||||
|
||||
switch (symp->sy_value.X_op)
|
||||
{
|
||||
case O_multiply: val = left * right; break;
|
||||
|
12
gas/write.c
12
gas/write.c
@ -874,7 +874,17 @@ write_relocs (abfd, sec, xxx)
|
||||
sym = fixp->fx_addsy;
|
||||
while (sym->sy_value.X_op == O_symbol
|
||||
&& (! S_IS_DEFINED (sym) || S_IS_COMMON (sym)))
|
||||
sym = sym->sy_value.X_add_symbol;
|
||||
{
|
||||
symbolS *n;
|
||||
|
||||
/* We must avoid looping, as that can occur with a badly
|
||||
written program. */
|
||||
n = sym->sy_value.X_add_symbol;
|
||||
if (n == sym)
|
||||
break;
|
||||
fixp->fx_offset += sym->sy_value.X_add_number;
|
||||
sym = n;
|
||||
}
|
||||
fixp->fx_addsy = sym;
|
||||
|
||||
reloc = tc_gen_reloc (sec, fixp);
|
||||
|
Loading…
x
Reference in New Issue
Block a user