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]

[PATCH] Support -z combreloc in binutils


Hi!

This patch adds support for ld -z combreloc, which instead of creating usual
zillions of .rel* resp. .rela* sections just creates one big (in addition to
.rel.plt/.rela.plt or PLT-like rela section) .rel.dyn resp. .rela.dyn
section with all dynamic relocations.
This section is sorted if possible by increasing r_offset, with the
exception that if there are multiple relocs against the same symbol, they
are grouped together (which allows the dynamic linker to have a single entry
cache for symbol lookups).
In addition to this, it sets DT_RELCOUNT resp. DT_RELACOUNT dynamic tag in
the way Solaris linker uses it (and compatible to the Solaris way, which is
IMHO broken - R_*_RELATIVE symbols come last, not first), so that if a
library has l_addr 0, all the R_*_RELATIVE relocs can be skipped for free.
I tried to implement this so that only minimal changes in elf backends are
needed (each backend just needs to provide function which categorizes reloc
types: relative, plt, copy relocs or other relocs).
Also, it reserves a few entries for use in prelinking, but user can disable
this (this is necessary for DT_REL*COUNT too, since I don't want to create
it if no relative relocs are found).

2001-08-15  Jakub Jelinek  <jakub@redhat.com>

	* elf-bfd.h (enum elf_reloc_type_class): New.
	(struct elf_backend_data): Add elf_backend_reloc_type_class.
	(_bfd_elf_reloc_type_class): New.
	* elfxx-target.h (elf_backend_reloc_type_class): Define.
	(elfNN_bed): Add elf_backend_reloc_type_class.
	* elf.c (_bfd_elf_reloc_type_class): New.
	* elf32-i386.c (elf_i386_reloc_type_class): New.
	(elf_backend_reloc_type_class): Define.
	* elflink.h (size_dynamic_sections): Add spare DT_NULL tags.
	(struct elf_link_sort_rela): New.
	(elf_link_sort_cmp1, elf_link_sort_cmp2, elf_link_sort_relocs): New.
	(elf_bfd_final_link): Call elf_link_sort_relocs.
	Convert one spare DT_NULL into DT_RELCOUNT resp. DT_RELACOUNT if
	necessary.

	* bfdlink.h (struct bfd_link_info): Add combreloc and
	spare_dynamic_tags fields.

	* emultempl/elf32.em (place_orphan): Place orphan .rel* sections
	into .rel.dyn resp. .rela.dyn if combreloc.
	(get_script): If .x linker script is equal to .xn, only put it
	once into the binary.
	Add .xc and .xsc scripts.
	(parse_args): Handle -z combreloc and -z nocombreloc.
	* scripttempl/elf.sc (.rela.sbss): Fix a typo.
	For .xc and .xsc scripts put all .rel* or .rela* input sections
	but .rel*.plt and PLT-like sections into .rel.dyn resp. .rela.dyn.
	* genscripts.sh (GENERATE_COMBRELOC_SCRIPT): Set if SCRIPT_NAME
	is elf.
	Strip trailing whitespace from script.
	Generate .xc and .xsc scripts if requested.
	* ldmain.c (main): Initialize link_info.combreloc and
	link_info.spare_dynamic_tags.
	* lexsup.c (OPTION_SPARE_DYNAMIC_TAGS): Define.
	(ld_options): Add --spare-dynamic-tags option.
	(parse_args): Likewise.

--- bfd/elf-bfd.h.jj	Mon Aug 13 13:05:23 2001
+++ bfd/elf-bfd.h	Wed Aug 15 17:16:55 2001
@@ -331,6 +331,14 @@ struct elf_size_info {
 	 ? (elf_symbol_type *) (S) \
 	 : 0)
 
