/* X86-64 specific support for ELF
- Copyright (C) 2000-2018 Free Software Foundation, Inc.
+ Copyright (C) 2000-2019 Free Software Foundation, Inc.
Contributed by Jan Hubicka <jh@suse.cz>.
This file is part of BFD, the Binary File Descriptor library.
unsigned r_type;
r_type = ELF32_R_TYPE (dst->r_info);
- if (r_type != (unsigned int) R_X86_64_GNU_VTINHERIT
- && r_type != (unsigned int) R_X86_64_GNU_VTENTRY)
- r_type &= ~R_X86_64_converted_reloc_bit;
cache_ptr->howto = elf_x86_64_rtype_to_howto (abfd, r_type);
if (cache_ptr->howto == NULL)
return FALSE;
}
#ifdef CORE_HEADER
+# if GCC_VERSION >= 8000
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wstringop-truncation"
+# endif
static char *
elf_x86_64_write_core_note (bfd *abfd, char *buf, int *bufsiz,
int note_type, ...)
}
/* NOTREACHED */
}
+# if GCC_VERSION >= 8000
+# pragma GCC diagnostic pop
+# endif
#endif
\f
/* Functions for the x86-64 ELF linker. */
0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00 /* nopw 0x0(%rax,%rax,1) */
};
+/* The TLSDESC entry in a lazy procedure linkage table. */
+static const bfd_byte elf_x86_64_tlsdesc_plt_entry[LAZY_PLT_ENTRY_SIZE] =
+{
+ 0xf3, 0x0f, 0x1e, 0xfa, /* endbr64 */
+ 0xff, 0x35, 8, 0, 0, 0, /* pushq GOT+8(%rip) */
+ 0xff, 0x25, 16, 0, 0, 0 /* jmpq *GOT+TDG(%rip) */
+};
+
/* .eh_frame covering the lazy .plt section. */
static const bfd_byte elf_x86_64_eh_frame_lazy_plt[] =
LAZY_PLT_ENTRY_SIZE, /* plt0_entry_size */
elf_x86_64_lazy_plt_entry, /* plt_entry */
LAZY_PLT_ENTRY_SIZE, /* plt_entry_size */
+ elf_x86_64_tlsdesc_plt_entry, /* plt_tlsdesc_entry */
+ LAZY_PLT_ENTRY_SIZE, /* plt_tlsdesc_entry_size */
+ 6, /* plt_tlsdesc_got1_offset */
+ 12, /* plt_tlsdesc_got2_offset */
+ 10, /* plt_tlsdesc_got1_insn_end */
+ 16, /* plt_tlsdesc_got2_insn_end */
2, /* plt0_got1_offset */
8, /* plt0_got2_offset */
12, /* plt0_got2_insn_end */
LAZY_PLT_ENTRY_SIZE, /* plt0_entry_size */
elf_x86_64_lazy_bnd_plt_entry, /* plt_entry */
LAZY_PLT_ENTRY_SIZE, /* plt_entry_size */
+ elf_x86_64_tlsdesc_plt_entry, /* plt_tlsdesc_entry */
+ LAZY_PLT_ENTRY_SIZE, /* plt_tlsdesc_entry_size */
+ 6, /* plt_tlsdesc_got1_offset */
+ 12, /* plt_tlsdesc_got2_offset */
+ 10, /* plt_tlsdesc_got1_insn_end */
+ 16, /* plt_tlsdesc_got2_insn_end */
2, /* plt0_got1_offset */
1+8, /* plt0_got2_offset */
1+12, /* plt0_got2_insn_end */
LAZY_PLT_ENTRY_SIZE, /* plt0_entry_size */
elf_x86_64_lazy_ibt_plt_entry, /* plt_entry */
LAZY_PLT_ENTRY_SIZE, /* plt_entry_size */
+ elf_x86_64_tlsdesc_plt_entry, /* plt_tlsdesc_entry */
+ LAZY_PLT_ENTRY_SIZE, /* plt_tlsdesc_entry_size */
+ 6, /* plt_tlsdesc_got1_offset */
+ 12, /* plt_tlsdesc_got2_offset */
+ 10, /* plt_tlsdesc_got1_insn_end */
+ 16, /* plt_tlsdesc_got2_insn_end */
2, /* plt0_got1_offset */
1+8, /* plt0_got2_offset */
1+12, /* plt0_got2_insn_end */
LAZY_PLT_ENTRY_SIZE, /* plt0_entry_size */
elf_x32_lazy_ibt_plt_entry, /* plt_entry */
LAZY_PLT_ENTRY_SIZE, /* plt_entry_size */
+ elf_x86_64_tlsdesc_plt_entry, /* plt_tlsdesc_entry */
+ LAZY_PLT_ENTRY_SIZE, /* plt_tlsdesc_entry_size */
+ 6, /* plt_tlsdesc_got1_offset */
+ 12, /* plt_tlsdesc_got2_offset */
+ 10, /* plt_tlsdesc_got1_insn_end */
+ 16, /* plt_tlsdesc_got2_insn_end */
2, /* plt0_got1_offset */
8, /* plt0_got2_offset */
12, /* plt0_got2_insn_end */
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;
+ }
plt_entry_size = htab->plt.plt_entry_size;
symtab_hdr = &elf_symtab_hdr (input_bfd);
continue;
}
+ r_symndx = htab->r_sym (rel->r_info);
converted_reloc = (r_type & R_X86_64_converted_reloc_bit) != 0;
- r_type &= ~R_X86_64_converted_reloc_bit;
+ if (converted_reloc)
+ {
+ r_type &= ~R_X86_64_converted_reloc_bit;
+ rel->r_info = htab->r_info (r_symndx, r_type);
+ }
- if (r_type >= (int) R_X86_64_standard)
+ howto = elf_x86_64_rtype_to_howto (input_bfd, r_type);
+ if (howto == NULL)
return _bfd_unrecognized_reloc (input_bfd, input_section, r_type);
- if (r_type != (int) R_X86_64_32
- || ABI_64_P (output_bfd))
- howto = x86_64_elf_howto_table + r_type;
- else
- howto = (x86_64_elf_howto_table
- + ARRAY_SIZE (x86_64_elf_howto_table) - 1);
- r_symndx = htab->r_sym (rel->r_info);
h = NULL;
sym = NULL;
sec = NULL;
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;
if ((input_section->flags & SEC_ALLOC) == 0)
{
+ /* If this is a SHT_NOTE section without SHF_ALLOC, treat
+ STT_GNU_IFUNC symbol as STT_FUNC. */
+ if (elf_section_type (input_section) == SHT_NOTE)
+ goto skip_ifunc;
/* Dynamic relocs are not propagated for SEC_DEBUGGING
sections because such sections are not SEC_ALLOC and
thus ld.so will not process them. */
}
}
+skip_ifunc:
resolved_to_zero = (eh != NULL
&& UNDEFINED_WEAK_RESOLVED_TO_ZERO (info, eh));
sym->st_value = 0;
}
+ _bfd_x86_elf_link_fixup_ifunc_symbol (info, htab, h, sym);
+
/* Don't generate dynamic GOT relocation against undefined weak
symbol in executable. */
if (h->got.offset != (bfd_vma) -1
htab->elf.sgot->contents + htab->tlsdesc_got);
memcpy (htab->elf.splt->contents + htab->tlsdesc_plt,
- htab->lazy_plt->plt0_entry,
- htab->lazy_plt->plt0_entry_size);
+ htab->lazy_plt->plt_tlsdesc_entry,
+ htab->lazy_plt->plt_tlsdesc_entry_size);
- /* Add offset for pushq GOT+8(%rip), since the
- instruction uses 6 bytes subtract this value. */
+ /* Add offset for pushq GOT+8(%rip), since ENDBR64 uses 4
+ bytes and the instruction uses 6 bytes, subtract these
+ values. */
bfd_put_32 (output_bfd,
(htab->elf.sgotplt->output_section->vma
+ htab->elf.sgotplt->output_offset
- htab->elf.splt->output_section->vma
- htab->elf.splt->output_offset
- htab->tlsdesc_plt
- - 6),
+ - htab->lazy_plt->plt_tlsdesc_got1_insn_end),
(htab->elf.splt->contents
+ htab->tlsdesc_plt
- + htab->lazy_plt->plt0_got1_offset));
- /* Add offset for the PC-relative instruction accessing
- GOT+TDG, where TDG stands for htab->tlsdesc_got,
- subtracting the offset to the end of that
- instruction. */
+ + htab->lazy_plt->plt_tlsdesc_got1_offset));
+ /* Add offset for indirect branch via GOT+TDG, where TDG
+ stands for htab->tlsdesc_got, subtracting the offset
+ to the end of that instruction. */
bfd_put_32 (output_bfd,
(htab->elf.sgot->output_section->vma
+ htab->elf.sgot->output_offset
- htab->elf.splt->output_section->vma
- htab->elf.splt->output_offset
- htab->tlsdesc_plt
- - htab->lazy_plt->plt0_got2_insn_end),
+ - htab->lazy_plt->plt_tlsdesc_got2_insn_end),
(htab->elf.splt->contents
+ htab->tlsdesc_plt
- + htab->lazy_plt->plt0_got2_offset));
+ + htab->lazy_plt->plt_tlsdesc_got2_offset));
}
}
#define ELF_ARCH bfd_arch_i386
#define ELF_TARGET_ID X86_64_ELF_DATA
#define ELF_MACHINE_CODE EM_X86_64
-#define ELF_MAXPAGESIZE 0x200000
+#if DEFAULT_LD_Z_SEPARATE_CODE
+# define ELF_MAXPAGESIZE 0x1000
+#else
+# define ELF_MAXPAGESIZE 0x200000
+#endif
#define ELF_MINPAGESIZE 0x1000
#define ELF_COMMONPAGESIZE 0x1000
#define elf_backend_hide_symbol \
_bfd_x86_elf_hide_symbol
+#undef elf64_bed
+#define elf64_bed elf64_x86_64_bed
+
#include "elf64-target.h"
/* CloudABI support. */
NACL_PLT_ENTRY_SIZE, /* plt0_entry_size */
elf_x86_64_nacl_plt_entry, /* plt_entry */
NACL_PLT_ENTRY_SIZE, /* plt_entry_size */
+ elf_x86_64_nacl_plt0_entry, /* plt_tlsdesc_entry */
+ NACL_PLT_ENTRY_SIZE, /* plt_tlsdesc_entry_size */
+ 2, /* plt_tlsdesc_got1_offset */
+ 9, /* plt_tlsdesc_got2_offset */
+ 6, /* plt_tlsdesc_got1_insn_end */
+ 13, /* plt_tlsdesc_got2_insn_end */
2, /* plt0_got1_offset */
9, /* plt0_got2_offset */
13, /* plt0_got2_insn_end */
#define elf_backend_size_info \
_bfd_elf32_size_info
+#undef elf32_bed
+#define elf32_bed elf32_x86_64_bed
+
#include "elf32-target.h"
/* Restore defaults. */
#undef ELF_MAXPAGESIZE
#undef ELF_MINPAGESIZE
#undef ELF_COMMONPAGESIZE
-#define ELF_MAXPAGESIZE 0x200000
+#if DEFAULT_LD_Z_SEPARATE_CODE
+# define ELF_MAXPAGESIZE 0x1000
+#else
+# define ELF_MAXPAGESIZE 0x200000
+#endif
#define ELF_MINPAGESIZE 0x1000
#define ELF_COMMONPAGESIZE 0x1000
#undef elf_backend_plt_alignment