X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=bfd%2Felf32-i386.c;h=51c3e863044b7b5e525c735b305414ccb4fd6ca4;hb=efba5c2319d6c25393e5cce9a2d30bbc0cb53123;hp=3dd709a10e446c06fa131cf15fbf97b4d0207306;hpb=011b32fd4270fb7111ee1f63695ccd44562ee7df;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c index 3dd709a10e..51c3e86304 100644 --- a/bfd/elf32-i386.c +++ b/bfd/elf32-i386.c @@ -1,5 +1,5 @@ /* Intel 80386/80486-specific support for 32-bit ELF - Copyright (C) 1993-2018 Free Software Foundation, Inc. + Copyright (C) 1993-2020 Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. @@ -370,7 +370,7 @@ elf_i386_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, } static reloc_howto_type * -elf_i386_rtype_to_howto (bfd *abfd ATTRIBUTE_UNUSED, unsigned r_type) +elf_i386_rtype_to_howto (unsigned r_type) { unsigned int indx; @@ -395,7 +395,7 @@ elf_i386_info_to_howto_rel (bfd *abfd, { unsigned int r_type = ELF32_R_TYPE (dst->r_info); - if ((cache_ptr->howto = elf_i386_rtype_to_howto (abfd, r_type)) == NULL) + if ((cache_ptr->howto = elf_i386_rtype_to_howto (r_type)) == NULL) { /* xgettext:c-format */ _bfd_error_handler (_("%pB: unsupported relocation type %#x"), @@ -766,6 +766,12 @@ static const struct elf_x86_lazy_plt_layout elf_i386_lazy_plt = sizeof (elf_i386_lazy_plt0_entry), /* plt0_entry_size */ elf_i386_lazy_plt_entry, /* plt_entry */ LAZY_PLT_ENTRY_SIZE, /* plt_entry_size */ + NULL, /* plt_tlsdesc_entry */ + 0, /* plt_tlsdesc_entry_size*/ + 0, /* plt_tlsdesc_got1_offset */ + 0, /* plt_tlsdesc_got2_offset */ + 0, /* plt_tlsdesc_got1_insn_end */ + 0, /* plt_tlsdesc_got2_insn_end */ 2, /* plt0_got1_offset */ 8, /* plt0_got2_offset */ 0, /* plt0_got2_insn_end */ @@ -798,6 +804,12 @@ static const struct elf_x86_lazy_plt_layout elf_i386_lazy_ibt_plt = sizeof (elf_i386_lazy_ibt_plt0_entry), /* plt0_entry_size */ elf_i386_lazy_ibt_plt_entry, /* plt_entry */ LAZY_PLT_ENTRY_SIZE, /* plt_entry_size */ + NULL, /* plt_tlsdesc_entry */ + 0, /* plt_tlsdesc_entry_size*/ + 0, /* plt_tlsdesc_got1_offset */ + 0, /* plt_tlsdesc_got2_offset */ + 0, /* plt_tlsdesc_got1_insn_end */ + 0, /* plt_tlsdesc_got2_insn_end */ 2, /* plt0_got1_offset */ 8, /* plt0_got2_offset */ 0, /* plt0_got2_insn_end */ @@ -1139,8 +1151,8 @@ elf_i386_tls_transition (struct bfd_link_info *info, bfd *abfd, reloc_howto_type *from, *to; const char *name; - from = elf_i386_rtype_to_howto (abfd, from_type); - to = elf_i386_rtype_to_howto (abfd, to_type); + from = elf_i386_rtype_to_howto (from_type); + to = elf_i386_rtype_to_howto (to_type); if (h) name = h->root.root.string; @@ -1214,6 +1226,7 @@ elf_i386_convert_load_reloc (bfd *abfd, Elf_Internal_Shdr *symtab_hdr, bfd_vma nop_offset; bfd_boolean is_pic; bfd_boolean to_reloc_32; + bfd_boolean abs_symbol; unsigned int r_type; unsigned int r_symndx; bfd_vma roff = irel->r_offset; @@ -1237,6 +1250,21 @@ elf_i386_convert_load_reloc (bfd *abfd, Elf_Internal_Shdr *symtab_hdr, modrm = bfd_get_8 (abfd, contents + roff - 1); baseless = (modrm & 0xc7) == 0x5; + if (h) + { + /* NB: Also set linker_def via SYMBOL_REFERENCES_LOCAL_P. */ + local_ref = SYMBOL_REFERENCES_LOCAL_P (link_info, h); + isym = NULL; + abs_symbol = ABS_SYMBOL_P (h); + } + else + { + local_ref = TRUE; + isym = bfd_sym_from_r_symndx (&htab->sym_cache, abfd, + r_symndx); + abs_symbol = isym->st_shndx == SHN_ABS; + } + if (baseless && is_pic) { /* For PIC, disallow R_386_GOT32X without a base register @@ -1244,11 +1272,7 @@ elf_i386_convert_load_reloc (bfd *abfd, Elf_Internal_Shdr *symtab_hdr, const char *name; if (h == NULL) - { - isym = bfd_sym_from_r_symndx (&htab->sym_cache, abfd, - r_symndx); - name = bfd_elf_sym_name (abfd, symtab_hdr, isym, NULL); - } + name = bfd_elf_sym_name (abfd, symtab_hdr, isym, NULL); else name = h->root.root.string; @@ -1282,9 +1306,6 @@ elf_i386_convert_load_reloc (bfd *abfd, Elf_Internal_Shdr *symtab_hdr, goto convert_load; } - /* NB: Also set linker_def via SYMBOL_REFERENCES_LOCAL_P. */ - local_ref = SYMBOL_REFERENCES_LOCAL_P (link_info, h); - /* Undefined weak symbol is only bound locally in executable and its reference is resolved as 0. */ if (h->root.type == bfd_link_hash_undefweak @@ -1315,7 +1336,7 @@ elf_i386_convert_load_reloc (bfd *abfd, Elf_Internal_Shdr *symtab_hdr, && local_ref) { /* The function is locally defined. */ -convert_branch: + convert_branch: /* Convert R_386_GOT32X to R_386_PC32. */ if (modrm == 0x15 || (modrm & 0xf8) == 0x90) { @@ -1331,8 +1352,8 @@ convert_branch: } else { - nop = link_info->call_nop_byte; - if (link_info->call_nop_as_suffix) + nop = htab->params->call_nop_byte; + if (htab->params->call_nop_as_suffix) { nop_offset = roff + 3; irel->r_offset -= 1; @@ -1381,9 +1402,12 @@ convert_branch: || h->root.type == bfd_link_hash_defweak) && local_ref)) { -convert_load: + convert_load: if (opcode == 0x8b) { + if (abs_symbol && local_ref) + to_reloc_32 = TRUE; + if (to_reloc_32) { /* Convert "mov foo@GOT[(%reg1)], %reg2" to @@ -1507,6 +1531,7 @@ elf_i386_check_relocs (bfd *abfd, Elf_Internal_Sym *isym; const char *name; bfd_boolean size_reloc; + bfd_boolean no_dynreloc; r_symndx = ELF32_R_SYM (rel->r_info); r_type = ELF32_R_TYPE (rel->r_info); @@ -1563,10 +1588,6 @@ elf_i386_check_relocs (bfd *abfd, /* It is referenced by a non-shared object. */ h->ref_regular = 1; - - if (h->type == STT_GNU_IFUNC) - elf_tdata (info->output_bfd)->has_gnu_symbols - |= elf_gnu_symbol_ifunc; } if (r_type == R_386_GOT32X @@ -1579,6 +1600,10 @@ elf_i386_check_relocs (bfd *abfd, goto error_return; } + if (!_bfd_elf_x86_valid_reloc_p (sec, info, htab, rel, h, isym, + symtab_hdr, &no_dynreloc)) + return FALSE; + if (! elf_i386_tls_transition (info, abfd, sec, contents, symtab_hdr, sym_hashes, &r_type, GOT_UNKNOWN, @@ -1731,7 +1756,7 @@ elf_i386_check_relocs (bfd *abfd, case R_386_GOTOFF: case R_386_GOTPC: -create_got: + create_got: if (r_type != R_386_TLS_IE) { if (eh != NULL) @@ -1761,7 +1786,7 @@ create_got: case R_386_PC32: if (eh != NULL && (sec->flags & SEC_CODE) != 0) eh->zero_undefweak |= 0x2; -do_relocation: + do_relocation: /* We are called after all symbols have been resolved. Only relocation against STT_GNU_IFUNC symbol must go through PLT. */ @@ -1818,9 +1843,10 @@ do_relocation: } size_reloc = FALSE; -do_size: - if (NEED_DYNAMIC_RELOCATION_P (info, FALSE, h, sec, r_type, - R_386_32)) + do_size: + if (!no_dynreloc + && NEED_DYNAMIC_RELOCATION_P (info, FALSE, h, sec, r_type, + R_386_32)) { struct elf_dyn_relocs *p; struct elf_dyn_relocs **head; @@ -1867,7 +1893,7 @@ do_size: p = *head; if (p == NULL || p->sec != sec) { - bfd_size_type amt = sizeof *p; + size_t amt = sizeof *p; p = (struct elf_dyn_relocs *) bfd_alloc (htab->elf.dynobj, amt); if (p == NULL) @@ -1896,9 +1922,7 @@ do_size: /* This relocation describes which C++ vtable entries are actually used. Record for later use during GC. */ case R_386_GNU_VTENTRY: - BFD_ASSERT (h != NULL); - if (h != NULL - && !bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_offset)) + if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_offset)) goto error_return; break; @@ -1925,7 +1949,7 @@ do_size: return TRUE; -error_return: + error_return: if (elf_section_data (sec)->this_hdr.contents != contents) free (contents); sec->check_relocs_failed = 1; @@ -1942,7 +1966,7 @@ elf_i386_fake_sections (bfd *abfd ATTRIBUTE_UNUSED, { const char *name; - name = bfd_get_section_name (abfd, sec); + name = bfd_section_name (sec); /* This is an ugly, but unfortunately necessary hack that is needed when producing EFI binaries on x86. It tells @@ -2016,7 +2040,11 @@ elf_i386_relocate_section (bfd *output_bfd, if (htab == NULL) return FALSE; - BFD_ASSERT (is_x86_elf (input_bfd, htab)); + if (!is_x86_elf (input_bfd, htab)) + { + bfd_set_error (bfd_error_wrong_format); + return FALSE; + } symtab_hdr = &elf_symtab_hdr (input_bfd); sym_hashes = elf_sym_hashes (input_bfd); @@ -2064,15 +2092,10 @@ elf_i386_relocate_section (bfd *output_bfd, continue; } - if ((indx = r_type) >= R_386_standard - && ((indx = r_type - R_386_ext_offset) - R_386_standard - >= R_386_ext - R_386_standard) - && ((indx = r_type - R_386_tls_offset) - R_386_ext - >= R_386_ext2 - R_386_ext)) + howto = elf_i386_rtype_to_howto (r_type); + if (howto == NULL) return _bfd_unrecognized_reloc (input_bfd, input_section, r_type); - howto = elf_howto_table + indx; - r_symndx = ELF32_R_SYM (rel->r_info); h = NULL; sym = NULL; @@ -2185,7 +2208,7 @@ elf_i386_relocate_section (bfd *output_bfd, if (sec != NULL && discarded_section (sec)) { _bfd_clear_contents (howto, input_bfd, input_section, - contents + rel->r_offset); + contents, rel->r_offset); wrel->r_offset = rel->r_offset; wrel->r_info = 0; wrel->r_addend = 0; @@ -2357,7 +2380,7 @@ elf_i386_relocate_section (bfd *output_bfd, switch (r_type) { default: -bad_ifunc_reloc: + bad_ifunc_reloc: if (h->root.root.string) name = h->root.root.string; else @@ -2381,7 +2404,7 @@ bad_ifunc_reloc: asection *sreloc; bfd_vma offset; -do_ifunc_pointer: + do_ifunc_pointer: /* Need a dynamic relocation to get the real function adddress. */ offset = _bfd_elf_section_offset (output_bfd, @@ -2444,7 +2467,7 @@ do_ifunc_pointer: } } -skip_ifunc: + skip_ifunc: resolved_to_zero = (eh != NULL && UNDEFINED_WEAK_RESOLVED_TO_ZERO (info, eh)); @@ -2546,7 +2569,7 @@ skip_ifunc: we don't know what the GOT base is. */ const char *name; -disallow_got32: + disallow_got32: if (h == NULL || h->root.root.string == NULL) name = bfd_elf_sym_name (input_bfd, symtab_hdr, sym, NULL); @@ -2699,7 +2722,7 @@ disallow_got32: || is_vxworks_tls) break; - if (GENERATE_DYNAMIC_RELOCATION_P (info, eh, r_type, + if (GENERATE_DYNAMIC_RELOCATION_P (info, eh, r_type, sec, FALSE, resolved_to_zero, (r_type == R_386_PC32))) { @@ -3404,12 +3427,12 @@ disallow_got32: return FALSE; } -do_relocation: + do_relocation: r = _bfd_final_link_relocate (howto, input_bfd, input_section, contents, rel->r_offset, relocation, 0); -check_relocation_error: + check_relocation_error: if (r != bfd_reloc_ok) { const char *name; @@ -3424,7 +3447,7 @@ check_relocation_error: if (name == NULL) return FALSE; if (*name == '\0') - name = bfd_section_name (input_bfd, sec); + name = bfd_section_name (sec); } if (r == bfd_reloc_overflow) @@ -3843,7 +3866,7 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd, else { BFD_ASSERT((h->got.offset & 1) == 0); -do_glob_dat: + do_glob_dat: bfd_put_32 (output_bfd, (bfd_vma) 0, htab->elf.sgot->contents + h->got.offset); rel.r_info = ELF32_R_INFO (h->dynindx, R_386_GLOB_DAT); @@ -4395,10 +4418,11 @@ elf_i386_link_setup_gnu_properties (struct bfd_link_info *info) "FreeBSD" label in the ELF header. So we put this label on all executables and (for simplicity) also all other object files. */ -static void -elf_i386_fbsd_post_process_headers (bfd *abfd, struct bfd_link_info *info) +static bfd_boolean +elf_i386_fbsd_init_file_header (bfd *abfd, struct bfd_link_info *info) { - _bfd_elf_post_process_headers (abfd, info); + if (!_bfd_elf_init_file_header (abfd, info)) + return FALSE; #ifdef OLD_FREEBSD_ABI_LABEL { @@ -4407,10 +4431,11 @@ elf_i386_fbsd_post_process_headers (bfd *abfd, struct bfd_link_info *info) memcpy (&i_ehdrp->e_ident[EI_ABIVERSION], "FreeBSD", 8); } #endif + return TRUE; } -#undef elf_backend_post_process_headers -#define elf_backend_post_process_headers elf_i386_fbsd_post_process_headers +#undef elf_backend_init_file_header +#define elf_backend_init_file_header elf_i386_fbsd_init_file_header #undef elf32_bed #define elf32_bed elf32_i386_fbsd_bed @@ -4418,6 +4443,8 @@ elf_i386_fbsd_post_process_headers (bfd *abfd, struct bfd_link_info *info) #include "elf32-target.h" +#undef elf_backend_init_file_header + /* Solaris 2. */ #undef TARGET_LITTLE_SYM @@ -4433,8 +4460,6 @@ static const struct elf_x86_backend_data elf_i386_solaris_arch_bed = #undef elf_backend_arch_data #define elf_backend_arch_data &elf_i386_solaris_arch_bed -#undef elf_backend_post_process_headers - /* Restore default: we cannot use ELFOSABI_SOLARIS, otherwise ELFOSABI_NONE objects won't be recognized. */ #undef ELF_OSABI @@ -4602,7 +4627,6 @@ elf32_iamcu_elf_object_p (bfd *abfd) #undef ELF_OSABI #undef elf_backend_want_plt_sym #define elf_backend_want_plt_sym 0 -#undef elf_backend_post_process_headers #undef elf_backend_static_tls_alignment /* NaCl uses substantially different PLT entries for the same effects. */ @@ -4728,6 +4752,12 @@ static const struct elf_x86_lazy_plt_layout elf_i386_nacl_plt = sizeof (elf_i386_nacl_plt0_entry), /* plt0_entry_size */ elf_i386_nacl_plt_entry, /* plt_entry */ NACL_PLT_ENTRY_SIZE, /* plt_entry_size */ + NULL, /* plt_tlsdesc_entry */ + 0, /* plt_tlsdesc_entry_size*/ + 0, /* plt_tlsdesc_got1_offset */ + 0, /* plt_tlsdesc_got2_offset */ + 0, /* plt_tlsdesc_got1_insn_end */ + 0, /* plt_tlsdesc_got2_insn_end */ 2, /* plt0_got1_offset */ 8, /* plt0_got2_offset */ 0, /* plt0_got2_insn_end */ @@ -4763,8 +4793,8 @@ elf32_i386_nacl_elf_object_p (bfd *abfd) #define elf_backend_object_p elf32_i386_nacl_elf_object_p #undef elf_backend_modify_segment_map #define elf_backend_modify_segment_map nacl_modify_segment_map -#undef elf_backend_modify_program_headers -#define elf_backend_modify_program_headers nacl_modify_program_headers +#undef elf_backend_modify_headers +#define elf_backend_modify_headers nacl_modify_headers #undef elf_backend_final_write_processing #define elf_backend_final_write_processing nacl_final_write_processing @@ -4773,7 +4803,7 @@ elf32_i386_nacl_elf_object_p (bfd *abfd) /* Restore defaults. */ #undef elf_backend_object_p #undef elf_backend_modify_segment_map -#undef elf_backend_modify_program_headers +#undef elf_backend_modify_headers #undef elf_backend_final_write_processing /* VxWorks support. */