+enum elf_reloc_type_class
+{
+  reloc_class_normal,
+  reloc_class_relative,
+  reloc_class_plt,
+  reloc_class_copy
+};
+
 struct elf_backend_data
 {
   /* The architecture for this backend.  */
@@ -636,10 +644,13 @@ struct elf_backend_data
      note is found in a core file. */
   boolean (*elf_backend_grok_psinfo) PARAMS ((bfd *, Elf_Internal_Note *));
 
-    /* Functions to print VMAs.  Special code to handle 64 bit ELF files.  */
+  /* Functions to print VMAs.  Special code to handle 64 bit ELF files.  */
   void (* elf_backend_sprintf_vma) PARAMS ((bfd *, char *, bfd_vma));
   void (* elf_backend_fprintf_vma) PARAMS ((bfd *, PTR, bfd_vma));
 
+  /* This function returns class of a reloc type.  */
+  enum elf_reloc_type_class (* elf_backend_reloc_type_class) PARAMS ((int));
+
   /* The swapping table to use when dealing with ECOFF information.
      Used for the MIPS ELF .mdebug section.  */
   const struct ecoff_debug_swap *elf_backend_ecoff_debug_swap;
@@ -1005,6 +1016,8 @@ extern void bfd_elf_print_symbol PARAMS 
 
 extern void _bfd_elf_sprintf_vma PARAMS ((bfd *, char *, bfd_vma));
 extern void _bfd_elf_fprintf_vma PARAMS ((bfd *, PTR, bfd_vma));
+
+extern enum elf_reloc_type_class _bfd_elf_reloc_type_class PARAMS ((int));
 
 extern unsigned long bfd_elf_hash PARAMS ((const char *));
 
--- bfd/elfxx-target.h.jj	Mon Aug 13 13:05:23 2001
+++ bfd/elfxx-target.h	Wed Aug 15 17:16:55 2001
@@ -344,6 +344,9 @@ Foundation, Inc., 59 Temple Place - Suit
 #ifndef elf_backend_fprintf_vma
 #define elf_backend_fprintf_vma			_bfd_elf_fprintf_vma
 #endif
+#ifndef elf_backend_reloc_type_class
+#define elf_backend_reloc_type_class		_bfd_elf_reloc_type_class
+#endif
 
 /* Previously, backends could only use SHT_REL or SHT_RELA relocation
    sections, but not both.  They defined USE_REL to indicate SHT_REL
@@ -431,6 +434,7 @@ static CONST struct elf_backend_data elf
   elf_backend_grok_psinfo,
   elf_backend_sprintf_vma,
   elf_backend_fprintf_vma,
+  elf_backend_reloc_type_class,
   elf_backend_ecoff_debug_swap,
   ELF_MACHINE_ALT1,
   ELF_MACHINE_ALT2,
--- bfd/elf.c.jj	Mon Aug 13 13:05:23 2001
+++ bfd/elf.c	Wed Aug 15 17:16:55 2001
@@ -6057,3 +6057,10 @@ _bfd_elf_fprintf_vma (abfd, stream, valu
   fprintf_vma ((FILE *) stream, value);
 #endif
 }
+
+enum elf_reloc_type_class
+_bfd_elf_reloc_type_class (type)
+     int type;
+{
+  return reloc_class_normal;
+}
--- bfd/elf32-i386.c.jj	Mon Aug 13 13:05:23 2001
+++ bfd/elf32-i386.c	Wed Aug 15 17:16:55 2001
@@ -63,6 +63,7 @@ static boolean elf_i386_finish_dynamic_s
   PARAMS ((bfd *, struct bfd_link_info *));
 static boolean elf_i386_fake_sections
   PARAMS ((bfd *, Elf32_Internal_Shdr *, asection *));
+static enum elf_reloc_type_class elf_i386_reloc_type_class PARAMS ((int));
 
 #define USE_REL	1		/* 386 uses REL relocations instead of RELA */
 
@@ -2215,6 +2216,22 @@ elf_i386_fake_sections (abfd, hdr, sec)
   return true;
 }
 
+static enum elf_reloc_type_class
+elf_i386_reloc_type_class (type)
+     int type;
+{
+  switch (type)
+    {
+    case R_386_RELATIVE:
+      return reloc_class_relative;
+    case R_386_JUMP_SLOT:
+      return reloc_class_plt;
+    case R_386_COPY:
+      return reloc_class_copy;
+    default:
+      return reloc_class_normal;
+    }
+}
 
 #define TARGET_LITTLE_SYM		bfd_elf32_i386_vec
 #define TARGET_LITTLE_NAME		"elf32-i386"
@@ -2246,5 +2263,6 @@ elf_i386_fake_sections (abfd, hdr, sec)
 #define elf_backend_relocate_section	      elf_i386_relocate_section
 #define elf_backend_size_dynamic_sections     elf_i386_size_dynamic_sections
 #define elf_backend_fake_sections	      elf_i386_fake_sections
+#define elf_backend_reloc_type_class	      elf_i386_reloc_type_class
 
 #include "elf32-target.h"
