]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Add PT_GNU_SHR/SHF_GNU_SHARABLE/SHN_GNU_SHARABLE_COMMON support to gas/ld users/hjl/sharable
authorH.J. Lu <hjl.tools@gmail.com>
Tue, 25 Aug 2015 16:42:20 +0000 (09:42 -0700)
committerH.J. Lu <hjl.tools@gmail.com>
Wed, 22 Jun 2016 13:04:17 +0000 (06:04 -0700)
PT_GNU_SHR/SHF_GNU_SHARABLE/SHN_GNU_SHARABLE_COMMON are used to group
data into a PT_GNU_SHR to improve performance on NUMA system.

18 files changed:
ChangeLog.sharable [new file with mode: 0644]
bfd/elf-bfd.h
bfd/elf.c
bfd/elf32-i386.c
bfd/elf64-x86-64.c
bfd/elflink.c
bfd/elfnn-ia64.c
binutils/readelf.c
gas/config/obj-elf.c
include/bfdlink.h
include/elf/common.h
ld/emulparams/elf32_x86_64.sh
ld/emulparams/elf64_ia64.sh
ld/emulparams/elf_i386.sh
ld/emulparams/elf_x86_64.sh
ld/emultempl/elf32.em
ld/ldmain.c
ld/scripttempl/elf.sc

diff --git a/ChangeLog.sharable b/ChangeLog.sharable
new file mode 100644 (file)
index 0000000..3ccf957
--- /dev/null
@@ -0,0 +1,140 @@
+bfd/
+
+2013-04-05  H.J. Lu  <hongjiu.lu@intel.com>
+
+       * elf-bfd.h (struct elf_backend_data <merge_symbol>):  Add abfd,
+       newdyn and olddyn.  Remove const from oldsec.
+       (_bfd_elf_sharable_merge_symbol): Updated.
+       * elf64-x86-64.c (elf_x86_64_merge_symbol): Likewise.
+       * elflink.c (_bfd_elf_merge_symbol): Update bed->merge_symbol
+       call.
+
+2009-12-12  H.J. Lu  <hongjiu.lu@intel.com>
+
+       * elf.c: Fix shadowed variable warnings.
+       * elf64-x86-64.c: Likewise.
+       * elflink.c: Likewise.
+
+2007-01-23  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.
+
+       * elfnn-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/
+
+2007-01-23  H.J. Lu  <hongjiu.lu@intel.com>
+
+       * bfdlink.h (bfd_link_info): Add 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/
+
+2011-01-08  H.J. Lu  <hongjiu.lu@intel.com>
+
+       * emulparams/elf32_x86_64.sh (SHARABLE_SECTIONS): Set to yes.
+
+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 (gld${EMULATION_NAME}_before_parse): Set
+       link_info.sharable_sections based on $SHARABLE_SECTIONS.
+       (gld${EMULATION_NAME}_place_orphan): Don't allow orphaned
+       sharable sections.
+
+       * ldmain.c (main): Initialize link_info.sharable_sections.
+       * scripttempl/elf.sc: Support sharable sections.
index 163ef35fadcc41987dd234c56d818be606a10cfe..63074d8d622fb26e1d09f42066a3a7c970e6b9aa 100644 (file)
@@ -1283,8 +1283,9 @@ struct elf_backend_data
   /* Return TRUE if we can merge 2 definitions.  */
   bfd_boolean (*merge_symbol) (struct elf_link_hash_entry *,
                               const Elf_Internal_Sym *, asection **,
+                              bfd_boolean, bfd_boolean, bfd *,
                               bfd_boolean, bfd_boolean,
-                              bfd *, const asection *);
+                              bfd *, asection *);
 
   /* Return TRUE if symbol should be hashed in the `.gnu.hash' section.  */
   bfd_boolean (*elf_hash_symbol) (struct elf_link_hash_entry *);
@@ -2268,6 +2269,24 @@ extern bfd_boolean _bfd_elf_add_dynamic_entry
   (struct bfd_link_info *, bfd_vma, bfd_vma);
 extern bfd_boolean _bfd_elf_link_check_relocs
   (bfd *, struct bfd_link_info *);
+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 elf_link_hash_entry *, const Elf_Internal_Sym *,
+   asection **, bfd_boolean, bfd_boolean, bfd *,
+   bfd_boolean, bfd_boolean, bfd *, asection *);
 
 extern bfd_boolean bfd_elf_link_record_dynamic_symbol
   (struct bfd_link_info *, struct elf_link_hash_entry *);
