public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* Re: [asm] Difference of symbols in another section
       [not found] <200109081344.f88Diif16713@harshad.wipro.com>
@ 2001-09-08  8:02 ` Harshad R Joglekar
  2001-09-09  6:56   ` Alan Modra
  0 siblings, 1 reply; 4+ messages in thread
From: Harshad R Joglekar @ 2001-09-08  8:02 UTC (permalink / raw)
  To: Alan Modra; +Cc: binutils

"Alan Modra" wrote:
> 
> With the current assembler, you get a branch to start+2.  Seems OK to me.
> 

The assembler gives an error only when listings are enabled:
Error:operation combines symbols in different segments

After some debugging though, I can see why you reverted that patch. I am
looking for an alternate solution.

The problem is expr () converts the expression (foo - bar) to a
O_constant when they are in the same frag. When listings are enabled, a
dummy frag is created for each input line, so the expression will be in
the data section.

How about removing the check itself from expr.c (patch below)? This
check is probably being done later when resolving symbols ??

regards
-- 
Harshad

Index: expr.c
===================================================================
RCS file: src/binutils/gas/expr.c,v
retrieving revision 1.1.1.1
diff -u -B -p -r1.1.1.1 expr.c
--- expr.c      24 Jul 2001 15:59:46 -0000      1.1.1.1
+++ expr.c      8 Sep 2001 20:03:33 -0000
@@ -1701,13 +1701,6 @@ expr (rankarg, resultP)
        }
       else if (! SEG_NORMAL (retval))
        retval = rightseg;
-      else if (SEG_NORMAL (rightseg)
-              && retval != rightseg
-#ifdef DIFF_EXPR_OK
-              && op_left != O_subtract
-#endif
-              )
-       as_bad (_("operation combines symbols in different segments"));
 
       op_right = operator (&op_chars);

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [asm] Difference of symbols in another section
  2001-09-08  8:02 ` [asm] Difference of symbols in another section Harshad R Joglekar
@ 2001-09-09  6:56   ` Alan Modra
  0 siblings, 0 replies; 4+ messages in thread
From: Alan Modra @ 2001-09-09  6:56 UTC (permalink / raw)
  To: Harshad R Joglekar; +Cc: binutils

On Sat, Sep 08, 2001 at 08:36:28PM +0530, Harshad R Joglekar wrote:
> 
> The assembler gives an error only when listings are enabled:

Ah, missed that.

> How about removing the check itself from expr.c (patch below)? This
> check is probably being done later when resolving symbols ??

I think we still want the check here, as otherwise we might lose the
line number information when reporting errors.

I'm going to commit the following, which should cure these problems (*),
and also extends allowed expressions a little.

	* expr.c (expr): Move code setting "retval" to the end of the loop,
	and rearrange for efficiency.  For "PIC code" subtraction, use
	"rightseg" rather than recalculating.  For "symbol OP symbol"
	subtract, set "retval" to absolute_section if symbols in same
	section.
	* symbols.c (resolve_symbol_value): Resolve "sym +/- expr" to an
	O_symbol.  Simplify a +/- b code.  Allow equality and non-equality
	comparisons on symbols from any section.  Allow other comparison
	operators as for subtraction.
	(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.
	(relax_segment <rs_machine_dependent>): Ensure segment for
	expression syms is set correctly.
	* config/tc-mips.c (md_estimate_size_before_relax): Likewise.
	* config/tc-i386.c (md_assemble <Output jumps>): Don't lose part
	of a complex expression when setting up frag_var.

*) At least on x86.  There are other gas/config/tc-* files that should
be patched similarly to tc-i386.c for frag_var calls.  hp has already
fixed cris, I see.  ;)

-- 
Alan Modra

