diff options
author | Ian Lance Taylor <ian@airs.com> | 1997-02-03 17:38:41 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@airs.com> | 1997-02-03 17:38:41 +0000 |
commit | 3569064fb5f1bce22b31a3c9d425e7fffdd214c7 (patch) | |
tree | 7334c48a6b9669ae462f68d4b07c8c3739e43a82 /gas/symbols.c | |
parent | bcb686ca093cb2d6a0e9496d108f2328cc65acd2 (diff) | |
download | gdb-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.c | 156 |
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; |