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]

Re: MIPS multigot fixes for Linux


> OK to install?
> 

OK.

-eric

> Richard
> 
> 
> 2003-11-26  Daniel Jacobowitz  <drow@mvista.com>
>             Richard Sandiford  <rsandifo@redhat.com>
> 
> 	* elfxx-mips.c (mips_elf_set_global_got_offset): Don't set no_fn_stub.
> 	(mips_elf_set_no_stub): New function.
> 	(mips_elf_multi_got): Call it.
> 	(_bfd_mips_elf_finish_dynamic_symbol): If a relocation is needed for
> 	a secondary GOT entry, create an R_MIPS_32 or R_MIPS_64 entry and
> 	use mips_elf_create_dynamic_relocation to deal with any compatibility
> 	issues.  Store the adjusted addend in the GOT slot.
> 
> Index: bfd/elfxx-mips.c
> ===================================================================
> RCS file: /cvs/src/src/bfd/elfxx-mips.c,v
> retrieving revision 1.82
> diff -c -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.82 elfxx-mips.c
> *** bfd/elfxx-mips.c	14 Nov 2003 16:05:13 -0000	1.82
> --- bfd/elfxx-mips.c	26 Nov 2003 20:32:04 -0000
> *************** static int mips_elf_bfd2got_entry_eq PAR
> *** 471,476 ****
> --- 471,477 ----
>   static int mips_elf_make_got_per_bfd PARAMS ((void **, void *));
>   static int mips_elf_merge_gots PARAMS ((void **, void *));
>   static int mips_elf_set_global_got_offset PARAMS ((void**, void *));
> + static int mips_elf_set_no_stub PARAMS ((void **, void *));
>   static int mips_elf_resolve_final_got_entry PARAMS ((void**, void *));
>   static void mips_elf_resolve_final_got_entries
>     PARAMS ((struct mips_got_info *));
> *************** mips_elf_set_global_got_offset (entryp, 
> *** 2338,2347 ****
>   	  BFD_ASSERT (g->global_gotsym == NULL);
>   
>   	  entry->gotidx = arg->value * (long) g->assigned_gotno++;
> - 	  /* We can't do lazy update of GOT entries for
> - 	     non-primary GOTs since the PLT entries don't use the
> - 	     right offsets, so punt at it for now.  */
> - 	  entry->d.h->no_fn_stub = TRUE;
>   	  if (arg->info->shared
>   	      || (elf_hash_table (arg->info)->dynamic_sections_created
>   		  && ((entry->d.h->root.elf_link_hash_flags
> --- 2339,2344 ----
> *************** mips_elf_set_global_got_offset (entryp, 
> *** 2357,2362 ****
> --- 2354,2376 ----
>     return 1;
>   }
>   
> + /* Mark any global symbols referenced in the GOT we are iterating over
> +    as inelligible for lazy resolution stubs.  */
> + static int
> + mips_elf_set_no_stub (entryp, p)
> +      void **entryp;
> +      void *p ATTRIBUTE_UNUSED;
> + {
> +   struct mips_got_entry *entry = (struct mips_got_entry *)*entryp;
> + 
> +   if (entry->abfd != NULL
> +       && entry->symndx == -1
> +       && entry->d.h->root.dynindx != -1)
> +     entry->d.h->no_fn_stub = TRUE;
> + 
> +   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
> *************** mips_elf_multi_got (abfd, info, g, got, 
> *** 2624,2629 ****
> --- 2638,2648 ----
>         g->next = gg->next;
>         gg->next = g;
>         g = gn;
> + 
> +       /* Mark global symbols in every non-primary GOT as ineligible for
> + 	 stubs.  */
> +       if (g)
> + 	htab_traverse (g->got_entries, mips_elf_set_no_stub, NULL);
>       }
>     while (g);
>   
> *************** _bfd_mips_elf_finish_dynamic_symbol (out
> *** 6660,6669 ****
>     if (g->next && h->dynindx != -1)
>       {
>         struct mips_got_entry e, *p;
>         bfd_vma offset;
> -       bfd_vma value;
> -       Elf_Internal_Rela rel[3];
> -       bfd_vma addend = 0;
>   
>         gg = g;
>   
> --- 6679,6686 ----
>     if (g->next && h->dynindx != -1)
>       {
>         struct mips_got_entry e, *p;
> +       bfd_vma entry;
>         bfd_vma offset;
>   
>         gg = g;
>   
> *************** _bfd_mips_elf_finish_dynamic_symbol (out
> *** 6671,6688 ****
>         e.symndx = -1;
>         e.d.h = (struct mips_elf_link_hash_entry *)h;
>   
> -       if (info->shared
> - 	  || h->root.type == bfd_link_hash_undefined
> - 	  || h->root.type == bfd_link_hash_undefweak)
> - 	value = 0;
> -       else if (sym->st_value)
> - 	value = sym->st_value;
> -       else
> - 	value = h->root.u.def.value;
> - 
> -       memset (rel, 0, sizeof (rel));
> -       rel[0].r_info = ELF_R_INFO (output_bfd, 0, R_MIPS_REL32);
> - 
>         for (g = g->next; g->next != gg; g = g->next)
>   	{
>   	  if (g->got_entries
> --- 6688,6693 ----
> *************** _bfd_mips_elf_finish_dynamic_symbol (out
> *** 6690,6711 ****
>   							   &e)))
>   	    {
>   	      offset = p->gotidx;
> ! 	      rel[0].r_offset = rel[1].r_offset = rel[2].r_offset = offset;
> ! 
> ! 	      MIPS_ELF_PUT_WORD (output_bfd, value, sgot->contents + offset);
>   
> ! 	      if ((info->shared
> ! 		   || (elf_hash_table (info)->dynamic_sections_created
> ! 		       && p->d.h != NULL
> ! 		       && ((p->d.h->root.elf_link_hash_flags
> ! 			    & ELF_LINK_HASH_DEF_DYNAMIC) != 0)
> ! 		       && ((p->d.h->root.elf_link_hash_flags
> ! 			    & ELF_LINK_HASH_DEF_REGULAR) == 0)))
> ! 		  && ! (mips_elf_create_dynamic_relocation
> ! 			(output_bfd, info, rel,
> ! 			 e.d.h, NULL, value, &addend, sgot)))
> ! 		return FALSE;
> ! 	      BFD_ASSERT (addend == 0);
>   	    }
>   	}
>       }
> --- 6695,6731 ----
>   							   &e)))
>   	    {
>   	      offset = p->gotidx;
> ! 	      if (info->shared
> ! 		  || (elf_hash_table (info)->dynamic_sections_created
> ! 		      && p->d.h != NULL
> ! 		      && ((p->d.h->root.elf_link_hash_flags
> ! 			   & ELF_LINK_HASH_DEF_DYNAMIC) != 0)
> ! 		      && ((p->d.h->root.elf_link_hash_flags
> ! 			   & ELF_LINK_HASH_DEF_REGULAR) == 0)))
> ! 		{
> ! 		  /* Create an R_MIPS_REL32 relocation for this entry.  Due to
> ! 		     the various compatibility problems, it's easier to mock
> ! 		     up an R_MIPS_32 or R_MIPS_64 relocation and leave
> ! 		     mips_elf_create_dynamic_relocation to calculate the
> ! 		     appropriate addend.  */
> ! 		  Elf_Internal_Rela rel[3];
> ! 
> ! 		  memset (rel, 0, sizeof (rel));
> ! 		  if (ABI_64_P (output_bfd))
> ! 		    rel[0].r_info = ELF_R_INFO (output_bfd, 0, R_MIPS_64);
> ! 		  else
> ! 		    rel[0].r_info = ELF_R_INFO (output_bfd, 0, R_MIPS_32);
> ! 		  rel[0].r_offset = rel[1].r_offset = rel[2].r_offset = offset;
>   
> ! 		  entry = 0;
> ! 		  if (! (mips_elf_create_dynamic_relocation
> ! 			 (output_bfd, info, rel,
> ! 			  e.d.h, NULL, sym->st_value, &entry, sgot)))
> ! 		    return FALSE;
> ! 		}
> ! 	      else
> ! 		entry = sym->st_value;
> ! 	      MIPS_ELF_PUT_WORD (output_bfd, entry, sgot->contents + offset);
>   	    }
>   	}
>       }
-- 
Eric Christopher <echristo@redhat.com>


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