X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=bfd%2Felf64-x86-64.c;h=6154a70bdd7073e5ad8124bbdb9f813064d86ec8;hb=713f370809b523277f8ecc69680ab591ce94da5e;hp=014bea147541caf686d203f519f3adf616146411;hpb=14470f0755dbc942aa684ed647df978ddfc7cff2;p=binutils-gdb.git diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c index 014bea14754..6154a70bdd7 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-2020 Free Software Foundation, Inc. + Copyright (C) 2000-2022 Free Software Foundation, Inc. Contributed by Jan Hubicka . This file is part of BFD, the Binary File Descriptor library. @@ -20,12 +20,10 @@ MA 02110-1301, USA. */ #include "elfxx-x86.h" -#include "elf-nacl.h" #include "dwarf2.h" #include "libiberty.h" #include "opcode/i386.h" -#include "elf/x86-64.h" #ifdef CORE_HEADER #include @@ -45,134 +43,132 @@ special_function, name, partial_inplace, src_mask, dst_mask, pcrel_offset. */ static reloc_howto_type x86_64_elf_howto_table[] = { - HOWTO(R_X86_64_NONE, 0, 3, 0, FALSE, 0, complain_overflow_dont, - bfd_elf_generic_reloc, "R_X86_64_NONE", FALSE, 0x00000000, 0x00000000, - FALSE), - HOWTO(R_X86_64_64, 0, 4, 64, FALSE, 0, complain_overflow_bitfield, - bfd_elf_generic_reloc, "R_X86_64_64", FALSE, MINUS_ONE, MINUS_ONE, - FALSE), - HOWTO(R_X86_64_PC32, 0, 2, 32, TRUE, 0, complain_overflow_signed, - bfd_elf_generic_reloc, "R_X86_64_PC32", FALSE, 0xffffffff, 0xffffffff, - TRUE), - HOWTO(R_X86_64_GOT32, 0, 2, 32, FALSE, 0, complain_overflow_signed, - bfd_elf_generic_reloc, "R_X86_64_GOT32", FALSE, 0xffffffff, 0xffffffff, - FALSE), - HOWTO(R_X86_64_PLT32, 0, 2, 32, TRUE, 0, complain_overflow_signed, - bfd_elf_generic_reloc, "R_X86_64_PLT32", FALSE, 0xffffffff, 0xffffffff, - TRUE), - HOWTO(R_X86_64_COPY, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, - bfd_elf_generic_reloc, "R_X86_64_COPY", FALSE, 0xffffffff, 0xffffffff, - FALSE), - HOWTO(R_X86_64_GLOB_DAT, 0, 4, 64, FALSE, 0, complain_overflow_bitfield, - bfd_elf_generic_reloc, "R_X86_64_GLOB_DAT", FALSE, MINUS_ONE, - MINUS_ONE, FALSE), - HOWTO(R_X86_64_JUMP_SLOT, 0, 4, 64, FALSE, 0, complain_overflow_bitfield, - bfd_elf_generic_reloc, "R_X86_64_JUMP_SLOT", FALSE, MINUS_ONE, - MINUS_ONE, FALSE), - HOWTO(R_X86_64_RELATIVE, 0, 4, 64, FALSE, 0, complain_overflow_bitfield, - bfd_elf_generic_reloc, "R_X86_64_RELATIVE", FALSE, MINUS_ONE, - MINUS_ONE, FALSE), - HOWTO(R_X86_64_GOTPCREL, 0, 2, 32, TRUE, 0, complain_overflow_signed, - bfd_elf_generic_reloc, "R_X86_64_GOTPCREL", FALSE, 0xffffffff, - 0xffffffff, TRUE), - HOWTO(R_X86_64_32, 0, 2, 32, FALSE, 0, complain_overflow_unsigned, - bfd_elf_generic_reloc, "R_X86_64_32", FALSE, 0xffffffff, 0xffffffff, - FALSE), - HOWTO(R_X86_64_32S, 0, 2, 32, FALSE, 0, complain_overflow_signed, - bfd_elf_generic_reloc, "R_X86_64_32S", FALSE, 0xffffffff, 0xffffffff, - FALSE), - HOWTO(R_X86_64_16, 0, 1, 16, FALSE, 0, complain_overflow_bitfield, - bfd_elf_generic_reloc, "R_X86_64_16", FALSE, 0xffff, 0xffff, FALSE), - HOWTO(R_X86_64_PC16,0, 1, 16, TRUE, 0, complain_overflow_bitfield, - bfd_elf_generic_reloc, "R_X86_64_PC16", FALSE, 0xffff, 0xffff, TRUE), - HOWTO(R_X86_64_8, 0, 0, 8, FALSE, 0, complain_overflow_bitfield, - bfd_elf_generic_reloc, "R_X86_64_8", FALSE, 0xff, 0xff, FALSE), - HOWTO(R_X86_64_PC8, 0, 0, 8, TRUE, 0, complain_overflow_signed, - bfd_elf_generic_reloc, "R_X86_64_PC8", FALSE, 0xff, 0xff, TRUE), - HOWTO(R_X86_64_DTPMOD64, 0, 4, 64, FALSE, 0, complain_overflow_bitfield, - bfd_elf_generic_reloc, "R_X86_64_DTPMOD64", FALSE, MINUS_ONE, - MINUS_ONE, FALSE), - HOWTO(R_X86_64_DTPOFF64, 0, 4, 64, FALSE, 0, complain_overflow_bitfield, - bfd_elf_generic_reloc, "R_X86_64_DTPOFF64", FALSE, MINUS_ONE, - MINUS_ONE, FALSE), - HOWTO(R_X86_64_TPOFF64, 0, 4, 64, FALSE, 0, complain_overflow_bitfield, - bfd_elf_generic_reloc, "R_X86_64_TPOFF64", FALSE, MINUS_ONE, - MINUS_ONE, FALSE), - HOWTO(R_X86_64_TLSGD, 0, 2, 32, TRUE, 0, complain_overflow_signed, - bfd_elf_generic_reloc, "R_X86_64_TLSGD", FALSE, 0xffffffff, - 0xffffffff, TRUE), - HOWTO(R_X86_64_TLSLD, 0, 2, 32, TRUE, 0, complain_overflow_signed, - bfd_elf_generic_reloc, "R_X86_64_TLSLD", FALSE, 0xffffffff, - 0xffffffff, TRUE), - HOWTO(R_X86_64_DTPOFF32, 0, 2, 32, FALSE, 0, complain_overflow_signed, - bfd_elf_generic_reloc, "R_X86_64_DTPOFF32", FALSE, 0xffffffff, - 0xffffffff, FALSE), - HOWTO(R_X86_64_GOTTPOFF, 0, 2, 32, TRUE, 0, complain_overflow_signed, - bfd_elf_generic_reloc, "R_X86_64_GOTTPOFF", FALSE, 0xffffffff, - 0xffffffff, TRUE), - HOWTO(R_X86_64_TPOFF32, 0, 2, 32, FALSE, 0, complain_overflow_signed, - bfd_elf_generic_reloc, "R_X86_64_TPOFF32", FALSE, 0xffffffff, - 0xffffffff, FALSE), - HOWTO(R_X86_64_PC64, 0, 4, 64, TRUE, 0, complain_overflow_bitfield, - bfd_elf_generic_reloc, "R_X86_64_PC64", FALSE, MINUS_ONE, MINUS_ONE, - TRUE), - HOWTO(R_X86_64_GOTOFF64, 0, 4, 64, FALSE, 0, complain_overflow_bitfield, - bfd_elf_generic_reloc, "R_X86_64_GOTOFF64", - FALSE, MINUS_ONE, MINUS_ONE, FALSE), - HOWTO(R_X86_64_GOTPC32, 0, 2, 32, TRUE, 0, complain_overflow_signed, - bfd_elf_generic_reloc, "R_X86_64_GOTPC32", - FALSE, 0xffffffff, 0xffffffff, TRUE), - HOWTO(R_X86_64_GOT64, 0, 4, 64, FALSE, 0, complain_overflow_signed, - bfd_elf_generic_reloc, "R_X86_64_GOT64", FALSE, MINUS_ONE, MINUS_ONE, - FALSE), - HOWTO(R_X86_64_GOTPCREL64, 0, 4, 64, TRUE, 0, complain_overflow_signed, - bfd_elf_generic_reloc, "R_X86_64_GOTPCREL64", FALSE, MINUS_ONE, - MINUS_ONE, TRUE), - HOWTO(R_X86_64_GOTPC64, 0, 4, 64, TRUE, 0, complain_overflow_signed, - bfd_elf_generic_reloc, "R_X86_64_GOTPC64", - FALSE, MINUS_ONE, MINUS_ONE, TRUE), - HOWTO(R_X86_64_GOTPLT64, 0, 4, 64, FALSE, 0, complain_overflow_signed, - bfd_elf_generic_reloc, "R_X86_64_GOTPLT64", FALSE, MINUS_ONE, - MINUS_ONE, FALSE), - HOWTO(R_X86_64_PLTOFF64, 0, 4, 64, FALSE, 0, complain_overflow_signed, - bfd_elf_generic_reloc, "R_X86_64_PLTOFF64", FALSE, MINUS_ONE, - MINUS_ONE, FALSE), - HOWTO(R_X86_64_SIZE32, 0, 2, 32, FALSE, 0, complain_overflow_unsigned, - bfd_elf_generic_reloc, "R_X86_64_SIZE32", FALSE, 0xffffffff, 0xffffffff, - FALSE), - HOWTO(R_X86_64_SIZE64, 0, 4, 64, FALSE, 0, complain_overflow_unsigned, - bfd_elf_generic_reloc, "R_X86_64_SIZE64", FALSE, MINUS_ONE, MINUS_ONE, - FALSE), - HOWTO(R_X86_64_GOTPC32_TLSDESC, 0, 2, 32, TRUE, 0, + HOWTO(R_X86_64_NONE, 0, 0, 0, false, 0, complain_overflow_dont, + bfd_elf_generic_reloc, "R_X86_64_NONE", false, 0, 0x00000000, + false), + HOWTO(R_X86_64_64, 0, 8, 64, false, 0, complain_overflow_dont, + bfd_elf_generic_reloc, "R_X86_64_64", false, 0, MINUS_ONE, + false), + HOWTO(R_X86_64_PC32, 0, 4, 32, true, 0, complain_overflow_signed, + bfd_elf_generic_reloc, "R_X86_64_PC32", false, 0, 0xffffffff, + true), + HOWTO(R_X86_64_GOT32, 0, 4, 32, false, 0, complain_overflow_signed, + bfd_elf_generic_reloc, "R_X86_64_GOT32", false, 0, 0xffffffff, + false), + HOWTO(R_X86_64_PLT32, 0, 4, 32, true, 0, complain_overflow_signed, + bfd_elf_generic_reloc, "R_X86_64_PLT32", false, 0, 0xffffffff, + true), + HOWTO(R_X86_64_COPY, 0, 4, 32, false, 0, complain_overflow_bitfield, + bfd_elf_generic_reloc, "R_X86_64_COPY", false, 0, 0xffffffff, + false), + HOWTO(R_X86_64_GLOB_DAT, 0, 8, 64, false, 0, complain_overflow_dont, + bfd_elf_generic_reloc, "R_X86_64_GLOB_DAT", false, 0, MINUS_ONE, + false), + HOWTO(R_X86_64_JUMP_SLOT, 0, 8, 64, false, 0, complain_overflow_dont, + bfd_elf_generic_reloc, "R_X86_64_JUMP_SLOT", false, 0, MINUS_ONE, + false), + HOWTO(R_X86_64_RELATIVE, 0, 8, 64, false, 0, complain_overflow_dont, + bfd_elf_generic_reloc, "R_X86_64_RELATIVE", false, 0, MINUS_ONE, + false), + HOWTO(R_X86_64_GOTPCREL, 0, 4, 32, true, 0, complain_overflow_signed, + bfd_elf_generic_reloc, "R_X86_64_GOTPCREL", false, 0, 0xffffffff, + true), + HOWTO(R_X86_64_32, 0, 4, 32, false, 0, complain_overflow_unsigned, + bfd_elf_generic_reloc, "R_X86_64_32", false, 0, 0xffffffff, + false), + HOWTO(R_X86_64_32S, 0, 4, 32, false, 0, complain_overflow_signed, + bfd_elf_generic_reloc, "R_X86_64_32S", false, 0, 0xffffffff, + false), + HOWTO(R_X86_64_16, 0, 2, 16, false, 0, complain_overflow_bitfield, + bfd_elf_generic_reloc, "R_X86_64_16", false, 0, 0xffff, false), + HOWTO(R_X86_64_PC16, 0, 2, 16, true, 0, complain_overflow_bitfield, + bfd_elf_generic_reloc, "R_X86_64_PC16", false, 0, 0xffff, true), + HOWTO(R_X86_64_8, 0, 1, 8, false, 0, complain_overflow_bitfield, + bfd_elf_generic_reloc, "R_X86_64_8", false, 0, 0xff, false), + HOWTO(R_X86_64_PC8, 0, 1, 8, true, 0, complain_overflow_signed, + bfd_elf_generic_reloc, "R_X86_64_PC8", false, 0, 0xff, true), + HOWTO(R_X86_64_DTPMOD64, 0, 8, 64, false, 0, complain_overflow_dont, + bfd_elf_generic_reloc, "R_X86_64_DTPMOD64", false, 0, MINUS_ONE, + false), + HOWTO(R_X86_64_DTPOFF64, 0, 8, 64, false, 0, complain_overflow_dont, + bfd_elf_generic_reloc, "R_X86_64_DTPOFF64", false, 0, MINUS_ONE, + false), + HOWTO(R_X86_64_TPOFF64, 0, 8, 64, false, 0, complain_overflow_dont, + bfd_elf_generic_reloc, "R_X86_64_TPOFF64", false, 0, MINUS_ONE, + false), + HOWTO(R_X86_64_TLSGD, 0, 4, 32, true, 0, complain_overflow_signed, + bfd_elf_generic_reloc, "R_X86_64_TLSGD", false, 0, 0xffffffff, + true), + HOWTO(R_X86_64_TLSLD, 0, 4, 32, true, 0, complain_overflow_signed, + bfd_elf_generic_reloc, "R_X86_64_TLSLD", false, 0, 0xffffffff, + true), + HOWTO(R_X86_64_DTPOFF32, 0, 4, 32, false, 0, complain_overflow_signed, + bfd_elf_generic_reloc, "R_X86_64_DTPOFF32", false, 0, 0xffffffff, + false), + HOWTO(R_X86_64_GOTTPOFF, 0, 4, 32, true, 0, complain_overflow_signed, + bfd_elf_generic_reloc, "R_X86_64_GOTTPOFF", false, 0, 0xffffffff, + true), + HOWTO(R_X86_64_TPOFF32, 0, 4, 32, false, 0, complain_overflow_signed, + bfd_elf_generic_reloc, "R_X86_64_TPOFF32", false, 0, 0xffffffff, + false), + HOWTO(R_X86_64_PC64, 0, 8, 64, true, 0, complain_overflow_dont, + bfd_elf_generic_reloc, "R_X86_64_PC64", false, 0, MINUS_ONE, + true), + HOWTO(R_X86_64_GOTOFF64, 0, 8, 64, false, 0, complain_overflow_dont, + bfd_elf_generic_reloc, "R_X86_64_GOTOFF64", false, 0, MINUS_ONE, + false), + HOWTO(R_X86_64_GOTPC32, 0, 4, 32, true, 0, complain_overflow_signed, + bfd_elf_generic_reloc, "R_X86_64_GOTPC32", false, 0, 0xffffffff, + true), + HOWTO(R_X86_64_GOT64, 0, 8, 64, false, 0, complain_overflow_signed, + bfd_elf_generic_reloc, "R_X86_64_GOT64", false, 0, MINUS_ONE, + false), + HOWTO(R_X86_64_GOTPCREL64, 0, 8, 64, true, 0, complain_overflow_signed, + bfd_elf_generic_reloc, "R_X86_64_GOTPCREL64", false, 0, MINUS_ONE, + true), + HOWTO(R_X86_64_GOTPC64, 0, 8, 64, true, 0, complain_overflow_signed, + bfd_elf_generic_reloc, "R_X86_64_GOTPC64", false, 0, MINUS_ONE, + true), + HOWTO(R_X86_64_GOTPLT64, 0, 8, 64, false, 0, complain_overflow_signed, + bfd_elf_generic_reloc, "R_X86_64_GOTPLT64", false, 0, MINUS_ONE, + false), + HOWTO(R_X86_64_PLTOFF64, 0, 8, 64, false, 0, complain_overflow_signed, + bfd_elf_generic_reloc, "R_X86_64_PLTOFF64", false, 0, MINUS_ONE, + false), + HOWTO(R_X86_64_SIZE32, 0, 4, 32, false, 0, complain_overflow_unsigned, + bfd_elf_generic_reloc, "R_X86_64_SIZE32", false, 0, 0xffffffff, + false), + HOWTO(R_X86_64_SIZE64, 0, 8, 64, false, 0, complain_overflow_dont, + bfd_elf_generic_reloc, "R_X86_64_SIZE64", false, 0, MINUS_ONE, + false), + HOWTO(R_X86_64_GOTPC32_TLSDESC, 0, 4, 32, true, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, - "R_X86_64_GOTPC32_TLSDESC", - FALSE, 0xffffffff, 0xffffffff, TRUE), - HOWTO(R_X86_64_TLSDESC_CALL, 0, 0, 0, FALSE, 0, + "R_X86_64_GOTPC32_TLSDESC", false, 0, 0xffffffff, true), + HOWTO(R_X86_64_TLSDESC_CALL, 0, 0, 0, false, 0, complain_overflow_dont, bfd_elf_generic_reloc, "R_X86_64_TLSDESC_CALL", - FALSE, 0, 0, FALSE), - HOWTO(R_X86_64_TLSDESC, 0, 4, 64, FALSE, 0, - complain_overflow_bitfield, bfd_elf_generic_reloc, - "R_X86_64_TLSDESC", - FALSE, MINUS_ONE, MINUS_ONE, FALSE), - HOWTO(R_X86_64_IRELATIVE, 0, 4, 64, FALSE, 0, complain_overflow_bitfield, - bfd_elf_generic_reloc, "R_X86_64_IRELATIVE", FALSE, MINUS_ONE, - MINUS_ONE, FALSE), - HOWTO(R_X86_64_RELATIVE64, 0, 4, 64, FALSE, 0, complain_overflow_bitfield, - bfd_elf_generic_reloc, "R_X86_64_RELATIVE64", FALSE, MINUS_ONE, - MINUS_ONE, FALSE), - HOWTO(R_X86_64_PC32_BND, 0, 2, 32, TRUE, 0, complain_overflow_signed, - bfd_elf_generic_reloc, "R_X86_64_PC32_BND", FALSE, 0xffffffff, 0xffffffff, - TRUE), - HOWTO(R_X86_64_PLT32_BND, 0, 2, 32, TRUE, 0, complain_overflow_signed, - bfd_elf_generic_reloc, "R_X86_64_PLT32_BND", FALSE, 0xffffffff, 0xffffffff, - TRUE), - HOWTO(R_X86_64_GOTPCRELX, 0, 2, 32, TRUE, 0, complain_overflow_signed, - bfd_elf_generic_reloc, "R_X86_64_GOTPCRELX", FALSE, 0xffffffff, - 0xffffffff, TRUE), - HOWTO(R_X86_64_REX_GOTPCRELX, 0, 2, 32, TRUE, 0, complain_overflow_signed, - bfd_elf_generic_reloc, "R_X86_64_REX_GOTPCRELX", FALSE, 0xffffffff, - 0xffffffff, TRUE), + false, 0, 0, false), + HOWTO(R_X86_64_TLSDESC, 0, 8, 64, false, 0, + complain_overflow_dont, bfd_elf_generic_reloc, + "R_X86_64_TLSDESC", false, 0, MINUS_ONE, false), + HOWTO(R_X86_64_IRELATIVE, 0, 8, 64, false, 0, complain_overflow_dont, + bfd_elf_generic_reloc, "R_X86_64_IRELATIVE", false, 0, MINUS_ONE, + false), + HOWTO(R_X86_64_RELATIVE64, 0, 8, 64, false, 0, complain_overflow_dont, + bfd_elf_generic_reloc, "R_X86_64_RELATIVE64", false, 0, MINUS_ONE, + false), + HOWTO(R_X86_64_PC32_BND, 0, 4, 32, true, 0, complain_overflow_signed, + bfd_elf_generic_reloc, "R_X86_64_PC32_BND", false, 0, 0xffffffff, + true), + HOWTO(R_X86_64_PLT32_BND, 0, 4, 32, true, 0, complain_overflow_signed, + bfd_elf_generic_reloc, "R_X86_64_PLT32_BND", false, 0, 0xffffffff, + true), + HOWTO(R_X86_64_GOTPCRELX, 0, 4, 32, true, 0, complain_overflow_signed, + bfd_elf_generic_reloc, "R_X86_64_GOTPCRELX", false, 0, 0xffffffff, + true), + HOWTO(R_X86_64_REX_GOTPCRELX, 0, 4, 32, true, 0, complain_overflow_signed, + bfd_elf_generic_reloc, "R_X86_64_REX_GOTPCRELX", false, 0, 0xffffffff, + true), /* We have a gap in the reloc numbers here. R_X86_64_standard counts the number up to this point, and @@ -182,33 +178,20 @@ static reloc_howto_type x86_64_elf_howto_table[] = #define R_X86_64_vt_offset (R_X86_64_GNU_VTINHERIT - R_X86_64_standard) /* GNU extension to record C++ vtable hierarchy. */ - HOWTO (R_X86_64_GNU_VTINHERIT, 0, 4, 0, FALSE, 0, complain_overflow_dont, - NULL, "R_X86_64_GNU_VTINHERIT", FALSE, 0, 0, FALSE), + HOWTO (R_X86_64_GNU_VTINHERIT, 0, 8, 0, false, 0, complain_overflow_dont, + NULL, "R_X86_64_GNU_VTINHERIT", false, 0, 0, false), /* GNU extension to record C++ vtable member usage. */ - HOWTO (R_X86_64_GNU_VTENTRY, 0, 4, 0, FALSE, 0, complain_overflow_dont, - _bfd_elf_rel_vtable_reloc_fn, "R_X86_64_GNU_VTENTRY", FALSE, 0, 0, - FALSE), + HOWTO (R_X86_64_GNU_VTENTRY, 0, 8, 0, false, 0, complain_overflow_dont, + _bfd_elf_rel_vtable_reloc_fn, "R_X86_64_GNU_VTENTRY", false, 0, 0, + false), /* Use complain_overflow_bitfield on R_X86_64_32 for x32. */ - HOWTO(R_X86_64_32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, - bfd_elf_generic_reloc, "R_X86_64_32", FALSE, 0xffffffff, 0xffffffff, - FALSE) + HOWTO(R_X86_64_32, 0, 4, 32, false, 0, complain_overflow_bitfield, + bfd_elf_generic_reloc, "R_X86_64_32", false, 0, 0xffffffff, + false) }; -/* Set if a relocation is converted from a GOTPCREL relocation. */ -#define R_X86_64_converted_reloc_bit (1 << 7) - -#define X86_PCREL_TYPE_P(TYPE) \ - ( ((TYPE) == R_X86_64_PC8) \ - || ((TYPE) == R_X86_64_PC16) \ - || ((TYPE) == R_X86_64_PC32) \ - || ((TYPE) == R_X86_64_PC32_BND) \ - || ((TYPE) == R_X86_64_PC64)) - -#define X86_SIZE_TYPE_P(TYPE) \ - ((TYPE) == R_X86_64_SIZE32 || (TYPE) == R_X86_64_SIZE64) - /* Map BFD relocs to the x86_64 elf relocs. */ struct elf_reloc_map { @@ -337,7 +320,7 @@ elf_x86_64_reloc_name_lookup (bfd *abfd, /* Given an x86_64 ELF reloc type, fill in an arelent structure. */ -static bfd_boolean +static bool elf_x86_64_info_to_howto (bfd *abfd, arelent *cache_ptr, Elf_Internal_Rela *dst) { @@ -346,13 +329,13 @@ elf_x86_64_info_to_howto (bfd *abfd, arelent *cache_ptr, r_type = ELF32_R_TYPE (dst->r_info); cache_ptr->howto = elf_x86_64_rtype_to_howto (abfd, r_type); if (cache_ptr->howto == NULL) - return FALSE; + return false; BFD_ASSERT (r_type == cache_ptr->howto->type || cache_ptr->howto->type == R_X86_64_NONE); - return TRUE; + return true; } /* Support for core dump NOTE sections. */ -static bfd_boolean +static bool elf_x86_64_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) { int offset; @@ -361,7 +344,7 @@ elf_x86_64_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) switch (note->descsz) { default: - return FALSE; + return false; case 296: /* sizeof(istruct elf_prstatus) on Linux/x32 */ /* pr_cursig */ @@ -397,13 +380,13 @@ elf_x86_64_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) size, note->descpos + offset); } -static bfd_boolean +static bool elf_x86_64_grok_psinfo (bfd *abfd, Elf_Internal_Note *note) { switch (note->descsz) { default: - return FALSE; + return false; case 124: /* sizeof(struct elf_prpsinfo) on Linux/x32 */ elf_tdata (abfd)->core->pid @@ -435,7 +418,7 @@ elf_x86_64_grok_psinfo (bfd *abfd, Elf_Internal_Note *note) command[n - 1] = '\0'; } - return TRUE; + return true; } #ifdef CORE_HEADER @@ -988,33 +971,27 @@ static const struct elf_x86_non_lazy_plt_layout elf_x32_non_lazy_ibt_plt = sizeof (elf_x86_64_eh_frame_non_lazy_plt) /* eh_frame_plt_size */ }; -static const struct elf_x86_backend_data elf_x86_64_arch_bed = - { - is_normal /* os */ - }; - -#define elf_backend_arch_data &elf_x86_64_arch_bed -static bfd_boolean +static bool elf64_x86_64_elf_object_p (bfd *abfd) { /* Set the right machine number for an x86-64 elf64 file. */ bfd_default_set_arch_mach (abfd, bfd_arch_i386, bfd_mach_x86_64); - return TRUE; + return true; } -static bfd_boolean +static bool elf32_x86_64_elf_object_p (bfd *abfd) { /* Set the right machine number for an x86-64 elf32 file. */ bfd_default_set_arch_mach (abfd, bfd_arch_i386, bfd_mach_x64_32); - return TRUE; + return true; } /* Return TRUE if the TLS access code sequence support transition from R_TYPE. */ -static bfd_boolean +static bool elf_x86_64_check_tls_transition (bfd *abfd, struct bfd_link_info *info, asection *sec, @@ -1027,12 +1004,12 @@ elf_x86_64_check_tls_transition (bfd *abfd, { unsigned int val; unsigned long r_symndx; - bfd_boolean largepic = FALSE; + bool largepic = false; struct elf_link_hash_entry *h; bfd_vma offset; struct elf_x86_link_hash_table *htab; bfd_byte *call; - bfd_boolean indirect_call; + bool indirect_call; htab = elf_x86_hash_table (info, X86_64_ELF_DATA); offset = rel->r_offset; @@ -1041,7 +1018,7 @@ elf_x86_64_check_tls_transition (bfd *abfd, case R_X86_64_TLSGD: case R_X86_64_TLSLD: if ((rel + 1) >= relend) - return FALSE; + return false; if (r_type == R_X86_64_TLSGD) { @@ -1078,7 +1055,7 @@ elf_x86_64_check_tls_transition (bfd *abfd, static const unsigned char leaq[] = { 0x66, 0x48, 0x8d, 0x3d }; if ((offset + 12) > sec->size) - return FALSE; + return false; call = contents + offset + 4; if (call[0] != 0x66 @@ -1102,20 +1079,20 @@ elf_x86_64_check_tls_transition (bfd *abfd, || call[14] != 0xd0 || !((call[10] == 0x48 && call[12] == 0xd8) || (call[10] == 0x4c && call[12] == 0xf8))) - return FALSE; - largepic = TRUE; + return false; + largepic = true; } else if (ABI_64_P (abfd)) { if (offset < 4 || memcmp (contents + offset - 4, leaq, 4) != 0) - return FALSE; + return false; } else { if (offset < 3 || memcmp (contents + offset - 3, leaq + 1, 3) != 0) - return FALSE; + return false; } indirect_call = call[2] == 0xff; } @@ -1144,10 +1121,10 @@ elf_x86_64_check_tls_transition (bfd *abfd, static const unsigned char lea[] = { 0x48, 0x8d, 0x3d }; if (offset < 3 || (offset + 9) > sec->size) - return FALSE; + return false; if (memcmp (contents + offset - 3, lea, 3) != 0) - return FALSE; + return false; call = contents + offset + 4; if (!(call[0] == 0xe8 @@ -1162,20 +1139,20 @@ elf_x86_64_check_tls_transition (bfd *abfd, || call[14] != 0xd0 || !((call[10] == 0x48 && call[12] == 0xd8) || (call[10] == 0x4c && call[12] == 0xf8))) - return FALSE; - largepic = TRUE; + return false; + largepic = true; } indirect_call = call[0] == 0xff; } r_symndx = htab->r_sym (rel[1].r_info); if (r_symndx < symtab_hdr->sh_info) - return FALSE; + return false; h = sym_hashes[r_symndx - symtab_hdr->sh_info]; if (h == NULL || !((struct elf_x86_link_hash_entry *) h)->tls_get_addr) - return FALSE; + return false; else { r_type = (ELF32_R_TYPE (rel[1].r_info) @@ -1202,21 +1179,21 @@ elf_x86_64_check_tls_transition (bfd *abfd, { /* X32 may have 0x44 REX prefix or no REX prefix. */ if (ABI_64_P (abfd)) - return FALSE; + return false; } } else { /* X32 may not have any REX prefix. */ if (ABI_64_P (abfd)) - return FALSE; + return false; if (offset < 2 || (offset + 3) > sec->size) - return FALSE; + return false; } val = bfd_get_8 (abfd, contents + offset - 2); if (val != 0x8b && val != 0x03) - return FALSE; + return false; val = bfd_get_8 (abfd, contents + offset - 1); return (val & 0xc7) == 5; @@ -1231,15 +1208,15 @@ elf_x86_64_check_tls_transition (bfd *abfd, going to be rax. */ if (offset < 3 || (offset + 4) > sec->size) - return FALSE; + return false; val = bfd_get_8 (abfd, contents + offset - 3); val &= 0xfb; if (val != 0x48 && (ABI_64_P (abfd) || val != 0x40)) - return FALSE; + return false; if (bfd_get_8 (abfd, contents + offset - 2) != 0x8d) - return FALSE; + return false; val = bfd_get_8 (abfd, contents + offset - 1); return (val & 0xc7) == 0x05; @@ -1261,14 +1238,14 @@ elf_x86_64_check_tls_transition (bfd *abfd, { prefix = 1; if (offset + 3 > sec->size) - return FALSE; + return false; } } /* Make sure that it's a call *x@tlsdesc(%rax). */ return call[prefix] == 0xff && call[1 + prefix] == 0x10; } - return FALSE; + return false; default: abort (); @@ -1278,7 +1255,7 @@ elf_x86_64_check_tls_transition (bfd *abfd, /* Return TRUE if the TLS access transition is OK or no transition will be performed. Update R_TYPE if there is a transition. */ -static bfd_boolean +static bool elf_x86_64_tls_transition (struct bfd_link_info *info, bfd *abfd, asection *sec, bfd_byte *contents, Elf_Internal_Shdr *symtab_hdr, @@ -1288,17 +1265,17 @@ elf_x86_64_tls_transition (struct bfd_link_info *info, bfd *abfd, const Elf_Internal_Rela *relend, struct elf_link_hash_entry *h, unsigned long r_symndx, - bfd_boolean from_relocate_section) + bool from_relocate_section) { unsigned int from_type = *r_type; unsigned int to_type = from_type; - bfd_boolean check = TRUE; + bool check = true; /* Skip TLS transition for functions. */ if (h != NULL && (h->type == STT_FUNC || h->type == STT_GNU_IFUNC)) - return TRUE; + return true; switch (from_type) { @@ -1332,7 +1309,7 @@ elf_x86_64_tls_transition (struct bfd_link_info *info, bfd *abfd, } /* We checked the transition before when we were called from - elf_x86_64_check_relocs. We only want to check the new + elf_x86_64_scan_relocs. We only want to check the new transition which hasn't been checked before. */ check = new_to_type != to_type && from_type == to_type; to_type = new_to_type; @@ -1346,12 +1323,12 @@ elf_x86_64_tls_transition (struct bfd_link_info *info, bfd *abfd, break; default: - return TRUE; + return true; } /* Return TRUE if there is no transition. */ if (from_type == to_type) - return TRUE; + return true; /* Check if the transition can be performed. */ if (check @@ -1366,7 +1343,7 @@ elf_x86_64_tls_transition (struct bfd_link_info *info, bfd *abfd, to = elf_x86_64_rtype_to_howto (abfd, to_type); if (from == NULL || to == NULL) - return FALSE; + return false; if (h) name = h->root.root.string; @@ -1381,7 +1358,7 @@ elf_x86_64_tls_transition (struct bfd_link_info *info, bfd *abfd, { Elf_Internal_Sym *isym; - isym = bfd_sym_from_r_symndx (&htab->sym_cache, + isym = bfd_sym_from_r_symndx (&htab->elf.sym_cache, abfd, r_symndx); name = bfd_elf_sym_name (abfd, symtab_hdr, isym, NULL); } @@ -1393,18 +1370,14 @@ elf_x86_64_tls_transition (struct bfd_link_info *info, bfd *abfd, " in section `%pA' failed"), abfd, from->name, to->name, name, (uint64_t) rel->r_offset, sec); bfd_set_error (bfd_error_bad_value); - return FALSE; + return false; } *r_type = to_type; - return TRUE; + return true; } -/* Rename some of the generic section flags to better document how they - are used here. */ -#define check_relocs_failed sec_flg0 - -static bfd_boolean +static bool elf_x86_64_need_pic (struct bfd_link_info *info, bfd *input_bfd, asection *sec, struct elf_link_hash_entry *h, @@ -1473,7 +1446,7 @@ elf_x86_64_need_pic (struct bfd_link_info *info, object, pic); bfd_set_error (bfd_error_bad_value); sec->check_relocs_failed = 1; - return FALSE; + return false; } /* With the local symbol, foo, we convert @@ -1495,20 +1468,22 @@ elf_x86_64_need_pic (struct bfd_link_info *info, where binop is one of adc, add, and, cmp, or, sbb, sub, xor instructions. */ -static bfd_boolean +static bool elf_x86_64_convert_load_reloc (bfd *abfd, bfd_byte *contents, unsigned int *r_type_p, Elf_Internal_Rela *irel, struct elf_link_hash_entry *h, - bfd_boolean *converted, + bool *converted, struct bfd_link_info *link_info) { struct elf_x86_link_hash_table *htab; - bfd_boolean is_pic; - bfd_boolean no_overflow; - bfd_boolean relocx; - bfd_boolean to_reloc_pc32; + bool is_pic; + bool no_overflow; + bool relocx; + bool to_reloc_pc32; + bool abs_symbol; + bool local_ref; asection *tsec; bfd_signed_vma raddend; unsigned int opcode; @@ -1516,14 +1491,15 @@ elf_x86_64_convert_load_reloc (bfd *abfd, unsigned int r_type = *r_type_p; unsigned int r_symndx; bfd_vma roff = irel->r_offset; + bfd_vma abs_relocation; if (roff < (r_type == R_X86_64_REX_GOTPCRELX ? 3 : 2)) - return TRUE; + return true; raddend = irel->r_addend; /* Addend for 32-bit PC-relative relocation must be -4. */ if (raddend != -4) - return TRUE; + return true; htab = elf_x86_hash_table (link_info, X86_64_ELF_DATA); is_pic = bfd_link_pic (link_info); @@ -1545,7 +1521,7 @@ elf_x86_64_convert_load_reloc (bfd *abfd, for call, jmp or one of adc, add, and, cmp, or, sbb, sub, test, xor instructions. */ if (!relocx) - return TRUE; + return true; } /* We convert only to R_X86_64_PC32: @@ -1559,18 +1535,26 @@ elf_x86_64_convert_load_reloc (bfd *abfd, || no_overflow || is_pic); + abs_symbol = false; + abs_relocation = 0; + /* Get the symbol referred to by the reloc. */ if (h == NULL) { Elf_Internal_Sym *isym - = bfd_sym_from_r_symndx (&htab->sym_cache, abfd, r_symndx); + = bfd_sym_from_r_symndx (&htab->elf.sym_cache, abfd, r_symndx); /* Skip relocation against undefined symbols. */ if (isym->st_shndx == SHN_UNDEF) - return TRUE; + return true; + local_ref = true; if (isym->st_shndx == SHN_ABS) - tsec = bfd_abs_section_ptr; + { + tsec = bfd_abs_section_ptr; + abs_symbol = true; + abs_relocation = isym->st_value; + } else if (isym->st_shndx == SHN_COMMON) tsec = bfd_com_section_ptr; else if (isym->st_shndx == SHN_X86_64_LCOMMON) @@ -1586,9 +1570,11 @@ elf_x86_64_convert_load_reloc (bfd *abfd, GOTPCRELX relocations since we need to modify REX byte. It is OK convert mov with R_X86_64_GOTPCREL to R_X86_64_PC32. */ - bfd_boolean local_ref; struct elf_x86_link_hash_entry *eh = elf_x86_hash_entry (h); + abs_symbol = ABS_SYMBOL_P (h); + abs_relocation = h->root.u.def.value; + /* NB: Also set linker_def via SYMBOL_REFERENCES_LOCAL_P. */ local_ref = SYMBOL_REFERENCES_LOCAL_P (link_info, h); if ((relocx || opcode == 0x8b) @@ -1601,20 +1587,20 @@ elf_x86_64_convert_load_reloc (bfd *abfd, /* Skip for branch instructions since R_X86_64_PC32 may overflow. */ if (no_overflow) - return TRUE; + return true; } else if (relocx) { /* For non-branch instructions, we can convert to R_X86_64_32/R_X86_64_32S since we know if there is a REX byte. */ - to_reloc_pc32 = FALSE; + to_reloc_pc32 = false; } /* Since we don't know the current PC when PIC is true, we can't convert to R_X86_64_PC32. */ if (to_reloc_pc32 && is_pic) - return TRUE; + return true; goto convert; } @@ -1644,25 +1630,25 @@ elf_x86_64_convert_load_reloc (bfd *abfd, { /* Skip since R_X86_64_32/R_X86_64_32S may overflow. */ if (no_overflow) - return TRUE; + return true; goto convert; } tsec = h->root.u.def.section; } else - return TRUE; + return true; } /* Don't convert GOTPCREL relocation against large section. */ if (elf_section_data (tsec) != NULL && (elf_section_flags (tsec) & SHF_X86_64_LARGE) != 0) - return TRUE; + return true; /* Skip since R_X86_64_PC32/R_X86_64_32/R_X86_64_32S may overflow. */ if (no_overflow) - return TRUE; + return true; -convert: + convert: if (opcode == 0xff) { /* We have "call/jmp *foo@GOTPCREL(%rip)". */ @@ -1728,6 +1714,9 @@ convert: if (opcode == 0x8b) { + if (abs_symbol && local_ref && relocx) + to_reloc_pc32 = false; + if (to_reloc_pc32) { /* Convert "mov foo@GOTPCREL(%rip), %reg" to @@ -1765,7 +1754,7 @@ convert: { /* R_X86_64_PC32 isn't supported. */ if (to_reloc_pc32) - return TRUE; + return true; modrm = bfd_get_8 (abfd, contents + roff - 1); if (opcode == 0x85) @@ -1787,7 +1776,22 @@ convert: overflow when sign-extending imm32 to imm64. */ r_type = (rex & REX_W) != 0 ? R_X86_64_32S : R_X86_64_32; -rewrite_modrm_rex: + rewrite_modrm_rex: + if (abs_relocation) + { + /* Check if R_X86_64_32S/R_X86_64_32 fits. */ + if (r_type == R_X86_64_32S) + { + if ((abs_relocation + 0x80000000) > 0xffffffff) + return true; + } + else + { + if (abs_relocation > 0xffffffff) + return true; + } + } + bfd_put_8 (abfd, modrm, contents + roff - 1); if (rex) @@ -1808,46 +1812,36 @@ rewrite_modrm_rex: irel->r_info = htab->r_info (r_symndx, r_type | R_X86_64_converted_reloc_bit); - *converted = TRUE; + *converted = true; - return TRUE; + return true; } /* Look through the relocs for a section during the first phase, and - calculate needed space in the global offset table, procedure - linkage table, and dynamic reloc sections. */ + calculate needed space in the global offset table, and procedure + linkage table. */ -static bfd_boolean -elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, - asection *sec, - const Elf_Internal_Rela *relocs) +static bool +elf_x86_64_scan_relocs (bfd *abfd, struct bfd_link_info *info, + asection *sec, + const Elf_Internal_Rela *relocs) { struct elf_x86_link_hash_table *htab; Elf_Internal_Shdr *symtab_hdr; struct elf_link_hash_entry **sym_hashes; const Elf_Internal_Rela *rel; const Elf_Internal_Rela *rel_end; - asection *sreloc; bfd_byte *contents; - bfd_boolean converted; + bool converted; if (bfd_link_relocatable (info)) - return TRUE; - - /* Don't do anything special with non-loaded, non-alloced sections. - In particular, any relocs in such sections should not affect GOT - and PLT reference counting (ie. we don't allow them to create GOT - or PLT entries), there's no possibility or desire to optimize TLS - relocs, and there's not much point in propagating relocs to shared - libs that the dynamic linker won't relocate. */ - if ((sec->flags & SEC_ALLOC) == 0) - return TRUE; + return true; htab = elf_x86_hash_table (info, X86_64_ELF_DATA); if (htab == NULL) { sec->check_relocs_failed = 1; - return FALSE; + return false; } BFD_ASSERT (is_x86_elf (abfd, htab)); @@ -1858,15 +1852,13 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, else if (!bfd_malloc_and_get_section (abfd, sec, &contents)) { sec->check_relocs_failed = 1; - return FALSE; + return false; } symtab_hdr = &elf_symtab_hdr (abfd); sym_hashes = elf_sym_hashes (abfd); - converted = FALSE; - - sreloc = NULL; + converted = false; rel_end = relocs + sec->reloc_count; for (rel = relocs; rel < rel_end; rel++) @@ -1877,8 +1869,9 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, struct elf_x86_link_hash_entry *eh; Elf_Internal_Sym *isym; const char *name; - bfd_boolean size_reloc; - bfd_boolean converted_reloc; + bool size_reloc; + bool converted_reloc; + bool no_dynreloc; r_symndx = htab->r_sym (rel->r_info); r_type = ELF32_R_TYPE (rel->r_info); @@ -1894,7 +1887,7 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, if (r_symndx < symtab_hdr->sh_info) { /* A local symbol. */ - isym = bfd_sym_from_r_symndx (&htab->sym_cache, + isym = bfd_sym_from_r_symndx (&htab->elf.sym_cache, abfd, r_symndx); if (isym == NULL) goto error_return; @@ -1903,7 +1896,7 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, if (ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC) { h = _bfd_elf_x86_get_local_sym_hash (htab, abfd, rel, - TRUE); + true); if (h == NULL) goto error_return; @@ -1961,13 +1954,15 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, break; } + eh = (struct elf_x86_link_hash_entry *) h; + if (h != NULL) { /* It is referenced by a non-shared object. */ h->ref_regular = 1; } - converted_reloc = FALSE; + converted_reloc = false; if ((r_type == R_X86_64_GOTPCREL || r_type == R_X86_64_GOTPCRELX || r_type == R_X86_64_REX_GOTPCRELX) @@ -1980,20 +1975,23 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, goto error_return; if (converted_reloc) - converted = TRUE; + converted = true; } + if (!_bfd_elf_x86_valid_reloc_p (sec, info, htab, rel, h, isym, + symtab_hdr, &no_dynreloc)) + return false; + if (! elf_x86_64_tls_transition (info, abfd, sec, contents, symtab_hdr, sym_hashes, &r_type, GOT_UNKNOWN, - rel, rel_end, h, r_symndx, FALSE)) + rel, rel_end, h, r_symndx, false)) goto error_return; /* Check if _GLOBAL_OFFSET_TABLE_ is referenced. */ if (h == htab->elf.hgot) - htab->got_referenced = TRUE; + htab->got_referenced = true; - eh = (struct elf_x86_link_hash_entry *) h; switch (r_type) { case R_X86_64_TLSLD: @@ -2029,12 +2027,26 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, switch (r_type) { - default: tls_type = GOT_NORMAL; break; - case R_X86_64_TLSGD: tls_type = GOT_TLS_GD; break; - case R_X86_64_GOTTPOFF: tls_type = GOT_TLS_IE; break; + default: + tls_type = GOT_NORMAL; + if (h) + { + if (ABS_SYMBOL_P (h)) + tls_type = GOT_ABS; + } + else if (isym->st_shndx == SHN_ABS) + tls_type = GOT_ABS; + break; + case R_X86_64_TLSGD: + tls_type = GOT_TLS_GD; + break; + case R_X86_64_GOTTPOFF: + tls_type = GOT_TLS_IE; + break; case R_X86_64_GOTPC32_TLSDESC: case R_X86_64_TLSDESC_CALL: - tls_type = GOT_TLS_GDESC; break; + tls_type = GOT_TLS_GDESC; + break; } if (h != NULL) @@ -2046,25 +2058,12 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, { bfd_signed_vma *local_got_refcounts; + if (!elf_x86_allocate_local_got_info (abfd, + symtab_hdr->sh_info)) + goto error_return; + /* This is a global offset table entry for a local symbol. */ local_got_refcounts = elf_local_got_refcounts (abfd); - if (local_got_refcounts == NULL) - { - bfd_size_type size; - - size = symtab_hdr->sh_info; - size *= sizeof (bfd_signed_vma) - + sizeof (bfd_vma) + sizeof (char); - local_got_refcounts = ((bfd_signed_vma *) - bfd_zalloc (abfd, size)); - if (local_got_refcounts == NULL) - goto error_return; - elf_local_got_refcounts (abfd) = local_got_refcounts; - elf_x86_local_tlsdesc_gotent (abfd) - = (bfd_vma *) (local_got_refcounts + symtab_hdr->sh_info); - elf_x86_local_got_tls_type (abfd) - = (char *) (local_got_refcounts + 2 * symtab_hdr->sh_info); - } local_got_refcounts[r_symndx] = 1; old_tls_type = elf_x86_local_got_tls_type (abfd) [r_symndx]; @@ -2147,7 +2146,7 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, case R_X86_64_SIZE32: case R_X86_64_SIZE64: - size_reloc = TRUE; + size_reloc = true; goto do_size; case R_X86_64_32: @@ -2179,7 +2178,7 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, case R_X86_64_PC32_BND: case R_X86_64_PC64: case R_X86_64_64: -pointer: + pointer: if (eh != NULL && (sec->flags & SEC_CODE) != 0) eh->zero_undefweak |= 0x2; /* We are called after all symbols have been resolved. Only @@ -2189,7 +2188,7 @@ pointer: && (bfd_link_executable (info) || h->type == STT_GNU_IFUNC)) { - bfd_boolean func_pointer_ref = FALSE; + bool func_pointer_ref = false; if (r_type == R_X86_64_PC32) { @@ -2212,16 +2211,24 @@ pointer: else if (r_type != R_X86_64_PC32_BND && r_type != R_X86_64_PC64) { - h->pointer_equality_needed = 1; /* At run-time, R_X86_64_64 can be resolved for both x86-64 and x32. But R_X86_64_32 and R_X86_64_32S - can only be resolved for x32. */ + can only be resolved for x32. Function pointer + reference doesn't need PLT for pointer equality. */ if ((sec->flags & SEC_READONLY) == 0 && (r_type == R_X86_64_64 || (!ABI_64_P (abfd) && (r_type == R_X86_64_32 || r_type == R_X86_64_32S)))) - func_pointer_ref = TRUE; + func_pointer_ref = true; + + /* IFUNC symbol needs pointer equality in PDE so that + function pointer reference will be resolved to its + PLT entry directly. */ + if (!func_pointer_ref + || (bfd_link_pde (info) + && h->type == STT_GNU_IFUNC)) + h->pointer_equality_needed = 1; } if (!func_pointer_ref) @@ -2234,40 +2241,49 @@ pointer: adjust_dynamic_symbol. */ h->non_got_ref = 1; + if (!elf_has_indirect_extern_access (sec->owner)) + eh->non_got_ref_without_indirect_extern_access = 1; + /* We may need a .plt entry if the symbol is a function defined in a shared lib or is a function referenced from the code or read-only section. */ if (!h->def_regular || (sec->flags & (SEC_CODE | SEC_READONLY)) != 0) h->plt.refcount = 1; + + if (h->pointer_equality_needed + && h->type == STT_FUNC + && eh->def_protected + && elf_has_indirect_extern_access (h->root.u.def.section->owner)) + { + /* Disallow non-canonical reference to canonical + protected function. */ + _bfd_error_handler + /* xgettext:c-format */ + (_("%pB: non-canonical reference to canonical " + "protected function `%s' in %pB"), + abfd, h->root.root.string, + h->root.u.def.section->owner); + bfd_set_error (bfd_error_bad_value); + goto error_return; + } } } - size_reloc = FALSE; -do_size: - if (NEED_DYNAMIC_RELOCATION_P (info, TRUE, h, sec, r_type, - htab->pointer_r_type)) + size_reloc = false; + do_size: + if (!no_dynreloc + && NEED_DYNAMIC_RELOCATION_P (true, info, true, h, sec, + r_type, + htab->pointer_r_type)) { struct elf_dyn_relocs *p; struct elf_dyn_relocs **head; - /* We must copy these reloc types into the output file. - Create a reloc section in dynobj and make room for - this reloc. */ - if (sreloc == NULL) - { - sreloc = _bfd_elf_make_dynamic_reloc_section - (sec, htab->elf.dynobj, ABI_64_P (abfd) ? 3 : 2, - abfd, /*rela?*/ TRUE); - - if (sreloc == NULL) - goto error_return; - } - /* If this is a global symbol, we count the number of relocations we need for this symbol. */ if (h != NULL) - head = &eh->dyn_relocs; + head = &h->dyn_relocs; else { /* Track dynamic relocs needed for local syms too. @@ -2276,7 +2292,7 @@ do_size: asection *s; void **vpp; - isym = bfd_sym_from_r_symndx (&htab->sym_cache, + isym = bfd_sym_from_r_symndx (&htab->elf.sym_cache, abfd, r_symndx); if (isym == NULL) goto error_return; @@ -2294,7 +2310,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)); @@ -2309,7 +2325,7 @@ do_size: p->count += 1; /* Count size relocation as PC-relative relocation. */ - if (X86_PCREL_TYPE_P (r_type) || size_reloc) + if (X86_PCREL_TYPE_P (true, r_type) || size_reloc) p->pc_count += 1; } break; @@ -2335,13 +2351,14 @@ do_size: if (elf_section_data (sec)->this_hdr.contents != contents) { - if (!converted && !info->keep_memory) + if (!converted && !_bfd_link_keep_memory (info)) free (contents); else { /* Cache the section contents for elf_link_input_bfd if any load is converted or --no-keep-memory isn't used. */ elf_section_data (sec)->this_hdr.contents = contents; + info->cache_size += sec->size; } } @@ -2349,13 +2366,31 @@ do_size: if (elf_section_data (sec)->relocs != relocs && converted) elf_section_data (sec)->relocs = (Elf_Internal_Rela *) relocs; - return TRUE; + return true; -error_return: + error_return: if (elf_section_data (sec)->this_hdr.contents != contents) free (contents); sec->check_relocs_failed = 1; - return FALSE; + return false; +} + +static bool +elf_x86_64_always_size_sections (bfd *output_bfd, + struct bfd_link_info *info) +{ + bfd *abfd; + + /* Scan relocations after rel_from_abs has been set on __ehdr_start. */ + for (abfd = info->input_bfds; + abfd != (bfd *) NULL; + abfd = abfd->link.next) + if (bfd_get_flavour (abfd) == bfd_target_elf_flavour + && !_bfd_elf_link_iterate_on_relocs (abfd, info, + elf_x86_64_scan_relocs)) + return false; + + return _bfd_x86_elf_always_size_sections (output_bfd, info); } /* Return the relocation value for @tpoff relocation @@ -2379,7 +2414,7 @@ elf_x86_64_tpoff (struct bfd_link_info *info, bfd_vma address) /* Relocate an x86_64 ELF section. */ -static bfd_boolean +static int elf_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info, bfd *input_bfd, @@ -2398,19 +2433,20 @@ elf_x86_64_relocate_section (bfd *output_bfd, Elf_Internal_Rela *wrel; Elf_Internal_Rela *relend; unsigned int plt_entry_size; + bool status; - /* Skip if check_relocs failed. */ + /* Skip if check_relocs or scan_relocs failed. */ if (input_section->check_relocs_failed) - return FALSE; + return false; htab = elf_x86_hash_table (info, X86_64_ELF_DATA); if (htab == NULL) - return FALSE; + return false; if (!is_x86_elf (input_bfd, htab)) { bfd_set_error (bfd_error_wrong_format); - return FALSE; + return false; } plt_entry_size = htab->plt.plt_entry_size; @@ -2421,6 +2457,7 @@ elf_x86_64_relocate_section (bfd *output_bfd, _bfd_x86_elf_set_tls_module_base (info); + status = true; rel = wrel = relocs; relend = relocs + input_section->reloc_count; for (; rel < relend; wrel++, rel++) @@ -2434,16 +2471,16 @@ elf_x86_64_relocate_section (bfd *output_bfd, asection *sec; bfd_vma off, offplt, plt_offset; bfd_vma relocation; - bfd_boolean unresolved_reloc; + bool unresolved_reloc; bfd_reloc_status_type r; int tls_type; asection *base_got, *resolved_plt; bfd_vma st_size; - bfd_boolean resolved_to_zero; - bfd_boolean relative_reloc; - bfd_boolean converted_reloc; - bfd_boolean need_copy_reloc_in_pie; - bfd_boolean no_copyreloc_p; + bool resolved_to_zero; + bool relative_reloc; + bool converted_reloc; + bool need_copy_reloc_in_pie; + bool no_copyreloc_p; r_type = ELF32_R_TYPE (rel->r_info); if (r_type == (int) R_X86_64_GNU_VTINHERIT @@ -2469,7 +2506,7 @@ elf_x86_64_relocate_section (bfd *output_bfd, h = NULL; sym = NULL; sec = NULL; - unresolved_reloc = FALSE; + unresolved_reloc = false; if (r_symndx < symtab_hdr->sh_info) { sym = local_syms + r_symndx; @@ -2484,7 +2521,7 @@ elf_x86_64_relocate_section (bfd *output_bfd, && ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC) { h = _bfd_elf_x86_get_local_sym_hash (htab, input_bfd, - rel, FALSE); + rel, false); if (h == NULL) abort (); @@ -2495,8 +2532,8 @@ elf_x86_64_relocate_section (bfd *output_bfd, } else { - bfd_boolean warned ATTRIBUTE_UNUSED; - bfd_boolean ignored ATTRIBUTE_UNUSED; + bool warned ATTRIBUTE_UNUSED; + bool ignored ATTRIBUTE_UNUSED; RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel, r_symndx, symtab_hdr, sym_hashes, @@ -2678,7 +2715,7 @@ elf_x86_64_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 @@ -2690,7 +2727,7 @@ bad_ifunc_reloc: "symbol `%s' isn't supported"), input_bfd, howto->name, name); bfd_set_error (bfd_error_bad_value); - return FALSE; + return false; case R_X86_64_32S: if (bfd_link_pic (info)) @@ -2702,7 +2739,7 @@ bad_ifunc_reloc: goto do_relocation; /* FALLTHROUGH */ case R_X86_64_64: -do_ifunc_pointer: + do_ifunc_pointer: if (rel->r_addend != 0) { if (h->root.root.string) @@ -2716,7 +2753,7 @@ do_ifunc_pointer: "symbol `%s' has non-zero addend: %" PRId64), input_bfd, howto->name, name, (int64_t) rel->r_addend); bfd_set_error (bfd_error_bad_value); - return FALSE; + return false; } /* Generate dynamic relcoation only when there is a @@ -2752,6 +2789,11 @@ do_ifunc_pointer: outrel.r_addend = (h->root.u.def.value + h->root.u.def.section->output_section->vma + h->root.u.def.section->output_offset); + + if (htab->params->report_relative_reloc) + _bfd_x86_elf_link_report_relative_reloc + (info, input_section, h, sym, + "R_X86_64_IRELATIVE", &outrel); } else { @@ -2788,7 +2830,7 @@ do_ifunc_pointer: } } -skip_ifunc: + skip_ifunc: resolved_to_zero = (eh != NULL && UNDEFINED_WEAK_RESOLVED_TO_ZERO (info, eh)); @@ -2812,7 +2854,7 @@ skip_ifunc: if (htab->elf.sgot == NULL) abort (); - relative_reloc = FALSE; + relative_reloc = false; if (h != NULL) { off = h->got.offset; @@ -2850,17 +2892,20 @@ skip_ifunc: as -1 | 1 still is -1. */ h->got.offset |= 1; - if (GENERATE_RELATIVE_RELOC_P (info, h)) + /* NB: Don't generate relative relocation here if + it has been generated by DT_RELR. */ + if (!info->enable_dt_relr + && GENERATE_RELATIVE_RELOC_P (info, h)) { /* If this symbol isn't dynamic in PIC, generate R_X86_64_RELATIVE here. */ eh->no_finish_dynamic_symbol = 1; - relative_reloc = TRUE; + relative_reloc = true; } } } else - unresolved_reloc = FALSE; + unresolved_reloc = false; } else { @@ -2880,8 +2925,18 @@ skip_ifunc: base_got->contents + off); local_got_offsets[r_symndx] |= 1; - if (bfd_link_pic (info)) - relative_reloc = TRUE; + /* NB: GOTPCREL relocations against local absolute + symbol store relocation value in the GOT slot + without relative relocation. Don't generate + relative relocation here if it has been generated + by DT_RELR. */ + if (!info->enable_dt_relr + && bfd_link_pic (info) + && !(sym->st_shndx == SHN_ABS + && (r_type == R_X86_64_GOTPCREL + || r_type == R_X86_64_GOTPCRELX + || r_type == R_X86_64_REX_GOTPCRELX))) + relative_reloc = true; } } @@ -2901,6 +2956,12 @@ skip_ifunc: + off); outrel.r_info = htab->r_info (0, R_X86_64_RELATIVE); outrel.r_addend = relocation; + + if (htab->params->report_relative_reloc) + _bfd_x86_elf_link_report_relative_reloc + (info, input_section, h, sym, "R_X86_64_RELATIVE", + &outrel); + elf_append_rela (output_bfd, s, &outrel); } @@ -2954,7 +3015,7 @@ skip_ifunc: " `%s' can not be used when making a shared object"), input_bfd, v, h->root.root.string); bfd_set_error (bfd_error_bad_value); - return FALSE; + return false; } else if (!bfd_link_executable (info) && !SYMBOL_REFERENCES_LOCAL_P (info, h) @@ -2970,7 +3031,7 @@ skip_ifunc: h->type == STT_FUNC ? "function" : "data", h->root.root.string); bfd_set_error (bfd_error_bad_value); - return FALSE; + return false; } } @@ -2988,7 +3049,7 @@ skip_ifunc: /* Use global offset table as symbol value. */ relocation = htab->elf.sgotplt->output_section->vma + htab->elf.sgotplt->output_offset; - unresolved_reloc = FALSE; + unresolved_reloc = false; break; case R_X86_64_PLTOFF64: @@ -3020,7 +3081,7 @@ skip_ifunc: relocation = (resolved_plt->output_section->vma + resolved_plt->output_offset + plt_offset); - unresolved_reloc = FALSE; + unresolved_reloc = false; } relocation -= htab->elf.sgotplt->output_section->vma @@ -3047,7 +3108,7 @@ skip_ifunc: break; } -use_plt: + use_plt: if (h->plt.offset != (bfd_vma) -1) { if (htab->plt_second != NULL) @@ -3071,7 +3132,7 @@ use_plt: relocation = (resolved_plt->output_section->vma + resolved_plt->output_offset + plt_offset); - unresolved_reloc = FALSE; + unresolved_reloc = false; break; case R_X86_64_SIZE32: @@ -3110,9 +3171,11 @@ use_plt: || (no_copyreloc_p && h->def_dynamic && !(h->root.u.def.section->flags & SEC_CODE)))) + || (bfd_link_pie (info) + && h->root.type == bfd_link_hash_undefweak) || bfd_link_dll (info))) { - bfd_boolean fail = FALSE; + bool fail = false; if (SYMBOL_REFERENCES_LOCAL_P (info, h)) { /* Symbol is referenced locally. Make sure it is @@ -3123,9 +3186,10 @@ use_plt: { /* 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; + if (h->root.type == bfd_link_hash_undefweak + || (h->type == STT_FUNC + && (sec->flags & SEC_CODE) != 0)) + fail = true; } else if (no_copyreloc_p || bfd_link_dll (info)) { @@ -3162,7 +3226,7 @@ use_plt: /* FIXME: The ABI says the linker should make sure the value is the same when it's zeroextended to 64 bit. */ -direct: + direct: if ((input_section->flags & SEC_ALLOC) == 0) break; @@ -3172,30 +3236,33 @@ direct: || eh->needs_copy || (h->root.type == bfd_link_hash_undefined)) - && (X86_PCREL_TYPE_P (r_type) - || X86_SIZE_TYPE_P (r_type))); + && (X86_PCREL_TYPE_P (true, r_type) + || X86_SIZE_TYPE_P (true, + r_type))); - if (GENERATE_DYNAMIC_RELOCATION_P (info, eh, r_type, + if (GENERATE_DYNAMIC_RELOCATION_P (true, info, eh, r_type, sec, need_copy_reloc_in_pie, - resolved_to_zero, FALSE)) + resolved_to_zero, false)) { Elf_Internal_Rela outrel; - bfd_boolean skip, relocate; + bool skip, relocate; + bool generate_dynamic_reloc = true; asection *sreloc; + const char *relative_reloc_name = NULL; /* When generating a shared object, these relocations are copied into the output file to be resolved at run time. */ - skip = FALSE; - relocate = FALSE; + skip = false; + relocate = false; outrel.r_offset = _bfd_elf_section_offset (output_bfd, info, input_section, rel->r_offset); if (outrel.r_offset == (bfd_vma) -1) - skip = TRUE; + skip = true; else if (outrel.r_offset == (bfd_vma) -2) - skip = TRUE, relocate = TRUE; + skip = true, relocate = true; outrel.r_offset += (input_section->output_section->vma + input_section->output_offset); @@ -3203,7 +3270,7 @@ direct: if (skip) memset (&outrel, 0, sizeof outrel); - else if (COPY_INPUT_RELOC_P (info, h, r_type)) + else if (COPY_INPUT_RELOC_P (true, info, h, r_type)) { outrel.r_info = htab->r_info (h->dynindx, r_type); outrel.r_addend = rel->r_addend; @@ -3217,17 +3284,27 @@ direct: || (r_type == R_X86_64_32 && htab->params->no_reloc_overflow_check)) { - relocate = TRUE; - outrel.r_info = htab->r_info (0, R_X86_64_RELATIVE); - outrel.r_addend = relocation + rel->r_addend; + relocate = true; + /* NB: Don't generate relative relocation here if + it has been generated by DT_RELR. */ + if (info->enable_dt_relr) + generate_dynamic_reloc = false; + else + { + outrel.r_info = + htab->r_info (0, R_X86_64_RELATIVE); + outrel.r_addend = relocation + rel->r_addend; + relative_reloc_name = "R_X86_64_RELATIVE"; + } } else if (r_type == R_X86_64_64 && !ABI_64_P (output_bfd)) { - relocate = TRUE; + relocate = true; outrel.r_info = htab->r_info (0, R_X86_64_RELATIVE64); outrel.r_addend = relocation + rel->r_addend; + relative_reloc_name = "R_X86_64_RELATIVE64"; /* Check addend overflow. */ if ((outrel.r_addend & 0x80000000) != (rel->r_addend & 0x80000000)) @@ -3248,7 +3325,7 @@ direct: howto->name, name, (uint64_t) rel->r_offset, input_section); bfd_set_error (bfd_error_bad_value); - return FALSE; + return false; } } else @@ -3260,7 +3337,7 @@ direct: else if (sec == NULL || sec->owner == NULL) { bfd_set_error (bfd_error_bad_value); - return FALSE; + return false; } else { @@ -3286,15 +3363,24 @@ direct: } } - sreloc = elf_section_data (input_section)->sreloc; - - if (sreloc == NULL || sreloc->contents == NULL) + if (generate_dynamic_reloc) { - r = bfd_reloc_notsupported; - goto check_relocation_error; - } + sreloc = elf_section_data (input_section)->sreloc; - elf_append_rela (output_bfd, sreloc, &outrel); + if (sreloc == NULL || sreloc->contents == NULL) + { + r = bfd_reloc_notsupported; + goto check_relocation_error; + } + + if (relative_reloc_name + && htab->params->report_relative_reloc) + _bfd_x86_elf_link_report_relative_reloc + (info, input_section, h, sym, + relative_reloc_name, &outrel); + + elf_append_rela (output_bfd, sreloc, &outrel); + } /* If this reloc is against an external symbol, we do not want to fiddle with the addend. Otherwise, we @@ -3321,8 +3407,8 @@ direct: input_section, contents, symtab_hdr, sym_hashes, &r_type_tls, tls_type, rel, - relend, h, r_symndx, TRUE)) - return FALSE; + relend, h, r_symndx, true)) + return false; if (r_type_tls == R_X86_64_TPOFF32) { @@ -3373,11 +3459,11 @@ direct: if (roff < 3 || (roff - 3 + 22) > input_section->size) { -corrupt_input: + corrupt_input: info->callbacks->einfo (_("%F%P: corrupt input: %pB\n"), input_bfd); - return FALSE; + return false; } memcpy (contents + roff - 3, "\x64\x48\x8b\x04\x25\0\0\0\0\x48\x8d\x80" @@ -3575,7 +3661,7 @@ corrupt_input: continue; } else - BFD_ASSERT (FALSE); + BFD_ASSERT (false); } if (htab->elf.sgot == NULL) @@ -3687,7 +3773,7 @@ corrupt_input: else relocation = htab->elf.sgot->output_section->vma + htab->elf.sgot->output_offset + off; - unresolved_reloc = FALSE; + unresolved_reloc = false; } else { @@ -3840,7 +3926,7 @@ corrupt_input: continue; } else - BFD_ASSERT (FALSE); + BFD_ASSERT (false); } break; @@ -3849,8 +3935,8 @@ corrupt_input: input_section, contents, symtab_hdr, sym_hashes, &r_type, GOT_UNKNOWN, rel, - relend, h, r_symndx, TRUE)) - return FALSE; + relend, h, r_symndx, true)) + return false; if (r_type != R_X86_64_TLSLD) { @@ -3970,7 +4056,7 @@ corrupt_input: } relocation = htab->elf.sgot->output_section->vma + htab->elf.sgot->output_offset + off; - unresolved_reloc = FALSE; + unresolved_reloc = false; break; case R_X86_64_DTPOFF32: @@ -4027,16 +4113,16 @@ corrupt_input: (uint64_t) rel->r_offset, howto->name, h->root.root.string); - return FALSE; + return false; } } -do_relocation: + do_relocation: r = _bfd_final_link_relocate (howto, input_bfd, input_section, contents, rel->r_offset, relocation, rel->r_addend); -check_relocation_error: + check_relocation_error: if (r != bfd_reloc_ok) { const char *name; @@ -4049,7 +4135,7 @@ check_relocation_error: symtab_hdr->sh_link, sym->st_name); if (name == NULL) - return FALSE; + return false; if (*name == '\0') name = bfd_section_name (sec); } @@ -4059,8 +4145,13 @@ check_relocation_error: if (converted_reloc) { info->callbacks->einfo - (_("%F%P: failed to convert GOTPCREL relocation; relink with --no-relax\n")); - return FALSE; + ("%X%H:", input_bfd, input_section, rel->r_offset); + info->callbacks->einfo + (_(" failed to convert GOTPCREL relocation against " + "'%s'; relink with --no-relax\n"), + name); + status = false; + continue; } (*info->callbacks->reloc_overflow) (info, (h ? &h->root : NULL), name, howto->name, @@ -4073,7 +4164,7 @@ check_relocation_error: (_("%pB(%pA+%#" PRIx64 "): reloc against `%s': error %d"), input_bfd, input_section, (uint64_t) rel->r_offset, name, (int) r); - return FALSE; + return false; } } @@ -4101,26 +4192,26 @@ check_relocation_error: input_section->reloc_count -= deleted; } - return TRUE; + return status; } /* Finish up dynamic symbol handling. We set the contents of various dynamic sections here. */ -static bfd_boolean +static bool elf_x86_64_finish_dynamic_symbol (bfd *output_bfd, struct bfd_link_info *info, struct elf_link_hash_entry *h, Elf_Internal_Sym *sym) { struct elf_x86_link_hash_table *htab; - bfd_boolean use_plt_second; + bool use_plt_second; struct elf_x86_link_hash_entry *eh; - bfd_boolean local_undefweak; + bool local_undefweak; htab = elf_x86_hash_table (info, X86_64_ELF_DATA); if (htab == NULL) - return FALSE; + return false; /* Use the second PLT section only if there is .plt section. */ use_plt_second = htab->elf.splt != NULL && htab->plt_second != NULL; @@ -4253,6 +4344,11 @@ elf_x86_64_finish_dynamic_symbol (bfd *output_bfd, rela.r_addend = (h->root.u.def.value + h->root.u.def.section->output_section->vma + h->root.u.def.section->output_offset); + + if (htab->params->report_relative_reloc) + _bfd_x86_elf_link_report_relative_reloc + (info, relplt, h, sym, "R_X86_64_IRELATIVE", &rela); + /* R_X86_64_IRELATIVE comes last. */ plt_index = htab->next_irelative_index--; } @@ -4296,7 +4392,7 @@ elf_x86_64_finish_dynamic_symbol (bfd *output_bfd, { bfd_vma got_offset, plt_offset; asection *plt, *got; - bfd_boolean got_after_plt; + bool got_after_plt; int32_t got_pcrel_offset; /* Set the entry in the GOT procedure linkage table. */ @@ -4370,6 +4466,8 @@ elf_x86_64_finish_dynamic_symbol (bfd *output_bfd, { Elf_Internal_Rela rela; asection *relgot = htab->elf.srelgot; + const char *relative_reloc_name = NULL; + bool generate_dynamic_reloc = true; /* This symbol has an entry in the global offset table. Set it up. */ @@ -4408,6 +4506,7 @@ elf_x86_64_finish_dynamic_symbol (bfd *output_bfd, rela.r_addend = (h->root.u.def.value + h->root.u.def.section->output_section->vma + h->root.u.def.section->output_offset); + relative_reloc_name = "R_X86_64_IRELATIVE"; } else goto do_glob_dat; @@ -4442,31 +4541,45 @@ elf_x86_64_finish_dynamic_symbol (bfd *output_bfd, + plt->output_offset + plt_offset), htab->elf.sgot->contents + h->got.offset); - return TRUE; + return true; } } else if (bfd_link_pic (info) && SYMBOL_REFERENCES_LOCAL_P (info, h)) { if (!SYMBOL_DEFINED_NON_SHARED_P (h)) - return FALSE; + return false; BFD_ASSERT((h->got.offset & 1) != 0); - rela.r_info = htab->r_info (0, R_X86_64_RELATIVE); - rela.r_addend = (h->root.u.def.value - + h->root.u.def.section->output_section->vma - + h->root.u.def.section->output_offset); + if (info->enable_dt_relr) + generate_dynamic_reloc = false; + else + { + rela.r_info = htab->r_info (0, R_X86_64_RELATIVE); + rela.r_addend = (h->root.u.def.value + + h->root.u.def.section->output_section->vma + + h->root.u.def.section->output_offset); + relative_reloc_name = "R_X86_64_RELATIVE"; + } } else { BFD_ASSERT((h->got.offset & 1) == 0); -do_glob_dat: + do_glob_dat: bfd_put_64 (output_bfd, (bfd_vma) 0, htab->elf.sgot->contents + h->got.offset); rela.r_info = htab->r_info (h->dynindx, R_X86_64_GLOB_DAT); rela.r_addend = 0; } - elf_append_rela (output_bfd, relgot, &rela); + if (generate_dynamic_reloc) + { + if (relative_reloc_name != NULL + && htab->params->report_relative_reloc) + _bfd_x86_elf_link_report_relative_reloc + (info, relgot, h, sym, relative_reloc_name, &rela); + + elf_append_rela (output_bfd, relgot, &rela); + } } if (h->needs_copy) @@ -4489,13 +4602,13 @@ do_glob_dat: elf_append_rela (output_bfd, s, &rela); } - return TRUE; + return true; } /* Finish up local dynamic symbol handling. We set the contents of various dynamic sections here. */ -static bfd_boolean +static int elf_x86_64_finish_local_dynamic_symbol (void **slot, void *inf) { struct elf_link_hash_entry *h @@ -4511,7 +4624,7 @@ elf_x86_64_finish_local_dynamic_symbol (void **slot, void *inf) here since undefined weak symbol may not be dynamic and may not be called for elf_x86_64_finish_dynamic_symbol. */ -static bfd_boolean +static bool elf_x86_64_pie_finish_undefweak_symbol (struct bfd_hash_entry *bh, void *inf) { @@ -4520,7 +4633,7 @@ elf_x86_64_pie_finish_undefweak_symbol (struct bfd_hash_entry *bh, if (h->root.type != bfd_link_hash_undefweak || h->dynindx != -1) - return TRUE; + return true; return elf_x86_64_finish_dynamic_symbol (info->output_bfd, info, h, NULL); @@ -4577,7 +4690,7 @@ elf_x86_64_reloc_type_class (const struct bfd_link_info *info, /* Finish up the dynamic sections. */ -static bfd_boolean +static bool elf_x86_64_finish_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info) { @@ -4585,13 +4698,21 @@ elf_x86_64_finish_dynamic_sections (bfd *output_bfd, htab = _bfd_x86_elf_finish_dynamic_sections (output_bfd, info); if (htab == NULL) - return FALSE; + return false; if (! htab->elf.dynamic_sections_created) - return TRUE; + return true; if (htab->elf.splt && htab->elf.splt->size > 0) { + if (bfd_is_abs_section (htab->elf.splt->output_section)) + { + info->callbacks->einfo + (_("%F%P: discarded output section: `%pA'\n"), + htab->elf.splt); + return false; + } + elf_section_data (htab->elf.splt->output_section) ->this_hdr.sh_entsize = htab->plt.plt_entry_size; @@ -4627,12 +4748,12 @@ elf_x86_64_finish_dynamic_sections (bfd *output_bfd, + htab->lazy_plt->plt0_got2_offset)); } - if (htab->tlsdesc_plt) + if (htab->elf.tlsdesc_plt) { bfd_put_64 (output_bfd, (bfd_vma) 0, - htab->elf.sgot->contents + htab->tlsdesc_got); + htab->elf.sgot->contents + htab->elf.tlsdesc_got); - memcpy (htab->elf.splt->contents + htab->tlsdesc_plt, + memcpy (htab->elf.splt->contents + htab->elf.tlsdesc_plt, htab->lazy_plt->plt_tlsdesc_entry, htab->lazy_plt->plt_tlsdesc_entry_size); @@ -4645,10 +4766,10 @@ elf_x86_64_finish_dynamic_sections (bfd *output_bfd, + 8 - htab->elf.splt->output_section->vma - htab->elf.splt->output_offset - - htab->tlsdesc_plt + - htab->elf.tlsdesc_plt - htab->lazy_plt->plt_tlsdesc_got1_insn_end), (htab->elf.splt->contents - + htab->tlsdesc_plt + + htab->elf.tlsdesc_plt + 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 @@ -4656,13 +4777,13 @@ elf_x86_64_finish_dynamic_sections (bfd *output_bfd, bfd_put_32 (output_bfd, (htab->elf.sgot->output_section->vma + htab->elf.sgot->output_offset - + htab->tlsdesc_got + + htab->elf.tlsdesc_got - htab->elf.splt->output_section->vma - htab->elf.splt->output_offset - - htab->tlsdesc_plt + - htab->elf.tlsdesc_plt - htab->lazy_plt->plt_tlsdesc_got2_insn_end), (htab->elf.splt->contents - + htab->tlsdesc_plt + + htab->elf.tlsdesc_plt + htab->lazy_plt->plt_tlsdesc_got2_offset)); } } @@ -4673,7 +4794,7 @@ elf_x86_64_finish_dynamic_sections (bfd *output_bfd, elf_x86_64_pie_finish_undefweak_symbol, info); - return TRUE; + return true; } /* Fill PLT/GOT entries and allocate dynamic relocations for local @@ -4681,7 +4802,7 @@ elf_x86_64_finish_dynamic_sections (bfd *output_bfd, It has to be done before elf_link_sort_relocs is called so that dynamic relocations are properly sorted. */ -static bfd_boolean +static bool elf_x86_64_output_arch_local_syms (bfd *output_bfd ATTRIBUTE_UNUSED, struct bfd_link_info *info, @@ -4694,19 +4815,16 @@ elf_x86_64_output_arch_local_syms struct elf_x86_link_hash_table *htab = elf_x86_hash_table (info, X86_64_ELF_DATA); if (htab == NULL) - return FALSE; + return false; /* Fill PLT and GOT entries for local STT_GNU_IFUNC symbols. */ htab_traverse (htab->loc_hash_table, elf_x86_64_finish_local_dynamic_symbol, info); - return TRUE; + return true; } -/* Forward declaration. */ -static const struct elf_x86_lazy_plt_layout elf_x86_64_nacl_plt; - /* Similar to _bfd_elf_get_synthetic_symtab. Support PLTs with all dynamic relocations. */ @@ -4751,31 +4869,19 @@ elf_x86_64_get_synthetic_symtab (bfd *abfd, if (relsize <= 0) return -1; - if (get_elf_x86_backend_data (abfd)->target_os != is_nacl) + lazy_plt = &elf_x86_64_lazy_plt; + non_lazy_plt = &elf_x86_64_non_lazy_plt; + lazy_bnd_plt = &elf_x86_64_lazy_bnd_plt; + non_lazy_bnd_plt = &elf_x86_64_non_lazy_bnd_plt; + if (ABI_64_P (abfd)) { - lazy_plt = &elf_x86_64_lazy_plt; - non_lazy_plt = &elf_x86_64_non_lazy_plt; - lazy_bnd_plt = &elf_x86_64_lazy_bnd_plt; - non_lazy_bnd_plt = &elf_x86_64_non_lazy_bnd_plt; - if (ABI_64_P (abfd)) - { - lazy_ibt_plt = &elf_x86_64_lazy_ibt_plt; - non_lazy_ibt_plt = &elf_x86_64_non_lazy_ibt_plt; - } - else - { - lazy_ibt_plt = &elf_x32_lazy_ibt_plt; - non_lazy_ibt_plt = &elf_x32_non_lazy_ibt_plt; - } + lazy_ibt_plt = &elf_x86_64_lazy_ibt_plt; + non_lazy_ibt_plt = &elf_x86_64_non_lazy_ibt_plt; } else { - lazy_plt = &elf_x86_64_nacl_plt; - non_lazy_plt = NULL; - lazy_bnd_plt = NULL; - non_lazy_bnd_plt = NULL; - lazy_ibt_plt = NULL; - non_lazy_ibt_plt = NULL; + lazy_ibt_plt = &elf_x32_lazy_ibt_plt; + non_lazy_ibt_plt = &elf_x32_non_lazy_ibt_plt; } count = 0; @@ -4786,15 +4892,8 @@ elf_x86_64_get_synthetic_symtab (bfd *abfd, continue; /* Get the PLT section contents. */ - plt_contents = (bfd_byte *) bfd_malloc (plt->size); - if (plt_contents == NULL) + if (!bfd_malloc_and_get_section (abfd, plt, &plt_contents)) break; - if (!bfd_get_section_contents (abfd, (asection *) plt, - plt_contents, 0, plt->size)) - { - free (plt_contents); - break; - } /* Check what kind of PLT it is. */ plt_type = plt_unknown; @@ -4906,24 +5005,24 @@ elf_x86_64_get_synthetic_symtab (bfd *abfd, /* Handle an x86-64 specific section when reading an object file. This is called when elfcode.h finds a section with an unknown type. */ -static bfd_boolean +static bool elf_x86_64_section_from_shdr (bfd *abfd, Elf_Internal_Shdr *hdr, const char *name, int shindex) { if (hdr->sh_type != SHT_X86_64_UNWIND) - return FALSE; + return false; if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex)) - return FALSE; + return false; - return TRUE; + return true; } /* Hook called by the linker routine which adds symbols from an object file. We use it to put SHN_X86_64_LCOMMON items in .lbss, instead of .bss. */ -static bfd_boolean +static bool elf_x86_64_add_symbol_hook (bfd *abfd, struct bfd_link_info *info ATTRIBUTE_UNUSED, Elf_Internal_Sym *sym, @@ -4946,31 +5045,31 @@ elf_x86_64_add_symbol_hook (bfd *abfd, | SEC_IS_COMMON | SEC_LINKER_CREATED)); if (lcomm == NULL) - return FALSE; + return false; elf_section_flags (lcomm) |= SHF_X86_64_LARGE; } *secp = lcomm; *valp = sym->st_size; - return TRUE; + return true; } - return TRUE; + return true; } /* Given a BFD section, try to locate the corresponding ELF section index. */ -static bfd_boolean +static bool elf_x86_64_elf_section_from_bfd_section (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, int *index_return) { if (sec == &_bfd_elf_large_com_section) { *index_return = SHN_X86_64_LCOMMON; - return TRUE; + return true; } - return FALSE; + return false; } /* Process a symbol. */ @@ -4992,7 +5091,7 @@ elf_x86_64_symbol_processing (bfd *abfd ATTRIBUTE_UNUSED, } } -static bfd_boolean +static bool elf_x86_64_common_definition (Elf_Internal_Sym *sym) { return (sym->st_shndx == SHN_COMMON @@ -5017,12 +5116,12 @@ elf_x86_64_common_section (asection *sec) return &_bfd_elf_large_com_section; } -static bfd_boolean +static bool elf_x86_64_merge_symbol (struct elf_link_hash_entry *h, const Elf_Internal_Sym *sym, asection **psec, - bfd_boolean newdef, - bfd_boolean olddef, + bool newdef, + bool olddef, bfd *oldbfd, const asection *oldsec) { @@ -5047,7 +5146,7 @@ elf_x86_64_merge_symbol (struct elf_link_hash_entry *h, *psec = bfd_com_section_ptr; } - return TRUE; + return true; } static int @@ -5074,7 +5173,7 @@ elf_x86_64_additional_program_headers (bfd *abfd, /* Return TRUE iff relocations for INPUT are compatible with OUTPUT. */ -static bfd_boolean +static bool elf_x86_64_relocs_compatible (const bfd_target *input, const bfd_target *output) { @@ -5090,6 +5189,8 @@ static bfd * elf_x86_64_link_setup_gnu_properties (struct bfd_link_info *info) { struct elf_x86_init_table init_table; + const struct elf_backend_data *bed; + struct elf_x86_link_hash_table *htab; if ((int) R_X86_64_standard >= (int) R_X86_64_converted_reloc_bit || (int) R_X86_64_max <= (int) R_X86_64_converted_reloc_bit @@ -5102,42 +5203,30 @@ elf_x86_64_link_setup_gnu_properties (struct bfd_link_info *info) /* This is unused for x86-64. */ init_table.plt0_pad_byte = 0x90; - if (get_elf_x86_backend_data (info->output_bfd)->target_os != is_nacl) + bed = get_elf_backend_data (info->output_bfd); + htab = elf_x86_hash_table (info, bed->target_id); + if (!htab) + abort (); + if (htab->params->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; - } - else - { - init_table.lazy_plt = &elf_x86_64_lazy_plt; - init_table.non_lazy_plt = &elf_x86_64_non_lazy_plt; - } + init_table.lazy_plt = &elf_x86_64_lazy_bnd_plt; + init_table.non_lazy_plt = &elf_x86_64_non_lazy_bnd_plt; + } + else + { + init_table.lazy_plt = &elf_x86_64_lazy_plt; + init_table.non_lazy_plt = &elf_x86_64_non_lazy_plt; + } - if (ABI_64_P (info->output_bfd)) - { - init_table.lazy_ibt_plt = &elf_x86_64_lazy_ibt_plt; - init_table.non_lazy_ibt_plt = &elf_x86_64_non_lazy_ibt_plt; - } - else - { - init_table.lazy_ibt_plt = &elf_x32_lazy_ibt_plt; - init_table.non_lazy_ibt_plt = &elf_x32_non_lazy_ibt_plt; - } + if (ABI_64_P (info->output_bfd)) + { + init_table.lazy_ibt_plt = &elf_x86_64_lazy_ibt_plt; + init_table.non_lazy_ibt_plt = &elf_x86_64_non_lazy_ibt_plt; } else { - init_table.lazy_plt = &elf_x86_64_nacl_plt; - init_table.non_lazy_plt = NULL; - init_table.lazy_ibt_plt = NULL; - init_table.non_lazy_ibt_plt = NULL; + init_table.lazy_ibt_plt = &elf_x32_lazy_ibt_plt; + init_table.non_lazy_ibt_plt = &elf_x32_non_lazy_ibt_plt; } if (ABI_64_P (info->output_bfd)) @@ -5176,7 +5265,6 @@ elf_x86_64_special_sections[]= #else # define ELF_MAXPAGESIZE 0x200000 #endif -#define ELF_MINPAGESIZE 0x1000 #define ELF_COMMONPAGESIZE 0x1000 #define elf_backend_can_gc_sections 1 @@ -5199,7 +5287,7 @@ elf_x86_64_special_sections[]= elf_x86_64_reloc_name_lookup #define elf_backend_relocs_compatible elf_x86_64_relocs_compatible -#define elf_backend_check_relocs elf_x86_64_check_relocs +#define elf_backend_always_size_sections elf_x86_64_always_size_sections #define elf_backend_create_dynamic_sections _bfd_elf_create_dynamic_sections #define elf_backend_finish_dynamic_sections elf_x86_64_finish_dynamic_sections #define elf_backend_finish_dynamic_symbol elf_x86_64_finish_dynamic_symbol @@ -5283,13 +5371,8 @@ elf_x86_64_special_sections[]= #undef TARGET_LITTLE_NAME #define TARGET_LITTLE_NAME "elf64-x86-64-sol2" -static const struct elf_x86_backend_data elf_x86_64_solaris_arch_bed = - { - is_solaris /* os */ - }; - -#undef elf_backend_arch_data -#define elf_backend_arch_data &elf_x86_64_solaris_arch_bed +#undef ELF_TARGET_OS +#define ELF_TARGET_OS is_solaris /* Restore default: we cannot use ELFOSABI_SOLARIS, otherwise ELFOSABI_NONE objects won't be recognized. */ @@ -5313,7 +5396,7 @@ static const struct elf_x86_backend_data elf_x86_64_solaris_arch_bed = #undef elf_backend_strtab_flags #define elf_backend_strtab_flags SHF_STRINGS -static bfd_boolean +static bool elf64_x86_64_copy_solaris_special_section_fields (const bfd *ibfd ATTRIBUTE_UNUSED, bfd *obfd ATTRIBUTE_UNUSED, const Elf_Internal_Shdr *isection ATTRIBUTE_UNUSED, @@ -5321,7 +5404,7 @@ elf64_x86_64_copy_solaris_special_section_fields (const bfd *ibfd ATTRIBUTE_UNUS { /* PR 19938: FIXME: Need to add code for setting the sh_info and sh_link fields of Solaris specific section types. */ - return FALSE; + return false; } #undef elf_backend_copy_special_section_fields @@ -5329,30 +5412,6 @@ elf64_x86_64_copy_solaris_special_section_fields (const bfd *ibfd ATTRIBUTE_UNUS #include "elf64-target.h" -/* Native Client support. */ - -static bfd_boolean -elf64_x86_64_nacl_elf_object_p (bfd *abfd) -{ - /* Set the right machine number for a NaCl x86-64 ELF64 file. */ - bfd_default_set_arch_mach (abfd, bfd_arch_i386, bfd_mach_x86_64_nacl); - return TRUE; -} - -#undef TARGET_LITTLE_SYM -#define TARGET_LITTLE_SYM x86_64_elf64_nacl_vec -#undef TARGET_LITTLE_NAME -#define TARGET_LITTLE_NAME "elf64-x86-64-nacl" -#undef elf64_bed -#define elf64_bed elf64_x86_64_nacl_bed - -#undef ELF_MAXPAGESIZE -#undef ELF_MINPAGESIZE -#undef ELF_COMMONPAGESIZE -#define ELF_MAXPAGESIZE 0x10000 -#define ELF_MINPAGESIZE 0x10000 -#define ELF_COMMONPAGESIZE 0x10000 - /* Restore defaults. */ #undef ELF_OSABI #undef elf_backend_static_tls_alignment @@ -5361,304 +5420,6 @@ elf64_x86_64_nacl_elf_object_p (bfd *abfd) #undef elf_backend_strtab_flags #undef elf_backend_copy_special_section_fields -/* NaCl uses substantially different PLT entries for the same effects. */ - -#undef elf_backend_plt_alignment -#define elf_backend_plt_alignment 5 -#define NACL_PLT_ENTRY_SIZE 64 -#define NACLMASK 0xe0 /* 32-byte alignment mask. */ - -static const bfd_byte elf_x86_64_nacl_plt0_entry[NACL_PLT_ENTRY_SIZE] = - { - 0xff, 0x35, 8, 0, 0, 0, /* pushq GOT+8(%rip) */ - 0x4c, 0x8b, 0x1d, 16, 0, 0, 0, /* mov GOT+16(%rip), %r11 */ - 0x41, 0x83, 0xe3, NACLMASK, /* and $-32, %r11d */ - 0x4d, 0x01, 0xfb, /* add %r15, %r11 */ - 0x41, 0xff, 0xe3, /* jmpq *%r11 */ - - /* 9-byte nop sequence to pad out to the next 32-byte boundary. */ - 0x66, 0x0f, 0x1f, 0x84, 0, 0, 0, 0, 0, /* nopw 0x0(%rax,%rax,1) */ - - /* 32 bytes of nop to pad out to the standard size. */ - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, /* excess data16 prefixes */ - 0x2e, 0x0f, 0x1f, 0x84, 0, 0, 0, 0, 0, /* nopw %cs:0x0(%rax,%rax,1) */ - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, /* excess data16 prefixes */ - 0x2e, 0x0f, 0x1f, 0x84, 0, 0, 0, 0, 0, /* nopw %cs:0x0(%rax,%rax,1) */ - 0x66, /* excess data16 prefix */ - 0x90 /* nop */ - }; - -static const bfd_byte elf_x86_64_nacl_plt_entry[NACL_PLT_ENTRY_SIZE] = - { - 0x4c, 0x8b, 0x1d, 0, 0, 0, 0, /* mov name@GOTPCREL(%rip),%r11 */ - 0x41, 0x83, 0xe3, NACLMASK, /* and $-32, %r11d */ - 0x4d, 0x01, 0xfb, /* add %r15, %r11 */ - 0x41, 0xff, 0xe3, /* jmpq *%r11 */ - - /* 15-byte nop sequence to pad out to the next 32-byte boundary. */ - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, /* excess data16 prefixes */ - 0x2e, 0x0f, 0x1f, 0x84, 0, 0, 0, 0, 0, /* nopw %cs:0x0(%rax,%rax,1) */ - - /* Lazy GOT entries point here (32-byte aligned). */ - 0x68, /* pushq immediate */ - 0, 0, 0, 0, /* replaced with index into relocation table. */ - 0xe9, /* jmp relative */ - 0, 0, 0, 0, /* replaced with offset to start of .plt0. */ - - /* 22 bytes of nop to pad out to the standard size. */ - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, /* excess data16 prefixes */ - 0x2e, 0x0f, 0x1f, 0x84, 0, 0, 0, 0, 0, /* nopw %cs:0x0(%rax,%rax,1) */ - 0x0f, 0x1f, 0x80, 0, 0, 0, 0, /* nopl 0x0(%rax) */ - }; - -/* .eh_frame covering the .plt section. */ - -static const bfd_byte elf_x86_64_nacl_eh_frame_plt[] = - { -#if (PLT_CIE_LENGTH != 20 \ - || PLT_FDE_LENGTH != 36 \ - || PLT_FDE_START_OFFSET != 4 + PLT_CIE_LENGTH + 8 \ - || PLT_FDE_LEN_OFFSET != 4 + PLT_CIE_LENGTH + 12) -# error "Need elf_x86_backend_data parameters for eh_frame_plt offsets!" -#endif - PLT_CIE_LENGTH, 0, 0, 0, /* CIE length */ - 0, 0, 0, 0, /* CIE ID */ - 1, /* CIE version */ - 'z', 'R', 0, /* Augmentation string */ - 1, /* Code alignment factor */ - 0x78, /* Data alignment factor */ - 16, /* Return address column */ - 1, /* Augmentation size */ - DW_EH_PE_pcrel | DW_EH_PE_sdata4, /* FDE encoding */ - DW_CFA_def_cfa, 7, 8, /* DW_CFA_def_cfa: r7 (rsp) ofs 8 */ - DW_CFA_offset + 16, 1, /* DW_CFA_offset: r16 (rip) at cfa-8 */ - DW_CFA_nop, DW_CFA_nop, - - PLT_FDE_LENGTH, 0, 0, 0, /* FDE length */ - PLT_CIE_LENGTH + 8, 0, 0, 0,/* CIE pointer */ - 0, 0, 0, 0, /* R_X86_64_PC32 .plt goes here */ - 0, 0, 0, 0, /* .plt size goes here */ - 0, /* Augmentation size */ - DW_CFA_def_cfa_offset, 16, /* DW_CFA_def_cfa_offset: 16 */ - DW_CFA_advance_loc + 6, /* DW_CFA_advance_loc: 6 to __PLT__+6 */ - DW_CFA_def_cfa_offset, 24, /* DW_CFA_def_cfa_offset: 24 */ - DW_CFA_advance_loc + 58, /* DW_CFA_advance_loc: 58 to __PLT__+64 */ - DW_CFA_def_cfa_expression, /* DW_CFA_def_cfa_expression */ - 13, /* Block length */ - DW_OP_breg7, 8, /* DW_OP_breg7 (rsp): 8 */ - DW_OP_breg16, 0, /* DW_OP_breg16 (rip): 0 */ - DW_OP_const1u, 63, DW_OP_and, DW_OP_const1u, 37, DW_OP_ge, - DW_OP_lit3, DW_OP_shl, DW_OP_plus, - DW_CFA_nop, DW_CFA_nop - }; - -static const struct elf_x86_lazy_plt_layout elf_x86_64_nacl_plt = - { - elf_x86_64_nacl_plt0_entry, /* plt0_entry */ - 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 */ - 3, /* plt_got_offset */ - 33, /* plt_reloc_offset */ - 38, /* plt_plt_offset */ - 7, /* plt_got_insn_size */ - 42, /* plt_plt_insn_end */ - 32, /* plt_lazy_offset */ - elf_x86_64_nacl_plt0_entry, /* pic_plt0_entry */ - elf_x86_64_nacl_plt_entry, /* pic_plt_entry */ - elf_x86_64_nacl_eh_frame_plt, /* eh_frame_plt */ - sizeof (elf_x86_64_nacl_eh_frame_plt) /* eh_frame_plt_size */ - }; - -static const struct elf_x86_backend_data elf_x86_64_nacl_arch_bed = - { - is_nacl /* os */ - }; - -#undef elf_backend_arch_data -#define elf_backend_arch_data &elf_x86_64_nacl_arch_bed - -#undef elf_backend_object_p -#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_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 - -#include "elf64-target.h" - -/* Native Client x32 support. */ - -static bfd_boolean -elf32_x86_64_nacl_elf_object_p (bfd *abfd) -{ - /* Set the right machine number for a NaCl x86-64 ELF32 file. */ - bfd_default_set_arch_mach (abfd, bfd_arch_i386, bfd_mach_x64_32_nacl); - return TRUE; -} - -#undef TARGET_LITTLE_SYM -#define TARGET_LITTLE_SYM x86_64_elf32_nacl_vec -#undef TARGET_LITTLE_NAME -#define TARGET_LITTLE_NAME "elf32-x86-64-nacl" -#undef elf32_bed -#define elf32_bed elf32_x86_64_nacl_bed - -#define bfd_elf32_bfd_reloc_type_lookup \ - elf_x86_64_reloc_type_lookup -#define bfd_elf32_bfd_reloc_name_lookup \ - elf_x86_64_reloc_name_lookup -#define bfd_elf32_get_synthetic_symtab \ - elf_x86_64_get_synthetic_symtab - -#undef elf_backend_object_p -#define elf_backend_object_p \ - elf32_x86_64_nacl_elf_object_p - -#undef elf_backend_bfd_from_remote_memory -#define elf_backend_bfd_from_remote_memory \ - _bfd_elf32_bfd_from_remote_memory - -#undef elf_backend_size_info -#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_backend_object_p -#define elf_backend_object_p elf64_x86_64_elf_object_p -#undef elf_backend_bfd_from_remote_memory -#undef elf_backend_size_info -#undef elf_backend_modify_segment_map -#undef elf_backend_modify_headers -#undef elf_backend_final_write_processing - -/* Intel L1OM support. */ - -static bfd_boolean -elf64_l1om_elf_object_p (bfd *abfd) -{ - /* Set the right machine number for an L1OM elf64 file. */ - bfd_default_set_arch_mach (abfd, bfd_arch_l1om, bfd_mach_l1om); - return TRUE; -} - -#undef TARGET_LITTLE_SYM -#define TARGET_LITTLE_SYM l1om_elf64_vec -#undef TARGET_LITTLE_NAME -#define TARGET_LITTLE_NAME "elf64-l1om" -#undef ELF_ARCH -#define ELF_ARCH bfd_arch_l1om - -#undef ELF_MACHINE_CODE -#define ELF_MACHINE_CODE EM_L1OM - -#undef ELF_OSABI - -#undef elf64_bed -#define elf64_bed elf64_l1om_bed - -#undef elf_backend_object_p -#define elf_backend_object_p elf64_l1om_elf_object_p - -/* Restore defaults. */ -#undef ELF_MAXPAGESIZE -#undef ELF_MINPAGESIZE -#undef ELF_COMMONPAGESIZE -#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 -#define elf_backend_plt_alignment 4 -#undef elf_backend_arch_data -#define elf_backend_arch_data &elf_x86_64_arch_bed - -#include "elf64-target.h" - -/* FreeBSD L1OM support. */ - -#undef TARGET_LITTLE_SYM -#define TARGET_LITTLE_SYM l1om_elf64_fbsd_vec -#undef TARGET_LITTLE_NAME -#define TARGET_LITTLE_NAME "elf64-l1om-freebsd" - -#undef ELF_OSABI -#define ELF_OSABI ELFOSABI_FREEBSD - -#undef elf64_bed -#define elf64_bed elf64_l1om_fbsd_bed - -#include "elf64-target.h" - -/* Intel K1OM support. */ - -static bfd_boolean -elf64_k1om_elf_object_p (bfd *abfd) -{ - /* Set the right machine number for an K1OM elf64 file. */ - bfd_default_set_arch_mach (abfd, bfd_arch_k1om, bfd_mach_k1om); - return TRUE; -} - -#undef TARGET_LITTLE_SYM -#define TARGET_LITTLE_SYM k1om_elf64_vec -#undef TARGET_LITTLE_NAME -#define TARGET_LITTLE_NAME "elf64-k1om" -#undef ELF_ARCH -#define ELF_ARCH bfd_arch_k1om - -#undef ELF_MACHINE_CODE -#define ELF_MACHINE_CODE EM_K1OM - -#undef ELF_OSABI - -#undef elf64_bed -#define elf64_bed elf64_k1om_bed - -#undef elf_backend_object_p -#define elf_backend_object_p elf64_k1om_elf_object_p - -#undef elf_backend_static_tls_alignment - -#undef elf_backend_want_plt_sym -#define elf_backend_want_plt_sym 0 - -#include "elf64-target.h" - -/* FreeBSD K1OM support. */ - -#undef TARGET_LITTLE_SYM -#define TARGET_LITTLE_SYM k1om_elf64_fbsd_vec -#undef TARGET_LITTLE_NAME -#define TARGET_LITTLE_NAME "elf64-k1om-freebsd" - -#undef ELF_OSABI -#define ELF_OSABI ELFOSABI_FREEBSD - -#undef elf64_bed -#define elf64_bed elf64_k1om_fbsd_bed - -#include "elf64-target.h" - /* 32bit x86-64 support. */ #undef TARGET_LITTLE_SYM @@ -5666,6 +5427,7 @@ elf64_k1om_elf_object_p (bfd *abfd) #undef TARGET_LITTLE_NAME #define TARGET_LITTLE_NAME "elf32-x86-64" #undef elf32_bed +#define elf32_bed elf32_x86_64_bed #undef ELF_ARCH #define ELF_ARCH bfd_arch_i386 @@ -5673,8 +5435,16 @@ elf64_k1om_elf_object_p (bfd *abfd) #undef ELF_MACHINE_CODE #define ELF_MACHINE_CODE EM_X86_64 +#undef ELF_TARGET_OS #undef ELF_OSABI +#define bfd_elf32_bfd_reloc_type_lookup \ + elf_x86_64_reloc_type_lookup +#define bfd_elf32_bfd_reloc_name_lookup \ + elf_x86_64_reloc_name_lookup +#define bfd_elf32_get_synthetic_symtab \ + elf_x86_64_get_synthetic_symtab + #undef elf_backend_object_p #define elf_backend_object_p \ elf32_x86_64_elf_object_p