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]

Fix x86-64 relocations



On x86-64 we generated 32 bit relocations even for some 8/16 and 64
bit relocations and used the 64 bit relative condition without
checking for sizes.

This code follows the code from m68k (guess who looked over the
code;-) and produces working dynamic binaries (at least one works, now
I'll have fix the next bug).

I'll commit this later after some more testing and incorporating any
comments I get.

Andreas 

2001-05-31  Andreas Jaeger  <aj@suse.de>

	* elf64-x86-64.c (elf64_x86_64_relocate_section): Don't use 32 bit
	relocations for all types, fix logic.

============================================================
Index: bfd/elf64-x86-64.c
--- bfd/elf64-x86-64.c	2001/05/30 18:44:46	1.17
+++ bfd/elf64-x86-64.c	2001/05/31 12:47:33
@@ -1264,12 +1264,12 @@
 		      && ((! info->symbolic && h->dynindx != -1)
 			  || (h->elf_link_hash_flags
 			      & ELF_LINK_HASH_DEF_REGULAR) == 0)
-		      && ( r_type == R_X86_64_8 ||
-			   r_type == R_X86_64_16 ||
-                           r_type == R_X86_64_32 ||
-			   r_type == R_X86_64_64 ||
-                           r_type == R_X86_64_PC16 ||
-			   r_type == R_X86_64_PC32)
+		      && ( r_type == R_X86_64_8
+			   || r_type == R_X86_64_16
+			   || r_type == R_X86_64_32
+			   || r_type == R_X86_64_64
+                           || r_type == R_X86_64_PC16
+			   || r_type == R_X86_64_PC32)
                       && ((input_section->flags & SEC_ALLOC) != 0
                           /* DWARF will emit R_X86_64_32 relocations in its
                              sections against symbols defined externally
@@ -1433,24 +1433,26 @@
 			+ h->plt.offset);
 	  break;
 
+	case R_X86_64_PC8:
+	case R_X86_64_PC16:
+	case R_X86_64_PC32:
+	  if (h == NULL)
+	    break;
+	  /* Fall through.  */
 	case R_X86_64_8:
 	case R_X86_64_16:
 	case R_X86_64_32:
 	case R_X86_64_64:
-	case R_X86_64_PC8:
-	case R_X86_64_PC16:
-	case R_X86_64_PC32:
-	  /* FIXME: The abi says the linker should make sure the value is
+	  /* FIXME: The ABI says the linker should make sure the value is
 	     the same when it's zeroextended to 64 bit.	 */
 	  if (info->shared
 	      && (input_section->flags & SEC_ALLOC) != 0
-	      && ((r_type != R_X86_64_PC8 && r_type != R_X86_64_PC16
+	      && ((r_type != R_X86_64_PC8
+		   && r_type != R_X86_64_PC16
 		   && r_type != R_X86_64_PC32)
-		  || (h != NULL
-		      && h->dynindx != -1
-		      && (! info->symbolic
-			  || (h->elf_link_hash_flags
-			      & ELF_LINK_HASH_DEF_REGULAR) == 0))))
+		  || (! info->symbolic
+		      || (h->elf_link_hash_flags
+			  & ELF_LINK_HASH_DEF_REGULAR) == 0)))
 	    {
 	      Elf_Internal_Rela outrel;
 	      boolean skip, relocate;
@@ -1505,22 +1507,21 @@
 		  memset (&outrel, 0, sizeof outrel);
 		  relocate = false;
 		}
-	      else if ((r_type == R_X86_64_PC8) || (r_type == R_X86_64_PC16)
-		       || (r_type == R_X86_64_PC32))
+	      /* h->dynindx may be -1 if this symbol was marked to
+		 become local.  */
+	      else if (h != NULL
+		       && ((! info->symbolic && h->dynindx != -1)
+			   || (h->elf_link_hash_flags
+			       & ELF_LINK_HASH_DEF_REGULAR) == 0))
 		{
-		  BFD_ASSERT (h != NULL && h->dynindx != -1);
+		  BFD_ASSERT (h->dynindx != -1);
 		  relocate = false;
 		  outrel.r_info = ELF64_R_INFO (h->dynindx, r_type);
 		  outrel.r_addend = relocation + rela->r_addend;
 		}
 	      else
 		{
-		  /* h->dynindx may be -1 if this symbol was marked to
-		     become local.  */
-		  if (h == NULL
-		      || ((info->symbolic || h->dynindx == -1)
-			  && (h->elf_link_hash_flags
-			      & ELF_LINK_HASH_DEF_REGULAR) != 0))
+		  if (r_type == R_X86_64_64)
 		    {
 		      relocate = true;
 		      outrel.r_info = ELF64_R_INFO (0, R_X86_64_RELATIVE);
@@ -1528,9 +1529,35 @@
 		    }
 		  else
 		    {
-		      BFD_ASSERT (h->dynindx != -1);
+		      long indx;
+
+		      if (h == NULL)
+			sec = local_sections[r_symndx];
+		      else
+			{
+			  BFD_ASSERT (h->root.type == bfd_link_hash_defined
+				      || (h->root.type
+					  == bfd_link_hash_defweak));
+			  sec = h->root.u.def.section;
+			}
+		      if (sec != NULL && bfd_is_abs_section (sec))
+			indx = 0;
+		      else if (sec == NULL || sec->owner == NULL)
+			{
+			  bfd_set_error (bfd_error_bad_value);
+			  return false;
+			}
+		      else
+			{
+			  asection *osec;
+
+			  osec = sec->output_section;
+			  indx = elf_section_data (osec)->dynindx;
+			  BFD_ASSERT (indx > 0);
+			}
+
 		      relocate = false;
-		      outrel.r_info = ELF64_R_INFO (h->dynindx, R_X86_64_32);
+		      outrel.r_info = ELF64_R_INFO (indx, r_type);
 		      outrel.r_addend = relocation + rela->r_addend;
 		    }
 		}

-- 
 Andreas Jaeger
  SuSE Labs aj@suse.de
   private aj@arthur.inka.de
    http://www.suse.de/~aj


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