#!/bin/sh -e ## 206-hjl-binutils-shr.dpatch ## ## DP: Description: implementation of ELF sharable section proposal ## DP: Author: H.J. Lu ## DP: Upstream status: hjl 2.17.50.0.18 ## DP: Original patch: binutils-shr-82.patch if [ $# -ne 1 ]; then echo >&2 "`basename $0`: script expects -patch|-unpatch as argument" exit 1 fi [ -f debian/patches/00patch-opts ] && . debian/patches/00patch-opts patch_opts="${patch_opts:--f --no-backup-if-mismatch}" case "$1" in -patch) patch $patch_opts -p1 < $0;; -unpatch) patch $patch_opts -p1 -R < $0;; *) echo >&2 "`basename $0`: script expects -patch|-unpatch as argument" exit 1;; esac exit 0 http://groups.google.com/group/generic-abi/browse_thread/thread/f7b3e06417ead85a http://groups.google.com/group/generic-abi/browse_thread/thread/bca08f6560f61b0d bfd/ 2007-01-23 H.J. Lu * elf-bfd.h (_bfd_elf_sharable_com_section): New. (_bfd_elf_add_sharable_symbol): Likewise. (_bfd_elf_sharable_section_from_bfd_section): Likewise. (_bfd_elf_sharable_symbol_processing): Likewise. (_bfd_elf_sharable_common_definition): Likewise. (_bfd_elf_sharable_common_section_index): Likewise. (_bfd_elf_sharable_common_section): Likewise. (_bfd_elf_sharable_merge_symbol): Likewise. * elf.c (special_sections_g): Add ".gnu.linkonce.shrb" and ".gnu.linkonce.shrd". (special_sections_s): Add ".sharable_bss" and ".sharable_data". (get_program_header_size): Handle PT_GNU_SHR segment. (_bfd_elf_map_sections_to_segments): Likewise. (assign_file_positions_for_load_sections): Likewise. * elf32-i386.c (elf_i386_link_hash_table): Add sdynsharablebss and srelsharablebss fields. (elf_i386_link_hash_table_create): Initialize sdynsharablebss and srelsharablebss. (elf_i386_create_dynamic_sections): Handle sdynsharablebss and srelsharablebss. (elf_i386_adjust_dynamic_symbol): Likewise. (elf_i386_size_dynamic_sections): Likewise. (elf_i386_finish_dynamic_symbol): Likewise. (elf_backend_add_symbol_hook): Defined. (elf_backend_section_from_bfd_section): Likewise. (elf_backend_symbol_processing): Likewise. (elf_backend_common_section_index): Likewise. (elf_backend_common_section): Likewise. (elf_backend_common_definition): Likewise. (elf_backend_merge_symbol): Likewise. * elf64-x86-64.c (elf64_x86_64_link_hash_table): Add sdynsharablebss and srelsharablebss fields. (elf64_x86_64_link_hash_table_create): Initialize sdynsharablebss and srelsharablebss. (elf64_x86_64_create_dynamic_sections): Handle sdynsharablebss and srelsharablebss. (elf64_x86_64_adjust_dynamic_symbol): Likewise. (elf64_x86_64_size_dynamic_sections): Likewise. (elf64_x86_64_finish_dynamic_symbol): Likewise. (elf64_x86_64_add_symbol_hook): Handle sharable symbols. (elf64_x86_64_elf_section_from_bfd_section): Likewise. (elf64_x86_64_symbol_processing): Likewise. (elf64_x86_64_merge_symbol): Likewise. (elf64_x86_64_common_definition): Handle sharable sections. (elf64_x86_64_common_section_index): Likewise. (elf64_x86_64_common_section): Likewise. * elflink.c (_bfd_elf_create_dynamic_sections): Handle .dynsharablebss section. (_bfd_elf_sharable_com_section): New. (get_sharable_common_section): Likewise. (_bfd_elf_add_sharable_symbol): Likewise. (_bfd_elf_sharable_section_from_bfd_section): Likewise. (_bfd_elf_sharable_symbol_processing): Likewise. (_bfd_elf_sharable_common_definition): Likewise. (_bfd_elf_sharable_common_section_index): Likewise. (_bfd_elf_sharable_common_section): Likewise. (_bfd_elf_sharable_merge_symbol): Likewise. * elfxx-ia64.c (elfNN_ia64_add_symbol_hook): Handle sharable symbols. (elf_backend_add_symbol_hook): Defined. (elf_backend_section_from_bfd_section): Likewise. (elf_backend_symbol_processing): Likewise. (elf_backend_common_section_index): Likewise. (elf_backend_common_section): Likewise. (elf_backend_common_definition): Likewise. (elf_backend_merge_symbol): Likewise. binutils/ 2007-01-04 H.J. Lu * 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 * 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 * bfdlink.h (bfd_link_info): Add sharable_sections. include/elf/ 2007-01-04 H.J. Lu * common.h (PT_GNU_SHR): New. (SHF_GNU_SHARABLE): Likewise. (SHN_GNU_SHARABLE_COMMON): Likewise. ld/ 2007-01-04 H.J. Lu * 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. @DPATCH@ diff -urNad binutils-2.18~cvs20070812~/bfd/elf-bfd.h binutils-2.18~cvs20070812/bfd/elf-bfd.h --- binutils-2.18~cvs20070812~/bfd/elf-bfd.h 2007-08-12 13:32:34.000000000 +0200 +++ binutils-2.18~cvs20070812/bfd/elf-bfd.h 2007-08-12 13:32:59.000000000 +0200 @@ -1929,6 +1929,28 @@ (bfd *, struct bfd_link_info *); extern bfd_boolean _bfd_elf_add_dynamic_entry (struct bfd_link_info *, bfd_vma, bfd_vma); +extern asection _bfd_elf_sharable_com_section; +extern bfd_boolean _bfd_elf_add_sharable_symbol + (bfd *, struct bfd_link_info *, Elf_Internal_Sym *, const char **, + flagword *, asection **, bfd_vma *); +extern bfd_boolean _bfd_elf_sharable_section_from_bfd_section + (bfd *, asection *, int *); +extern void _bfd_elf_sharable_symbol_processing + (bfd *, asymbol *); +extern bfd_boolean _bfd_elf_sharable_common_definition + (Elf_Internal_Sym *); +extern unsigned int _bfd_elf_sharable_common_section_index + (asection *); +extern asection *_bfd_elf_sharable_common_section + (asection *); +extern bfd_boolean _bfd_elf_sharable_merge_symbol + (struct bfd_link_info *, struct elf_link_hash_entry **, + struct elf_link_hash_entry *, Elf_Internal_Sym *, asection **, + bfd_vma *, unsigned int *, bfd_boolean *, bfd_boolean *, + bfd_boolean *, bfd_boolean *, bfd_boolean *, bfd_boolean *, + bfd_boolean *, bfd_boolean *, bfd *, asection **, + bfd_boolean *, bfd_boolean *, bfd_boolean *, bfd_boolean *, + bfd *, asection **); extern bfd_boolean bfd_elf_link_record_dynamic_symbol (struct bfd_link_info *, struct elf_link_hash_entry *); diff -urNad binutils-2.18~cvs20070812~/bfd/elf.c binutils-2.18~cvs20070812/bfd/elf.c --- binutils-2.18~cvs20070812~/bfd/elf.c 2007-08-12 13:32:34.000000000 +0200 +++ binutils-2.18~cvs20070812/bfd/elf.c 2007-08-12 13:32:59.000000000 +0200 @@ -1992,6 +1992,8 @@ { 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 } }; @@ -2046,6 +2048,8 @@ /* 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 } }; @@ -3374,6 +3378,32 @@ } } + /* 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) @@ -3514,6 +3544,8 @@ 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; @@ -3785,6 +3817,22 @@ 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. */ @@ -3814,6 +3862,60 @@ pm = &m->next; } + /* If there are any output SHF_GNU_SHARABLE data sections, add a + PT_GNU_SHR segment. */ + if (sharable_data_count > 0) + { + int i; + + amt = sizeof (struct elf_segment_map); + amt += (sharable_data_count - 1) * sizeof (asection *); + m = bfd_zalloc (abfd, amt); + if (m == NULL) + goto error_return; + m->next = NULL; + m->p_type = PT_GNU_SHR; + m->count = sharable_data_count; + /* Mandated PF_R. */ + m->p_flags = PF_R; + m->p_flags_valid = 1; + for (i = 0; i < sharable_data_count; ++i) + { + m->sections[i] = first_sharable_data; + first_sharable_data = first_sharable_data->next; + } + + *pm = m; + pm = &m->next; + } + + /* If there are any output SHF_GNU_SHARABLE bss sections, add a + PT_GNU_SHR segment. */ + if (sharable_bss_count > 0) + { + int i; + + amt = sizeof (struct elf_segment_map); + amt += (sharable_bss_count - 1) * sizeof (asection *); + m = bfd_zalloc (abfd, amt); + if (m == NULL) + goto error_return; + m->next = NULL; + m->p_type = PT_GNU_SHR; + m->count = sharable_bss_count; + /* Mandated PF_R. */ + m->p_flags = PF_R; + m->p_flags_valid = 1; + for (i = 0; i < sharable_bss_count; ++i) + { + m->sections[i] = first_sharable_bss; + first_sharable_bss = first_sharable_bss->next; + } + + *pm = m; + pm = &m->next; + } + /* If there is a .eh_frame_hdr section, throw in a PT_GNU_EH_FRAME segment. */ eh_frame_hdr = elf_tdata (abfd)->eh_frame_hdr; @@ -4247,6 +4349,7 @@ align = (bfd_size_type) 1 << bfd_get_section_alignment (abfd, sec); if (p->p_type == PT_LOAD + || p->p_type == PT_GNU_SHR || p->p_type == PT_TLS) { bfd_signed_vma adjust = sec->lma - (p->p_paddr + p->p_memsz); diff -urNad binutils-2.18~cvs20070812~/bfd/elf32-i386.c binutils-2.18~cvs20070812/bfd/elf32-i386.c --- binutils-2.18~cvs20070812~/bfd/elf32-i386.c 2007-07-27 20:50:18.000000000 +0200 +++ binutils-2.18~cvs20070812/bfd/elf32-i386.c 2007-08-12 13:32:59.000000000 +0200 @@ -661,6 +661,8 @@ asection *srelplt; asection *sdynbss; asection *srelbss; + asection *sdynsharablebss; + asection *srelsharablebss; /* The (unloaded but important) .rel.plt.unloaded section on VxWorks. */ asection *srelplt2; @@ -753,6 +755,8 @@ ret->srelplt = NULL; ret->sdynbss = NULL; ret->srelbss = NULL; + ret->sdynsharablebss = NULL; + ret->srelsharablebss = NULL; ret->tls_ldm_got.refcount = 0; ret->next_tls_desc_index = 0; ret->sgotplt_jump_table_size = 0; @@ -813,10 +817,19 @@ htab->srelplt = bfd_get_section_by_name (dynobj, ".rel.plt"); htab->sdynbss = bfd_get_section_by_name (dynobj, ".dynbss"); if (!info->shared) - htab->srelbss = bfd_get_section_by_name (dynobj, ".rel.bss"); + { + htab->srelbss = bfd_get_section_by_name (dynobj, ".rel.bss"); + htab->sdynsharablebss + = bfd_get_section_by_name (dynobj, ".dynsharablebss"); + htab->srelsharablebss + = bfd_get_section_by_name (dynobj, ".rel.sharable_bss"); + } if (!htab->splt || !htab->srelplt || !htab->sdynbss - || (!info->shared && !htab->srelbss)) + || (!info->shared + && (!htab->srelbss + || !htab->sdynsharablebss + || !htab->srelsharablebss))) abort (); if (htab->is_vxworks @@ -1534,17 +1547,23 @@ both the dynamic object and the regular object will refer to the same memory location for the variable. */ + s = htab->sdynbss; + /* We must generate a R_386_COPY reloc to tell the dynamic linker to copy the initial value out of the dynamic object and into the runtime process image. */ if ((h->root.u.def.section->flags & SEC_ALLOC) != 0) { - htab->srelbss->size += sizeof (Elf32_External_Rel); + if (elf_section_flags (h->root.u.def.section) & SHF_GNU_SHARABLE) + { + htab->srelsharablebss->size += sizeof (Elf32_External_Rel); + s = htab->sdynsharablebss; + } + else + htab->srelbss->size += sizeof (Elf32_External_Rel); h->needs_copy = 1; } - s = htab->sdynbss; - return _bfd_elf_adjust_dynamic_copy (h, s); } @@ -1998,7 +2017,8 @@ if (s == htab->splt || s == htab->sgot || s == htab->sgotplt - || s == htab->sdynbss) + || s == htab->sdynbss + || s == htab->sdynsharablebss) { /* Strip this section if we don't need it; see the comment below. */ @@ -3536,21 +3556,27 @@ { Elf_Internal_Rela rel; bfd_byte *loc; + asection *s; + + if (h->root.u.def.section == htab->sdynsharablebss) + s = htab->srelsharablebss; + else + s = htab->srelbss; /* This symbol needs a copy reloc. Set it up. */ if (h->dynindx == -1 || (h->root.type != bfd_link_hash_defined && h->root.type != bfd_link_hash_defweak) - || htab->srelbss == NULL) + || s == NULL) abort (); rel.r_offset = (h->root.u.def.value + h->root.u.def.section->output_section->vma + h->root.u.def.section->output_offset); rel.r_info = ELF32_R_INFO (h->dynindx, R_386_COPY); - loc = htab->srelbss->contents; - loc += htab->srelbss->reloc_count++ * sizeof (Elf32_External_Rel); + loc = s->contents; + loc += s->reloc_count++ * sizeof (Elf32_External_Rel); bfd_elf32_swap_reloc_out (output_bfd, &rel, loc); } @@ -3838,6 +3864,21 @@ #define elf_backend_plt_sym_val elf_i386_plt_sym_val #define elf_backend_hash_symbol elf_i386_hash_symbol +#define elf_backend_add_symbol_hook \ + _bfd_elf_add_sharable_symbol +#define elf_backend_section_from_bfd_section \ + _bfd_elf_sharable_section_from_bfd_section +#define elf_backend_symbol_processing \ + _bfd_elf_sharable_symbol_processing +#define elf_backend_common_section_index \ + _bfd_elf_sharable_common_section_index +#define elf_backend_common_section \ + _bfd_elf_sharable_common_section +#define elf_backend_common_definition \ + _bfd_elf_sharable_common_definition +#define elf_backend_merge_symbol \ + _bfd_elf_sharable_merge_symbol + #include "elf32-target.h" /* FreeBSD support. */ diff -urNad binutils-2.18~cvs20070812~/bfd/elf64-x86-64.c binutils-2.18~cvs20070812/bfd/elf64-x86-64.c --- binutils-2.18~cvs20070812~/bfd/elf64-x86-64.c 2007-07-03 16:26:42.000000000 +0200 +++ binutils-2.18~cvs20070812/bfd/elf64-x86-64.c 2007-08-12 13:32:59.000000000 +0200 @@ -470,6 +470,8 @@ asection *srelplt; asection *sdynbss; asection *srelbss; + asection *sdynsharablebss; + asection *srelsharablebss; /* The offset into splt of the PLT entry for the TLS descriptor resolver. Special values are 0, if not necessary (or not found @@ -557,6 +559,8 @@ ret->srelplt = NULL; ret->sdynbss = NULL; ret->srelbss = NULL; + ret->sdynsharablebss = NULL; + ret->srelsharablebss = NULL; ret->sym_sec.abfd = NULL; ret->tlsdesc_plt = 0; ret->tlsdesc_got = 0; @@ -615,10 +619,19 @@ htab->srelplt = bfd_get_section_by_name (dynobj, ".rela.plt"); htab->sdynbss = bfd_get_section_by_name (dynobj, ".dynbss"); if (!info->shared) - htab->srelbss = bfd_get_section_by_name (dynobj, ".rela.bss"); + { + htab->srelbss = bfd_get_section_by_name (dynobj, ".rela.bss"); + htab->sdynsharablebss + = bfd_get_section_by_name (dynobj, ".dynsharablebss"); + htab->srelsharablebss + = bfd_get_section_by_name (dynobj, ".rela.sharable_bss"); + } if (!htab->splt || !htab->srelplt || !htab->sdynbss - || (!info->shared && !htab->srelbss)) + || (!info->shared + && (!htab->srelbss + || !htab->sdynsharablebss + || !htab->srelsharablebss))) abort (); return TRUE; @@ -1396,17 +1409,23 @@ htab = elf64_x86_64_hash_table (info); + s = htab->sdynbss; + /* We must generate a R_X86_64_COPY reloc to tell the dynamic linker to copy the initial value out of the dynamic object and into the runtime process image. */ if ((h->root.u.def.section->flags & SEC_ALLOC) != 0) { - htab->srelbss->size += sizeof (Elf64_External_Rela); + if (elf_section_flags (h->root.u.def.section) & SHF_GNU_SHARABLE) + { + htab->srelsharablebss->size += sizeof (Elf64_External_Rela); + s = htab->sdynsharablebss; + } + else + htab->srelbss->size += sizeof (Elf64_External_Rela); h->needs_copy = 1; } - s = htab->sdynbss; - return _bfd_elf_adjust_dynamic_copy (h, s); } @@ -1854,7 +1873,8 @@ if (s == htab->splt || s == htab->sgot || s == htab->sgotplt - || s == htab->sdynbss) + || s == htab->sdynbss + || s == htab->sdynsharablebss) { /* Strip this section if we don't need it; see the comment below. */ @@ -3193,13 +3213,19 @@ { Elf_Internal_Rela rela; bfd_byte *loc; + asection *s; + + if (h->root.u.def.section == htab->sdynsharablebss) + s = htab->srelsharablebss; + else + s = htab->srelbss; /* This symbol needs a copy reloc. Set it up. */ if (h->dynindx == -1 || (h->root.type != bfd_link_hash_defined && h->root.type != bfd_link_hash_defweak) - || htab->srelbss == NULL) + || s == NULL) abort (); rela.r_offset = (h->root.u.def.value @@ -3207,8 +3233,8 @@ + h->root.u.def.section->output_offset); rela.r_info = ELF64_R_INFO (h->dynindx, R_X86_64_COPY); rela.r_addend = 0; - loc = htab->srelbss->contents; - loc += htab->srelbss->reloc_count++ * sizeof (Elf64_External_Rela); + loc = s->contents; + loc += s->reloc_count++ * sizeof (Elf64_External_Rela); bfd_elf64_swap_reloca_out (output_bfd, &rela, loc); } @@ -3472,9 +3498,12 @@ } *secp = lcomm; *valp = sym->st_size; + return TRUE; break; } - return TRUE; + + return _bfd_elf_add_sharable_symbol (abfd, info, sym, namep, flagsp, + secp, valp); } @@ -3490,7 +3519,7 @@ *index = SHN_X86_64_LCOMMON; return TRUE; } - return FALSE; + return _bfd_elf_sharable_section_from_bfd_section (abfd, sec, index); } /* Process a symbol. */ @@ -3508,22 +3537,26 @@ asym->value = elfsym->internal_elf_sym.st_size; /* Common symbol doesn't set BSF_GLOBAL. */ asym->flags &= ~BSF_GLOBAL; + return; break; } + + _bfd_elf_sharable_symbol_processing (abfd, asym); } static bfd_boolean elf64_x86_64_common_definition (Elf_Internal_Sym *sym) { return (sym->st_shndx == SHN_COMMON - || sym->st_shndx == SHN_X86_64_LCOMMON); + || sym->st_shndx == SHN_X86_64_LCOMMON + || _bfd_elf_sharable_common_definition (sym)); } static unsigned int elf64_x86_64_common_section_index (asection *sec) { if ((elf_section_flags (sec) & SHF_X86_64_LARGE) == 0) - return SHN_COMMON; + return _bfd_elf_sharable_common_section_index (sec); else return SHN_X86_64_LCOMMON; } @@ -3532,7 +3565,7 @@ elf64_x86_64_common_section (asection *sec) { if ((elf_section_flags (sec) & SHF_X86_64_LARGE) == 0) - return bfd_com_section_ptr; + return _bfd_elf_sharable_common_section (sec); else return &_bfd_elf_large_com_section; } @@ -3569,7 +3602,8 @@ && h->root.type == bfd_link_hash_common && !*newdyn && bfd_is_com_section (*sec) - && *oldsec != *sec) + && *oldsec != *sec + && _bfd_elf_sharable_common_section_index (*oldsec) == SHN_COMMON) { if (sym->st_shndx == SHN_COMMON && (elf_section_flags (*oldsec) & SHF_X86_64_LARGE) != 0) @@ -3577,13 +3611,26 @@ h->root.u.c.p->section = bfd_make_section_old_way (oldbfd, "COMMON"); h->root.u.c.p->section->flags = SEC_ALLOC; + return TRUE; } else if (sym->st_shndx == SHN_X86_64_LCOMMON && (elf_section_flags (*oldsec) & SHF_X86_64_LARGE) == 0) - *psec = *sec = bfd_com_section_ptr; + { + *psec = *sec = bfd_com_section_ptr; + return TRUE; + } } - return TRUE; + return _bfd_elf_sharable_merge_symbol (info, sym_hash, h, sym, + psec, pvalue, pold_alignment, + skip, override, + type_change_ok, size_change_ok, + newdyn, newdef, + newdyncommon, newweak, + abfd, sec, + olddyn, olddef, + olddyncommon, oldweak, + oldbfd, oldsec); } static int diff -urNad binutils-2.18~cvs20070812~/bfd/elflink.c binutils-2.18~cvs20070812/bfd/elflink.c --- binutils-2.18~cvs20070812~/bfd/elflink.c 2007-08-12 13:32:34.000000000 +0200 +++ binutils-2.18~cvs20070812/bfd/elflink.c 2007-08-12 13:32:59.000000000 +0200 @@ -353,6 +353,27 @@ 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; + } } } @@ -12319,3 +12340,219 @@ { return bfd_com_section_ptr; } + +asection _bfd_elf_sharable_com_section + = BFD_FAKE_SECTION (_bfd_elf_sharable_com_section, SEC_IS_COMMON, + NULL, "SHARABLE_COMMON", 0); + +static asection * +get_sharable_common_section (bfd *abfd) +{ + asection *scomm = bfd_get_section_by_name (abfd, "SHARABLE_COMMON"); + + if (scomm == NULL) + { + scomm = bfd_make_section_with_flags (abfd, + "SHARABLE_COMMON", + (SEC_ALLOC + | SEC_IS_COMMON + | SEC_LINKER_CREATED)); + if (scomm == NULL) + return scomm; + elf_section_flags (scomm) |= SHF_GNU_SHARABLE; + } + + return scomm; +} + +bfd_boolean +_bfd_elf_add_sharable_symbol (bfd *abfd ATTRIBUTE_UNUSED, + struct bfd_link_info *info ATTRIBUTE_UNUSED, + Elf_Internal_Sym *sym, + const char **namep ATTRIBUTE_UNUSED, + flagword *flagsp ATTRIBUTE_UNUSED, + asection **secp, + bfd_vma *valp) +{ + asection *scomm; + + switch (sym->st_shndx) + { + case SHN_GNU_SHARABLE_COMMON: + scomm = get_sharable_common_section (abfd); + if (scomm == NULL) + return FALSE; + *secp = scomm; + *valp = sym->st_size; + break; + } + return TRUE; +} + +bfd_boolean +_bfd_elf_sharable_section_from_bfd_section + (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, int *index) +{ + if (sec == &_bfd_elf_sharable_com_section) + { + *index = SHN_GNU_SHARABLE_COMMON; + return TRUE; + } + return FALSE; +} + +void +_bfd_elf_sharable_symbol_processing (bfd *abfd ATTRIBUTE_UNUSED, + asymbol *asym) +{ + elf_symbol_type *elfsym = (elf_symbol_type *) asym; + + switch (elfsym->internal_elf_sym.st_shndx) + { + case SHN_GNU_SHARABLE_COMMON: + asym->section = &_bfd_elf_sharable_com_section; + asym->value = elfsym->internal_elf_sym.st_size; + asym->flags &= ~BSF_GLOBAL; + break; + } +} + +bfd_boolean +_bfd_elf_sharable_common_definition (Elf_Internal_Sym *sym) +{ + return (sym->st_shndx == SHN_COMMON + || sym->st_shndx == SHN_GNU_SHARABLE_COMMON); +} + +unsigned int +_bfd_elf_sharable_common_section_index (asection *sec) +{ + if ((elf_section_flags (sec) & SHF_GNU_SHARABLE) == 0) + return SHN_COMMON; + else + return SHN_GNU_SHARABLE_COMMON; +} + +asection * +_bfd_elf_sharable_common_section (asection *sec) +{ + if ((elf_section_flags (sec) & SHF_GNU_SHARABLE) == 0) + return bfd_com_section_ptr; + else + return &_bfd_elf_sharable_com_section; +} + +bfd_boolean +_bfd_elf_sharable_merge_symbol + (struct bfd_link_info *info ATTRIBUTE_UNUSED, + struct elf_link_hash_entry **sym_hash ATTRIBUTE_UNUSED, + struct elf_link_hash_entry *h, + Elf_Internal_Sym *sym ATTRIBUTE_UNUSED, + asection **psec, + bfd_vma *pvalue ATTRIBUTE_UNUSED, + unsigned int *pold_alignment ATTRIBUTE_UNUSED, + bfd_boolean *skip ATTRIBUTE_UNUSED, + bfd_boolean *override ATTRIBUTE_UNUSED, + bfd_boolean *type_change_ok ATTRIBUTE_UNUSED, + bfd_boolean *size_change_ok ATTRIBUTE_UNUSED, + bfd_boolean *newdef ATTRIBUTE_UNUSED, + bfd_boolean *newdyn, + bfd_boolean *newdyncommon ATTRIBUTE_UNUSED, + bfd_boolean *newweak ATTRIBUTE_UNUSED, + bfd *abfd, + asection **sec, + bfd_boolean *olddef ATTRIBUTE_UNUSED, + bfd_boolean *olddyn, + bfd_boolean *olddyncommon ATTRIBUTE_UNUSED, + bfd_boolean *oldweak ATTRIBUTE_UNUSED, + bfd *oldbfd, + asection **oldsec) +{ + /* Check sharable symbol. If one is undefined, it is OK. */ + if (*oldsec && !bfd_is_und_section (*sec)) + { + bfd_boolean sharable, oldsharable; + + sharable = (elf_section_data (*sec) + && (elf_section_flags (*sec) & SHF_GNU_SHARABLE)); + oldsharable = (elf_section_data (*oldsec) + && (elf_section_flags (*oldsec) + & SHF_GNU_SHARABLE)); + + if (sharable != oldsharable) + { + bfd *nsbfd, *sbfd; + asection *nssec, *ssec; + bfd_boolean nsdyn, sdyn, nsdef, sdef; + + if (oldsharable) + { + sbfd = oldbfd; + nsbfd = abfd; + ssec = *oldsec; + nssec = *sec; + sdyn = *olddyn; + nsdyn = *newdyn; + sdef = *olddef; + nsdef = *newdef; + } + else + { + sbfd = abfd; + nsbfd = oldbfd; + ssec = *sec; + nssec = *oldsec; + sdyn = *newdyn; + nsdyn = *olddyn; + sdef = *newdef; + nsdef = *olddef; + } + + if (sdef && !sdyn) + { + /* If the sharable definition comes from a relocatable + file, it will override the non-sharable one in DSO. */ + return TRUE; + } + else if (!nsdef + && !nsdyn + && (h->root.type == bfd_link_hash_common + || bfd_is_com_section (nssec))) + { + asection *scomm; + + /* When the non-sharable common symbol in a relocatable + file, we can turn it into sharable. If the sharable + symbol isn't common, the non-sharable common symbol + will be overidden. We only need to handle the + sharable common symbol and the non-sharable common + symbol. We just turn the non-sharable common symbol + into the sharable one. */ + if (sym->st_shndx == SHN_GNU_SHARABLE_COMMON) + { + scomm = get_sharable_common_section (oldbfd); + if (scomm == NULL) + return FALSE; + h->root.u.c.p->section = scomm; + } + else + { + scomm = get_sharable_common_section (abfd); + if (scomm == NULL) + return FALSE; + *psec = *sec = scomm; + } + + return TRUE; + } + + (*_bfd_error_handler) + (_("%s: sharable symbol in %B section %A mismatches non-shrable symbol in %B section %A"), + sbfd, ssec, nsbfd, nssec, h->root.root.string); + bfd_set_error (bfd_error_bad_value); + return FALSE; + } + } + + return TRUE; +} diff -urNad binutils-2.18~cvs20070812~/bfd/elfxx-ia64.c binutils-2.18~cvs20070812/bfd/elfxx-ia64.c --- binutils-2.18~cvs20070812~/bfd/elfxx-ia64.c 2007-07-03 16:26:42.000000000 +0200 +++ binutils-2.18~cvs20070812/bfd/elfxx-ia64.c 2007-08-12 13:32:59.000000000 +0200 @@ -1637,7 +1637,8 @@ *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. */ @@ -5901,6 +5902,19 @@ #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 -urNad binutils-2.18~cvs20070812~/binutils/readelf.c binutils-2.18~cvs20070812/binutils/readelf.c --- binutils-2.18~cvs20070812~/binutils/readelf.c 2007-07-27 02:48:30.000000000 +0200 +++ binutils-2.18~cvs20070812/binutils/readelf.c 2007-08-12 13:32:59.000000000 +0200 @@ -1266,6 +1266,8 @@ sec_name = "ABS"; else if (psym->st_shndx == SHN_COMMON) sec_name = "COMMON"; + else if (psym->st_shndx == SHN_GNU_SHARABLE_COMMON) + sec_name = "GNU_SHARABLE_COMMON"; else if (elf_header.e_machine == EM_MIPS && psym->st_shndx == SHN_MIPS_SCOMMON) sec_name = "SCOMMON"; @@ -2464,6 +2466,7 @@ 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"; @@ -6971,6 +6974,8 @@ 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 -urNad binutils-2.18~cvs20070812~/gas/config/obj-elf.c binutils-2.18~cvs20070812/gas/config/obj-elf.c --- binutils-2.18~cvs20070812~/gas/config/obj-elf.c 2007-07-03 13:01:04.000000000 +0200 +++ binutils-2.18~cvs20070812/gas/config/obj-elf.c 2007-08-12 13:32:59.000000000 +0200 @@ -73,6 +73,7 @@ static void obj_elf_subsection (int); static void obj_elf_popsection (int); static void obj_elf_tls_common (int); +static void obj_elf_sharable_common (int); static void obj_elf_lcomm (int); static void obj_elf_struct (int); @@ -130,6 +131,8 @@ {"tls_common", obj_elf_tls_common, 0}, + {"sharable_common", obj_elf_sharable_common, 0}, + /* End sentinel. */ {NULL, NULL, 0}, }; @@ -374,6 +377,39 @@ } 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); @@ -587,11 +623,17 @@ .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 -urNad binutils-2.18~cvs20070812~/include/bfdlink.h binutils-2.18~cvs20070812/include/bfdlink.h --- binutils-2.18~cvs20070812~/include/bfdlink.h 2007-07-09 23:21:42.000000000 +0200 +++ binutils-2.18~cvs20070812/include/bfdlink.h 2007-08-12 13:32:59.000000000 +0200 @@ -351,6 +351,9 @@ /* Non-NULL if .note.gnu.build-id section should be created. */ char *emit_note_gnu_build_id; + /* TRUE if sharables sections may be created. */ + unsigned int sharable_sections: 1; + /* What to do with unresolved symbols in an object file. When producing executables the default is GENERATE_ERROR. When producing shared libraries the default is IGNORE. The diff -urNad binutils-2.18~cvs20070812~/include/elf/common.h binutils-2.18~cvs20070812/include/elf/common.h --- binutils-2.18~cvs20070812~/include/elf/common.h 2007-07-09 23:17:42.000000000 +0200 +++ binutils-2.18~cvs20070812/include/elf/common.h 2007-08-12 13:32:59.000000000 +0200 @@ -309,6 +309,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. */ @@ -381,6 +382,8 @@ #define SHF_MASKOS 0x0FF00000 /* New value, Oct 4, 1999 Draft */ #define SHF_MASKPROC 0xF0000000 /* Processor-specific semantics */ +#define SHF_GNU_SHARABLE 0x01000000 /* sharable section */ + /* Values of note segment descriptor types for core files. */ #define NT_PRSTATUS 1 /* Contains copy of prstatus struct */ @@ -505,6 +508,9 @@ #define SHN_HIRESERVE 0xFFFF /* End range of reserved indices */ #define SHN_BAD ((unsigned) -1) /* Used internally by bfd */ +/* Associated symbol is in common sharable */ +#define SHN_GNU_SHARABLE_COMMON (SHN_LOOS + 10) + /* The following constants control how a symbol may be accessed once it has become part of an executable or shared library. */ diff -urNad binutils-2.18~cvs20070812~/ld/emulparams/elf64_ia64.sh binutils-2.18~cvs20070812/ld/emulparams/elf64_ia64.sh --- binutils-2.18~cvs20070812~/ld/emulparams/elf64_ia64.sh 2006-05-30 18:45:32.000000000 +0200 +++ binutils-2.18~cvs20070812/ld/emulparams/elf64_ia64.sh 2007-08-12 13:32:59.000000000 +0200 @@ -37,3 +37,4 @@ # .dtors. They have to be next to .sbss/.sbss2/.sdata/.sdata2. SMALL_DATA_CTOR=" " SMALL_DATA_DTOR=" " +SHARABLE_SECTIONS=yes diff -urNad binutils-2.18~cvs20070812~/ld/emulparams/elf_i386.sh binutils-2.18~cvs20070812/ld/emulparams/elf_i386.sh --- binutils-2.18~cvs20070812~/ld/emulparams/elf_i386.sh 2007-08-12 13:32:34.000000000 +0200 +++ binutils-2.18~cvs20070812/ld/emulparams/elf_i386.sh 2007-08-12 13:33:45.000000000 +0200 @@ -11,6 +11,7 @@ GENERATE_PIE_SCRIPT=yes NO_SMALL_DATA=yes SEPARATE_GOTPLT=12 +SHARABLE_SECTIONS=yes # Linux modify the default library search path to first include # a 32-bit specific directory. diff -urNad binutils-2.18~cvs20070812~/ld/emulparams/elf_x86_64.sh binutils-2.18~cvs20070812/ld/emulparams/elf_x86_64.sh --- binutils-2.18~cvs20070812~/ld/emulparams/elf_x86_64.sh 2007-08-12 10:00:33.000000000 +0200 +++ binutils-2.18~cvs20070812/ld/emulparams/elf_x86_64.sh 2007-08-12 13:32:59.000000000 +0200 @@ -13,6 +13,7 @@ NO_SMALL_DATA=yes LARGE_SECTIONS=yes SEPARATE_GOTPLT=24 +SHARABLE_SECTIONS=yes if [ "x${host}" = "x${target}" ]; then case " $EMULATION_LIBPATH " in diff -urNad binutils-2.18~cvs20070812~/ld/emultempl/elf32.em binutils-2.18~cvs20070812/ld/emultempl/elf32.em --- binutils-2.18~cvs20070812~/ld/emultempl/elf32.em 2007-08-12 13:32:34.000000000 +0200 +++ binutils-2.18~cvs20070812/ld/emultempl/elf32.em 2007-08-12 13:32:59.000000000 +0200 @@ -101,6 +101,7 @@ ldfile_set_output_arch ("${OUTPUT_ARCH}", bfd_arch_`echo ${ARCH} | sed -e 's/:.*//'`); config.dynamic_link = ${DYNAMIC_LINK-TRUE}; config.has_shared = `if test -n "$GENERATE_SHLIB_SCRIPT" ; then echo TRUE ; else echo FALSE ; fi`; + link_info.sharable_sections = `if test "$SHARABLE_SECTIONS" = "yes" ; then echo TRUE ; else echo FALSE ; fi`; } EOF @@ -1679,6 +1680,12 @@ secname = bfd_get_section_name (s->owner, s); + /* Orphaned sharable sections won't have correct page + requirements. */ + if (elf_section_flags (s) & SHF_GNU_SHARABLE) + einfo ("%F%P: unable to place orphaned sharable section %A (%B)\n", + s, s->owner); + if (! link_info.relocatable && link_info.combreloc && (s->flags & SEC_ALLOC)) diff -urNad binutils-2.18~cvs20070812~/ld/ldmain.c binutils-2.18~cvs20070812/ld/ldmain.c --- binutils-2.18~cvs20070812~/ld/ldmain.c 2007-07-06 16:09:41.000000000 +0200 +++ binutils-2.18~cvs20070812/ld/ldmain.c 2007-08-12 13:32:59.000000000 +0200 @@ -275,6 +275,7 @@ link_info.relax_pass = 1; link_info.pei386_auto_import = -1; link_info.spare_dynamic_tags = 5; + link_info.sharable_sections = FALSE; ldfile_add_arch (""); emulation = get_emulation (argc, argv); diff -urNad binutils-2.18~cvs20070812~/ld/scripttempl/elf.sc binutils-2.18~cvs20070812/ld/scripttempl/elf.sc --- binutils-2.18~cvs20070812~/ld/scripttempl/elf.sc 2007-07-28 00:33:24.000000000 +0200 +++ binutils-2.18~cvs20070812/ld/scripttempl/elf.sc 2007-08-12 13:32:59.000000000 +0200 @@ -238,6 +238,40 @@ ${RELOCATING+_stack = .;} *(.stack) }" +test "${SHARABLE_SECTIONS}" = "yes" && OTHER_READWRITE_SECTIONS=" + ${OTHER_READWRITE_SECTIONS} + /* Sharable data sections. */ + .sharable_data ${RELOCATING-0} : ${RELOCATING+ALIGN(${MAXPAGESIZE})} + { + ${RELOCATING+PROVIDE_HIDDEN (__sharable_data_start = .);} + *(.sharable_data${RELOCATING+ .sharable_data.* .gnu.linkonce.shrd.*}) + /* Align here to ensure that the sharable data section ends at the + page boundary. */ + ${RELOCATING+. = ALIGN(. != 0 ? ${MAXPAGESIZE} : 1);} + ${RELOCATING+PROVIDE_HIDDEN (__sharable_data_end = .);} + } +" +test "${SHARABLE_SECTIONS}" = "yes" && OTHER_BSS_SECTIONS=" + ${OTHER_BSS_SECTIONS} + /* Sharable bss sections */ + .sharable_bss ${RELOCATING-0} : ${RELOCATING+ALIGN(${MAXPAGESIZE})} + { + ${RELOCATING+PROVIDE_HIDDEN (__sharable_bss_start = .);} + *(.dynsharablebss) + *(.sharable_bss${RELOCATING+ .sharable_bss.* .gnu.linkonce.shrb.*}) + *(SHARABLE_COMMON) + /* Align here to ensure that the sharable bss section ends at the + page boundary. */ + ${RELOCATING+. = ALIGN(. != 0 ? ${MAXPAGESIZE} : 1);} + ${RELOCATING+PROVIDE_HIDDEN (__sharable_bss_end = .);} + } +" +test "${SHARABLE_SECTIONS}" = "yes" && REL_SHARABLE=" + .rel.sharable_data ${RELOCATING-0} : { *(.rel.sharable_data${RELOCATING+ .rel.sharable_data.* .rel.gnu.linkonce.shrd.*}) } + .rela.sharable_data ${RELOCATING-0} : { *(.rela.sharable_data${RELOCATING+ .rela.sharable_data.* .rela.gnu.linkonce.shrd.*}) } + .rel.sharable_bss ${RELOCATING-0} : { *(.rel.sharable_bss${RELOCATING+ .rel.sharable_bss.* .rel.gnu.linkonce.shrb.*}) } + .rela.sharable_bss ${RELOCATING-0} : { *(.rela.sharable_bss${RELOCATING+ .rela.sharable_bss.* .rela.gnu.linkonce.shrb.*}) } +" # if this is for an embedded system, don't add SIZEOF_HEADERS. if [ -z "$EMBEDDED" ]; then @@ -308,6 +342,7 @@ .rel.got ${RELOCATING-0} : { *(.rel.got) } .rela.got ${RELOCATING-0} : { *(.rela.got) } ${OTHER_GOT_RELOC_SECTIONS} + ${REL_SHARABLE} ${REL_SDATA} ${REL_SBSS} ${REL_SDATA2}