diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2013-11-04 10:15:09 -0800 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2013-11-06 09:09:32 -0800 |
commit | bd20f1ced5c064bd633e3d8c8b9a73b5c71e1c7f (patch) | |
tree | 5fd1c547ac6f720ad7b0ae3a050582fc9c7552d9 | |
parent | b9502d3fd7848cd4d843be8bdc28633a3d24438d (diff) | |
download | gdb-bd20f1ced5c064bd633e3d8c8b9a73b5c71e1c7f.zip gdb-bd20f1ced5c064bd633e3d8c8b9a73b5c71e1c7f.tar.gz gdb-bd20f1ced5c064bd633e3d8c8b9a73b5c71e1c7f.tar.bz2 |
Add binutils-sharable.patch
-rw-r--r-- | patches/README | 32 | ||||
-rw-r--r-- | patches/binutils-sharable.patch | 1285 |
2 files changed, 1317 insertions, 0 deletions
diff --git a/patches/README b/patches/README new file mode 100644 index 0000000..124532f --- /dev/null +++ b/patches/README @@ -0,0 +1,32 @@ +#! /bin/sh + +# If you don't use rpm, you can use this file to apply additional Linux +# patches. At the top level of the binutils source tree, do +# +# /bin/sh patches/README +# +# You may have to do +# +# cd bfd +# make headers +# +# if the build fails. + +dir=`dirname $0` +clean=$1 + +patches=" + binutils-sharable.patch +" + +for p in $patches +do + if [ ! -n "$clean" ] + then + suffix=$(echo $p | sed -e "s/.*-\([^-]\+\).patch/\1/") + backup="-b --suffix .$suffix" + fi + patch -E -p1 $backup < $dir/$p || exit 1 +done +find -name "*.orig" | xargs rm -fv +find -name "*.gmo" | xargs rm -fv diff --git a/patches/binutils-sharable.patch b/patches/binutils-sharable.patch new file mode 100644 index 0000000..49d4f60 --- /dev/null +++ b/patches/binutils-sharable.patch @@ -0,0 +1,1285 @@ +From d982080fe4d81ee0a863a0258b317377260a3a8f Mon Sep 17 00:00:00 2001 +From: "H.J. Lu" <hjl.tools@gmail.com> +Date: Mon, 4 Nov 2013 09:44:13 -0800 +Subject: [PATCH] Add PT_GNU_SHR/SHF_GNU_SHARABLE/SHN_GNU_SHARABLE_COMMON + support to gas/ld + +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. +--- + ChangeLog.sharable | 140 ++++++++++++++++++++++++++ + bfd/elf-bfd.h | 21 +++- + bfd/elf.c | 103 +++++++++++++++++++ + bfd/elf32-i386.c | 55 ++++++++-- + bfd/elf64-x86-64.c | 73 +++++++++++--- + bfd/elflink.c | 228 +++++++++++++++++++++++++++++++++++++++++- + bfd/elfnn-ia64.c | 16 ++- + binutils/readelf.c | 5 + + gas/config/obj-elf.c | 42 ++++++++ + include/bfdlink.h | 3 + + include/elf/common.h | 6 ++ + ld/emulparams/elf32_x86_64.sh | 1 + + ld/emulparams/elf64_ia64.sh | 1 + + ld/emulparams/elf_i386.sh | 1 + + ld/emulparams/elf_x86_64.sh | 1 + + ld/emultempl/elf32.em | 7 ++ + ld/ldmain.c | 1 + + ld/scripttempl/elf.sc | 35 +++++++ + 18 files changed, 712 insertions(+), 27 deletions(-) + create mode 100644 ChangeLog.sharable + +diff --git a/ChangeLog.sharable b/ChangeLog.sharable +new file mode 100644 +index 0000000..3ccf957 +--- /dev/null ++++ b/ChangeLog.sharable +@@ -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. +diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h +index add80b3..525d4b9 100644 +--- a/bfd/elf-bfd.h ++++ b/bfd/elf-bfd.h +@@ -1210,8 +1210,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 *); +@@ -2148,6 +2149,24 @@ extern bfd_boolean bfd_elf_link_add_symbols + (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 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 *); +diff --git a/bfd/elf.c b/bfd/elf.c +index 8df38ee..88c182e 100644 +--- a/bfd/elf.c ++++ b/bfd/elf.c +@@ -2102,6 +2102,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 } + }; + +@@ -2156,6 +2158,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 } + }; + +@@ -3615,6 +3619,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) +@@ -3785,6 +3815,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; +@@ -4093,6 +4125,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. */ +@@ -4120,6 +4168,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); +@@ -4661,6 +4763,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 +diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c +index 560e05c..bd5a1d2 100644 +--- a/bfd/elf32-i386.c ++++ b/bfd/elf32-i386.c +@@ -819,6 +819,9 @@ struct elf_i386_link_hash_table + + /* The index of the next unused R_386_IRELATIVE slot in .rel.plt. */ + bfd_vma next_irelative_index; ++ ++ asection *sdynsharablebss; ++ asection *srelsharablebss; + }; + + /* Get the i386 ELF linker hash table from a link_info structure. */ +@@ -997,10 +1000,19 @@ elf_i386_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info) + + htab->sdynbss = bfd_get_linker_section (dynobj, ".dynbss"); + if (!info->shared) +- htab->srelbss = bfd_get_linker_section (dynobj, ".rel.bss"); ++ { ++ htab->srelbss = bfd_get_linker_section (dynobj, ".rel.bss"); ++ htab->sdynsharablebss ++ = bfd_get_linker_section (dynobj, ".dynsharablebss"); ++ htab->srelsharablebss ++ = bfd_get_linker_section (dynobj, ".rel.sharable_bss"); ++ } + + if (!htab->sdynbss +- || (!info->shared && !htab->srelbss)) ++ || (!info->shared ++ && (!htab->srelbss ++ || !htab->sdynsharablebss ++ || !htab->srelsharablebss))) + abort (); + + if (get_elf_i386_backend_data (dynobj)->is_vxworks +@@ -2154,17 +2166,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 (h, s); + } + +@@ -2886,6 +2904,7 @@ elf_i386_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info) + || s == htab->elf.iplt + || s == htab->elf.igotplt + || s == htab->plt_eh_frame ++ || s == htab->sdynsharablebss + || s == htab->sdynbss) + { + /* Strip these too. */ +@@ -4682,20 +4701,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; +@@ -5016,7 +5041,8 @@ elf_i386_add_symbol_hook (bfd * abfd, + || ELF_ST_BIND (sym->st_info) == STB_GNU_UNIQUE)) + elf_tdata (info->output_bfd)->has_gnu_symbols = TRUE; + +- return TRUE; ++ return _bfd_elf_add_sharable_symbol (abfd, info, sym, namep, flagsp, ++ secp, valp); + } + + #define TARGET_LITTLE_SYM bfd_elf32_i386_vec +@@ -5070,6 +5096,19 @@ elf_i386_add_symbol_hook (bfd * abfd, + #undef elf_backend_post_process_headers + #define elf_backend_post_process_headers _bfd_elf_set_osabi + ++#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. */ +diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c +index f748641..bc5b578 100644 +--- a/bfd/elf64-x86-64.c ++++ b/bfd/elf64-x86-64.c +@@ -771,6 +771,9 @@ struct elf_x86_64_link_hash_table + bfd_vma next_jump_slot_index; + /* The index of the next R_X86_64_IRELATIVE entry in .rela.plt. */ + bfd_vma next_irelative_index; ++ ++ asection *sdynsharablebss; ++ asection *srelsharablebss; + }; + + /* Get the x86-64 ELF linker hash table from a link_info structure. */ +@@ -968,10 +971,19 @@ elf_x86_64_create_dynamic_sections (bfd *dynobj, + + htab->sdynbss = bfd_get_linker_section (dynobj, ".dynbss"); + if (!info->shared) +- htab->srelbss = bfd_get_linker_section (dynobj, ".rela.bss"); ++ { ++ htab->srelbss = bfd_get_linker_section (dynobj, ".rela.bss"); ++ htab->sdynsharablebss ++ = bfd_get_linker_section (dynobj, ".dynsharablebss"); ++ htab->srelsharablebss ++ = bfd_get_linker_section (dynobj, ".rela.sharable_bss"); ++ } + + if (!htab->sdynbss +- || (!info->shared && !htab->srelbss)) ++ || (!info->shared ++ && (!htab->srelbss ++ || !htab->sdynsharablebss ++ || !htab->srelsharablebss))) + abort (); + + if (!info->no_ld_generated_unwind_info +@@ -2248,6 +2260,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. */ +@@ -2255,12 +2269,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 (h, s); + } + +@@ -2960,6 +2978,7 @@ elf_x86_64_size_dynamic_sections (bfd *output_bfd, + || s == htab->elf.iplt + || s == htab->elf.igotplt + || s == htab->plt_eh_frame ++ || s == htab->sdynsharablebss + || s == htab->sdynbss) + { + /* Strip this section if we don't need it; see the +@@ -4720,13 +4739,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 +@@ -4734,7 +4759,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; +@@ -5069,7 +5094,8 @@ elf_x86_64_add_symbol_hook (bfd *abfd, + || ELF_ST_BIND (sym->st_info) == STB_GNU_UNIQUE)) + elf_tdata (info->output_bfd)->has_gnu_symbols = TRUE; + +- return TRUE; ++ return _bfd_elf_add_sharable_symbol (abfd, info, sym, namep, flagsp, ++ secp, valp); + } + + +@@ -5085,7 +5111,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. */ +@@ -5103,22 +5130,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; + } +@@ -5127,7 +5158,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; + } +@@ -5137,9 +5168,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 +@@ -5148,7 +5182,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) +@@ -5156,13 +5191,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 +diff --git a/bfd/elflink.c b/bfd/elflink.c +index 1e6abd9..e187d91 100644 +--- a/bfd/elflink.c ++++ b/bfd/elflink.c +@@ -385,6 +385,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; ++ } + } + } + +@@ -1347,7 +1368,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; + } +@@ -13047,3 +13069,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; ++} +diff --git a/bfd/elfnn-ia64.c b/bfd/elfnn-ia64.c +index 117b4c8..33c7ee4 100644 +--- a/bfd/elfnn-ia64.c ++++ b/bfd/elfnn-ia64.c +@@ -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. */ +@@ -5069,6 +5070,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 +diff --git a/binutils/readelf.c b/binutils/readelf.c +index 0389f14..cdc18ba 100644 +--- a/binutils/readelf.c ++++ b/binutils/readelf.c +@@ -1406,6 +1406,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 +@@ -3035,6 +3037,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"; +@@ -9264,6 +9267,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 +diff --git a/gas/config/obj-elf.c b/gas/config/obj-elf.c +index 3377261..286df1f 100644 +--- a/gas/config/obj-elf.c ++++ b/gas/config/obj-elf.c +@@ -78,6 +78,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); + +@@ -138,6 +139,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) + } + + 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); +@@ -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) +diff --git a/include/bfdlink.h b/include/bfdlink.h +index 1ac0738..8f6f2dc 100644 +--- a/include/bfdlink.h ++++ b/include/bfdlink.h +@@ -387,6 +387,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; +diff --git a/include/elf/common.h b/include/elf/common.h +index cd3bcdd..4f5e4b6 100644 +--- a/include/elf/common.h ++++ b/include/elf/common.h +@@ -437,6 +437,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. */ + +@@ -519,6 +520,8 @@ + are not to be further + relocated. */ + ++#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 */ +@@ -688,6 +691,9 @@ + #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. */ + +diff --git a/ld/emulparams/elf32_x86_64.sh b/ld/emulparams/elf32_x86_64.sh +index d34297b..9fb8982 100644 +--- a/ld/emulparams/elf32_x86_64.sh ++++ b/ld/emulparams/elf32_x86_64.sh +@@ -16,6 +16,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 +diff --git a/ld/emulparams/elf64_ia64.sh b/ld/emulparams/elf64_ia64.sh +index 7e5e54d..d8cf531 100644 +--- a/ld/emulparams/elf64_ia64.sh ++++ b/ld/emulparams/elf64_ia64.sh +@@ -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 +diff --git a/ld/emulparams/elf_i386.sh b/ld/emulparams/elf_i386.sh +index add700f..dc2d6ef 100644 +--- a/ld/emulparams/elf_i386.sh ++++ b/ld/emulparams/elf_i386.sh +@@ -13,6 +13,7 @@ GENERATE_PIE_SCRIPT=yes + NO_SMALL_DATA=yes + SEPARATE_GOTPLT="SIZEOF (.got.plt) >= 12 ? 12 : 0" + IREL_IN_PLT= ++SHARABLE_SECTIONS=yes + + # Linux modify the default library search path to first include + # a 32-bit specific directory. +diff --git a/ld/emulparams/elf_x86_64.sh b/ld/emulparams/elf_x86_64.sh +index 4842257..e9cd479 100644 +--- a/ld/emulparams/elf_x86_64.sh ++++ b/ld/emulparams/elf_x86_64.sh +@@ -16,6 +16,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 +diff --git a/ld/emultempl/elf32.em b/ld/emultempl/elf32.em +index 682f5e5..510ca2f 100644 +--- a/ld/emultempl/elf32.em ++++ b/ld/emultempl/elf32.em +@@ -105,6 +105,7 @@ gld${EMULATION_NAME}_before_parse (void) + input_flags.dynamic = ${DYNAMIC_LINK-TRUE}; + config.has_shared = `if test -n "$GENERATE_SHLIB_SCRIPT" ; then echo TRUE ; else echo FALSE ; fi`; + config.separate_code = `if test "x${SEPARATE_CODE}" = xyes ; then echo TRUE ; else echo FALSE ; fi`; ++ link_info.sharable_sections = `if test "$SHARABLE_SECTIONS" = "yes" ; then echo TRUE ; else echo FALSE ; fi`; + } + + EOF +@@ -1816,6 +1817,12 @@ gld${EMULATION_NAME}_place_orphan (asection *s, + int iself = s->owner->xvec->flavour == bfd_target_elf_flavour; + unsigned int sh_type = iself ? elf_section_type (s) : SHT_NULL; + ++ /* 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)) +diff --git a/ld/ldmain.c b/ld/ldmain.c +index 019df71..8a5f01f 100644 +--- a/ld/ldmain.c ++++ b/ld/ldmain.c +@@ -289,6 +289,7 @@ main (int argc, char **argv) + link_info.pei386_auto_import = -1; + link_info.spare_dynamic_tags = 5; + link_info.path_separator = ':'; ++ link_info.sharable_sections = FALSE; + + ldfile_add_arch (""); + emulation = get_emulation (argc, argv); +diff --git a/ld/scripttempl/elf.sc b/ld/scripttempl/elf.sc +index e8126cb..922a906 100644 +--- a/ld/scripttempl/elf.sc ++++ b/ld/scripttempl/elf.sc +@@ -298,6 +298,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})" +@@ -392,6 +426,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} +-- +1.8.3.1 + |