Index: gas/expr.c
===================================================================
RCS file: /cvs/src/src/gas/expr.c,v
retrieving revision 1.38
diff -u -p -r1.38 expr.c
--- expr.c	2001/08/14 20:00:32	1.38
+++ expr.c	2001/09/09 12:55:05
@@ -1699,21 +1699,6 @@ expr (rankarg, resultP)
 	    }
 	}
 
-      if (retval == undefined_section)
-	{
-	  if (SEG_NORMAL (rightseg))
-	    retval = rightseg;
-	}
-      else if (! SEG_NORMAL (retval))
-	retval = rightseg;
-      else if (SEG_NORMAL (rightseg)
-	       && retval != rightseg
-#ifdef DIFF_EXPR_OK
-	       && op_left != O_subtract
-#endif
-	       )
-	as_bad (_("operation combines symbols in different segments"));
-
       op_right = operator (&op_chars);
 
       know (op_right == O_illegal
@@ -1769,7 +1754,7 @@ expr (rankarg, resultP)
 	       && resultP->X_op == O_symbol
 	       && (symbol_get_frag (right.X_add_symbol)
 		   == symbol_get_frag (resultP->X_add_symbol))
-	       && SEG_NORMAL (S_GET_SEGMENT (right.X_add_symbol)))
+	       && SEG_NORMAL (rightseg))
 
 	{
 	  resultP->X_add_number -= right.X_add_number;
@@ -1865,7 +1850,14 @@ expr (rankarg, resultP)
 	  if (op_left == O_add)
 	    resultP->X_add_number += right.X_add_number;
 	  else if (op_left == O_subtract)
-	    resultP->X_add_number -= right.X_add_number;
+	    {
+	      resultP->X_add_number -= right.X_add_number;
+	      if (retval == rightseg && SEG_NORMAL (retval))
+		{
+		  retval = absolute_section;
+		  rightseg = absolute_section;
+		}
+	    }
 	}
       else
 	{
@@ -1875,6 +1867,21 @@ expr (rankarg, resultP)
 	  resultP->X_op = op_left;
 	  resultP->X_add_number = 0;
 	  resultP->X_unsigned = 1;
+	}
+
+      if (retval != rightseg)
+	{
+	  if (! SEG_NORMAL (retval))
+	    {
+	      if (retval != undefined_section || SEG_NORMAL (rightseg))
+		retval = rightseg;
+	    }
+	  else if (SEG_NORMAL (rightseg)
+#ifdef DIFF_EXPR_OK
+		   && op_left != O_subtract
+#endif
+		   )
+	    as_bad (_("operation combines symbols in different segments"));
 	}
 
       op_left = op_right;
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/09 12:55:07
@@ -914,8 +914,11 @@ resolve_symbol_value (symp)
 	case O_symbol:
 	case O_symbol_rva:
 	  left = resolve_symbol_value (add_symbol);
-	do_symbol:
+	  seg_left = S_GET_SEGMENT (add_symbol);
+	  if (finalize_syms)
+	    symp->sy_value.X_op_symbol = NULL;
 
