/* Intel 80386/80486-specific support for 32-bit ELF
- Copyright (C) 1993-2018 Free Software Foundation, Inc.
+ Copyright (C) 1993-2020 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
#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)
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 *
}
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;
>= 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 (_("%pB: unsupported relocation type %#x"),
- abfd, 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 bfd_boolean
+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
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 */
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 */
+ 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 */
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;
&& 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)
{
}
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;
|| h->root.type == bfd_link_hash_defweak)
&& local_ref))
{
-convert_load:
+ convert_load:
if (opcode == 0x8b)
{
if (to_reloc_32)
/* It is referenced by a non-shared object. */
h->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
case R_386_GOTOFF:
case R_386_GOTPC:
-create_got:
+ create_got:
if (r_type != R_386_TLS_IE)
{
if (eh != NULL)
case R_386_PC32:
if (eh != NULL && (sec->flags & SEC_CODE) != 0)
eh->zero_undefweak |= 0x2;
-do_relocation:
+ do_relocation:
/* We are called after all symbols have been resolved. Only
relocation against STT_GNU_IFUNC symbol must go through
PLT. */
}
size_reloc = FALSE;
-do_size:
+ do_size:
if (NEED_DYNAMIC_RELOCATION_P (info, FALSE, h, sec, r_type,
R_386_32))
{
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);
if (p == NULL)
/* 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;
return TRUE;
-error_return:
+ error_return:
if (elf_section_data (sec)->this_hdr.contents != contents)
free (contents);
sec->check_relocs_failed = 1;
{
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
if (htab == NULL)
return FALSE;
- BFD_ASSERT (is_x86_elf (input_bfd, htab));
+ if (!is_x86_elf (input_bfd, htab))
+ {
+ bfd_set_error (bfd_error_wrong_format);
+ return FALSE;
+ }
symtab_hdr = &elf_symtab_hdr (input_bfd);
sym_hashes = elf_sym_hashes (input_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;
if (sec != NULL && discarded_section (sec))
{
_bfd_clear_contents (howto, input_bfd, input_section,
- contents + rel->r_offset);
+ contents, rel->r_offset);
wrel->r_offset = rel->r_offset;
wrel->r_info = 0;
wrel->r_addend = 0;
if ((input_section->flags & SEC_ALLOC) == 0)
{
+ /* If this is a SHT_NOTE section without SHF_ALLOC, treat
+ STT_GNU_IFUNC symbol as STT_FUNC. */
+ if (elf_section_type (input_section) == SHT_NOTE)
+ goto skip_ifunc;
/* Dynamic relocs are not propagated for SEC_DEBUGGING
sections because such sections are not SEC_ALLOC and
thus ld.so will not process them. */
switch (r_type)
{
default:
-bad_ifunc_reloc:
+ bad_ifunc_reloc:
if (h->root.root.string)
name = h->root.root.string;
else
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,
}
}
+ skip_ifunc:
resolved_to_zero = (eh != NULL
&& 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)
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);
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;
if (name == NULL)
return FALSE;
if (*name == '\0')
- name = bfd_section_name (input_bfd, sec);
+ name = bfd_section_name (sec);
}
if (r == bfd_reloc_overflow)
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
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);
#define elf_backend_linux_prpsinfo32_ugid16 TRUE
+#define elf32_bed elf32_i386_bed
+
#include "elf32-target.h"
/* FreeBSD support. */
"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 bfd_boolean
+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
{
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
#include "elf32-target.h"
+#undef elf_backend_init_file_header
+
/* Solaris 2. */
#undef TARGET_LITTLE_SYM
#undef elf_backend_arch_data
#define elf_backend_arch_data &elf_i386_solaris_arch_bed
-#undef elf_backend_post_process_headers
-
/* Restore default: we cannot use ELFOSABI_SOLARIS, otherwise ELFOSABI_NONE
objects won't be recognized. */
#undef ELF_OSABI
#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. */
sizeof (elf_i386_nacl_plt0_entry), /* plt0_entry_size */
elf_i386_nacl_plt_entry, /* plt_entry */
NACL_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 */
#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_modify_headers
+#define elf_backend_modify_headers nacl_modify_headers
#undef elf_backend_final_write_processing
#define elf_backend_final_write_processing nacl_final_write_processing
/* Restore defaults. */
#undef elf_backend_object_p
#undef elf_backend_modify_segment_map
-#undef elf_backend_modify_program_headers
+#undef elf_backend_modify_headers
#undef elf_backend_final_write_processing
/* VxWorks support. */