--- bfd/elflink.h.jj	Mon Aug 13 13:05:23 2001
+++ bfd/elflink.h	Wed Aug 15 17:16:55 2001
@@ -67,6 +67,12 @@ static boolean elf_link_size_reloc_secti
 static void elf_link_adjust_relocs
   PARAMS ((bfd *, Elf_Internal_Shdr *, unsigned int,
 	   struct elf_link_hash_entry **));
+static int elf_link_sort_cmp1
+  PARAMS ((const void *, const void *));
+static int elf_link_sort_cmp2
+  PARAMS ((const void *, const void *));
+static size_t elf_link_sort_relocs
+  PARAMS ((bfd *, struct bfd_link_info *, asection **));
 
 /* Given an ELF BFD, add symbols to the global hash table as
    appropriate.  */
@@ -3065,6 +3071,7 @@ NAME(bfd_elf,size_dynamic_sections) (out
       asection *s;
       size_t bucketcount = 0;
       size_t hash_entry_size;
+      unsigned int dtagcount;
 
       /* Set up the version definition section.  */
       s = bfd_get_section_by_name (dynobj, ".gnu.version_d");
@@ -3439,8 +3446,9 @@ NAME(bfd_elf,size_dynamic_sections) (out
       BFD_ASSERT (s != NULL);
       s->_raw_size = _bfd_stringtab_size (elf_hash_table (info)->dynstr);
 
-      if (! elf_add_dynamic_entry (info, DT_NULL, 0))
-	return false;
+      for (dtagcount = 0; dtagcount <= info->spare_dynamic_tags; ++dtagcount)
+	if (! elf_add_dynamic_entry (info, DT_NULL, 0))
+	  return false;
     }
 
   return true;
@@ -4270,6 +4278,212 @@ elf_link_adjust_relocs (abfd, rel_hdr, c
   free (irela);
 }
 
+struct elf_link_sort_rela
+{
+  bfd_vma offset;
+  enum elf_reloc_type_class type;
+  union
+    {
+      Elf_Internal_Rel rel;
+      Elf_Internal_Rela rela;
+    } u;
+};
+
+static int
+elf_link_sort_cmp1 (A, B)
+     const PTR A;
+     const PTR B;
+{
+  struct elf_link_sort_rela *a = (struct elf_link_sort_rela *)A;
+  struct elf_link_sort_rela *b = (struct elf_link_sort_rela *)B;
+  int relativea, relativeb;
+
+  relativea = a->type == reloc_class_relative;
+  relativeb = b->type == reloc_class_relative;
+
+  if (relativea < relativeb)
+    return -1;
+  if (relativea > relativeb)
+    return 1;
+  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))
+    return 1;
+  if (a->u.rel.r_offset < b->u.rel.r_offset)
+    return -1;
+  if (a->u.rel.r_offset > b->u.rel.r_offset)
+    return 1;
+  return 0;
+}
+
+static int
+elf_link_sort_cmp2 (A, B)
+     const PTR A;
+     const PTR B;
+{
+  struct elf_link_sort_rela *a = (struct elf_link_sort_rela *)A;
+  struct elf_link_sort_rela *b = (struct elf_link_sort_rela *)B;
+  int copya, copyb;
+
+  if (a->offset < b->offset)
+    return -1;
+  if (a->offset > b->offset)
+    return 1;
+  copya = a->type == reloc_class_copy;
+  copyb = b->type == reloc_class_copy;
+  if (copya < copyb)
+    return -1;
+  if (copya > copyb)
+    return 1;
+  if (a->u.rel.r_offset < b->u.rel.r_offset)
+    return -1;
+  if (a->u.rel.r_offset > b->u.rel.r_offset)
+    return 1;
+  return 0;
+}
+
+static size_t
+elf_link_sort_relocs (abfd, info, psec)
+     bfd *abfd;
+     struct bfd_link_info *info;
+     asection **psec;
+{
+  bfd *dynobj = elf_hash_table (info)->dynobj;
+  asection *reldyn, *o;
+  boolean rel = false;
+  size_t count, size, i, j, ret;
+  struct elf_link_sort_rela *rela;
+  struct elf_backend_data *bed = get_elf_backend_data (abfd);
+
+  reldyn = bfd_get_section_by_name (abfd, ".rela.dyn");
+  if (reldyn == NULL || reldyn->_raw_size == 0)
+    {
+      reldyn = bfd_get_section_by_name (abfd, ".rel.dyn");
+      if (reldyn == NULL || reldyn->_raw_size == 0)
+	return 0;
+      rel = true;
+      count = reldyn->_raw_size / sizeof (Elf_External_Rel);
+    }
+  else
+    count = reldyn->_raw_size / sizeof (Elf_External_Rela);
+
+  size = 0;
+  for (o = dynobj->sections; o != NULL; o = o->next)
+    if ((o->flags & (SEC_HAS_CONTENTS|SEC_LINKER_CREATED))
+	== (SEC_HAS_CONTENTS|SEC_LINKER_CREATED)
+	&& o->output_section == reldyn)
+      size += o->_raw_size;
+
+  if (size != reldyn->_raw_size)
+    return 0;
+
+  rela = (struct elf_link_sort_rela *) calloc (sizeof (*rela), count);
+  if (rela == NULL)
+    {
+      (*info->callbacks->warning)
+	(info, _("Not enough memory to sort relocations"), 0, abfd, 0, 0);
+      return 0;
+    }
+
+  for (o = dynobj->sections; o != NULL; o = o->next)
+    if ((o->flags & (SEC_HAS_CONTENTS|SEC_LINKER_CREATED))
+	== (SEC_HAS_CONTENTS|SEC_LINKER_CREATED)
+	&& o->output_section == reldyn)
+      {
+	if (rel)
+	  {
+	    Elf_External_Rel *erel, *erelend;
+	    struct elf_link_sort_rela *s;
+
+	    erel = (Elf_External_Rel *) o->contents;
+	    erelend = (Elf_External_Rel *) ((PTR) o->contents + o->_raw_size);
+	    s = rela + o->output_offset / sizeof (Elf_External_Rel);
+	    for (; erel < erelend; erel++, s++)
+	      {
+		if (bed->s->swap_reloc_in)
+		  (*bed->s->swap_reloc_in) (abfd, (bfd_byte *) erel, &s->u.rel);
+		else
+		  elf_swap_reloc_in (abfd, erel, &s->u.rel);
+
+		s->type = (*bed->elf_backend_reloc_type_class)
+			    (ELF_R_TYPE (s->u.rel.r_info));
+	      }	    
+	  }
+	else
+	  {
+	    Elf_External_Rela *erela, *erelaend;
+	    struct elf_link_sort_rela *s;
+
+	    erela = (Elf_External_Rela *) o->contents;
+	    erelaend = (Elf_External_Rela *) ((PTR) o->contents + o->_raw_size);
+	    s = rela + o->output_offset / sizeof (Elf_External_Rela);
+	    for (; erela < erelaend; erela++, s++)
+	      {
+		if (bed->s->swap_reloca_in)
+		  (*bed->s->swap_reloca_in) (dynobj, (bfd_byte *) erela, &s->u.rela);
+		else
+		  elf_swap_reloca_in (dynobj, erela, &s->u.rela);
+
+		s->type = (*bed->elf_backend_reloc_type_class)
+			    (ELF_R_TYPE (s->u.rel.r_info));
+	      }	    
+	  }
+      }
+
+  qsort (rela, count, sizeof (*rela), elf_link_sort_cmp1);
+  for (i = 0, j = 0; i < count && rela[i].type != reloc_class_relative; i++)
+    {
+      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;
+    }
+  ret = count - i;
+  qsort (rela, i, sizeof (*rela), elf_link_sort_cmp2);
+  
+  for (o = dynobj->sections; o != NULL; o = o->next)
+    if ((o->flags & (SEC_HAS_CONTENTS|SEC_LINKER_CREATED))
+	== (SEC_HAS_CONTENTS|SEC_LINKER_CREATED)
+	&& o->output_section == reldyn)
+      {
+	if (rel)
+	  {
+	    Elf_External_Rel *erel, *erelend;
+	    struct elf_link_sort_rela *s;
+
+	    erel = (Elf_External_Rel *) o->contents;
+	    erelend = (Elf_External_Rel *) ((PTR) o->contents + o->_raw_size);
+	    s = rela + o->output_offset / sizeof (Elf_External_Rel);
+	    for (; erel < erelend; erel++, s++)
+	      {
+		if (bed->s->swap_reloc_out)
+		  (*bed->s->swap_reloc_out) (abfd, &s->u.rel, (bfd_byte *) erel);
+		else
+		  elf_swap_reloc_out (abfd, &s->u.rel, erel);
+	      }
+	  }
+	else
+	  {
+	    Elf_External_Rela *erela, *erelaend;
+	    struct elf_link_sort_rela *s;
+
+	    erela = (Elf_External_Rela *) o->contents;
+	    erelaend = (Elf_External_Rela *) ((PTR) o->contents + o->_raw_size);
+	    s = rela + o->output_offset / sizeof (Elf_External_Rela);
+	    for (; erela < erelaend; erela++, s++)
+	      {
+		if (bed->s->swap_reloca_out)
+		  (*bed->s->swap_reloca_out) (dynobj, &s->u.rela, (bfd_byte *) erela);
+		else
+		  elf_swap_reloca_out (dynobj, &s->u.rela, erela);
+	      }	    
+	  }
+      }
+
+  free (rela);
+  *psec = reldyn;
+  return ret;
+}
+
 /* Do the final step of an ELF link.  */
 
 boolean
