X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=bfd%2Felf32-i386.c;h=fb5ed161f50c4cde39e8d7b24fe843fe18aaad09;hb=924cf858c94ebc3f54e1e2e0710099fb94e2c901;hp=a0d428565960a5dc4e742eab3b8385d76b8ffa85;hpb=a6798baba212170e427d2f9bd99af12f1078b162;p=binutils-gdb.git diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c index a0d42856596..fb5ed161f50 100644 --- a/bfd/elf32-i386.c +++ b/bfd/elf32-i386.c @@ -1,5 +1,5 @@ /* Intel 80386/80486-specific support for 32-bit ELF - Copyright (C) 1993-2017 Free Software Foundation, Inc. + Copyright (C) 1993-2022 Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. @@ -19,7 +19,6 @@ MA 02110-1301, USA. */ #include "elfxx-x86.h" -#include "elf-nacl.h" #include "elf-vxworks.h" #include "dwarf2.h" #include "opcode/i386.h" @@ -27,43 +26,41 @@ /* 386 uses REL relocations instead of RELA. */ #define USE_REL 1 -#include "elf/i386.h" - static reloc_howto_type elf_howto_table[]= { - HOWTO(R_386_NONE, 0, 3, 0, FALSE, 0, complain_overflow_dont, + HOWTO(R_386_NONE, 0, 3, 0, false, 0, complain_overflow_dont, bfd_elf_generic_reloc, "R_386_NONE", - TRUE, 0x00000000, 0x00000000, FALSE), - HOWTO(R_386_32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, + true, 0x00000000, 0x00000000, false), + HOWTO(R_386_32, 0, 2, 32, false, 0, complain_overflow_dont, bfd_elf_generic_reloc, "R_386_32", - TRUE, 0xffffffff, 0xffffffff, FALSE), - HOWTO(R_386_PC32, 0, 2, 32, TRUE, 0, complain_overflow_bitfield, + true, 0xffffffff, 0xffffffff, false), + HOWTO(R_386_PC32, 0, 2, 32, true, 0, complain_overflow_dont, bfd_elf_generic_reloc, "R_386_PC32", - TRUE, 0xffffffff, 0xffffffff, TRUE), - HOWTO(R_386_GOT32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, + true, 0xffffffff, 0xffffffff, true), + HOWTO(R_386_GOT32, 0, 2, 32, false, 0, complain_overflow_dont, bfd_elf_generic_reloc, "R_386_GOT32", - TRUE, 0xffffffff, 0xffffffff, FALSE), - HOWTO(R_386_PLT32, 0, 2, 32, TRUE, 0, complain_overflow_bitfield, + true, 0xffffffff, 0xffffffff, false), + HOWTO(R_386_PLT32, 0, 2, 32, true, 0, complain_overflow_dont, bfd_elf_generic_reloc, "R_386_PLT32", - TRUE, 0xffffffff, 0xffffffff, TRUE), - HOWTO(R_386_COPY, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, + true, 0xffffffff, 0xffffffff, true), + HOWTO(R_386_COPY, 0, 2, 32, false, 0, complain_overflow_dont, bfd_elf_generic_reloc, "R_386_COPY", - TRUE, 0xffffffff, 0xffffffff, FALSE), - HOWTO(R_386_GLOB_DAT, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, + true, 0xffffffff, 0xffffffff, false), + HOWTO(R_386_GLOB_DAT, 0, 2, 32, false, 0, complain_overflow_dont, bfd_elf_generic_reloc, "R_386_GLOB_DAT", - TRUE, 0xffffffff, 0xffffffff, FALSE), - HOWTO(R_386_JUMP_SLOT, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, + true, 0xffffffff, 0xffffffff, false), + HOWTO(R_386_JUMP_SLOT, 0, 2, 32, false, 0, complain_overflow_dont, bfd_elf_generic_reloc, "R_386_JUMP_SLOT", - TRUE, 0xffffffff, 0xffffffff, FALSE), - HOWTO(R_386_RELATIVE, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, + true, 0xffffffff, 0xffffffff, false), + HOWTO(R_386_RELATIVE, 0, 2, 32, false, 0, complain_overflow_dont, bfd_elf_generic_reloc, "R_386_RELATIVE", - TRUE, 0xffffffff, 0xffffffff, FALSE), - HOWTO(R_386_GOTOFF, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, + true, 0xffffffff, 0xffffffff, false), + HOWTO(R_386_GOTOFF, 0, 2, 32, false, 0, complain_overflow_dont, bfd_elf_generic_reloc, "R_386_GOTOFF", - TRUE, 0xffffffff, 0xffffffff, FALSE), - HOWTO(R_386_GOTPC, 0, 2, 32, TRUE, 0, complain_overflow_bitfield, + true, 0xffffffff, 0xffffffff, false), + HOWTO(R_386_GOTPC, 0, 2, 32, true, 0, complain_overflow_dont, bfd_elf_generic_reloc, "R_386_GOTPC", - TRUE, 0xffffffff, 0xffffffff, TRUE), + true, 0xffffffff, 0xffffffff, true), /* We have a gap in the reloc numbers here. R_386_standard counts the number up to this point, and @@ -73,76 +70,76 @@ static reloc_howto_type elf_howto_table[]= #define R_386_ext_offset (R_386_TLS_TPOFF - R_386_standard) /* These relocs are a GNU extension. */ - HOWTO(R_386_TLS_TPOFF, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, + HOWTO(R_386_TLS_TPOFF, 0, 2, 32, false, 0, complain_overflow_dont, bfd_elf_generic_reloc, "R_386_TLS_TPOFF", - TRUE, 0xffffffff, 0xffffffff, FALSE), - HOWTO(R_386_TLS_IE, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, + true, 0xffffffff, 0xffffffff, false), + HOWTO(R_386_TLS_IE, 0, 2, 32, false, 0, complain_overflow_dont, bfd_elf_generic_reloc, "R_386_TLS_IE", - TRUE, 0xffffffff, 0xffffffff, FALSE), - HOWTO(R_386_TLS_GOTIE, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, + true, 0xffffffff, 0xffffffff, false), + HOWTO(R_386_TLS_GOTIE, 0, 2, 32, false, 0, complain_overflow_dont, bfd_elf_generic_reloc, "R_386_TLS_GOTIE", - TRUE, 0xffffffff, 0xffffffff, FALSE), - HOWTO(R_386_TLS_LE, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, + true, 0xffffffff, 0xffffffff, false), + HOWTO(R_386_TLS_LE, 0, 2, 32, false, 0, complain_overflow_dont, bfd_elf_generic_reloc, "R_386_TLS_LE", - TRUE, 0xffffffff, 0xffffffff, FALSE), - HOWTO(R_386_TLS_GD, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, + true, 0xffffffff, 0xffffffff, false), + HOWTO(R_386_TLS_GD, 0, 2, 32, false, 0, complain_overflow_dont, bfd_elf_generic_reloc, "R_386_TLS_GD", - TRUE, 0xffffffff, 0xffffffff, FALSE), - HOWTO(R_386_TLS_LDM, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, + true, 0xffffffff, 0xffffffff, false), + HOWTO(R_386_TLS_LDM, 0, 2, 32, false, 0, complain_overflow_dont, bfd_elf_generic_reloc, "R_386_TLS_LDM", - TRUE, 0xffffffff, 0xffffffff, FALSE), - HOWTO(R_386_16, 0, 1, 16, FALSE, 0, complain_overflow_bitfield, + true, 0xffffffff, 0xffffffff, false), + HOWTO(R_386_16, 0, 1, 16, false, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_386_16", - TRUE, 0xffff, 0xffff, FALSE), - HOWTO(R_386_PC16, 0, 1, 16, TRUE, 0, complain_overflow_bitfield, + true, 0xffff, 0xffff, false), + HOWTO(R_386_PC16, 0, 1, 16, true, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_386_PC16", - TRUE, 0xffff, 0xffff, TRUE), - HOWTO(R_386_8, 0, 0, 8, FALSE, 0, complain_overflow_bitfield, + true, 0xffff, 0xffff, true), + HOWTO(R_386_8, 0, 0, 8, false, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_386_8", - TRUE, 0xff, 0xff, FALSE), - HOWTO(R_386_PC8, 0, 0, 8, TRUE, 0, complain_overflow_signed, + true, 0xff, 0xff, false), + HOWTO(R_386_PC8, 0, 0, 8, true, 0, complain_overflow_signed, bfd_elf_generic_reloc, "R_386_PC8", - TRUE, 0xff, 0xff, TRUE), + true, 0xff, 0xff, true), #define R_386_ext (R_386_PC8 + 1 - R_386_ext_offset) #define R_386_tls_offset (R_386_TLS_LDO_32 - R_386_ext) /* These are common with Solaris TLS implementation. */ - HOWTO(R_386_TLS_LDO_32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, + HOWTO(R_386_TLS_LDO_32, 0, 2, 32, false, 0, complain_overflow_dont, bfd_elf_generic_reloc, "R_386_TLS_LDO_32", - TRUE, 0xffffffff, 0xffffffff, FALSE), - HOWTO(R_386_TLS_IE_32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, + true, 0xffffffff, 0xffffffff, false), + HOWTO(R_386_TLS_IE_32, 0, 2, 32, false, 0, complain_overflow_dont, bfd_elf_generic_reloc, "R_386_TLS_IE_32", - TRUE, 0xffffffff, 0xffffffff, FALSE), - HOWTO(R_386_TLS_LE_32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, + true, 0xffffffff, 0xffffffff, false), + HOWTO(R_386_TLS_LE_32, 0, 2, 32, false, 0, complain_overflow_dont, bfd_elf_generic_reloc, "R_386_TLS_LE_32", - TRUE, 0xffffffff, 0xffffffff, FALSE), - HOWTO(R_386_TLS_DTPMOD32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, + true, 0xffffffff, 0xffffffff, false), + HOWTO(R_386_TLS_DTPMOD32, 0, 2, 32, false, 0, complain_overflow_dont, bfd_elf_generic_reloc, "R_386_TLS_DTPMOD32", - TRUE, 0xffffffff, 0xffffffff, FALSE), - HOWTO(R_386_TLS_DTPOFF32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, + true, 0xffffffff, 0xffffffff, false), + HOWTO(R_386_TLS_DTPOFF32, 0, 2, 32, false, 0, complain_overflow_dont, bfd_elf_generic_reloc, "R_386_TLS_DTPOFF32", - TRUE, 0xffffffff, 0xffffffff, FALSE), - HOWTO(R_386_TLS_TPOFF32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, + true, 0xffffffff, 0xffffffff, false), + HOWTO(R_386_TLS_TPOFF32, 0, 2, 32, false, 0, complain_overflow_dont, bfd_elf_generic_reloc, "R_386_TLS_TPOFF32", - TRUE, 0xffffffff, 0xffffffff, FALSE), - HOWTO(R_386_SIZE32, 0, 2, 32, FALSE, 0, complain_overflow_unsigned, + true, 0xffffffff, 0xffffffff, false), + HOWTO(R_386_SIZE32, 0, 2, 32, false, 0, complain_overflow_dont, bfd_elf_generic_reloc, "R_386_SIZE32", - TRUE, 0xffffffff, 0xffffffff, FALSE), - HOWTO(R_386_TLS_GOTDESC, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, + true, 0xffffffff, 0xffffffff, false), + HOWTO(R_386_TLS_GOTDESC, 0, 2, 32, false, 0, complain_overflow_dont, bfd_elf_generic_reloc, "R_386_TLS_GOTDESC", - TRUE, 0xffffffff, 0xffffffff, FALSE), - HOWTO(R_386_TLS_DESC_CALL, 0, 0, 0, FALSE, 0, complain_overflow_dont, + true, 0xffffffff, 0xffffffff, false), + HOWTO(R_386_TLS_DESC_CALL, 0, 3, 0, false, 0, complain_overflow_dont, bfd_elf_generic_reloc, "R_386_TLS_DESC_CALL", - FALSE, 0, 0, FALSE), - HOWTO(R_386_TLS_DESC, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, + false, 0, 0, false), + HOWTO(R_386_TLS_DESC, 0, 2, 32, false, 0, complain_overflow_dont, bfd_elf_generic_reloc, "R_386_TLS_DESC", - TRUE, 0xffffffff, 0xffffffff, FALSE), - HOWTO(R_386_IRELATIVE, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, + true, 0xffffffff, 0xffffffff, false), + HOWTO(R_386_IRELATIVE, 0, 2, 32, false, 0, complain_overflow_dont, bfd_elf_generic_reloc, "R_386_IRELATIVE", - TRUE, 0xffffffff, 0xffffffff, FALSE), - HOWTO(R_386_GOT32X, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, + true, 0xffffffff, 0xffffffff, false), + HOWTO(R_386_GOT32X, 0, 2, 32, false, 0, complain_overflow_dont, bfd_elf_generic_reloc, "R_386_GOT32X", - TRUE, 0xffffffff, 0xffffffff, FALSE), + true, 0xffffffff, 0xffffffff, false), /* Another gap. */ #define R_386_ext2 (R_386_GOT32X + 1 - R_386_tls_offset) @@ -153,30 +150,30 @@ static reloc_howto_type elf_howto_table[]= 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 0, /* bitsize */ - FALSE, /* pc_relative */ + false, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ NULL, /* special_function */ "R_386_GNU_VTINHERIT", /* name */ - FALSE, /* partial_inplace */ + false, /* partial_inplace */ 0, /* src_mask */ 0, /* dst_mask */ - FALSE), /* pcrel_offset */ + false), /* pcrel_offset */ /* GNU extension to record C++ vtable member usage. */ HOWTO (R_386_GNU_VTENTRY, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 0, /* bitsize */ - FALSE, /* pc_relative */ + false, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ _bfd_elf_rel_vtable_reloc_fn, /* special_function */ "R_386_GNU_VTENTRY", /* name */ - FALSE, /* partial_inplace */ + false, /* partial_inplace */ 0, /* src_mask */ 0, /* dst_mask */ - FALSE) /* pcrel_offset */ + false) /* pcrel_offset */ #define R_386_vt (R_386_GNU_VTENTRY + 1 - R_386_vt_offset) @@ -190,7 +187,7 @@ static reloc_howto_type elf_howto_table[]= #endif static reloc_howto_type * -elf_i386_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, +elf_i386_reloc_type_lookup (bfd *abfd, bfd_reloc_code_real_type code) { switch (code) @@ -342,11 +339,13 @@ elf_i386_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, return &elf_howto_table[R_386_GNU_VTENTRY - R_386_vt_offset]; default: - break; + TRACE ("Unknown"); + /* xgettext:c-format */ + _bfd_error_handler (_("%pB: unsupported relocation type: %#x"), + abfd, (int) code); + bfd_set_error (bfd_error_bad_value); + return NULL; } - - TRACE ("Unknown"); - return 0; } static reloc_howto_type * @@ -364,7 +363,7 @@ elf_i386_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, } static reloc_howto_type * -elf_i386_rtype_to_howto (bfd *abfd, unsigned r_type) +elf_i386_rtype_to_howto (unsigned r_type) { unsigned int indx; @@ -375,25 +374,30 @@ elf_i386_rtype_to_howto (bfd *abfd, unsigned r_type) >= R_386_ext2 - R_386_ext) && ((indx = r_type - R_386_vt_offset) - R_386_ext2 >= R_386_vt - R_386_ext2)) - { - /* xgettext:c-format */ - _bfd_error_handler (_("%B: invalid relocation type %d"), - abfd, (int) r_type); - indx = R_386_NONE; - } + return NULL; /* PR 17512: file: 0f67f69d. */ if (elf_howto_table [indx].type != r_type) return NULL; return &elf_howto_table[indx]; } -static void -elf_i386_info_to_howto_rel (bfd *abfd ATTRIBUTE_UNUSED, +static bool +elf_i386_info_to_howto_rel (bfd *abfd, arelent *cache_ptr, Elf_Internal_Rela *dst) { unsigned int r_type = ELF32_R_TYPE (dst->r_info); - cache_ptr->howto = elf_i386_rtype_to_howto (abfd, r_type); + + if ((cache_ptr->howto = elf_i386_rtype_to_howto (r_type)) == NULL) + { + /* xgettext:c-format */ + _bfd_error_handler (_("%pB: unsupported relocation type %#x"), + abfd, r_type); + bfd_set_error (bfd_error_bad_value); + return false; + } + + return true; } /* Return whether a symbol name implies a local label. The UnixWare @@ -402,18 +406,18 @@ elf_i386_info_to_howto_rel (bfd *abfd ATTRIBUTE_UNUSED, If so, we should move the .X recognition into _bfd_elf_is_local_label_name. */ -static bfd_boolean +static bool elf_i386_is_local_label_name (bfd *abfd, const char *name) { if (name[0] == '.' && name[1] == 'X') - return TRUE; + return true; return _bfd_elf_is_local_label_name (abfd, name); } /* Support for core dump NOTE sections. */ -static bfd_boolean +static bool elf_i386_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) { int offset; @@ -424,7 +428,7 @@ elf_i386_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) int pr_version = bfd_get_32 (abfd, note->descdata); if (pr_version != 1) - return FALSE; + return false; /* pr_cursig */ elf_tdata (abfd)->core->signal = bfd_get_32 (abfd, note->descdata + 20); @@ -441,7 +445,7 @@ elf_i386_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) switch (note->descsz) { default: - return FALSE; + return false; case 144: /* Linux/i386 */ /* pr_cursig */ @@ -463,7 +467,7 @@ elf_i386_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) size, note->descpos + offset); } -static bfd_boolean +static bool elf_i386_grok_psinfo (bfd *abfd, Elf_Internal_Note *note) { if (note->namesz == 8 && strcmp (note->namedata, "FreeBSD") == 0) @@ -471,7 +475,7 @@ elf_i386_grok_psinfo (bfd *abfd, Elf_Internal_Note *note) int pr_version = bfd_get_32 (abfd, note->descdata); if (pr_version != 1) - return FALSE; + return false; elf_tdata (abfd)->core->program = _bfd_elfcore_strndup (abfd, note->descdata + 8, 17); @@ -483,7 +487,7 @@ elf_i386_grok_psinfo (bfd *abfd, Elf_Internal_Note *note) switch (note->descsz) { default: - return FALSE; + return false; case 124: /* Linux/i386 elf_prpsinfo. */ elf_tdata (abfd)->core->pid @@ -506,7 +510,7 @@ elf_i386_grok_psinfo (bfd *abfd, Elf_Internal_Note *note) command[n - 1] = '\0'; } - return TRUE; + return true; } /* Functions for the i386 ELF linker. @@ -518,7 +522,7 @@ elf_i386_grok_psinfo (bfd *abfd, Elf_Internal_Note *note) Functions named elf_i386_* are called by external routines, other functions are only called locally. elf_i386_* functions appear in this file more or less in the order in which they are called - from external routines. eg. elf_i386_check_relocs is called + from external routines. eg. elf_i386_scan_relocs is called early in the link process, elf_i386_finish_dynamic_sections is one of the last functions. */ @@ -603,9 +607,9 @@ static const bfd_byte elf_i386_pic_non_lazy_plt_entry[NON_LAZY_PLT_ENTRY_SIZE] = static const bfd_byte elf_i386_lazy_ibt_plt0_entry[LAZY_PLT_ENTRY_SIZE] = { - 0xff, 0x35, 0, 0, 0, 0, /* pushl GOT[1] */ - 0xff, 0x25, 0, 0, 0, 0, /* jmp *GOT[2] */ - 0x0f, 0x1f, 0x40, 0x00 /* nopl 0(%rax) */ + 0xff, 0x35, 0, 0, 0, 0, /* pushl GOT[1] */ + 0xff, 0x25, 0, 0, 0, 0, /* jmp *GOT[2] */ + 0x0f, 0x1f, 0x40, 0x00 /* nopl 0(%rax) */ }; /* Subsequent entries for an absolute IBT-enabled lazy procedure linkage @@ -614,10 +618,10 @@ static const bfd_byte elf_i386_lazy_ibt_plt0_entry[LAZY_PLT_ENTRY_SIZE] = static const bfd_byte elf_i386_lazy_ibt_plt_entry[LAZY_PLT_ENTRY_SIZE] = { - 0xf3, 0x0f, 0x1e, 0xfb, /* endbr32 */ - 0x68, 0, 0, 0, 0, /* pushl immediate */ - 0xe9, 0, 0, 0, 0, /* jmp relative */ - 0x66, 0x90 /* xchg %ax,%ax */ + 0xf3, 0x0f, 0x1e, 0xfb, /* endbr32 */ + 0x68, 0, 0, 0, 0, /* pushl immediate */ + 0xe9, 0, 0, 0, 0, /* jmp relative */ + 0x66, 0x90 /* xchg %ax,%ax */ }; /* The first entry in a PIC IBT-enabled lazy procedure linkage table @@ -626,8 +630,8 @@ static const bfd_byte elf_i386_lazy_ibt_plt_entry[LAZY_PLT_ENTRY_SIZE] = static const bfd_byte elf_i386_pic_lazy_ibt_plt0_entry[LAZY_PLT_ENTRY_SIZE] = { 0xff, 0xb3, 4, 0, 0, 0, /* pushl 4(%ebx) */ - 0xff, 0xa3, 8, 0, 0, 0, /* jmp *8(%ebx) */ - 0x0f, 0x1f, 0x40, 0x00 /* nopl 0(%rax) */ + 0xff, 0xa3, 8, 0, 0, 0, /* jmp *8(%ebx) */ + 0x0f, 0x1f, 0x40, 0x00 /* nopl 0(%rax) */ }; /* Entries for branches with IBT-enabled in the absolute non-lazey @@ -636,7 +640,7 @@ static const bfd_byte elf_i386_pic_lazy_ibt_plt0_entry[LAZY_PLT_ENTRY_SIZE] = static const bfd_byte elf_i386_non_lazy_ibt_plt_entry[LAZY_PLT_ENTRY_SIZE] = { - 0xf3, 0x0f, 0x1e, 0xfb, /* endbr32 */ + 0xf3, 0x0f, 0x1e, 0xfb, /* endbr32 */ 0xff, 0x25, 0, 0, 0, 0, /* jmp *name@GOT */ 0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00 /* nopw 0x0(%rax,%rax,1) */ }; @@ -647,7 +651,7 @@ static const bfd_byte elf_i386_non_lazy_ibt_plt_entry[LAZY_PLT_ENTRY_SIZE] = static const bfd_byte elf_i386_pic_non_lazy_ibt_plt_entry[LAZY_PLT_ENTRY_SIZE] = { - 0xf3, 0x0f, 0x1e, 0xfb, /* endbr32 */ + 0xf3, 0x0f, 0x1e, 0xfb, /* endbr32 */ 0xff, 0xa3, 0, 0, 0, 0, /* jmp *name@GOT(%ebx) */ 0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00 /* nopw 0x0(%rax,%rax,1) */ }; @@ -656,10 +660,6 @@ static const bfd_byte elf_i386_pic_non_lazy_ibt_plt_entry[LAZY_PLT_ENTRY_SIZE] = static const bfd_byte elf_i386_eh_frame_lazy_plt[] = { -#define PLT_CIE_LENGTH 20 -#define PLT_FDE_LENGTH 36 -#define PLT_FDE_START_OFFSET 4 + PLT_CIE_LENGTH + 8 -#define PLT_FDE_LEN_OFFSET 4 + PLT_CIE_LENGTH + 12 PLT_CIE_LENGTH, 0, 0, 0, /* CIE length */ 0, 0, 0, 0, /* CIE ID */ 1, /* CIE version */ @@ -755,65 +755,77 @@ static const bfd_byte elf_i386_eh_frame_non_lazy_plt[] = /* These are the standard parameters. */ static const struct elf_x86_lazy_plt_layout elf_i386_lazy_plt = { - elf_i386_lazy_plt0_entry, /* plt0_entry */ - sizeof (elf_i386_lazy_plt0_entry), /* plt0_entry_size */ - elf_i386_lazy_plt_entry, /* plt_entry */ - LAZY_PLT_ENTRY_SIZE, /* plt_entry_size */ - 2, /* plt0_got1_offset */ - 8, /* plt0_got2_offset */ - 0, /* plt0_got2_insn_end */ - 2, /* plt_got_offset */ - 7, /* plt_reloc_offset */ - 12, /* plt_plt_offset */ - 0, /* plt_got_insn_size */ - 0, /* plt_plt_insn_end */ - 6, /* plt_lazy_offset */ - elf_i386_pic_lazy_plt0_entry, /* pic_plt0_entry */ - elf_i386_pic_lazy_plt_entry, /* pic_plt_entry */ - elf_i386_eh_frame_lazy_plt, /* eh_frame_plt */ + elf_i386_lazy_plt0_entry, /* plt0_entry */ + sizeof (elf_i386_lazy_plt0_entry), /* plt0_entry_size */ + elf_i386_lazy_plt_entry, /* plt_entry */ + LAZY_PLT_ENTRY_SIZE, /* plt_entry_size */ + NULL, /* plt_tlsdesc_entry */ + 0, /* plt_tlsdesc_entry_size*/ + 0, /* plt_tlsdesc_got1_offset */ + 0, /* plt_tlsdesc_got2_offset */ + 0, /* plt_tlsdesc_got1_insn_end */ + 0, /* plt_tlsdesc_got2_insn_end */ + 2, /* plt0_got1_offset */ + 8, /* plt0_got2_offset */ + 0, /* plt0_got2_insn_end */ + 2, /* plt_got_offset */ + 7, /* plt_reloc_offset */ + 12, /* plt_plt_offset */ + 0, /* plt_got_insn_size */ + 0, /* plt_plt_insn_end */ + 6, /* plt_lazy_offset */ + elf_i386_pic_lazy_plt0_entry, /* pic_plt0_entry */ + elf_i386_pic_lazy_plt_entry, /* pic_plt_entry */ + elf_i386_eh_frame_lazy_plt, /* eh_frame_plt */ sizeof (elf_i386_eh_frame_lazy_plt) /* eh_frame_plt_size */ }; static const struct elf_x86_non_lazy_plt_layout elf_i386_non_lazy_plt = { - elf_i386_non_lazy_plt_entry, /* plt_entry */ - elf_i386_pic_non_lazy_plt_entry, /* pic_plt_entry */ - NON_LAZY_PLT_ENTRY_SIZE, /* plt_entry_size */ - 2, /* plt_got_offset */ - 0, /* plt_got_insn_size */ - elf_i386_eh_frame_non_lazy_plt, /* eh_frame_plt */ + elf_i386_non_lazy_plt_entry, /* plt_entry */ + elf_i386_pic_non_lazy_plt_entry, /* pic_plt_entry */ + NON_LAZY_PLT_ENTRY_SIZE, /* plt_entry_size */ + 2, /* plt_got_offset */ + 0, /* plt_got_insn_size */ + elf_i386_eh_frame_non_lazy_plt, /* eh_frame_plt */ sizeof (elf_i386_eh_frame_non_lazy_plt) /* eh_frame_plt_size */ }; static const struct elf_x86_lazy_plt_layout elf_i386_lazy_ibt_plt = { - elf_i386_lazy_ibt_plt0_entry, /* plt0_entry */ + elf_i386_lazy_ibt_plt0_entry, /* plt0_entry */ sizeof (elf_i386_lazy_ibt_plt0_entry), /* plt0_entry_size */ - elf_i386_lazy_ibt_plt_entry, /* plt_entry */ - LAZY_PLT_ENTRY_SIZE, /* plt_entry_size */ - 2, /* plt0_got1_offset */ - 8, /* plt0_got2_offset */ - 0, /* plt0_got2_insn_end */ - 4+2, /* plt_got_offset */ - 4+1, /* plt_reloc_offset */ - 4+6, /* plt_plt_offset */ - 0, /* plt_got_insn_size */ - 0, /* plt_plt_insn_end */ - 0, /* plt_lazy_offset */ - elf_i386_pic_lazy_ibt_plt0_entry, /* pic_plt0_entry */ - elf_i386_lazy_ibt_plt_entry, /* pic_plt_entry */ - elf_i386_eh_frame_lazy_ibt_plt, /* eh_frame_plt */ + elf_i386_lazy_ibt_plt_entry, /* plt_entry */ + LAZY_PLT_ENTRY_SIZE, /* plt_entry_size */ + NULL, /* plt_tlsdesc_entry */ + 0, /* plt_tlsdesc_entry_size*/ + 0, /* plt_tlsdesc_got1_offset */ + 0, /* plt_tlsdesc_got2_offset */ + 0, /* plt_tlsdesc_got1_insn_end */ + 0, /* plt_tlsdesc_got2_insn_end */ + 2, /* plt0_got1_offset */ + 8, /* plt0_got2_offset */ + 0, /* plt0_got2_insn_end */ + 4+2, /* plt_got_offset */ + 4+1, /* plt_reloc_offset */ + 4+6, /* plt_plt_offset */ + 0, /* plt_got_insn_size */ + 0, /* plt_plt_insn_end */ + 0, /* plt_lazy_offset */ + elf_i386_pic_lazy_ibt_plt0_entry, /* pic_plt0_entry */ + elf_i386_lazy_ibt_plt_entry, /* pic_plt_entry */ + elf_i386_eh_frame_lazy_ibt_plt, /* eh_frame_plt */ sizeof (elf_i386_eh_frame_lazy_ibt_plt) /* eh_frame_plt_size */ }; static const struct elf_x86_non_lazy_plt_layout elf_i386_non_lazy_ibt_plt = { - elf_i386_non_lazy_ibt_plt_entry, /* plt_entry */ + elf_i386_non_lazy_ibt_plt_entry, /* plt_entry */ elf_i386_pic_non_lazy_ibt_plt_entry,/* pic_plt_entry */ - LAZY_PLT_ENTRY_SIZE, /* plt_entry_size */ - 4+2, /* plt_got_offset */ - 0, /* plt_got_insn_size */ - elf_i386_eh_frame_non_lazy_plt, /* eh_frame_plt */ + LAZY_PLT_ENTRY_SIZE, /* plt_entry_size */ + 4+2, /* plt_got_offset */ + 0, /* plt_got_insn_size */ + elf_i386_eh_frame_non_lazy_plt, /* eh_frame_plt */ sizeof (elf_i386_eh_frame_non_lazy_plt) /* eh_frame_plt_size */ }; @@ -824,70 +836,10 @@ static const struct elf_x86_non_lazy_plt_layout elf_i386_non_lazy_ibt_plt = #define PLTRESOLVE_RELOCS 2 #define PLT_NON_JUMP_SLOT_RELOCS 2 -/* Architecture-specific backend data for i386. */ - -struct elf_i386_backend_data -{ - /* Value used to fill the unused bytes of the first PLT entry. */ - bfd_byte plt0_pad_byte; - - /* Target system. */ - enum - { - is_normal, - is_vxworks, - is_nacl - } os; -}; - -#define get_elf_i386_backend_data(abfd) \ - ((const struct elf_i386_backend_data *) \ - get_elf_backend_data (abfd)->arch_data) - -/* These are the standard parameters. */ -static const struct elf_i386_backend_data elf_i386_arch_bed = - { - 0, /* plt0_pad_byte */ - is_normal /* os */ - }; - -#define elf_backend_arch_data &elf_i386_arch_bed - -/* Values in tls_type of x86 ELF linker hash entry. */ -#define GOT_TLS_IE 4 -#define GOT_TLS_IE_POS 5 -#define GOT_TLS_IE_NEG 6 -#define GOT_TLS_IE_BOTH 7 -#define GOT_TLS_GDESC 8 -#define GOT_TLS_GD_BOTH_P(type) \ - ((type) == (GOT_TLS_GD | GOT_TLS_GDESC)) -#define GOT_TLS_GD_P(type) \ - ((type) == GOT_TLS_GD || GOT_TLS_GD_BOTH_P (type)) -#define GOT_TLS_GDESC_P(type) \ - ((type) == GOT_TLS_GDESC || GOT_TLS_GD_BOTH_P (type)) -#define GOT_TLS_GD_ANY_P(type) \ - (GOT_TLS_GD_P (type) || GOT_TLS_GDESC_P (type)) - -#define is_i386_elf(bfd) \ - (bfd_get_flavour (bfd) == bfd_target_elf_flavour \ - && elf_tdata (bfd) != NULL \ - && elf_object_id (bfd) == I386_ELF_DATA) - -static bfd_boolean -elf_i386_mkobject (bfd *abfd) -{ - return bfd_elf_allocate_object (abfd, - sizeof (struct elf_x86_obj_tdata), - I386_ELF_DATA); -} - -#define elf_i386_compute_jump_table_size(htab) \ - ((htab)->elf.srelplt->reloc_count * 4) - /* Return TRUE if the TLS access code sequence support transition from R_TYPE. */ -static bfd_boolean +static bool elf_i386_check_tls_transition (asection *sec, bfd_byte *contents, Elf_Internal_Shdr *symtab_hdr, @@ -901,7 +853,7 @@ elf_i386_check_tls_transition (asection *sec, struct elf_link_hash_entry *h; bfd_vma offset; bfd_byte *call; - bfd_boolean indirect_call; + bool indirect_call; offset = rel->r_offset; switch (r_type) @@ -909,9 +861,9 @@ elf_i386_check_tls_transition (asection *sec, case R_386_TLS_GD: case R_386_TLS_LDM: if (offset < 2 || (rel + 1) >= relend) - return FALSE; + return false; - indirect_call = FALSE; + indirect_call = false; call = contents + offset + 4; val = *(call - 5); type = *(call - 6); @@ -932,19 +884,19 @@ elf_i386_check_tls_transition (asection *sec, can transit to different access model. */ if ((offset + 10) > sec->size || (type != 0x8d && type != 0x04)) - return FALSE; + return false; if (type == 0x04) { /* leal foo@tlsgd(,%ebx,1), %eax call ___tls_get_addr@PLT */ if (offset < 3) - return FALSE; + return false; if (*(call - 7) != 0x8d || val != 0x1d || call[0] != 0xe8) - return FALSE; + return false; } else { @@ -962,7 +914,7 @@ elf_i386_check_tls_transition (asection *sec, is used to pass parameter to ___tls_get_addr. */ reg = val & 7; if ((val & 0xf8) != 0x80 || reg == 4 || reg == 0) - return FALSE; + return false; indirect_call = call[0] == 0xff; if (!(reg == 3 && call[0] == 0xe8 && call[5] == 0x90) @@ -970,7 +922,7 @@ elf_i386_check_tls_transition (asection *sec, && !(indirect_call && (call[1] & 0xf8) == 0x90 && (call[1] & 0x7) == reg)) - return FALSE; + return false; } } else @@ -985,13 +937,13 @@ elf_i386_check_tls_transition (asection *sec, addr32 call ___tls_get_addr can transit to different access model. */ if (type != 0x8d || (offset + 9) > sec->size) - return FALSE; + return false; /* %eax can't be used as the GOT base register since it is used to pass parameter to ___tls_get_addr. */ reg = val & 7; if ((val & 0xf8) != 0x80 || reg == 4 || reg == 0) - return FALSE; + return false; indirect_call = call[0] == 0xff; if (!(reg == 3 && call[0] == 0xe8) @@ -999,17 +951,17 @@ elf_i386_check_tls_transition (asection *sec, && !(indirect_call && (call[1] & 0xf8) == 0x90 && (call[1] & 0x7) == reg)) - return FALSE; + return false; } r_symndx = ELF32_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 if (indirect_call) return (ELF32_R_TYPE (rel[1].r_info) == R_386_GOT32X); else @@ -1024,15 +976,15 @@ elf_i386_check_tls_transition (asection *sec, */ if (offset < 1 || (offset + 4) > sec->size) - return FALSE; + return false; /* Check "movl foo@tpoff(%rip), %eax" first. */ val = bfd_get_8 (abfd, contents + offset - 1); if (val == 0xa1) - return TRUE; + return true; if (offset < 2) - return FALSE; + return false; /* Check movl|addl foo@tpoff(%rip), %reg. */ type = bfd_get_8 (abfd, contents + offset - 2); @@ -1048,11 +1000,11 @@ elf_i386_check_tls_transition (asection *sec, */ if (offset < 2 || (offset + 4) > sec->size) - return FALSE; + return false; val = bfd_get_8 (abfd, contents + offset - 1); if ((val & 0xc0) != 0x80 || (val & 7) == 4) - return FALSE; + return false; type = bfd_get_8 (abfd, contents + offset - 2); return type == 0x8b || type == 0x2b || type == 0x03; @@ -1066,10 +1018,10 @@ elf_i386_check_tls_transition (asection *sec, going to be eax. */ if (offset < 2 || (offset + 4) > sec->size) - 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) == 0x83; @@ -1085,7 +1037,7 @@ elf_i386_check_tls_transition (asection *sec, return call[0] == 0xff && call[1] == 0x10; } - return FALSE; + return false; default: abort (); @@ -1095,7 +1047,7 @@ elf_i386_check_tls_transition (asection *sec, /* 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_i386_tls_transition (struct bfd_link_info *info, bfd *abfd, asection *sec, bfd_byte *contents, Elf_Internal_Shdr *symtab_hdr, @@ -1105,17 +1057,17 @@ elf_i386_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) { @@ -1140,10 +1092,7 @@ elf_i386_tls_transition (struct bfd_link_info *info, bfd *abfd, { unsigned int new_to_type = to_type; - if (bfd_link_executable (info) - && h != NULL - && h->dynindx == -1 - && (tls_type & GOT_TLS_IE)) + if (TLS_TRANSITION_IE_TO_LE_P (info, h, tls_type)) new_to_type = R_386_TLS_LE_32; if (to_type == R_386_TLS_GD @@ -1157,7 +1106,7 @@ elf_i386_tls_transition (struct bfd_link_info *info, bfd *abfd, } /* We checked the transition before when we were called from - elf_i386_check_relocs. We only want to check the new + elf_i386_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; @@ -1171,12 +1120,12 @@ elf_i386_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 @@ -1187,8 +1136,8 @@ elf_i386_tls_transition (struct bfd_link_info *info, bfd *abfd, reloc_howto_type *from, *to; const char *name; - from = elf_i386_rtype_to_howto (abfd, from_type); - to = elf_i386_rtype_to_howto (abfd, to_type); + from = elf_i386_rtype_to_howto (from_type); + to = elf_i386_rtype_to_howto (to_type); if (h) name = h->root.root.string; @@ -1203,7 +1152,7 @@ elf_i386_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); } @@ -1211,16 +1160,16 @@ elf_i386_tls_transition (struct bfd_link_info *info, bfd *abfd, _bfd_error_handler /* xgettext:c-format */ - (_("%B: TLS transition from %s to %s against `%s' at %#Lx " - "in section `%A' failed"), + (_("%pB: TLS transition from %s to %s against `%s'" + " at %#" PRIx64 " in section `%pA' failed"), abfd, from->name, to->name, name, - rel->r_offset, sec); + (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; } /* With the local symbol, foo, we convert @@ -1243,45 +1192,64 @@ elf_i386_tls_transition (struct bfd_link_info *info, bfd *abfd, instructions. */ static -bfd_boolean +bool elf_i386_convert_load_reloc (bfd *abfd, Elf_Internal_Shdr *symtab_hdr, 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; unsigned int opcode; unsigned int modrm; - bfd_boolean baseless; + bool baseless; Elf_Internal_Sym *isym; unsigned int addend; unsigned int nop; bfd_vma nop_offset; - bfd_boolean is_pic; - bfd_boolean to_reloc_32; + bool is_pic; + bool to_reloc_32; + bool abs_symbol; unsigned int r_type; unsigned int r_symndx; bfd_vma roff = irel->r_offset; + bool local_ref; + struct elf_x86_link_hash_entry *eh; if (roff < 2) - return TRUE; + return true; /* Addend for R_386_GOT32X relocations must be 0. */ addend = bfd_get_32 (abfd, contents + roff); if (addend != 0) - return TRUE; + return true; htab = elf_x86_hash_table (link_info, I386_ELF_DATA); is_pic = bfd_link_pic (link_info); - r_type = ELF32_R_TYPE (irel->r_info); + r_type = *r_type_p; r_symndx = ELF32_R_SYM (irel->r_info); modrm = bfd_get_8 (abfd, contents + roff - 1); baseless = (modrm & 0xc7) == 0x5; + if (h) + { + /* NB: Also set linker_def via SYMBOL_REFERENCES_LOCAL_P. */ + local_ref = SYMBOL_REFERENCES_LOCAL_P (link_info, h); + isym = NULL; + abs_symbol = ABS_SYMBOL_P (h); + } + else + { + local_ref = true; + isym = bfd_sym_from_r_symndx (&htab->elf.sym_cache, abfd, + r_symndx); + abs_symbol = isym->st_shndx == SHN_ABS; + } + if (baseless && is_pic) { /* For PIC, disallow R_386_GOT32X without a base register @@ -1289,20 +1257,16 @@ elf_i386_convert_load_reloc (bfd *abfd, Elf_Internal_Shdr *symtab_hdr, const char *name; if (h == NULL) - { - isym = bfd_sym_from_r_symndx (&htab->sym_cache, abfd, - r_symndx); - name = bfd_elf_sym_name (abfd, symtab_hdr, isym, NULL); - } + name = bfd_elf_sym_name (abfd, symtab_hdr, isym, NULL); else name = h->root.root.string; _bfd_error_handler /* xgettext:c-format */ - (_("%B: direct GOT relocation R_386_GOT32X against `%s' without base" + (_("%pB: direct GOT relocation R_386_GOT32X against `%s' without base" " register can not be used when making a shared object"), abfd, name); - return FALSE; + return false; } opcode = bfd_get_8 (abfd, contents + roff - 2); @@ -1311,6 +1275,8 @@ elf_i386_convert_load_reloc (bfd *abfd, Elf_Internal_Shdr *symtab_hdr, register. */ to_reloc_32 = !is_pic || baseless; + eh = elf_x86_hash_entry (h); + /* Try to convert R_386_GOT32X. Get the symbol referred to by the reloc. */ if (h == NULL) @@ -1327,21 +1293,22 @@ elf_i386_convert_load_reloc (bfd *abfd, Elf_Internal_Shdr *symtab_hdr, /* Undefined weak symbol is only bound locally in executable and its reference is resolved as 0. */ - if (UNDEFINED_WEAK_RESOLVED_TO_ZERO (link_info, I386_ELF_DATA, TRUE, - elf_x86_hash_entry (h))) + if (h->root.type == bfd_link_hash_undefweak + && !eh->linker_def + && local_ref) { if (opcode == 0xff) { /* No direct branch to 0 for PIC. */ if (is_pic) - return TRUE; + return true; else goto convert_branch; } else { /* We can convert load of address 0 to R_386_32. */ - to_reloc_32 = TRUE; + to_reloc_32 = true; goto convert_load; } } @@ -1351,16 +1318,13 @@ elf_i386_convert_load_reloc (bfd *abfd, Elf_Internal_Shdr *symtab_hdr, /* We have "call/jmp *foo@GOT[(%reg)]". */ if ((h->root.type == bfd_link_hash_defined || h->root.type == bfd_link_hash_defweak) - && SYMBOL_REFERENCES_LOCAL (link_info, h)) + && local_ref) { /* The function is locally defined. */ -convert_branch: + convert_branch: /* Convert R_386_GOT32X to R_386_PC32. */ if (modrm == 0x15 || (modrm & 0xf8) == 0x90) { - struct elf_x86_link_hash_entry *eh - = (struct elf_x86_link_hash_entry *) h; - /* Convert to "nop call foo". ADDR_PREFIX_OPCODE is a nop prefix. */ modrm = 0xe8; @@ -1373,8 +1337,8 @@ convert_branch: } else { - nop = link_info->call_nop_byte; - if (link_info->call_nop_as_suffix) + nop = htab->params->call_nop_byte; + if (htab->params->call_nop_as_suffix) { nop_offset = roff + 3; irel->r_offset -= 1; @@ -1398,8 +1362,8 @@ convert_branch: need to adjust addend by -4. */ bfd_put_32 (abfd, -4, contents + irel->r_offset); irel->r_info = ELF32_R_INFO (r_symndx, R_386_PC32); - - *converted = TRUE; + *r_type_p = R_386_PC32; + *converted = true; } } else @@ -1411,20 +1375,24 @@ convert_branch: Avoid optimizing _DYNAMIC since ld.so may use its link-time address. */ if (h == htab->elf.hdynamic) - return TRUE; + return true; /* def_regular is set by an assignment in a linker script in bfd_elf_record_link_assignment. start_stop is set on __start_SECNAME/__stop_SECNAME which mark section SECNAME. */ if (h->start_stop + || eh->linker_def || ((h->def_regular || h->root.type == bfd_link_hash_defined || h->root.type == bfd_link_hash_defweak) - && SYMBOL_REFERENCES_LOCAL (link_info, h))) + && local_ref)) { -convert_load: + convert_load: if (opcode == 0x8b) { + if (abs_symbol && local_ref) + to_reloc_32 = true; + if (to_reloc_32) { /* Convert "mov foo@GOT[(%reg1)], %reg2" to @@ -1446,7 +1414,7 @@ convert_load: { /* Only R_386_32 is supported. */ if (!to_reloc_32) - return TRUE; + return true; if (opcode == 0x85) { @@ -1470,71 +1438,57 @@ convert_load: bfd_put_8 (abfd, opcode, contents + roff - 2); irel->r_info = ELF32_R_INFO (r_symndx, r_type); - - *converted = TRUE; + *r_type_p = r_type; + *converted = true; } } - return TRUE; + return true; } -/* Rename some of the generic section flags to better document how they - are used here. */ -#define need_convert_load sec_flg0 -#define check_relocs_failed sec_flg1 - /* 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. */ - -static bfd_boolean -elf_i386_check_relocs (bfd *abfd, - struct bfd_link_info *info, - asection *sec, - const Elf_Internal_Rela *relocs) + calculate needed space in the global offset table, and procedure + linkage table. */ + +static bool +elf_i386_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; + 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; - - BFD_ASSERT (is_i386_elf (abfd)); + return true; htab = elf_x86_hash_table (info, I386_ELF_DATA); if (htab == NULL) { sec->check_relocs_failed = 1; - return FALSE; + return false; } + BFD_ASSERT (is_x86_elf (abfd, htab)); + /* Get the section contents. */ if (elf_section_data (sec)->this_hdr.contents != NULL) contents = elf_section_data (sec)->this_hdr.contents; 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); - sreloc = NULL; + converted = false; rel_end = relocs + sec->reloc_count; for (rel = relocs; rel < rel_end; rel++) @@ -1545,7 +1499,8 @@ elf_i386_check_relocs (bfd *abfd, struct elf_x86_link_hash_entry *eh; Elf_Internal_Sym *isym; const char *name; - bfd_boolean size_reloc; + bool size_reloc; + bool no_dynreloc; r_symndx = ELF32_R_SYM (rel->r_info); r_type = ELF32_R_TYPE (rel->r_info); @@ -1553,7 +1508,7 @@ elf_i386_check_relocs (bfd *abfd, if (r_symndx >= NUM_SHDR_ENTRIES (symtab_hdr)) { /* xgettext:c-format */ - _bfd_error_handler (_("%B: bad symbol index: %d"), + _bfd_error_handler (_("%pB: bad symbol index: %d"), abfd, r_symndx); goto error_return; } @@ -1561,7 +1516,7 @@ elf_i386_check_relocs (bfd *abfd, 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; @@ -1569,7 +1524,7 @@ elf_i386_check_relocs (bfd *abfd, /* Check relocation against local STT_GNU_IFUNC symbol. */ if (ELF32_ST_TYPE (isym->st_info) == STT_GNU_IFUNC) { - h = _bfd_elf_x86_get_local_sym_hash (htab, abfd, rel, TRUE); + h = _bfd_elf_x86_get_local_sym_hash (htab, abfd, rel, true); if (h == NULL) goto error_return; @@ -1602,23 +1557,36 @@ elf_i386_check_relocs (bfd *abfd, /* It is referenced by a non-shared object. */ h->ref_regular = 1; - h->root.non_ir_ref_regular = 1; + } - if (h->type == STT_GNU_IFUNC) - elf_tdata (info->output_bfd)->has_gnu_symbols - |= elf_gnu_symbol_ifunc; + if (r_type == R_386_GOT32X + && (h == NULL || h->type != STT_GNU_IFUNC)) + { + Elf_Internal_Rela *irel = (Elf_Internal_Rela *) rel; + if (!elf_i386_convert_load_reloc (abfd, symtab_hdr, contents, + &r_type, irel, h, + &converted, info)) + goto error_return; } + if (!_bfd_elf_x86_valid_reloc_p (sec, info, htab, rel, h, isym, + symtab_hdr, &no_dynreloc)) + return false; + if (! elf_i386_tls_transition (info, abfd, sec, contents, symtab_hdr, sym_hashes, &r_type, GOT_UNKNOWN, - 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; + switch (r_type) { case R_386_TLS_LDM: - htab->tls_ld_or_ldm_got.refcount += 1; + htab->tls_ld_or_ldm_got.refcount = 1; goto create_got; case R_386_PLT32: @@ -1634,13 +1602,13 @@ elf_i386_check_relocs (bfd *abfd, if (h == NULL) continue; - eh->has_got_reloc = 1; + eh->zero_undefweak &= 0x2; h->needs_plt = 1; - h->plt.refcount += 1; + h->plt.refcount = 1; break; case R_386_SIZE32: - size_reloc = TRUE; + size_reloc = true; goto do_size; case R_386_TLS_IE_32: @@ -1685,33 +1653,20 @@ elf_i386_check_relocs (bfd *abfd, if (h != NULL) { - h->got.refcount += 1; + h->got.refcount = 1; old_tls_type = elf_x86_hash_entry (h)->tls_type; } else { 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; + local_got_refcounts[r_symndx] = 1; old_tls_type = elf_x86_local_got_tls_type (abfd) [r_symndx]; } @@ -1737,7 +1692,7 @@ elf_i386_check_relocs (bfd *abfd, NULL); _bfd_error_handler /* xgettext:c-format */ - (_("%B: `%s' accessed both as normal and " + (_("%pB: `%s' accessed both as normal and " "thread local symbol"), abfd, name); bfd_set_error (bfd_error_bad_value); @@ -1761,7 +1716,15 @@ elf_i386_check_relocs (bfd *abfd, if (r_type != R_386_TLS_IE) { if (eh != NULL) - eh->has_got_reloc = 1; + { + eh->zero_undefweak &= 0x2; + + /* Need GOT to resolve undefined weak symbol to 0. */ + if (r_type == R_386_GOTOFF + && h->root.type == bfd_link_hash_undefweak + && bfd_link_executable (info)) + htab->got_referenced = true; + } break; } /* Fall through */ @@ -1769,7 +1732,7 @@ elf_i386_check_relocs (bfd *abfd, case R_386_TLS_LE_32: case R_386_TLS_LE: if (eh != NULL) - eh->has_got_reloc = 1; + eh->zero_undefweak &= 0x2; if (bfd_link_executable (info)) break; info->flags |= DF_STATIC_TLS; @@ -1778,8 +1741,8 @@ elf_i386_check_relocs (bfd *abfd, case R_386_32: case R_386_PC32: if (eh != NULL && (sec->flags & SEC_CODE) != 0) - eh->has_non_got_reloc = 1; -do_relocation: + eh->zero_undefweak |= 0x2; + do_relocation: /* We are called after all symbols have been resolved. Only relocation against STT_GNU_IFUNC symbol must go through PLT. */ @@ -1787,20 +1750,7 @@ do_relocation: && (bfd_link_executable (info) || h->type == STT_GNU_IFUNC)) { - /* If this reloc is in a read-only section, we might - need a copy reloc. We can't check reliably at this - stage whether the section is read-only, as input - sections have not yet been mapped to output sections. - Tentatively set the flag for now, and correct in - adjust_dynamic_symbol. */ - h->non_got_ref = 1; - - /* We may need a .plt entry if the symbol is a function - defined in a shared lib or is a STT_GNU_IFUNC function - referenced from the code or read-only section. */ - if (!h->def_regular - || (sec->flags & (SEC_CODE | SEC_READONLY)) != 0) - h->plt.refcount += 1; + bool func_pointer_ref = false; if (r_type == R_386_PC32) { @@ -1814,7 +1764,7 @@ do_relocation: { _bfd_error_handler /* xgettext:c-format */ - (_("%B: unsupported non-PIC call to IFUNC `%s'"), + (_("%pB: unsupported non-PIC call to IFUNC `%s'"), abfd, h->root.root.string); bfd_set_error (bfd_error_bad_value); goto error_return; @@ -1826,73 +1776,62 @@ do_relocation: /* R_386_32 can be resolved at run-time. */ if (r_type == R_386_32 && (sec->flags & SEC_READONLY) == 0) - eh->func_pointer_refcount += 1; + func_pointer_ref = true; + } + + 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; + } + + if (!func_pointer_ref) + { + /* If this reloc is in a read-only section, we might + need a copy reloc. We can't check reliably at this + stage whether the section is read-only, as input + sections have not yet been mapped to output sections. + Tentatively set the flag for now, and correct in + 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; } } - size_reloc = FALSE; -do_size: - /* If we are creating a shared library, and this is a reloc - against a global symbol, or a non PC relative reloc - against a local symbol, then we need to copy the reloc - into the shared library. However, if we are linking with - -Bsymbolic, we do not need to copy a reloc against a - global symbol which is defined in an object we are - including in the link (i.e., DEF_REGULAR is set). At - this point we have not seen all the input files, so it is - possible that DEF_REGULAR is not set now but will be set - later (it is never cleared). In case of a weak definition, - DEF_REGULAR may be cleared later by a strong definition in - a shared library. We account for that possibility below by - storing information in the relocs_copied field of the hash - table entry. A similar situation occurs when creating - shared libraries and symbol visibility changes render the - symbol local. - - If on the other hand, we are creating an executable, we - may need to keep relocations for symbols satisfied by a - dynamic library if we manage to avoid copy relocs for the - symbol. - - Generate dynamic pointer relocation against STT_GNU_IFUNC - symbol in the non-code section. */ - if ((bfd_link_pic (info) - && (r_type != R_386_PC32 - || (h != NULL - && (! (bfd_link_pie (info) - || SYMBOLIC_BIND (info, h)) - || h->root.type == bfd_link_hash_defweak - || !h->def_regular)))) - || (h != NULL - && h->type == STT_GNU_IFUNC - && r_type == R_386_32 - && (sec->flags & SEC_CODE) == 0) - || (ELIMINATE_COPY_RELOCS - && !bfd_link_pic (info) - && h != NULL - && (h->root.type == bfd_link_hash_defweak - || !h->def_regular))) + size_reloc = false; + do_size: + if (!no_dynreloc + && NEED_DYNAMIC_RELOCATION_P (false, info, false, h, sec, + r_type, R_386_32)) { 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, 2, abfd, /*rela?*/ FALSE); - - 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 { @@ -1902,7 +1841,7 @@ do_size: void **vpp; asection *s; - 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; @@ -1918,9 +1857,9 @@ 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); + amt); if (p == NULL) goto error_return; p->next = *head; @@ -1928,1262 +1867,89 @@ do_size: p->sec = sec; p->count = 0; p->pc_count = 0; - } - - p->count += 1; - /* Count size relocation as PC-relative relocation. */ - if (r_type == R_386_PC32 || size_reloc) - p->pc_count += 1; - } - break; - - /* This relocation describes the C++ object vtable hierarchy. - Reconstruct it for later use during GC. */ - case R_386_GNU_VTINHERIT: - if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset)) - goto error_return; - break; - - /* This relocation describes which C++ vtable entries are actually - used. Record for later use during GC. */ - case R_386_GNU_VTENTRY: - BFD_ASSERT (h != NULL); - if (h != NULL - && !bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_offset)) - goto error_return; - break; - - default: - break; - } - - if (r_type == R_386_GOT32X - && (h == NULL || h->type != STT_GNU_IFUNC)) - sec->need_convert_load = 1; - } - - if (elf_section_data (sec)->this_hdr.contents != contents) - { - if (!info->keep_memory) - free (contents); - else - { - /* Cache the section contents for elf_link_input_bfd. */ - elf_section_data (sec)->this_hdr.contents = contents; - } - } - - return TRUE; - -error_return: - if (elf_section_data (sec)->this_hdr.contents != contents) - free (contents); - sec->check_relocs_failed = 1; - return FALSE; -} - -/* Return the section that should be marked against GC for a given - relocation. */ - -static asection * -elf_i386_gc_mark_hook (asection *sec, - struct bfd_link_info *info, - Elf_Internal_Rela *rel, - struct elf_link_hash_entry *h, - Elf_Internal_Sym *sym) -{ - if (h != NULL) - switch (ELF32_R_TYPE (rel->r_info)) - { - case R_386_GNU_VTINHERIT: - case R_386_GNU_VTENTRY: - return NULL; - } - - return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym); -} - -/* Adjust a symbol defined by a dynamic object and referenced by a - regular object. The current definition is in some section of the - dynamic object, but we're not including those sections. We have to - change the definition to something the rest of the link can - understand. */ - -static bfd_boolean -elf_i386_adjust_dynamic_symbol (struct bfd_link_info *info, - struct elf_link_hash_entry *h) -{ - struct elf_x86_link_hash_table *htab; - asection *s, *srel; - struct elf_x86_link_hash_entry *eh; - struct elf_dyn_relocs *p; - - /* STT_GNU_IFUNC symbol must go through PLT. */ - if (h->type == STT_GNU_IFUNC) - { - /* All local STT_GNU_IFUNC references must be treate as local - calls via local PLT. */ - if (h->ref_regular - && SYMBOL_CALLS_LOCAL (info, h)) - { - bfd_size_type pc_count = 0, count = 0; - struct elf_dyn_relocs **pp; - - eh = (struct elf_x86_link_hash_entry *) h; - for (pp = &eh->dyn_relocs; (p = *pp) != NULL; ) - { - pc_count += p->pc_count; - p->count -= p->pc_count; - p->pc_count = 0; - count += p->count; - if (p->count == 0) - *pp = p->next; - else - pp = &p->next; - } - - if (pc_count || count) - { - h->non_got_ref = 1; - if (pc_count) - { - /* Increment PLT reference count only for PC-relative - references. */ - h->needs_plt = 1; - if (h->plt.refcount <= 0) - h->plt.refcount = 1; - else - h->plt.refcount += 1; - } - } - } - - if (h->plt.refcount <= 0) - { - h->plt.offset = (bfd_vma) -1; - h->needs_plt = 0; - } - return TRUE; - } - - /* If this is a function, put it in the procedure linkage table. We - will fill in the contents of the procedure linkage table later, - when we know the address of the .got section. */ - if (h->type == STT_FUNC - || h->needs_plt) - { - if (h->plt.refcount <= 0 - || SYMBOL_CALLS_LOCAL (info, h) - || (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT - && h->root.type == bfd_link_hash_undefweak)) - { - /* This case can occur if we saw a PLT32 reloc in an input - file, but the symbol was never referred to by a dynamic - object, or if all references were garbage collected. In - such a case, we don't actually need to build a procedure - linkage table, and we can just do a PC32 reloc instead. */ - h->plt.offset = (bfd_vma) -1; - h->needs_plt = 0; - } - - return TRUE; - } - else - /* It's possible that we incorrectly decided a .plt reloc was - needed for an R_386_PC32 reloc to a non-function sym in - check_relocs. We can't decide accurately between function and - non-function syms in check-relocs; Objects loaded later in - the link may change h->type. So fix it now. */ - h->plt.offset = (bfd_vma) -1; - - eh = (struct elf_x86_link_hash_entry *) h; - - /* If this is a weak symbol, and there is a real definition, the - processor independent code will have arranged for us to see the - real definition first, and we can just use the same value. */ - if (h->u.weakdef != NULL) - { - BFD_ASSERT (h->u.weakdef->root.type == bfd_link_hash_defined - || h->u.weakdef->root.type == bfd_link_hash_defweak); - h->root.u.def.section = h->u.weakdef->root.u.def.section; - h->root.u.def.value = h->u.weakdef->root.u.def.value; - if (ELIMINATE_COPY_RELOCS - || info->nocopyreloc - || SYMBOL_NO_COPYRELOC (info, eh)) - h->non_got_ref = h->u.weakdef->non_got_ref; - return TRUE; - } - - /* This is a reference to a symbol defined by a dynamic object which - is not a function. */ - - /* If we are creating a shared library, we must presume that the - only references to the symbol are via the global offset table. - For such cases we need not do anything here; the relocations will - be handled correctly by relocate_section. */ - if (!bfd_link_executable (info)) - return TRUE; - - /* If there are no references to this symbol that do not use the - GOT nor R_386_GOTOFF relocation, we don't need to generate a copy - reloc. */ - if (!h->non_got_ref && !eh->gotoff_ref) - return TRUE; - - /* If -z nocopyreloc was given, we won't generate them either. */ - if (info->nocopyreloc || SYMBOL_NO_COPYRELOC (info, eh)) - { - h->non_got_ref = 0; - return TRUE; - } - - htab = elf_x86_hash_table (info, I386_ELF_DATA); - if (htab == NULL) - return FALSE; - - /* If there aren't any dynamic relocs in read-only sections nor - R_386_GOTOFF relocation, then we can keep the dynamic relocs and - avoid the copy reloc. This doesn't work on VxWorks, where we can - not have dynamic relocations (other than copy and jump slot - relocations) in an executable. */ - if (ELIMINATE_COPY_RELOCS - && !eh->gotoff_ref - && get_elf_i386_backend_data (info->output_bfd)->os != is_vxworks) - { - for (p = eh->dyn_relocs; p != NULL; p = p->next) - { - s = p->sec->output_section; - if (s != NULL && (s->flags & SEC_READONLY) != 0) - break; - } - - if (p == NULL) - { - h->non_got_ref = 0; - return TRUE; - } - } - - /* We must allocate the symbol in our .dynbss section, which will - become part of the .bss section of the executable. There will be - an entry for this symbol in the .dynsym section. The dynamic - object will contain position independent code, so all references - from the dynamic object to this symbol will go through the global - offset table. The dynamic linker will use the .dynsym entry to - determine the address it must put in the global offset table, so - both the dynamic object and the regular object will refer to the - same memory location for the variable. */ - - /* We must generate a R_386_COPY reloc to tell the dynamic linker to - copy the initial value out of the dynamic object and into the - runtime process image. */ - if ((h->root.u.def.section->flags & SEC_READONLY) != 0) - { - s = htab->elf.sdynrelro; - srel = htab->elf.sreldynrelro; - } - else - { - s = htab->elf.sdynbss; - srel = htab->elf.srelbss; - } - if ((h->root.u.def.section->flags & SEC_ALLOC) != 0 && h->size != 0) - { - srel->size += sizeof (Elf32_External_Rel); - h->needs_copy = 1; - } - - return _bfd_elf_adjust_dynamic_copy (info, h, s); -} - -/* Allocate space in .plt, .got and associated reloc sections for - dynamic relocs. */ - -static bfd_boolean -elf_i386_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) -{ - struct bfd_link_info *info; - struct elf_x86_link_hash_table *htab; - struct elf_x86_link_hash_entry *eh; - struct elf_dyn_relocs *p; - unsigned plt_entry_size; - bfd_boolean resolved_to_zero; - const struct elf_i386_backend_data *bed; - - if (h->root.type == bfd_link_hash_indirect) - return TRUE; - - eh = (struct elf_x86_link_hash_entry *) h; - - info = (struct bfd_link_info *) inf; - htab = elf_x86_hash_table (info, I386_ELF_DATA); - if (htab == NULL) - return FALSE; - - bed = get_elf_i386_backend_data (info->output_bfd); - - plt_entry_size = htab->plt.plt_entry_size; - - resolved_to_zero = UNDEFINED_WEAK_RESOLVED_TO_ZERO (info, - I386_ELF_DATA, - eh->has_got_reloc, - eh); - - /* Clear the reference count of function pointer relocations if - symbol isn't a normal function. */ - if (h->type != STT_FUNC) - eh->func_pointer_refcount = 0; - - /* We can't use the GOT PLT if pointer equality is needed since - finish_dynamic_symbol won't clear symbol value and the dynamic - linker won't update the GOT slot. We will get into an infinite - loop at run-time. */ - if (htab->plt_got != NULL - && h->type != STT_GNU_IFUNC - && !h->pointer_equality_needed - && h->plt.refcount > 0 - && h->got.refcount > 0) - { - /* Don't use the regular PLT if there are both GOT and GOTPLT - reloctions. */ - h->plt.offset = (bfd_vma) -1; - - /* Use the GOT PLT. */ - eh->plt_got.refcount = 1; - } - - /* Since STT_GNU_IFUNC symbol must go through PLT, we handle it - here if it is defined and referenced in a non-shared object. */ - if (h->type == STT_GNU_IFUNC - && h->def_regular) - { - if (_bfd_elf_allocate_ifunc_dyn_relocs (info, h, &eh->dyn_relocs, - &htab->readonly_dynrelocs_against_ifunc, - plt_entry_size, - (htab->plt.has_plt0 - * plt_entry_size), - 4, TRUE)) - { - asection *s = htab->plt_second; - if (h->plt.offset != (bfd_vma) -1 && s != NULL) - { - /* Use the second PLT section if it is created. */ - eh->plt_second.offset = s->size; - - /* Make room for this entry in the second PLT section. */ - s->size += htab->non_lazy_plt->plt_entry_size; - } - - return TRUE; - } - else - return FALSE; - } - /* Don't create the PLT entry if there are only function pointer - relocations which can be resolved at run-time. */ - else if (htab->elf.dynamic_sections_created - && (h->plt.refcount > eh->func_pointer_refcount - || eh->plt_got.refcount > 0)) - { - bfd_boolean use_plt_got = eh->plt_got.refcount > 0; - - /* Clear the reference count of function pointer relocations - if PLT is used. */ - eh->func_pointer_refcount = 0; - - /* Make sure this symbol is output as a dynamic symbol. - Undefined weak syms won't yet be marked as dynamic. */ - if (h->dynindx == -1 - && !h->forced_local - && !resolved_to_zero - && h->root.type == bfd_link_hash_undefweak) - { - if (! bfd_elf_link_record_dynamic_symbol (info, h)) - return FALSE; - } - - if (bfd_link_pic (info) - || WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, 0, h)) - { - asection *s = htab->elf.splt; - asection *second_s = htab->plt_second; - asection *got_s = htab->plt_got; - - /* If this is the first .plt entry, make room for the special - first entry. The .plt section is used by prelink to undo - prelinking for dynamic relocations. */ - if (s->size == 0) - s->size = htab->plt.has_plt0 * plt_entry_size; - - if (use_plt_got) - eh->plt_got.offset = got_s->size; - else - { - h->plt.offset = s->size; - if (second_s) - eh->plt_second.offset = second_s->size; - } - - /* If this symbol is not defined in a regular file, and we are - not generating a shared library, then set the symbol to this - location in the .plt. This is required to make function - pointers compare as equal between the normal executable and - the shared library. */ - if (! bfd_link_pic (info) - && !h->def_regular) - { - if (use_plt_got) - { - /* We need to make a call to the entry of the GOT PLT - instead of regular PLT entry. */ - h->root.u.def.section = got_s; - h->root.u.def.value = eh->plt_got.offset; - } - else - { - if (second_s) - { - /* We need to make a call to the entry of the - second PLT instead of regular PLT entry. */ - h->root.u.def.section = second_s; - h->root.u.def.value = eh->plt_second.offset; - } - else - { - h->root.u.def.section = s; - h->root.u.def.value = h->plt.offset; - } - } - } - - /* Make room for this entry. */ - if (use_plt_got) - got_s->size += htab->non_lazy_plt->plt_entry_size; - else - { - s->size += plt_entry_size; - if (second_s) - second_s->size += htab->non_lazy_plt->plt_entry_size; - - /* We also need to make an entry in the .got.plt section, - which will be placed in the .got section by the linker - script. */ - htab->elf.sgotplt->size += 4; - - /* There should be no PLT relocation against resolved - undefined weak symbol in executable. */ - if (!resolved_to_zero) - { - /* We also need to make an entry in the .rel.plt - section. */ - htab->elf.srelplt->size += sizeof (Elf32_External_Rel); - htab->elf.srelplt->reloc_count++; - } - } - - if (bed->os == is_vxworks && !bfd_link_pic (info)) - { - /* VxWorks has a second set of relocations for each PLT entry - in executables. They go in a separate relocation section, - which is processed by the kernel loader. */ - - /* There are two relocations for the initial PLT entry: an - R_386_32 relocation for _GLOBAL_OFFSET_TABLE_ + 4 and an - R_386_32 relocation for _GLOBAL_OFFSET_TABLE_ + 8. */ - - asection *srelplt2 = htab->srelplt2; - if (h->plt.offset == plt_entry_size) - srelplt2->size += (sizeof (Elf32_External_Rel) * 2); - - /* There are two extra relocations for each subsequent PLT entry: - an R_386_32 relocation for the GOT entry, and an R_386_32 - relocation for the PLT entry. */ - - srelplt2->size += (sizeof (Elf32_External_Rel) * 2); - } - } - else - { - eh->plt_got.offset = (bfd_vma) -1; - h->plt.offset = (bfd_vma) -1; - h->needs_plt = 0; - } - } - else - { - eh->plt_got.offset = (bfd_vma) -1; - h->plt.offset = (bfd_vma) -1; - h->needs_plt = 0; - } - - eh->tlsdesc_got = (bfd_vma) -1; - - /* If R_386_TLS_{IE_32,IE,GOTIE} symbol is now local to the binary, - make it a R_386_TLS_LE_32 requiring no TLS entry. */ - if (h->got.refcount > 0 - && bfd_link_executable (info) - && h->dynindx == -1 - && (elf_x86_hash_entry (h)->tls_type & GOT_TLS_IE)) - h->got.offset = (bfd_vma) -1; - else if (h->got.refcount > 0) - { - asection *s; - bfd_boolean dyn; - int tls_type = elf_x86_hash_entry (h)->tls_type; - - /* Make sure this symbol is output as a dynamic symbol. - Undefined weak syms won't yet be marked as dynamic. */ - if (h->dynindx == -1 - && !h->forced_local - && !resolved_to_zero - && h->root.type == bfd_link_hash_undefweak) - { - if (! bfd_elf_link_record_dynamic_symbol (info, h)) - return FALSE; - } - - s = htab->elf.sgot; - if (GOT_TLS_GDESC_P (tls_type)) - { - eh->tlsdesc_got = htab->elf.sgotplt->size - - elf_i386_compute_jump_table_size (htab); - htab->elf.sgotplt->size += 8; - h->got.offset = (bfd_vma) -2; - } - if (! GOT_TLS_GDESC_P (tls_type) - || GOT_TLS_GD_P (tls_type)) - { - h->got.offset = s->size; - s->size += 4; - /* R_386_TLS_GD needs 2 consecutive GOT slots. */ - if (GOT_TLS_GD_P (tls_type) || tls_type == GOT_TLS_IE_BOTH) - s->size += 4; - } - dyn = htab->elf.dynamic_sections_created; - /* R_386_TLS_IE_32 needs one dynamic relocation, - R_386_TLS_IE resp. R_386_TLS_GOTIE needs one dynamic relocation, - (but if both R_386_TLS_IE_32 and R_386_TLS_IE is present, we - need two), R_386_TLS_GD needs one if local symbol and two if - global. No dynamic relocation against resolved undefined weak - symbol in executable. */ - if (tls_type == GOT_TLS_IE_BOTH) - htab->elf.srelgot->size += 2 * sizeof (Elf32_External_Rel); - else if ((GOT_TLS_GD_P (tls_type) && h->dynindx == -1) - || (tls_type & GOT_TLS_IE)) - htab->elf.srelgot->size += sizeof (Elf32_External_Rel); - else if (GOT_TLS_GD_P (tls_type)) - htab->elf.srelgot->size += 2 * sizeof (Elf32_External_Rel); - else if (! GOT_TLS_GDESC_P (tls_type) - && ((ELF_ST_VISIBILITY (h->other) == STV_DEFAULT - && !resolved_to_zero) - || h->root.type != bfd_link_hash_undefweak) - && (bfd_link_pic (info) - || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h))) - htab->elf.srelgot->size += sizeof (Elf32_External_Rel); - if (GOT_TLS_GDESC_P (tls_type)) - htab->elf.srelplt->size += sizeof (Elf32_External_Rel); - } - else - h->got.offset = (bfd_vma) -1; - - if (eh->dyn_relocs == NULL) - return TRUE; - - /* In the shared -Bsymbolic case, discard space allocated for - dynamic pc-relative relocs against symbols which turn out to be - defined in regular objects. For the normal shared case, discard - space for pc-relative relocs that have become local due to symbol - visibility changes. */ - - if (bfd_link_pic (info)) - { - /* The only reloc that uses pc_count is R_386_PC32, which will - appear on a call or on something like ".long foo - .". We - want calls to protected symbols to resolve directly to the - function rather than going via the plt. If people want - function pointer comparisons to work as expected then they - should avoid writing assembly like ".long foo - .". */ - if (SYMBOL_CALLS_LOCAL (info, h)) - { - struct elf_dyn_relocs **pp; - - for (pp = &eh->dyn_relocs; (p = *pp) != NULL; ) - { - p->count -= p->pc_count; - p->pc_count = 0; - if (p->count == 0) - *pp = p->next; - else - pp = &p->next; - } - } - - if (bed->os == is_vxworks) - { - struct elf_dyn_relocs **pp; - for (pp = &eh->dyn_relocs; (p = *pp) != NULL; ) - { - if (strcmp (p->sec->output_section->name, ".tls_vars") == 0) - *pp = p->next; - else - pp = &p->next; - } - } - - /* Also discard relocs on undefined weak syms with non-default - visibility or in PIE. */ - if (eh->dyn_relocs != NULL - && h->root.type == bfd_link_hash_undefweak) - { - /* Undefined weak symbol is never bound locally in shared - library. */ - if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT - || resolved_to_zero) - { - if (h->non_got_ref) - { - /* Keep dynamic non-GOT/non-PLT relocation so that we - can branch to 0 without PLT. */ - struct elf_dyn_relocs **pp; - - for (pp = &eh->dyn_relocs; (p = *pp) != NULL; ) - if (p->pc_count == 0) - *pp = p->next; - else - { - /* Remove non-R_386_PC32 relocation. */ - p->count = p->pc_count; - pp = &p->next; - } - - if (eh->dyn_relocs != NULL) - { - /* Make sure undefined weak symbols are output - as dynamic symbols in PIEs for dynamic non-GOT - non-PLT reloations. */ - if (! bfd_elf_link_record_dynamic_symbol (info, h)) - return FALSE; - } - } - else - eh->dyn_relocs = NULL; - } - else if (h->dynindx == -1 - && !h->forced_local) - { - if (! bfd_elf_link_record_dynamic_symbol (info, h)) - return FALSE; - } - } - } - else if (ELIMINATE_COPY_RELOCS) - { - /* For the non-shared case, discard space for relocs against - symbols which turn out to need copy relocs or are not - dynamic. Keep dynamic relocations for run-time function - pointer initialization. */ - - if ((!h->non_got_ref - || eh->func_pointer_refcount > 0 - || (h->root.type == bfd_link_hash_undefweak - && !resolved_to_zero)) - && ((h->def_dynamic - && !h->def_regular) - || (htab->elf.dynamic_sections_created - && (h->root.type == bfd_link_hash_undefweak - || h->root.type == bfd_link_hash_undefined)))) - { - /* Make sure this symbol is output as a dynamic symbol. - Undefined weak syms won't yet be marked as dynamic. */ - if (h->dynindx == -1 - && !h->forced_local - && !resolved_to_zero - && h->root.type == bfd_link_hash_undefweak) - { - if (! bfd_elf_link_record_dynamic_symbol (info, h)) - return FALSE; - } - - /* If that succeeded, we know we'll be keeping all the - relocs. */ - if (h->dynindx != -1) - goto keep; - } - - eh->dyn_relocs = NULL; - eh->func_pointer_refcount = 0; - - keep: ; - } - - /* Finally, allocate space. */ - for (p = eh->dyn_relocs; p != NULL; p = p->next) - { - asection *sreloc; - - sreloc = elf_section_data (p->sec)->sreloc; - - BFD_ASSERT (sreloc != NULL); - sreloc->size += p->count * sizeof (Elf32_External_Rel); - } - - return TRUE; -} - -/* Allocate space in .plt, .got and associated reloc sections for - local dynamic relocs. */ - -static bfd_boolean -elf_i386_allocate_local_dynrelocs (void **slot, void *inf) -{ - struct elf_link_hash_entry *h - = (struct elf_link_hash_entry *) *slot; - - if (h->type != STT_GNU_IFUNC - || !h->def_regular - || !h->ref_regular - || !h->forced_local - || h->root.type != bfd_link_hash_defined) - abort (); - - return elf_i386_allocate_dynrelocs (h, inf); -} - -/* Convert load via the GOT slot to load immediate. */ - -static bfd_boolean -elf_i386_convert_load (bfd *abfd, asection *sec, - struct bfd_link_info *link_info) -{ - struct elf_x86_link_hash_table *htab; - Elf_Internal_Shdr *symtab_hdr; - Elf_Internal_Rela *internal_relocs; - Elf_Internal_Rela *irel, *irelend; - bfd_byte *contents; - bfd_boolean changed; - bfd_signed_vma *local_got_refcounts; - - /* Don't even try to convert non-ELF outputs. */ - if (!is_elf_hash_table (link_info->hash)) - return FALSE; - - /* Nothing to do if there is no need or no output. */ - if ((sec->flags & (SEC_CODE | SEC_RELOC)) != (SEC_CODE | SEC_RELOC) - || sec->need_convert_load == 0 - || bfd_is_abs_section (sec->output_section)) - return TRUE; - - symtab_hdr = &elf_tdata (abfd)->symtab_hdr; - - /* Load the relocations for this section. */ - internal_relocs = (_bfd_elf_link_read_relocs - (abfd, sec, NULL, (Elf_Internal_Rela *) NULL, - link_info->keep_memory)); - if (internal_relocs == NULL) - return FALSE; - - changed = FALSE; - htab = elf_x86_hash_table (link_info, I386_ELF_DATA); - local_got_refcounts = elf_local_got_refcounts (abfd); - - /* Get the section contents. */ - if (elf_section_data (sec)->this_hdr.contents != NULL) - contents = elf_section_data (sec)->this_hdr.contents; - else - { - if (!bfd_malloc_and_get_section (abfd, sec, &contents)) - goto error_return; - } - - irelend = internal_relocs + sec->reloc_count; - for (irel = internal_relocs; irel < irelend; irel++) - { - unsigned int r_type = ELF32_R_TYPE (irel->r_info); - unsigned int r_symndx; - struct elf_link_hash_entry *h; - bfd_boolean converted; - - /* Don't convert R_386_GOT32 since we can't tell if it is applied - to "mov $foo@GOT, %reg" which isn't a load via GOT. */ - if (r_type != R_386_GOT32X) - continue; - - r_symndx = ELF32_R_SYM (irel->r_info); - if (r_symndx < symtab_hdr->sh_info) - h = _bfd_elf_x86_get_local_sym_hash (htab, sec->owner, - (const Elf_Internal_Rela *) irel, - FALSE); - else - { - h = elf_sym_hashes (abfd)[r_symndx - symtab_hdr->sh_info]; - while (h->root.type == bfd_link_hash_indirect - || h->root.type == bfd_link_hash_warning) - h = (struct elf_link_hash_entry *) h->root.u.i.link; - } - - /* STT_GNU_IFUNC must keep GOT32 relocations. */ - if (h != NULL && h->type == STT_GNU_IFUNC) - continue; - - converted = FALSE; - if (!elf_i386_convert_load_reloc (abfd, symtab_hdr, contents, - irel, h, &converted, link_info)) - goto error_return; - - if (converted) - { - changed = converted; - if (h) - { - if (h->got.refcount > 0) - h->got.refcount -= 1; - } - else - { - if (local_got_refcounts != NULL - && local_got_refcounts[r_symndx] > 0) - local_got_refcounts[r_symndx] -= 1; - } - } - } - - if (contents != NULL - && elf_section_data (sec)->this_hdr.contents != contents) - { - if (!changed && !link_info->keep_memory) - free (contents); - else - { - /* Cache the section contents for elf_link_input_bfd. */ - elf_section_data (sec)->this_hdr.contents = contents; - } - } - - if (elf_section_data (sec)->relocs != internal_relocs) - { - if (!changed) - free (internal_relocs); - else - elf_section_data (sec)->relocs = internal_relocs; - } - - return TRUE; - - error_return: - if (contents != NULL - && elf_section_data (sec)->this_hdr.contents != contents) - free (contents); - if (internal_relocs != NULL - && elf_section_data (sec)->relocs != internal_relocs) - free (internal_relocs); - return FALSE; -} - -/* Set the sizes of the dynamic sections. */ - -static bfd_boolean -elf_i386_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info) -{ - struct elf_x86_link_hash_table *htab; - bfd *dynobj; - asection *s; - bfd_boolean relocs; - bfd *ibfd; - - htab = elf_x86_hash_table (info, I386_ELF_DATA); - if (htab == NULL) - return FALSE; - dynobj = htab->elf.dynobj; - if (dynobj == NULL) - abort (); - - /* Set up .got offsets for local syms, and space for local dynamic - relocs. */ - for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next) - { - bfd_signed_vma *local_got; - bfd_signed_vma *end_local_got; - char *local_tls_type; - bfd_vma *local_tlsdesc_gotent; - bfd_size_type locsymcount; - Elf_Internal_Shdr *symtab_hdr; - asection *srel; - - if (! is_i386_elf (ibfd)) - continue; - - for (s = ibfd->sections; s != NULL; s = s->next) - { - struct elf_dyn_relocs *p; - - if (!elf_i386_convert_load (ibfd, s, info)) - return FALSE; - - for (p = ((struct elf_dyn_relocs *) - elf_section_data (s)->local_dynrel); - p != NULL; - p = p->next) - { - if (!bfd_is_abs_section (p->sec) - && bfd_is_abs_section (p->sec->output_section)) - { - /* Input section has been discarded, either because - it is a copy of a linkonce section or due to - linker script /DISCARD/, so we'll be discarding - the relocs too. */ - } - else if ((get_elf_i386_backend_data (output_bfd)->os - == is_vxworks) - && strcmp (p->sec->output_section->name, - ".tls_vars") == 0) - { - /* Relocations in vxworks .tls_vars sections are - handled specially by the loader. */ - } - else if (p->count != 0) - { - srel = elf_section_data (p->sec)->sreloc; - srel->size += p->count * sizeof (Elf32_External_Rel); - if ((p->sec->output_section->flags & SEC_READONLY) != 0 - && (info->flags & DF_TEXTREL) == 0) - { - info->flags |= DF_TEXTREL; - if ((info->warn_shared_textrel && bfd_link_pic (info)) - || info->error_textrel) - /* xgettext:c-format */ - info->callbacks->einfo (_("%P: %B: warning: relocation in readonly section `%A'\n"), - p->sec->owner, p->sec); - } - } - } - } - - local_got = elf_local_got_refcounts (ibfd); - if (!local_got) - continue; - - symtab_hdr = &elf_symtab_hdr (ibfd); - locsymcount = symtab_hdr->sh_info; - end_local_got = local_got + locsymcount; - local_tls_type = elf_x86_local_got_tls_type (ibfd); - local_tlsdesc_gotent = elf_x86_local_tlsdesc_gotent (ibfd); - s = htab->elf.sgot; - srel = htab->elf.srelgot; - for (; local_got < end_local_got; - ++local_got, ++local_tls_type, ++local_tlsdesc_gotent) - { - *local_tlsdesc_gotent = (bfd_vma) -1; - if (*local_got > 0) - { - if (GOT_TLS_GDESC_P (*local_tls_type)) - { - *local_tlsdesc_gotent = htab->elf.sgotplt->size - - elf_i386_compute_jump_table_size (htab); - htab->elf.sgotplt->size += 8; - *local_got = (bfd_vma) -2; - } - if (! GOT_TLS_GDESC_P (*local_tls_type) - || GOT_TLS_GD_P (*local_tls_type)) - { - *local_got = s->size; - s->size += 4; - if (GOT_TLS_GD_P (*local_tls_type) - || *local_tls_type == GOT_TLS_IE_BOTH) - s->size += 4; - } - if (bfd_link_pic (info) - || GOT_TLS_GD_ANY_P (*local_tls_type) - || (*local_tls_type & GOT_TLS_IE)) - { - if (*local_tls_type == GOT_TLS_IE_BOTH) - srel->size += 2 * sizeof (Elf32_External_Rel); - else if (GOT_TLS_GD_P (*local_tls_type) - || ! GOT_TLS_GDESC_P (*local_tls_type)) - srel->size += sizeof (Elf32_External_Rel); - if (GOT_TLS_GDESC_P (*local_tls_type)) - htab->elf.srelplt->size += sizeof (Elf32_External_Rel); - } - } - else - *local_got = (bfd_vma) -1; - } - } - - if (htab->tls_ld_or_ldm_got.refcount > 0) - { - /* Allocate 2 got entries and 1 dynamic reloc for R_386_TLS_LDM - relocs. */ - htab->tls_ld_or_ldm_got.offset = htab->elf.sgot->size; - htab->elf.sgot->size += 8; - htab->elf.srelgot->size += sizeof (Elf32_External_Rel); - } - else - htab->tls_ld_or_ldm_got.offset = -1; - - /* Allocate global sym .plt and .got entries, and space for global - sym dynamic relocs. */ - elf_link_hash_traverse (&htab->elf, elf_i386_allocate_dynrelocs, info); - - /* Allocate .plt and .got entries, and space for local symbols. */ - htab_traverse (htab->loc_hash_table, - elf_i386_allocate_local_dynrelocs, - info); - - /* For every jump slot reserved in the sgotplt, reloc_count is - incremented. However, when we reserve space for TLS descriptors, - it's not incremented, so in order to compute the space reserved - for them, it suffices to multiply the reloc count by the jump - slot size. - - PR ld/13302: We start next_irelative_index at the end of .rela.plt - so that R_386_IRELATIVE entries come last. */ - if (htab->elf.srelplt) - { - htab->next_tls_desc_index = htab->elf.srelplt->reloc_count; - htab->sgotplt_jump_table_size = htab->next_tls_desc_index * 4; - htab->next_irelative_index = htab->elf.srelplt->reloc_count - 1; - } - else if (htab->elf.irelplt) - htab->next_irelative_index = htab->elf.irelplt->reloc_count - 1; - - - if (htab->elf.sgotplt) - { - /* Don't allocate .got.plt section if there are no GOT nor PLT - entries and there is no reference to _GLOBAL_OFFSET_TABLE_. */ - if ((htab->elf.hgot == NULL - || !htab->elf.hgot->ref_regular_nonweak) - && (htab->elf.sgotplt->size - == get_elf_backend_data (output_bfd)->got_header_size) - && (htab->elf.splt == NULL - || htab->elf.splt->size == 0) - && (htab->elf.sgot == NULL - || htab->elf.sgot->size == 0) - && (htab->elf.iplt == NULL - || htab->elf.iplt->size == 0) - && (htab->elf.igotplt == NULL - || htab->elf.igotplt->size == 0)) - htab->elf.sgotplt->size = 0; - } - - if (_bfd_elf_eh_frame_present (info)) - { - if (htab->plt_eh_frame != NULL - && htab->elf.splt != NULL - && htab->elf.splt->size != 0 - && !bfd_is_abs_section (htab->elf.splt->output_section)) - htab->plt_eh_frame->size = htab->plt.eh_frame_plt_size; - - if (htab->plt_got_eh_frame != NULL - && htab->plt_got != NULL - && htab->plt_got->size != 0 - && !bfd_is_abs_section (htab->plt_got->output_section)) - htab->plt_got_eh_frame->size - = htab->non_lazy_plt->eh_frame_plt_size; - - /* Unwind info for the second PLT and .plt.got sections are - identical. */ - if (htab->plt_second_eh_frame != NULL - && htab->plt_second != NULL - && htab->plt_second->size != 0 - && !bfd_is_abs_section (htab->plt_second->output_section)) - htab->plt_second_eh_frame->size - = htab->non_lazy_plt->eh_frame_plt_size; - } - - /* We now have determined the sizes of the various dynamic sections. - Allocate memory for them. */ - relocs = FALSE; - for (s = dynobj->sections; s != NULL; s = s->next) - { - bfd_boolean strip_section = TRUE; - - if ((s->flags & SEC_LINKER_CREATED) == 0) - continue; - - if (s == htab->elf.splt - || s == htab->elf.sgot) - { - /* Strip this section if we don't need it; see the - comment below. */ - /* We'd like to strip these sections if they aren't needed, but if - we've exported dynamic symbols from them we must leave them. - It's too late to tell BFD to get rid of the symbols. */ - - if (htab->elf.hplt != NULL) - strip_section = FALSE; - } - else if (s == htab->elf.sgotplt - || s == htab->elf.iplt - || s == htab->elf.igotplt - || s == htab->plt_second - || s == htab->plt_got - || s == htab->plt_eh_frame - || s == htab->plt_got_eh_frame - || s == htab->plt_second_eh_frame - || s == htab->elf.sdynbss - || s == htab->elf.sdynrelro) - { - /* Strip these too. */ - } - else if (CONST_STRNEQ (bfd_get_section_name (dynobj, s), ".rel")) - { - if (s->size != 0 - && s != htab->elf.srelplt - && s != htab->srelplt2) - relocs = TRUE; - - /* We use the reloc_count field as a counter if we need - to copy relocs into the output file. */ - s->reloc_count = 0; - } - else - { - /* It's not one of our sections, so don't allocate space. */ - continue; - } - - if (s->size == 0) - { - /* If we don't need this section, strip it from the - output file. This is mostly to handle .rel.bss and - .rel.plt. We must create both sections in - create_dynamic_sections, because they must be created - before the linker maps input sections to output - sections. The linker does that before - adjust_dynamic_symbol is called, and it is that - function which decides whether anything needs to go - into these sections. */ - if (strip_section) - s->flags |= SEC_EXCLUDE; - continue; - } - - if ((s->flags & SEC_HAS_CONTENTS) == 0) - continue; + } - /* Allocate memory for the section contents. We use bfd_zalloc - here in case unused entries are not reclaimed before the - section's contents are written out. This should not happen, - but this way if it does, we get a R_386_NONE reloc instead - of garbage. */ - s->contents = (unsigned char *) bfd_zalloc (dynobj, s->size); - if (s->contents == NULL) - return FALSE; - } + p->count += 1; + /* Count size relocation as PC-relative relocation. */ + if (r_type == R_386_PC32 || size_reloc) + p->pc_count += 1; + } + break; - if (htab->plt_eh_frame != NULL - && htab->plt_eh_frame->contents != NULL) - { - memcpy (htab->plt_eh_frame->contents, - htab->plt.eh_frame_plt, - htab->plt_eh_frame->size); - bfd_put_32 (dynobj, htab->elf.splt->size, - htab->plt_eh_frame->contents + PLT_FDE_LEN_OFFSET); - } + /* This relocation describes the C++ object vtable hierarchy. + Reconstruct it for later use during GC. */ + case R_386_GNU_VTINHERIT: + if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset)) + goto error_return; + break; - if (htab->plt_got_eh_frame != NULL - && htab->plt_got_eh_frame->contents != NULL) - { - memcpy (htab->plt_got_eh_frame->contents, - htab->non_lazy_plt->eh_frame_plt, - htab->plt_got_eh_frame->size); - bfd_put_32 (dynobj, htab->plt_got->size, - (htab->plt_got_eh_frame->contents - + PLT_FDE_LEN_OFFSET)); - } + /* This relocation describes which C++ vtable entries are actually + used. Record for later use during GC. */ + case R_386_GNU_VTENTRY: + if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_offset)) + goto error_return; + break; - if (htab->plt_second_eh_frame != NULL - && htab->plt_second_eh_frame->contents != NULL) - { - memcpy (htab->plt_second_eh_frame->contents, - htab->non_lazy_plt->eh_frame_plt, - htab->plt_second_eh_frame->size); - bfd_put_32 (dynobj, htab->plt_second->size, - (htab->plt_second_eh_frame->contents - + PLT_FDE_LEN_OFFSET)); + default: + break; + } } - if (htab->elf.dynamic_sections_created) + if (elf_section_data (sec)->this_hdr.contents != contents) { - /* Add some entries to the .dynamic section. We fill in the - values later, in elf_i386_finish_dynamic_sections, but we - must add the entries now so that we get the correct size for - the .dynamic section. The DT_DEBUG entry is filled in by the - dynamic linker and used by the debugger. */ -#define add_dynamic_entry(TAG, VAL) \ - _bfd_elf_add_dynamic_entry (info, TAG, VAL) - - if (bfd_link_executable (info)) - { - if (!add_dynamic_entry (DT_DEBUG, 0)) - return FALSE; - } - - if (htab->elf.splt->size != 0) + if (!converted && !_bfd_link_keep_memory (info)) + free (contents); + else { - /* DT_PLTGOT is used by prelink even if there is no PLT - relocation. */ - if (!add_dynamic_entry (DT_PLTGOT, 0)) - return FALSE; + /* 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; } + } - if (htab->elf.srelplt->size != 0) - { - if (!add_dynamic_entry (DT_PLTRELSZ, 0) - || !add_dynamic_entry (DT_PLTREL, DT_REL) - || !add_dynamic_entry (DT_JMPREL, 0)) - return FALSE; - } + /* Cache relocations if any load is converted. */ + if (elf_section_data (sec)->relocs != relocs && converted) + elf_section_data (sec)->relocs = (Elf_Internal_Rela *) relocs; - if (relocs) - { - if (!add_dynamic_entry (DT_REL, 0) - || !add_dynamic_entry (DT_RELSZ, 0) - || !add_dynamic_entry (DT_RELENT, sizeof (Elf32_External_Rel))) - return FALSE; - - /* If any dynamic relocs apply to a read-only section, - then we need a DT_TEXTREL entry. */ - if ((info->flags & DF_TEXTREL) == 0) - elf_link_hash_traverse (&htab->elf, - _bfd_x86_elf_readonly_dynrelocs, - info); - - if ((info->flags & DF_TEXTREL) != 0) - { - if (htab->readonly_dynrelocs_against_ifunc) - { - info->callbacks->einfo - (_("%P%X: read-only segment has dynamic IFUNC relocations; recompile with -fPIC\n")); - bfd_set_error (bfd_error_bad_value); - return FALSE; - } + return true; - if (!add_dynamic_entry (DT_TEXTREL, 0)) - return FALSE; - } - } - if (get_elf_i386_backend_data (output_bfd)->os == is_vxworks - && !elf_vxworks_add_dynamic_entries (output_bfd, info)) - return FALSE; - } -#undef add_dynamic_entry + error_return: + if (elf_section_data (sec)->this_hdr.contents != contents) + free (contents); + sec->check_relocs_failed = 1; + return false; +} - return TRUE; +static bool +elf_i386_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_i386_scan_relocs)) + return false; + + return _bfd_x86_elf_always_size_sections (output_bfd, info); } /* Set the correct type for an x86 ELF section. We do this by the section name, which is a hack, but ought to work. */ -static bfd_boolean +static bool elf_i386_fake_sections (bfd *abfd ATTRIBUTE_UNUSED, Elf_Internal_Shdr *hdr, asection *sec) { const char *name; - name = bfd_get_section_name (abfd, sec); + name = bfd_section_name (sec); /* This is an ugly, but unfortunately necessary hack that is needed when producing EFI binaries on x86. It tells @@ -3204,7 +1970,7 @@ elf_i386_fake_sections (bfd *abfd ATTRIBUTE_UNUSED, if (strcmp (name, ".reloc") == 0) hdr->sh_type = SHT_PROGBITS; - return TRUE; + return true; } /* Return the relocation value for @tpoff relocation @@ -3228,7 +1994,7 @@ elf_i386_tpoff (struct bfd_link_info *info, bfd_vma address) /* Relocate an i386 ELF section. */ -static bfd_boolean +static int elf_i386_relocate_section (bfd *output_bfd, struct bfd_link_info *info, bfd *input_bfd, @@ -3246,27 +2012,31 @@ elf_i386_relocate_section (bfd *output_bfd, Elf_Internal_Rela *rel; Elf_Internal_Rela *wrel; Elf_Internal_Rela *relend; - bfd_boolean is_vxworks_tls; + bool is_vxworks_tls; unsigned plt_entry_size; - BFD_ASSERT (is_i386_elf (input_bfd)); - - /* 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, I386_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; + } + symtab_hdr = &elf_symtab_hdr (input_bfd); sym_hashes = elf_sym_hashes (input_bfd); local_got_offsets = elf_local_got_offsets (input_bfd); local_tlsdesc_gotents = elf_x86_local_tlsdesc_gotent (input_bfd); /* We have to handle relocations in vxworks .tls_vars sections specially, because the dynamic loader is 'weird'. */ - is_vxworks_tls = ((get_elf_i386_backend_data (output_bfd)->os - == is_vxworks) - && bfd_link_pic (info) + is_vxworks_tls = (htab->elf.target_os == is_vxworks + && bfd_link_pic (info) && !strcmp (input_section->output_section->name, ".tls_vars")); @@ -3278,7 +2048,7 @@ elf_i386_relocate_section (bfd *output_bfd, relend = relocs + input_section->reloc_count; for (; rel < relend; wrel++, rel++) { - unsigned int r_type; + unsigned int r_type, r_type_tls; reloc_howto_type *howto; unsigned long r_symndx; struct elf_link_hash_entry *h; @@ -3287,14 +2057,14 @@ elf_i386_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; unsigned int indx; int tls_type; bfd_vma st_size; asection *resolved_plt; - bfd_boolean resolved_to_zero; - bfd_boolean relative_reloc; + bool resolved_to_zero; + bool relative_reloc; r_type = ELF32_R_TYPE (rel->r_info); if (r_type == R_386_GNU_VTINHERIT @@ -3305,20 +2075,15 @@ elf_i386_relocate_section (bfd *output_bfd, continue; } - if ((indx = r_type) >= R_386_standard - && ((indx = r_type - R_386_ext_offset) - R_386_standard - >= R_386_ext - R_386_standard) - && ((indx = r_type - R_386_tls_offset) - R_386_ext - >= R_386_ext2 - R_386_ext)) + howto = elf_i386_rtype_to_howto (r_type); + if (howto == NULL) return _bfd_unrecognized_reloc (input_bfd, input_section, r_type); - howto = elf_howto_table + indx; - r_symndx = ELF32_R_SYM (rel->r_info); h = NULL; sym = NULL; sec = NULL; - unresolved_reloc = FALSE; + unresolved_reloc = false; if (r_symndx < symtab_hdr->sh_info) { sym = local_syms + r_symndx; @@ -3402,7 +2167,7 @@ elf_i386_relocate_section (bfd *output_bfd, { /* Relocate against local STT_GNU_IFUNC symbol. */ h = _bfd_elf_x86_get_local_sym_hash (htab, input_bfd, rel, - FALSE); + false); if (h == NULL) abort (); @@ -3413,8 +2178,8 @@ elf_i386_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, @@ -3426,7 +2191,7 @@ elf_i386_relocate_section (bfd *output_bfd, if (sec != NULL && discarded_section (sec)) { _bfd_clear_contents (howto, input_bfd, input_section, - contents + rel->r_offset); + contents, rel->r_offset); wrel->r_offset = rel->r_offset; wrel->r_info = 0; wrel->r_addend = 0; @@ -3462,6 +2227,10 @@ elf_i386_relocate_section (bfd *output_bfd, 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. */ @@ -3534,7 +2303,7 @@ elf_i386_relocate_section (bfd *output_bfd, { /* This references the local defitionion. We must initialize this entry in the global offset table. - Since the offset must always be a multiple of 8, + Since the offset must always be a multiple of 4, we use the least significant bit to record whether we have initialized it already. @@ -3594,7 +2363,7 @@ elf_i386_relocate_section (bfd *output_bfd, switch (r_type) { default: -bad_ifunc_reloc: + bad_ifunc_reloc: if (h->root.root.string) name = h->root.root.string; else @@ -3602,11 +2371,11 @@ bad_ifunc_reloc: NULL); _bfd_error_handler /* xgettext:c-format */ - (_("%B: relocation %s against STT_GNU_IFUNC " + (_("%pB: relocation %s against STT_GNU_IFUNC " "symbol `%s' isn't supported"), input_bfd, howto->name, name); bfd_set_error (bfd_error_bad_value); - return FALSE; + return false; case R_386_32: /* Generate dynamic relcoation only when there is a @@ -3618,7 +2387,7 @@ bad_ifunc_reloc: asection *sreloc; bfd_vma offset; -do_ifunc_pointer: + do_ifunc_pointer: /* Need a dynamic relocation to get the real function adddress. */ offset = _bfd_elf_section_offset (output_bfd, @@ -3633,16 +2402,20 @@ do_ifunc_pointer: + input_section->output_offset + offset); - if (h->dynindx == -1 - || h->forced_local - || bfd_link_executable (info)) + if (POINTER_LOCAL_IFUNC_P (info, h)) { - info->callbacks->minfo (_("Local IFUNC function `%s' in %B\n"), + info->callbacks->minfo (_("Local IFUNC function `%s' in %pB\n"), h->root.root.string, h->root.u.def.section->owner); /* This symbol is resolved locally. */ outrel.r_info = ELF32_R_INFO (0, R_386_IRELATIVE); + + if (htab->params->report_relative_reloc) + _bfd_x86_elf_link_report_relative_reloc + (info, input_section, h, sym, + "R_386_IRELATIVE", &outrel); + bfd_put_32 (output_bfd, (h->root.u.def.value + h->root.u.def.section->output_section->vma @@ -3683,103 +2456,29 @@ do_ifunc_pointer: } } + skip_ifunc: resolved_to_zero = (eh != NULL - && UNDEFINED_WEAK_RESOLVED_TO_ZERO (info, - I386_ELF_DATA, - eh->has_got_reloc, - eh)); + && UNDEFINED_WEAK_RESOLVED_TO_ZERO (info, eh)); switch (r_type) { case R_386_GOT32X: - /* Avoid optimizing _DYNAMIC since ld.so may use its - link-time address. */ - if (h == htab->elf.hdynamic) - goto r_386_got32; - - if (bfd_link_pic (info)) - { - /* It is OK to convert mov to lea and convert indirect - branch to direct branch. It is OK to convert adc, - add, and, cmp, or, sbb, sub, test, xor only when PIC - is false. */ - unsigned int opcode, addend; - addend = bfd_get_32 (input_bfd, contents + rel->r_offset); - if (addend != 0) - goto r_386_got32; - opcode = bfd_get_8 (input_bfd, contents + rel->r_offset - 2); - if (opcode != 0x8b && opcode != 0xff) - goto r_386_got32; - } - - /* Resolve "mov GOT[(%reg)], %reg", - "call/jmp *GOT[(%reg)]", "test %reg, foo@GOT[(%reg)]" - and "binop foo@GOT[(%reg)], %reg". */ - if (h == NULL - || (h->plt.offset == (bfd_vma) -1 - && h->got.offset == (bfd_vma) -1) - || htab->elf.sgotplt == NULL) - abort (); - - offplt = (htab->elf.sgotplt->output_section->vma - + htab->elf.sgotplt->output_offset); - - /* It is relative to .got.plt section. */ - if (h->got.offset != (bfd_vma) -1) - /* Use GOT entry. Mask off the least significant bit in - GOT offset which may be set by R_386_GOT32 processing - below. */ - relocation = (htab->elf.sgot->output_section->vma - + htab->elf.sgot->output_offset - + (h->got.offset & ~1) - offplt); - else - /* Use GOTPLT entry. */ - relocation = (h->plt.offset / plt_entry_size - - htab->plt.has_plt0 + 3) * 4; - - if (!bfd_link_pic (info)) - { - /* If not PIC, add the .got.plt section address for - baseless addressing. */ - unsigned int modrm; - modrm = bfd_get_8 (input_bfd, contents + rel->r_offset - 1); - if ((modrm & 0xc7) == 0x5) - relocation += offplt; - } - - unresolved_reloc = FALSE; - break; - case R_386_GOT32: -r_386_got32: /* Relocation is to the entry for this symbol in the global offset table. */ if (htab->elf.sgot == NULL) abort (); - relative_reloc = FALSE; + relative_reloc = false; if (h != NULL) { - bfd_boolean dyn; - off = h->got.offset; - dyn = htab->elf.dynamic_sections_created; - if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, - bfd_link_pic (info), - h) - || (bfd_link_pic (info) - && SYMBOL_REFERENCES_LOCAL (info, h)) - || (ELF_ST_VISIBILITY (h->other) - && h->root.type == bfd_link_hash_undefweak)) + if (RESOLVED_LOCALLY_P (info, h, htab)) { - /* This is actually a static link, or it is a - -Bsymbolic link and the symbol is defined - locally, or the symbol was forced to be local - because of a version file. We must initialize - this entry in the global offset table. Since the - offset must always be a multiple of 4, we use the - least significant bit to record whether we have - initialized it already. + /* We must initialize this entry in the global offset + table. Since the offset must always be a multiple + of 4, we use the least significant bit to record + whether we have initialized it already. When doing a dynamic link, we create a .rel.got relocation entry to initialize the value. This @@ -3791,21 +2490,20 @@ r_386_got32: bfd_put_32 (output_bfd, relocation, htab->elf.sgot->contents + off); h->got.offset |= 1; - - if (h->dynindx == -1 - && !h->forced_local - && h->root.type != bfd_link_hash_undefweak - && bfd_link_pic (info)) + /* 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)) { /* PR ld/21402: If this symbol isn't dynamic in PIC, generate R_386_RELATIVE here. */ eh->no_finish_dynamic_symbol = 1; - relative_reloc = TRUE; + relative_reloc = true; } } } else - unresolved_reloc = FALSE; + unresolved_reloc = false; } else { @@ -3825,8 +2523,10 @@ r_386_got32: htab->elf.sgot->contents + off); local_got_offsets[r_symndx] |= 1; - if (bfd_link_pic (info)) - relative_reloc = TRUE; + /* NB: Don't generate relative relocation here if it + has been generated by DT_RELR. */ + if (!info->enable_dt_relr && bfd_link_pic (info)) + relative_reloc = true; } } @@ -3843,6 +2543,12 @@ r_386_got32: + htab->elf.sgot->output_offset + off); outrel.r_info = ELF32_R_INFO (0, R_386_RELATIVE); + + if (htab->params->report_relative_reloc) + _bfd_x86_elf_link_report_relative_reloc + (info, input_section, h, sym, "R_386_RELATIVE", + &outrel); + elf_append_rel (output_bfd, s, &outrel); } @@ -3862,7 +2568,7 @@ r_386_got32: we don't know what the GOT base is. */ const char *name; -disallow_got32: + disallow_got32: if (h == NULL || h->root.root.string == NULL) name = bfd_elf_sym_name (input_bfd, symtab_hdr, sym, NULL); @@ -3871,12 +2577,12 @@ disallow_got32: _bfd_error_handler /* xgettext:c-format */ - (_("%B: direct GOT relocation %s against `%s'" + (_("%pB: direct GOT relocation %s against `%s'" " without base register can not be used" " when making a shared object"), input_bfd, howto->name, name); bfd_set_error (bfd_error_bad_value); - return FALSE; + return false; } } else @@ -3921,26 +2627,26 @@ disallow_got32: _bfd_error_handler /* xgettext:c-format */ - (_("%B: relocation R_386_GOTOFF against undefined %s" + (_("%pB: relocation R_386_GOTOFF against undefined %s" " `%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 (!SYMBOL_REFERENCES_LOCAL (info, h) + else if (!SYMBOL_REFERENCES_LOCAL_P (info, h) && (h->type == STT_FUNC || h->type == STT_OBJECT) && ELF_ST_VISIBILITY (h->other) == STV_PROTECTED) { _bfd_error_handler /* xgettext:c-format */ - (_("%B: relocation R_386_GOTOFF against protected %s" + (_("%pB: relocation R_386_GOTOFF against protected %s" " `%s' can not be used when making a shared object"), input_bfd, h->type == STT_FUNC ? "function" : "data", h->root.root.string); bfd_set_error (bfd_error_bad_value); - return FALSE; + return false; } } @@ -3957,7 +2663,7 @@ disallow_got32: /* 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_386_PLT32: @@ -4001,7 +2707,7 @@ disallow_got32: relocation = (resolved_plt->output_section->vma + resolved_plt->output_offset + plt_offset); - unresolved_reloc = FALSE; + unresolved_reloc = false; break; case R_386_SIZE32: @@ -4015,76 +2721,68 @@ disallow_got32: || is_vxworks_tls) break; - /* Copy dynamic function pointer relocations. Don't generate - dynamic relocations against resolved undefined weak symbols - in PIE, except for R_386_PC32. */ - if ((bfd_link_pic (info) - && (h == NULL - || ((ELF_ST_VISIBILITY (h->other) == STV_DEFAULT - && (!resolved_to_zero - || r_type == R_386_PC32)) - || h->root.type != bfd_link_hash_undefweak)) - && ((r_type != R_386_PC32 && r_type != R_386_SIZE32) - || !SYMBOL_CALLS_LOCAL (info, h))) - || (ELIMINATE_COPY_RELOCS - && !bfd_link_pic (info) - && h != NULL - && h->dynindx != -1 - && (!h->non_got_ref - || eh->func_pointer_refcount > 0 - || (h->root.type == bfd_link_hash_undefweak - && !resolved_to_zero)) - && ((h->def_dynamic && !h->def_regular) - /* Undefined weak symbol is bound locally when - PIC is false. */ - || h->root.type == bfd_link_hash_undefweak))) + if (GENERATE_DYNAMIC_RELOCATION_P (false, info, eh, r_type, + sec, false, + resolved_to_zero, + (r_type == R_386_PC32))) { Elf_Internal_Rela outrel; - bfd_boolean skip, relocate; + bool skip, relocate; + bool generate_dynamic_reloc = true; asection *sreloc; /* 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); if (skip) memset (&outrel, 0, sizeof outrel); - else if (h != NULL - && h->dynindx != -1 - && (r_type == R_386_PC32 - || !(bfd_link_executable (info) - || SYMBOLIC_BIND (info, h)) - || !h->def_regular)) + else if (COPY_INPUT_RELOC_P (false, info, h, r_type)) outrel.r_info = ELF32_R_INFO (h->dynindx, r_type); else { /* This symbol is local, or marked to become local. */ - relocate = TRUE; - outrel.r_info = ELF32_R_INFO (0, R_386_RELATIVE); - } + 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 = ELF32_R_INFO (0, R_386_RELATIVE); - sreloc = elf_section_data (input_section)->sreloc; + if (htab->params->report_relative_reloc) + _bfd_x86_elf_link_report_relative_reloc + (info, input_section, h, sym, "R_386_RELATIVE", + &outrel); + } + } - 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_rel (output_bfd, sreloc, &outrel); + if (sreloc == NULL || sreloc->contents == NULL) + { + r = bfd_reloc_notsupported; + goto check_relocation_error; + } + + elf_append_rel (output_bfd, sreloc, &outrel); + } /* If this reloc is against an external symbol, we do not want to fiddle with the addend. Otherwise, we @@ -4105,6 +2803,12 @@ disallow_got32: + input_section->output_section->vma + input_section->output_offset; outrel.r_info = ELF32_R_INFO (0, R_386_RELATIVE); + + if (htab->params->report_relative_reloc) + _bfd_x86_elf_link_report_relative_reloc + (info, input_section, h, sym, "R_386_RELATIVE", + &outrel); + sreloc = elf_section_data (input_section)->sreloc; if (sreloc == NULL) abort (); @@ -4125,17 +2829,18 @@ disallow_got32: if (tls_type == GOT_TLS_IE) tls_type = GOT_TLS_IE_NEG; + r_type_tls = r_type; if (! elf_i386_tls_transition (info, input_bfd, input_section, contents, symtab_hdr, sym_hashes, - &r_type, tls_type, rel, - relend, h, r_symndx, TRUE)) - return FALSE; + &r_type_tls, tls_type, rel, + relend, h, r_symndx, true)) + return false; - if (r_type == R_386_TLS_LE_32) + if (r_type_tls == R_386_TLS_LE_32) { BFD_ASSERT (! unresolved_reloc); - if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_GD) + if (r_type == R_386_TLS_GD) { unsigned int type; bfd_vma roff; @@ -4178,7 +2883,7 @@ disallow_got32: wrel++; continue; } - else if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_GOTDESC) + else if (r_type == R_386_TLS_GOTDESC) { /* GDesc -> LE transition. It's originally something like: @@ -4203,7 +2908,7 @@ disallow_got32: contents + roff); continue; } - else if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_DESC_CALL) + else if (r_type == R_386_TLS_DESC_CALL) { /* GDesc -> LE transition. It's originally: @@ -4218,7 +2923,7 @@ disallow_got32: bfd_put_8 (output_bfd, 0x90, contents + roff + 1); continue; } - else if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_IE) + else if (r_type == R_386_TLS_IE) { unsigned int val; @@ -4312,7 +3017,7 @@ disallow_got32: } else BFD_FAIL (); - if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_GOTIE) + if (r_type == R_386_TLS_GOTIE) bfd_put_32 (output_bfd, -elf_i386_tpoff (info, relocation), contents + rel->r_offset); else @@ -4418,7 +3123,7 @@ disallow_got32: { if (indx == 0) { - BFD_ASSERT (! unresolved_reloc); + BFD_ASSERT (! unresolved_reloc); bfd_put_32 (output_bfd, relocation - _bfd_x86_elf_dtpoff_base (info), htab->elf.sgot->contents + off + 4); @@ -4455,13 +3160,13 @@ disallow_got32: if (off >= (bfd_vma) -2 && ! GOT_TLS_GDESC_P (tls_type)) abort (); - if (r_type == R_386_TLS_GOTDESC - || r_type == R_386_TLS_DESC_CALL) + if (r_type_tls == R_386_TLS_GOTDESC + || r_type_tls == R_386_TLS_DESC_CALL) { relocation = htab->sgotplt_jump_table_size + offplt; - unresolved_reloc = FALSE; + unresolved_reloc = false; } - else if (r_type == ELF32_R_TYPE (rel->r_info)) + else if (r_type_tls == r_type) { bfd_vma g_o_t = htab->elf.sgotplt->output_section->vma + htab->elf.sgotplt->output_offset; @@ -4472,9 +3177,9 @@ disallow_got32: relocation += 4; if (r_type == R_386_TLS_IE) relocation += g_o_t; - unresolved_reloc = FALSE; + unresolved_reloc = false; } - else if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_GD) + else if (r_type == R_386_TLS_GD) { unsigned int val, type; bfd_vma roff; @@ -4530,7 +3235,7 @@ disallow_got32: wrel++; continue; } - else if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_GOTDESC) + else if (r_type == R_386_TLS_GOTDESC) { /* GDesc -> IE transition. It's originally something like: @@ -4569,7 +3274,7 @@ disallow_got32: contents + roff); continue; } - else if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_DESC_CALL) + else if (r_type == R_386_TLS_DESC_CALL) { /* GDesc -> IE transition. It's originally: @@ -4603,7 +3308,7 @@ disallow_got32: continue; } else - BFD_ASSERT (FALSE); + BFD_ASSERT (false); break; case R_386_TLS_LDM: @@ -4611,8 +3316,8 @@ disallow_got32: 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_386_TLS_LDM) { @@ -4673,7 +3378,7 @@ disallow_got32: + htab->elf.sgot->output_offset + off - htab->elf.sgotplt->output_section->vma - htab->elf.sgotplt->output_offset; - unresolved_reloc = FALSE; + unresolved_reloc = false; break; case R_386_TLS_LDO_32: @@ -4735,21 +3440,21 @@ disallow_got32: { _bfd_error_handler /* xgettext:c-format */ - (_("%B(%A+%#Lx): unresolvable %s relocation against symbol `%s'"), + (_("%pB(%pA+%#" PRIx64 "): unresolvable %s relocation against symbol `%s'"), input_bfd, input_section, - rel->r_offset, + (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, 0); -check_relocation_error: + check_relocation_error: if (r != bfd_reloc_ok) { const char *name; @@ -4762,9 +3467,9 @@ check_relocation_error: symtab_hdr->sh_link, sym->st_name); if (name == NULL) - return FALSE; + return false; if (*name == '\0') - name = bfd_section_name (input_bfd, sec); + name = bfd_section_name (sec); } if (r == bfd_reloc_overflow) @@ -4775,10 +3480,10 @@ check_relocation_error: { _bfd_error_handler /* xgettext:c-format */ - (_("%B(%A+%#Lx): reloc against `%s': error %d"), + (_("%pB(%pA+%#" PRIx64 "): reloc against `%s': error %d"), input_bfd, input_section, - rel->r_offset, name, (int) r); - return FALSE; + (uint64_t) rel->r_offset, name, (int) r); + return false; } } @@ -4806,13 +3511,13 @@ check_relocation_error: input_section->reloc_count -= deleted; } - return TRUE; + return true; } /* Finish up dynamic symbol handling. We set the contents of various dynamic sections here. */ -static bfd_boolean +static bool elf_i386_finish_dynamic_symbol (bfd *output_bfd, struct bfd_link_info *info, struct elf_link_hash_entry *h, @@ -4820,16 +3525,14 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd, { struct elf_x86_link_hash_table *htab; unsigned plt_entry_size; - const struct elf_i386_backend_data *abed; struct elf_x86_link_hash_entry *eh; - bfd_boolean local_undefweak; - bfd_boolean use_plt_second; + bool local_undefweak; + bool use_plt_second; htab = elf_x86_hash_table (info, I386_ELF_DATA); if (htab == NULL) - return FALSE; + return false; - abed = get_elf_i386_backend_data (output_bfd); plt_entry_size = htab->plt.plt_entry_size; /* Use the second PLT section only if there is .plt section. */ @@ -4842,9 +3545,7 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd, /* We keep PLT/GOT entries without dynamic PLT/GOT relocations for resolved undefined weak symbols in executable so that their references have value 0 at run-time. */ - local_undefweak = UNDEFINED_WEAK_RESOLVED_TO_ZERO (info, I386_ELF_DATA, - eh->has_got_reloc, - eh); + local_undefweak = UNDEFINED_WEAK_RESOLVED_TO_ZERO (info, eh); if (h->plt.offset != (bfd_vma) -1) { @@ -4869,18 +3570,7 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd, relplt = htab->elf.irelplt; } - /* This symbol has an entry in the procedure linkage table. Set - it up. */ - - if ((h->dynindx == -1 - && !local_undefweak - && !((h->forced_local || bfd_link_executable (info)) - && h->def_regular - && h->type == STT_GNU_IFUNC)) - || plt == NULL - || gotplt == NULL - || relplt == NULL) - abort (); + VERIFY_PLT_ENTRY (info, h, plt, gotplt, relplt, local_undefweak) /* Get the index in the procedure linkage table which corresponds to this symbol. This is the index of this symbol @@ -4936,9 +3626,9 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd, + gotplt->output_offset + got_offset), resolved_plt->contents + plt_offset - + htab->plt.plt_got_offset); + + htab->plt.plt_got_offset); - if (abed->os == is_vxworks) + if (htab->elf.target_os == is_vxworks) { int s, k, reloc_index; @@ -4947,7 +3637,7 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd, /* S: Current slot number (zero-based). */ s = ((h->plt.offset - htab->plt.plt_entry_size) - / htab->plt.plt_entry_size); + / htab->plt.plt_entry_size); /* K: Number of relocations for PLTResolve. */ if (bfd_link_pic (info)) k = PLTRESOLVE_RELOCS_SHLIB; @@ -4979,7 +3669,7 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd, { bfd_put_32 (output_bfd, got_offset, resolved_plt->contents + plt_offset - + htab->plt.plt_got_offset); + + htab->plt.plt_got_offset); } /* Fill in the entry in the global offset table. Leave the entry @@ -4999,13 +3689,9 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd, rel.r_offset = (gotplt->output_section->vma + gotplt->output_offset + got_offset); - if (h->dynindx == -1 - || ((bfd_link_executable (info) - || ELF_ST_VISIBILITY (h->other) != STV_DEFAULT) - && h->def_regular - && h->type == STT_GNU_IFUNC)) + if (PLT_LOCAL_IFUNC_P (info, h)) { - info->callbacks->minfo (_("Local IFUNC function `%s' in %B\n"), + info->callbacks->minfo (_("Local IFUNC function `%s' in %pB\n"), h->root.root.string, h->root.u.def.section->owner); @@ -5018,6 +3704,11 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd, + h->root.u.def.section->output_offset), gotplt->contents + got_offset); rel.r_info = ELF32_R_INFO (0, R_386_IRELATIVE); + + if (htab->params->report_relative_reloc) + _bfd_x86_elf_link_report_relative_reloc + (info, relplt, h, sym, "R_386_IRELATIVE", &rel); + /* R_386_IRELATIVE comes last. */ plt_index = htab->next_irelative_index--; } @@ -5105,6 +3796,8 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd, 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 @@ -5114,6 +3807,8 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd, { Elf_Internal_Rela rel; 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. */ @@ -5142,9 +3837,9 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd, in static executable. */ relgot = htab->elf.irelplt; } - if (SYMBOL_REFERENCES_LOCAL (info, h)) + if (SYMBOL_REFERENCES_LOCAL_P (info, h)) { - info->callbacks->minfo (_("Local IFUNC function `%s' in %B\n"), + info->callbacks->minfo (_("Local IFUNC function `%s' in %pB\n"), h->root.root.string, h->root.u.def.section->owner); @@ -5154,6 +3849,7 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd, + h->root.u.def.section->output_offset), htab->elf.sgot->contents + h->got.offset); rel.r_info = ELF32_R_INFO (0, R_386_IRELATIVE); + relative_reloc_name = "R_386_IRELATIVE"; } else goto do_glob_dat; @@ -5188,25 +3884,39 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd, (plt->output_section->vma + 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 (info, h)) + && SYMBOL_REFERENCES_LOCAL_P (info, h)) { BFD_ASSERT((h->got.offset & 1) != 0); - rel.r_info = ELF32_R_INFO (0, R_386_RELATIVE); + if (info->enable_dt_relr) + generate_dynamic_reloc = false; + else + { + rel.r_info = ELF32_R_INFO (0, R_386_RELATIVE); + relative_reloc_name = "R_386_RELATIVE"; + } } else { BFD_ASSERT((h->got.offset & 1) == 0); -do_glob_dat: + do_glob_dat: bfd_put_32 (output_bfd, (bfd_vma) 0, htab->elf.sgot->contents + h->got.offset); rel.r_info = ELF32_R_INFO (h->dynindx, R_386_GLOB_DAT); } - elf_append_rel (output_bfd, relgot, &rel); + 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, &rel); + + elf_append_rel (output_bfd, relgot, &rel); + } } if (h->needs_copy) @@ -5215,13 +3925,7 @@ do_glob_dat: asection *s; /* This symbol needs a copy reloc. Set it up. */ - - if (h->dynindx == -1 - || (h->root.type != bfd_link_hash_defined - && h->root.type != bfd_link_hash_defweak) - || htab->elf.srelbss == NULL - || htab->elf.sreldynrelro == NULL) - abort (); + VERIFY_COPY_RELOC (h, htab) rel.r_offset = (h->root.u.def.value + h->root.u.def.section->output_section->vma @@ -5234,13 +3938,13 @@ do_glob_dat: elf_append_rel (output_bfd, s, &rel); } - 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_i386_finish_local_dynamic_symbol (void **slot, void *inf) { struct elf_link_hash_entry *h @@ -5256,7 +3960,7 @@ elf_i386_finish_local_dynamic_symbol (void **slot, void *inf) here since undefined weak symbol may not be dynamic and may not be called for elf_i386_finish_dynamic_symbol. */ -static bfd_boolean +static bool elf_i386_pie_finish_undefweak_symbol (struct bfd_hash_entry *bh, void *inf) { @@ -5265,7 +3969,7 @@ elf_i386_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_i386_finish_dynamic_symbol (info->output_bfd, info, h, NULL); @@ -5287,7 +3991,7 @@ elf_i386_reloc_type_class (const struct bfd_link_info *info, && htab->dynsym->contents != NULL) { /* Check relocation against STT_GNU_IFUNC symbol if there are - dynamic symbols. */ + dynamic symbols. */ unsigned long r_symndx = ELF32_R_SYM (rela->r_info); if (r_symndx != STN_UNDEF) { @@ -5320,274 +4024,119 @@ elf_i386_reloc_type_class (const struct bfd_link_info *info, /* Finish up the dynamic sections. */ -static bfd_boolean +static bool elf_i386_finish_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info) { struct elf_x86_link_hash_table *htab; - bfd *dynobj; - asection *sdyn; - const struct elf_i386_backend_data *abed; - htab = elf_x86_hash_table (info, I386_ELF_DATA); + htab = _bfd_x86_elf_finish_dynamic_sections (output_bfd, info); if (htab == NULL) - return FALSE; + return false; - dynobj = htab->elf.dynobj; - sdyn = bfd_get_linker_section (dynobj, ".dynamic"); - abed = get_elf_i386_backend_data (output_bfd); + if (!htab->elf.dynamic_sections_created) + return true; - if (htab->elf.dynamic_sections_created) + if (htab->elf.splt && htab->elf.splt->size > 0) { - Elf32_External_Dyn *dyncon, *dynconend; - - if (sdyn == NULL || htab->elf.sgot == NULL) - abort (); - - dyncon = (Elf32_External_Dyn *) sdyn->contents; - dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->size); - for (; dyncon < dynconend; dyncon++) + if (bfd_is_abs_section (htab->elf.splt->output_section)) { - Elf_Internal_Dyn dyn; - asection *s; - - bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn); - - switch (dyn.d_tag) - { - default: - if (abed->os == is_vxworks - && elf_vxworks_finish_dynamic_entry (output_bfd, &dyn)) - break; - continue; - - case DT_PLTGOT: - s = htab->elf.sgotplt; - dyn.d_un.d_ptr = s->output_section->vma + s->output_offset; - break; - - case DT_JMPREL: - s = htab->elf.srelplt; - dyn.d_un.d_ptr = s->output_section->vma + s->output_offset; - break; - - case DT_PLTRELSZ: - s = htab->elf.srelplt; - dyn.d_un.d_val = s->size; - break; - } - - bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon); + info->callbacks->einfo + (_("%F%P: discarded output section: `%pA'\n"), + htab->elf.splt); + return false; } - if (htab->elf.splt && htab->elf.splt->size > 0) - { - /* UnixWare sets the entsize of .plt to 4, although that doesn't - really seem like the right value. */ - elf_section_data (htab->elf.splt->output_section) - ->this_hdr.sh_entsize = 4; + /* UnixWare sets the entsize of .plt to 4, although that doesn't + really seem like the right value. */ + elf_section_data (htab->elf.splt->output_section) + ->this_hdr.sh_entsize = 4; - if (htab->plt.has_plt0) + if (htab->plt.has_plt0) + { + /* Fill in the special first entry in the procedure linkage + table. */ + memcpy (htab->elf.splt->contents, htab->plt.plt0_entry, + htab->lazy_plt->plt0_entry_size); + memset (htab->elf.splt->contents + htab->lazy_plt->plt0_entry_size, + htab->plt0_pad_byte, + htab->plt.plt_entry_size - htab->lazy_plt->plt0_entry_size); + if (!bfd_link_pic (info)) { - /* Fill in the special first entry in the procedure linkage - table. */ - memcpy (htab->elf.splt->contents, htab->plt.plt0_entry, - htab->lazy_plt->plt0_entry_size); - memset (htab->elf.splt->contents + htab->lazy_plt->plt0_entry_size, - abed->plt0_pad_byte, - htab->plt.plt_entry_size - htab->lazy_plt->plt0_entry_size); - if (!bfd_link_pic (info)) + bfd_put_32 (output_bfd, + (htab->elf.sgotplt->output_section->vma + + htab->elf.sgotplt->output_offset + + 4), + htab->elf.splt->contents + + htab->lazy_plt->plt0_got1_offset); + bfd_put_32 (output_bfd, + (htab->elf.sgotplt->output_section->vma + + htab->elf.sgotplt->output_offset + + 8), + htab->elf.splt->contents + + htab->lazy_plt->plt0_got2_offset); + + if (htab->elf.target_os == is_vxworks) { - bfd_put_32 (output_bfd, - (htab->elf.sgotplt->output_section->vma - + htab->elf.sgotplt->output_offset - + 4), - htab->elf.splt->contents - + htab->lazy_plt->plt0_got1_offset); - bfd_put_32 (output_bfd, - (htab->elf.sgotplt->output_section->vma - + htab->elf.sgotplt->output_offset - + 8), - htab->elf.splt->contents - + htab->lazy_plt->plt0_got2_offset); + Elf_Internal_Rela rel; + int num_plts = (htab->elf.splt->size + / htab->plt.plt_entry_size) - 1; + unsigned char *p; + asection *srelplt2 = htab->srelplt2; + + /* Generate a relocation for _GLOBAL_OFFSET_TABLE_ + + 4. On IA32 we use REL relocations so the + addend goes in the PLT directly. */ + rel.r_offset = (htab->elf.splt->output_section->vma + + htab->elf.splt->output_offset + + htab->lazy_plt->plt0_got1_offset); + rel.r_info = ELF32_R_INFO (htab->elf.hgot->indx, + R_386_32); + bfd_elf32_swap_reloc_out (output_bfd, &rel, + srelplt2->contents); + /* Generate a relocation for _GLOBAL_OFFSET_TABLE_ + + 8. */ + rel.r_offset = (htab->elf.splt->output_section->vma + + htab->elf.splt->output_offset + + htab->lazy_plt->plt0_got2_offset); + rel.r_info = ELF32_R_INFO (htab->elf.hgot->indx, + R_386_32); + bfd_elf32_swap_reloc_out (output_bfd, &rel, + srelplt2->contents + + sizeof (Elf32_External_Rel)); + /* Correct the .rel.plt.unloaded relocations. */ + p = srelplt2->contents; + if (bfd_link_pic (info)) + p += PLTRESOLVE_RELOCS_SHLIB * sizeof (Elf32_External_Rel); + else + p += PLTRESOLVE_RELOCS * sizeof (Elf32_External_Rel); - if (abed->os == is_vxworks) + for (; num_plts; num_plts--) { - Elf_Internal_Rela rel; - int num_plts = (htab->elf.splt->size - / htab->plt.plt_entry_size) - 1; - unsigned char *p; - asection *srelplt2 = htab->srelplt2; - - /* Generate a relocation for _GLOBAL_OFFSET_TABLE_ - + 4. On IA32 we use REL relocations so the - addend goes in the PLT directly. */ - rel.r_offset = (htab->elf.splt->output_section->vma - + htab->elf.splt->output_offset - + htab->lazy_plt->plt0_got1_offset); + bfd_elf32_swap_reloc_in (output_bfd, p, &rel); rel.r_info = ELF32_R_INFO (htab->elf.hgot->indx, R_386_32); - bfd_elf32_swap_reloc_out (output_bfd, &rel, - srelplt2->contents); - /* Generate a relocation for _GLOBAL_OFFSET_TABLE_ - + 8. */ - rel.r_offset = (htab->elf.splt->output_section->vma - + htab->elf.splt->output_offset - + htab->lazy_plt->plt0_got2_offset); - rel.r_info = ELF32_R_INFO (htab->elf.hgot->indx, - R_386_32); - bfd_elf32_swap_reloc_out (output_bfd, &rel, - srelplt2->contents + - sizeof (Elf32_External_Rel)); - /* Correct the .rel.plt.unloaded relocations. */ - p = srelplt2->contents; - if (bfd_link_pic (info)) - p += PLTRESOLVE_RELOCS_SHLIB * sizeof (Elf32_External_Rel); - else - p += PLTRESOLVE_RELOCS * sizeof (Elf32_External_Rel); + bfd_elf32_swap_reloc_out (output_bfd, &rel, p); + p += sizeof (Elf32_External_Rel); - for (; num_plts; num_plts--) - { - bfd_elf32_swap_reloc_in (output_bfd, p, &rel); - rel.r_info = ELF32_R_INFO (htab->elf.hgot->indx, - R_386_32); - bfd_elf32_swap_reloc_out (output_bfd, &rel, p); - p += sizeof (Elf32_External_Rel); - - bfd_elf32_swap_reloc_in (output_bfd, p, &rel); - rel.r_info = ELF32_R_INFO (htab->elf.hplt->indx, - R_386_32); - bfd_elf32_swap_reloc_out (output_bfd, &rel, p); - p += sizeof (Elf32_External_Rel); - } + bfd_elf32_swap_reloc_in (output_bfd, p, &rel); + rel.r_info = ELF32_R_INFO (htab->elf.hplt->indx, + R_386_32); + bfd_elf32_swap_reloc_out (output_bfd, &rel, p); + p += sizeof (Elf32_External_Rel); } } } } - - if (htab->plt_got != NULL && htab->plt_got->size > 0) - elf_section_data (htab->plt_got->output_section) - ->this_hdr.sh_entsize = htab->non_lazy_plt->plt_entry_size; - - if (htab->plt_second != NULL && htab->plt_second->size > 0) - elf_section_data (htab->plt_second->output_section) - ->this_hdr.sh_entsize = htab->non_lazy_plt->plt_entry_size; - } - - /* Fill in the first three entries in the global offset table. */ - if (htab->elf.sgotplt && htab->elf.sgotplt->size > 0) - { - if (bfd_is_abs_section (htab->elf.sgotplt->output_section)) - { - _bfd_error_handler - (_("discarded output section: `%A'"), htab->elf.sgotplt); - return FALSE; - } - - bfd_put_32 (output_bfd, - (sdyn == NULL ? 0 - : sdyn->output_section->vma + sdyn->output_offset), - htab->elf.sgotplt->contents); - bfd_put_32 (output_bfd, 0, htab->elf.sgotplt->contents + 4); - bfd_put_32 (output_bfd, 0, htab->elf.sgotplt->contents + 8); - - elf_section_data (htab->elf.sgotplt->output_section)->this_hdr.sh_entsize = 4; - } - - /* Adjust .eh_frame for .plt section. */ - if (htab->plt_eh_frame != NULL - && htab->plt_eh_frame->contents != NULL) - { - if (htab->elf.splt != NULL - && htab->elf.splt->size != 0 - && (htab->elf.splt->flags & SEC_EXCLUDE) == 0 - && htab->elf.splt->output_section != NULL - && htab->plt_eh_frame->output_section != NULL) - { - bfd_vma plt_start = htab->elf.splt->output_section->vma; - bfd_vma eh_frame_start = htab->plt_eh_frame->output_section->vma - + htab->plt_eh_frame->output_offset - + PLT_FDE_START_OFFSET; - bfd_put_signed_32 (dynobj, plt_start - eh_frame_start, - htab->plt_eh_frame->contents - + PLT_FDE_START_OFFSET); - } - if (htab->plt_eh_frame->sec_info_type - == SEC_INFO_TYPE_EH_FRAME) - { - if (! _bfd_elf_write_section_eh_frame (output_bfd, info, - htab->plt_eh_frame, - htab->plt_eh_frame->contents)) - return FALSE; - } - } - - /* Adjust .eh_frame for .plt.got section. */ - if (htab->plt_got_eh_frame != NULL - && htab->plt_got_eh_frame->contents != NULL) - { - if (htab->plt_got != NULL - && htab->plt_got->size != 0 - && (htab->plt_got->flags & SEC_EXCLUDE) == 0 - && htab->plt_got->output_section != NULL - && htab->plt_got_eh_frame->output_section != NULL) - { - bfd_vma plt_start = htab->plt_got->output_section->vma; - bfd_vma eh_frame_start = htab->plt_got_eh_frame->output_section->vma - + htab->plt_got_eh_frame->output_offset - + PLT_FDE_START_OFFSET; - bfd_put_signed_32 (dynobj, plt_start - eh_frame_start, - htab->plt_got_eh_frame->contents - + PLT_FDE_START_OFFSET); - } - if (htab->plt_got_eh_frame->sec_info_type == SEC_INFO_TYPE_EH_FRAME) - { - if (! _bfd_elf_write_section_eh_frame (output_bfd, info, - htab->plt_got_eh_frame, - htab->plt_got_eh_frame->contents)) - return FALSE; - } - } - - /* Adjust .eh_frame for the second PLT section. */ - if (htab->plt_second_eh_frame != NULL - && htab->plt_second_eh_frame->contents != NULL) - { - if (htab->plt_second != NULL - && htab->plt_second->size != 0 - && (htab->plt_second->flags & SEC_EXCLUDE) == 0 - && htab->plt_second->output_section != NULL - && htab->plt_second_eh_frame->output_section != NULL) - { - bfd_vma plt_start = htab->plt_second->output_section->vma; - bfd_vma eh_frame_start - = (htab->plt_second_eh_frame->output_section->vma - + htab->plt_second_eh_frame->output_offset - + PLT_FDE_START_OFFSET); - bfd_put_signed_32 (dynobj, plt_start - eh_frame_start, - htab->plt_second_eh_frame->contents - + PLT_FDE_START_OFFSET); - } - if (htab->plt_second_eh_frame->sec_info_type - == SEC_INFO_TYPE_EH_FRAME) - { - if (! _bfd_elf_write_section_eh_frame (output_bfd, info, - htab->plt_second_eh_frame, - htab->plt_second_eh_frame->contents)) - return FALSE; - } } - if (htab->elf.sgot && htab->elf.sgot->size > 0) - elf_section_data (htab->elf.sgot->output_section)->this_hdr.sh_entsize = 4; - /* Fill PLT entries for undefined weak symbols in PIE. */ if (bfd_link_pie (info)) bfd_hash_traverse (&info->hash->table, elf_i386_pie_finish_undefweak_symbol, info); - return TRUE; + return true; } /* Fill PLT/GOT entries and allocate dynamic relocations for local @@ -5595,7 +4144,7 @@ elf_i386_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_i386_output_arch_local_syms (bfd *output_bfd ATTRIBUTE_UNUSED, struct bfd_link_info *info, @@ -5608,19 +4157,16 @@ elf_i386_output_arch_local_syms struct elf_x86_link_hash_table *htab = elf_x86_hash_table (info, I386_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_i386_finish_local_dynamic_symbol, info); - return TRUE; + return true; } -/* Forward declaration. */ -static const struct elf_x86_lazy_plt_layout elf_i386_nacl_plt; - /* Similar to _bfd_elf_get_synthetic_symtab. Support PLTs with all dynamic relocations. */ @@ -5668,9 +4214,10 @@ elf_i386_get_synthetic_symtab (bfd *abfd, lazy_plt = NULL; non_lazy_ibt_plt = NULL; lazy_ibt_plt = NULL; - switch (get_elf_i386_backend_data (abfd)->os) + switch (get_elf_backend_data (abfd)->target_os) { case is_normal: + case is_solaris: non_lazy_plt = &elf_i386_non_lazy_plt; lazy_ibt_plt = &elf_i386_lazy_ibt_plt; non_lazy_ibt_plt = &elf_i386_non_lazy_ibt_plt; @@ -5678,9 +4225,8 @@ elf_i386_get_synthetic_symtab (bfd *abfd, case is_vxworks: lazy_plt = &elf_i386_lazy_plt; break; - case is_nacl: - lazy_plt = &elf_i386_nacl_plt; - break; + default: + abort (); } got_addr = 0; @@ -5825,35 +4371,33 @@ elf_i386_get_synthetic_symtab (bfd *abfd, static bfd * elf_i386_link_setup_gnu_properties (struct bfd_link_info *info) { - struct elf_x86_plt_layout_table plt_layout; + struct elf_x86_init_table init_table; - plt_layout.normal_target = FALSE; - plt_layout.is_vxworks = FALSE; - switch (get_elf_i386_backend_data (info->output_bfd)->os) + switch (get_elf_backend_data (info->output_bfd)->target_os) { case is_normal: - plt_layout.lazy_plt = &elf_i386_lazy_plt; - plt_layout.non_lazy_plt = &elf_i386_non_lazy_plt; - plt_layout.lazy_ibt_plt = &elf_i386_lazy_ibt_plt; - plt_layout.non_lazy_ibt_plt = &elf_i386_non_lazy_ibt_plt; - plt_layout.normal_target = TRUE; + case is_solaris: + init_table.plt0_pad_byte = 0x0; + init_table.lazy_plt = &elf_i386_lazy_plt; + init_table.non_lazy_plt = &elf_i386_non_lazy_plt; + init_table.lazy_ibt_plt = &elf_i386_lazy_ibt_plt; + init_table.non_lazy_ibt_plt = &elf_i386_non_lazy_ibt_plt; break; case is_vxworks: - plt_layout.lazy_plt = &elf_i386_lazy_plt; - plt_layout.non_lazy_plt = NULL; - plt_layout.lazy_ibt_plt = NULL; - plt_layout.non_lazy_ibt_plt = NULL; - plt_layout.is_vxworks = TRUE; - break; - case is_nacl: - plt_layout.lazy_plt = &elf_i386_nacl_plt; - plt_layout.non_lazy_plt = NULL; - plt_layout.lazy_ibt_plt = NULL; - plt_layout.non_lazy_ibt_plt = NULL; + init_table.plt0_pad_byte = 0x90; + init_table.lazy_plt = &elf_i386_lazy_plt; + init_table.non_lazy_plt = NULL; + init_table.lazy_ibt_plt = NULL; + init_table.non_lazy_ibt_plt = NULL; break; + default: + abort (); } - return _bfd_x86_elf_link_setup_gnu_properties (info, &plt_layout); + init_table.r_info = elf32_r_info; + init_table.r_sym = elf32_r_sym; + + return _bfd_x86_elf_link_setup_gnu_properties (info, &init_table); } #define TARGET_LITTLE_SYM i386_elf32_vec @@ -5879,28 +4423,28 @@ elf_i386_link_setup_gnu_properties (struct bfd_link_info *info) #define elf_info_to_howto elf_i386_info_to_howto_rel #define elf_info_to_howto_rel elf_i386_info_to_howto_rel -#define bfd_elf32_mkobject elf_i386_mkobject - #define bfd_elf32_bfd_is_local_label_name elf_i386_is_local_label_name #define bfd_elf32_bfd_reloc_type_lookup elf_i386_reloc_type_lookup #define bfd_elf32_bfd_reloc_name_lookup elf_i386_reloc_name_lookup #define bfd_elf32_get_synthetic_symtab elf_i386_get_synthetic_symtab -#define elf_backend_adjust_dynamic_symbol elf_i386_adjust_dynamic_symbol #define elf_backend_relocs_compatible _bfd_elf_relocs_compatible -#define elf_backend_check_relocs elf_i386_check_relocs +#define elf_backend_always_size_sections elf_i386_always_size_sections #define elf_backend_create_dynamic_sections _bfd_elf_create_dynamic_sections #define elf_backend_fake_sections elf_i386_fake_sections #define elf_backend_finish_dynamic_sections elf_i386_finish_dynamic_sections #define elf_backend_finish_dynamic_symbol elf_i386_finish_dynamic_symbol #define elf_backend_output_arch_local_syms elf_i386_output_arch_local_syms -#define elf_backend_gc_mark_hook elf_i386_gc_mark_hook #define elf_backend_grok_prstatus elf_i386_grok_prstatus #define elf_backend_grok_psinfo elf_i386_grok_psinfo #define elf_backend_reloc_type_class elf_i386_reloc_type_class #define elf_backend_relocate_section elf_i386_relocate_section -#define elf_backend_size_dynamic_sections elf_i386_size_dynamic_sections #define elf_backend_setup_gnu_properties elf_i386_link_setup_gnu_properties +#define elf_backend_hide_symbol _bfd_x86_elf_hide_symbol + +#define elf_backend_linux_prpsinfo32_ugid16 true + +#define elf32_bed elf32_i386_bed #include "elf32-target.h" @@ -5917,10 +4461,11 @@ elf_i386_link_setup_gnu_properties (struct bfd_link_info *info) "FreeBSD" label in the ELF header. So we put this label on all executables and (for simplicity) also all other object files. */ -static void -elf_i386_fbsd_post_process_headers (bfd *abfd, struct bfd_link_info *info) +static bool +elf_i386_fbsd_init_file_header (bfd *abfd, struct bfd_link_info *info) { - _bfd_elf_post_process_headers (abfd, info); + if (!_bfd_elf_init_file_header (abfd, info)) + return false; #ifdef OLD_FREEBSD_ABI_LABEL { @@ -5929,10 +4474,11 @@ elf_i386_fbsd_post_process_headers (bfd *abfd, struct bfd_link_info *info) memcpy (&i_ehdrp->e_ident[EI_ABIVERSION], "FreeBSD", 8); } #endif + return true; } -#undef elf_backend_post_process_headers -#define elf_backend_post_process_headers elf_i386_fbsd_post_process_headers +#undef elf_backend_init_file_header +#define elf_backend_init_file_header elf_i386_fbsd_init_file_header #undef elf32_bed #define elf32_bed elf32_i386_fbsd_bed @@ -5940,6 +4486,8 @@ elf_i386_fbsd_post_process_headers (bfd *abfd, struct bfd_link_info *info) #include "elf32-target.h" +#undef elf_backend_init_file_header + /* Solaris 2. */ #undef TARGET_LITTLE_SYM @@ -5947,7 +4495,8 @@ elf_i386_fbsd_post_process_headers (bfd *abfd, struct bfd_link_info *info) #undef TARGET_LITTLE_NAME #define TARGET_LITTLE_NAME "elf32-i386-sol2" -#undef elf_backend_post_process_headers +#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. */ @@ -5972,11 +4521,11 @@ elf_i386_fbsd_post_process_headers (bfd *abfd, struct bfd_link_info *info) #define elf_backend_strtab_flags SHF_STRINGS /* Called to set the sh_flags, sh_link and sh_info fields of OSECTION which - has a type >= SHT_LOOS. Returns TRUE if these fields were initialised + has a type >= SHT_LOOS. Returns TRUE if these fields were initialised FALSE otherwise. ISECTION is the best guess matching section from the input bfd IBFD, but it might be NULL. */ -static bfd_boolean +static bool elf32_i386_copy_solaris_special_section_fields (const bfd *ibfd ATTRIBUTE_UNUSED, bfd *obfd ATTRIBUTE_UNUSED, const Elf_Internal_Shdr *isection ATTRIBUTE_UNUSED, @@ -5984,7 +4533,7 @@ elf32_i386_copy_solaris_special_section_fields (const bfd *ibfd ATTRIBUTE_UNUSED { /* 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; /* Based upon Oracle Solaris 11.3 Linkers and Libraries Guide, Ch. 13, Object File Format, Table 13-9 ELF sh_link and sh_info Interpretation: @@ -5992,60 +4541,60 @@ elf32_i386_copy_solaris_special_section_fields (const bfd *ibfd ATTRIBUTE_UNUSED http://docs.oracle.com/cd/E53394_01/html/E54813/chapter6-94076.html#scrolltoc The following values should be set: - -Type Link Info + +Type Link Info ----------------------------------------------------------------------------- SHT_SUNW_ancillary The section header index of 0 - [0x6fffffee] the associated string table. - + [0x6fffffee] the associated string table. + SHT_SUNW_capinfo The section header index of For a dynamic object, the - [0x6ffffff0] the associated symbol table. section header index of - the associated + [0x6ffffff0] the associated symbol table. section header index of + the associated SHT_SUNW_capchain table, otherwise 0. SHT_SUNW_symsort The section header index of 0 - [0x6ffffff1] the associated symbol table. + [0x6ffffff1] the associated symbol table. SHT_SUNW_tlssort The section header index of 0 - [0x6ffffff2] the associated symbol table. - -SHT_SUNW_LDYNSYM The section header index of One greater than the - [0x6ffffff3] the associated string table. symbol table index of the - This index is the same string last local symbol, + [0x6ffffff2] the associated symbol table. + +SHT_SUNW_LDYNSYM The section header index of One greater than the + [0x6ffffff3] the associated string table. symbol table index of the + This index is the same string last local symbol, table used by the SHT_DYNSYM STB_LOCAL. Since - section. SHT_SUNW_LDYNSYM only - contains local symbols, + section. SHT_SUNW_LDYNSYM only + contains local symbols, sh_info is equivalent to the number of symbols in the table. -SHT_SUNW_cap If symbol capabilities exist, If any capabilities refer - [0x6ffffff5] the section header index of to named strings, the - the associated section header index of - SHT_SUNW_capinfo table, the associated string - otherwise 0. table, otherwise 0. +SHT_SUNW_cap If symbol capabilities exist, If any capabilities refer + [0x6ffffff5] the section header index of to named strings, the + the associated section header index of + SHT_SUNW_capinfo table, the associated string + otherwise 0. table, otherwise 0. + +SHT_SUNW_move The section header index of 0 + [0x6ffffffa] the associated symbol table. -SHT_SUNW_move The section header index of 0 - [0x6ffffffa] the associated symbol table. - -SHT_SUNW_COMDAT 0 0 +SHT_SUNW_COMDAT 0 0 [0x6ffffffb] SHT_SUNW_syminfo The section header index of The section header index - [0x6ffffffc] the associated symbol table. of the associated - .dynamic section. + [0x6ffffffc] the associated symbol table. of the associated + .dynamic section. -SHT_SUNW_verdef The section header index of The number of version - [0x6ffffffd] the associated string table. definitions within the - section. +SHT_SUNW_verdef The section header index of The number of version + [0x6ffffffd] the associated string table. definitions within the + section. SHT_SUNW_verneed The section header index of The number of version - [0x6ffffffe] the associated string table. dependencies within the - section. + [0x6ffffffe] the associated string table. dependencies within the + section. -SHT_SUNW_versym The section header index of 0 - [0x6fffffff] the associated symbol table. */ +SHT_SUNW_versym The section header index of 0 + [0x6fffffff] the associated symbol table. */ } #undef elf_backend_copy_special_section_fields @@ -6055,12 +4604,12 @@ SHT_SUNW_versym The section header index of 0 /* Intel MCU support. */ -static bfd_boolean +static bool elf32_iamcu_elf_object_p (bfd *abfd) { /* Set the right machine number for an IAMCU elf32 file. */ bfd_default_set_arch_mach (abfd, bfd_arch_iamcu, bfd_mach_i386_iamcu); - return TRUE; + return true; } #undef TARGET_LITTLE_SYM @@ -6073,6 +4622,7 @@ elf32_iamcu_elf_object_p (bfd *abfd) #undef ELF_MACHINE_CODE #define ELF_MACHINE_CODE EM_IAMCU +#undef ELF_TARGET_OS #undef ELF_OSABI #undef elf32_bed @@ -6084,7 +4634,7 @@ elf32_iamcu_elf_object_p (bfd *abfd) #undef elf_backend_static_tls_alignment #undef elf_backend_want_plt_sym -#define elf_backend_want_plt_sym 0 +#define elf_backend_want_plt_sym 0 #undef elf_backend_strtab_flags #undef elf_backend_copy_special_section_fields @@ -6096,197 +4646,7 @@ elf32_iamcu_elf_object_p (bfd *abfd) #define ELF_ARCH bfd_arch_i386 #undef ELF_MACHINE_CODE #define ELF_MACHINE_CODE EM_386 - -/* Native Client support. */ - -#undef TARGET_LITTLE_SYM -#define TARGET_LITTLE_SYM i386_elf32_nacl_vec -#undef TARGET_LITTLE_NAME -#define TARGET_LITTLE_NAME "elf32-i386-nacl" -#undef elf32_bed -#define elf32_bed elf32_i386_nacl_bed - -#undef ELF_MAXPAGESIZE -#define ELF_MAXPAGESIZE 0x10000 - -/* Restore defaults. */ -#undef ELF_OSABI -#undef elf_backend_want_plt_sym -#define elf_backend_want_plt_sym 0 -#undef elf_backend_post_process_headers -#undef elf_backend_static_tls_alignment - -/* NaCl uses substantially different PLT entries for the same effects. */ - -#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_i386_nacl_plt0_entry[] = - { - 0xff, 0x35, /* pushl contents of address */ - 0, 0, 0, 0, /* replaced with address of .got + 4. */ - 0x8b, 0x0d, /* movl contents of address, %ecx */ - 0, 0, 0, 0, /* replaced with address of .got + 8. */ - 0x83, 0xe1, NACLMASK, /* andl $NACLMASK, %ecx */ - 0xff, 0xe1 /* jmp *%ecx */ - }; - -static const bfd_byte elf_i386_nacl_plt_entry[NACL_PLT_ENTRY_SIZE] = - { - 0x8b, 0x0d, /* movl contents of address, %ecx */ - 0, 0, 0, 0, /* replaced with GOT slot address. */ - 0x83, 0xe1, NACLMASK, /* andl $NACLMASK, %ecx */ - 0xff, 0xe1, /* jmp *%ecx */ - - /* Pad to the next 32-byte boundary with nop instructions. */ - 0x90, - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, - - /* Lazy GOT entries point here (32-byte aligned). */ - 0x68, /* pushl immediate */ - 0, 0, 0, 0, /* replaced with reloc offset. */ - 0xe9, /* jmp relative */ - 0, 0, 0, 0, /* replaced with offset to .plt. */ - - /* Pad to the next 32-byte boundary with nop instructions. */ - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, - 0x90, 0x90 - }; - -static const bfd_byte -elf_i386_nacl_pic_plt0_entry[sizeof (elf_i386_nacl_plt0_entry)] = - { - 0xff, 0x73, 0x04, /* pushl 4(%ebx) */ - 0x8b, 0x4b, 0x08, /* mov 0x8(%ebx), %ecx */ - 0x83, 0xe1, 0xe0, /* and $NACLMASK, %ecx */ - 0xff, 0xe1, /* jmp *%ecx */ - - /* This is expected to be the same size as elf_i386_nacl_plt0_entry, - so pad to that size with nop instructions. */ - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 - }; - -static const bfd_byte elf_i386_nacl_pic_plt_entry[NACL_PLT_ENTRY_SIZE] = - { - 0x8b, 0x8b, /* movl offset(%ebx), %ecx */ - 0, 0, 0, 0, /* replaced with offset of this symbol in .got. */ - 0x83, 0xe1, 0xe0, /* andl $NACLMASK, %ecx */ - 0xff, 0xe1, /* jmp *%ecx */ - - /* Pad to the next 32-byte boundary with nop instructions. */ - 0x90, - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, - - /* Lazy GOT entries point here (32-byte aligned). */ - 0x68, /* pushl immediate */ - 0, 0, 0, 0, /* replaced with offset into relocation table. */ - 0xe9, /* jmp relative */ - 0, 0, 0, 0, /* replaced with offset to start of .plt. */ - - /* Pad to the next 32-byte boundary with nop instructions. */ - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, - 0x90, 0x90 - }; - -static const bfd_byte elf_i386_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_i386_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 */ - 0x7c, /* Data alignment factor: -4 */ - 8, /* Return address column */ - 1, /* Augmentation size */ - DW_EH_PE_pcrel | DW_EH_PE_sdata4, /* FDE encoding */ - DW_CFA_def_cfa, 4, 4, /* DW_CFA_def_cfa: r4 (esp) ofs 4 */ - DW_CFA_offset + 8, 1, /* DW_CFA_offset: r8 (eip) at cfa-4 */ - 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_386_PC32 .plt goes here */ - 0, 0, 0, 0, /* .plt size goes here */ - 0, /* Augmentation size */ - DW_CFA_def_cfa_offset, 8, /* DW_CFA_def_cfa_offset: 8 */ - DW_CFA_advance_loc + 6, /* DW_CFA_advance_loc: 6 to __PLT__+6 */ - DW_CFA_def_cfa_offset, 12, /* DW_CFA_def_cfa_offset: 12 */ - 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_breg4, 4, /* DW_OP_breg4 (esp): 4 */ - DW_OP_breg8, 0, /* DW_OP_breg8 (eip): 0 */ - DW_OP_const1u, 63, DW_OP_and, DW_OP_const1u, 37, DW_OP_ge, - DW_OP_lit2, DW_OP_shl, DW_OP_plus, - DW_CFA_nop, DW_CFA_nop - }; - -static const struct elf_x86_lazy_plt_layout elf_i386_nacl_plt = - { - elf_i386_nacl_plt0_entry, /* plt0_entry */ - sizeof (elf_i386_nacl_plt0_entry), /* plt0_entry_size */ - elf_i386_nacl_plt_entry, /* plt_entry */ - NACL_PLT_ENTRY_SIZE, /* plt_entry_size */ - 2, /* plt0_got1_offset */ - 8, /* plt0_got2_offset */ - 0, /* plt0_got2_insn_end */ - 2, /* plt_got_offset */ - 33, /* plt_reloc_offset */ - 38, /* plt_plt_offset */ - 0, /* plt_got_insn_size */ - 0, /* plt_plt_insn_end */ - 32, /* plt_lazy_offset */ - elf_i386_nacl_pic_plt0_entry, /* pic_plt0_entry */ - elf_i386_nacl_pic_plt_entry, /* pic_plt_entry */ - elf_i386_nacl_eh_frame_plt, /* eh_frame_plt */ - sizeof (elf_i386_nacl_eh_frame_plt) /* eh_frame_plt_size */ - }; - -static const struct elf_i386_backend_data elf_i386_nacl_arch_bed = - { - 0x90, /* plt0_pad_byte: nop insn */ - is_nacl /* os */ - }; - -static bfd_boolean -elf32_i386_nacl_elf_object_p (bfd *abfd) -{ - /* Set the right machine number for a NaCl i386 ELF32 file. */ - bfd_default_set_arch_mach (abfd, bfd_arch_i386, bfd_mach_i386_i386_nacl); - return TRUE; -} - -#undef elf_backend_arch_data -#define elf_backend_arch_data &elf_i386_nacl_arch_bed - #undef elf_backend_object_p -#define elf_backend_object_p elf32_i386_nacl_elf_object_p -#undef elf_backend_modify_segment_map -#define elf_backend_modify_segment_map nacl_modify_segment_map -#undef elf_backend_modify_program_headers -#define elf_backend_modify_program_headers nacl_modify_program_headers -#undef elf_backend_final_write_processing -#define elf_backend_final_write_processing nacl_final_write_processing - -#include "elf32-target.h" - -/* Restore defaults. */ -#undef elf_backend_object_p -#undef elf_backend_modify_segment_map -#undef elf_backend_modify_program_headers -#undef elf_backend_final_write_processing /* VxWorks support. */ @@ -6300,14 +4660,8 @@ elf32_i386_nacl_elf_object_p (bfd *abfd) #undef elf_backend_plt_alignment #define elf_backend_plt_alignment 4 -static const struct elf_i386_backend_data elf_i386_vxworks_arch_bed = - { - 0x90, /* plt0_pad_byte */ - is_vxworks /* os */ - }; - -#undef elf_backend_arch_data -#define elf_backend_arch_data &elf_i386_vxworks_arch_bed +#undef ELF_TARGET_OS +#define ELF_TARGET_OS is_vxworks #undef elf_backend_relocs_compatible #undef elf_backend_add_symbol_hook