diff options
Diffstat (limited to 'bfd/elf64-x86-64.c')
-rw-r--r-- | bfd/elf64-x86-64.c | 88 |
1 files changed, 73 insertions, 15 deletions
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c index f920208..5c7eb3b 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 |