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]

resize alpha .plt, .rela.plt, .rela.got sections


Relaxation was leaving all sorts of garbage in the .plt
sections, and the .rela.got section had relocations for
entries that had been removed.


r~


        * elf64-alpha.c (elf64_alpha_relax_with_lituse): Reject undefined
        symbols from JSR relaxation. 
        (elf64_alpha_size_plt_section_1): New.
        (elf64_alpha_calc_dynrel_sizes): Split out .rela.got bits ...
        (elf64_alpha_size_rela_got_1): ... here.
        (elf64_alpha_size_dynamic_sections): Split out .rela.got bits ...
        (elf64_alpha_size_rela_got_section): ... here. 
        (elf64_alpha_size_plt_section): New.
        (elf64_alpha_relax_section): Call them.
        (elf64_alpha_size_got_sections): Remove output_bfd arg.
        (elf64_alpha_finish_dynamic_symbol): Check gotent use_count.

Index: elf64-alpha.c
===================================================================
RCS file: /cvs/src/src/bfd/elf64-alpha.c,v
retrieving revision 1.67
diff -c -p -d -r1.67 elf64-alpha.c
*** elf64-alpha.c	2 Jun 2002 02:28:44 -0000	1.67
--- elf64-alpha.c	2 Jun 2002 03:52:35 -0000
*************** static boolean elf64_alpha_calc_got_offs
*** 106,118 ****
    PARAMS ((struct alpha_elf_link_hash_entry *, PTR));
  static void elf64_alpha_calc_got_offsets PARAMS ((struct bfd_link_info *));
  static boolean elf64_alpha_size_got_sections
!   PARAMS ((bfd *, struct bfd_link_info *));
  static boolean elf64_alpha_always_size_sections
    PARAMS ((bfd *, struct bfd_link_info *));
  static int alpha_dynamic_entries_for_reloc
    PARAMS ((int, int, int));
  static boolean elf64_alpha_calc_dynrel_sizes
    PARAMS ((struct alpha_elf_link_hash_entry *, struct bfd_link_info *));
  static boolean elf64_alpha_add_symbol_hook
    PARAMS ((bfd *, struct bfd_link_info *, const Elf_Internal_Sym *,
  	   const char **, flagword *, asection **, bfd_vma *));
--- 106,126 ----
    PARAMS ((struct alpha_elf_link_hash_entry *, PTR));
  static void elf64_alpha_calc_got_offsets PARAMS ((struct bfd_link_info *));
  static boolean elf64_alpha_size_got_sections
!   PARAMS ((struct bfd_link_info *));
! static boolean elf64_alpha_size_plt_section
!   PARAMS ((struct bfd_link_info *));
! static boolean elf64_alpha_size_plt_section_1
!   PARAMS ((struct alpha_elf_link_hash_entry *, PTR));
  static boolean elf64_alpha_always_size_sections
    PARAMS ((bfd *, struct bfd_link_info *));
  static int alpha_dynamic_entries_for_reloc
    PARAMS ((int, int, int));
  static boolean elf64_alpha_calc_dynrel_sizes
    PARAMS ((struct alpha_elf_link_hash_entry *, struct bfd_link_info *));
+ static boolean elf64_alpha_size_rela_got_section
+   PARAMS ((struct bfd_link_info *));
+ static boolean elf64_alpha_size_rela_got_1
+   PARAMS ((struct alpha_elf_link_hash_entry *, struct bfd_link_info *));
  static boolean elf64_alpha_add_symbol_hook
    PARAMS ((bfd *, struct bfd_link_info *, const Elf_Internal_Sym *,
  	   const char **, flagword *, asection **, bfd_vma *));