@@ -4296,6 +4510,8 @@ elf_bfd_final_link (abfd, info)
   struct elf_backend_data *bed = get_elf_backend_data (abfd);
   struct elf_outext_info eoinfo;
   boolean merged;
+  size_t relativecount = 0;
+  asection *reldyn = 0;
 
   if (info->shared)
     abfd->flags |= DYNAMIC;
@@ -4866,6 +5082,9 @@ elf_bfd_final_link (abfd, info)
       o->reloc_count = 0;
     }
 
+  if (dynamic && info->combreloc && dynobj != NULL)
+    relativecount = elf_link_sort_relocs (abfd, info, &reldyn);
+
   /* If we are linking against a dynamic object, or generating a
      shared library, finish up the dynamic linking information.  */
   if (dynamic)
@@ -4889,6 +5108,23 @@ elf_bfd_final_link (abfd, info)
 	  switch (dyn.d_tag)
 	    {
 	    default:
+	      break;
+	    case DT_NULL:
+	      if (relativecount > 0 && dyncon + 1 < dynconend)
+		{
+		  switch (elf_section_data (reldyn)->this_hdr.sh_type)
+		    {
+		    case SHT_REL: dyn.d_tag = DT_RELCOUNT; break;
+		    case SHT_RELA: dyn.d_tag = DT_RELACOUNT; break;
+		    default: break;
+		    }
+		  if (dyn.d_tag != DT_NULL)
+		    {
+		      dyn.d_un.d_val = relativecount;
+		      elf_swap_dyn_out (dynobj, &dyn, dyncon);
+		      relativecount = 0;
+		    }
+		}
 	      break;
 	    case DT_INIT:
 	      name = info->init_function;
--- include/bfdlink.h.jj	Mon Aug 13 13:05:43 2001
+++ include/bfdlink.h	Wed Aug 15 17:16:55 2001
@@ -278,6 +278,13 @@ struct bfd_link_info
   /* true if auto-import thunks for DATA items in pei386 DLLs 
      should be generated/linked against.  */
   boolean pei386_auto_import;
+
+  /* true if non-PLT relocs should be merged into one reloc section
+     and sorted so that relocs against the same symbol come together.  */
+  boolean combreloc;
+
+  /* How many spare .dynamic DT_NULL entries should be added?  */
+  int spare_dynamic_tags;
 };
 
 /* This structures holds a set of callback functions.  These are
--- ld/emultempl/elf32.em.jj	Wed Aug 15 17:16:15 2001
+++ ld/emultempl/elf32.em	Wed Aug 15 17:17:30 2001
@@ -1135,7 +1135,25 @@ gld${EMULATION_NAME}_place_orphan (file,
   else if (strncmp (secname, ".rel", 4) == 0
 	   && (hold_rel.os != NULL
 	       || (hold_rel.os = output_rel_find ()) != NULL))
-    place = &hold_rel;
+    {
+      if (! link_info.relocateable && link_info.combreloc)
+	{
+	  if (strncmp (secname, ".rela", 5) == 0)
+	    os = lang_output_section_find (".rela.dyn");
+	  else
+	    os = lang_output_section_find (".rel.dyn");
+
+	  if (os != NULL
+	      && os->bfd_section != NULL
+	      && ((s->flags ^ os->bfd_section->flags)
+		  & (SEC_LOAD | SEC_ALLOC)) == 0)
+	    {
+	      lang_add_section (&os->children, s, os, file);
+	      return true;
+	    }
+	}
+      place = &hold_rel;
+    }
   else if ((s->flags & (SEC_CODE | SEC_READONLY)) == SEC_READONLY
 	   && HAVE_SECTION (hold_rodata, ".rodata"))
     place = &hold_rodata;
@@ -1332,14 +1350,18 @@ echo '  ; else if (link_info.relocateabl
 sed $sc ldscripts/${EMULATION_NAME}.xr                     >> e${EMULATION_NAME}.c
 echo '  ; else if (!config.text_read_only) return'         >> e${EMULATION_NAME}.c
 sed $sc ldscripts/${EMULATION_NAME}.xbn                    >> e${EMULATION_NAME}.c
+if ! cmp -s ldscripts/${EMULATION_NAME}.x ldscripts/${EMULATION_NAME}.xn; then
 echo '  ; else if (!config.magic_demand_paged) return'     >> e${EMULATION_NAME}.c
 sed $sc ldscripts/${EMULATION_NAME}.xn                     >> e${EMULATION_NAME}.c
-
+fi
 if test -n "$GENERATE_SHLIB_SCRIPT" ; then
+echo '  ; else if (link_info.shared && link_info.combreloc) return' >> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xsc                    >> e${EMULATION_NAME}.c
 echo '  ; else if (link_info.shared) return'		   >> e${EMULATION_NAME}.c
 sed $sc ldscripts/${EMULATION_NAME}.xs                     >> e${EMULATION_NAME}.c
 fi
-
+echo '  ; else if (link_info.combreloc) return'            >> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xc                     >> e${EMULATION_NAME}.c
 echo '  ; else return'                                     >> e${EMULATION_NAME}.c
 sed $sc ldscripts/${EMULATION_NAME}.x                      >> e${EMULATION_NAME}.c
 echo '; }'                                                 >> e${EMULATION_NAME}.c
@@ -1492,6 +1514,10 @@ cat >>e${EMULATION_NAME}.c <<EOF
 	}
       else if (strcmp (optarg, "defs") == 0)
 	link_info.no_undefined = true;
+      else if (strcmp (optarg, "combreloc") == 0)
+	link_info.combreloc = true;
+      else if (strcmp (optarg, "nocombreloc") == 0)
+	link_info.combreloc = false;
       /* What about the other Solaris -z options? FIXME.  */
       break;
 EOF
