RFC: Implementation of ELF sharable sections

H. J. Lu hjl@lucon.org
Thu Jan 4 23:32:00 GMT 2007


Here is one implementation of ELF sharable section proposal:

http://groups-beta.google.com/group/generic-abi/browse_thread/thread/bca08f6560f61b0d

Several people have expressed interests. I post it here for comments.
I used OS specific values. If we get consensus, I can change those
values to generic range.


H.J.
-------------- next part --------------
bfd/

2007-01-04  H.J. Lu  <hongjiu.lu@intel.com>

	* elf-bfd.h (_bfd_elf_sharable_com_section): New.
	(_bfd_elf_add_sharable_symbol): Likewise.
	(_bfd_elf_sharable_section_from_bfd_section): Likewise.
	(_bfd_elf_sharable_symbol_processing): Likewise.
	(_bfd_elf_sharable_common_definition): Likewise.
	(_bfd_elf_sharable_common_section_index): Likewise.
	(_bfd_elf_sharable_common_section): Likewise.
	(_bfd_elf_sharable_merge_symbol): Likewise.

	* elf.c (special_sections_g): Add ".gnu.linkonce.shrb" and
	".gnu.linkonce.shrd".
	(special_sections_s): Add ".sharable_bss" and ".sharable_data".
	(get_program_header_size): Handle PT_GNU_SHR segment.
	(_bfd_elf_map_sections_to_segments): Likewise.
	(assign_file_positions_for_load_sections): Likewise.

	* elf32-i386.c (elf_i386_link_hash_table): Add sdynsharablebss
	and srelsharablebss fields.
	(elf_i386_link_hash_table_create): Initialize sdynsharablebss
	and srelsharablebss.
	(elf_i386_create_dynamic_sections): Handle sdynsharablebss and
	srelsharablebss.
	(elf_i386_adjust_dynamic_symbol): Likewise.
	(elf_i386_size_dynamic_sections): Likewise.
	(elf_i386_finish_dynamic_symbol): Likewise.
	(elf_backend_add_symbol_hook): Defined.
	(elf_backend_section_from_bfd_section): Likewise.
	(elf_backend_symbol_processing): Likewise.
	(elf_backend_common_section_index): Likewise.
	(elf_backend_common_section): Likewise.
	(elf_backend_common_definition): Likewise.
	(elf_backend_merge_symbol): Likewise.

	* elf64-x86-64.c (elf64_x86_64_link_hash_table): Add
	sdynsharablebss and srelsharablebss fields.
	(elf64_x86_64_link_hash_table_create): Initialize sdynsharablebss
	and srelsharablebss.
	(elf64_x86_64_create_dynamic_sections): Handle sdynsharablebss
	and srelsharablebss.
	(elf64_x86_64_adjust_dynamic_symbol): Likewise.
	(elf64_x86_64_size_dynamic_sections): Likewise.
	(elf64_x86_64_finish_dynamic_symbol): Likewise.
	(elf64_x86_64_add_symbol_hook): Handle sharable symbols.
	(elf64_x86_64_elf_section_from_bfd_section): Likewise.
	(elf64_x86_64_symbol_processing): Likewise.
	(elf64_x86_64_merge_symbol): Likewise.
	(elf64_x86_64_common_definition): Handle sharable sections.
	(elf64_x86_64_common_section_index): Likewise.
	(elf64_x86_64_common_section): Likewise.

	* elflink.c (_bfd_elf_create_dynamic_sections): Handle
	.dynsharablebss section.
	(_bfd_elf_sharable_com_section): New.
	(get_sharable_common_section): Likewise.
	(_bfd_elf_add_sharable_symbol): Likewise.
	(_bfd_elf_sharable_section_from_bfd_section): Likewise.
	(_bfd_elf_sharable_symbol_processing): Likewise.
	(_bfd_elf_sharable_common_definition): Likewise.
	(_bfd_elf_sharable_common_section_index): Likewise.
	(_bfd_elf_sharable_common_section): Likewise.
	(_bfd_elf_sharable_merge_symbol): Likewise.

	* elfxx-ia64.c (elfNN_ia64_add_symbol_hook): Handle sharable
	symbols.
	(elf_backend_add_symbol_hook): Defined.
	(elf_backend_section_from_bfd_section): Likewise.
	(elf_backend_symbol_processing): Likewise.
	(elf_backend_common_section_index): Likewise.
	(elf_backend_common_section): Likewise.
	(elf_backend_common_definition): Likewise.
	(elf_backend_merge_symbol): Likewise.

binutils/

2007-01-04  H.J. Lu  <hongjiu.lu@intel.com>

	* readelf.c (dump_relocations): Handle sharable sections.
	(get_segment_type): Handle sharable segment.
	(get_symbol_index_type): Handle sharable sections.

gas/

2007-01-04  H.J. Lu  <hongjiu.lu@intel.com>

	* config/obj-elf.c (obj_elf_sharable_common): New.
	(elf_pseudo_table): Add "sharable_common".
	(obj_elf_change_section): Handle sharable sections.

include/elf/

2007-01-04  H.J. Lu  <hongjiu.lu@intel.com>

	* common.h (PT_GNU_SHR): New.
	(SHF_GNU_SHARABLE): Likewise.
	(SHN_GNU_SHARABLE_COMMON): Likewise.

ld/

2007-01-04  H.J. Lu  <hongjiu.lu@intel.com>

	* emulparams/elf64_ia64.sh (SHARABLE_SECTIONS): Set to yes.
	* emulparams/elf_i386.sh (SHARABLE_SECTIONS): Likewise.
	* emulparams/elf_x86_64.sh (SHARABLE_SECTIONS): Likewise.

	* emultempl/elf32.em: Include "elf-bfd.h".
	(gld${EMULATION_NAME}_place_orphan): Don't allow orphaned
	sharable sections.

	* scripttempl/elf.sc: Support sharable sections.

--- binutils/bfd/elf-bfd.h.shr	2007-01-04 12:24:45.000000000 -0800
+++ binutils/bfd/elf-bfd.h	2007-01-04 12:24:45.000000000 -0800
@@ -1828,6 +1828,28 @@ extern bfd_boolean bfd_elf_link_add_symb
   (bfd *, struct bfd_link_info *);
 extern bfd_boolean _bfd_elf_add_dynamic_entry
   (struct bfd_link_info *, bfd_vma, bfd_vma);
