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]

Misc patches to x86-64 relocations


This patch fixes a couple of problems with x86-64 relocations:

- .rela.got section is now aligned at 2**3
- R_X86_64_GOTPCREL gets a slot in the GOT
- r_addend in R_X86_64_(8|16|32|PC8|PC16|PC32) was wrong

Bo.

Index: ChangeLog
===================================================================
RCS file: /cvs/src/src/bfd/ChangeLog,v
retrieving revision 1.765
diff -u -r1.765 ChangeLog
--- ChangeLog	2001/02/09 06:58:59	1.765
+++ ChangeLog	2001/02/09 09:39:16
@@ -1,3 +1,13 @@
+2001-02-09  Bo Thorsen  <bo@suse.de>
+
+	* elf64-x86-64.c (elf64_x86_64_check_relocs): Set .rela.got section
+	alignment to 3.
+	(elf64_x86_64_check_relocs): Write R_X86_64_GOTPCREL GOT entry
+	and relocation.
+	(elf64_x86_64_relocate_section): Fix formatting.
+	(elf64_x86_64_relocate_section): Fix addend for relocation of
+	R_X86_64_(8|16|32|PC8|PC16|PC32).
+
 2001-02-08  H.J. Lu  <hjl@gnu.org>
 
 	* elf32-i386.c (elf_i386_check_relocs): Reserve R_386_PC32
Index: elf64-x86-64.c
===================================================================
RCS file: /cvs/src/src/bfd/elf64-x86-64.c,v
retrieving revision 1.4
diff -u -r1.4 elf64-x86-64.c
--- elf64-x86-64.c	2001/01/23 20:27:53	1.4
+++ elf64-x86-64.c	2001/02/09 09:39:16
@@ -349,6 +349,7 @@
 
       switch (ELF64_R_TYPE (rel->r_info))
 	{
+	case R_X86_64_GOTPCREL:
 	case R_X86_64_GOT32:
 	  /* This symbol requires a global offset table entry.  */
 
@@ -372,7 +373,7 @@
 						   | SEC_IN_MEMORY
 						   | SEC_LINKER_CREATED
 						   | SEC_READONLY))
-		      || ! bfd_set_section_alignment (dynobj, srelgot, 2))
+		      || ! bfd_set_section_alignment (dynobj, srelgot, 3))
 		    return false;
 		}
 	    }
@@ -1265,7 +1266,7 @@
 		{
 		  bfd_put_64 (output_bfd, relocation, sgot->contents + off);
 
-      if (info->shared)
+		  if (info->shared)
 		    {
 		      asection *srelgot;
 		      Elf_Internal_Rela outrel;
@@ -1298,14 +1299,84 @@
 	case R_X86_64_GOTPCREL:
 	  /* Use global offset table as symbol value.  */
 
-	  if (sgot == NULL)
+	  BFD_ASSERT (sgot != NULL);
+	  if (h != NULL)
 	    {
-	      sgot = bfd_get_section_by_name (dynobj, ".got");
-	      BFD_ASSERT (sgot != NULL);
+	      bfd_vma off = h->got.offset;
+	      BFD_ASSERT (off != (bfd_vma) -1);
+
+	      if (! elf_hash_table (info)->dynamic_sections_created
+		  || (info->shared
+		      && (info->symbolic || h->dynindx == -1)
+		      && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)))
+		{
+		  /* This is actually a static link, or it is a -Bsymbolic
+		     link and the symbol is defined locally, or the symbol
+		     was forced to be local because of a version file.  We
+		     must initialize this entry in the global offset table.
+		     Since the offset must always be a multiple of 8, we
+		     use the least significant bit to record whether we
+		     have initialized it already.
+
+		     When doing a dynamic link, we create a .rela.got
+		     relocation entry to initialize the value.  This is
+		     done in the finish_dynamic_symbol routine.  */
+		  if ((off & 1) != 0)
+		    off &= ~1;
+		  else
+		    {
+		      bfd_put_64 (output_bfd, relocation,
+				  sgot->contents + off);
+		      h->got.offset |= 1;
+		    }
+		}
+	      relocation = sgot->output_offset + off;
 	    }
+	  else
+	    {
+	      bfd_vma off;
 
-	  relocation = sgot->output_section->vma + (h->got.offset & ~1);
+	      BFD_ASSERT (local_got_offsets != NULL
+			  && local_got_offsets[r_symndx] != (bfd_vma) -1);
+
+	      off = local_got_offsets[r_symndx];
+
+	      /* The offset must always be a multiple of 8.  We use
+                 the least significant bit to record whether we have
+                 already generated the necessary reloc.  */
+	      if ((off & 1) != 0)
+		off &= ~1;
+	      else
+		{
+		  bfd_put_64 (output_bfd, relocation, sgot->contents + off);
+
+		  if (info->shared)
+		    {
+		      asection *srelgot;
+		      Elf_Internal_Rela outrel;
 
+		      /* We need to generate a R_X86_64_RELATIVE reloc
+			 for the dynamic linker.  */
+		      srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
+		      BFD_ASSERT (srelgot != NULL);
+
+		      outrel.r_offset = (sgot->output_section->vma
+					 + sgot->output_offset
+					 + off);
+		      outrel.r_info = ELF64_R_INFO (0, R_X86_64_RELATIVE);
+		      outrel.r_addend = relocation;
+		      bfd_elf64_swap_reloca_out (output_bfd, &outrel,
+						 (((Elf64_External_Rela *)
+						   srelgot->contents)
+						  + srelgot->reloc_count));
+		      ++srelgot->reloc_count;
+		    }
+
+		  local_got_offsets[r_symndx] |= 1;
+		}
+
+	      relocation = sgot->output_section->vma + off;
+	    }
 	  break;
 
 	case R_X86_64_PLT32:
@@ -1407,7 +1478,7 @@
 		  BFD_ASSERT (h != NULL && h->dynindx != -1);
 		  relocate = false;
 		  outrel.r_info = ELF64_R_INFO (h->dynindx, r_type);
-		  outrel.r_addend = relocation + rela->r_addend;
+		  outrel.r_addend = rela->r_addend;
 		}
 	      else
 		{
@@ -1420,14 +1491,14 @@
 		    {
 		      relocate = true;
 		      outrel.r_info = ELF64_R_INFO (0, R_X86_64_RELATIVE);
-		      outrel.r_addend = relocation + rela->r_addend;
+		      outrel.r_addend = rela->r_addend;
 		    }
 		  else
 		    {
 		      BFD_ASSERT (h->dynindx != -1);
 		      relocate = false;
 		      outrel.r_info = ELF64_R_INFO (h->dynindx, R_X86_64_32);
-		      outrel.r_addend = relocation + rela->r_addend;
+		      outrel.r_addend = rela->r_addend;
 		    }
 		}
 


-- 

     Bo Thorsen                 |   Lahnsgade 31, st.
     Free software developer    |   5000 Odense C
     SuSE Labs                  |   Denmark


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