index aaf2b5351d326f5b2312aaf698b959bd253d1136..ac8bd60171e7d5ee02f052c38aaf10d1c9a1e0af 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -2570,6 +2570,8 @@ static const struct bfd_elf_special_section special_sections_g[] =
   { 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 }
 };
 
@@ -2624,6 +2626,8 @@ static const struct bfd_elf_special_section special_sections_s[] =
   /* 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 }
 };
 
@@ -4233,6 +4237,32 @@ get_program_header_size (bfd *abfd, struct bfd_link_info *info)
        }
     }
 
+  /* 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)
@@ -4403,6 +4433,8 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info)
       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;
@@ -4723,6 +4755,22 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info)
                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.  */
@@ -4770,6 +4818,60 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info)
          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 j;
+
+         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 (j = 0; j < sharable_data_count; ++j)
+           {
+             m->sections[j] = 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 j;
+
+         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 (j = 0; j < sharable_bss_count; ++j)
+           {
+             m->sections[j] = 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_eh_frame_hdr (abfd);
@@ -5307,6 +5409,7 @@ assign_file_positions_for_load_sections (bfd *abfd,
          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)
              && (this_hdr->sh_type != SHT_NOBITS
                  || ((this_hdr->sh_flags & SHF_ALLOC) != 0
index 417957214dbb6257e97fe1510ebd431807a1a256..a90937b769c8913ed3216717a9b6e0496a673677 100644 (file)
@@ -887,6 +887,9 @@ struct elf_i386_link_hash_table
   /* TRUE if there are dynamic relocs against IFUNC symbols that apply
      to read-only sections.  */
   bfd_boolean readonly_dynrelocs_against_ifunc;
+
+  asection *sdynsharablebss;
+  asection *srelsharablebss;
 };
 
 /* Get the i386 ELF linker hash table from a link_info structure.  */
@@ -1090,10 +1093,10 @@ elf_i386_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info)
   if (bfd_link_executable (info))
     {
       /* Always allow copy relocs for building executables.  */
+      const struct elf_backend_data *bed = get_elf_backend_data (dynobj);
       asection *s = bfd_get_linker_section (dynobj, ".rel.bss");
       if (s == NULL)
        {
-         const struct elf_backend_data *bed = get_elf_backend_data (dynobj);
          s = bfd_make_section_anyway_with_flags (dynobj,
                                                  ".rel.bss",
                                                  (bed->dynamic_sec_flags
@@ -1104,6 +1107,32 @@ elf_i386_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info)
            return FALSE;
        }
       htab->srelbss = s;
+
+      s = bfd_get_linker_section (dynobj, ".dynsharablebss");
+      if (s == NULL)
+       {
+         s = bfd_make_section_anyway_with_flags (dynobj,
+                                                 ".dynsharablebss",
+                                                 (SEC_ALLOC
+                                                  | SEC_LINKER_CREATED));
+         if (s == NULL)
+           return FALSE;
+       }
+      htab->sdynsharablebss = s;
+
+      s = bfd_get_linker_section (dynobj, ".rel.sharable_bss");
+      if (s == NULL)
+       {
+         s = bfd_make_section_anyway_with_flags (dynobj,
+                                                 ".rel.sharable_bss",
+                                                 (bed->dynamic_sec_flags
+                                                  | SEC_READONLY));
+         if (s == NULL
+             || ! bfd_set_section_alignment (dynobj, s,
+                                             bed->s->log_file_align))
+           return FALSE;
+       }
+      htab->srelsharablebss = s;
     }
 
   if (get_elf_i386_backend_data (dynobj)->is_vxworks
@@ -2586,17 +2615,23 @@ elf_i386_adjust_dynamic_symbol (struct bfd_link_info *info,
      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 && h->size != 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;
     }
 
-  s = htab->sdynbss;
-
   return _bfd_elf_adjust_dynamic_copy (info, h, s);
 }
 
@@ -3408,6 +3443,7 @@ elf_i386_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
               || s == htab->elf.igotplt
               || s == htab->plt_got
               || s == htab->plt_eh_frame
+              || s == htab->sdynsharablebss
               || s == htab->sdynbss)
        {
          /* Strip these too.  */
@@ -5560,20 +5596,26 @@ do_glob_dat:
   if (h->needs_copy)
     {
       Elf_Internal_Rela rel;
+      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);
-      elf_append_rel (output_bfd, htab->srelbss, &rel);
+      elf_append_rel (output_bfd, s, &rel);
     }
 
   return TRUE;
@@ -6032,6 +6074,22 @@ elf_i386_hash_symbol (struct elf_link_hash_entry *h)
   return _bfd_elf_hash_symbol (h);
 }
 
+/* Hook called by the linker routine which adds symbols from an object
+   file.  */
+
+static bfd_boolean
+elf_i386_add_symbol_hook (bfd * abfd,
+                         struct bfd_link_info * info,
+                         Elf_Internal_Sym * sym,
+                         const char ** namep,
+                         flagword * flagsp,
+                         asection ** secp,
+                         bfd_vma * valp)
+{
+  return _bfd_elf_add_sharable_symbol (abfd, info, sym, namep, flagsp,
+                                      secp, valp);
+}
+
 #define TARGET_LITTLE_SYM              i386_elf32_vec
 #define TARGET_LITTLE_NAME             "elf32-i386"
 #define ELF_ARCH                       bfd_arch_i386
@@ -6080,8 +6138,22 @@ elf_i386_hash_symbol (struct elf_link_hash_entry *h)
 #define elf_backend_omit_section_dynsym \
   ((bfd_boolean (*) (bfd *, struct bfd_link_info *, asection *)) bfd_true)
 #define elf_backend_hash_symbol                      elf_i386_hash_symbol
+#define elf_backend_add_symbol_hook          elf_i386_add_symbol_hook
 #define elf_backend_fixup_symbol             elf_i386_fixup_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.  */
index f9202085b38968cdada56b190a210ebcfd3b409f..5c7eb3be9723998a20d8667e8ccd719a94abd1ac 100644 (file)
@@ -909,6 +909,9 @@ struct elf_x86_64_link_hash_table
   /* TRUE if there are dynamic relocs against IFUNC symbols that apply
      to read-only sections.  */
   bfd_boolean readonly_dynrelocs_against_ifunc;
+
+  asection *sdynsharablebss;
+  asection *srelsharablebss;
 };
 
 /* Get the x86-64 ELF linker hash table from a link_info structure.  */
