diff options
Diffstat (limited to 'bfd/elfxx-x86.c')
-rw-r--r-- | bfd/elfxx-x86.c | 81 |
1 files changed, 66 insertions, 15 deletions
diff --git a/bfd/elfxx-x86.c b/bfd/elfxx-x86.c index bc9bb70..140e868 100644 --- a/bfd/elfxx-x86.c +++ b/bfd/elfxx-x86.c @@ -366,7 +366,7 @@ elf_x86_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) htab->elf.srelgot->size += htab->sizeof_reloc; if (GOT_TLS_GDESC_P (tls_type)) { - htab->elf.srelplt->size += htab->sizeof_reloc; + htab->rel_tls_desc->size += htab->sizeof_reloc; if (bed->target_id == X86_64_ELF_DATA) htab->elf.tlsdesc_plt = (bfd_vma) -1; } @@ -882,6 +882,8 @@ _bfd_x86_elf_link_check_relocs (bfd *abfd, struct bfd_link_info *info) h = (struct elf_link_hash_entry *) h->root.u.i.link; elf_x86_hash_entry (h)->tls_get_addr = 1; } + + htab->has_tls_get_addr_call = 1; } /* Pass NULL for __ehdr_start which will be defined by @@ -1891,7 +1893,7 @@ _bfd_x86_elf_create_sframe_plt (bfd *output_bfd, } *ectx = sframe_encode (SFRAME_VERSION_2, - 0, + SFRAME_F_FDE_FUNC_START_PCREL, SFRAME_ABI_AMD64_ENDIAN_LITTLE, SFRAME_CFA_FIXED_FP_INVALID, -8, /* Fixed RA offset. */ @@ -2155,6 +2157,16 @@ _bfd_elf_x86_finish_relative_relocs (struct bfd_link_info *info) return true; } +asection * +_bfd_elf_x86_get_reloc_section (bfd *abfd, const char *name) +{ + /* Treat .rel.tls/.rela.tls section the same as .rel.plt/.rela.plt + section. */ + if (strcmp (name, ".tls") == 0) + name = ".plt"; + return _bfd_elf_plt_get_reloc_section (abfd, name); +} + bool _bfd_elf_x86_valid_reloc_p (asection *input_section, struct bfd_link_info *info, @@ -2374,7 +2386,7 @@ _bfd_x86_elf_late_size_sections (bfd *output_bfd, srel->size += htab->sizeof_reloc; if (GOT_TLS_GDESC_P (*local_tls_type)) { - htab->elf.srelplt->size += htab->sizeof_reloc; + htab->rel_tls_desc->size += htab->sizeof_reloc; if (bed->target_id == X86_64_ELF_DATA) htab->elf.tlsdesc_plt = (bfd_vma) -1; } @@ -2415,7 +2427,6 @@ _bfd_x86_elf_late_size_sections (bfd *output_bfd, so that R_{386,X86_64}_IRELATIVE entries come last. */ if (htab->elf.srelplt) { - htab->next_tls_desc_index = htab->elf.srelplt->reloc_count; htab->sgotplt_jump_table_size = elf_x86_compute_jump_table_size (htab); htab->next_irelative_index = htab->elf.srelplt->reloc_count - 1; @@ -2445,6 +2456,8 @@ _bfd_x86_elf_late_size_sections (bfd *output_bfd, if (htab->elf.sgotplt) { + asection *eh_frame; + /* Don't allocate .got.plt section if there are no GOT nor PLT entries and there is no reference to _GLOBAL_OFFSET_TABLE_. */ if ((htab->elf.hgot == NULL @@ -2457,7 +2470,11 @@ _bfd_x86_elf_late_size_sections (bfd *output_bfd, && (htab->elf.iplt == NULL || htab->elf.iplt->size == 0) && (htab->elf.igotplt == NULL - || htab->elf.igotplt->size == 0)) + || htab->elf.igotplt->size == 0) + && (!htab->elf.dynamic_sections_created + || (eh_frame = bfd_get_section_by_name (output_bfd, + ".eh_frame")) == NULL + || eh_frame->rawsize == 0)) { htab->elf.sgotplt->size = 0; /* Solaris requires to keep _GLOBAL_OFFSET_TABLE_ even if it @@ -3140,10 +3157,16 @@ _bfd_x86_elf_copy_indirect_symbol (struct bfd_link_info *info, eind->tls_type = GOT_UNKNOWN; } - /* Copy gotoff_ref so that elf_i386_adjust_dynamic_symbol will + /* Copy gotoff_ref so that _bfd_x86_elf_adjust_dynamic_symbol will generate a R_386_COPY reloc. */ edir->gotoff_ref |= eind->gotoff_ref; + /* Copy non_got_ref_without_indirect_extern_access so that + _bfd_x86_elf_adjust_dynamic_symbol will handle + GNU_PROPERTY_1_NEEDED_INDIRECT_EXTERN_ACCESS properly. */ + edir->non_got_ref_without_indirect_extern_access + |= eind->non_got_ref_without_indirect_extern_access; + edir->zero_undefweak |= eind->zero_undefweak; if (ELIMINATE_COPY_RELOCS @@ -3348,6 +3371,26 @@ _bfd_x86_elf_link_report_tls_transition_error bfd_set_error (bfd_error_bad_value); } +/* Report TLS invalid section error. */ + +void +_bfd_x86_elf_link_report_tls_invalid_section_error + (bfd *abfd, asection *sec, Elf_Internal_Shdr *symtab_hdr, + struct elf_link_hash_entry *h, Elf_Internal_Sym *sym, + reloc_howto_type *howto) +{ + const char *name; + if (h) + name = h->root.root.string; + else + name = bfd_elf_sym_name (abfd, symtab_hdr, sym, NULL); + _bfd_error_handler + /* xgettext:c-format */ + (_("%pB: relocation %s against thread local symbol `%s' in " + "invalid section `%pA'"), abfd, howto->name, name, sec); + bfd_set_error (bfd_error_bad_value); +} + /* Return TRUE if symbol should be hashed in the `.gnu.hash' section. */ bool @@ -3648,7 +3691,7 @@ _bfd_x86_elf_link_symbol_references_local (struct bfd_link_info *info, || (h->root.type == bfd_link_hash_undefweak && (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT || (bfd_link_executable (info) - && htab->interp == NULL) + && htab->elf.interp == NULL) || info->dynamic_undefined_weak == 0)) || ((h->def_regular || ELF_COMMON_DEF_P (h)) && info->version_info != NULL @@ -4604,6 +4647,8 @@ _bfd_x86_elf_link_setup_gnu_properties htab->sframe_plt = init_table->sframe_non_lazy_plt; } } + else if (lazy_plt) + htab->sframe_plt = init_table->sframe_lazy_plt; else htab->sframe_plt = NULL; @@ -4683,15 +4728,12 @@ _bfd_x86_elf_link_setup_gnu_properties { /* Whe creating executable, set the contents of the .interp section to the interpreter. */ - if (bfd_link_executable (info) && !info->nointerp) + asection *s = htab->elf.interp; + if (s != NULL) { - asection *s = bfd_get_linker_section (dynobj, ".interp"); - if (s == NULL) - abort (); s->size = htab->dynamic_interpreter_size; s->contents = (unsigned char *) htab->dynamic_interpreter; s->alloced = 1; - htab->interp = s; } if (normal_target) @@ -4738,6 +4780,14 @@ _bfd_x86_elf_link_setup_gnu_properties } } + sec = bfd_make_section_anyway_with_flags + (dynobj, bed->rela_plts_and_copies_p ? ".rela.tls" : ".rel.tls", + bed->dynamic_sec_flags | SEC_READONLY); + if (sec == NULL + || !bfd_set_section_alignment (sec, bed->s->log_file_align)) + return false; + htab->rel_tls_desc = sec; + if (!info->no_ld_generated_unwind_info) { flagword flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY @@ -4785,11 +4835,10 @@ _bfd_x86_elf_link_setup_gnu_properties | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED); - sec = bfd_make_section_anyway_with_flags (dynobj, - ".sframe", - flags); + sec = bfd_make_section_anyway_with_flags (dynobj, ".sframe", flags); if (sec == NULL) info->callbacks->fatal (_("%P: failed to create PLT .sframe section\n")); + elf_section_type (sec) = SHT_GNU_SFRAME; // FIXME check this // if (!bfd_set_section_alignment (sec, class_align)) @@ -4805,6 +4854,7 @@ _bfd_x86_elf_link_setup_gnu_properties flags); if (sec == NULL) info->callbacks->fatal (_("%P: failed to create second PLT .sframe section\n")); + elf_section_type (sec) = SHT_GNU_SFRAME; htab->plt_second_sframe = sec; } @@ -4817,6 +4867,7 @@ _bfd_x86_elf_link_setup_gnu_properties flags); if (sec == NULL) info->callbacks->fatal (_("%P: failed to create PLT GOT .sframe section\n")); + elf_section_type (sec) = SHT_GNU_SFRAME; htab->plt_got_sframe = sec; } |