This is the mail archive of the binutils@sources.redhat.com 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]

More pcrel fixes for x86-64 gas


As it turned out, the last pcrel fixes for x86-64 were not good enough.
This one has a good chance to be the final version. :-) Approved privately
by Jan Hubicka and checked into mainline and 2.12 branch.

Andreas.

2002-04-24  Andreas Schwab  <schwab@suse.de>

	* config/tc-i386.c (output_jump, output_disp)
	(md_estimate_size_before_relax): Don't set fx_pcrel_adjust any
	more.
	(md_apply_fix3): Remember addend value for rela relocations.
	(tc_gen_reloc): Correctly compute pc-relative relocation addend.

--- gas/config/tc-i386.c.~1.115.~	2002-04-11 12:14:36.000000000 +0200
+++ gas/config/tc-i386.c	2002-04-24 14:56:05.000000000 +0200
@@ -2980,7 +2980,6 @@ output_jump ()
 {
   char *p;
   int size;
-  fixS *fixP;
 
   if (i.tm.opcode_modifier & JumpByte)
     {
@@ -3031,9 +3030,8 @@ output_jump ()
   p = frag_more (1 + size);
   *p++ = i.tm.base_opcode;
 
-  fixP = fix_new_exp (frag_now, p - frag_now->fr_literal, size,
-		      i.op[0].disps, 1, reloc (size, 1, 1, i.reloc[0]));
-  fixP->fx_pcrel_adjust = size;
+  fix_new_exp (frag_now, p - frag_now->fr_literal, size,
+	       i.op[0].disps, 1, reloc (size, 1, 1, i.reloc[0]));
 }
 
 static void
@@ -3226,7 +3224,6 @@ output_disp ()
 	      int size = 4;
 	      int sign = 0;
 	      int pcrel = (i.flags[n] & Operand_PCrel) != 0;
-	      fixS *fixP;
 
 	      /* The PC relative address is computed relative
 		 to the instruction boundary, so in case immediate
@@ -3266,11 +3263,9 @@ output_disp ()
 		}
 
 	      p = frag_more (size);
-	      fixP = fix_new_exp (frag_now, p - frag_now->fr_literal, size,
-				  i.op[n].disps, pcrel,
-				  reloc (size, pcrel, sign, i.reloc[n]));
-	      if (pcrel)
-		fixP->fx_pcrel_adjust = size;
+	      fix_new_exp (frag_now, p - frag_now->fr_literal, size,
+			   i.op[n].disps, pcrel,
+			   reloc (size, pcrel, sign, i.reloc[n]));
 	    }
 	}
     }
@@ -4215,7 +4210,6 @@ md_estimate_size_before_relax (fragP, se
       RELOC_ENUM reloc_type;
       unsigned char *opcode;
       int old_fr_fix;
-      fixS *fixP;
 
       if (fragP->fr_var != NO_RELOC)
 	reloc_type = fragP->fr_var;
@@ -4233,11 +4227,10 @@ md_estimate_size_before_relax (fragP, se
 	  /* Make jmp (0xeb) a (d)word displacement jump.  */
 	  opcode[0] = 0xe9;
 	  fragP->fr_fix += size;
-	  fixP = fix_new (fragP, old_fr_fix, size,
-			  fragP->fr_symbol,
-			  fragP->fr_offset, 1,
-			  reloc_type);
-	  fixP->fx_pcrel_adjust = size;
+	  fix_new (fragP, old_fr_fix, size,
+		   fragP->fr_symbol,
+		   fragP->fr_offset, 1,
+		   reloc_type);
 	  break;
 
 	case COND_JUMP86:
@@ -4255,11 +4248,10 @@ md_estimate_size_before_relax (fragP, se
 	      /* We added two extra opcode bytes, and have a two byte
 		 offset.  */
 	      fragP->fr_fix += 2 + 2;
-	      fixP = fix_new (fragP, old_fr_fix + 2, 2,
-			      fragP->fr_symbol,
-			      fragP->fr_offset, 1,
-			      reloc_type);
-	      fixP->fx_pcrel_adjust = size;
+	      fix_new (fragP, old_fr_fix + 2, 2,
+		       fragP->fr_symbol,
+		       fragP->fr_offset, 1,
+		       reloc_type);
 	      break;
 	    }
 	  /* Fall through.  */
@@ -4274,11 +4266,10 @@ md_estimate_size_before_relax (fragP, se
 	  opcode[0] = TWO_BYTE_OPCODE_ESCAPE;
 	  /* We've added an opcode byte.  */
 	  fragP->fr_fix += 1 + size;
-	  fixP = fix_new (fragP, old_fr_fix + 1, size,
-			  fragP->fr_symbol,
-			  fragP->fr_offset, 1,
-			  reloc_type);
-	  fixP->fx_pcrel_adjust = size;
+	  fix_new (fragP, old_fr_fix + 1, size,
+		   fragP->fr_symbol,
+		   fragP->fr_offset, 1,
+		   reloc_type);
 	  break;
 
 	default:
@@ -4607,6 +4598,8 @@ md_apply_fix3 (fixP, valP, seg)
   else if (use_rela_relocations)
     {
       fixP->fx_no_overflow = 1;
+      /* Remember value for tc_gen_reloc.  */
+      fixP->fx_addnumber = value;
       value = 0;
     }
 #endif
@@ -5120,9 +5113,23 @@ tc_gen_reloc (section, fixp)
   /* Use the rela in 64bit mode.  */
   else
     {
-      rel->addend = fixp->fx_offset;
-      if (fixp->fx_pcrel)
-	rel->addend -= fixp->fx_pcrel_adjust;
+      if (!fixp->fx_pcrel)
+	rel->addend = fixp->fx_offset;
+      else
+	switch (code)
+	  {
+	  case BFD_RELOC_X86_64_PLT32:
+	  case BFD_RELOC_X86_64_GOT32:
+	  case BFD_RELOC_X86_64_GOTPCREL:
+	    rel->addend = fixp->fx_offset - fixp->fx_size;
+	    break;
+	  default:
+	    rel->addend = (section->vma
+			   - fixp->fx_size
+			   + fixp->fx_addnumber
+			   + md_pcrel_from (fixp));
+	    break;
+	  }
     }
 
   rel->howto = bfd_reloc_type_lookup (stdoutput, code);

-- 
Andreas Schwab, SuSE Labs, schwab@suse.de
SuSE GmbH, Deutschherrnstr. 15-19, D-90429 Nürnberg
Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."


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