+	do_symbol:
 	  if (symp->sy_mri_common)
 	    {
 	      /* This is a symbol inside an MRI common section.  The
@@ -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,42 +1031,49 @@ 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;
 		}
 	    }
+
+	  /* Equality and non-equality tests are permitted on anything.
+	     Subtraction, and other comparison operators are 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.
 
-	  /* 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.  */
-	  /* Don't emit messages unless we're finalizing the symbol value,
+	     Don't emit messages unless we're finalizing the symbol value,
 	     otherwise we may get the same message multiple times.  */
-	  if ((seg_left != absolute_section
-	       || seg_right != absolute_section)
-	      && (op != O_subtract
+	  if (op != O_eq && op != O_ne
+	      && (seg_left != absolute_section
+		  || seg_right != absolute_section)
+	      && ((op != O_subtract
+		   && op != O_lt && op != O_le && op != O_ge && op != O_gt)
 		  || seg_left != seg_right
-		  || seg_left == undefined_section)
+		  || (seg_left == undefined_section
+		      && add_symbol != op_symbol))
 	      && finalize_syms)
 	    {
 	      char *file;
@@ -1114,8 +1144,15 @@ resolve_symbol_value (symp)
 	    case O_bit_and:		left &= right; break;
 	    case O_add:			left += right; break;
 	    case O_subtract:		left -= right; break;
-	    case O_eq:	left = left == right ? ~ (offsetT) 0 : 0; break;
-	    case O_ne:	left = left != right ? ~ (offsetT) 0 : 0; break;
+	    case O_eq:
+	    case O_ne:
+	      left = (left == right && seg_left == seg_right
+		      && (seg_left != undefined_section
+			  || add_symbol == op_symbol)
+		      ? ~ (offsetT) 0 : 0);
+	      if (symp->sy_value.X_op == O_ne)
+		left = ~left;
+	      break;
 	    case O_lt:	left = left <  right ? ~ (offsetT) 0 : 0; break;
 	    case O_le:	left = left <= right ? ~ (offsetT) 0 : 0; break;
 	    case O_ge:	left = left >= right ? ~ (offsetT) 0 : 0; break;
@@ -2144,6 +2181,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/09 12:55:07
@@ -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/09 12:55:09
@@ -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;
@@ -2264,6 +2260,12 @@ relax_segment (segment_frag_root, segmen
 	  break;
 
 	case rs_machine_dependent:
+	  /* If fr_symbol is an expression, this call to
+	     resolve_symbol_value sets up the correct segment, which will
+	     likely be needed in md_estimate_size_before_relax.  */
+	  if (fragP->fr_symbol)
+	    resolve_symbol_value (fragP->fr_symbol);
+
 	  address += md_estimate_size_before_relax (fragP, segment);
 	  break;
 
Index: gas/config/tc-mips.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-mips.c,v
retrieving revision 1.73
diff -u -p -r1.73 tc-mips.c
--- tc-mips.c	2001/09/07 05:54:11	1.73
+++ tc-mips.c	2001/09/09 12:55:38
@@ -11143,8 +11143,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;
 
Index: gas/config/tc-i386.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-i386.c,v
retrieving revision 1.102
diff -u -p -r1.102 tc-i386.c
--- tc-i386.c	2001/08/01 02:27:11	1.102
+++ tc-i386.c	2001/09/09 12:55:28
@@ -2741,6 +2741,9 @@ md_assemble (line)
       {
 	int code16;
 	int prefix;
+	relax_substateT subtype;
+	symbolS *sym;
+	offsetT off;
 
 	code16 = 0;
 	if (flag_code == CODE_16BIT)
@@ -2785,19 +2788,29 @@ md_assemble (line)
 	if (i.prefix[REX_PREFIX])
 	  *p++ = i.prefix[REX_PREFIX];
 	*p = i.tm.base_opcode;
-	/* 1 possible extra opcode + displacement go in var part.
+
+	if ((unsigned char) *p == JUMP_PC_RELATIVE)
+	  subtype = ENCODE_RELAX_STATE (UNCOND_JUMP, SMALL);
+	else if ((cpu_arch_flags & Cpu386) != 0)
+	  subtype = ENCODE_RELAX_STATE (COND_JUMP, SMALL);
+	else
+	  subtype = ENCODE_RELAX_STATE (COND_JUMP86, SMALL);
+	subtype |= code16;
+
+	sym = i.op[0].disps->X_add_symbol;
+	off = i.op[0].disps->X_add_number;
+
+	if (i.op[0].disps->X_op != O_constant
+	    && i.op[0].disps->X_op != O_symbol)
+	  {
+	    /* Handle complex expressions.  */
+	    sym = make_expr_symbol (i.op[0].disps);
+	    off = 0;
+	  }
+
+	/* 1 possible extra opcode + 4 byte displacement go in var part.
 	   Pass reloc in fr_var.  */
-	frag_var (rs_machine_dependent,
-		  1 + 4,
-		  i.reloc[0],
-		  ((unsigned char) *p == JUMP_PC_RELATIVE
-		   ? ENCODE_RELAX_STATE (UNCOND_JUMP, SMALL) | code16
-		   : ((cpu_arch_flags & Cpu386) != 0
-		      ? ENCODE_RELAX_STATE (COND_JUMP, SMALL) | code16
-		      : ENCODE_RELAX_STATE (COND_JUMP86, SMALL) | code16)),
-		  i.op[0].disps->X_add_symbol,
-		  i.op[0].disps->X_add_number,
-		  p);
+	frag_var (rs_machine_dependent, 5, i.reloc[0], subtype, sym, off, p);
       }
     else if (i.tm.opcode_modifier & (JumpByte | JumpDword))
       {

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [asm] Difference of symbols in another section
  2001-09-08  3:49 Harshad R Joglekar
@ 2001-09-08  6:30 ` Alan Modra
  0 siblings, 0 replies; 4+ messages in thread
From: Alan Modra @ 2001-09-08  6:30 UTC (permalink / raw)
  To: Harshad R Joglekar; +Cc: binutils

On Sat, Sep 08, 2001 at 04:22:59PM +0530, Harshad R Joglekar wrote:
> Hi Alan,
> 
> You had submitted the below patch for assembler (expr.c),
> http://sources.redhat.com/cgi-bin/cvsweb.cgi/src/gas/expr.c.diff?r1=1.33&r2=1.34&cvsroot=src&f=h
> 
> and then you reverted it in the next revision !! I couldn't find any
> message descrbing either of the changes.

See http://sources.redhat.com/ml/binutils/2001-05/msg00435.html
and the followup.

revision 1.35
date: 2001/05/25 01:59:43;  author: amodra;  state: Exp;  lines: +0 -13
Revert last patch.
----------------------------
revision 1.34
date: 2001/05/25 00:01:30;  author: amodra;  state: Exp;  lines: +13 -0
        * expr.c (expr): Set return value to absolute_section for
        subtractive operations on symbols within a segment.
        * read.c (pseudo_set): Set segment for complex expressions.

Looks like I reverted the ChangeLog too.  That was a bit naughty.

> The patch was useful in the following case:
> -----------------------------------------------
> .data
> foo:
>     .word 0x00
> bar:
> .text
> start:
>     jmp start + (bar - foo)

With the current assembler, you get a branch to start+2.  Seems OK to me.

Alan

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [asm] Difference of symbols in another section
@ 2001-09-08  3:49 Harshad R Joglekar
  2001-09-08  6:30 ` Alan Modra
  0 siblings, 1 reply; 4+ messages in thread
From: Harshad R Joglekar @ 2001-09-08  3:49 UTC (permalink / raw)
  To: binutils

Hi Alan,

You had submitted the below patch for assembler (expr.c),
http://sources.redhat.com/cgi-bin/cvsweb.cgi/src/gas/expr.c.diff?r1=1.33&r2=1.34&cvsroot=src&f=h

and then you reverted it in the next revision !! I couldn't find any
message descrbing either of the changes.

The patch was useful in the following case:
-----------------------------------------------
.data
foo:
    .word 0x00
bar:
.text
start:
    jmp start + (bar - foo)
---------------------------------------------

The i386 and ARM assemblers parse this with default options,
but complain when listings are enabled.

The patch you had submitted corrected the problem, and I did not find
any side-effects, although I have not tested it thoroughly.

If there are no issues, can you reapply that patch?

regards,
Harshad

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2001-09-09  6:56 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <200109081344.f88Diif16713@harshad.wipro.com>
2001-09-08  8:02 ` [asm] Difference of symbols in another section Harshad R Joglekar
2001-09-09  6:56   ` Alan Modra
2001-09-08  3:49 Harshad R Joglekar
2001-09-08  6:30 ` 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).