summaryrefslogtreecommitdiff
path: root/bfd/elf64-x86-64.c
diff options
context:
space:
mode:
Diffstat (limited to 'bfd/elf64-x86-64.c')
-rw-r--r--bfd/elf64-x86-64.c88
1 files changed, 73 insertions, 15 deletions
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index f9202085b38..5c7eb3be972 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -909,6 +909,9 @@ struct elf_x86_64_link_hash_table
/* TRUE if there are dynamic relocs against IFUNC symbols that apply
to read-only sections. */
bfd_boolean readonly_dynrelocs_against_ifunc;
+
+ asection *sdynsharablebss;
+ asection *srelsharablebss;
};
/* Get the x86-64 ELF linker hash table from a link_info structure. */
@@ -1133,10 +1136,10 @@ elf_x86_64_create_dynamic_sections (bfd *dynobj,
if (bfd_link_executable (info))
{
/* Always allow copy relocs for building executables. */
+ const struct elf_backend_data *bed = get_elf_backend_data (dynobj);
asection *s = bfd_get_linker_section (dynobj, ".rela.bss");
if (s == NULL)
{
- const struct elf_backend_data *bed = get_elf_backend_data (dynobj);
s = bfd_make_section_anyway_with_flags (dynobj,
".rela.bss",
(bed->dynamic_sec_flags
@@ -1147,6 +1150,32 @@ elf_x86_64_create_dynamic_sections (bfd *dynobj,
return FALSE;
}
htab->srelbss = s;
+
+ s = bfd_get_linker_section (dynobj, ".dynsharablebss");
+ if (s == NULL)
+ {
+ s = bfd_make_section_anyway_with_flags (dynobj,
+ ".dynsharablebss",
+ (SEC_ALLOC
+ | SEC_LINKER_CREATED));
+ if (s == NULL)
+ return FALSE;
+ }
+ htab->sdynsharablebss = s;
+
+ s = bfd_get_linker_section (dynobj, ".rela.sharable_bss");
+ if (s == NULL)
+ {
+ s = bfd_make_section_anyway_with_flags (dynobj,
+ ".rela.sharable_bss",
+ (bed->dynamic_sec_flags
+ | SEC_READONLY));
+ if (s == NULL
+ || ! bfd_set_section_alignment (dynobj, s,
+ bed->s->log_file_align))
+ return FALSE;
+ }
+ htab->srelsharablebss = s;
}
if (!info->no_ld_generated_unwind_info
@@ -2986,6 +3015,8 @@ elf_x86_64_adjust_dynamic_symbol (struct bfd_link_info *info,
if (htab == NULL)
return FALSE;
+ s = htab->sdynbss;
+
/* We must generate a R_X86_64_COPY reloc to tell the dynamic linker
to copy the initial value out of the dynamic object and into the
runtime process image. */
@@ -2993,12 +3024,16 @@ elf_x86_64_adjust_dynamic_symbol (struct bfd_link_info *info,
{
const struct elf_backend_data *bed;
bed = get_elf_backend_data (info->output_bfd);
- htab->srelbss->size += bed->s->sizeof_rela;
+ if (elf_section_flags (h->root.u.def.section) & SHF_GNU_SHARABLE)
+ {
+ htab->srelsharablebss->size += bed->s->sizeof_rela;
+ s = htab->sdynsharablebss;
+ }
+ else
+ htab->srelbss->size += bed->s->sizeof_rela;
h->needs_copy = 1;
}
- s = htab->sdynbss;
-
return _bfd_elf_adjust_dynamic_copy (info, h, s);
}
@@ -3812,6 +3847,7 @@ elf_x86_64_size_dynamic_sections (bfd *output_bfd,
|| s == htab->plt_bnd
|| s == htab->plt_got
|| s == htab->plt_eh_frame
+ || s == htab->sdynsharablebss
|| s == htab->sdynbss)
{
/* Strip this section if we don't need it; see the
@@ -6004,13 +6040,19 @@ do_glob_dat:
if (h->needs_copy)
{
Elf_Internal_Rela rela;
+ asection *s;
+
+ if (h->root.u.def.section == htab->sdynsharablebss)
+ s = htab->srelsharablebss;
+ else
+ s = htab->srelbss;
/* This symbol needs a copy reloc. Set it up. */
if (h->dynindx == -1
|| (h->root.type != bfd_link_hash_defined
&& h->root.type != bfd_link_hash_defweak)
- || htab->srelbss == NULL)
+ || s == NULL)
abort ();
rela.r_offset = (h->root.u.def.value
@@ -6018,7 +6060,7 @@ do_glob_dat:
+ h->root.u.def.section->output_offset);
rela.r_info = htab->r_info (h->dynindx, R_X86_64_COPY);
rela.r_addend = 0;
- elf_append_rela (output_bfd, htab->srelbss, &rela);
+ elf_append_rela (output_bfd, s, &rela);
}
return TRUE;
@@ -6540,7 +6582,8 @@ elf_x86_64_add_symbol_hook (bfd *abfd,
return TRUE;
}
- return TRUE;
+ return _bfd_elf_add_sharable_symbol (abfd, info, sym, namep, flagsp,
+ secp, valp);
}
@@ -6556,7 +6599,8 @@ elf_x86_64_elf_section_from_bfd_section (bfd *abfd ATTRIBUTE_UNUSED,
*index_return = SHN_X86_64_LCOMMON;
return TRUE;
}
- return FALSE;
+ return _bfd_elf_sharable_section_from_bfd_section (abfd, sec,
+ index_return);
}
/* Process a symbol. */
@@ -6574,22 +6618,26 @@ elf_x86_64_symbol_processing (bfd *abfd ATTRIBUTE_UNUSED,
asym->value = elfsym->internal_elf_sym.st_size;
/* Common symbol doesn't set BSF_GLOBAL. */
asym->flags &= ~BSF_GLOBAL;
+ return;
break;
}
+
+ _bfd_elf_sharable_symbol_processing (abfd, asym);
}
static bfd_boolean
elf_x86_64_common_definition (Elf_Internal_Sym *sym)
{
return (sym->st_shndx == SHN_COMMON
- || sym->st_shndx == SHN_X86_64_LCOMMON);
+ || sym->st_shndx == SHN_X86_64_LCOMMON
+ || _bfd_elf_sharable_common_definition (sym));
}
static unsigned int
elf_x86_64_common_section_index (asection *sec)
{
if ((elf_section_flags (sec) & SHF_X86_64_LARGE) == 0)
- return SHN_COMMON;
+ return _bfd_elf_sharable_common_section_index (sec);
else
return SHN_X86_64_LCOMMON;
}
@@ -6598,7 +6646,7 @@ static asection *
elf_x86_64_common_section (asection *sec)
{
if ((elf_section_flags (sec) & SHF_X86_64_LARGE) == 0)
- return bfd_com_section_ptr;
+ return _bfd_elf_sharable_common_section (sec);
else
return &_bfd_elf_large_com_section;
}
@@ -6608,9 +6656,12 @@ elf_x86_64_merge_symbol (struct elf_link_hash_entry *h,
const Elf_Internal_Sym *sym,
asection **psec,
bfd_boolean newdef,
+ bfd_boolean newdyn,
+ bfd *abfd,
bfd_boolean olddef,
+ bfd_boolean olddyn,
bfd *oldbfd,
- const asection *oldsec)
+ asection *oldsec)
{
/* A normal common symbol and a large common symbol result in a
normal common symbol. We turn the large common symbol into a
@@ -6619,7 +6670,8 @@ elf_x86_64_merge_symbol (struct elf_link_hash_entry *h,
&& h->root.type == bfd_link_hash_common
&& !newdef
&& bfd_is_com_section (*psec)
- && oldsec != *psec)
+ && oldsec != *psec
+ && _bfd_elf_sharable_common_section_index (oldsec) == SHN_COMMON)
{
if (sym->st_shndx == SHN_COMMON
&& (elf_section_flags (oldsec) & SHF_X86_64_LARGE) != 0)
@@ -6627,13 +6679,19 @@ elf_x86_64_merge_symbol (struct elf_link_hash_entry *h,
h->root.u.c.p->section
= bfd_make_section_old_way (oldbfd, "COMMON");
h->root.u.c.p->section->flags = SEC_ALLOC;
+ return TRUE;
}
else if (sym->st_shndx == SHN_X86_64_LCOMMON
&& (elf_section_flags (oldsec) & SHF_X86_64_LARGE) == 0)
- *psec = bfd_com_section_ptr;
+ {
+ *psec = bfd_com_section_ptr;
+ return TRUE;
+ }
}
- return TRUE;
+ return _bfd_elf_sharable_merge_symbol (h, sym, psec, newdef, newdyn,
+ abfd, olddef, olddyn, oldbfd,
+ oldsec);
}
static int