X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=bfd%2Felfxx-x86.c;h=29b020442f808aef23e0570e4e7f8ea30489d8ec;hb=423054beadf317757d43aefb9eddfe711a42e3e1;hp=d8165d17528006689572634db163274fdc004033;hpb=fd3619828e94a24a92cddec42cbc0ab33352eeb4;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elfxx-x86.c b/bfd/elfxx-x86.c index d8165d1752..29b020442f 100644 --- a/bfd/elfxx-x86.c +++ b/bfd/elfxx-x86.c @@ -1,5 +1,5 @@ /* x86 specific support for ELF - Copyright (C) 2017-2019 Free Software Foundation, Inc. + Copyright (C) 2017-2020 Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. @@ -131,8 +131,7 @@ elf_x86_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) if (h->type == STT_GNU_IFUNC && h->def_regular) { - if (_bfd_elf_allocate_ifunc_dyn_relocs (info, h, &eh->dyn_relocs, - &htab->readonly_dynrelocs_against_ifunc, + if (_bfd_elf_allocate_ifunc_dyn_relocs (info, h, &h->dyn_relocs, plt_entry_size, (htab->plt.has_plt0 * plt_entry_size), @@ -260,7 +259,7 @@ elf_x86_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) } } - if (htab->target_os == is_vxworks && !bfd_link_pic (info)) + if (htab->elf.target_os == is_vxworks && !bfd_link_pic (info)) { /* VxWorks has a second set of relocations for each PLT entry in executables. They go in a separate relocation section, @@ -347,7 +346,8 @@ elf_x86_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) (but if both R_386_TLS_IE_32 and R_386_TLS_IE is present, we need two), R_386_TLS_GD and R_X86_64_TLSGD need one if local symbol and two if global. No dynamic relocation against - resolved undefined weak symbol in executable. */ + resolved undefined weak symbol in executable. No dynamic + relocation against non-preemptible absolute symbol. */ if (tls_type == GOT_TLS_IE_BOTH) htab->elf.srelgot->size += 2 * htab->sizeof_reloc; else if ((GOT_TLS_GD_P (tls_type) && h->dynindx == -1) @@ -359,20 +359,22 @@ elf_x86_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) && ((ELF_ST_VISIBILITY (h->other) == STV_DEFAULT && !resolved_to_zero) || h->root.type != bfd_link_hash_undefweak) - && (bfd_link_pic (info) + && ((bfd_link_pic (info) + && !(h->dynindx == -1 + && ABS_SYMBOL_P (h))) || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h))) htab->elf.srelgot->size += htab->sizeof_reloc; if (GOT_TLS_GDESC_P (tls_type)) { htab->elf.srelplt->size += htab->sizeof_reloc; if (bed->target_id == X86_64_ELF_DATA) - htab->tlsdesc_plt = (bfd_vma) -1; + htab->elf.tlsdesc_plt = (bfd_vma) -1; } } else h->got.offset = (bfd_vma) -1; - if (eh->dyn_relocs == NULL) + if (h->dyn_relocs == NULL) return TRUE; /* In the shared -Bsymbolic case, discard space allocated for @@ -393,7 +395,7 @@ elf_x86_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) { struct elf_dyn_relocs **pp; - for (pp = &eh->dyn_relocs; (p = *pp) != NULL; ) + for (pp = &h->dyn_relocs; (p = *pp) != NULL; ) { p->count -= p->pc_count; p->pc_count = 0; @@ -404,10 +406,10 @@ elf_x86_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) } } - if (htab->target_os == is_vxworks) + if (htab->elf.target_os == is_vxworks) { struct elf_dyn_relocs **pp; - for (pp = &eh->dyn_relocs; (p = *pp) != NULL; ) + for (pp = &h->dyn_relocs; (p = *pp) != NULL; ) { if (strcmp (p->sec->output_section->name, ".tls_vars") == 0) *pp = p->next; @@ -418,7 +420,7 @@ elf_x86_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) /* Also discard relocs on undefined weak syms with non-default visibility or in PIE. */ - if (eh->dyn_relocs != NULL) + if (h->dyn_relocs != NULL) { if (h->root.type == bfd_link_hash_undefweak) { @@ -434,7 +436,7 @@ elf_x86_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) that we can branch to 0 without PLT. */ struct elf_dyn_relocs **pp; - for (pp = &eh->dyn_relocs; (p = *pp) != NULL; ) + for (pp = &h->dyn_relocs; (p = *pp) != NULL; ) if (p->pc_count == 0) *pp = p->next; else @@ -447,12 +449,12 @@ elf_x86_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) /* Make sure undefined weak symbols are output as dynamic symbols in PIEs for dynamic non-GOT non-PLT reloations. */ - if (eh->dyn_relocs != NULL + if (h->dyn_relocs != NULL && !bfd_elf_link_record_dynamic_symbol (info, h)) return FALSE; } else - eh->dyn_relocs = NULL; + h->dyn_relocs = NULL; } else if (h->dynindx == -1 && !h->forced_local @@ -469,7 +471,7 @@ elf_x86_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) which turn out to need copy relocs. */ struct elf_dyn_relocs **pp; - for (pp = &eh->dyn_relocs; (p = *pp) != NULL; ) + for (pp = &h->dyn_relocs; (p = *pp) != NULL; ) { if (p->pc_count != 0) *pp = p->next; @@ -510,13 +512,13 @@ elf_x86_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) goto keep; } - eh->dyn_relocs = NULL; + h->dyn_relocs = NULL; keep: ; } /* Finally, allocate space. */ - for (p = eh->dyn_relocs; p != NULL; p = p->next) + for (p = h->dyn_relocs; p != NULL; p = p->next) { asection *sreloc; @@ -529,62 +531,6 @@ elf_x86_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) return TRUE; } -/* Find dynamic relocs for H that apply to read-only sections. */ - -static asection * -readonly_dynrelocs (struct elf_link_hash_entry *h) -{ - struct elf_dyn_relocs *p; - - for (p = elf_x86_hash_entry (h)->dyn_relocs; p != NULL; p = p->next) - { - asection *s = p->sec->output_section; - - if (s != NULL && (s->flags & SEC_READONLY) != 0) - return p->sec; - } - return NULL; -} - -/* Set DF_TEXTREL if we find any dynamic relocs that apply to - read-only sections. */ - -static bfd_boolean -maybe_set_textrel (struct elf_link_hash_entry *h, void *inf) -{ - asection *sec; - - if (h->root.type == bfd_link_hash_indirect) - return TRUE; - - /* Skip local IFUNC symbols. */ - if (h->forced_local && h->type == STT_GNU_IFUNC) - return TRUE; - - sec = readonly_dynrelocs (h); - if (sec != NULL) - { - struct bfd_link_info *info = (struct bfd_link_info *) inf; - - info->flags |= DF_TEXTREL; - /* xgettext:c-format */ - info->callbacks->minfo (_("%pB: dynamic relocation against `%pT' " - "in read-only section `%pA'\n"), - sec->owner, h->root.root.string, sec); - - if ((info->warn_shared_textrel && bfd_link_pic (info)) - || info->error_textrel) - /* xgettext:c-format */ - info->callbacks->einfo (_("%P: %pB: warning: relocation against `%s' " - "in read-only section `%pA'\n"), - sec->owner, h->root.root.string, sec); - - /* Not an error, just cut short the traversal. */ - return FALSE; - } - return TRUE; -} - /* Allocate space in .plt, .got and associated reloc sections for local dynamic relocs. */ @@ -756,7 +702,7 @@ _bfd_x86_elf_link_hash_table_create (bfd *abfd) { struct elf_x86_link_hash_table *ret; const struct elf_backend_data *bed; - bfd_size_type amt = sizeof (struct elf_x86_link_hash_table); + size_t amt = sizeof (struct elf_x86_link_hash_table); ret = (struct elf_x86_link_hash_table *) bfd_zmalloc (amt); if (ret == NULL) @@ -815,8 +761,6 @@ _bfd_x86_elf_link_hash_table_create (bfd *abfd) ret->tls_get_addr = "___tls_get_addr"; } } - ret->target_id = bed->target_id; - ret->target_os = get_elf_x86_backend_data (abfd)->target_os; ret->loc_hash_table = htab_try_create (1024, _bfd_x86_elf_local_htab_hash, @@ -952,6 +896,100 @@ _bfd_x86_elf_link_check_relocs (bfd *abfd, struct bfd_link_info *info) return _bfd_elf_link_check_relocs (abfd, info); } +bfd_boolean +_bfd_elf_x86_valid_reloc_p (asection *input_section, + struct bfd_link_info *info, + struct elf_x86_link_hash_table *htab, + const Elf_Internal_Rela *rel, + struct elf_link_hash_entry *h, + Elf_Internal_Sym *sym, + Elf_Internal_Shdr *symtab_hdr, + bfd_boolean *no_dynreloc_p) +{ + bfd_boolean valid_p = TRUE; + + *no_dynreloc_p = FALSE; + + /* Check If relocation against non-preemptible absolute symbol is + valid in PIC. FIXME: Can't use SYMBOL_REFERENCES_LOCAL_P since + it may call _bfd_elf_link_hide_sym_by_version and result in + ld-elfvers/ vers21 test failure. */ + if (bfd_link_pic (info) + && (h == NULL || SYMBOL_REFERENCES_LOCAL (info, h))) + { + const struct elf_backend_data *bed; + unsigned int r_type; + Elf_Internal_Rela irel; + + /* Skip non-absolute symbol. */ + if (h) + { + if (!ABS_SYMBOL_P (h)) + return valid_p; + } + else if (sym->st_shndx != SHN_ABS) + return valid_p; + + bed = get_elf_backend_data (input_section->owner); + r_type = ELF32_R_TYPE (rel->r_info); + irel = *rel; + + /* Only allow relocations against absolute symbol, which can be + resolved as absolute value + addend. GOTPCREL relocations + are allowed since absolute value + addend is stored in the + GOT slot. */ + if (bed->target_id == X86_64_ELF_DATA) + { + r_type &= ~R_X86_64_converted_reloc_bit; + valid_p = (r_type == R_X86_64_64 + || r_type == R_X86_64_32 + || r_type == R_X86_64_32S + || r_type == R_X86_64_16 + || r_type == R_X86_64_8 + || r_type == R_X86_64_GOTPCREL + || r_type == R_X86_64_GOTPCRELX + || r_type == R_X86_64_REX_GOTPCRELX); + if (!valid_p) + { + unsigned int r_symndx = htab->r_sym (rel->r_info); + irel.r_info = htab->r_info (r_symndx, r_type); + } + } + else + valid_p = (r_type == R_386_32 + || r_type == R_386_16 + || r_type == R_386_8); + + if (valid_p) + *no_dynreloc_p = TRUE; + else + { + const char *name; + arelent internal_reloc; + + if (!bed->elf_info_to_howto (input_section->owner, + &internal_reloc, &irel) + || internal_reloc.howto == NULL) + abort (); + + if (h) + name = h->root.root.string; + else + name = bfd_elf_sym_name (input_section->owner, symtab_hdr, + sym, NULL); + info->callbacks->einfo + /* xgettext:c-format */ + (_("%F%P: %pB: relocation %s against absolute symbol " + "`%s' in section `%pA' is disallowed\n"), + input_section->owner, internal_reloc.howto->name, name, + input_section); + bfd_set_error (bfd_error_bad_value); + } + } + + return valid_p; +} + /* Set the sizes of the dynamic sections. */ bfd_boolean @@ -1005,7 +1043,7 @@ _bfd_x86_elf_size_dynamic_sections (bfd *output_bfd, linker script /DISCARD/, so we'll be discarding the relocs too. */ } - else if (htab->target_os == is_vxworks + else if (htab->elf.target_os == is_vxworks && strcmp (p->sec->output_section->name, ".tls_vars") == 0) { @@ -1020,8 +1058,7 @@ _bfd_x86_elf_size_dynamic_sections (bfd *output_bfd, && (info->flags & DF_TEXTREL) == 0) { info->flags |= DF_TEXTREL; - if ((info->warn_shared_textrel && bfd_link_pic (info)) - || info->error_textrel) + if (bfd_link_textrel_check (info)) /* xgettext:c-format */ info->callbacks->einfo (_("%P: %pB: warning: relocation " @@ -1065,7 +1102,7 @@ _bfd_x86_elf_size_dynamic_sections (bfd *output_bfd, || *local_tls_type == GOT_TLS_IE_BOTH) s->size += htab->got_entry_size; } - if (bfd_link_pic (info) + if ((bfd_link_pic (info) && *local_tls_type != GOT_ABS) || GOT_TLS_GD_ANY_P (*local_tls_type) || (*local_tls_type & GOT_TLS_IE)) { @@ -1078,7 +1115,7 @@ _bfd_x86_elf_size_dynamic_sections (bfd *output_bfd, { htab->elf.srelplt->size += htab->sizeof_reloc; if (bed->target_id == X86_64_ELF_DATA) - htab->tlsdesc_plt = (bfd_vma) -1; + htab->elf.tlsdesc_plt = (bfd_vma) -1; } } } @@ -1125,22 +1162,22 @@ _bfd_x86_elf_size_dynamic_sections (bfd *output_bfd, else if (htab->elf.irelplt) htab->next_irelative_index = htab->elf.irelplt->reloc_count - 1; - if (htab->tlsdesc_plt) + if (htab->elf.tlsdesc_plt) { /* NB: tlsdesc_plt is set only for x86-64. If we're not using lazy TLS relocations, don't generate the PLT and GOT entries they require. */ if ((info->flags & DF_BIND_NOW)) - htab->tlsdesc_plt = 0; + htab->elf.tlsdesc_plt = 0; else { - htab->tlsdesc_got = htab->elf.sgot->size; + htab->elf.tlsdesc_got = htab->elf.sgot->size; htab->elf.sgot->size += htab->got_entry_size; /* Reserve room for the initial entry. FIXME: we could probably do away with it in this case. */ if (htab->elf.splt->size == 0) htab->elf.splt->size = htab->plt.plt_entry_size; - htab->tlsdesc_plt = htab->elf.splt->size; + htab->elf.tlsdesc_plt = htab->elf.splt->size; htab->elf.splt->size += htab->plt.plt_entry_size; } } @@ -1164,7 +1201,8 @@ _bfd_x86_elf_size_dynamic_sections (bfd *output_bfd, htab->elf.sgotplt->size = 0; /* Solaris requires to keep _GLOBAL_OFFSET_TABLE_ even if it isn't used. */ - if (htab->elf.hgot != NULL && htab->target_os != is_solaris) + if (htab->elf.hgot != NULL + && htab->elf.target_os != is_solaris) { /* Remove the unused _GLOBAL_OFFSET_TABLE_ from symbol table. */ @@ -1356,7 +1394,7 @@ _bfd_x86_elf_size_dynamic_sections (bfd *output_bfd, return FALSE; } - if (htab->tlsdesc_plt + if (htab->elf.tlsdesc_plt && (!add_dynamic_entry (DT_TLSDESC_PLT, 0) || !add_dynamic_entry (DT_TLSDESC_GOT, 0))) return FALSE; @@ -1372,25 +1410,22 @@ _bfd_x86_elf_size_dynamic_sections (bfd *output_bfd, /* If any dynamic relocs apply to a read-only section, then we need a DT_TEXTREL entry. */ if ((info->flags & DF_TEXTREL) == 0) - elf_link_hash_traverse (&htab->elf, maybe_set_textrel, info); + elf_link_hash_traverse (&htab->elf, + _bfd_elf_maybe_set_textrel, info); if ((info->flags & DF_TEXTREL) != 0) { - if (htab->readonly_dynrelocs_against_ifunc) - { - info->callbacks->einfo - (_("%P%X: read-only segment has dynamic IFUNC relocations;" - " recompile with %s\n"), - bfd_link_dll (info) ? "-fPIC" : "-fPIE"); - bfd_set_error (bfd_error_bad_value); - return FALSE; - } + if (htab->elf.ifunc_resolvers) + info->callbacks->einfo + (_("%P: warning: GNU indirect functions with DT_TEXTREL " + "may result in a segfault at runtime; recompile with %s\n"), + bfd_link_dll (info) ? "-fPIC" : "-fPIE"); if (!add_dynamic_entry (DT_TEXTREL, 0)) return FALSE; } } - if (htab->target_os == is_vxworks + if (htab->elf.target_os == is_vxworks && !elf_vxworks_add_dynamic_entries (output_bfd, info)) return FALSE; } @@ -1482,7 +1517,7 @@ _bfd_x86_elf_finish_dynamic_sections (bfd *output_bfd, switch (dyn.d_tag) { default: - if (htab->target_os == is_vxworks + if (htab->elf.target_os == is_vxworks && elf_vxworks_finish_dynamic_entry (output_bfd, &dyn)) break; continue; @@ -1504,13 +1539,13 @@ _bfd_x86_elf_finish_dynamic_sections (bfd *output_bfd, case DT_TLSDESC_PLT: s = htab->elf.splt; dyn.d_un.d_ptr = s->output_section->vma + s->output_offset - + htab->tlsdesc_plt; + + htab->elf.tlsdesc_plt; break; case DT_TLSDESC_GOT: s = htab->elf.sgot; dyn.d_un.d_ptr = s->output_section->vma + s->output_offset - + htab->tlsdesc_got; + + htab->elf.tlsdesc_got; break; } @@ -1688,37 +1723,6 @@ _bfd_x86_elf_copy_indirect_symbol (struct bfd_link_info *info, edir = (struct elf_x86_link_hash_entry *) dir; eind = (struct elf_x86_link_hash_entry *) ind; - if (eind->dyn_relocs != NULL) - { - if (edir->dyn_relocs != NULL) - { - struct elf_dyn_relocs **pp; - struct elf_dyn_relocs *p; - - /* Add reloc counts against the indirect sym to the direct sym - list. Merge any entries against the same section. */ - for (pp = &eind->dyn_relocs; (p = *pp) != NULL; ) - { - struct elf_dyn_relocs *q; - - for (q = edir->dyn_relocs; q != NULL; q = q->next) - if (q->sec == p->sec) - { - q->pc_count += p->pc_count; - q->count += p->count; - *pp = p->next; - break; - } - if (q == NULL) - pp = &p->next; - } - *pp = edir->dyn_relocs; - } - - edir->dyn_relocs = eind->dyn_relocs; - eind->dyn_relocs = NULL; - } - if (ind->root.type == bfd_link_hash_indirect && dir->got.refcount <= 0) { @@ -1855,7 +1859,7 @@ _bfd_x86_elf_adjust_dynamic_symbol (struct bfd_link_info *info, struct elf_dyn_relocs **pp; eh = (struct elf_x86_link_hash_entry *) h; - for (pp = &eh->dyn_relocs; (p = *pp) != NULL; ) + for (pp = &h->dyn_relocs; (p = *pp) != NULL; ) { pc_count += p->pc_count; p->count -= p->pc_count; @@ -1978,12 +1982,12 @@ _bfd_x86_elf_adjust_dynamic_symbol (struct bfd_link_info *info, if (ELIMINATE_COPY_RELOCS && (bed->target_id == X86_64_ELF_DATA || (!eh->gotoff_ref - && htab->target_os != is_vxworks))) + && htab->elf.target_os != is_vxworks))) { /* If we don't find any dynamic relocs in read-only sections, then we'll be keeping the dynamic relocs and avoiding the copy reloc. */ - if (!readonly_dynrelocs (h)) + if (!_bfd_elf_readonly_dynrelocs (h)) { h->non_got_ref = 0; return TRUE; @@ -2347,15 +2351,14 @@ _bfd_x86_elf_get_synthetic_symtab (bfd *abfd, /* PLT entries with R_386_TLS_DESC relocations are skipped. */ if (n == 0) { -bad_return: + bad_return: count = -1; } else count = n; for (j = 0; plts[j].name != NULL; j++) - if (plts[j].contents != NULL) - free (plts[j].contents); + free (plts[j].contents); free (dynrelbuf); @@ -2626,7 +2629,7 @@ _bfd_x86_elf_link_setup_gnu_properties if (!bfd_set_section_alignment (sec, class_align)) { -error_alignment: + error_alignment: info->callbacks->einfo (_("%F%pA: failed to align section\n"), sec); } @@ -2754,7 +2757,7 @@ error_alignment: still be used with LD_AUDIT or LD_PROFILE if PLT entry is used for canonical function address. */ htab->plt.has_plt0 = 1; - normal_target = htab->target_os == is_normal; + normal_target = htab->elf.target_os == is_normal; if (normal_target) { @@ -2817,7 +2820,7 @@ error_alignment: htab->plt.eh_frame_plt = htab->lazy_plt->eh_frame_plt; } - if (htab->target_os == is_vxworks + if (htab->elf.target_os == is_vxworks && !elf_vxworks_create_dynamic_sections (dynobj, info, &htab->srelplt2)) { @@ -2998,6 +3001,23 @@ error_alignment: : bed->plt_alignment); } + if (bfd_link_executable (info) + && !info->nointerp + && !htab->params->has_dynamic_linker + && htab->params->static_before_all_inputs) + { + /* Report error for dynamic input objects if -static is passed at + command-line before all input files without --dynamic-linker + unless --no-dynamic-linker is used. */ + bfd *abfd; + + for (abfd = info->input_bfds; abfd != NULL; abfd = abfd->link.next) + if ((abfd->flags & DYNAMIC)) + info->callbacks->einfo + (_("%X%P: attempted static link of dynamic object `%pB'\n"), + abfd); + } + return pbfd; }