This is the mail archive of the binutils@sourceware.cygnus.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]

elf32-mips.c patch



This patch is the result of an audit of the changes in the rel.dyn
generation from the pre-N32 code to the present, as well as
conversation with Ian.  Checked in after verification on IRIX6.

-- Mark

Tue Aug 10 00:21:08 1999  Mark P. Mitchell  <mark@codesourcery.com>

	* elf32-mips.c (mips_elf_create_dynamic_relocation): Change
	prototype.  Handle local symbols.  Add commentary.
	(mips_elf_calculate_relocation): Adjust accordingly.
	(_bfd_mips_elf_check_relocs): Handle local symbols in R_MIPS_32
	relocations. 

Index: elf32-mips.c
===================================================================
RCS file: /cvs/binutils/binutils/bfd/elf32-mips.c,v
retrieving revision 1.46
diff -c -p -r1.46 elf32-mips.c
*** elf32-mips.c	1999/08/09 22:45:38	1.46
--- elf32-mips.c	1999/08/10 06:23:15
*************** static bfd_vma mips_elf_create_local_got
*** 192,200 ****
    PARAMS ((bfd *, struct mips_got_info *, asection *, bfd_vma));
  static bfd_vma mips_elf_got16_entry 
    PARAMS ((bfd *, struct bfd_link_info *, bfd_vma));
! static unsigned int mips_elf_create_dynamic_relocation 
    PARAMS ((bfd *, struct bfd_link_info *, const Elf_Internal_Rela *,
! 	   long, bfd_vma, asection *));
  static void mips_elf_allocate_dynamic_relocations 
    PARAMS ((bfd *, unsigned int));
  static boolean mips_elf_stub_section_p 
--- 192,201 ----
    PARAMS ((bfd *, struct mips_got_info *, asection *, bfd_vma));
  static bfd_vma mips_elf_got16_entry 
    PARAMS ((bfd *, struct bfd_link_info *, bfd_vma));
! static boolean mips_elf_create_dynamic_relocation 
    PARAMS ((bfd *, struct bfd_link_info *, const Elf_Internal_Rela *,
! 	   struct mips_elf_link_hash_entry *, asection *,
! 	   bfd_vma, bfd_vma *, asection *));
  static void mips_elf_allocate_dynamic_relocations 
    PARAMS ((bfd *, unsigned int));
  static boolean mips_elf_stub_section_p 
*************** mips_elf_got16_entry (abfd, info, value)
*** 5541,5547 ****
       want, it is really the %high value.  The complete value is
       calculated with a `addiu' of a LO16 relocation, just as with a
       HI16/LO16 pair.  */
!   value = mips_elf_high (value);
    g = mips_elf_got_info (elf_hash_table (info)->dynobj, &sgot);
  
    /* Look to see if we already have an appropriate entry.  */
--- 5542,5548 ----
       want, it is really the %high value.  The complete value is
       calculated with a `addiu' of a LO16 relocation, just as with a
       HI16/LO16 pair.  */
!   value = mips_elf_high (value) << 16;
    g = mips_elf_got_info (elf_hash_table (info)->dynobj, &sgot);
  
    /* Look to see if we already have an appropriate entry.  */
*************** mips_elf_next_lo16_relocation (relocatio
*** 5594,5612 ****
    return NULL;
  }
  
! /* Create a rel.dyn relocation for the dynamic linker to resolve.  The
!    relocatin is against the symbol with the dynamic symbol table index
!    DYNINDX.  REL is the original relocation, which is now being made
!    dynamic.  */
! 
! static unsigned int
! mips_elf_create_dynamic_relocation (output_bfd, info, rel, dynindx,
! 				    addend, input_section)
       bfd *output_bfd;
       struct bfd_link_info *info;
       const Elf_Internal_Rela *rel;
!      long dynindx;
!      bfd_vma addend;
       asection *input_section;
  {
    Elf_Internal_Rel outrel;
--- 5595,5615 ----
    return NULL;
  }
  
! /* Create a rel.dyn relocation for the dynamic linker to resolve.  REL
!    is the original relocation, which is now being transformed into a
!    dyanmic relocation.  The ADDENDP is adjusted if necessary; the
!    caller should store the result in place of the original addend.  */
! 
! static boolean
! mips_elf_create_dynamic_relocation (output_bfd, info, rel, h, sec,
! 				    symbol, addendp, input_section)
       bfd *output_bfd;
       struct bfd_link_info *info;
       const Elf_Internal_Rela *rel;
