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]

[PATCH] mips64 relocations for the ELF linker


Hi All,

this patch fixes the handling of MIPS ELF64 three-in-one relocations
in elflink.h.


Thiemo


2001-05-24  Thiemo Seufer  <seufer@csv.ica.uni-stuttgart.de>

	src/bfd/ChangeLog
	* elflink.h (elf_link_size_reloc_section): Use bfd_zmalloc instead of
	a zeroing loop.
	(elf_link_output_relocs): Handle MIPS ELF64 relocations correctly.
	(elf_link_input_bfd): Likewise.
	(elf_reloc_link_order): Likewise.
	(elf_finish_pointer_linker_section): Typo. Handle MIPS ELF64
	relocations correctly.


diff -BurPX /bigdisk/dl/src/binutils-exclude src-orig/bfd/elflink.h src/bfd/elflink.h
--- src-orig/bfd/elflink.h	Wed May 23 21:08:55 2001
+++ src/bfd/elflink.h	Wed May 23 22:47:12 2001
@@ -4108,7 +4115,6 @@
      Elf_Internal_Shdr *rel_hdr;
      asection *o;
 {
-  register struct elf_link_hash_entry **p, **pend;
   unsigned reloc_count;
 
   /* Figure out how many relocations there will be.  */
@@ -4132,16 +4138,15 @@
      first time we are called.  */
   if (elf_section_data (o)->rel_hashes == NULL)
     {
+      register struct elf_link_hash_entry **p;
+
       p = ((struct elf_link_hash_entry **)
-	   bfd_malloc (o->reloc_count
-		       * sizeof (struct elf_link_hash_entry *)));
+	   bfd_zmalloc (o->reloc_count
+			* sizeof (struct elf_link_hash_entry *)));
       if (p == NULL && o->reloc_count != 0)
 	return false;
 
       elf_section_data (o)->rel_hashes = p;
-      pend = p + o->reloc_count;
-      for (; p < pend; p++)
-	*p = NULL;
     }
 
   return true;
@@ -4160,8 +4165,26 @@
      struct elf_link_hash_entry **rel_hash;
 {
   unsigned int i;
+  Elf_Internal_Rel *irel;
+  Elf_Internal_Rela *irela;
   struct elf_backend_data *bed = get_elf_backend_data (abfd);
 
+  irel = (Elf_Internal_Rel *) bfd_zmalloc (sizeof (Elf_Internal_Rel)
+					   * bed->s->int_rels_per_ext_rel);
+  if (irel == NULL)
+    {
+      (*_bfd_error_handler) (_("Error: out of memory"));
+      abort();
+    }
+
+  irela = (Elf_Internal_Rela *) bfd_zmalloc (sizeof (Elf_Internal_Rela)
+					     * bed->s->int_rels_per_ext_rel);
+  if (irela == NULL)
+    {
+      (*_bfd_error_handler) (_("Error: out of memory"));
+      abort();
+    }
+
   for (i = 0; i < count; i++, rel_hash++)
     {
       if (*rel_hash == NULL)
@@ -4172,41 +4195,50 @@
       if (rel_hdr->sh_entsize == sizeof (Elf_External_Rel))
 	{
 	  Elf_External_Rel *erel;
-	  Elf_Internal_Rel irel;
-
+	  unsigned int j;
+	  
 	  erel = (Elf_External_Rel *) rel_hdr->contents + i;
 	  if (bed->s->swap_reloc_in)
-	    (*bed->s->swap_reloc_in) (abfd, (bfd_byte *) erel, &irel);
+	    (*bed->s->swap_reloc_in) (abfd, (bfd_byte *) erel, irel);
 	  else
-	    elf_swap_reloc_in (abfd, erel, &irel);
-	  irel.r_info = ELF_R_INFO ((*rel_hash)->indx,
-				    ELF_R_TYPE (irel.r_info));
+	    elf_swap_reloc_in (abfd, erel, irel);
+	  for (j = 0; j < bed->s->int_rels_per_ext_rel; j++)
+	    {
+	      irel[j].r_info = ELF_R_INFO ((*rel_hash)->indx,
+					   ELF_R_TYPE (irel[j].r_info));
+	    }
 	  if (bed->s->swap_reloc_out)
-	    (*bed->s->swap_reloc_out) (abfd, &irel, (bfd_byte *) erel);
+	    (*bed->s->swap_reloc_out) (abfd, irel, (bfd_byte *) erel);
 	  else
-	    elf_swap_reloc_out (abfd, &irel, erel);
+	    elf_swap_reloc_out (abfd, irel, erel);
 	}
       else
 	{
 	  Elf_External_Rela *erela;
-	  Elf_Internal_Rela irela;
+	  unsigned int j;
 
 	  BFD_ASSERT (rel_hdr->sh_entsize
 		      == sizeof (Elf_External_Rela));
 
 	  erela = (Elf_External_Rela *) rel_hdr->contents + i;
 	  if (bed->s->swap_reloca_in)
-	    (*bed->s->swap_reloca_in) (abfd, (bfd_byte *) erela, &irela);
+	    (*bed->s->swap_reloca_in) (abfd, (bfd_byte *) erela, irela);
 	  else
-	    elf_swap_reloca_in (abfd, erela, &irela);
-	  irela.r_info = ELF_R_INFO ((*rel_hash)->indx,
-				     ELF_R_TYPE (irela.r_info));
+	    elf_swap_reloca_in (abfd, erela, irela);
+	  for (j = 0; j < bed->s->int_rels_per_ext_rel; j++)
+	    {
+	      irela[j].r_info = ELF_R_INFO ((*rel_hash)->indx,
+					    ELF_R_TYPE (irela[j].r_info));
+	    }
 	  if (bed->s->swap_reloca_out)
-	    (*bed->s->swap_reloca_out) (abfd, &irela, (bfd_byte *) erela);
+	    (*bed->s->swap_reloca_out) (abfd, irela, (bfd_byte *) erela);
 	  else
-	    elf_swap_reloca_out (abfd, &irela, erela);
+	    elf_swap_reloca_out (abfd, irela, erela);
 	}
     }
+
+    free (irel);
+    free (irela);
 }
 
 /* Do the final step of an ELF link.  */
