X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=bfd%2Felf64-x86-64.c;h=b82bcd11b768993134da4b75507fafd3254d3573;hb=d8045f234d8865a7a7bfce71e81fcbeaf4098a7e;hp=1ea033bda04c38beba4ee35933145e8fdd18940a;hpb=e7c3341679431c5ecfc170a984d7196cdc175777;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c index 1ea033bda0..b82bcd11b7 100644 --- a/bfd/elf64-x86-64.c +++ b/bfd/elf64-x86-64.c @@ -161,6 +161,12 @@ static reloc_howto_type x86_64_elf_howto_table[] = FALSE) }; +#define IS_X86_64_PCREL_TYPE(TYPE) \ + ( ((TYPE) == R_X86_64_PC8) \ + || ((TYPE) == R_X86_64_PC16) \ + || ((TYPE) == R_X86_64_PC32) \ + || ((TYPE) == R_X86_64_PC64)) + /* Map BFD relocs to the x86_64 elf relocs. */ struct elf_reloc_map { @@ -810,11 +816,14 @@ elf64_x86_64_check_tls_transition (bfd *abfd, asection *sec, return FALSE; h = sym_hashes[r_symndx - symtab_hdr->sh_info]; + /* Use strncmp to check __tls_get_addr since __tls_get_addr + may be versioned. */ return (h != NULL && h->root.root.string != NULL && (ELF64_R_TYPE (rel[1].r_info) == R_X86_64_PC32 || ELF64_R_TYPE (rel[1].r_info) == R_X86_64_PLT32) - && (strcmp (h->root.root.string, "__tls_get_addr") == 0)); + && (strncmp (h->root.root.string, + "__tls_get_addr", 14) == 0)); case R_X86_64_GOTTPOFF: /* Check transition from IE access model: @@ -987,8 +996,7 @@ is_indirect_symbol (bfd * abfd, struct elf_link_hash_entry * h) bed = get_elf_backend_data (abfd); - return h->type == STT_IFUNC - && bed != NULL + return h->type == STT_GNU_IFUNC && (bed->elf_osabi == ELFOSABI_LINUX /* GNU/Linux is still using the default value 0. */ || bed->elf_osabi == ELFOSABI_NONE); @@ -1020,7 +1028,7 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, sym_hashes = elf_sym_hashes (abfd); sreloc = NULL; - + rel_end = relocs + sec->reloc_count; for (rel = relocs; rel < rel_end; rel++) { @@ -1275,16 +1283,10 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, If on the other hand, we are creating an executable, we may need to keep relocations for symbols satisfied by a dynamic library if we manage to avoid copy relocs for the - symbol. - - Also we must keep any relocations against IFUNC symbols as - they will be evaluated at load time. */ + symbol. */ if ((info->shared && (sec->flags & SEC_ALLOC) != 0 - && (((r_type != R_X86_64_PC8) - && (r_type != R_X86_64_PC16) - && (r_type != R_X86_64_PC32) - && (r_type != R_X86_64_PC64)) + && (! IS_X86_64_PCREL_TYPE (r_type) || (h != NULL && (! SYMBOLIC_BIND (info, h) || h->root.type == bfd_link_hash_defweak @@ -1294,8 +1296,7 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, && (sec->flags & SEC_ALLOC) != 0 && h != NULL && (h->root.type == bfd_link_hash_defweak - || !h->def_regular)) - || is_indirect_symbol (abfd, h)) + || !h->def_regular))) { struct elf64_x86_64_dyn_relocs *p; struct elf64_x86_64_dyn_relocs **head; @@ -1313,10 +1314,13 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, if (sreloc == NULL) return FALSE; - } - if (is_indirect_symbol (abfd, h)) - (void) _bfd_elf_make_ifunc_reloc_section (abfd, sec, htab->elf.dynobj, 2); + /* Create the ifunc section, even if we will not encounter an + indirect function symbol. We may not even see one in the input + object file, but we can still encounter them in libraries. */ + (void) _bfd_elf_make_ifunc_reloc_section + (abfd, sec, htab->elf.dynobj, 2); + } /* If this is a global symbol, we count the number of relocations we need for this symbol. */ @@ -1347,6 +1351,7 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, if (p == NULL || p->sec != sec) { bfd_size_type amt = sizeof *p; + p = ((struct elf64_x86_64_dyn_relocs *) bfd_alloc (htab->elf.dynobj, amt)); if (p == NULL) @@ -1359,10 +1364,7 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, } p->count += 1; - if (r_type == R_X86_64_PC8 - || r_type == R_X86_64_PC16 - || r_type == R_X86_64_PC32 - || r_type == R_X86_64_PC64) + if (IS_X86_64_PCREL_TYPE (r_type)) p->pc_count += 1; } break; @@ -1673,6 +1675,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf) struct elf64_x86_64_link_hash_table *htab; struct elf64_x86_64_link_hash_entry *eh; struct elf64_x86_64_dyn_relocs *p; + bfd_boolean use_indirect_section = FALSE; if (h->root.type == bfd_link_hash_indirect) return TRUE; @@ -1751,7 +1754,9 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf) && !info->shared && h->dynindx == -1 && elf64_x86_64_hash_entry (h)->tls_type == GOT_TLS_IE) - h->got.offset = (bfd_vma) -1; + { + h->got.offset = (bfd_vma) -1; + } else if (h->got.refcount > 0) { asection *s; @@ -1850,19 +1855,20 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf) /* Make sure undefined weak symbols are output as a dynamic symbol in PIEs. */ else if (h->dynindx == -1 - && !h->forced_local) - { - if (! bfd_elf_link_record_dynamic_symbol (info, h)) - return FALSE; - } + && ! h->forced_local + && ! bfd_elf_link_record_dynamic_symbol (info, h)) + return FALSE; } } - else if (is_indirect_symbol (info->output_bfd, h)) + else if (is_indirect_symbol (info->output_bfd, h) + && h->dynindx == -1 + && ! h->forced_local) { - if (h->dynindx == -1 - && ! h->forced_local - && ! bfd_elf_link_record_dynamic_symbol (info, h)) - return FALSE; + if (bfd_elf_link_record_dynamic_symbol (info, h) + && h->dynindx != -1) + use_indirect_section = TRUE; + else + return FALSE; } else if (ELIMINATE_COPY_RELOCS) { @@ -1880,11 +1886,9 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf) /* Make sure this symbol is output as a dynamic symbol. Undefined weak syms won't yet be marked as dynamic. */ if (h->dynindx == -1 - && !h->forced_local) - { - if (! bfd_elf_link_record_dynamic_symbol (info, h)) - return FALSE; - } + && ! h->forced_local + && ! bfd_elf_link_record_dynamic_symbol (info, h)) + return FALSE; /* If that succeeded, we know we'll be keeping all the relocs. */ @@ -1902,8 +1906,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf) { asection * sreloc; - if (! info->shared - && is_indirect_symbol (info->output_bfd, h)) + if (use_indirect_section) sreloc = elf_section_data (p->sec)->indirect_relocs; else sreloc = elf_section_data (p->sec)->sreloc; @@ -2708,11 +2711,14 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info, && (h == NULL || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT || h->root.type != bfd_link_hash_undefweak) - && ((r_type != R_X86_64_PC8 - && r_type != R_X86_64_PC16 - && r_type != R_X86_64_PC32 - && r_type != R_X86_64_PC64) - || !SYMBOL_CALLS_LOCAL (info, h))) + && (! IS_X86_64_PCREL_TYPE (r_type) + || ! SYMBOL_CALLS_LOCAL (info, h))) + || (! info->shared + && h != NULL + && h->dynindx != -1 + && ! h->forced_local + && ((struct elf64_x86_64_link_hash_entry *) h)->dyn_relocs != NULL + && is_indirect_symbol (output_bfd, h)) || (ELIMINATE_COPY_RELOCS && !info->shared && h != NULL @@ -2721,8 +2727,7 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info, && ((h->def_dynamic && !h->def_regular) || h->root.type == bfd_link_hash_undefweak - || h->root.type == bfd_link_hash_undefined)) - || is_indirect_symbol (output_bfd, h)) + || h->root.type == bfd_link_hash_undefined))) { Elf_Internal_Rela outrel; bfd_byte *loc; @@ -2753,13 +2758,10 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info, become local. */ else if (h != NULL && h->dynindx != -1 - && (r_type == R_X86_64_PC8 - || r_type == R_X86_64_PC16 - || r_type == R_X86_64_PC32 - || r_type == R_X86_64_PC64 - || !info->shared - || !SYMBOLIC_BIND (info, h) - || !h->def_regular)) + && (IS_X86_64_PCREL_TYPE (r_type) + || ! info->shared + || ! SYMBOLIC_BIND (info, h) + || ! h->def_regular)) { outrel.r_info = ELF64_R_INFO (h->dynindx, r_type); outrel.r_addend = rel->r_addend; @@ -2808,11 +2810,17 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info, } } - if ((! info->shared) && is_indirect_symbol (output_bfd, h)) + if (! info->shared + && h != NULL + && h->dynindx != -1 + && ! h->forced_local + && is_indirect_symbol (output_bfd, h) + && elf_section_data (input_section)->indirect_relocs != NULL + && elf_section_data (input_section)->indirect_relocs->contents != NULL) sreloc = elf_section_data (input_section)->indirect_relocs; else sreloc = elf_section_data (input_section)->sreloc; - + BFD_ASSERT (sreloc != NULL && sreloc->contents != NULL); loc = sreloc->contents; @@ -2823,7 +2831,7 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info, not want to fiddle with the addend. Otherwise, we need to include the symbol value so that it becomes an addend for the dynamic reloc. */ - if (! relocate || is_indirect_symbol (output_bfd, h)) + if (! relocate) continue; } @@ -3698,11 +3706,12 @@ elf64_x86_64_section_from_shdr (bfd *abfd, static bfd_boolean elf64_x86_64_add_symbol_hook (bfd *abfd, - struct bfd_link_info *info ATTRIBUTE_UNUSED, + struct bfd_link_info *info, Elf_Internal_Sym *sym, const char **namep ATTRIBUTE_UNUSED, flagword *flagsp ATTRIBUTE_UNUSED, - asection **secp, bfd_vma *valp) + asection **secp, + bfd_vma *valp) { asection *lcomm; @@ -3725,6 +3734,10 @@ elf64_x86_64_add_symbol_hook (bfd *abfd, *valp = sym->st_size; break; } + + if (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC) + elf_tdata (info->output_bfd)->has_ifunc_symbols = TRUE; + return TRUE; } @@ -3952,6 +3965,9 @@ static const struct bfd_elf_special_section #define elf_backend_hash_symbol \ elf64_x86_64_hash_symbol +#undef elf_backend_post_process_headers +#define elf_backend_post_process_headers _bfd_elf_set_osabi + #include "elf64-target.h" /* FreeBSD support. */ @@ -3964,9 +3980,6 @@ static const struct bfd_elf_special_section #undef ELF_OSABI #define ELF_OSABI ELFOSABI_FREEBSD -#undef elf_backend_post_process_headers -#define elf_backend_post_process_headers _bfd_elf_set_osabi - #undef elf64_bed #define elf64_bed elf64_x86_64_fbsd_bed