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

Blackfin: BFD fixes for deleted relocs


Over time, the Blackfin and FRV FD-PIC implementations have slightly
diverged.  We've had our own fixes for dealing with deleted relocs in
eh-frame sections, and these have worked in the 2.17 tree we're using
locally.  However, with CVS binutils there are lots of assertion
failures when trying to link C++ programs.

This patch just copies over the FRV version of these fixes.  To do that,
I've also had to bring in a few structural changes - the FRV code got a
bit rearranged with the introduction of TLS.


Bernd
-- 
This footer brought to you by insane German lawmakers.
Analog Devices GmbH      Wilhelm-Wagenfeld-Str. 6      80807 Muenchen
Sitz der Gesellschaft Muenchen, Registergericht Muenchen HRB 40368
Geschaeftsfuehrer Thomas Wessel, William A. Martin, Margaret Seif
Index: ChangeLog
===================================================================
RCS file: /cvs/src/src/bfd/ChangeLog,v
retrieving revision 1.4735
diff -c -p -r1.4735 ChangeLog
*** ChangeLog	11 Aug 2009 02:21:34 -0000	1.4735
--- ChangeLog	11 Aug 2009 11:40:02 -0000
***************
*** 1,3 ****
--- 1,23 ----
+ 2009-08-11  Bernd Schmidt  <bernd.schmidt@analog.com>
+ 
+ 	Merge some FRV FDPIC changes into the Blackfin code.
+ 	* elf32-bfin.c (struct bfinfdpic_elf_link_hash_table): Add pointer to
+ 	summary reloc information.
+ 	(bfinfdpic_dynamic_got_plt_info): New.
+ 	(_bfin_create_got_section): Create the PLT section here.
+ 	(elf32_bfinfdpic_create_dynamic_sections): Not here.
+ 	(_bfinfdpic_count_nontls_entries): Move out of...
+ 	(_bfinfdpic_count_got_plt_entries): ... here.
+ 	(_bfinfdpic_count_relocs_fixups): Likewise.
+ 	(_bfinfdpic_reset_got_plt_entries): New.
+ 	(_bfinfdpic_size_got_plt): Move out of...
+ 	(elf32_bfinfdpic_size_dynamic_sections): ... here.
+ 	(bfinfdpic_relocate_section): Be careful not to call
+ 	_bfinfdpic_add_rofixup or _bfinfdpic_add_dyn_reloc for deleted relocs.
+ 	(bfinfdpic_check_discarded_relocs, bfinfdpic_elf_discard_info):
+ 	New functions.
+ 	(elf_backend_discard_info): Define for FD-PIC.
+ 
  2009-08-11  Alan Modra  <amodra@bigpond.net.au>
  
  	* elflink.c: Add FIXMEs for some places that require octets_per_byte
***************
*** 69,75 ****
  	(ppc_elf_size_dynamic_sections): Likewise.
  	(ppc_elf_relocate_section): Likewise.
  
