This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
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);