X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=bfd%2Felf32-i386.c;h=fb5ed161f50c4cde39e8d7b24fe843fe18aaad09;hb=680e019e5aeec49734760653145fee89f0ddc00b;hp=01006620404561dda6dd13a1fdf4ecc608840a9d;hpb=0a27fed72d4190cc70025c671b5133e6c58d9c09;p=binutils-gdb.git diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c index 01006620404..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) */ }; @@ -751,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 */ }; @@ -820,39 +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 - /* 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, @@ -866,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) @@ -874,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); @@ -897,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 { @@ -927,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) @@ -935,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 @@ -950,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) @@ -964,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 @@ -989,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); @@ -1013,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; @@ -1031,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; @@ -1050,7 +1037,7 @@ elf_i386_check_tls_transition (asection *sec, return call[0] == 0xff && call[1] == 0x10; } - return FALSE; + return false; default: abort (); @@ -1060,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, @@ -1070,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) { @@ -1105,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 @@ -1122,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; @@ -1136,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 @@ -1152,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; @@ -1168,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); } @@ -1176,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 @@ -1208,37 +1192,39 @@ 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, + 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; - bfd_boolean local_ref; + 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); @@ -1249,6 +1235,21 @@ elf_i386_convert_load_reloc (bfd *abfd, Elf_Internal_Shdr *symtab_hdr, 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 @@ -1256,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); @@ -1294,9 +1291,6 @@ elf_i386_convert_load_reloc (bfd *abfd, Elf_Internal_Shdr *symtab_hdr, goto convert_load; } - /* NB: Also set linker_def via SYMBOL_REFERENCES_LOCAL_P. */ - local_ref = SYMBOL_REFERENCES_LOCAL_P (link_info, h); - /* Undefined weak symbol is only bound locally in executable and its reference is resolved as 0. */ if (h->root.type == bfd_link_hash_undefweak @@ -1307,14 +1301,14 @@ elf_i386_convert_load_reloc (bfd *abfd, Elf_Internal_Shdr *symtab_hdr, { /* 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; } } @@ -1327,7 +1321,7 @@ elf_i386_convert_load_reloc (bfd *abfd, Elf_Internal_Shdr *symtab_hdr, && 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) { @@ -1343,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; @@ -1369,6 +1363,7 @@ convert_branch: bfd_put_32 (abfd, -4, contents + irel->r_offset); irel->r_info = ELF32_R_INFO (r_symndx, R_386_PC32); *r_type_p = R_386_PC32; + *converted = true; } } else @@ -1380,7 +1375,7 @@ 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 @@ -1392,9 +1387,12 @@ convert_branch: || h->root.type == bfd_link_hash_defweak) && 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 @@ -1416,7 +1414,7 @@ convert_load: { /* Only R_386_32 is supported. */ if (!to_reloc_32) - return TRUE; + return true; if (opcode == 0x85) { @@ -1441,51 +1439,39 @@ convert_load: bfd_put_8 (abfd, opcode, contents + roff - 2); irel->r_info = ELF32_R_INFO (r_symndx, r_type); *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 check_relocs_failed sec_flg0 - /* 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; + 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)); @@ -1496,13 +1482,13 @@ elf_i386_check_relocs (bfd *abfd, 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++) @@ -1513,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); @@ -1521,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; } @@ -1529,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; @@ -1537,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; @@ -1570,11 +1557,6 @@ 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 @@ -1582,20 +1564,29 @@ elf_i386_check_relocs (bfd *abfd, { Elf_Internal_Rela *irel = (Elf_Internal_Rela *) rel; if (!elf_i386_convert_load_reloc (abfd, symtab_hdr, contents, - &r_type, irel, h, info)) + &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: @@ -1611,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: @@ -1662,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]; } @@ -1714,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); @@ -1738,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 */ @@ -1746,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; @@ -1755,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. */ @@ -1764,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) { @@ -1791,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; @@ -1803,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 { @@ -1879,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; @@ -1895,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; @@ -1924,9 +1886,7 @@ do_size: /* 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)) + if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_offset)) goto error_return; break; @@ -1937,35 +1897,59 @@ do_size: if (elf_section_data (sec)->this_hdr.contents != contents) { - if (!info->keep_memory) + if (!converted && !_bfd_link_keep_memory (info)) free (contents); else { - /* Cache the section contents for elf_link_input_bfd. */ + /* 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; } } - return TRUE; + /* Cache relocations if any load is converted. */ + if (elf_section_data (sec)->relocs != relocs && converted) + elf_section_data (sec)->relocs = (Elf_Internal_Rela *) relocs; + + return true; -error_return: + error_return: if (elf_section_data (sec)->this_hdr.contents != contents) free (contents); sec->check_relocs_failed = 1; - return FALSE; + return false; +} + +static bool +elf_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 @@ -1986,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 @@ -2010,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, @@ -2028,18 +2012,22 @@ 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; - /* 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; - BFD_ASSERT (is_x86_elf (input_bfd, htab)); + 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); @@ -2047,8 +2035,8 @@ elf_i386_relocate_section (bfd *output_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 = (htab->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")); @@ -2069,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 @@ -2087,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; @@ -2184,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 (); @@ -2195,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, @@ -2208,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; @@ -2244,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. */ @@ -2316,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. @@ -2376,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 @@ -2384,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 @@ -2400,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, @@ -2415,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 @@ -2465,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_P (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 @@ -2573,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 { @@ -2607,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; } } @@ -2625,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); } @@ -2644,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); @@ -2653,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 @@ -2703,11 +2627,11 @@ 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_P (info, h) && (h->type == STT_FUNC @@ -2716,13 +2640,13 @@ disallow_got32: { _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; } } @@ -2739,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: @@ -2783,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: @@ -2797,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 @@ -2887,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 (); @@ -2912,8 +2834,8 @@ disallow_got32: input_section, contents, symtab_hdr, sym_hashes, &r_type_tls, tls_type, rel, - relend, h, r_symndx, TRUE)) - return FALSE; + relend, h, r_symndx, true)) + return false; if (r_type_tls == R_386_TLS_LE_32) { @@ -3201,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); @@ -3242,7 +3164,7 @@ disallow_got32: || 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_tls == r_type) { @@ -3255,7 +3177,7 @@ disallow_got32: relocation += 4; if (r_type == R_386_TLS_IE) relocation += g_o_t; - unresolved_reloc = FALSE; + unresolved_reloc = false; } else if (r_type == R_386_TLS_GD) { @@ -3386,7 +3308,7 @@ disallow_got32: continue; } else - BFD_ASSERT (FALSE); + BFD_ASSERT (false); break; case R_386_TLS_LDM: @@ -3394,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) { @@ -3456,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: @@ -3518,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; @@ -3545,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) @@ -3558,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; } } @@ -3589,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, @@ -3604,12 +3526,12 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd, struct elf_x86_link_hash_table *htab; unsigned plt_entry_size; 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; plt_entry_size = htab->plt.plt_entry_size; @@ -3623,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) { @@ -3650,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 @@ -3717,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 (htab->is_vxworks) + if (htab->elf.target_os == is_vxworks) { int s, k, reloc_index; @@ -3728,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; @@ -3760,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 @@ -3780,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); @@ -3799,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--; } @@ -3886,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 @@ -3895,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. */ @@ -3925,7 +3839,7 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd, } 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); @@ -3935,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; @@ -3969,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_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) @@ -3996,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 @@ -4015,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 @@ -4037,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) { @@ -4046,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); @@ -4068,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) { @@ -4101,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 (htab->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 (htab->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); - 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); + 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 + - 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 @@ -4376,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, @@ -4389,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. */ @@ -4449,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; @@ -4459,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; @@ -4608,30 +4373,25 @@ elf_i386_link_setup_gnu_properties (struct bfd_link_info *info) { struct elf_x86_init_table init_table; - init_table.normal_target = FALSE; - init_table.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: + 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; - init_table.normal_target = TRUE; break; case is_vxworks: + 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; - init_table.is_vxworks = TRUE; - break; - case is_nacl: - init_table.lazy_plt = &elf_i386_nacl_plt; - init_table.non_lazy_plt = NULL; - init_table.lazy_ibt_plt = NULL; - init_table.non_lazy_ibt_plt = NULL; break; + default: + abort (); } init_table.r_info = elf32_r_info; @@ -4669,7 +4429,7 @@ elf_i386_link_setup_gnu_properties (struct bfd_link_info *info) #define bfd_elf32_get_synthetic_symtab elf_i386_get_synthetic_symtab #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 @@ -4680,6 +4440,11 @@ elf_i386_link_setup_gnu_properties (struct bfd_link_info *info) #define elf_backend_reloc_type_class elf_i386_reloc_type_class #define elf_backend_relocate_section elf_i386_relocate_section #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" @@ -4696,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 { @@ -4708,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 @@ -4719,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 @@ -4726,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. */ @@ -4751,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, @@ -4763,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: @@ -4771,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 @@ -4834,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 @@ -4852,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 @@ -4863,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 @@ -4875,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. */ @@ -5079,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