*************** elf64_alpha_relax_with_lituse (info, sym
*** 1388,1401 ****
  	case LITUSE_ALPHA_TLSGD:
  	case LITUSE_ALPHA_TLSLDM:
  	  {
! 	    /* If not zero, place to jump without needing pv.  */
! 	    bfd_vma optdest = elf64_alpha_relax_opt_call (info, symval);
! 	    bfd_vma org = (info->sec->output_section->vma
! 			   + info->sec->output_offset
! 			   + urel->r_offset + 4);
  	    bfd_signed_vma odisp;
  
  	    odisp = (optdest ? optdest : symval) - org;
  	    if (odisp >= -0x400000 && odisp < 0x400000)
  	      {
  		Elf_Internal_Rela *xrel;
--- 1396,1420 ----
  	case LITUSE_ALPHA_TLSGD:
  	case LITUSE_ALPHA_TLSLDM:
  	  {
! 	    bfd_vma optdest, org;
  	    bfd_signed_vma odisp;
  
+ 	    /* If this symbol is undefined, we can't relax it to a branch.  */
+ 	    if (info->h
+ 		&& (info->h->root.root.type == bfd_link_hash_undefweak
+ 		    || info->h->root.root.type == bfd_link_hash_undefined))
+ 	      {
+ 		all_optimized = false;
+ 		break;
+ 	      }
+ 
+ 	    /* If not zero, place to jump without needing pv.  */
+ 	    optdest = elf64_alpha_relax_opt_call (info, symval);
+ 	    org = (info->sec->output_section->vma
+ 		   + info->sec->output_offset
+ 		   + urel->r_offset + 4);
  	    odisp = (optdest ? optdest : symval) - org;
+ 
  	    if (odisp >= -0x400000 && odisp < 0x400000)
  	      {
  		Elf_Internal_Rela *xrel;
*************** elf64_alpha_relax_section (abfd, sec, li
*** 2251,2257 ****
  	}
      }
  
!   if (!elf64_alpha_size_got_sections (abfd, link_info))
      return false;
  
    if (info.changed_relocs)
--- 2270,2280 ----
  	}
      }
  
!   if (!elf64_alpha_size_plt_section (link_info))
!     return false;
!   if (!elf64_alpha_size_got_sections (link_info))
!     return false;
!   if (!elf64_alpha_size_rela_got_section (link_info))
      return false;
  
    if (info.changed_relocs)
*************** elf64_alpha_calc_got_offsets (info)
*** 3650,3657 ****
  /* Constructs the gots.  */
  
  static boolean
! elf64_alpha_size_got_sections (output_bfd, info)
!      bfd *output_bfd ATTRIBUTE_UNUSED;
       struct bfd_link_info *info;
  {
    bfd *i, *got_list, *cur_got_obj = NULL;
--- 3673,3679 ----
  /* Constructs the gots.  */
  
  static boolean
! elf64_alpha_size_got_sections (info)
       struct bfd_link_info *info;
  {
    bfd *i, *got_list, *cur_got_obj = NULL;
*************** elf64_alpha_size_got_sections (output_bf
*** 3725,3733 ****
    return true;
  }
  
  static boolean
  elf64_alpha_always_size_sections (output_bfd, info)
!      bfd *output_bfd;
       struct bfd_link_info *info;
  {
    bfd *i;
--- 3747,3826 ----
    return true;
  }
  
+ /* Called from relax_section to rebuild the PLT in light of 
+    potential changes in the function's status.  */
+ 
+ static boolean
+ elf64_alpha_size_plt_section (info)
+      struct bfd_link_info *info;
+ {
+   asection *splt, *spltrel;
+   unsigned long entries;
+   bfd *dynobj;
+ 
+   dynobj = elf_hash_table(info)->dynobj;
+   splt = bfd_get_section_by_name(dynobj, ".plt");
+   if (splt == NULL)
+     return true;
+ 
+   splt->_raw_size = 0;
+ 
+   alpha_elf_link_hash_traverse (alpha_elf_hash_table (info),
+ 				elf64_alpha_size_plt_section_1, splt);
+ 
+   splt->_cooked_size = splt->_raw_size;
+ 
+   /* Every plt entry requires a JMP_SLOT relocation.  */
+   spltrel = bfd_get_section_by_name (dynobj, ".rela.plt");
+   if (splt->_raw_size)
+     entries = (splt->_raw_size - PLT_HEADER_SIZE) / PLT_ENTRY_SIZE;
+   else
+     entries = 0;
+   spltrel->_raw_size = entries * sizeof (Elf64_External_Rela);
+   spltrel->_cooked_size = spltrel->_raw_size;
+ 
+   return true;
+ }
+ 
+ static boolean
+ elf64_alpha_size_plt_section_1 (h, data)
+      struct alpha_elf_link_hash_entry *h;
+      PTR data;
+ {
+   asection *splt = (asection *) data;
+   struct alpha_elf_got_entry *gotent;
+ 
+   /* If we didn't need an entry before, we still don't.  */
+   if (!(h->root.elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT))
+     return true;
+ 
+   /* There must still be a LITERAL got entry for the function.  */
+   for (gotent = h->got_entries; gotent ; gotent = gotent->next)
+     if (gotent->reloc_type == R_ALPHA_LITERAL
+ 	&& gotent->use_count > 0)
+       break;
+ 
+   /* If there is, reset the PLT offset.  If not, there's no longer
+      a need for the PLT entry.  */
+   if (gotent)
+     {
+       if (splt->_raw_size == 0)
+ 	splt->_raw_size = PLT_HEADER_SIZE;
+       h->root.plt.offset = splt->_raw_size;
+       splt->_raw_size += PLT_ENTRY_SIZE;
+     }
+   else
+     {
+       h->root.elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
+       h->root.plt.offset = -1;
+     }
+ 
+   return true;
+ }
+ 
  static boolean
  elf64_alpha_always_size_sections (output_bfd, info)
!      bfd *output_bfd ATTRIBUTE_UNUSED;
       struct bfd_link_info *info;
  {
    bfd *i;
*************** elf64_alpha_always_size_sections (output
*** 3740,3746 ****
  				elf64_alpha_merge_ind_symbols,
  				NULL);
  
!   if (!elf64_alpha_size_got_sections (output_bfd, info))
      return false;
  
    /* Allocate space for all of the .got subsections.  */
--- 3833,3839 ----
  				elf64_alpha_merge_ind_symbols,
  				NULL);
  
!   if (!elf64_alpha_size_got_sections (info))
      return false;
  
    /* Allocate space for all of the .got subsections.  */
*************** elf64_alpha_calc_dynrel_sizes (h, info)
*** 3802,3809 ****
  {
    boolean dynamic;
    struct alpha_elf_reloc_entry *relent;
!   struct alpha_elf_got_entry *gotent;
!   int entries;
  
    if (h->root.root.type == bfd_link_hash_warning)
      h = (struct alpha_elf_link_hash_entry *) h->root.root.u.i.link;
--- 3895,3901 ----
  {
    boolean dynamic;
    struct alpha_elf_reloc_entry *relent;
!   unsigned long entries;
  
    if (h->root.root.type == bfd_link_hash_warning)
      h = (struct alpha_elf_link_hash_entry *) h->root.root.u.i.link;
*************** elf64_alpha_calc_dynrel_sizes (h, info)
*** 3823,3831 ****
        && (h->root.root.type == bfd_link_hash_defined
  	  || h->root.root.type == bfd_link_hash_defweak)
        && !(h->root.root.u.def.section->owner->flags & DYNAMIC))
!     {
!       h->root.elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
!     }
  
    /* If the symbol is dynamic, we'll need all the relocations in their
       natural form.  If this is a shared object, and it has been forced
--- 3915,3921 ----
        && (h->root.root.type == bfd_link_hash_defined
  	  || h->root.root.type == bfd_link_hash_defweak)
        && !(h->root.root.u.def.section->owner->flags & DYNAMIC))
!     h->root.elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
  
    /* If the symbol is dynamic, we'll need all the relocations in their
       natural form.  If this is a shared object, and it has been forced
*************** elf64_alpha_calc_dynrel_sizes (h, info)
*** 3846,3855 ****
  	}
      }
  
    entries = 0;
    for (gotent = h->got_entries; gotent ; gotent = gotent->next)
!     entries += alpha_dynamic_entries_for_reloc (gotent->reloc_type,
! 						dynamic, info->shared);
  
    /* If we are using a .plt entry, subtract one, as the first
       reference uses a .rela.plt entry instead.  */
--- 3936,4025 ----
  	}
      }
  
+   return true;
+ }
+ 
+ /* Set the sizes of the dynamic relocation sections.  */
+ 
+ static boolean
+ elf64_alpha_size_rela_got_section (info)
+      struct bfd_link_info *info;
+ {
+   unsigned long entries;
+   bfd *i, *dynobj;
+   asection *srel;
+ 
+   /* Shared libraries often require RELATIVE relocs, and some relocs
+      require attention for the main application as well.  */
+ 	 
+   entries = 0;
+   for (i = alpha_elf_hash_table(info)->got_list;
+        i ; i = alpha_elf_tdata(i)->got_link_next)
+     {
+       bfd *j;
+ 
+       for (j = i; j ; j = alpha_elf_tdata(j)->in_got_link_next)
+ 	{
+ 	  struct alpha_elf_got_entry **local_got_entries, *gotent;
+ 	  int k, n;
+ 
+ 	  local_got_entries = alpha_elf_tdata(j)->local_got_entries;
+ 	  if (!local_got_entries)
+ 	    continue;
+ 
+ 	  for (k = 0, n = elf_tdata(j)->symtab_hdr.sh_info; k < n; ++k)
+ 	    for (gotent = local_got_entries[k];
+ 		 gotent ; gotent = gotent->next)
+ 	      if (gotent->use_count > 0)
+ 		entries += (alpha_dynamic_entries_for_reloc
+ 			    (gotent->reloc_type, 0, info->shared));
+ 	}
+     }
+ 
+   dynobj = elf_hash_table(info)->dynobj;
+   srel = bfd_get_section_by_name (dynobj, ".rela.got");
+   if (!srel)
+     {
+       BFD_ASSERT (entries == 0);
+       return true;
+     }
+   srel->_raw_size = sizeof (Elf64_External_Rela) * entries;
+ 
+   /* Now do the non-local symbols.  */
+   alpha_elf_link_hash_traverse (alpha_elf_hash_table (info),
+ 				elf64_alpha_size_rela_got_1, info);
+ 
+   srel->_cooked_size = srel->_raw_size;
+ 
+   return true;
+ }
+ 
+ /* Subroutine of elf64_alpha_size_rela_got_section for doing the
+    global symbols.  */
+ 
+ static boolean
+ elf64_alpha_size_rela_got_1 (h, info)
+      struct alpha_elf_link_hash_entry *h;
+      struct bfd_link_info *info;
+ {
+   boolean dynamic;
+   struct alpha_elf_got_entry *gotent;
+   unsigned long entries;
+ 
+   if (h->root.root.type == bfd_link_hash_warning)
+     h = (struct alpha_elf_link_hash_entry *) h->root.root.u.i.link;
+ 
+   /* If the symbol is dynamic, we'll need all the relocations in their
+      natural form.  If this is a shared object, and it has been forced
+      local, we'll need the same number of RELATIVE relocations.  */
+ 
+   dynamic = alpha_elf_dynamic_symbol_p (&h->root, info);
+ 
    entries = 0;
    for (gotent = h->got_entries; gotent ; gotent = gotent->next)
!     if (gotent->use_count > 0)
!       entries += alpha_dynamic_entries_for_reloc (gotent->reloc_type,
! 						  dynamic, info->shared);
  
    /* If we are using a .plt entry, subtract one, as the first
       reference uses a .rela.plt entry instead.  */
*************** elf64_alpha_size_dynamic_sections (outpu
*** 3883,3891 ****
  
    if (elf_hash_table (info)->dynamic_sections_created)
      {
-       int entries;
-       bfd *i;
- 
        /* Set the contents of the .interp section to the interpreter.  */
        if (!info->shared)
  	{
--- 4053,4058 ----
*************** elf64_alpha_size_dynamic_sections (outpu
*** 3900,3941 ****
  	 collected information in check_relocs that we can now apply to
  	 size the dynamic relocation sections.  */
        alpha_elf_link_hash_traverse (alpha_elf_hash_table (info),
! 				    elf64_alpha_calc_dynrel_sizes,
! 				    info);
! 
!       /* Shared libraries often require RELATIVE relocs, and some relocs
! 	 require attention for the main application as well.  */
! 	 
!       entries = 0;
!       for (i = alpha_elf_hash_table(info)->got_list;
! 	   i ; i = alpha_elf_tdata(i)->got_link_next)
! 	{
! 	  bfd *j;
! 
! 	  for (j = i; j ; j = alpha_elf_tdata(j)->in_got_link_next)
! 	    {
! 	      struct alpha_elf_got_entry **local_got_entries, *gotent;
! 	      int k, n;
! 
! 	      local_got_entries = alpha_elf_tdata(j)->local_got_entries;
! 	      if (!local_got_entries)
! 		continue;
! 
! 	      for (k = 0, n = elf_tdata(j)->symtab_hdr.sh_info; k < n; ++k)
! 		for (gotent = local_got_entries[k];
! 		     gotent ; gotent = gotent->next)
! 		  if (gotent->use_count > 0)
! 		    entries += (alpha_dynamic_entries_for_reloc
! 				(gotent->reloc_type, 0, info->shared));
! 	    }
! 	}
  
!       if (entries > 0)
! 	{
! 	  s = bfd_get_section_by_name (dynobj, ".rela.got");
! 	  BFD_ASSERT (s != NULL);
! 	  s->_raw_size += sizeof (Elf64_External_Rela) * entries;
! 	}
      }
    /* else we're not dynamic and by definition we don't need such things.  */
  
--- 4067,4075 ----
  	 collected information in check_relocs that we can now apply to
  	 size the dynamic relocation sections.  */
        alpha_elf_link_hash_traverse (alpha_elf_hash_table (info),
! 				    elf64_alpha_calc_dynrel_sizes, info);
  
!       elf64_alpha_size_rela_got_section (info);
      }
    /* else we're not dynamic and by definition we don't need such things.  */
  
*************** elf64_alpha_finish_dynamic_symbol (outpu
*** 4827,4835 ****
  	   gotent != NULL;
  	   gotent = gotent->next)
  	{
! 	  asection *sgot = alpha_elf_tdata (gotent->gotobj)->got;
  	  int r_type;
  
  	  outrel.r_offset = (sgot->output_section->vma
  			     + sgot->output_offset
  			     + gotent->got_offset);
--- 4961,4973 ----
  	   gotent != NULL;
  	   gotent = gotent->next)
  	{
! 	  asection *sgot;
  	  int r_type;
  
+ 	  if (gotent->use_count == 0)
+ 	    continue;
+ 
+ 	  sgot = alpha_elf_tdata (gotent->gotobj)->got;
  	  outrel.r_offset = (sgot->output_section->vma
  			     + sgot->output_offset
  			     + gotent->got_offset);


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