@@ -1133,10 +1136,10 @@ elf_x86_64_create_dynamic_sections (bfd *dynobj,
   if (bfd_link_executable (info))
     {
       /* Always allow copy relocs for building executables.  */
+      const struct elf_backend_data *bed = get_elf_backend_data (dynobj);
       asection *s = bfd_get_linker_section (dynobj, ".rela.bss");
       if (s == NULL)
        {
-         const struct elf_backend_data *bed = get_elf_backend_data (dynobj);
          s = bfd_make_section_anyway_with_flags (dynobj,
                                                  ".rela.bss",
                                                  (bed->dynamic_sec_flags
@@ -1147,6 +1150,32 @@ elf_x86_64_create_dynamic_sections (bfd *dynobj,
            return FALSE;
        }
       htab->srelbss = s;
+
+      s = bfd_get_linker_section (dynobj, ".dynsharablebss");
+      if (s == NULL)
+       {
+         s = bfd_make_section_anyway_with_flags (dynobj,
+                                                 ".dynsharablebss",
+                                                 (SEC_ALLOC
+                                                  | SEC_LINKER_CREATED));
+         if (s == NULL)
+           return FALSE;
+       }
+      htab->sdynsharablebss = s;
+
+      s = bfd_get_linker_section (dynobj, ".rela.sharable_bss");
+      if (s == NULL)
+       {
+         s = bfd_make_section_anyway_with_flags (dynobj,
+                                                 ".rela.sharable_bss",
+                                                 (bed->dynamic_sec_flags
+                                                  | SEC_READONLY));
+         if (s == NULL
+             || ! bfd_set_section_alignment (dynobj, s,
+                                             bed->s->log_file_align))
+           return FALSE;
+       }
+      htab->srelsharablebss = s;
     }
 
   if (!info->no_ld_generated_unwind_info
@@ -2986,6 +3015,8 @@ elf_x86_64_adjust_dynamic_symbol (struct bfd_link_info *info,
   if (htab == NULL)
     return FALSE;
 
+  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.  */
@@ -2993,12 +3024,16 @@ elf_x86_64_adjust_dynamic_symbol (struct bfd_link_info *info,
     {
       const struct elf_backend_data *bed;
       bed = get_elf_backend_data (info->output_bfd);
-      htab->srelbss->size += bed->s->sizeof_rela;
+      if (elf_section_flags (h->root.u.def.section) & SHF_GNU_SHARABLE)
+       {
+         htab->srelsharablebss->size += bed->s->sizeof_rela;
+         s = htab->sdynsharablebss;
+       }
+      else
+       htab->srelbss->size += bed->s->sizeof_rela;
       h->needs_copy = 1;
     }
 
-  s = htab->sdynbss;
-
   return _bfd_elf_adjust_dynamic_copy (info, h, s);
 }
 
@@ -3812,6 +3847,7 @@ elf_x86_64_size_dynamic_sections (bfd *output_bfd,
          || s == htab->plt_bnd
          || s == htab->plt_got
          || s == htab->plt_eh_frame
+         || s == htab->sdynsharablebss
          || s == htab->sdynbss)
        {
          /* Strip this section if we don't need it; see the
@@ -6004,13 +6040,19 @@ do_glob_dat:
   if (h->needs_copy)
     {
       Elf_Internal_Rela rela;
+      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
@@ -6018,7 +6060,7 @@ do_glob_dat:
                       + h->root.u.def.section->output_offset);
       rela.r_info = htab->r_info (h->dynindx, R_X86_64_COPY);
       rela.r_addend = 0;
-      elf_append_rela (output_bfd, htab->srelbss, &rela);
+      elf_append_rela (output_bfd, s, &rela);
     }
 
   return TRUE;
@@ -6540,7 +6582,8 @@ elf_x86_64_add_symbol_hook (bfd *abfd,
       return TRUE;
     }
 
-  return TRUE;
+  return _bfd_elf_add_sharable_symbol (abfd, info, sym, namep, flagsp,
+                                      secp, valp);
 }
 
 
@@ -6556,7 +6599,8 @@ elf_x86_64_elf_section_from_bfd_section (bfd *abfd ATTRIBUTE_UNUSED,
       *index_return = SHN_X86_64_LCOMMON;
       return TRUE;
     }
-  return FALSE;
+  return _bfd_elf_sharable_section_from_bfd_section (abfd, sec,
+                                                    index_return);
 }
 
 /* Process a symbol.  */
@@ -6574,22 +6618,26 @@ elf_x86_64_symbol_processing (bfd *abfd ATTRIBUTE_UNUSED,
       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
 elf_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
 elf_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;
 }
@@ -6598,7 +6646,7 @@ static asection *
 elf_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;
 }
@@ -6608,9 +6656,12 @@ elf_x86_64_merge_symbol (struct elf_link_hash_entry *h,
                         const Elf_Internal_Sym *sym,
                         asection **psec,
                         bfd_boolean newdef,
+                        bfd_boolean newdyn,
+                        bfd *abfd,
                         bfd_boolean olddef,
+                        bfd_boolean olddyn,
                         bfd *oldbfd,
-                        const asection *oldsec)
+                        asection *oldsec)
 {
   /* A normal common symbol and a large common symbol result in a
      normal common symbol.  We turn the large common symbol into a
@@ -6619,7 +6670,8 @@ elf_x86_64_merge_symbol (struct elf_link_hash_entry *h,
       && h->root.type == bfd_link_hash_common
       && !newdef
       && bfd_is_com_section (*psec)
-      && oldsec != *psec)
+      && oldsec != *psec
+      && _bfd_elf_sharable_common_section_index (oldsec) == SHN_COMMON)
     {
       if (sym->st_shndx == SHN_COMMON
          && (elf_section_flags (oldsec) & SHF_X86_64_LARGE) != 0)
@@ -6627,13 +6679,19 @@ elf_x86_64_merge_symbol (struct elf_link_hash_entry *h,
          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 = bfd_com_section_ptr;
+       {
+         *psec = bfd_com_section_ptr;
+         return TRUE;
+       }
     }
 
-  return TRUE;
+  return _bfd_elf_sharable_merge_symbol (h, sym, psec, newdef, newdyn,
+                                        abfd, olddef, olddyn, oldbfd,
+                                        oldsec);
 }
 
 static int
index bb83854a275120cec34ae05d81293c01ef740f98..fe02b75c8e53706fa53ad6fb49913f06e49fbc90 100644 (file)
@@ -448,6 +448,27 @@ _bfd_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
          if (s == NULL
              || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
            return FALSE;
+
+         if (info->sharable_sections)
+           {
+             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;
+           }
        }
     }
 
@@ -1464,7 +1485,8 @@ _bfd_elf_merge_symbol (bfd *abfd,
      backend to check if we can merge them.  */
   if (bed->merge_symbol != NULL)
     {
-      if (!bed->merge_symbol (h, sym, psec, newdef, olddef, oldbfd, oldsec))
+      if (!bed->merge_symbol (h, sym, psec, newdef, newdyn, abfd,
+                             olddef, olddyn, oldbfd, oldsec))
        return FALSE;
       sec = *psec;
     }
@@ -13870,3 +13892,207 @@ elf_append_rel (bfd *abfd, asection *s, Elf_Internal_Rela *rel)
   BFD_ASSERT (loc + bed->s->sizeof_rel <= s->contents + s->size);
   bed->s->swap_reloc_out (abfd, rel, loc);
 }
+
+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_return)
+{
+  if (sec == &_bfd_elf_sharable_com_section)
+    {
+      *index_return = 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 elf_link_hash_entry *h,
+                               const Elf_Internal_Sym *sym,
+                               asection **psec,
+                               bfd_boolean newdef,
+                               bfd_boolean newdyn,
+                               bfd *abfd,
+                               bfd_boolean olddef,
+                               bfd_boolean olddyn,
+                               bfd *oldbfd,
+                               asection *oldsec)
+{
+  asection *sec = *psec;
+
+  /* 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 = 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;
+}
index b8e0e76c94200717506b1136d0fcc7e8041a61fc..3c9e9a662df4f5c5eccb79a20fc3850d20e767e5 100644 (file)
@@ -1055,7 +1055,8 @@ elfNN_ia64_add_symbol_hook (bfd *abfd,
       *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.  */
@@ -5066,6 +5067,19 @@ elfNN_hpux_backend_symbol_processing (bfd *abfd ATTRIBUTE_UNUSED,
 #define elf_backend_special_sections   elfNN_ia64_special_sections
 #define elf_backend_default_execstack  0
 
+#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
index 274ddd17266aef6e4ad1f67af8a13a21500ff2af..a7861c2f86c03525147f5dd502c1a350b449ef1e 100644 (file)
@@ -1580,6 +1580,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)
                               || (elf_header.e_machine == EM_TI_C6000
@@ -3717,6 +3719,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";
@@ -10463,6 +10466,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
index 8af563fbd24e6d1c6c1b99175d77248eace9745a..da3b483c3c5646ce41e2f91258591f29ea3c8b27 100644 (file)
@@ -76,6 +76,7 @@ static void obj_elf_subsection (int);
 static void obj_elf_popsection (int);
 static void obj_elf_gnu_attribute (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);
 
@@ -136,6 +137,8 @@ static const pseudo_typeS elf_pseudo_table[] =
 
   {"tls_common", obj_elf_tls_common, 0},
 
+  {"sharable_common", obj_elf_sharable_common, 0},
+
   /* End sentinel.  */
   {NULL, NULL, 0},
 };
@@ -393,6 +396,39 @@ obj_elf_tls_common (int ignore ATTRIBUTE_UNUSED)
     symbol_get_bfdsym (symbolP)->flags |= BSF_THREAD_LOCAL;
 }
 
+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)
 {
@@ -611,11 +647,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)
index b392d54b3557690161beb5a13505668557041756..4d0634474e6f4bc3547bd726a3dd1ab6c8e3bd63 100644 (file)
@@ -433,6 +433,9 @@ struct bfd_link_info
      --dynamic-list command line options.  */
   unsigned int dynamic: 1;
 
+  /* TRUE if sharables sections may be created.  */
+  unsigned int sharable_sections: 1;
+
   /* TRUE if PT_GNU_STACK segment should be created with PF_R|PF_W|PF_X
      flags.  */
   unsigned int execstack: 1;
index 087d876f6bc1bf5dd34102664ecdeefbbb9da6ac..111f206f8ec215fab064a2508f4f1ba2c65726e7 100644 (file)
 #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.  */
 
                                           are not to be further
                                           relocated.  */
 
+#define SHF_GNU_SHARABLE 0x01000000    /* sharable section */
+
 /* Compression types */
 #define ELFCOMPRESS_ZLIB   1           /* Compressed with zlib.  */
 #define ELFCOMPRESS_LOOS   0x60000000  /* OS-specific semantics, lo */
 #define STT_LOPROC     13              /* Processor-specific semantics */
 #define STT_HIPROC     15              /* Processor-specific semantics */
 
+/* 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.  */
 
index 9050730834f4b484e2d1b472cb27a1d71461d484..b5507e23efd92e676e1016a55952a814c4eef462 100644 (file)
@@ -21,6 +21,7 @@ LARGE_SECTIONS=yes
 LARGE_BSS_AFTER_BSS=
 SEPARATE_GOTPLT="SIZEOF (.got.plt) >= 24 ? 24 : 0"
 IREL_IN_PLT=
+SHARABLE_SECTIONS=yes
 
 if [ "x${host}" = "x${target}" ]; then
   case " $EMULATION_LIBPATH " in
index 7e5e54d391ed8ce0fc03a07e50eff2f683a42257..d8cf531f0dab7201f0b72074a75bbdea1ef02f51 100644 (file)
@@ -37,3 +37,4 @@ OTHER_READONLY_SECTIONS="${OTHER_READONLY_SECTIONS}
 # .dtors.  They have to be next to .sbss/.sbss2/.sdata/.sdata2.
 SMALL_DATA_CTOR=" "
 SMALL_DATA_DTOR=" "
+SHARABLE_SECTIONS=yes
index b08e6610d0bc222fd0513ab31384e4cb6353f0d6..2dd59fec361dadd34e69d2874489281cd5e1e0d9 100644 (file)
@@ -21,6 +21,7 @@ IREL_IN_PLT=
 TINY_READONLY_SECTION="
 .plt.got      ${RELOCATING-0} : { *(.plt.got) }
 "
+SHARABLE_SECTIONS=yes
 
 # Linux modify the default library search path to first include
 # a 32-bit specific directory.
index 6055204874e298bdd13dfc7d60c7858542977c20..f1cca77b6e93c4b906dc142930b45744f268154f 100644 (file)
@@ -26,6 +26,7 @@ TINY_READONLY_SECTION="
 .plt.got      ${RELOCATING-0} : { *(.plt.got) }
 .plt.bnd      ${RELOCATING-0} : { *(.plt.bnd) }
 "
+SHARABLE_SECTIONS=yes
 
 if [ "x${host}" = "x${target}" ]; then
   case " $EMULATION_LIBPATH " in
index 47fa549a9afef3c5d5a5538574dba5a7788fb4d6..152fb934738cbddc60ca43b112fa65e1b3c96b15 100644 (file)
@@ -106,6 +106,7 @@ gld${EMULATION_NAME}_before_parse (void)
   `if test -n "$CALL_NOP_BYTE" ; then echo link_info.call_nop_byte = $CALL_NOP_BYTE; fi`;
   link_info.check_relocs_after_open_input = `if test "x${CHECK_RELOCS_AFTER_OPEN_INPUT}" = xyes ; then echo TRUE ; else echo FALSE ; fi`;
   link_info.relro = DEFAULT_LD_Z_RELRO;
+  link_info.sharable_sections = `if test "$SHARABLE_SECTIONS" = "yes" ; then echo TRUE ; else echo FALSE ; fi`;
 }
 
 EOF
@@ -1854,6 +1855,12 @@ gld${EMULATION_NAME}_place_orphan (asection *s,
   flagword flags;
   asection *nexts;
 
+  /* 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 (!bfd_link_relocatable (&link_info)
       && link_info.combreloc
       && (s->flags & SEC_ALLOC))
index e7a8dff9d262fe7d44bf3521c2815894593f44e8..7be099920375c5041aea24b1fa8964fabbe88a1c 100644 (file)
@@ -285,6 +285,7 @@ main (int argc, char **argv)
 #ifdef DEFAULT_FLAG_COMPRESS_DEBUG
   link_info.compress_debug = COMPRESS_DEBUG_GABI_ZLIB;
 #endif
+  link_info.sharable_sections = FALSE;
 
   ldfile_add_arch ("");
   emulation = get_emulation (argc, argv);
index f0c64390729ec19ed454ecc9a156057459b20467..24af0ebd6e400a5b5032f58e130d3b4f292a03e6 100644 (file)
@@ -308,6 +308,40 @@ STACK="  .stack        ${RELOCATING-0}${RELOCATING+${STACK_ADDR}} :
     ${RELOCATING+${USER_LABEL_PREFIX}_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.*}) }
+"
 
 TEXT_START_ADDR="SEGMENT_START(\"text-segment\", ${TEXT_START_ADDR})"
 SHLIB_TEXT_START_ADDR="SEGMENT_START(\"text-segment\", ${SHLIB_TEXT_START_ADDR:-0})"
@@ -408,6 +442,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}