X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=bfd%2Felf64-x86-64.c;h=79e68ff47674220a1d8e9a6840b5a671e1f0cb40;hb=456e800a63def18484f69a51f59c2338a5cc4568;hp=6a4b366fddacae313e73e77e5eed0596d51d2a98;hpb=83924b3846361f2f76f9a6e7b5afa01c0eebbd4f;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c index 6a4b366fdd..79e68ff476 100644 --- a/bfd/elf64-x86-64.c +++ b/bfd/elf64-x86-64.c @@ -1,5 +1,5 @@ /* X86-64 specific support for ELF - Copyright (C) 2000-2019 Free Software Foundation, Inc. + Copyright (C) 2000-2020 Free Software Foundation, Inc. Contributed by Jan Hubicka . This file is part of BFD, the Binary File Descriptor library. @@ -1422,7 +1422,7 @@ elf_x86_64_need_pic (struct bfd_link_info *info, v = _("protected symbol "); else v = _("symbol "); - pic = _("; recompile with -fPIC"); + pic = NULL; break; } @@ -1432,15 +1432,24 @@ elf_x86_64_need_pic (struct bfd_link_info *info, else { name = bfd_elf_sym_name (input_bfd, symtab_hdr, isym, NULL); - pic = _("; recompile with -fPIC"); + pic = NULL; } if (bfd_link_dll (info)) - object = _("a shared object"); - else if (bfd_link_pie (info)) - object = _("a PIE object"); + { + object = _("a shared object"); + if (!pic) + pic = _("; recompile with -fPIC"); + } else - object = _("a PDE object"); + { + if (bfd_link_pie (info)) + object = _("a PIE object"); + else + object = _("a PDE object"); + if (!pic) + pic = _("; recompile with -fPIE"); + } /* xgettext:c-format */ _bfd_error_handler (_("%pB: relocation %s against %s%s`%s' can " @@ -1676,8 +1685,8 @@ convert: } 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 = irel->r_offset + 3; disp = bfd_get_32 (abfd, contents + irel->r_offset); @@ -1855,7 +1864,6 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, const char *name; bfd_boolean size_reloc; bfd_boolean converted_reloc; - bfd_boolean do_check_pic; r_symndx = htab->r_sym (rel->r_info); r_type = ELF32_R_TYPE (rel->r_info); @@ -1942,10 +1950,6 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, { /* 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; } converted_reloc = FALSE; @@ -2131,13 +2135,6 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, size_reloc = TRUE; goto do_size; - case R_X86_64_PC8: - case R_X86_64_PC16: - case R_X86_64_PC32: - case R_X86_64_PC32_BND: - do_check_pic = TRUE; - goto check_pic; - case R_X86_64_32: if (!ABI_64_P (abfd)) goto pointer; @@ -2149,7 +2146,7 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, run-time relocation overflow. Don't error out for sections we don't care about, such as debug sections or when relocation overflow check is disabled. */ - if (!info->no_reloc_overflow_check + if (!htab->params->no_reloc_overflow_check && !converted_reloc && (bfd_link_pic (info) || (bfd_link_executable (info) @@ -2161,11 +2158,13 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, &x86_64_elf_howto_table[r_type]); /* Fall through. */ + case R_X86_64_PC8: + case R_X86_64_PC16: + case R_X86_64_PC32: + case R_X86_64_PC32_BND: case R_X86_64_PC64: case R_X86_64_64: pointer: - do_check_pic = FALSE; -check_pic: if (eh != NULL && (sec->flags & SEC_CODE) != 0) eh->zero_undefweak |= 0x2; /* We are called after all symbols have been resolved. Only @@ -2229,67 +2228,6 @@ check_pic: } } - if (do_check_pic) - { - /* Don't complain about -fPIC if the symbol is undefined - when building executable unless it is unresolved weak - symbol, references a dynamic definition in PIE or - -z nocopyreloc is used. */ - bfd_boolean no_copyreloc_p - = (info->nocopyreloc - || (h != NULL - && eh->def_protected - && elf_has_no_copy_on_protected (h->root.u.def.section->owner))); - if ((sec->flags & SEC_ALLOC) != 0 - && (sec->flags & SEC_READONLY) != 0 - && h != NULL - && ((bfd_link_executable (info) - && ((h->root.type == bfd_link_hash_undefweak - && (eh == NULL - || !UNDEFINED_WEAK_RESOLVED_TO_ZERO (info, - eh))) - || (bfd_link_pie (info) - && !SYMBOL_DEFINED_NON_SHARED_P (h) - && h->def_dynamic) - || (no_copyreloc_p - && h->def_dynamic - && !(h->root.u.def.section->flags & SEC_CODE)))) - || bfd_link_dll (info))) - { - bfd_boolean fail = FALSE; - if (SYMBOL_REFERENCES_LOCAL_P (info, h)) - { - /* Symbol is referenced locally. Make sure it is - defined locally. */ - fail = !SYMBOL_DEFINED_NON_SHARED_P (h); - } - else if (bfd_link_pie (info)) - { - /* We can only use PC-relative relocations in PIE - from non-code sections. */ - if (h->type == STT_FUNC - && (sec->flags & SEC_CODE) != 0) - fail = TRUE; - } - else if (no_copyreloc_p || bfd_link_dll (info)) - { - /* Symbol doesn't need copy reloc and isn't - referenced locally. Don't allow PC-relative - relocations against default and protected - symbols since address of protected function - and location of protected data may not be in - the shared object. */ - fail = (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT - || ELF_ST_VISIBILITY (h->other) == STV_PROTECTED); - } - - if (fail) - return elf_x86_64_need_pic (info, abfd, sec, h, - symtab_hdr, isym, - &x86_64_elf_howto_table[r_type]); - } - } - size_reloc = FALSE; do_size: if (NEED_DYNAMIC_RELOCATION_P (info, TRUE, h, sec, r_type, @@ -2371,9 +2309,7 @@ do_size: /* This relocation describes which C++ vtable entries are actually used. Record for later use during GC. */ case R_X86_64_GNU_VTENTRY: - BFD_ASSERT (h != NULL); - if (h != NULL - && !bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend)) + if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend)) goto error_return; break; @@ -2492,6 +2428,7 @@ elf_x86_64_relocate_section (bfd *output_bfd, bfd_boolean relative_reloc; bfd_boolean converted_reloc; bfd_boolean need_copy_reloc_in_pie; + bfd_boolean no_copyreloc_p; r_type = ELF32_R_TYPE (rel->r_info); if (r_type == (int) R_X86_64_GNU_VTINHERIT @@ -3011,14 +2948,14 @@ skip_ifunc: && ELF_ST_VISIBILITY (h->other) == STV_PROTECTED) { _bfd_error_handler - /* xgettext:c-format */ + /* xgettext:c-format */ (_("%pB: relocation R_X86_64_GOTOFF64 against protected %s" " `%s' can not be used when making a shared object"), input_bfd, h->type == STT_FUNC ? "function" : "data", h->root.root.string); bfd_set_error (bfd_error_bad_value); - return FALSE; + return FALSE; } } @@ -3132,14 +3069,73 @@ use_plt: case R_X86_64_PC16: case R_X86_64_PC32: case R_X86_64_PC32_BND: + /* Don't complain about -fPIC if the symbol is undefined when + building executable unless it is unresolved weak symbol, + references a dynamic definition in PIE or -z nocopyreloc + is used. */ + no_copyreloc_p + = (info->nocopyreloc + || (h != NULL + && !h->root.linker_def + && !h->root.ldscript_def + && eh->def_protected + && elf_has_no_copy_on_protected (h->root.u.def.section->owner))); + + if ((input_section->flags & SEC_ALLOC) != 0 + && (input_section->flags & SEC_READONLY) != 0 + && h != NULL + && ((bfd_link_executable (info) + && ((h->root.type == bfd_link_hash_undefweak + && (eh == NULL + || !UNDEFINED_WEAK_RESOLVED_TO_ZERO (info, + eh))) + || (bfd_link_pie (info) + && !SYMBOL_DEFINED_NON_SHARED_P (h) + && h->def_dynamic) + || (no_copyreloc_p + && h->def_dynamic + && !(h->root.u.def.section->flags & SEC_CODE)))) + || bfd_link_dll (info))) + { + bfd_boolean fail = FALSE; + if (SYMBOL_REFERENCES_LOCAL_P (info, h)) + { + /* Symbol is referenced locally. Make sure it is + defined locally. */ + fail = !SYMBOL_DEFINED_NON_SHARED_P (h); + } + else if (bfd_link_pie (info)) + { + /* We can only use PC-relative relocations in PIE + from non-code sections. */ + if (h->type == STT_FUNC + && (sec->flags & SEC_CODE) != 0) + fail = TRUE; + } + else if (no_copyreloc_p || bfd_link_dll (info)) + { + /* Symbol doesn't need copy reloc and isn't + referenced locally. Don't allow PC-relative + relocations against default and protected + symbols since address of protected function + and location of protected data may not be in + the shared object. */ + fail = (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT + || ELF_ST_VISIBILITY (h->other) == STV_PROTECTED); + } + + if (fail) + return elf_x86_64_need_pic (info, input_bfd, input_section, + h, NULL, NULL, howto); + } /* Since x86-64 has PC-relative PLT, we can use PLT in PIE as function address. */ - if (h != NULL - && (input_section->flags & SEC_CODE) == 0 - && bfd_link_pie (info) - && h->type == STT_FUNC - && !h->def_regular - && h->def_dynamic) + else if (h != NULL + && (input_section->flags & SEC_CODE) == 0 + && bfd_link_pie (info) + && h->type == STT_FUNC + && !h->def_regular + && h->def_dynamic) goto use_plt; /* Fall through. */ @@ -3204,7 +3200,7 @@ direct: convert R_X86_64_32 to dynamic R_X86_64_RELATIVE. */ if (r_type == htab->pointer_r_type || (r_type == R_X86_64_32 - && info->no_reloc_overflow_check)) + && htab->params->no_reloc_overflow_check)) { relocate = TRUE; outrel.r_info = htab->r_info (0, R_X86_64_RELATIVE); @@ -3359,20 +3355,39 @@ direct: { if (contents[roff + 5] == 0xb8) { + if (roff < 3 + || (roff - 3 + 22) > input_section->size) + { +corrupt_input: + info->callbacks->einfo + (_("%F%P: corrupt input: %pB\n"), + input_bfd); + return FALSE; + } memcpy (contents + roff - 3, "\x64\x48\x8b\x04\x25\0\0\0\0\x48\x8d\x80" "\0\0\0\0\x66\x0f\x1f\x44\0", 22); largepic = 1; } else - memcpy (contents + roff - 4, - "\x64\x48\x8b\x04\x25\0\0\0\0\x48\x8d\x80\0\0\0", - 16); + { + if (roff < 4 + || (roff - 4 + 16) > input_section->size) + goto corrupt_input; + memcpy (contents + roff - 4, + "\x64\x48\x8b\x04\x25\0\0\0\0\x48\x8d\x80\0\0\0", + 16); + } } else - memcpy (contents + roff - 3, - "\x64\x8b\x04\x25\0\0\0\0\x48\x8d\x80\0\0\0", - 15); + { + if (roff < 3 + || (roff - 3 + 15) > input_section->size) + goto corrupt_input; + memcpy (contents + roff - 3, + "\x64\x8b\x04\x25\0\0\0\0\x48\x8d\x80\0\0\0", + 15); + } bfd_put_32 (output_bfd, elf_x86_64_tpoff (info, relocation), contents + roff + 8 + largepic); @@ -3393,6 +3408,8 @@ direct: unsigned int val, type; + if (roff < 3) + goto corrupt_input; type = bfd_get_8 (input_bfd, contents + roff - 3); val = bfd_get_8 (input_bfd, contents + roff - 1); bfd_put_8 (output_bfd, 0x48 | ((type >> 2) & 1), @@ -3439,7 +3456,11 @@ direct: if (roff >= 3) val = bfd_get_8 (input_bfd, contents + roff - 3); else - val = 0; + { + if (roff < 2) + goto corrupt_input; + val = 0; + } type = bfd_get_8 (input_bfd, contents + roff - 2); reg = bfd_get_8 (input_bfd, contents + roff - 1); reg >>= 3; @@ -3447,11 +3468,19 @@ direct: { /* movq */ if (val == 0x4c) - bfd_put_8 (output_bfd, 0x49, - contents + roff - 3); + { + if (roff < 3) + goto corrupt_input; + bfd_put_8 (output_bfd, 0x49, + contents + roff - 3); + } else if (!ABI_64_P (output_bfd) && val == 0x44) - bfd_put_8 (output_bfd, 0x41, - contents + roff - 3); + { + if (roff < 3) + goto corrupt_input; + bfd_put_8 (output_bfd, 0x41, + contents + roff - 3); + } bfd_put_8 (output_bfd, 0xc7, contents + roff - 2); bfd_put_8 (output_bfd, 0xc0 | reg, @@ -3462,11 +3491,19 @@ direct: /* addq/addl -> addq/addl - addressing with %rsp/%r12 is special */ if (val == 0x4c) - bfd_put_8 (output_bfd, 0x49, - contents + roff - 3); + { + if (roff < 3) + goto corrupt_input; + bfd_put_8 (output_bfd, 0x49, + contents + roff - 3); + } else if (!ABI_64_P (output_bfd) && val == 0x44) - bfd_put_8 (output_bfd, 0x41, - contents + roff - 3); + { + if (roff < 3) + goto corrupt_input; + bfd_put_8 (output_bfd, 0x41, + contents + roff - 3); + } bfd_put_8 (output_bfd, 0x81, contents + roff - 2); bfd_put_8 (output_bfd, 0xc0 | reg, @@ -3476,11 +3513,19 @@ direct: { /* addq/addl -> leaq/leal */ if (val == 0x4c) - bfd_put_8 (output_bfd, 0x4d, - contents + roff - 3); + { + if (roff < 3) + goto corrupt_input; + bfd_put_8 (output_bfd, 0x4d, + contents + roff - 3); + } else if (!ABI_64_P (output_bfd) && val == 0x44) - bfd_put_8 (output_bfd, 0x45, - contents + roff - 3); + { + if (roff < 3) + goto corrupt_input; + bfd_put_8 (output_bfd, 0x45, + contents + roff - 3); + } bfd_put_8 (output_bfd, 0x8d, contents + roff - 2); bfd_put_8 (output_bfd, 0x80 | reg | (reg << 3), @@ -3650,20 +3695,33 @@ direct: { if (contents[roff + 5] == 0xb8) { + if (roff < 3 + || (roff - 3 + 22) > input_section->size) + goto corrupt_input; memcpy (contents + roff - 3, "\x64\x48\x8b\x04\x25\0\0\0\0\x48\x03\x05" "\0\0\0\0\x66\x0f\x1f\x44\0", 22); largepic = 1; } else - memcpy (contents + roff - 4, - "\x64\x48\x8b\x04\x25\0\0\0\0\x48\x03\x05\0\0\0", - 16); + { + if (roff < 4 + || (roff - 4 + 16) > input_section->size) + goto corrupt_input; + memcpy (contents + roff - 4, + "\x64\x48\x8b\x04\x25\0\0\0\0\x48\x03\x05\0\0\0", + 16); + } } else - memcpy (contents + roff - 3, - "\x64\x8b\x04\x25\0\0\0\0\x48\x03\x05\0\0\0", - 15); + { + if (roff < 3 + || (roff - 3 + 15) > input_section->size) + goto corrupt_input; + memcpy (contents + roff - 3, + "\x64\x8b\x04\x25\0\0\0\0\x48\x03\x05\0\0\0", + 15); + } relocation = (htab->elf.sgot->output_section->vma + htab->elf.sgot->output_offset + off @@ -3692,6 +3750,8 @@ direct: turn a leaq into a movq in the form we use it, it suffices to change the second byte from 0x8d to 0x8b. */ + if (roff < 2) + goto corrupt_input; bfd_put_8 (output_bfd, 0x8b, contents + roff - 2); bfd_put_32 (output_bfd, @@ -3760,28 +3820,58 @@ direct: BFD_ASSERT (r_type == R_X86_64_TPOFF32); if (ABI_64_P (output_bfd)) { + if ((rel->r_offset + 5) >= input_section->size) + goto corrupt_input; if (contents[rel->r_offset + 5] == 0xb8) - memcpy (contents + rel->r_offset - 3, - "\x66\x66\x66\x66\x2e\x0f\x1f\x84\0\0\0\0\0" - "\x64\x48\x8b\x04\x25\0\0\0", 22); + { + if (rel->r_offset < 3 + || (rel->r_offset - 3 + 22) > input_section->size) + goto corrupt_input; + memcpy (contents + rel->r_offset - 3, + "\x66\x66\x66\x66\x2e\x0f\x1f\x84\0\0\0\0\0" + "\x64\x48\x8b\x04\x25\0\0\0", 22); + } else if (contents[rel->r_offset + 4] == 0xff || contents[rel->r_offset + 4] == 0x67) - memcpy (contents + rel->r_offset - 3, - "\x66\x66\x66\x66\x64\x48\x8b\x04\x25\0\0\0", - 13); + { + if (rel->r_offset < 3 + || (rel->r_offset - 3 + 13) > input_section->size) + goto corrupt_input; + memcpy (contents + rel->r_offset - 3, + "\x66\x66\x66\x66\x64\x48\x8b\x04\x25\0\0\0", + 13); + + } else - memcpy (contents + rel->r_offset - 3, - "\x66\x66\x66\x64\x48\x8b\x04\x25\0\0\0", 12); + { + if (rel->r_offset < 3 + || (rel->r_offset - 3 + 12) > input_section->size) + goto corrupt_input; + memcpy (contents + rel->r_offset - 3, + "\x66\x66\x66\x64\x48\x8b\x04\x25\0\0\0", 12); + } } else { + if ((rel->r_offset + 4) >= input_section->size) + goto corrupt_input; if (contents[rel->r_offset + 4] == 0xff) - memcpy (contents + rel->r_offset - 3, - "\x66\x0f\x1f\x40\x00\x64\x8b\x04\x25\0\0\0", - 13); + { + if (rel->r_offset < 3 + || (rel->r_offset - 3 + 13) > input_section->size) + goto corrupt_input; + memcpy (contents + rel->r_offset - 3, + "\x66\x0f\x1f\x40\x00\x64\x8b\x04\x25\0\0\0", + 13); + } else - memcpy (contents + rel->r_offset - 3, - "\x0f\x1f\x40\x00\x64\x8b\x04\x25\0\0\0", 12); + { + if (rel->r_offset < 3 + || (rel->r_offset - 3 + 12) > input_section->size) + goto corrupt_input; + memcpy (contents + rel->r_offset - 3, + "\x0f\x1f\x40\x00\x64\x8b\x04\x25\0\0\0", 12); + } } /* Skip R_X86_64_PC32, R_X86_64_PLT32, R_X86_64_GOTPCRELX and R_X86_64_PLTOFF64. */ @@ -3899,7 +3989,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) @@ -4952,7 +5042,13 @@ elf_x86_64_link_setup_gnu_properties (struct bfd_link_info *info) if (get_elf_x86_backend_data (info->output_bfd)->target_os != is_nacl) { - if (info->bndplt) + const struct elf_backend_data *bed + = get_elf_backend_data (info->output_bfd); + struct elf_x86_link_hash_table *htab + = elf_x86_hash_table (info, bed->target_id); + if (!htab) + abort (); + if (htab->params->bndplt) { init_table.lazy_plt = &elf_x86_64_lazy_bnd_plt; init_table.non_lazy_plt = &elf_x86_64_non_lazy_bnd_plt; @@ -5333,8 +5429,8 @@ static const struct elf_x86_backend_data elf_x86_64_nacl_arch_bed = #define elf_backend_object_p elf64_x86_64_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 @@ -5387,7 +5483,7 @@ elf32_x86_64_nacl_elf_object_p (bfd *abfd) #undef elf_backend_bfd_from_remote_memory #undef elf_backend_size_info #undef elf_backend_modify_segment_map -#undef elf_backend_modify_program_headers +#undef elf_backend_modify_headers #undef elf_backend_final_write_processing /* Intel L1OM support. */