+extern asection _bfd_elf_sharable_com_section;
+extern bfd_boolean _bfd_elf_add_sharable_symbol
+  (bfd *, struct bfd_link_info *, Elf_Internal_Sym *, const char **,
+   flagword *, asection **, bfd_vma *);
+extern bfd_boolean _bfd_elf_sharable_section_from_bfd_section
+  (bfd *, asection *, int *);
+extern void _bfd_elf_sharable_symbol_processing
+  (bfd *, asymbol *);
+extern bfd_boolean _bfd_elf_sharable_common_definition
+  (Elf_Internal_Sym *);
+extern unsigned int _bfd_elf_sharable_common_section_index
+  (asection *);
+extern asection *_bfd_elf_sharable_common_section
+  (asection *);
+extern bfd_boolean _bfd_elf_sharable_merge_symbol
+  (struct bfd_link_info *, struct elf_link_hash_entry **,
+   struct elf_link_hash_entry *, Elf_Internal_Sym *, asection **,
+   bfd_vma *, unsigned int *, bfd_boolean *, bfd_boolean *,
+   bfd_boolean *, bfd_boolean *, bfd_boolean *, bfd_boolean *,
+   bfd_boolean *, bfd_boolean *, bfd *, asection **,
+   bfd_boolean *, bfd_boolean *, bfd_boolean *, bfd_boolean *,
+   bfd *, asection **);
 
 extern bfd_boolean bfd_elf_link_record_dynamic_symbol
   (struct bfd_link_info *, struct elf_link_hash_entry *);
--- binutils/bfd/elf.c.shr	2007-01-04 12:24:45.000000000 -0800
+++ binutils/bfd/elf.c	2007-01-04 12:24:45.000000000 -0800
@@ -2329,6 +2329,8 @@ static const struct bfd_elf_special_sect
   { STRING_COMMA_LEN (".gnu.liblist"),     0, SHT_GNU_LIBLIST, SHF_ALLOC },
   { STRING_COMMA_LEN (".gnu.conflict"),    0, SHT_RELA,        SHF_ALLOC },
   { STRING_COMMA_LEN (".gnu.hash"),        0, SHT_GNU_HASH,    SHF_ALLOC },
+  { STRING_COMMA_LEN (".gnu.linkonce.shrb"), -2, SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_GNU_SHARABLE},
+  { STRING_COMMA_LEN (".gnu.linkonce.shrd"), -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_GNU_SHARABLE},
   { NULL,                        0,        0, 0,               0 }
 };
 
@@ -2383,6 +2385,8 @@ static const struct bfd_elf_special_sect
   /* See struct bfd_elf_special_section declaration for the semantics of
      this special case where .prefix_length != strlen (.prefix).  */
   { ".stabstr",			5,  3, SHT_STRTAB, 0 },
+  { STRING_COMMA_LEN (".sharable_bss"), -2, SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_GNU_SHARABLE},
+  { STRING_COMMA_LEN (".sharable_data"), -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_GNU_SHARABLE},
   { NULL,                       0,  0, 0,          0 }
 };
 
@@ -3671,6 +3675,32 @@ get_program_header_size (bfd *abfd, stru
 	}
     }
 
+  /* Check to see if we need a PT_GNU_SHR segment for sharable data
+     sections.  */
+  for (s = abfd->sections; s != NULL; s = s->next)
+    {
+      if ((elf_section_flags (s) & SHF_GNU_SHARABLE) != 0
+	  && elf_section_type (s) == SHT_PROGBITS)
+	{
+	  /* We need a PT_GNU_SHR segment.  */
+	  ++segs;
+	  break;
+	}
+    }
+
+  /* Check to see if we need a PT_GNU_SHR segment for sharable bss
+     sections.  */
+  for (s = abfd->sections; s != NULL; s = s->next)
+    {
+      if ((elf_section_flags (s) & SHF_GNU_SHARABLE) != 0
+	  && elf_section_type (s) == SHT_NOBITS)
+	{
+	  /* We need a PT_GNU_SHR segment.  */
+	  ++segs;
+	  break;
+	}
+    }
+
   /* Let the backend count up any program headers it might need.  */
   bed = get_elf_backend_data (abfd);
   if (bed->elf_backend_additional_program_headers)
@@ -3811,6 +3841,8 @@ _bfd_elf_map_sections_to_segments (bfd *
       bfd_boolean phdr_in_segment = TRUE;
       bfd_boolean writable;
       int tls_count = 0;
+      int sharable_data_count = 0, sharable_bss_count = 0;
+      asection *first_sharable_data = NULL, *first_sharable_bss = NULL;
       asection *first_tls = NULL;
       asection *dynsec, *eh_frame_hdr;
       bfd_size_type amt;
@@ -4056,6 +4088,22 @@ _bfd_elf_map_sections_to_segments (bfd *
 		first_tls = s;
 	      tls_count++;
 	    }
+	  if (elf_section_flags (s) & SHF_GNU_SHARABLE)
+	    {
+	      if (elf_section_type (s) == SHT_PROGBITS)
+		{
+		  if (! sharable_data_count)
+		    first_sharable_data = s;
+		  sharable_data_count++;
+		}
+	      else
+		{
+		  BFD_ASSERT (elf_section_type (s) == SHT_NOBITS);
+		  if (! sharable_bss_count)
+		    first_sharable_bss = s;
+		  sharable_bss_count++;
+		}
+	    }
 	}
 
       /* If there are any SHF_TLS output sections, add PT_TLS segment.  */
@@ -4085,6 +4133,60 @@ _bfd_elf_map_sections_to_segments (bfd *
 	  pm = &m->next;
 	}
 
+      /* If there are any output SHF_GNU_SHARABLE data sections, add a
+	 PT_GNU_SHR segment.  */
+      if (sharable_data_count > 0)
+	{
+	  int i;
+
+	  amt = sizeof (struct elf_segment_map);
+	  amt += (sharable_data_count - 1) * sizeof (asection *);
+	  m = bfd_zalloc (abfd, amt);
+	  if (m == NULL)
+	    goto error_return;
+	  m->next = NULL;
+	  m->p_type = PT_GNU_SHR;
+	  m->count = sharable_data_count;
+	  /* Mandated PF_R.  */
+	  m->p_flags = PF_R;
+	  m->p_flags_valid = 1;
+	  for (i = 0; i < sharable_data_count; ++i)
+	    {
+	      m->sections[i] = first_sharable_data;
+	      first_sharable_data = first_sharable_data->next;
+	    }
+
+	  *pm = m;
+	   pm = &m->next;
+	}
+
+      /* If there are any output SHF_GNU_SHARABLE bss sections, add a
+	 PT_GNU_SHR segment.  */
+      if (sharable_bss_count > 0)
+	{
+	  int i;
+
+	  amt = sizeof (struct elf_segment_map);
+	  amt += (sharable_bss_count - 1) * sizeof (asection *);
+	  m = bfd_zalloc (abfd, amt);
+	  if (m == NULL)
+	    goto error_return;
+	  m->next = NULL;
+	  m->p_type = PT_GNU_SHR;
+	  m->count = sharable_bss_count;
+	  /* Mandated PF_R.  */
+	  m->p_flags = PF_R;
+	  m->p_flags_valid = 1;
+	  for (i = 0; i < sharable_bss_count; ++i)
+	    {
+	      m->sections[i] = first_sharable_bss;
+	      first_sharable_bss = first_sharable_bss->next;
+	    }
+
+	  *pm = m;
+	   pm = &m->next;
+	}
+
       /* If there is a .eh_frame_hdr section, throw in a PT_GNU_EH_FRAME
 	 segment.  */
       eh_frame_hdr = elf_tdata (abfd)->eh_frame_hdr;
