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]

[PATCH] MIPS bfd: Fix addend for _gp_disp special symbol


Hello All,

the addend calculation for _gp_disp's R_MIPS_HI16 relocation is
broken because its special case was improperly intermingled with
the normal one. This led to a non-zero inplace addend for
addresses above 0x8000. The appended patch fixes it.


Thiemo


2003-06-26  Thiemo Seufer <seufer@csv.ica.uni-stuttgart.de>

	/bfd/ChangeLog
	* elf32-mips.c: Fix addend for _gp_disp special symbol.


diff -BurpNX /bigdisk/src/gcc-exclude source-orig/bfd/elf32-mips.c source/bfd/elf32-mips.c
--- source-orig/bfd/elf32-mips.c	Thu Jun 12 15:21:40 2003
+++ source/bfd/elf32-mips.c	Thu Jun 26 06:08:02 2003
@@ -887,41 +886,42 @@ mips_elf_lo16_reloc (abfd, reloc_entry, 
 	  unsigned long vallo;
 	  struct mips_hi16 *next;
 
-	  /* Do the HI16 relocation.  Note that we actually don't need
-	     to know anything about the LO16 itself, except where to
-	     find the low 16 bits of the addend needed by the LO16.  */
-	  insn = bfd_get_32 (abfd, l->addr);
-	  vallo = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
-
-	  /* The low order 16 bits are always treated as a signed
-	     value.  */
-	  vallo = ((vallo & 0xffff) ^ 0x8000) - 0x8000;
-	  val = ((insn & 0xffff) << 16) + vallo;
-	  val += l->addend;
-
-	  /* If PC-relative, we need to subtract out the address of the LO
-	     half of the HI/LO.  (The actual relocation is relative
-	     to that instruction.)  */
-	  if (reloc_entry->howto->pc_relative)
-	    val -= reloc_entry->address;
-
-	  /* At this point, "val" has the value of the combined HI/LO
-	     pair.  If the low order 16 bits (which will be used for
-	     the LO16 insn) are negative, then we will need an
-	     adjustment for the high order 16 bits.  */
-	  val += 0x8000;
-	  val = (val >> 16) & 0xffff;
-
-	  insn &= ~ (bfd_vma) 0xffff;
-	  insn |= val;
-	  bfd_put_32 (abfd, (bfd_vma) insn, l->addr);
-
 	  if (strcmp (bfd_asymbol_name (symbol), "_gp_disp") == 0)
 	    {
 	      gp_disp_relent = *reloc_entry;
 	      reloc_entry = &gp_disp_relent;
 	      reloc_entry->addend = l->addend;
 	    }
+	  else
+	    {
+	      /* Do the HI16 relocation.  Note that we actually don't need
+		 to know anything about the LO16 itself, except where to
+		 find the low 16 bits of the addend needed by the LO16.  */
+	      insn = bfd_get_32 (abfd, l->addr);
+	      vallo = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
+	      /* The low order 16 bits are always treated as a signed
+		 value.  */
+	      vallo = ((vallo & 0xffff) ^ 0x8000) - 0x8000;
+	      val = ((insn & 0xffff) << 16) + vallo;
+	      val += l->addend;
+
+	      /* If PC-relative, we need to subtract out the address of the LO
+		 half of the HI/LO.  (The actual relocation is relative
+		 to that instruction.)  */
+	      if (reloc_entry->howto->pc_relative)
+		val -= reloc_entry->address;
+
+	      /* At this point, "val" has the value of the combined HI/LO
+		 pair.  If the low order 16 bits (which will be used for
+		 the LO16 insn) are negative, then we will need an
+		 adjustment for the high order 16 bits.  */
+	      val += 0x8000;
+	      val = (val >> 16) & 0xffff;
+
+	      insn &= ~ (bfd_vma) 0xffff;
+	      insn |= val;
+	      bfd_put_32 (abfd, (bfd_vma) insn, l->addr);
+	    }
 
 	  next = l->next;
 	  free (l);


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