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: disable combreloc for NEWABI


On Oct 19, 2002, Alexandre Oliva <aoliva@redhat.com> wrote:

> Now that I realize sorting relocations is actually useful for n32 and
> n64, I'll try to fix the relocation-sorting code so as to cope with
> this situation.

Here's a patch that supersedes the previous one.  I'm not totally
happy with the hack of using allocating
struct elf_link_sort_rela rela[i2e*count] as if it were
struct {
  ...
  union { Elf_Internal_Rel rel[i2e]; Elf_Internal_Rela rela[i2e]; }
} rela[count] but this was the best I could come up with that wouldn't
increase the memory use significantly for the most common case of
i2e==1.

Also, it was obviously not necessary to turn the union members into
arrays, but I found this would draw further attention to the fact that
something unusual is going on with them.


While investigating the dynamic relocations, I realized I had failed
to compose REL32 with 64 when generating dynamic relocations for n64,
so I fixed this too.

I'm giving this patch a round of heavy testing by building a lot of
shared libraries for n32 and n64 right now.  Ok to install if it
passes?

Index: bfd/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	* elflink.h (struct elf_link_sort_rela): Turn rel and rela
	into arrays.
	(elf_link_sort_cmp1, elf_link_sort_cmp2): Adjust.
	(elf_link_sort_relocs): Likewise.  Take int_rels_per_ext_rel
	into account.
	* elfxx-mips.c (mips_elf_create_dynamic_relocation): Compose
	R_MIPS_REL32 with R_MIPS64 if ABI_64_P.

Index: bfd/elflink.h
===================================================================
RCS file: /cvs/src/src/bfd/elflink.h,v
retrieving revision 1.191
diff -u -p -r1.191 elflink.h
--- bfd/elflink.h 19 Oct 2002 17:13:58 -0000 1.191
+++ bfd/elflink.h 20 Oct 2002 03:30:43 -0000
@@ -4669,8 +4669,9 @@ struct elf_link_sort_rela
   enum elf_reloc_type_class type;
   union
   {
-    Elf_Internal_Rel rel;
-    Elf_Internal_Rela rela;
+    /* We use these as arrays of size int_rels_per_ext_rel.  */
+    Elf_Internal_Rel rel[1];
+    Elf_Internal_Rela rela[1];
   } u;
 };
 
@@ -4690,13 +4691,13 @@ elf_link_sort_cmp1 (A, B)
     return 1;
   if (relativea > relativeb)
     return -1;
-  if (ELF_R_SYM (a->u.rel.r_info) < ELF_R_SYM (b->u.rel.r_info))
+  if (ELF_R_SYM (a->u.rel->r_info) < ELF_R_SYM (b->u.rel->r_info))
     return -1;
-  if (ELF_R_SYM (a->u.rel.r_info) > ELF_R_SYM (b->u.rel.r_info))
+  if (ELF_R_SYM (a->u.rel->r_info) > ELF_R_SYM (b->u.rel->r_info))
     return 1;
-  if (a->u.rel.r_offset < b->u.rel.r_offset)
+  if (a->u.rel->r_offset < b->u.rel->r_offset)
     return -1;
-  if (a->u.rel.r_offset > b->u.rel.r_offset)
+  if (a->u.rel->r_offset > b->u.rel->r_offset)
     return 1;
   return 0;
 }
@@ -4720,9 +4721,9 @@ elf_link_sort_cmp2 (A, B)
     return -1;
   if (copya > copyb)
     return 1;
-  if (a->u.rel.r_offset < b->u.rel.r_offset)
+  if (a->u.rel->r_offset < b->u.rel->r_offset)
     return -1;
-  if (a->u.rel.r_offset > b->u.rel.r_offset)
+  if (a->u.rel->r_offset > b->u.rel->r_offset)
     return 1;
   return 0;
 }
@@ -4740,6 +4741,7 @@ elf_link_sort_relocs (abfd, info, psec)
   size_t i, j, ret;
   struct elf_link_sort_rela *rela;
   struct elf_backend_data *bed = get_elf_backend_data (abfd);
+  int i2e = bed->s->int_rels_per_ext_rel;
 
   reldyn = bfd_get_section_by_name (abfd, ".rela.dyn");
   if (reldyn == NULL || reldyn->_raw_size == 0)