! 2006-08-09  Bernd Schmidt  <bernd.schmidt@analog.com>
  
  	From Mike Frysinger <michael.frysinger@analog.com>
  	* elf32-bfin.c (bfin_howto_table, bfin_reloc_map, bfin_check_relocs,
--- 89,95 ----
  	(ppc_elf_size_dynamic_sections): Likewise.
  	(ppc_elf_relocate_section): Likewise.
  
! 2009-08-09  Bernd Schmidt  <bernd.schmidt@analog.com>
  
  	From Mike Frysinger <michael.frysinger@analog.com>
  	* elf32-bfin.c (bfin_howto_table, bfin_reloc_map, bfin_check_relocs,
Index: elf32-bfin.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-bfin.c,v
retrieving revision 1.39
diff -c -p -r1.39 elf32-bfin.c
*** elf32-bfin.c	9 Aug 2009 16:45:04 -0000	1.39
--- elf32-bfin.c	11 Aug 2009 11:40:03 -0000
*************** struct bfinfdpic_elf_link_hash_table
*** 1740,1745 ****
--- 1740,1748 ----
    /* A hash table holding information about which symbols were
       referenced with which PIC-related relocations.  */
    struct htab *relocs_info;
+   /* Summary reloc information collected by
+      _bfinfdpic_count_got_plt_entries.  */
+   struct _bfinfdpic_dynamic_got_info *g;
  };
  
  /* Get the Blackfin ELF linker hash table from a link_info structure.  */
*************** struct bfinfdpic_elf_link_hash_table
*** 1763,1768 ****
--- 1766,1773 ----
    (bfinfdpic_hash_table (info)->got0)
  #define bfinfdpic_plt_initial_offset(info) \
    (bfinfdpic_hash_table (info)->plt0)
+ #define bfinfdpic_dynamic_got_plt_info(info) \
+   (bfinfdpic_hash_table (info)->g)
  
  /* The name of the dynamic interpreter.  This is put in the .interp
     section.  */
*************** _bfinfdpic_emit_got_relocs_plt_entries (
*** 2149,2155 ****
  	dynindx = entry->d.h->dynindx;
        else
  	{
! 	  if (sec->output_section
  	      && ! bfd_is_abs_section (sec->output_section)
  	      && ! bfd_is_und_section (sec->output_section))
  	    dynindx = elf_section_data (sec->output_section)->dynindx;
--- 2154,2161 ----
  	dynindx = entry->d.h->dynindx;
        else
  	{
! 	  if (sec
! 	      && sec->output_section
  	      && ! bfd_is_abs_section (sec->output_section)
  	      && ! bfd_is_und_section (sec->output_section))
  	    dynindx = elf_section_data (sec->output_section)->dynindx;
*************** _bfinfdpic_emit_got_relocs_plt_entries (
*** 2417,2424 ****
  	     of the section.  For a non-local function, it's
  	     disregarded.  */
  	  lowword = ad;
! 	  if (entry->symndx == -1 && entry->d.h->dynindx != -1
! 	      && entry->d.h->dynindx == idx)
  	    highword = 0;
  	  else
  	    highword = _bfinfdpic_osec_to_segment
--- 2423,2431 ----
  	     of the section.  For a non-local function, it's
  	     disregarded.  */
  	  lowword = ad;
! 	  if (sec == NULL
! 	      || (entry->symndx == -1 && entry->d.h->dynindx != -1
! 		  && entry->d.h->dynindx == idx))
  	    highword = 0;
  	  else
  	    highword = _bfinfdpic_osec_to_segment
*************** bfinfdpic_relocate_section (bfd * output
*** 2843,2848 ****
--- 2850,2857 ----
  		if (info->executable && !info->pie
  		    && (!h || BFINFDPIC_FUNCDESC_LOCAL (info, h)))
  		  {
+ 		    bfd_vma offset;
+ 
  		    addend += bfinfdpic_got_section (info)->output_section->vma;
  		    if ((bfd_get_section_flags (output_bfd,
  						input_section->output_section)
*************** bfinfdpic_relocate_section (bfd * output
*** 2858,2873 ****
  			       name, input_bfd, input_section, rel->r_offset);
  			    return FALSE;
  			  }
! 			_bfinfdpic_add_rofixup (output_bfd,
! 					       bfinfdpic_gotfixup_section
! 					       (info),
! 					       _bfd_elf_section_offset
! 					       (output_bfd, info,
! 						input_section, rel->r_offset)
! 					       + input_section
! 					       ->output_section->vma
! 					       + input_section->output_offset,
! 					       picrel);
  		      }
  		  }
  		else if ((bfd_get_section_flags (output_bfd,
--- 2867,2885 ----
  			       name, input_bfd, input_section, rel->r_offset);
  			    return FALSE;
  			  }
! 
! 			offset = _bfd_elf_section_offset
! 			  (output_bfd, info,
! 			   input_section, rel->r_offset);
! 
! 			if (offset != (bfd_vma)-1)
! 			  _bfinfdpic_add_rofixup (output_bfd,
! 						  bfinfdpic_gotfixup_section
! 						  (info),
! 						  offset + input_section
! 						  ->output_section->vma
! 						  + input_section->output_offset,
! 						  picrel);
  		      }
  		  }
  		else if ((bfd_get_section_flags (output_bfd,
*************** bfinfdpic_relocate_section (bfd * output
*** 2888,2901 ****
  		      }
  		    offset = _bfd_elf_section_offset (output_bfd, info,
  						      input_section, rel->r_offset);
! 		    /* Only output a reloc for a not deleted entry.  */
! 		    if (offset >= (bfd_vma) -2)
! 		      _bfinfdpic_add_dyn_reloc (output_bfd,
! 						bfinfdpic_gotrel_section (info),
! 						0,
! 						R_BFIN_UNUSED0,
! 						dynindx, addend, picrel);
! 		    else
  		      _bfinfdpic_add_dyn_reloc (output_bfd,
  						bfinfdpic_gotrel_section (info),
  						offset + input_section
--- 2900,2907 ----
  		      }
  		    offset = _bfd_elf_section_offset (output_bfd, info,
  						      input_section, rel->r_offset);
! 
! 		    if (offset != (bfd_vma)-1)
  		      _bfinfdpic_add_dyn_reloc (output_bfd,
  						bfinfdpic_gotrel_section (info),
  						offset + input_section
*************** bfinfdpic_relocate_section (bfd * output
*** 2986,3013 ****
  		      }
  		    if (!h || h->root.type != bfd_link_hash_undefweak)
  		      {
! 			/* Only output a reloc for a not deleted entry.  */
! 			if (offset >= (bfd_vma)-2)
! 			  _bfinfdpic_add_rofixup (output_bfd,
! 						  bfinfdpic_gotfixup_section
! 						  (info), -1, picrel);
! 			else
! 			  _bfinfdpic_add_rofixup (output_bfd,
! 						  bfinfdpic_gotfixup_section
! 						  (info),
! 						  offset + input_section
! 						  ->output_section->vma
! 						  + input_section->output_offset,
! 						  picrel);
! 
! 			if (r_type == R_BFIN_FUNCDESC_VALUE)
  			  {
! 			    if (offset >= (bfd_vma)-2)
! 			      _bfinfdpic_add_rofixup
! 				(output_bfd,
! 				 bfinfdpic_gotfixup_section (info),
! 				 -1, picrel);
! 			    else
  			      _bfinfdpic_add_rofixup
  				(output_bfd,
  				 bfinfdpic_gotfixup_section (info),
--- 2992,3008 ----
  		      }
  		    if (!h || h->root.type != bfd_link_hash_undefweak)
  		      {
! 			if (offset != (bfd_vma)-1)
  			  {
! 			    _bfinfdpic_add_rofixup (output_bfd,
! 						    bfinfdpic_gotfixup_section
! 						    (info),
! 						    offset + input_section
! 						    ->output_section->vma
! 						    + input_section->output_offset,
! 						    picrel);
! 
! 			    if (r_type == R_BFIN_FUNCDESC_VALUE)
  			      _bfinfdpic_add_rofixup
  				(output_bfd,
  				 bfinfdpic_gotfixup_section (info),
*************** bfinfdpic_relocate_section (bfd * output
*** 3033,3049 ****
  			   name, input_bfd, input_section, rel->r_offset);
  			return FALSE;
  		      }
! 		    /* Only output a reloc for a not deleted entry.  */
! 		    if (offset >= (bfd_vma)-2)
! 		      _bfinfdpic_add_dyn_reloc (output_bfd,
! 						bfinfdpic_gotrel_section (info),
! 						0, R_BFIN_UNUSED0, dynindx, addend, picrel);
! 		    else
  		      _bfinfdpic_add_dyn_reloc (output_bfd,
  						bfinfdpic_gotrel_section (info),
  						offset
! 						+ input_section
! 						->output_section->vma
  						+ input_section->output_offset,
  						r_type, dynindx, addend, picrel);
  		  }
--- 3028,3039 ----
  			   name, input_bfd, input_section, rel->r_offset);
  			return FALSE;
  		      }
! 
! 		    if (offset != (bfd_vma)-1)
  		      _bfinfdpic_add_dyn_reloc (output_bfd,
  						bfinfdpic_gotrel_section (info),
  						offset
! 						+ input_section->output_section->vma
  						+ input_section->output_offset,
  						r_type, dynindx, addend, picrel);
  		  }
*************** bfinfdpic_relocate_section (bfd * output
*** 3055,3061 ****
  		relocation = addend - rel->r_addend;
  	      }
  
! 	    if (r_type == R_BFIN_FUNCDESC_VALUE && offset < (bfd_vma)-2)
  	      {
  		/* If we've omitted the dynamic relocation, just emit
  		   the fixed addresses of the symbol and of the local
--- 3045,3051 ----
  		relocation = addend - rel->r_addend;
  	      }
  
! 	    if (r_type == R_BFIN_FUNCDESC_VALUE)
  	      {
  		/* If we've omitted the dynamic relocation, just emit
  		   the fixed addresses of the symbol and of the local
*************** _bfin_create_got_section (bfd *abfd, str
*** 3469,3496 ****
        flags = BSF_GLOBAL | BSF_WEAK;
      }
  
!   return TRUE;
! }
! 
! /* Make sure the got and plt sections exist, and that our pointers in
!    the link hash table point to them.  */
! 
! static bfd_boolean
! elf32_bfinfdpic_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
! {
!   /* This is mostly copied from
!      elflink.c:_bfd_elf_create_dynamic_sections().  */
!   flagword flags, pltflags;
!   asection *s;
!   const struct elf_backend_data *bed = get_elf_backend_data (abfd);
! 
!   /* We need to create .plt, .rel[a].plt, .got, .got.plt, .dynbss, and
!      .rel[a].bss sections.  */
! 
!   flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
! 	   | SEC_LINKER_CREATED);
! 
!   pltflags = flags;
    pltflags |= SEC_CODE;
    if (bed->plt_not_loaded)
      pltflags &= ~ (SEC_CODE | SEC_LOAD | SEC_HAS_CONTENTS);
--- 3459,3465 ----
        flags = BSF_GLOBAL | BSF_WEAK;
      }
  
!   flags = pltflags;
    pltflags |= SEC_CODE;
    if (bed->plt_not_loaded)
      pltflags &= ~ (SEC_CODE | SEC_LOAD | SEC_HAS_CONTENTS);
*************** elf32_bfinfdpic_create_dynamic_sections 
*** 3532,3537 ****
--- 3501,3527 ----
    /* Blackfin-specific: remember it.  */
    bfinfdpic_pltrel_section (info) = s;
  
+   return TRUE;
+ }
+ 
+ /* Make sure the got and plt sections exist, and that our pointers in
+    the link hash table point to them.  */
+ 
+ static bfd_boolean
+ elf32_bfinfdpic_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
+ {
+   /* This is mostly copied from
+      elflink.c:_bfd_elf_create_dynamic_sections().  */
+   flagword flags;
+   asection *s;
+   const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+ 
+   flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
+ 	   | SEC_LINKER_CREATED);
+ 
+   /* We need to create .plt, .rel[a].plt, .got, .got.plt, .dynbss, and
+      .rel[a].bss sections.  */
+ 
    /* Blackfin-specific: we want to create the GOT in the Blackfin way.  */
    if (! _bfin_create_got_section (abfd, info))
      return FALSE;
*************** elf32_bfinfdpic_create_dynamic_sections 
*** 3586,3598 ****
     the symbol, an entry pointing to its function descriptor, and a
     private function descriptors taking two words.  */
  
! static int
! _bfinfdpic_count_got_plt_entries (void **entryp, void *dinfo_)
  {
-   struct bfinfdpic_relocs_info *entry = *entryp;
-   struct _bfinfdpic_dynamic_got_info *dinfo = dinfo_;
-   unsigned relocs = 0, fixups = 0;
- 
    /* Allocate space for a GOT entry pointing to the symbol.  */
    if (entry->got17m4)
      dinfo->got17m4 += 4;
--- 3576,3585 ----
     the symbol, an entry pointing to its function descriptor, and a
     private function descriptors taking two words.  */
  
! static void
! _bfinfdpic_count_nontls_entries (struct bfinfdpic_relocs_info *entry,
! 				 struct _bfinfdpic_dynamic_got_info *dinfo)
  {
    /* Allocate space for a GOT entry pointing to the symbol.  */
    if (entry->got17m4)
      dinfo->got17m4 += 4;
*************** _bfinfdpic_count_got_plt_entries (void *
*** 3640,3645 ****
--- 3627,3644 ----
  
    if (entry->lazyplt)
      dinfo->lzplt += LZPLT_NORMAL_SIZE;
+ }
+ 
+ /* Compute the number of dynamic relocations and fixups that a symbol
+    requires, and add (or subtract) from the grand and per-symbol
+    totals.  */
+ 
+ static void
+ _bfinfdpic_count_relocs_fixups (struct bfinfdpic_relocs_info *entry,
+ 				struct _bfinfdpic_dynamic_got_info *dinfo,
+ 				bfd_boolean subtract)
+ {
+   bfd_vma relocs = 0, fixups = 0;
  
    if (!dinfo->info->executable || dinfo->info->pie)
      relocs = entry->relocs32 + entry->relocsfd + entry->relocsfdv;
*************** _bfinfdpic_count_got_plt_entries (void *
*** 3665,3674 ****
--- 3664,3695 ----
  	relocs += entry->relocsfd;
      }
  
+   if (subtract)
+     {
+       relocs = - relocs;
+       fixups = - fixups;
+     }
+ 
    entry->dynrelocs += relocs;
    entry->fixups += fixups;
    dinfo->relocs += relocs;
    dinfo->fixups += fixups;
+ }
+ 
+ /* Compute the total GOT and PLT size required by each symbol in each range. *
+    Symbols may require up to 4 words in the GOT: an entry pointing to
+    the symbol, an entry pointing to its function descriptor, and a
+    private function descriptors taking two words.  */
+ 
+ static int
+ _bfinfdpic_count_got_plt_entries (void **entryp, void *dinfo_)
+ {
+   struct bfinfdpic_relocs_info *entry = *entryp;
+   struct _bfinfdpic_dynamic_got_info *dinfo = dinfo_;
+ 
+   _bfinfdpic_count_nontls_entries (entry, dinfo);
+ 
+   _bfinfdpic_count_relocs_fixups (entry, dinfo, FALSE);
  
    return 1;
  }
*************** _bfinfdpic_assign_plt_entries (void **en
*** 3964,3969 ****
--- 3985,4007 ----
    return 1;
  }
  
+ /* Cancel out any effects of calling _bfinfdpic_assign_got_entries and
+    _bfinfdpic_assign_plt_entries.  */
+ 
+ static int
+ _bfinfdpic_reset_got_plt_entries (void **entryp, void *ignore ATTRIBUTE_UNUSED)
+ {
+   struct bfinfdpic_relocs_info *entry = *entryp;
+ 
+   entry->got_entry = 0;
+   entry->fdgot_entry = 0;
+   entry->fd_entry = 0;
+   entry->plt_entry = (bfd_vma)-1;
+   entry->lzplt_entry = (bfd_vma)-1;
+ 
+   return 1;
+ }
+ 
  /* Follow indirect and warning hash entries so that each got entry
     points to the final symbol definition.  P must point to a pointer
     to the hash table we're traversing.  Since this traversal may
*************** _bfinfdpic_resolve_final_relocs_info (vo
*** 4020,4108 ****
    return 1;
  }
  
! /* Set the sizes of the dynamic sections.  */
  
  static bfd_boolean
! elf32_bfinfdpic_size_dynamic_sections (bfd *output_bfd,
! 				      struct bfd_link_info *info)
  {
-   bfd *dynobj;
-   asection *s;
-   struct _bfinfdpic_dynamic_got_plt_info gpinfo;
    bfd_signed_vma odd;
    bfd_vma limit;
  
!   dynobj = elf_hash_table (info)->dynobj;
!   BFD_ASSERT (dynobj != NULL);
! 
!   if (elf_hash_table (info)->dynamic_sections_created)
!     {
!       /* Set the contents of the .interp section to the interpreter.  */
!       if (info->executable)
! 	{
! 	  s = bfd_get_section_by_name (dynobj, ".interp");
! 	  BFD_ASSERT (s != NULL);
! 	  s->size = sizeof ELF_DYNAMIC_INTERPRETER;
! 	  s->contents = (bfd_byte *) ELF_DYNAMIC_INTERPRETER;
! 	}
!     }
! 
!   memset (&gpinfo, 0, sizeof (gpinfo));
!   gpinfo.g.info = info;
! 
!   for (;;)
!     {
!       htab_t relocs = bfinfdpic_relocs_info (info);
! 
!       htab_traverse (relocs, _bfinfdpic_resolve_final_relocs_info, &relocs);
! 
!       if (relocs == bfinfdpic_relocs_info (info))
! 	break;
!     }
! 
!   htab_traverse (bfinfdpic_relocs_info (info), _bfinfdpic_count_got_plt_entries,
! 		 &gpinfo.g);
  
    odd = 12;
    /* Compute the total size taken by entries in the 18-bit range,
       to tell how many PLT function descriptors we can bring into it
       without causing it to overflow.  */
!   limit = odd + gpinfo.g.got17m4 + gpinfo.g.fd17m4;
    if (limit < (bfd_vma)1 << 18)
      limit = ((bfd_vma)1 << 18) - limit;
    else
      limit = 0;
!   if (gpinfo.g.fdplt < limit)
!     limit = gpinfo.g.fdplt;
  
    /* Determine the ranges of GOT offsets that we can use for each
       range of addressing modes.  */
!   odd = _bfinfdpic_compute_got_alloc_data (&gpinfo.got17m4,
  					  0,
  					  odd,
  					  16,
! 					  gpinfo.g.got17m4,
! 					  gpinfo.g.fd17m4,
  					  limit,
  					  (bfd_vma)1 << (18-1));
!   odd = _bfinfdpic_compute_got_alloc_data (&gpinfo.gothilo,
! 					  gpinfo.got17m4.min,
  					  odd,
! 					  gpinfo.got17m4.max,
! 					  gpinfo.g.gothilo,
! 					  gpinfo.g.fdhilo,
! 					  gpinfo.g.fdplt - gpinfo.got17m4.fdplt,
  					  (bfd_vma)1 << (32-1));
  
    /* Now assign (most) GOT offsets.  */
    htab_traverse (bfinfdpic_relocs_info (info), _bfinfdpic_assign_got_entries,
! 		 &gpinfo);
  
!   bfinfdpic_got_section (info)->size = gpinfo.gothilo.max
!     - gpinfo.gothilo.min
      /* If an odd word is the last word of the GOT, we don't need this
         word to be part of the GOT.  */
!     - (odd + 4 == gpinfo.gothilo.max ? 4 : 0);
    if (bfinfdpic_got_section (info)->size == 0)
      bfinfdpic_got_section (info)->flags |= SEC_EXCLUDE;
    else if (bfinfdpic_got_section (info)->size == 12
--- 4058,4119 ----
    return 1;
  }
  
! /* Compute the total size of the GOT, the PLT, the dynamic relocations
!    section and the rofixup section.  Assign locations for GOT and PLT
!    entries.  */
  
  static bfd_boolean
! _bfinfdpic_size_got_plt (bfd *output_bfd,
! 			 struct _bfinfdpic_dynamic_got_plt_info *gpinfop)
  {
    bfd_signed_vma odd;
    bfd_vma limit;
+   struct bfd_link_info *info = gpinfop->g.info;
+   bfd *dynobj = elf_hash_table (info)->dynobj;
  
!   memcpy (bfinfdpic_dynamic_got_plt_info (info), &gpinfop->g,
! 	  sizeof (gpinfop->g));
  
    odd = 12;
    /* Compute the total size taken by entries in the 18-bit range,
       to tell how many PLT function descriptors we can bring into it
       without causing it to overflow.  */
!   limit = odd + gpinfop->g.got17m4 + gpinfop->g.fd17m4;
    if (limit < (bfd_vma)1 << 18)
      limit = ((bfd_vma)1 << 18) - limit;
    else
      limit = 0;
!   if (gpinfop->g.fdplt < limit)
!     limit = gpinfop->g.fdplt;
  
    /* Determine the ranges of GOT offsets that we can use for each
       range of addressing modes.  */
!   odd = _bfinfdpic_compute_got_alloc_data (&gpinfop->got17m4,
  					  0,
  					  odd,
  					  16,
! 					  gpinfop->g.got17m4,
! 					  gpinfop->g.fd17m4,
  					  limit,
  					  (bfd_vma)1 << (18-1));
!   odd = _bfinfdpic_compute_got_alloc_data (&gpinfop->gothilo,
! 					  gpinfop->got17m4.min,
  					  odd,
! 					  gpinfop->got17m4.max,
! 					  gpinfop->g.gothilo,
! 					  gpinfop->g.fdhilo,
! 					  gpinfop->g.fdplt - gpinfop->got17m4.fdplt,
  					  (bfd_vma)1 << (32-1));
  
    /* Now assign (most) GOT offsets.  */
    htab_traverse (bfinfdpic_relocs_info (info), _bfinfdpic_assign_got_entries,
! 		 gpinfop);
  
!   bfinfdpic_got_section (info)->size = gpinfop->gothilo.max
!     - gpinfop->gothilo.min
      /* If an odd word is the last word of the GOT, we don't need this
         word to be part of the GOT.  */
!     - (odd + 4 == gpinfop->gothilo.max ? 4 : 0);
    if (bfinfdpic_got_section (info)->size == 0)
      bfinfdpic_got_section (info)->flags |= SEC_EXCLUDE;
    else if (bfinfdpic_got_section (info)->size == 12
*************** elf32_bfinfdpic_size_dynamic_sections (b
*** 4124,4133 ****
      /* Subtract the number of lzplt entries, since those will generate
         relocations in the pltrel section.  */
      bfinfdpic_gotrel_section (info)->size =
!       (gpinfo.g.relocs - gpinfo.g.lzplt / LZPLT_NORMAL_SIZE)
        * get_elf_backend_data (output_bfd)->s->sizeof_rel;
    else
!     BFD_ASSERT (gpinfo.g.relocs == 0);
    if (bfinfdpic_gotrel_section (info)->size == 0)
      bfinfdpic_gotrel_section (info)->flags |= SEC_EXCLUDE;
    else
--- 4135,4144 ----
      /* Subtract the number of lzplt entries, since those will generate
         relocations in the pltrel section.  */
      bfinfdpic_gotrel_section (info)->size =
!       (gpinfop->g.relocs - gpinfop->g.lzplt / LZPLT_NORMAL_SIZE)
        * get_elf_backend_data (output_bfd)->s->sizeof_rel;
    else
!     BFD_ASSERT (gpinfop->g.relocs == 0);
    if (bfinfdpic_gotrel_section (info)->size == 0)
      bfinfdpic_gotrel_section (info)->flags |= SEC_EXCLUDE;
    else
*************** elf32_bfinfdpic_size_dynamic_sections (b
*** 4139,4145 ****
  	return FALSE;
      }
  
!   bfinfdpic_gotfixup_section (info)->size = (gpinfo.g.fixups + 1) * 4;
    if (bfinfdpic_gotfixup_section (info)->size == 0)
      bfinfdpic_gotfixup_section (info)->flags |= SEC_EXCLUDE;
    else
--- 4150,4156 ----
  	return FALSE;
      }
  
!   bfinfdpic_gotfixup_section (info)->size = (gpinfop->g.fixups + 1) * 4;
    if (bfinfdpic_gotfixup_section (info)->size == 0)
      bfinfdpic_gotfixup_section (info)->flags |= SEC_EXCLUDE;
    else
*************** elf32_bfinfdpic_size_dynamic_sections (b
*** 4154,4160 ****
    if (elf_hash_table (info)->dynamic_sections_created)
      {
        bfinfdpic_pltrel_section (info)->size =
! 	gpinfo.g.lzplt / LZPLT_NORMAL_SIZE * get_elf_backend_data (output_bfd)->s->sizeof_rel;
        if (bfinfdpic_pltrel_section (info)->size == 0)
  	bfinfdpic_pltrel_section (info)->flags |= SEC_EXCLUDE;
        else
--- 4165,4171 ----
    if (elf_hash_table (info)->dynamic_sections_created)
      {
        bfinfdpic_pltrel_section (info)->size =
! 	gpinfop->g.lzplt / LZPLT_NORMAL_SIZE * get_elf_backend_data (output_bfd)->s->sizeof_rel;
        if (bfinfdpic_pltrel_section (info)->size == 0)
  	bfinfdpic_pltrel_section (info)->flags |= SEC_EXCLUDE;
        else
*************** elf32_bfinfdpic_size_dynamic_sections (b
*** 4174,4202 ****
       block size.  */
    if (elf_hash_table (info)->dynamic_sections_created)
      {
!       bfinfdpic_plt_section (info)->size = gpinfo.g.lzplt
! 	+ ((gpinfo.g.lzplt + (BFINFDPIC_LZPLT_BLOCK_SIZE - 4) - LZPLT_NORMAL_SIZE)
  	   / (BFINFDPIC_LZPLT_BLOCK_SIZE - 4) * LZPLT_RESOLVER_EXTRA);
      }
  
    /* Reset it, such that _bfinfdpic_assign_plt_entries() can use it to
       actually assign lazy PLT entries addresses.  */
!   gpinfo.g.lzplt = 0;
  
    /* Save information that we're going to need to generate GOT and PLT
       entries.  */
!   bfinfdpic_got_initial_offset (info) = -gpinfo.gothilo.min;
  
    if (get_elf_backend_data (output_bfd)->want_got_sym)
      elf_hash_table (info)->hgot->root.u.def.value
!       += bfinfdpic_got_initial_offset (info);
  
    if (elf_hash_table (info)->dynamic_sections_created)
      bfinfdpic_plt_initial_offset (info) =
        bfinfdpic_plt_section (info)->size;
  
    htab_traverse (bfinfdpic_relocs_info (info), _bfinfdpic_assign_plt_entries,
! 		 &gpinfo);
  
    /* Allocate the PLT section contents only after
       _bfinfdpic_assign_plt_entries has a chance to add the size of the
--- 4185,4213 ----
       block size.  */
    if (elf_hash_table (info)->dynamic_sections_created)
      {
!       bfinfdpic_plt_section (info)->size = gpinfop->g.lzplt
! 	+ ((gpinfop->g.lzplt + (BFINFDPIC_LZPLT_BLOCK_SIZE - 4) - LZPLT_NORMAL_SIZE)
  	   / (BFINFDPIC_LZPLT_BLOCK_SIZE - 4) * LZPLT_RESOLVER_EXTRA);
      }
  
    /* Reset it, such that _bfinfdpic_assign_plt_entries() can use it to
       actually assign lazy PLT entries addresses.  */
!   gpinfop->g.lzplt = 0;
  
    /* Save information that we're going to need to generate GOT and PLT
       entries.  */
!   bfinfdpic_got_initial_offset (info) = -gpinfop->gothilo.min;
  
    if (get_elf_backend_data (output_bfd)->want_got_sym)
      elf_hash_table (info)->hgot->root.u.def.value
!       = bfinfdpic_got_initial_offset (info);
  
    if (elf_hash_table (info)->dynamic_sections_created)
      bfinfdpic_plt_initial_offset (info) =
        bfinfdpic_plt_section (info)->size;
  
    htab_traverse (bfinfdpic_relocs_info (info), _bfinfdpic_assign_plt_entries,
! 		 gpinfop);
  
    /* Allocate the PLT section contents only after
       _bfinfdpic_assign_plt_entries has a chance to add the size of the
*************** elf32_bfinfdpic_size_dynamic_sections (b
*** 4215,4220 ****
--- 4226,4284 ----
  	}
      }
  
+   return TRUE;
+ }
+ 
+ /* Set the sizes of the dynamic sections.  */
+ 
+ static bfd_boolean
+ elf32_bfinfdpic_size_dynamic_sections (bfd *output_bfd,
+ 				      struct bfd_link_info *info)
+ {
+   struct elf_link_hash_table *htab;
+   bfd *dynobj;
+   asection *s;
+   struct _bfinfdpic_dynamic_got_plt_info gpinfo;
+ 
+   htab = elf_hash_table (info);
+   dynobj = htab->dynobj;
+   BFD_ASSERT (dynobj != NULL);
+ 
+   if (htab->dynamic_sections_created)
+     {
+       /* Set the contents of the .interp section to the interpreter.  */
+       if (info->executable)
+ 	{
+ 	  s = bfd_get_section_by_name (dynobj, ".interp");
+ 	  BFD_ASSERT (s != NULL);
+ 	  s->size = sizeof ELF_DYNAMIC_INTERPRETER;
+ 	  s->contents = (bfd_byte *) ELF_DYNAMIC_INTERPRETER;
+ 	}
+     }
+ 
+   memset (&gpinfo, 0, sizeof (gpinfo));
+   gpinfo.g.info = info;
+ 
+   for (;;)
+     {
+       htab_t relocs = bfinfdpic_relocs_info (info);
+ 
+       htab_traverse (relocs, _bfinfdpic_resolve_final_relocs_info, &relocs);
+ 
+       if (relocs == bfinfdpic_relocs_info (info))
+ 	break;
+     }
+ 
+   htab_traverse (bfinfdpic_relocs_info (info), _bfinfdpic_count_got_plt_entries,
+ 		 &gpinfo.g);
+ 
+   /* Allocate space to save the summary information, we're going to
+      use it if we're doing relaxations.  */
+   bfinfdpic_dynamic_got_plt_info (info) = bfd_alloc (dynobj, sizeof (gpinfo.g));
+ 
+   if (!_bfinfdpic_size_got_plt (output_bfd, &gpinfo))
+       return FALSE;
+ 
    if (elf_hash_table (info)->dynamic_sections_created)
      {
        if (bfinfdpic_got_section (info)->size)
*************** elf32_bfinfdpic_always_size_sections (bf
*** 4275,4280 ****
--- 4339,4460 ----
    return TRUE;
  }
  
+ /* Check whether any of the relocations was optimized away, and
+    subtract it from the relocation or fixup count.  */
+ static bfd_boolean
+ _bfinfdpic_check_discarded_relocs (bfd *abfd, asection *sec,
+ 				  struct bfd_link_info *info,
+ 				  
+ 				  bfd_boolean *changed)
+ {
+   Elf_Internal_Shdr *symtab_hdr;
+   struct elf_link_hash_entry **sym_hashes, **sym_hashes_end;
+   Elf_Internal_Rela *rel, *erel;
+ 
+   if ((sec->flags & SEC_RELOC) == 0
+       || sec->reloc_count == 0)
+     return TRUE;
+ 
+   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
+   sym_hashes = elf_sym_hashes (abfd);
+   sym_hashes_end = sym_hashes + symtab_hdr->sh_size/sizeof(Elf32_External_Sym);
+   if (!elf_bad_symtab (abfd))
+     sym_hashes_end -= symtab_hdr->sh_info;
+ 
+   rel = elf_section_data (sec)->relocs;
+ 
+   /* Now examine each relocation.  */
+   for (erel = rel + sec->reloc_count; rel < erel; rel++)
+     {
+       struct elf_link_hash_entry *h;
+       unsigned long r_symndx;
+       struct bfinfdpic_relocs_info *picrel;
+       struct _bfinfdpic_dynamic_got_info *dinfo;
+ 
+       if (ELF32_R_TYPE (rel->r_info) != R_BFIN_BYTE4_DATA
+ 	  && ELF32_R_TYPE (rel->r_info) != R_BFIN_FUNCDESC)
+ 	continue;
+ 
+       if (_bfd_elf_section_offset (sec->output_section->owner,
+ 				   info, sec, rel->r_offset)
+ 	  != (bfd_vma)-1)
+ 	continue;
+ 
+       r_symndx = ELF32_R_SYM (rel->r_info);
+       if (r_symndx < symtab_hdr->sh_info)
+ 	h = NULL;
+       else
+ 	{
+ 	  h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+ 	  while (h->root.type == bfd_link_hash_indirect
+ 		 || h->root.type == bfd_link_hash_warning)
+ 	    h = (struct elf_link_hash_entry *)h->root.u.i.link;
+ 	}
+ 
+       if (h != NULL)
+ 	picrel = bfinfdpic_relocs_info_for_global (bfinfdpic_relocs_info (info),
+ 						  abfd, h,
+ 						  rel->r_addend, NO_INSERT);
+       else
+ 	picrel = bfinfdpic_relocs_info_for_local (bfinfdpic_relocs_info (info),
+ 						 abfd, r_symndx,
+ 						 rel->r_addend, NO_INSERT);
+ 
+       if (! picrel)
+ 	return FALSE;
+ 
+       *changed = TRUE;
+       dinfo = bfinfdpic_dynamic_got_plt_info (info);
+ 
+       _bfinfdpic_count_relocs_fixups (picrel, dinfo, TRUE);
+       if (ELF32_R_TYPE (rel->r_info) == R_BFIN_BYTE4_DATA)
+ 	picrel->relocs32--;
+       else /* we know (ELF32_R_TYPE (rel->r_info) == R_BFIN_FUNCDESC) */
+ 	picrel->relocsfd--;
+       _bfinfdpic_count_relocs_fixups (picrel, dinfo, FALSE);
+     }
+ 
+   return TRUE;
+ }
+ 
+ static bfd_boolean
+ bfinfdpic_elf_discard_info (bfd *ibfd,
+ 			   struct elf_reloc_cookie *cookie ATTRIBUTE_UNUSED,
+ 			   struct bfd_link_info *info)
+ {
+   bfd_boolean changed = FALSE;
+   asection *s;
+   bfd *obfd = NULL;
+ 
+   /* Account for relaxation of .eh_frame section.  */
+   for (s = ibfd->sections; s; s = s->next)
+     if (s->sec_info_type == ELF_INFO_TYPE_EH_FRAME)
+       {
+ 	if (!_bfinfdpic_check_discarded_relocs (ibfd, s, info, &changed))
+ 	  return FALSE;
+ 	obfd = s->output_section->owner;
+       }
+ 
+   if (changed)
+     {
+       struct _bfinfdpic_dynamic_got_plt_info gpinfo;
+ 
+       memset (&gpinfo, 0, sizeof (gpinfo));
+       memcpy (&gpinfo.g, bfinfdpic_dynamic_got_plt_info (info),
+ 	      sizeof (gpinfo.g));
+ 
+       /* Clear GOT and PLT assignments.  */
+       htab_traverse (bfinfdpic_relocs_info (info),
+ 		     _bfinfdpic_reset_got_plt_entries,
+ 		     NULL);
+ 
+       if (!_bfinfdpic_size_got_plt (obfd, &gpinfo))
+ 	return FALSE;
+     }
+ 
+   return TRUE;
+ }
+ 
  static bfd_boolean
  elf32_bfinfdpic_modify_program_headers (bfd *output_bfd,
  					struct bfd_link_info *info)
*************** struct bfd_elf_special_section const elf
*** 5678,5683 ****
--- 5858,5866 ----
  #define elf_backend_finish_dynamic_sections \
  		elf32_bfinfdpic_finish_dynamic_sections
  
+ #undef elf_backend_discard_info
+ #define elf_backend_discard_info \
+ 		bfinfdpic_elf_discard_info
  #undef elf_backend_can_make_relative_eh_frame
  #define elf_backend_can_make_relative_eh_frame \
  		bfinfdpic_elf_use_relative_eh_frame

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