@@ -4505,6 +4607,7 @@ assign_file_positions_for_load_sections 
 	  align = (bfd_size_type) 1 << bfd_get_section_alignment (abfd, sec);
 
 	  if (p->p_type == PT_LOAD
+	      || p->p_type == PT_GNU_SHR
 	      || p->p_type == PT_TLS)
 	    {
 	      bfd_signed_vma adjust;
--- binutils/bfd/elf32-i386.c.shr	2007-01-04 12:24:45.000000000 -0800
+++ binutils/bfd/elf32-i386.c	2007-01-04 12:24:45.000000000 -0800
@@ -646,6 +646,8 @@ struct elf_i386_link_hash_table
   asection *srelplt;
   asection *sdynbss;
   asection *srelbss;
+  asection *sdynsharablebss;
+  asection *srelsharablebss;
 
   /* The (unloaded but important) .rel.plt.unloaded section on VxWorks.  */
   asection *srelplt2;
@@ -738,6 +740,8 @@ elf_i386_link_hash_table_create (bfd *ab
   ret->srelplt = NULL;
   ret->sdynbss = NULL;
   ret->srelbss = NULL;
+  ret->sdynsharablebss = NULL;
+  ret->srelsharablebss = NULL;
   ret->tls_ldm_got.refcount = 0;
   ret->next_tls_desc_index = 0;
   ret->sgotplt_jump_table_size = 0;
@@ -798,10 +802,19 @@ elf_i386_create_dynamic_sections (bfd *d
   htab->srelplt = bfd_get_section_by_name (dynobj, ".rel.plt");
   htab->sdynbss = bfd_get_section_by_name (dynobj, ".dynbss");
   if (!info->shared)
-    htab->srelbss = bfd_get_section_by_name (dynobj, ".rel.bss");
+    {
+      htab->srelbss = bfd_get_section_by_name (dynobj, ".rel.bss");
+      htab->sdynsharablebss
+	= bfd_get_section_by_name (dynobj, ".dynsharablebss");
+      htab->srelsharablebss
+	= bfd_get_section_by_name (dynobj, ".rel.sharable_bss");
+    }
 
   if (!htab->splt || !htab->srelplt || !htab->sdynbss
-      || (!info->shared && !htab->srelbss))
+      || (!info->shared
+	  && (!htab->srelbss
+	      || !htab->sdynsharablebss
+	      || !htab->srelsharablebss)))
     abort ();
 
   if (htab->is_vxworks
@@ -1516,12 +1529,20 @@ elf_i386_adjust_dynamic_symbol (struct b
      both the dynamic object and the regular object will refer to the
      same memory location for the variable.  */
 
+  s = htab->sdynbss;
+
   /* We must generate a R_386_COPY reloc to tell the dynamic linker to
      copy the initial value out of the dynamic object and into the
      runtime process image.  */
   if ((h->root.u.def.section->flags & SEC_ALLOC) != 0)
     {
-      htab->srelbss->size += sizeof (Elf32_External_Rel);
+      if (elf_section_flags (h->root.u.def.section) & SHF_GNU_SHARABLE)
+	{
+	  htab->srelsharablebss->size += sizeof (Elf32_External_Rel);
+	  s = htab->sdynsharablebss;
+	}
+      else
+	htab->srelbss->size += sizeof (Elf32_External_Rel);
       h->needs_copy = 1;
     }
 
@@ -1532,7 +1553,6 @@ elf_i386_adjust_dynamic_symbol (struct b
     power_of_two = 3;
 
   /* Apply the required alignment.  */
-  s = htab->sdynbss;
   s->size = BFD_ALIGN (s->size, (bfd_size_type) (1 << power_of_two));
   if (power_of_two > bfd_get_section_alignment (htab->elf.dynobj, s))
     {
@@ -2000,7 +2020,8 @@ elf_i386_size_dynamic_sections (bfd *out
       if (s == htab->splt
 	  || s == htab->sgot
 	  || s == htab->sgotplt
-	  || s == htab->sdynbss)
+	  || s == htab->sdynbss
+	  || s == htab->sdynsharablebss)
 	{
 	  /* Strip this section if we don't need it; see the
 	     comment below.  */
@@ -3571,21 +3592,27 @@ elf_i386_finish_dynamic_symbol (bfd *out
     {
       Elf_Internal_Rela rel;
       bfd_byte *loc;
+      asection *s;
+
+      if (h->root.u.def.section == htab->sdynsharablebss)
+	s = htab->srelsharablebss;
+      else
+	s = htab->srelbss;
 
       /* This symbol needs a copy reloc.  Set it up.  */
 
       if (h->dynindx == -1
 	  || (h->root.type != bfd_link_hash_defined
 	      && h->root.type != bfd_link_hash_defweak)
-	  || htab->srelbss == NULL)
+	  || s == NULL)
 	abort ();
 
       rel.r_offset = (h->root.u.def.value
 		      + h->root.u.def.section->output_section->vma
 		      + h->root.u.def.section->output_offset);
       rel.r_info = ELF32_R_INFO (h->dynindx, R_386_COPY);
-      loc = htab->srelbss->contents;
-      loc += htab->srelbss->reloc_count++ * sizeof (Elf32_External_Rel);
+      loc = s->contents;
+      loc += s->reloc_count++ * sizeof (Elf32_External_Rel);
       bfd_elf32_swap_reloc_out (output_bfd, &rel, loc);
     }
 
@@ -3872,6 +3899,21 @@ elf_i386_hash_symbol (struct elf_link_ha
 #define elf_backend_plt_sym_val		      elf_i386_plt_sym_val
 #define elf_backend_hash_symbol		      elf_i386_hash_symbol
 
+#define elf_backend_add_symbol_hook \
+  _bfd_elf_add_sharable_symbol
+#define elf_backend_section_from_bfd_section \
+  _bfd_elf_sharable_section_from_bfd_section
+#define elf_backend_symbol_processing \
+  _bfd_elf_sharable_symbol_processing
+#define elf_backend_common_section_index \
+  _bfd_elf_sharable_common_section_index
+#define elf_backend_common_section \
+  _bfd_elf_sharable_common_section
+#define elf_backend_common_definition \
+  _bfd_elf_sharable_common_definition
+#define elf_backend_merge_symbol \
+  _bfd_elf_sharable_merge_symbol
+
 #include "elf32-target.h"
 
 /* FreeBSD support.  */
--- binutils/bfd/elf64-x86-64.c.shr	2007-01-04 12:24:45.000000000 -0800
+++ binutils/bfd/elf64-x86-64.c	2007-01-04 12:24:45.000000000 -0800
@@ -452,6 +452,8 @@ struct elf64_x86_64_link_hash_table
   asection *srelplt;
   asection *sdynbss;
   asection *srelbss;
+  asection *sdynsharablebss;
+  asection *srelsharablebss;
 
   /* The offset into splt of the PLT entry for the TLS descriptor
      resolver.  Special values are 0, if not necessary (or not found
@@ -539,6 +541,8 @@ elf64_x86_64_link_hash_table_create (bfd
   ret->srelplt = NULL;
   ret->sdynbss = NULL;
   ret->srelbss = NULL;
+  ret->sdynsharablebss = NULL;
+  ret->srelsharablebss = NULL;
   ret->sym_sec.abfd = NULL;
   ret->tlsdesc_plt = 0;
   ret->tlsdesc_got = 0;
@@ -597,10 +601,19 @@ elf64_x86_64_create_dynamic_sections (bf
   htab->srelplt = bfd_get_section_by_name (dynobj, ".rela.plt");
   htab->sdynbss = bfd_get_section_by_name (dynobj, ".dynbss");
   if (!info->shared)
-    htab->srelbss = bfd_get_section_by_name (dynobj, ".rela.bss");
+    {
+      htab->srelbss = bfd_get_section_by_name (dynobj, ".rela.bss");
+      htab->sdynsharablebss
+	= bfd_get_section_by_name (dynobj, ".dynsharablebss");
+      htab->srelsharablebss
+	= bfd_get_section_by_name (dynobj, ".rela.sharable_bss");
+    }
 
   if (!htab->splt || !htab->srelplt || !htab->sdynbss
-      || (!info->shared && !htab->srelbss))
+      || (!info->shared
+	  && (!htab->srelbss
+	      || !htab->sdynsharablebss
+	      || !htab->srelsharablebss)))
     abort ();
 
   return TRUE;
@@ -1379,12 +1392,20 @@ elf64_x86_64_adjust_dynamic_symbol (stru
 
   htab = elf64_x86_64_hash_table (info);
 
+  s = htab->sdynbss;
+
   /* We must generate a R_X86_64_COPY reloc to tell the dynamic linker
      to copy the initial value out of the dynamic object and into the
      runtime process image.  */
   if ((h->root.u.def.section->flags & SEC_ALLOC) != 0)
     {
-      htab->srelbss->size += sizeof (Elf64_External_Rela);
+      if (elf_section_flags (h->root.u.def.section) & SHF_GNU_SHARABLE)
+	{
+	  htab->srelsharablebss->size += sizeof (Elf64_External_Rela);
+	  s = htab->sdynsharablebss;
+	}
+      else
+	htab->srelbss->size += sizeof (Elf64_External_Rela);
       h->needs_copy = 1;
     }
 
@@ -1398,7 +1419,6 @@ elf64_x86_64_adjust_dynamic_symbol (stru
     power_of_two = 4;
 
   /* Apply the required alignment.  */
-  s = htab->sdynbss;
   s->size = BFD_ALIGN (s->size, (bfd_size_type) (1 << power_of_two));
   if (power_of_two > bfd_get_section_alignment (htab->elf.dynobj, s))
     {
@@ -1860,7 +1880,8 @@ elf64_x86_64_size_dynamic_sections (bfd 
       if (s == htab->splt
 	  || s == htab->sgot
 	  || s == htab->sgotplt
-	  || s == htab->sdynbss)
+	  || s == htab->sdynbss
+	  || s == htab->sdynsharablebss)
 	{
 	  /* Strip this section if we don't need it; see the
 	     comment below.  */
@@ -3196,13 +3217,19 @@ elf64_x86_64_finish_dynamic_symbol (bfd 
     {
       Elf_Internal_Rela rela;
       bfd_byte *loc;
+      asection *s;
+
+      if (h->root.u.def.section == htab->sdynsharablebss)
+	s = htab->srelsharablebss;
+      else
+	s = htab->srelbss;
 
       /* This symbol needs a copy reloc.  Set it up.  */
 
       if (h->dynindx == -1
 	  || (h->root.type != bfd_link_hash_defined
 	      && h->root.type != bfd_link_hash_defweak)
-	  || htab->srelbss == NULL)
+	  || s == NULL)
 	abort ();
 
       rela.r_offset = (h->root.u.def.value
@@ -3210,8 +3237,8 @@ elf64_x86_64_finish_dynamic_symbol (bfd 
 		       + h->root.u.def.section->output_offset);
       rela.r_info = ELF64_R_INFO (h->dynindx, R_X86_64_COPY);
       rela.r_addend = 0;
-      loc = htab->srelbss->contents;
-      loc += htab->srelbss->reloc_count++ * sizeof (Elf64_External_Rela);
+      loc = s->contents;
+      loc += s->reloc_count++ * sizeof (Elf64_External_Rela);
       bfd_elf64_swap_reloca_out (output_bfd, &rela, loc);
     }
 
@@ -3475,9 +3502,12 @@ elf64_x86_64_add_symbol_hook (bfd *abfd,
 	}
       *secp = lcomm;
       *valp = sym->st_size;
+      return TRUE;
       break;
     }
-  return TRUE;
+
+  return _bfd_elf_add_sharable_symbol (abfd, info, sym, namep, flagsp,
+				       secp, valp);
 }
 
 
@@ -3493,7 +3523,7 @@ elf64_x86_64_elf_section_from_bfd_sectio
       *index = SHN_X86_64_LCOMMON;
       return TRUE;
     }
-  return FALSE;
+  return _bfd_elf_sharable_section_from_bfd_section (abfd, sec, index);
 }
 
 /* Process a symbol.  */
@@ -3511,22 +3541,26 @@ elf64_x86_64_symbol_processing (bfd *abf
       asym->value = elfsym->internal_elf_sym.st_size;
       /* Common symbol doesn't set BSF_GLOBAL.  */
       asym->flags &= ~BSF_GLOBAL;
+      return;
       break;
     }
+  
+  _bfd_elf_sharable_symbol_processing (abfd, asym);
 }
 
 static bfd_boolean
 elf64_x86_64_common_definition (Elf_Internal_Sym *sym)
 {
   return (sym->st_shndx == SHN_COMMON
-	  || sym->st_shndx == SHN_X86_64_LCOMMON);
+	  || sym->st_shndx == SHN_X86_64_LCOMMON
+	  || _bfd_elf_sharable_common_definition (sym));
 }
 
 static unsigned int
 elf64_x86_64_common_section_index (asection *sec)
 {
   if ((elf_section_flags (sec) & SHF_X86_64_LARGE) == 0)
-    return SHN_COMMON;
+    return _bfd_elf_sharable_common_section_index (sec);
   else
     return SHN_X86_64_LCOMMON;
 }
@@ -3535,7 +3569,7 @@ static asection *
 elf64_x86_64_common_section (asection *sec)
 {
   if ((elf_section_flags (sec) & SHF_X86_64_LARGE) == 0)
-    return bfd_com_section_ptr;
+    return _bfd_elf_sharable_common_section (sec);
   else
     return &_bfd_elf_large_com_section;
 }
@@ -3572,7 +3606,8 @@ elf64_x86_64_merge_symbol (struct bfd_li
       && h->root.type == bfd_link_hash_common
       && !*newdyn
       && bfd_is_com_section (*sec)
-      && *oldsec != *sec)
+      && *oldsec != *sec
+      && _bfd_elf_sharable_common_section_index (*oldsec) == SHN_COMMON)
     {
       if (sym->st_shndx == SHN_COMMON
 	  && (elf_section_flags (*oldsec) & SHF_X86_64_LARGE) != 0)
@@ -3580,13 +3615,26 @@ elf64_x86_64_merge_symbol (struct bfd_li
 	  h->root.u.c.p->section
 	    = bfd_make_section_old_way (oldbfd, "COMMON");
 	  h->root.u.c.p->section->flags = SEC_ALLOC;
+	  return TRUE;
 	}
       else if (sym->st_shndx == SHN_X86_64_LCOMMON
 	       && (elf_section_flags (*oldsec) & SHF_X86_64_LARGE) == 0)
-	*psec = *sec = bfd_com_section_ptr; 
+	{
+	  *psec = *sec = bfd_com_section_ptr; 
+	  return TRUE;
+	}
     }
 
-  return TRUE;
+  return _bfd_elf_sharable_merge_symbol (info, sym_hash, h, sym,
+					 psec, pvalue, pold_alignment,
+					 skip, override,
+					 type_change_ok, size_change_ok,
+					 newdyn, newdef,
+					 newdyncommon, newweak,
+					 abfd, sec,
+					 olddyn, olddef,
+					 olddyncommon, oldweak,
+					 oldbfd, oldsec);
 }
 
 static int
--- binutils/bfd/elflink.c.shr	2007-01-04 12:24:45.000000000 -0800
+++ binutils/bfd/elflink.c	2007-01-04 12:24:45.000000000 -0800
@@ -352,6 +352,22 @@ _bfd_elf_create_dynamic_sections (bfd *a
 	  if (s == NULL
 	      || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
 	    return FALSE;
+
+	  s = bfd_make_section (abfd, ".dynsharablebss");
+	  if (s == NULL
+	      || ! bfd_set_section_flags (abfd, s,
+					  (SEC_ALLOC
+					   | SEC_LINKER_CREATED)))
+	    return FALSE;
+
+	  s = bfd_make_section (abfd,
+				(bed->default_use_rela_p
+				 ? ".rela.sharable_bss"
+				 : ".rel.sharable_bss"));
+	  if (s == NULL
+	      || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
+	      || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
+	    return FALSE;
 	}
     }
 
@@ -10581,3 +10597,219 @@ _bfd_elf_common_section (asection *sec A
 {
   return bfd_com_section_ptr;
 }
+
+asection _bfd_elf_sharable_com_section
+  = BFD_FAKE_SECTION (_bfd_elf_sharable_com_section, SEC_IS_COMMON,
+		      NULL, "SHARABLE_COMMON", 0);
+ 
+static asection *
+get_sharable_common_section (bfd *abfd)
+{
+  asection *scomm = bfd_get_section_by_name (abfd, "SHARABLE_COMMON");
+
+  if (scomm == NULL)
+    {
+      scomm = bfd_make_section_with_flags (abfd,
+					   "SHARABLE_COMMON",
+					   (SEC_ALLOC
+					    | SEC_IS_COMMON
+					    | SEC_LINKER_CREATED));
+      if (scomm == NULL)
+	return scomm;
+      elf_section_flags (scomm) |= SHF_GNU_SHARABLE;
+    }
+
+  return scomm;
+}
+
+bfd_boolean
+_bfd_elf_add_sharable_symbol (bfd *abfd ATTRIBUTE_UNUSED,
+			      struct bfd_link_info *info ATTRIBUTE_UNUSED,
+			      Elf_Internal_Sym *sym,
+			      const char **namep ATTRIBUTE_UNUSED,
+			      flagword *flagsp ATTRIBUTE_UNUSED,
+			      asection **secp,
+			      bfd_vma *valp)
+{
+  asection *scomm;
+
+  switch (sym->st_shndx)
+    {
+    case SHN_GNU_SHARABLE_COMMON:
+      scomm = get_sharable_common_section (abfd);
+      if (scomm == NULL)
+	return FALSE;
+      *secp = scomm;
+      *valp = sym->st_size;
+      break;
+    }
+  return TRUE;
+}
+
+bfd_boolean
+_bfd_elf_sharable_section_from_bfd_section
+  (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, int *index)
+{
+  if (sec == &_bfd_elf_sharable_com_section)
+    {
+      *index = SHN_GNU_SHARABLE_COMMON;
+      return TRUE;
+    }
+  return FALSE;
+}
+
+void
+_bfd_elf_sharable_symbol_processing (bfd *abfd ATTRIBUTE_UNUSED,
+				     asymbol *asym)
+{
+  elf_symbol_type *elfsym = (elf_symbol_type *) asym;
+
+  switch (elfsym->internal_elf_sym.st_shndx)
+    {
+    case SHN_GNU_SHARABLE_COMMON:
+      asym->section = &_bfd_elf_sharable_com_section;
+      asym->value = elfsym->internal_elf_sym.st_size;
+      asym->flags &= ~BSF_GLOBAL;
+      break;
+    }
+}
+
+bfd_boolean
+_bfd_elf_sharable_common_definition (Elf_Internal_Sym *sym)
+{
+  return (sym->st_shndx == SHN_COMMON
+	  || sym->st_shndx == SHN_GNU_SHARABLE_COMMON);
+}
+
+unsigned int
+_bfd_elf_sharable_common_section_index (asection *sec)
+{
+  if ((elf_section_flags (sec) & SHF_GNU_SHARABLE) == 0)
+    return SHN_COMMON;
+  else
+    return SHN_GNU_SHARABLE_COMMON;
+}
+
+asection *
+_bfd_elf_sharable_common_section (asection *sec)
+{
+  if ((elf_section_flags (sec) & SHF_GNU_SHARABLE) == 0)
+    return bfd_com_section_ptr;
+  else
+    return &_bfd_elf_sharable_com_section;
+}
+
+bfd_boolean
+_bfd_elf_sharable_merge_symbol
+  (struct bfd_link_info *info ATTRIBUTE_UNUSED,
+   struct elf_link_hash_entry **sym_hash ATTRIBUTE_UNUSED,
+   struct elf_link_hash_entry *h,
+   Elf_Internal_Sym *sym ATTRIBUTE_UNUSED,
+   asection **psec,
+   bfd_vma *pvalue ATTRIBUTE_UNUSED,
+   unsigned int *pold_alignment ATTRIBUTE_UNUSED,
+   bfd_boolean *skip ATTRIBUTE_UNUSED,
+   bfd_boolean *override ATTRIBUTE_UNUSED,
+   bfd_boolean *type_change_ok ATTRIBUTE_UNUSED,
+   bfd_boolean *size_change_ok ATTRIBUTE_UNUSED,
+   bfd_boolean *newdef ATTRIBUTE_UNUSED,
+   bfd_boolean *newdyn,
+   bfd_boolean *newdyncommon ATTRIBUTE_UNUSED,
+   bfd_boolean *newweak ATTRIBUTE_UNUSED,
+   bfd *abfd,
+   asection **sec,
+   bfd_boolean *olddef ATTRIBUTE_UNUSED,
+   bfd_boolean *olddyn,
+   bfd_boolean *olddyncommon ATTRIBUTE_UNUSED,
+   bfd_boolean *oldweak ATTRIBUTE_UNUSED,
+   bfd *oldbfd,
+   asection **oldsec)
+{
+  /* Check sharable symbol.  If one is undefined, it is OK.  */
+  if (*oldsec && !bfd_is_und_section (*sec))
+    {
+      bfd_boolean sharable, oldsharable;
+     
+      sharable = (elf_section_data (*sec)
+		  && (elf_section_flags (*sec) & SHF_GNU_SHARABLE));
+      oldsharable = (elf_section_data (*oldsec)
+		     && (elf_section_flags (*oldsec)
+			 & SHF_GNU_SHARABLE));
+
+      if (sharable != oldsharable)
+	{
+	  bfd *nsbfd, *sbfd;
+	  asection *nssec, *ssec;
+	  bfd_boolean nsdyn, sdyn, nsdef, sdef;
+
+	  if (oldsharable)
+	    {
+	      sbfd = oldbfd;
+	      nsbfd = abfd;
+	      ssec = *oldsec;
+	      nssec = *sec;
+	      sdyn = *olddyn;
+	      nsdyn = *newdyn;
+	      sdef = *olddef;
+	      nsdef = *newdef;
+	    }
+	  else
+	    {
+	      sbfd = abfd;
+	      nsbfd = oldbfd;
+	      ssec = *sec;
+	      nssec = *oldsec;
+	      sdyn = *newdyn;
+	      nsdyn = *olddyn;
+	      sdef = *newdef;
+	      nsdef = *olddef;
+	    }
+
+	  if (sdef && !sdyn)
+	    {
+	      /* If the sharable definition comes from a relocatable
+		 file, it will override the non-sharable one in DSO. */
+	      return TRUE;
+	    }
+	  else if (!nsdef
+		   && !nsdyn
+		   && (h->root.type == bfd_link_hash_common
+		       || bfd_is_com_section (nssec)))
+	    {
+	      asection *scomm;
+
+	      /* When the non-sharable common symbol in a relocatable
+		 file, we can turn it into sharable.  If the sharable
+		 symbol isn't common, the non-sharable common symbol
+		 will be overidden.  We only need to handle the
+		 sharable common symbol and the non-sharable common
+		 symbol.  We just turn the non-sharable common symbol
+		 into the sharable one. */
+	      if (sym->st_shndx == SHN_GNU_SHARABLE_COMMON)
+		{
+		  scomm = get_sharable_common_section (oldbfd);
+		  if (scomm == NULL)
+		    return FALSE;
+		  h->root.u.c.p->section = scomm;
+		}
+	      else
+		{
+		  scomm = get_sharable_common_section (abfd);
+		  if (scomm == NULL)
+		    return FALSE;
+		  *psec = *sec = scomm;
+		}
+
+	      return TRUE;
+	    }
+
+	  (*_bfd_error_handler)
+	    (_("%s: sharable symbol in %B section %A mismatches non-shrable symbol in %B section %A"),
+	     sbfd, ssec, nsbfd, nssec, h->root.root.string);
+	  bfd_set_error (bfd_error_bad_value);
+	  return FALSE;
+	}
+    }
+
+  return TRUE;
+}
--- binutils/bfd/elfxx-ia64.c.shr	2007-01-04 12:24:45.000000000 -0800
+++ binutils/bfd/elfxx-ia64.c	2007-01-04 12:24:45.000000000 -0800
@@ -1620,7 +1620,8 @@ elfNN_ia64_add_symbol_hook (abfd, info, 
       *valp = sym->st_size;
     }
 
-  return TRUE;
+  return _bfd_elf_add_sharable_symbol (abfd, info, sym, namep, flagsp,
+				       secp, valp);
 }
 
 /* Return the number of additional phdrs we will need.  */
@@ -5802,6 +5803,19 @@ elfNN_hpux_backend_symbol_processing (bf
 #define elf_backend_rela_normal		1
 #define elf_backend_special_sections	elfNN_ia64_special_sections
 
+#define elf_backend_section_from_bfd_section \
+  _bfd_elf_sharable_section_from_bfd_section
+#define elf_backend_symbol_processing \
+  _bfd_elf_sharable_symbol_processing
+#define elf_backend_common_section_index \
+  _bfd_elf_sharable_common_section_index
+#define elf_backend_common_section \
+  _bfd_elf_sharable_common_section
+#define elf_backend_common_definition \
+  _bfd_elf_sharable_common_definition
+#define elf_backend_merge_symbol \
+  _bfd_elf_sharable_merge_symbol
+
 /* FIXME: PR 290: The Intel C compiler generates SHT_IA_64_UNWIND with
    SHF_LINK_ORDER. But it doesn't set the sh_link or sh_info fields.
    We don't want to flood users with so many error messages. We turn
--- binutils/binutils/readelf.c.shr	2006-12-27 07:30:41.000000000 -0800
+++ binutils/binutils/readelf.c	2007-01-04 12:24:45.000000000 -0800
@@ -1238,6 +1238,8 @@ dump_relocations (FILE *file,
 			sec_name = "ABS";
 		      else if (psym->st_shndx == SHN_COMMON)
 			sec_name = "COMMON";
+		      else if (psym->st_shndx == SHN_GNU_SHARABLE_COMMON)
+			sec_name = "GNU_SHARABLE_COMMON";
 		      else if (elf_header.e_machine == EM_MIPS
 			       && psym->st_shndx == SHN_MIPS_SCOMMON)
 			sec_name = "SCOMMON";
@@ -2436,6 +2438,7 @@ get_segment_type (unsigned long p_type)
     case PT_SHLIB:	return "SHLIB";
     case PT_PHDR:	return "PHDR";
     case PT_TLS:	return "TLS";
+    case PT_GNU_SHR:	return "GNU_SHR";
 
     case PT_GNU_EH_FRAME:
 			return "GNU_EH_FRAME";
@@ -6935,6 +6938,8 @@ get_symbol_index_type (unsigned int type
     case SHN_UNDEF:	return "UND";
     case SHN_ABS:	return "ABS";
     case SHN_COMMON:	return "COM";
+    case SHN_GNU_SHARABLE_COMMON:
+			return "GNU_SHARABLE_COM";
     default:
       if (type == SHN_IA_64_ANSI_COMMON
 	  && elf_header.e_machine == EM_IA_64
--- binutils/gas/config/obj-elf.c.shr	2006-12-05 11:27:59.000000000 -0800
+++ binutils/gas/config/obj-elf.c	2007-01-04 12:24:45.000000000 -0800
@@ -68,6 +68,7 @@ static void obj_elf_symver (int);
 static void obj_elf_subsection (int);
 static void obj_elf_popsection (int);
 static void obj_elf_tls_common (int);
+static void obj_elf_sharable_common (int);
 static void obj_elf_lcomm (int);
 static void obj_elf_struct (int);
 
@@ -125,6 +126,8 @@ static const pseudo_typeS elf_pseudo_tab
 
   {"tls_common", obj_elf_tls_common, 0},
 
+  {"sharable_common", obj_elf_sharable_common, 0},
+
   /* End sentinel.  */
   {NULL, NULL, 0},
 };
@@ -369,6 +372,39 @@ obj_elf_tls_common (int ignore ATTRIBUTE
 }
 
 static void
+obj_elf_sharable_common (int ignore ATTRIBUTE_UNUSED)
+{
+  static segT sharable_bss_section;
+  asection *saved_com_section_ptr = elf_com_section_ptr;
+  asection *saved_bss_section = bss_section;
+
+  if (sharable_bss_section == NULL)
+    {
+      flagword applicable;
+      segT seg = now_seg;
+      subsegT subseg = now_subseg;
+
+      /* The .sharable_bss section is for local .sharable_common
+	 symbols.  */
+      sharable_bss_section = subseg_new (".sharable_bss", 0);
+      applicable = bfd_applicable_section_flags (stdoutput);
+      bfd_set_section_flags (stdoutput, sharable_bss_section,
+			     applicable & SEC_ALLOC);
+      seg_info (sharable_bss_section)->bss = 1;
+
+      subseg_set (seg, subseg);
+    }
+
+  elf_com_section_ptr = &_bfd_elf_sharable_com_section;
+  bss_section = sharable_bss_section;
+
+  s_comm_internal (0, elf_common_parse);
+
+  elf_com_section_ptr = saved_com_section_ptr;
+  bss_section = saved_bss_section;
+}
+
+static void
 obj_elf_lcomm (int ignore ATTRIBUTE_UNUSED)
 {
   symbolS *symbolP = s_comm_internal (0, s_lcomm_internal);
@@ -582,11 +618,17 @@ obj_elf_change_section (const char *name
 
 		 .section .lbss,"aw",@progbits
 
+		 "@progbits" is incorrect.  Also for sharable bss
+		 sections, gcc, as of 2005-07-06, will emit
+
+		 .section .sharable_bss,"aw",@progbits
+
 		 "@progbits" is incorrect.  */
 #ifdef TC_I386
 	      && (bed->s->arch_size != 64
 		  || !(ssect->attr & SHF_X86_64_LARGE))
 #endif
+	      && !(ssect->attr & SHF_GNU_SHARABLE)
 	      && ssect->type != SHT_INIT_ARRAY
 	      && ssect->type != SHT_FINI_ARRAY
 	      && ssect->type != SHT_PREINIT_ARRAY)
--- binutils/include/elf/common.h.shr	2006-10-24 23:49:18.000000000 -0700
+++ binutils/include/elf/common.h	2007-01-04 12:25:50.000000000 -0800
@@ -306,6 +306,7 @@
 #define PT_SUNW_EH_FRAME PT_GNU_EH_FRAME      /* Solaris uses the same value */
 #define PT_GNU_STACK	(PT_LOOS + 0x474e551) /* Stack flags */
 #define PT_GNU_RELRO	(PT_LOOS + 0x474e552) /* Read-only after relocation */
+#define PT_GNU_SHR	(PT_LOOS + 0x474e554) /* Sharable segment */
 
 /* Program segment permissions, in program header p_flags field.  */
 
@@ -377,6 +378,8 @@
 #define SHF_MASKOS	0x0FF00000	/* New value, Oct 4, 1999 Draft */
 #define SHF_MASKPROC	0xF0000000	/* Processor-specific semantics */
 
+#define SHF_GNU_SHARABLE 0x01000000	/* sharable section */
+
 /* Values of note segment descriptor types for core files.  */
 
 #define NT_PRSTATUS	1		/* Contains copy of prstatus struct */
@@ -495,6 +498,9 @@
 #define SHN_HIRESERVE	0xFFFF		/* End range of reserved indices */
 #define SHN_BAD		((unsigned) -1) /* Used internally by bfd */
 
+/* Associated symbol is in common sharable */
+#define SHN_GNU_SHARABLE_COMMON (SHN_LOOS + 10)
+
 /* The following constants control how a symbol may be accessed once it has
    become part of an executable or shared library.  */
 
--- binutils/ld/emulparams/elf64_ia64.sh.shr	2006-05-30 09:45:32.000000000 -0700
+++ binutils/ld/emulparams/elf64_ia64.sh	2007-01-04 12:24:45.000000000 -0800
@@ -37,3 +37,4 @@ OTHER_READONLY_SECTIONS="${OTHER_READONL
 # .dtors.  They have to be next to .sbss/.sbss2/.sdata/.sdata2.
 SMALL_DATA_CTOR=" "
 SMALL_DATA_DTOR=" "
+SHARABLE_SECTIONS=yes
--- binutils/ld/emulparams/elf_i386.sh.shr	2006-05-30 09:45:32.000000000 -0700
+++ binutils/ld/emulparams/elf_i386.sh	2007-01-04 12:24:45.000000000 -0800
@@ -12,3 +12,4 @@ GENERATE_SHLIB_SCRIPT=yes
 GENERATE_PIE_SCRIPT=yes
 NO_SMALL_DATA=yes
 SEPARATE_GOTPLT=12
+SHARABLE_SECTIONS=yes
--- binutils/ld/emulparams/elf_x86_64.sh.shr	2006-10-18 09:24:01.000000000 -0700
+++ binutils/ld/emulparams/elf_x86_64.sh	2007-01-04 12:24:45.000000000 -0800
@@ -14,6 +14,7 @@ GENERATE_PIE_SCRIPT=yes
 NO_SMALL_DATA=yes
 LARGE_SECTIONS=yes
 SEPARATE_GOTPLT=24
+SHARABLE_SECTIONS=yes
 
 if [ "x${host}" = "x${target}" ]; then
   case " $EMULATION_LIBPATH " in
--- binutils/ld/emultempl/elf32.em.shr	2006-12-05 11:28:02.000000000 -0800
+++ binutils/ld/emultempl/elf32.em	2007-01-04 12:24:45.000000000 -0800
@@ -55,6 +55,8 @@ Foundation, Inc., 51 Franklin Street - F
 #include "elf/common.h"
 #include "elf-bfd.h"
 
+#include "elf-bfd.h"
+
 /* Declare functions used by various EXTRA_EM_FILEs.  */
 static void gld${EMULATION_NAME}_before_parse (void);
 static void gld${EMULATION_NAME}_after_open (void);
@@ -1456,6 +1458,12 @@ gld${EMULATION_NAME}_place_orphan (asect
 
   secname = bfd_get_section_name (s->owner, s);
 
+  /* Orphaned sharable sections won't have correct page
+     requirements.  */
+  if (elf_section_flags (s) & SHF_GNU_SHARABLE)
+    einfo ("%F%P: unable to place orphaned sharable section %A (%B)\n",
+	   s, s->owner);
+
   if (! link_info.relocatable
       && link_info.combreloc
       && (s->flags & SEC_ALLOC))
--- binutils/ld/scripttempl/elf.sc.shr	2006-10-25 17:31:59.000000000 -0700
+++ binutils/ld/scripttempl/elf.sc	2007-01-04 12:24:45.000000000 -0800
@@ -236,6 +236,40 @@ STACK="  .stack        ${RELOCATING-0}${
     ${RELOCATING+_stack = .;}
     *(.stack)
   }"
+test "${SHARABLE_SECTIONS}" = "yes" && OTHER_READWRITE_SECTIONS="
+  ${OTHER_READWRITE_SECTIONS}
+  /* Sharable data sections.  */
+  .sharable_data ${RELOCATING-0} : ${RELOCATING+ALIGN(${MAXPAGESIZE})}
+  {
+    ${RELOCATING+PROVIDE_HIDDEN (__sharable_data_start = .);}
+    *(.sharable_data${RELOCATING+ .sharable_data.* .gnu.linkonce.shrd.*})
+    /* Align here to ensure that the sharable data section ends at the
+       page boundary.  */
+    ${RELOCATING+. = ALIGN(. != 0 ? ${MAXPAGESIZE} : 1);}
+    ${RELOCATING+PROVIDE_HIDDEN (__sharable_data_end = .);}
+  }
+"
+test "${SHARABLE_SECTIONS}" = "yes" && OTHER_BSS_SECTIONS="
+  ${OTHER_BSS_SECTIONS}
+  /* Sharable bss sections  */
+  .sharable_bss ${RELOCATING-0} : ${RELOCATING+ALIGN(${MAXPAGESIZE})}
+  {
+    ${RELOCATING+PROVIDE_HIDDEN (__sharable_bss_start = .);}
+    *(.dynsharablebss)
+    *(.sharable_bss${RELOCATING+ .sharable_bss.* .gnu.linkonce.shrb.*}) 
+    *(SHARABLE_COMMON)
+    /* Align here to ensure that the sharable bss section ends at the
+       page boundary.  */
+    ${RELOCATING+. = ALIGN(. != 0 ? ${MAXPAGESIZE} : 1);}
+    ${RELOCATING+PROVIDE_HIDDEN (__sharable_bss_end = .);}
+  }
+"
+test "${SHARABLE_SECTIONS}" = "yes" && REL_SHARABLE="
+  .rel.sharable_data	${RELOCATING-0} : { *(.rel.sharable_data${RELOCATING+ .rel.sharable_data.* .rel.gnu.linkonce.shrd.*}) }
+  .rela.sharable_data	${RELOCATING-0} : { *(.rela.sharable_data${RELOCATING+ .rela.sharable_data.* .rela.gnu.linkonce.shrd.*}) }
+  .rel.sharable_bss	${RELOCATING-0} : { *(.rel.sharable_bss${RELOCATING+ .rel.sharable_bss.* .rel.gnu.linkonce.shrb.*}) }
+  .rela.sharable_bss	${RELOCATING-0} : { *(.rela.sharable_bss${RELOCATING+ .rela.sharable_bss.* .rela.gnu.linkonce.shrb.*}) }
+"
 
 # if this is for an embedded system, don't add SIZEOF_HEADERS.
 if [ -z "$EMBEDDED" ]; then
@@ -305,6 +339,7 @@ eval $COMBRELOCCAT <<EOF
   .rel.got      ${RELOCATING-0} : { *(.rel.got) }
   .rela.got     ${RELOCATING-0} : { *(.rela.got) }
   ${OTHER_GOT_RELOC_SECTIONS}
+  ${REL_SHARABLE}
   ${REL_SDATA}
   ${REL_SBSS}
   ${REL_SDATA2}


More information about the Libc-alpha mailing list