forked from Imagelibrary/binutils-gdb
1286 lines
42 KiB
Diff
1286 lines
42 KiB
Diff
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
|
|
|