This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH, gas] PC-relative fx_offset calculation


On 2013/3/4 08:04 AM, Alan Modra wrote:
> On Fri, Mar 01, 2013 at 10:02:53PM +0800, Chung-Lin Tang wrote:
>> > So how does this (one liner) patch look, does the change look sensible?
> No, it is not correct.  fx_where is supposed to be location of the
> field where the fixup is applied.  "dot" is not necessarily the same
> location.  For intstance, given a 4 byte instruction that consists of
> a 2 byte opcode followed by a 2 byte offset field, "dot" will point to
> the start of the insn but fx_where ought to point at the field.
> ie. fx_where = dot + 2.  However if you simply had a .short directive
> with the same fixup, then both "dot" and fx_where will point to the
> same location.
> 

Thanks for the explanation, it makes things clearer.

It seems that fx_dot_value needs to be paired with the frag at the point
of saving, so here's a new patch that saves a pointer to the frag_now
along with dot_value. The pc-relative case now bases the calculation on
fx_dot_frag rather than fx_frag.

A few lines of comments in read.c:emit_expr() denoting the invalidating
of dot_value after frag_more() was also deleted, since I believe this is
not the case anymore after explicitly saving dot_frag/dot_value together.

This is only lightly tested so far, WDYT? (I believe this patch should
make more sense now...)

Thanks,
Chung-Lin

2013-03-06  Chung-Lin Tang  <cltang@codesourcery.com>

        * write.h (struct fix): Add fx_dot_frag field.
        (dot_frag): Declare.
        * write.c (dot_frag): New variable.
        (fix_new_internal): Set fx_dot_frag field with dot_frag.
        (fixup_segment): Base calculation of fx_offset with fx_dot_frag.
        * expr.c (expr): Save value of frag_now in dot_frag when setting
        dot_value.
        * read.c (emit_expr): Likewise. Delete comments.

Index: expr.c
===================================================================
RCS file: /cvs/src/src/gas/expr.c,v
retrieving revision 1.91
diff -u -p -r1.91 expr.c
--- expr.c	30 Jun 2012 00:27:31 -0000	1.91
+++ expr.c	6 Mar 2013 06:25:37 -0000
@@ -1735,7 +1735,10 @@ expr (int rankarg,		/* Larger # is highe
 
   /* Save the value of dot for the fixup code.  */
   if (rank == 0)
-    dot_value = frag_now_fix ();
+    {
+      dot_value = frag_now_fix ();
+      dot_frag = frag_now;
+    }
 
   retval = operand (resultP, mode);
 
Index: read.c
===================================================================
RCS file: /cvs/src/src/gas/read.c,v
retrieving revision 1.182
diff -u -p -r1.182 read.c
--- read.c	10 Jan 2013 19:51:54 -0000	1.182
+++ read.c	6 Mar 2013 06:25:37 -0000
@@ -4087,10 +4087,9 @@ emit_expr (expressionS *exp, unsigned in
   if (need_pass_2)
     return;
 
-  /* Grow the current frag now so that dot_value does not get invalidated
-     if the frag were to fill up in the frag_more() call below.  */
   frag_grow (nbytes);
   dot_value = frag_now_fix ();
+  dot_frag = frag_now;
 
 #ifndef NO_LISTING
 #ifdef OBJ_ELF
Index: write.c
===================================================================
RCS file: /cvs/src/src/gas/write.c,v
retrieving revision 1.154
diff -u -p -r1.154 write.c
--- write.c	4 Feb 2013 12:34:17 -0000	1.154
+++ write.c	6 Mar 2013 06:25:37 -0000
@@ -122,6 +122,9 @@ symbolS *abs_section_sym;
 /* Remember the value of dot when parsing expressions.  */
 addressT dot_value;
 
+/* The frag that dot_value is based from.  */
+fragS *dot_frag;
+
 /* Relocs generated by ".reloc" pseudo.  */
 struct reloc_list* reloc_list;
 
@@ -169,6 +172,7 @@ fix_new_internal (fragS *frag,		/* Which
   fixP->fx_subsy = sub_symbol;
   fixP->fx_offset = offset;
   fixP->fx_dot_value = dot_value;
+  fixP->fx_dot_frag = dot_frag;
   fixP->fx_pcrel = pcrel;
   fixP->fx_r_type = r_type;
   fixP->fx_im_disp = 0;
@@ -977,7 +981,7 @@ fixup_segment (fixS *fixP, segT this_seg
 	    {
 	      add_number -= S_GET_VALUE (fixP->fx_subsy);
 	      fixP->fx_offset = (add_number + fixP->fx_dot_value
-				 + fixP->fx_frag->fr_address);
+				 + fixP->fx_dot_frag->fr_address);
 
 	      /* Make it pc-relative.  If the back-end code has not
 		 selected a pc-relative reloc, cancel the adjustment
Index: write.h
===================================================================
RCS file: /cvs/src/src/gas/write.h,v
retrieving revision 1.22
diff -u -p -r1.22 write.h
--- write.h	5 Nov 2012 07:10:37 -0000	1.22
+++ write.h	6 Mar 2013 06:25:37 -0000
@@ -88,6 +88,9 @@ struct fix
   /* The value of dot when the fixup expression was parsed.  */
   addressT fx_dot_value;
 
+  /* The frag fx_dot_value is based on.  */
+  fragS *fx_dot_frag;
+
   /* Next fixS in linked list, or NULL.  */
   struct fix *fx_next;
 
@@ -162,6 +165,7 @@ struct reloc_list
 extern int finalize_syms;
 extern symbolS *abs_section_sym;
 extern addressT dot_value;
+extern fragS *dot_frag;
 extern struct reloc_list* reloc_list;
 
 extern void append (char **charPP, char *fromP, unsigned long length);

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]