@@ -5440,33 +5472,49 @@
 
   bed = get_elf_backend_data (output_bfd);
   irela = internal_relocs;
-  irelaend = irela + NUM_SHDR_ENTRIES (input_rel_hdr);
+  irelaend = irela + NUM_SHDR_ENTRIES (input_rel_hdr)
+		     * bed->s->int_rels_per_ext_rel;
   if (input_rel_hdr->sh_entsize == sizeof (Elf_External_Rel))
     {
       Elf_External_Rel *erel;
+      Elf_Internal_Rel *irel;
+      
+      irel = (Elf_Internal_Rel *) bfd_zmalloc (bed->s->int_rels_per_ext_rel
+					       * sizeof (Elf_Internal_Rel));
+      if (irel == NULL)
+	{
+	  (*_bfd_error_handler) (_("Error: out of memory"));
+	  abort();
+	}
 
       erel = ((Elf_External_Rel *) output_rel_hdr->contents + *rel_countp);
-      for (; irela < irelaend; irela++, erel++)
+      for (; irela < irelaend; irela += bed->s->int_rels_per_ext_rel, erel++)
 	{
-	  Elf_Internal_Rel irel;
-
-	  irel.r_offset = irela->r_offset;
-	  irel.r_info = irela->r_info;
-	  BFD_ASSERT (irela->r_addend == 0);
+	  unsigned char i;
+	  
+	  for (i = 0; i < bed->s->int_rels_per_ext_rel; i++)
+	    {
+	      irel[i].r_offset = irela[i].r_offset;
+	      irel[i].r_info = irela[i].r_info;
+	      BFD_ASSERT (irela[i].r_addend == 0);
+	    }
+	  
 	  if (bed->s->swap_reloc_out)
-	    (*bed->s->swap_reloc_out) (output_bfd, &irel, (PTR) erel);
+	    (*bed->s->swap_reloc_out) (output_bfd, irel, (PTR) erel);
 	  else
-	    elf_swap_reloc_out (output_bfd, &irel, erel);
+	    elf_swap_reloc_out (output_bfd, irel, erel);
 	}
+      
+      free (irel);
     }
   else
     {
       Elf_External_Rela *erela;
 
-      BFD_ASSERT (input_rel_hdr->sh_entsize
-		  == sizeof (Elf_External_Rela));
+      BFD_ASSERT (input_rel_hdr->sh_entsize == sizeof (Elf_External_Rela));
+
       erela = ((Elf_External_Rela *) output_rel_hdr->contents + *rel_countp);
-      for (; irela < irelaend; irela++, erela++)
+      for (; irela < irelaend; irela += bed->s->int_rels_per_ext_rel, erela++)
 	if (bed->s->swap_reloca_out)
 	  (*bed->s->swap_reloca_out) (output_bfd, irela, (PTR) erela);
 	else
@@ -5798,21 +5846,28 @@
 	      Elf_Internal_Rela *irelaend;
 	      struct elf_link_hash_entry **rel_hash;
 	      Elf_Internal_Shdr *input_rel_hdr;
+	      unsigned char next_erel;
 
 	      /* Adjust the reloc addresses and symbol indices.  */
 
 	      irela = internal_relocs;
-	      irelaend =
-		irela + o->reloc_count * bed->s->int_rels_per_ext_rel;
+	      irelaend = irela
+		         + o->reloc_count * bed->s->int_rels_per_ext_rel;
 	      rel_hash = (elf_section_data (o->output_section)->rel_hashes
 			  + elf_section_data (o->output_section)->rel_count
 			  + elf_section_data (o->output_section)->rel_count2);
-	      for (; irela < irelaend; irela++, rel_hash++)
+	      for (next_erel = 0; irela < irelaend; irela++, next_erel++)
 		{
 		  unsigned long r_symndx;
 		  Elf_Internal_Sym *isym;
 		  asection *sec;
 
+		  if (next_erel == bed->s->int_rels_per_ext_rel)
+		    {
+		      rel_hash++;
+		      next_erel = 0;
+		    }
+
 		  irela->r_offset += o->output_offset;
 
 		  /* Relocs in an executable have to be virtual addresses.  */
@@ -5829,7 +5884,7 @@
 			  && finfo->sections[r_symndx] == NULL))
 		    {
 		      struct elf_link_hash_entry *rh;
-		      long indx;
+		      unsigned long indx;
 
 		      /* This is a reloc against a global symbol.  We
 			 have not yet output all the local symbols, so
@@ -5937,7 +5992,8 @@
 	      elf_link_output_relocs (output_bfd, o,
 				      input_rel_hdr,
 				      internal_relocs);
-	      internal_relocs += NUM_SHDR_ENTRIES (input_rel_hdr);
+	      internal_relocs += NUM_SHDR_ENTRIES (input_rel_hdr)
+				 * bed->s->int_rels_per_ext_rel;
 	      input_rel_hdr = elf_section_data (o)->rel_hdr2;
 	      if (input_rel_hdr)
 		elf_link_output_relocs (output_bfd, o,
@@ -6110,32 +6166,56 @@
 
   if (rel_hdr->sh_type == SHT_REL)
     {
-      Elf_Internal_Rel irel;
+      Elf_Internal_Rel *irel;
       Elf_External_Rel *erel;
-
-      irel.r_offset = offset;
-      irel.r_info = ELF_R_INFO (indx, howto->type);
+      unsigned char i;
+      
+      irel = (Elf_Internal_Rel *) bfd_zmalloc (bed->s->int_rels_per_ext_rel
+					       * sizeof (Elf_Internal_Rel));
+      if (irel == NULL)
+	{
+	  (*_bfd_error_handler) (_("Error: out of memory"));
+	  abort();
+	}
+      
+      for (i = 0; i < bed->s->int_rels_per_ext_rel; i++)
+	irel[i].r_offset = offset;
+      irel[0].r_info = ELF_R_INFO (indx, howto->type);
       erel = ((Elf_External_Rel *) rel_hdr->contents
 	      + elf_section_data (output_section)->rel_count);
       if (bed->s->swap_reloc_out)
-	(*bed->s->swap_reloc_out) (output_bfd, &irel, (bfd_byte *) erel);
+	(*bed->s->swap_reloc_out) (output_bfd, irel, (bfd_byte *) erel);
       else
-	elf_swap_reloc_out (output_bfd, &irel, erel);
+	elf_swap_reloc_out (output_bfd, irel, erel);
+
+      free (irel);
     }
   else
     {
-      Elf_Internal_Rela irela;
+      Elf_Internal_Rela *irela;
       Elf_External_Rela *erela;
+      unsigned char i;
+      
+      irela = (Elf_Internal_Rela *) bfd_zmalloc (bed->s->int_rels_per_ext_rel
+						 * sizeof (Elf_Internal_Rela));
+      if (irela == NULL)
+	{
+	  (*_bfd_error_handler) (_("Error: out of memory"));
+	  abort();
+	}
 
-      irela.r_offset = offset;
-      irela.r_info = ELF_R_INFO (indx, howto->type);
-      irela.r_addend = addend;
+      for (i = 0; i < bed->s->int_rels_per_ext_rel; i++)
+	irela[i].r_offset = offset;
+      irela[0].r_info = ELF_R_INFO (indx, howto->type);
+      irela[0].r_addend = addend;
       erela = ((Elf_External_Rela *) rel_hdr->contents
 	       + elf_section_data (output_section)->rel_count);
       if (bed->s->swap_reloca_out)
-	(*bed->s->swap_reloca_out) (output_bfd, &irela, (bfd_byte *) erela);
+	(*bed->s->swap_reloca_out) (output_bfd, irela, (bfd_byte *) erela);
       else
-	elf_swap_reloca_out (output_bfd, &irela, erela);
+	elf_swap_reloca_out (output_bfd, irela, erela);
+      
+      free (irela);
     }
 
   ++elf_section_data (output_section)->rel_count;
@@ -6272,7 +6352,7 @@
 #define bfd_put_ptr(BFD,VAL,ADDR) bfd_put_32 (BFD, VAL, ADDR)
 #endif
 
-/* Fill in the address for a pointer generated in alinker section.  */
+/* Fill in the address for a pointer generated in a linker section.  */
 
 bfd_vma
 elf_finish_pointer_linker_section (output_bfd, input_bfd, info, lsect, h, relocation, rel, relative_reloc)
@@ -6339,8 +6419,18 @@
 	  if (info->shared)
 	    {
 	      asection *srel = lsect->rel_section;
-	      Elf_Internal_Rela outrel;
-
+	      Elf_Internal_Rela *outrel;
+	      struct elf_backend_data *bed = get_elf_backend_data (output_bfd);
+	      unsigned char i;
+
+	      outrel = (Elf_Internal_Rela *) bfd_zmalloc (sizeof (Elf_Internal_Rela)
+							  * bed->s->int_rels_per_ext_rel);
+	      if (outrel == NULL)
+		{
+		  (*_bfd_error_handler) (_("Error: out of memory"));
+		  abort();
+		}
+	      
 	      /* We need to generate a relative reloc for the dynamic linker.  */
 	      if (!srel)
 		lsect->rel_section = srel = bfd_get_section_by_name (elf_hash_table (info)->dynobj,
@@ -6348,16 +6438,19 @@
 
 	      BFD_ASSERT (srel != NULL);
 
-	      outrel.r_offset = (lsect->section->output_section->vma
-				 + lsect->section->output_offset
-				 + linker_section_ptr->offset);
-	      outrel.r_info = ELF_R_INFO (0, relative_reloc);
-	      outrel.r_addend = 0;
-	      elf_swap_reloca_out (output_bfd, &outrel,
+	      for (i = 0; i < bed->s->int_rels_per_ext_rel; i++)
+		outrel[i].r_offset = (lsect->section->output_section->vma
+				      + lsect->section->output_offset
+				      + linker_section_ptr->offset);
+	      outrel[0].r_info = ELF_R_INFO (0, relative_reloc);
+	      outrel[0].r_addend = 0;
+	      elf_swap_reloca_out (output_bfd, outrel,
 				   (((Elf_External_Rela *)
 				     lsect->section->contents)
 				    + elf_section_data (lsect->section)->rel_count));
 	      ++elf_section_data (lsect->section)->rel_count;
+	      
+	      free (outrel);
 	    }
 	}
     }


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