* Fix PR997, gas listings breakage
@ 2006-04-04 8:03 Alan Modra
0 siblings, 0 replies; only message in thread
From: Alan Modra @ 2006-04-04 8:03 UTC (permalink / raw)
To: binutils
Turning on gas listings can break perfectly good assembly. See the
PR for an example and analysis. This patch mends some of the damage.
Except when listings are turned on, the frag list traversal will
terminate fairly quickly so there shouldn't be a noticeable slowdown
due to the extra processing here.
PR 997
* frags.c (frag_offset_fixed_p): New function.
* frags.h (frag_offset_fixed_p): Declare.
* expr.c (expr): Use frag_offset_fixed_p when simplifying subtraction.
(resolve_expression): Likewise.
Index: gas/frags.c
===================================================================
RCS file: /cvs/src/src/gas/frags.c,v
retrieving revision 1.18
diff -u -p -r1.18 frags.c
--- gas/frags.c 10 May 2005 15:10:04 -0000 1.18
+++ gas/frags.c 4 Apr 2006 07:18:32 -0000
@@ -1,6 +1,6 @@
/* frags.c - manage frags -
Copyright 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2003, 2004
+ 1999, 2000, 2001, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
@@ -383,3 +383,55 @@ frag_append_1_char (int datum)
}
obstack_1grow (&frchain_now->frch_obstack, datum);
}
+
+/* Return TRUE if FRAG1 and FRAG2 have a fixed relationship between
+ their start addresses. Set OFFSET to the difference in address
+ not already accounted for in the frag FR_ADDRESS. */
+
+bfd_boolean
+frag_offset_fixed_p (fragS *frag1, fragS *frag2, bfd_vma *offset)
+{
+ fragS *frag;
+ bfd_vma off;
+
+ /* Start with offset initialised to difference between the two frags.
+ Prior to assigning frag addresses this will be zero. */
+ off = frag1->fr_address - frag2->fr_address;
+ if (frag1 == frag2)
+ {
+ *offset = off;
+ return TRUE;
+ }
+
+ /* Maybe frag2 is after frag1. */
+ frag = frag1;
+ while (frag->fr_type == rs_fill)
+ {
+ off += frag->fr_fix + frag->fr_offset * frag->fr_var;
+ frag = frag->fr_next;
+ if (frag == NULL)
+ break;
+ if (frag == frag2)
+ {
+ *offset = off;
+ return TRUE;
+ }
+ }
+
+ /* Maybe frag1 is after frag2. */
+ frag = frag2;
+ while (frag->fr_type == rs_fill)
+ {
+ off -= frag->fr_fix + frag->fr_offset * frag->fr_var;
+ frag = frag->fr_next;
+ if (frag == NULL)
+ break;
+ if (frag == frag1)
+ {
+ *offset = off;
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
Index: gas/frags.h
===================================================================
RCS file: /cvs/src/src/gas/frags.h,v
retrieving revision 1.20
diff -u -p -r1.20 frags.h
--- gas/frags.h 8 Jul 2005 05:57:20 -0000 1.20
+++ gas/frags.h 4 Apr 2006 07:18:32 -0000
@@ -1,6 +1,6 @@
/* frags.h - Header file for the frag concept.
Copyright 1987, 1992, 1993, 1994, 1995, 1997, 1998, 1999, 2000, 2001,
- 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+ 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
@@ -148,4 +148,6 @@ char *frag_var (relax_stateT type,
offsetT offset,
char *opcode);
+bfd_boolean frag_offset_fixed_p (fragS *, fragS *, bfd_vma *);
+
#endif /* FRAGS_H */
Index: gas/expr.c
===================================================================
RCS file: /cvs/src/src/gas/expr.c,v
retrieving revision 1.64
diff -u -p -r1.64 expr.c
--- gas/expr.c 22 Dec 2005 17:05:40 -0000 1.64
+++ gas/expr.c 4 Apr 2006 08:02:27 -0000
@@ -1,6 +1,6 @@
/* expr.c -operands, expressions-
Copyright 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004, 2005
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
@@ -1662,6 +1662,7 @@ expr (int rankarg, /* Larger # is highe
while (op_left != O_illegal && op_rank[(int) op_left] > rank)
{
segT rightseg;
+ bfd_vma frag_off;
input_line_pointer += op_chars; /* -> after operator. */
@@ -1741,12 +1742,15 @@ expr (int rankarg, /* Larger # is highe
else if (op_left == O_subtract
&& right.X_op == O_symbol
&& resultP->X_op == O_symbol
- && (symbol_get_frag (right.X_add_symbol)
- == symbol_get_frag (resultP->X_add_symbol))
+ && retval == rightseg
&& (SEG_NORMAL (rightseg)
- || right.X_add_symbol == resultP->X_add_symbol))
+ || right.X_add_symbol == resultP->X_add_symbol)
+ && frag_offset_fixed_p (symbol_get_frag (resultP->X_add_symbol),
+ symbol_get_frag (right.X_add_symbol),
+ &frag_off))
{
resultP->X_add_number -= right.X_add_number;
+ resultP->X_add_number -= frag_off / OCTETS_PER_BYTE;
resultP->X_add_number += (S_GET_VALUE (resultP->X_add_symbol)
- S_GET_VALUE (right.X_add_symbol));
resultP->X_op = O_constant;
@@ -1900,6 +1904,7 @@ resolve_expression (expressionS *express
valueT left, right;
segT seg_left, seg_right;
fragS *frag_left, *frag_right;
+ bfd_vma frag_off;
switch (op)
{
@@ -2002,13 +2007,15 @@ resolve_expression (expressionS *express
on the input value.
Otherwise, both operands must be absolute. We already handled
the case of addition or subtraction of a constant above. */
+ frag_off = 0;
if (!(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
- && (finalize_syms || frag_left == frag_right)
+ && (finalize_syms
+ || frag_offset_fixed_p (frag_left, frag_right, &frag_off))
&& (seg_left != reg_section || left == right)
&& (seg_left != undefined_section || add_symbol == op_symbol)))
{
@@ -2068,6 +2075,7 @@ resolve_expression (expressionS *express
return 0;
}
+ right += frag_off / OCTETS_PER_BYTE;
switch (op)
{
case O_add: left += right; break;
--
Alan Modra
IBM OzLabs - Linux Technology Centre
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2006-04-04 8:03 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-04-04 8:03 Fix PR997, gas listings breakage Alan Modra
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).