--- ld/scripttempl/elf.sc.jj	Mon Aug 13 13:05:58 2001
+++ ld/scripttempl/elf.sc	Wed Aug 15 17:16:55 2001
@@ -145,6 +145,13 @@ SECTIONS
   .gnu.version_d ${RELOCATING-0} : { *(.gnu.version_d)	}
   .gnu.version_r ${RELOCATING-0} : { *(.gnu.version_r)	}
 
+EOF
+if [ "x$COMBRELOC" = x ]; then
+  COMBRELOCCAT=cat
+else
+  COMBRELOCCAT="cat > $COMBRELOC"
+fi
+eval $COMBRELOCCAT <<EOF
   .rel.init    ${RELOCATING-0} : { *(.rel.init)	}
   .rela.init   ${RELOCATING-0} : { *(.rela.init)	}
   .rel.text    ${RELOCATING-0} :
@@ -215,7 +222,7 @@ SECTIONS
     {
       *(.rela.sbss)
       ${RELOCATING+*(.rela.sbss.*)}
-      ${RELOCATING+*(.rel.gnu.linkonce.sb.*)}
+      ${RELOCATING+*(.rela.gnu.linkonce.sb.*)}
     }
   .rel.sdata2  ${RELOCATING-0} : 
     { 
@@ -253,6 +260,24 @@ SECTIONS
       ${RELOCATING+*(.rela.bss.*)}
       ${RELOCATING+*(.rela.gnu.linkonce.b.*)}
     }