@@ -4763,7 +4765,23 @@ elf_link_sort_relocs (abfd, info, psec)
   if (size != reldyn->_raw_size)
     return 0;
 
-  rela = (struct elf_link_sort_rela *) bfd_zmalloc (sizeof (*rela) * count);
+  /* We waste some memory here when N = i2e is greater than 1, since
+     we allocate space for N * sizeof (*rela) where sizeof (*rela) +
+     (N - 1) * sizeof (Elf_Internal_Rel/Rela) would do.  Also, we use
+     rela[k] only when k is a multiple of N, and then we index the
+     array within the union, such that rela[k].u.rel[i], i < N, is the
+     (i+1)th internal relocation corresponding to the (k/N)th external
+     relocation.  This is done such that the relocation swap-in and
+     swap-out functions can gen pointers to arrays of internal
+     relocations that form a single external relocation.
+
+     If C permitted arrays of structures with dynamic sizes, we could
+     do better, but trying to avoid wasting space at the end of the
+     chunk from rela[k] to rela[k+N-1] would require us to allocate a
+     separate array of pointers and since most ports have N == 1, this
+     would be more wasteful.  */
+  rela = (struct elf_link_sort_rela *) bfd_zmalloc
+    (sizeof (*rela) * count * i2e);
   if (rela == NULL)
     {
       (*info->callbacks->warning)
@@ -4784,15 +4802,16 @@ elf_link_sort_relocs (abfd, info, psec)
 
 	    erel = (Elf_External_Rel *) o->contents;
 	    erelend = (Elf_External_Rel *) (o->contents + o->_raw_size);
-	    s = rela + o->output_offset / sizeof (Elf_External_Rel);
-	    for (; erel < erelend; erel++, s++)
+	    s = rela + (o->output_offset / sizeof (Elf_External_Rel) * i2e);
+	    for (; erel < erelend; erel++, s += i2e)
 	      {
 		if (bed->s->swap_reloc_in)
-		  (*bed->s->swap_reloc_in) (abfd, (bfd_byte *) erel, &s->u.rel);
+		  (*bed->s->swap_reloc_in) (abfd, (bfd_byte *) erel,
+					    s->u.rel);
 		else
-		  elf_swap_reloc_in (abfd, erel, &s->u.rel);
+		  elf_swap_reloc_in (abfd, erel, s->u.rel);
 
-		s->type = (*bed->elf_backend_reloc_type_class) (&s->u.rela);
+		s->type = (*bed->elf_backend_reloc_type_class) (s->u.rela);
 	      }
 	  }
 	else
@@ -4802,30 +4821,34 @@ elf_link_sort_relocs (abfd, info, psec)
 
 	    erela = (Elf_External_Rela *) o->contents;
 	    erelaend = (Elf_External_Rela *) (o->contents + o->_raw_size);
-	    s = rela + o->output_offset / sizeof (Elf_External_Rela);
-	    for (; erela < erelaend; erela++, s++)
+	    s = rela + (o->output_offset / sizeof (Elf_External_Rela) * i2e);
+	    for (; erela < erelaend; erela++, s += i2e)
 	      {
 		if (bed->s->swap_reloca_in)
 		  (*bed->s->swap_reloca_in) (dynobj, (bfd_byte *) erela,
-					     &s->u.rela);
+					     s->u.rela);
 		else
-		  elf_swap_reloca_in (dynobj, erela, &s->u.rela);
+		  elf_swap_reloca_in (dynobj, erela, s->u.rela);
 
-		s->type = (*bed->elf_backend_reloc_type_class) (&s->u.rela);
+		s->type = (*bed->elf_backend_reloc_type_class) (s->u.rela);
 	      }
 	  }
       }
 
-  qsort (rela, (size_t) count, sizeof (*rela), elf_link_sort_cmp1);
-  for (ret = 0; ret < count && rela[ret].type == reloc_class_relative; ret++)
+  qsort (rela, (size_t) count, sizeof (*rela) * i2e, elf_link_sort_cmp1);
+  for (ret = 0; ret < count * i2e && rela[ret].type == reloc_class_relative;
+       ret += i2e)
     ;
