aboutsummaryrefslogtreecommitdiff
path: root/gas/symbols.c
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@airs.com>1997-02-03 17:38:41 +0000
committerIan Lance Taylor <ian@airs.com>1997-02-03 17:38:41 +0000
commit3569064fb5f1bce22b31a3c9d425e7fffdd214c7 (patch)
tree7334c48a6b9669ae462f68d4b07c8c3739e43a82 /gas/symbols.c
parentbcb686ca093cb2d6a0e9496d108f2328cc65acd2 (diff)
downloadgdb-3569064fb5f1bce22b31a3c9d425e7fffdd214c7.zip
gdb-3569064fb5f1bce22b31a3c9d425e7fffdd214c7.tar.gz
gdb-3569064fb5f1bce22b31a3c9d425e7fffdd214c7.tar.bz2
* 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.
Diffstat (limited to 'gas/symbols.c')
-rw-r--r--gas/symbols.c156
1 files changed, 84 insertions, 72 deletions
diff --git a/gas/symbols.c b/gas/symbols.c
index fa2fadb..def3f6b 100644
--- a/gas/symbols.c
+++ b/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;
+ left = S_GET_VALUE (symp->sy_value.X_add_symbol);
+ right = S_GET_VALUE (symp->sy_value.X_op_symbol);
- 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)
+ /* 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))
- as_bad_where (file, line,
- "illegal operation on non-absolute symbols");
+ {
+ 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
- as_bad ("%s set to illegal operation on non-absolute symbols",
- S_GET_NAME (symp));
+ {
+ 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));
+ }
}
- left = S_GET_VALUE (symp->sy_value.X_add_symbol);
- right = S_GET_VALUE (symp->sy_value.X_op_symbol);
+
switch (symp->sy_value.X_op)
{
case O_multiply: val = left * right; break;