| 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 |
| |