!      struct mips_elf_link_hash_entry *h;
!      asection *sec;
!      bfd_vma symbol;
!      bfd_vma *addendp;
       asection *input_section;
  {
    Elf_Internal_Rel outrel;
*************** mips_elf_create_dynamic_relocation (outp
*** 5624,5659 ****
  
    skip = false;
  
!   /* The symbol for the relocation is the same as it was for the
!      original relocation.  */
!   outrel.r_info = ELF32_R_INFO (dynindx, R_MIPS_REL32);
! 
!   /* The offset for the dynamic relocation is the same as for the
!      original relocation, adjusted by the offset at which the original
!      section is output.  */
    if (elf_section_data (input_section)->stab_info == NULL)
      outrel.r_offset = rel->r_offset;
    else
      {
!       bfd_vma off;
! 
!       off = (_bfd_stab_section_offset
! 	     (output_bfd, &elf_hash_table (info)->stab_info,
! 	      input_section,
! 	      &elf_section_data (input_section)->stab_info,
! 	      rel->r_offset));
!       if (off == (bfd_vma) -1)
  	skip = true;
-       outrel.r_offset = off;
      }
-   outrel.r_offset += (input_section->output_section->vma
- 		      + input_section->output_offset);
  
    /* If we've decided to skip this relocation, just output an emtpy
!      record.  */
    if (skip)
      memset (&outrel, 0, sizeof (outrel));
  
    if (ABI_64_P (output_bfd))
      {
        (*get_elf_backend_data (output_bfd)->s->swap_reloc_out)
--- 5627,5720 ----
  
    skip = false;
  
!   /* We begin by assuming that the offset for the dynamic relocation
!      is the same as for the original relocation.  We'll adjust this
!      later to reflect the correct output offsets.  */
    if (elf_section_data (input_section)->stab_info == NULL)
      outrel.r_offset = rel->r_offset;
    else
      {
!       /* Except that in a stab section things are more complex.
! 	 Because we compress stab information, the offset given in the
! 	 relocation may not be the one we want; we must let the stabs
! 	 machinery tell us the offset.  */
!       outrel.r_offset 
! 	= (_bfd_stab_section_offset
! 	   (output_bfd, &elf_hash_table (info)->stab_info,
! 	    input_section,
! 	    &elf_section_data (input_section)->stab_info,
! 	    rel->r_offset));
!       /* If we didn't need the relocation at all, this value will be
! 	 -1.  */
!       if (outrel.r_offset == (bfd_vma) -1)
  	skip = true;
      }
  
    /* If we've decided to skip this relocation, just output an emtpy
!      record.  Note that R_MIPS_NONE == 0, so that this call to memset
!      is a way of setting R_TYPE to R_MIPS_NONE.  */
    if (skip)
      memset (&outrel, 0, sizeof (outrel));
+   else
+     {
+       long indx;
+       bfd_vma section_offset;
+ 
+       /* We must now calculate the dynamic symbol table index to use
+ 	 in the relocation.  */
+       if (h != NULL
+ 	  && (! info->symbolic || (h->root.elf_link_hash_flags
+ 				   & ELF_LINK_HASH_DEF_REGULAR) == 0))
+ 	{
+ 	  indx = h->root.dynindx;
+ 	  BFD_ASSERT (indx != -1);
+ 	}
+       else
+ 	{
+ 	  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
+ 	    {
+ 	      indx = elf_section_data (sec->output_section)->dynindx;
+ 	      if (indx == 0)
+ 		abort ();
+ 	    }
  
+ 	  /* Figure out how far the target of the relocation is from
+ 	     the beginning of its section.  */
+ 	  section_offset = symbol - sec->output_section->vma;
+ 	  /* The relocation we're building is section-relative.
+ 	     Therefore, the original addend must be adjusted by the
+ 	     section offset.  */
+ 	  *addendp += symbol - sec->output_section->vma;
+ 	  /* Now, the relocation is just against the section.  */
+ 	  symbol = sec->output_section->vma;
+ 	}
+       
+       /* If the relocation was previously an absolute relocation, we
+ 	 must adjust it by the value we give it in the dynamic symbol
+ 	 table.  */
+       if (r_type != R_MIPS_REL32)
+ 	*addendp += symbol;
+ 
+       /* The relocation is always an REL32 relocation because we don't
+ 	 know where the shared library will wind up at load-time.  */
+       outrel.r_info = ELF32_R_INFO (indx, R_MIPS_REL32);
+ 
+       /* Adjust the output offset of the relocation to reference the
+ 	 correct location in the output file.  */
+       outrel.r_offset += (input_section->output_section->vma
+ 			  + input_section->output_offset);
+     }
+ 
+   /* Put the relocation back out.  We have to use the special
+      relocation outputter in the 64-bit case since the 64-bit
+      relocation format is non-standard.  */
    if (ABI_64_P (output_bfd))
      {
        (*get_elf_backend_data (output_bfd)->s->swap_reloc_out)
*************** mips_elf_create_dynamic_relocation (outp
*** 5666,5671 ****
--- 5727,5741 ----
  			      (((Elf32_External_Rel *)
  				sreloc->contents)
  			       + sreloc->reloc_count));
+ 
+   /* Record the index of the first relocation referencing H.  This
+      information is later emitted in the .msym section.  */
+   if (h != NULL
+       && (h->min_dyn_reloc_index == 0 
+ 	  || sreloc->reloc_count < h->min_dyn_reloc_index))
+     h->min_dyn_reloc_index = sreloc->reloc_count;
+ 
+   /* We've now added another relocation.  */
    ++sreloc->reloc_count;
  
    /* Make sure the output section is writable.  The dynamic linker
*************** mips_elf_create_dynamic_relocation (outp
*** 5692,5698 ****
  	  else
  	    mips_elf_set_cr_type (cptrel, CRT_MIPS_WORD);
  	  mips_elf_set_cr_dist2to (cptrel, 0);
! 	  cptrel.konst = addend;
  
  	  cr = (scpt->contents
  		+ sizeof (Elf32_External_compact_rel));
--- 5762,5768 ----
  	  else
  	    mips_elf_set_cr_type (cptrel, CRT_MIPS_WORD);
  	  mips_elf_set_cr_dist2to (cptrel, 0);
! 	  cptrel.konst = *addendp;
  
  	  cr = (scpt->contents
  		+ sizeof (Elf32_External_compact_rel));
*************** mips_elf_create_dynamic_relocation (outp
*** 5703,5709 ****
  	}
      }
  
!   return sreloc->reloc_count - 1;
  }
  
  /* Calculate the value produced by the RELOCATION (which comes from
--- 5773,5779 ----
  	}
      }
  
!   return true;
  }
  
  /* Calculate the value produced by the RELOCATION (which comes from
*************** mips_elf_calculate_relocation (abfd, 
*** 6024,6050 ****
      case R_MIPS_32:
      case R_MIPS_REL32:
      case R_MIPS_64:
!       /* If we're creating a shared library, or this relocation is
! 	 against a symbol in a shared library, then we can't know
! 	 where the symbol will end up.  So, we create a relocation
! 	 record in the output, and leave the job up to the dynamic
! 	 linker.  */
!       if (info->shared || !sec->output_section)
! 	{
! 	  unsigned int reloc_index;
! 
! 	  BFD_ASSERT (h != NULL);
! 	  reloc_index 
! 	    = mips_elf_create_dynamic_relocation (abfd, 
! 						  info, 
! 						  relocation,
! 						  h->root.dynindx,
! 						  addend,
! 						  input_section);
! 	  if (h->min_dyn_reloc_index == 0
! 	      || reloc_index < h->min_dyn_reloc_index)
! 	    h->min_dyn_reloc_index = reloc_index;
! 	  value = symbol + addend;
  	}
        else
  	{
--- 6094,6121 ----
      case R_MIPS_32:
      case R_MIPS_REL32:
      case R_MIPS_64:
!       if ((info->shared
! 	   || (elf_hash_table (info)->dynamic_sections_created
! 	       && h != NULL
! 	       && ((h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)
! 		   == 0)))
! 	  && (input_section->flags & SEC_ALLOC) != 0)
! 	{
! 	  /* If we're creating a shared library, or this relocation is
! 	     against a symbol in a shared library, then we can't know
! 	     where the symbol will end up.  So, we create a relocation
! 	     record in the output, and leave the job up to the dynamic
! 	     linker.  */
! 	  value = addend;
! 	  if (!mips_elf_create_dynamic_relocation (abfd, 
! 						   info, 
! 						   relocation,
! 						   h,
! 						   sec,
! 						   symbol,
! 						   &value,
! 						   input_section))
! 	    return false;
  	}
        else
  	{
*************** _bfd_mips_elf_check_relocs (abfd, info, 
*** 7488,7494 ****
  		 this symbol, a symbol must have a dynamic symbol
  		 table index greater that DT_GOTSYM if there are
  		 dynamic relocations against it.  */
! 	      if (!mips_elf_record_global_got_symbol (h, info, g))
  		return false;
  	    }
  
--- 7559,7566 ----
  		 this symbol, a symbol must have a dynamic symbol
  		 table index greater that DT_GOTSYM if there are
  		 dynamic relocations against it.  */
! 	      if (h != NULL
! 		  && !mips_elf_record_global_got_symbol (h, info, g))
  		return false;
  	    }
  


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