diff options
Diffstat (limited to 'bfd/elf64-x86-64.c')
-rw-r--r-- | bfd/elf64-x86-64.c | 150 |
1 files changed, 93 insertions, 57 deletions
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c index 1e08f2e..4f0e97c 100644 --- a/bfd/elf64-x86-64.c +++ b/bfd/elf64-x86-64.c @@ -868,13 +868,6 @@ static const bfd_byte elf_x86_64_eh_frame_non_lazy_plt[] = DW_CFA_nop, DW_CFA_nop, DW_CFA_nop }; -static const sframe_frame_row_entry elf_x86_64_sframe_null_fre = -{ - 0, - {16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* 12 bytes. */ - SFRAME_V1_FRE_INFO (SFRAME_BASE_REG_SP, 1, SFRAME_FRE_OFFSET_1B) /* FRE info. */ -}; - /* .sframe FRE covering the .plt section entry. */ static const sframe_frame_row_entry elf_x86_64_sframe_plt0_fre1 = { @@ -923,6 +916,14 @@ static const sframe_frame_row_entry elf_x86_64_sframe_sec_pltn_fre1 = SFRAME_V1_FRE_INFO (SFRAME_BASE_REG_SP, 1, SFRAME_FRE_OFFSET_1B) /* FRE info. */ }; +/* .sframe FRE covering the .plt.got section entry. */ +static const sframe_frame_row_entry elf_x86_64_sframe_pltgot_fre1 = +{ + 0, /* SFrame FRE start address. */ + {16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* 12 bytes. */ + SFRAME_V1_FRE_INFO (SFRAME_BASE_REG_SP, 1, SFRAME_FRE_OFFSET_1B) /* FRE info. */ +}; + /* SFrame helper object for non-lazy PLT. */ static const struct elf_x86_sframe_plt elf_x86_64_sframe_non_lazy_plt = { @@ -933,14 +934,14 @@ static const struct elf_x86_sframe_plt elf_x86_64_sframe_non_lazy_plt = LAZY_PLT_ENTRY_SIZE, 1, /* Number of FREs for PLTn. */ /* Array of SFrame FREs for plt. */ - { &elf_x86_64_sframe_sec_pltn_fre1, &elf_x86_64_sframe_null_fre }, + { &elf_x86_64_sframe_sec_pltn_fre1 }, 0, 0, /* There is no second PLT necessary. */ - { &elf_x86_64_sframe_null_fre }, + { }, NON_LAZY_PLT_ENTRY_SIZE, 1, /* Number of FREs for PLT GOT. */ /* Array of SFrame FREs for PLT GOT. */ - { &elf_x86_64_sframe_null_fre }, + { &elf_x86_64_sframe_pltgot_fre1 }, }; /* SFrame helper object for non-lazy IBT enabled PLT. */ @@ -953,14 +954,14 @@ static const struct elf_x86_sframe_plt elf_x86_64_sframe_non_lazy_ibt_plt = LAZY_PLT_ENTRY_SIZE, 1, /* Number of FREs for PLTn. */ /* Array of SFrame FREs for plt. */ - { &elf_x86_64_sframe_sec_pltn_fre1, &elf_x86_64_sframe_null_fre }, + { &elf_x86_64_sframe_sec_pltn_fre1 }, 0, 0, /* There is no second PLT necessary. */ - { &elf_x86_64_sframe_null_fre }, + { }, LAZY_PLT_ENTRY_SIZE, 1, /* Number of FREs for PLT GOT. */ /* Array of SFrame FREs for PLT GOT. */ - { &elf_x86_64_sframe_null_fre }, + { &elf_x86_64_sframe_pltgot_fre1 }, }; /* SFrame helper object for lazy PLT. */ @@ -981,7 +982,7 @@ static const struct elf_x86_sframe_plt elf_x86_64_sframe_plt = NON_LAZY_PLT_ENTRY_SIZE, 1, /* Number of FREs for PLT GOT. */ /* Array of SFrame FREs for PLT GOT. */ - { &elf_x86_64_sframe_null_fre }, + { &elf_x86_64_sframe_pltgot_fre1 }, }; /* SFrame helper object for lazy PLT with IBT. */ @@ -1002,7 +1003,7 @@ static const struct elf_x86_sframe_plt elf_x86_64_sframe_ibt_plt = LAZY_PLT_ENTRY_SIZE, 1, /* Number of FREs for PLT GOT. */ /* Array of SFrame FREs for PLT GOT. */ - { &elf_x86_64_sframe_null_fre }, + { &elf_x86_64_sframe_pltgot_fre1 }, }; /* These are the standard parameters. */ @@ -2552,7 +2553,13 @@ elf_x86_64_scan_relocs (bfd *abfd, struct bfd_link_info *info, } howto = elf_x86_64_rtype_to_howto (abfd, r_type); - if (rel->r_offset + bfd_get_reloc_size (howto) > sec->size) + if (howto == NULL) + { + _bfd_error_handler (_("%pB: unsupported relocation type %#x"), + abfd, r_type); + goto error_return; + } + if (!bfd_reloc_offset_in_range (howto, abfd, sec, rel->r_offset)) { /* xgettext:c-format */ _bfd_error_handler @@ -2687,6 +2694,10 @@ elf_x86_64_scan_relocs (bfd *abfd, struct bfd_link_info *info, eh->zero_undefweak &= 0x2; break; + case R_X86_64_TLSDESC_CALL: + htab->has_tls_desc_call = 1; + goto need_got; + case R_X86_64_GOTTPOFF: case R_X86_64_CODE_4_GOTTPOFF: case R_X86_64_CODE_5_GOTTPOFF: @@ -2708,7 +2719,7 @@ elf_x86_64_scan_relocs (bfd *abfd, struct bfd_link_info *info, case R_X86_64_GOTPLT64: case R_X86_64_GOTPC32_TLSDESC: case R_X86_64_CODE_4_GOTPC32_TLSDESC: - case R_X86_64_TLSDESC_CALL: +need_got: /* This symbol requires a global offset table entry. */ { int tls_type, old_tls_type; @@ -3261,10 +3272,14 @@ elf_x86_64_relocate_section (bfd *output_bfd, wrel->r_addend = 0; /* For ld -r, remove relocations in debug sections against - sections defined in discarded sections. Not done for - eh_frame editing code expects to be present. */ + sections defined in discarded sections, including sframe + sections. Not done for eh_frame editing code expects to + be present. NB: Since sframe code keeps R_X86_64_NONE + reloc as is, its r_offset is wrong, we must not generate + R_X86_64_NONE reloc in sframe section. */ if (bfd_link_relocatable (info) - && (input_section->flags & SEC_DEBUGGING)) + && ((input_section->flags & SEC_DEBUGGING) != 0 + || elf_section_type (input_section) == SHT_GNU_SFRAME)) wrel--; continue; @@ -4612,7 +4627,7 @@ elf_x86_64_relocate_section (bfd *output_bfd, + htab->elf.sgotplt->output_offset + offplt + htab->sgotplt_jump_table_size); - sreloc = htab->elf.srelplt; + sreloc = htab->rel_tls_desc; if (indx == 0) outrel.r_addend = relocation - _bfd_x86_elf_dtpoff_base (info); else @@ -5088,14 +5103,6 @@ elf_x86_64_relocate_section (bfd *output_bfd, rel_hdr = _bfd_elf_single_rel_hdr (input_section->output_section); rel_hdr->sh_size -= rel_hdr->sh_entsize * deleted; - if (rel_hdr->sh_size == 0) - { - /* It is too late to remove an empty reloc section. Leave - one NONE reloc. - ??? What is wrong with an empty section??? */ - rel_hdr->sh_size = rel_hdr->sh_entsize; - deleted -= 1; - } rel_hdr = _bfd_elf_single_rel_hdr (input_section); rel_hdr->sh_size -= rel_hdr->sh_entsize * deleted; input_section->reloc_count -= deleted; @@ -5241,6 +5248,9 @@ elf_x86_64_finish_dynamic_symbol (bfd *output_bfd, + got_offset); if (PLT_LOCAL_IFUNC_P (info, h)) { + if (h->root.u.def.section == NULL) + return false; + info->callbacks->minfo (_("Local IFUNC function `%s' in %pB\n"), h->root.root.string, h->root.u.def.section->owner); @@ -5409,6 +5419,9 @@ elf_x86_64_finish_dynamic_symbol (bfd *output_bfd, } if (SYMBOL_REFERENCES_LOCAL_P (info, h)) { + if (h->root.u.def.section == NULL) + return false; + info->callbacks->minfo (_("Local IFUNC function `%s' in %pB\n"), h->root.root.string, h->root.u.def.section->owner); @@ -6123,13 +6136,14 @@ elf_x86_64_fake_sections (bfd *abfd ATTRIBUTE_UNUSED, static bool elf_x86_64_copy_private_section_data (bfd *ibfd, asection *isec, - bfd *obfd, asection *osec) + bfd *obfd, asection *osec, + struct bfd_link_info *link_info) { - if (!_bfd_elf_copy_private_section_data (ibfd, isec, obfd, osec)) + if (!_bfd_elf_copy_private_section_data (ibfd, isec, obfd, osec, link_info)) return false; /* objcopy --set-section-flags without "large" drops SHF_X86_64_LARGE. */ - if (ibfd != obfd) + if (link_info == NULL && ibfd != obfd) elf_section_flags (osec) &= ~SHF_X86_64_LARGE; return true; @@ -6232,8 +6246,9 @@ static void elf_x86_64_add_glibc_version_dependency (struct elf_find_verdep_info *rinfo) { - unsigned int i = 0; - const char *version[3] = { NULL, NULL, NULL }; + int i = 0, mark_plt = -1; + const char *version[4] = { NULL, NULL, NULL, NULL }; + bool auto_version[4] = { false, false, false, false }; struct elf_x86_link_hash_table *htab; if (rinfo->info->enable_dt_relr) @@ -6243,14 +6258,41 @@ elf_x86_64_add_glibc_version_dependency } htab = elf_x86_hash_table (rinfo->info, X86_64_ELF_DATA); - if (htab != NULL && htab->params->mark_plt) + if (htab != NULL) { - version[i] = "GLIBC_2.36"; - i++; + if (htab->params->gnu2_tls_version_tag && htab->has_tls_desc_call) + { + version[i] = "GLIBC_ABI_GNU2_TLS"; + /* 2 == auto, enable if libc.so defines the GLIBC_ABI_GNU2_TLS + version. */ + if (htab->params->gnu2_tls_version_tag == 2) + auto_version[i] = true; + i++; + } + if (htab->params->mark_plt) + { + mark_plt = i; + auto_version[i] = true; + version[i] = "GLIBC_ABI_DT_X86_64_PLT"; + i++; + } } - if (i != 0) - _bfd_elf_link_add_glibc_version_dependency (rinfo, version); + if (i == 0 + || !_bfd_elf_link_add_glibc_version_dependency (rinfo, version, + auto_version)) + return; + + if (mark_plt < 0 || auto_version[mark_plt]) + return; + + /* Add the GLIBC_2.36 version dependency if libc.so doesn't have + GLIBC_ABI_DT_X86_64_PLT. */ + version[0] = "GLIBC_2.36"; + auto_version[0] = false; + version[1] = NULL; + _bfd_elf_link_add_glibc_version_dependency (rinfo, version, + auto_version); } static const struct bfd_elf_special_section @@ -6271,7 +6313,7 @@ elf_x86_64_special_sections[]= #define ELF_TARGET_ID X86_64_ELF_DATA #define ELF_MACHINE_CODE EM_X86_64 #define ELF_MAXPAGESIZE 0x1000 -#define ELF_COMMONPAGESIZE 0x1000 +#define ELF_COMMONPAGESIZE ELF_MAXPAGESIZE #define elf_backend_can_gc_sections 1 #define elf_backend_can_refcount 1 @@ -6345,20 +6387,7 @@ elf_x86_64_special_sections[]= #include "elf64-target.h" -/* CloudABI support. */ - -#undef TARGET_LITTLE_SYM -#define TARGET_LITTLE_SYM x86_64_elf64_cloudabi_vec -#undef TARGET_LITTLE_NAME -#define TARGET_LITTLE_NAME "elf64-x86-64-cloudabi" - -#undef ELF_OSABI -#define ELF_OSABI ELFOSABI_CLOUDABI - -#undef elf64_bed -#define elf64_bed elf64_x86_64_cloudabi_bed - -#include "elf64-target.h" +#undef elf_backend_add_glibc_version_dependency /* FreeBSD support. */ @@ -6382,7 +6411,10 @@ elf_x86_64_special_sections[]= #undef TARGET_LITTLE_NAME #define TARGET_LITTLE_NAME "elf64-x86-64-sol2" -#undef ELF_TARGET_OS +#undef ELF_MAXPAGESIZE +#define ELF_MAXPAGESIZE 0x100000 + +#undef ELF_TARGET_OS #define ELF_TARGET_OS is_solaris /* Restore default: we cannot use ELFOSABI_SOLARIS, otherwise ELFOSABI_NONE @@ -6443,8 +6475,8 @@ elf64_x86_64_copy_solaris_special_section_fields (const bfd *ibfd ATTRIBUTE_UNUS #undef ELF_ARCH #define ELF_ARCH bfd_arch_i386 -#undef ELF_MACHINE_CODE -#define ELF_MACHINE_CODE EM_X86_64 +#undef ELF_MAXPAGESIZE +#define ELF_MAXPAGESIZE 0x1000 #undef ELF_TARGET_OS #undef ELF_OSABI @@ -6466,6 +6498,10 @@ elf64_x86_64_copy_solaris_special_section_fields (const bfd *ibfd ATTRIBUTE_UNUS #define elf_backend_bfd_from_remote_memory \ _bfd_elf32_bfd_from_remote_memory +#undef elf_backend_add_glibc_version_dependency +#define elf_backend_add_glibc_version_dependency \ + elf_x86_64_add_glibc_version_dependency + #undef elf_backend_size_info #define elf_backend_size_info \ _bfd_elf32_size_info |