+EOF
+if [ -n "$COMBRELOC" ]; then
+cat <<EOF
+  .rel.dyn	 :
+    {
+EOF
+sed -e '/^[ 	]*[{}][ 	]*$/d;/:[ 	]*$/d;/\.rela\./d;s/^.*: { *\(.*\)}$/      \1/' $COMBRELOC
+cat <<EOF
+    }
+  .rela.dyn	 :
+    {
+EOF
+sed -e '/^[ 	]*[{}][ 	]*$/d;/:[ 	]*$/d;/\.rel\./d;s/^.*: { *\(.*\)}/      \1/' $COMBRELOC
+cat <<EOF
+    }
+EOF
+fi
+cat <<EOF
   .rel.plt     ${RELOCATING-0} : { *(.rel.plt)		}
   .rela.plt    ${RELOCATING-0} : { *(.rela.plt)		}
   ${OTHER_PLT_RELOC_SECTIONS}
--- ld/genscripts.sh.jj	Mon Aug 13 13:05:50 2001
+++ ld/genscripts.sh	Wed Aug 15 17:16:55 2001
@@ -84,6 +84,17 @@ LIB_SEARCH_DIRS=`echo ${LIB_PATH} | tr '
 # A .xs script is for generating a shared library with the --shared
 #   flag; it is only generated if $GENERATE_SHLIB_SCRIPT is set by the
 #   emulation parameters.
+# A .xc script is for linking with -z combreloc; it is only generated if
+#   $GENERATE_COMBRELOC_SCRIPT is set by the emulation parameters or
+#   $SCRIPT_NAME is "elf".
+# A .xsc script is for linking with --shared -z combreloc; it is generated
+#   if $GENERATE_COMBRELOC_SCRIPT is set by the emulation parameters or
+#   $SCRIPT_NAME is "elf" and $GENERATE_SHLIB_SCRIPT is set by the emulation
+#   parameters too.
+
+if [ "x$SCRIPT_NAME" = "xelf" ]; then
+  GENERATE_COMBRELOC_SCRIPT=yes
+fi
 
 SEGMENT_SIZE=${SEGMENT_SIZE-${TARGET_PAGE_SIZE}}
 
@@ -101,34 +112,45 @@ DATA_ALIGNMENT=${DATA_ALIGNMENT_r}
 DEFAULT_DATA_ALIGNMENT="ALIGN(${SEGMENT_SIZE})"
 ( . ${srcdir}/emulparams/${EMULATION_NAME}.sh
   . ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
-) | sed -e '/^ *$/d' > ldscripts/${EMULATION_NAME}.xr
+) | sed -e '/^ *$/d;s/[ 	]*$//' > ldscripts/${EMULATION_NAME}.xr
 
 LD_FLAG=u
 DATA_ALIGNMENT=${DATA_ALIGNMENT_u}
 CONSTRUCTING=" "
 ( . ${srcdir}/emulparams/${EMULATION_NAME}.sh
   . ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
-) | sed -e '/^ *$/d' > ldscripts/${EMULATION_NAME}.xu
+) | sed -e '/^ *$/d;s/[ 	]*$//' > ldscripts/${EMULATION_NAME}.xu
 
 LD_FLAG=
 DATA_ALIGNMENT=${DATA_ALIGNMENT_}
 RELOCATING=" "
 ( . ${srcdir}/emulparams/${EMULATION_NAME}.sh
   . ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
-) | sed -e '/^ *$/d' > ldscripts/${EMULATION_NAME}.x
+) | sed -e '/^ *$/d;s/[ 	]*$//' > ldscripts/${EMULATION_NAME}.x
 
 LD_FLAG=n
 DATA_ALIGNMENT=${DATA_ALIGNMENT_n}
 TEXT_START_ADDR=${NONPAGED_TEXT_START_ADDR-${TEXT_START_ADDR}}
 ( . ${srcdir}/emulparams/${EMULATION_NAME}.sh
   . ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
-) | sed -e '/^ *$/d' > ldscripts/${EMULATION_NAME}.xn
+) | sed -e '/^ *$/d;s/[ 	]*$//' > ldscripts/${EMULATION_NAME}.xn
 
 LD_FLAG=N
 DATA_ALIGNMENT=${DATA_ALIGNMENT_N}
 ( . ${srcdir}/emulparams/${EMULATION_NAME}.sh
   . ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
-) | sed -e '/^ *$/d' > ldscripts/${EMULATION_NAME}.xbn
+) | sed -e '/^ *$/d;s/[ 	]*$//' > ldscripts/${EMULATION_NAME}.xbn
+
+if test -n "$GENERATE_COMBRELOC_SCRIPT"; then
+  DATA_ALIGNMENT=${DATA_ALIGNMENT_c-${DATA_ALIGNMENT_}}
+  LD_FLAG=
+  COMBRELOC=ldscripts/${EMULATION_NAME}.xc.tmp
+  ( . ${srcdir}/emulparams/${EMULATION_NAME}.sh
+    . ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
+  ) | sed -e '/^ *$/d;s/[ 	]*$//' > ldscripts/${EMULATION_NAME}.xc
+  rm -f ${COMBRELOC}
+  COMBRELOC=
+fi
 
 if test -n "$GENERATE_SHLIB_SCRIPT"; then
   LD_FLAG=shared
@@ -137,7 +159,16 @@ if test -n "$GENERATE_SHLIB_SCRIPT"; the
   # Note that TEXT_START_ADDR is set to NONPAGED_TEXT_START_ADDR.
   ( . ${srcdir}/emulparams/${EMULATION_NAME}.sh
     . ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
-  ) | sed -e '/^ *$/d' > ldscripts/${EMULATION_NAME}.xs
+  ) | sed -e '/^ *$/d;s/[ 	]*$//' > ldscripts/${EMULATION_NAME}.xs
+  if test -n "$GENERATE_COMBRELOC_SCRIPT"; then
+    DATA_ALIGNMENT=${DATA_ALIGNMENT_sc-${DATA_ALIGNMENT}}
+    COMBRELOC=ldscripts/${EMULATION_NAME}.xc.tmp
+    ( . ${srcdir}/emulparams/${EMULATION_NAME}.sh
+      . ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
+    ) | sed -e '/^ *$/d;s/[ 	]*$//' > ldscripts/${EMULATION_NAME}.xsc
+    rm -f ${COMBRELOC}
+    COMBRELOC=
+  fi
 fi
 
 for i in $EMULATION_LIBPATH ; do
--- ld/ldmain.c.jj	Mon Aug 13 13:10:57 2001
+++ ld/ldmain.c	Wed Aug 15 17:16:55 2001
@@ -244,6 +244,8 @@ main (argc, argv)
   link_info.flags = (bfd_vma) 0;
   link_info.flags_1 = (bfd_vma) 0;
   link_info.pei386_auto_import = false;
+  link_info.combreloc = false;
+  link_info.spare_dynamic_tags = 5;
 
   ldfile_add_arch ("");
 
--- ld/lexsup.c.jj	Mon Aug 13 13:05:50 2001
+++ ld/lexsup.c	Wed Aug 15 17:16:55 2001
@@ -131,6 +131,7 @@ int parsing_defsym = 0;
 #define OPTION_TARGET_HELP              (OPTION_UNIQUE + 1)
 #define OPTION_ALLOW_SHLIB_UNDEFINED	(OPTION_TARGET_HELP + 1)
 #define OPTION_DISCARD_NONE		(OPTION_ALLOW_SHLIB_UNDEFINED + 1)
+#define OPTION_SPARE_DYNAMIC_TAGS	(OPTION_DISCARD_NONE + 1)
 
 /* The long options.  This structure is used for both the option
    parsing and the help text.  */
@@ -347,6 +348,8 @@ static const struct ld_option ld_options
       '\0', NULL, N_("Sort common symbols by size"), TWO_DASHES },
   { {"sort_common", no_argument, NULL, OPTION_SORT_COMMON},
       '\0', NULL, NULL, NO_HELP },
+  { {"spare-dynamic-tags", required_argument, NULL, OPTION_SPARE_DYNAMIC_TAGS},
+      '\0', N_("COUNT"), N_("How many tags to reserve in .dynamic section"), TWO_DASHES },
   { {"split-by-file", optional_argument, NULL, OPTION_SPLIT_BY_FILE},
       '\0', N_("[=SIZE]"), N_("Split output sections every SIZE octets"), TWO_DASHES },
   { {"split-by-reloc", optional_argument, NULL, OPTION_SPLIT_BY_RELOC},
@@ -1072,6 +1075,9 @@ the GNU General Public License.  This pr
 	  break;
 	case 'y':
 	  add_ysym (optarg);
+	  break;
+	case OPTION_SPARE_DYNAMIC_TAGS:
+	  link_info.spare_dynamic_tags = strtoul (optarg, NULL, 0);
 	  break;
 	case OPTION_SPLIT_BY_RELOC:
 	  if (optarg != NULL)

	Jakub


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