-  for (i = ret, j = ret; i < count; i++)
+  for (i = ret, j = ret; i < count * i2e; i += i2e)
     {
-      if (ELF_R_SYM (rela[i].u.rel.r_info) != ELF_R_SYM (rela[j].u.rel.r_info))
+      if (ELF_R_SYM (rela[i].u.rel->r_info)
+	  != ELF_R_SYM (rela[j].u.rel->r_info))
 	j = i;
-      rela[i].offset = rela[j].u.rel.r_offset;
+      rela[i].offset = rela[j].u.rel->r_offset;
     }
-  qsort (rela + ret, (size_t) count - ret, sizeof (*rela), elf_link_sort_cmp2);
+  ret /= i2e;
+  qsort (rela + ret, (size_t) count - ret,
+	 sizeof (*rela) * i2e, elf_link_sort_cmp2);
 
   for (o = dynobj->sections; o != NULL; o = o->next)
     if ((o->flags & (SEC_HAS_CONTENTS|SEC_LINKER_CREATED))
@@ -4839,14 +4862,14 @@ elf_link_sort_relocs (abfd, info, psec)
 
 	    erel = (Elf_External_Rel *) o->contents;
 	    erelend = (Elf_External_Rel *) (o->contents + o->_raw_size);
-	    s = rela + o->output_offset / sizeof (Elf_External_Rel);
-	    for (; erel < erelend; erel++, s++)
+	    s = rela + (o->output_offset / sizeof (Elf_External_Rel) * i2e);
+	    for (; erel < erelend; erel++, s += i2e)
 	      {
 		if (bed->s->swap_reloc_out)
-		  (*bed->s->swap_reloc_out) (abfd, &s->u.rel,
+		  (*bed->s->swap_reloc_out) (abfd, s->u.rel,
 					     (bfd_byte *) erel);
 		else
-		  elf_swap_reloc_out (abfd, &s->u.rel, erel);
+		  elf_swap_reloc_out (abfd, s->u.rel, erel);
 	      }
 	  }
 	else
@@ -4856,14 +4879,14 @@ elf_link_sort_relocs (abfd, info, psec)
 
 	    erela = (Elf_External_Rela *) o->contents;
 	    erelaend = (Elf_External_Rela *) (o->contents + o->_raw_size);
-	    s = rela + o->output_offset / sizeof (Elf_External_Rela);
-	    for (; erela < erelaend; erela++, s++)
+	    s = rela + (o->output_offset / sizeof (Elf_External_Rela) * i2e);
+	    for (; erela < erelaend; erela++, s += i2e)
 	      {
 		if (bed->s->swap_reloca_out)
-		  (*bed->s->swap_reloca_out) (dynobj, &s->u.rela,
+		  (*bed->s->swap_reloca_out) (dynobj, s->u.rela,
 					      (bfd_byte *) erela);
 		else
-		  elf_swap_reloca_out (dynobj, &s->u.rela, erela);
+		  elf_swap_reloca_out (dynobj, s->u.rela, erela);
 	      }
 	  }
       }
Index: bfd/elfxx-mips.c
===================================================================
RCS file: /cvs/src/src/bfd/elfxx-mips.c,v
retrieving revision 1.27
diff -u -p -r1.27 elfxx-mips.c
--- bfd/elfxx-mips.c 13 Oct 2002 21:22:31 -0000 1.27
+++ bfd/elfxx-mips.c 20 Oct 2002 03:30:48 -0000
@@ -2954,7 +2954,9 @@ mips_elf_create_dynamic_relocation (outp
       outrel[0].r_info = ELF_R_INFO (output_bfd, (unsigned long) indx,
 				     R_MIPS_REL32);
       outrel[1].r_info = ELF_R_INFO (output_bfd, (unsigned long) 0,
-				     R_MIPS_NONE);
+				     ABI_64_P (output_bfd)
+				     ? R_MIPS_64
+				     : R_MIPS_NONE);
       outrel[2].r_info = ELF_R_INFO (output_bfd, (unsigned long) 0,
 				     R_MIPS_NONE);
 
-- 
Alexandre Oliva   Enjoy Guarana', see http://www.ic.unicamp.br/~oliva/
Red Hat GCC Developer                 aoliva@{redhat.com, gcc.gnu.org}
CS PhD student at IC-Unicamp        oliva@{lsd.ic.unicamp.br, gnu.org}
Free Software Evangelist                Professional serial bug killer

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