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


Richard Sandiford <rsandifo@redhat.com> writes:
> Just thinking... maybe the _bfd_mips_elf_finish_dynamic_symbol code
> could look like this?  Then we wouldn't have any pesky SGI_COMPAT tests.
> Haven't tested this at all though.

Now I have, and it doesn't work.  create_dynamic_relocation quite rightly
does nothing with existing R_MIPS_REL32 relocations.  If we want to reuse
the compatibility logic, we should be passing it an R_MIPS_32 or R_MIPS_64
entry instead.

Updated patch below.  Tested:

  - by bootstrapping & regression testing on mips-sgi-irix6.5 (n32 & n64)

  - against the binutils, gas & ld testsuites, targets: mips64-linux-gnu,
    mips64el-linux-gnu and mips-sgi-irix6.5

  - mocking up an executable multi-got testcase and verifying that it works
    for all three ABIs on mips64-linux-gnu

  - running the same test case on mips-sgi-irix6.5 and verifying that the
    test now passes for n32 & n64 (it failed before)

The test case causes ld to segfault for o32 on mips-sgi-irix6.5,
but for unrelated reasons.  Same thing happened before the patch.

OK to install?

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);
  	    }
  	}
      }


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