/* x86 specific support for ELF
- Copyright (C) 2017-2018 Free Software Foundation, Inc.
+ Copyright (C) 2017-2022 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
MA 02110-1301, USA. */
+/* Don't generate unused section symbols. */
+#define TARGET_KEEP_UNUSED_SECTION_SYMBOLS false
+
#include "sysdep.h"
#include "bfd.h"
#include "bfdlink.h"
#include "libbfd.h"
#include "elf-bfd.h"
-#include "bfd_stdint.h"
#include "hashtab.h"
+#include "elf-linker-x86.h"
+#include "elf/i386.h"
+#include "elf/x86-64.h"
+
+#define X86_64_PCREL_TYPE_P(TYPE) \
+ ((TYPE) == R_X86_64_PC8 \
+ || (TYPE) == R_X86_64_PC16 \
+ || (TYPE) == R_X86_64_PC32 \
+ || (TYPE) == R_X86_64_PC32_BND \
+ || (TYPE) == R_X86_64_PC64)
+#define I386_PCREL_TYPE_P(TYPE) ((TYPE) == R_386_PC32)
+#define X86_PCREL_TYPE_P(IS_X86_64, TYPE) \
+ ((IS_X86_64) ? X86_64_PCREL_TYPE_P (TYPE) : I386_PCREL_TYPE_P (TYPE))
+
+#define X86_64_SIZE_TYPE_P(TYPE) \
+ ((TYPE) == R_X86_64_SIZE32 || (TYPE) == R_X86_64_SIZE64)
+#define I386_SIZE_TYPE_P(TYPE) ((TYPE) == R_386_SIZE32)
+#define X86_SIZE_TYPE_P(IS_X86_64, TYPE) \
+ ((IS_X86_64) ? X86_64_SIZE_TYPE_P(TYPE) : I386_SIZE_TYPE_P (TYPE))
+
+#define X86_64_GOT_TYPE_P(TYPE) \
+ ((TYPE) == R_X86_64_GOTPCREL \
+ || (TYPE) == R_X86_64_GOTPCRELX \
+ || (TYPE) == R_X86_64_REX_GOTPCRELX \
+ || (TYPE) == R_X86_64_GOT32 \
+ || (TYPE) == R_X86_64_GOT64 \
+ || (TYPE) == R_X86_64_GOTPCREL64 \
+ || (TYPE) == R_X86_64_GOTPLT64)
+#define I386_GOT_TYPE_P(TYPE) \
+ ((TYPE) == R_386_GOT32 || (TYPE) == R_386_GOT32X)
+#define X86_GOT_TYPE_P(IS_X86_64, TYPE) \
+ ((IS_X86_64) ? X86_64_GOT_TYPE_P (TYPE) : I386_GOT_TYPE_P (TYPE))
+
+#define X86_64_RELATIVE_RELOC_TYPE_P(TYPE) \
+ (X86_64_PCREL_TYPE_P (TYPE) \
+ || (TYPE) == R_X86_64_8 \
+ || (TYPE) == R_X86_64_16 \
+ || (TYPE) == R_X86_64_32 \
+ || (TYPE) == R_X86_64_32S \
+ || (TYPE) == R_X86_64_64)
+#define I386_RELATIVE_RELOC_TYPE_P(TYPE) \
+ ((TYPE) == R_386_32 || (TYPE) == R_386_PC32)
+#define X86_RELATIVE_RELOC_TYPE_P(IS_X86_64, TYPE) \
+ ((IS_X86_64) \
+ ? X86_64_RELATIVE_RELOC_TYPE_P (TYPE) \
+ : I386_RELATIVE_RELOC_TYPE_P(TYPE))
+
+#define X86_64_NEED_DYNAMIC_RELOC_TYPE_P(TYPE) \
+ (X86_64_SIZE_TYPE_P (TYPE) \
+ || X86_64_RELATIVE_RELOC_TYPE_P (TYPE))
+#define I386_NEED_DYNAMIC_RELOC_TYPE_P(TYPE) \
+ (I386_SIZE_TYPE_P (TYPE) \
+ || I386_RELATIVE_RELOC_TYPE_P (TYPE) \
+ || (TYPE) == R_386_TLS_IE \
+ || (TYPE) == R_386_TLS_LE \
+ || (TYPE) == R_386_TLS_LE_32)
+#define X86_NEED_DYNAMIC_RELOC_TYPE_P(IS_X86_64, TYPE) \
+ ((IS_X86_64) \
+ ? X86_64_NEED_DYNAMIC_RELOC_TYPE_P (TYPE) \
+ : I386_NEED_DYNAMIC_RELOC_TYPE_P (TYPE))
+
+#define X86_LOCAL_GOT_RELATIVE_RELOC_P(IS_X86_64, INFO, SYM) \
+ (bfd_link_pic (INFO) \
+ && (!(IS_X86_64) || ((SYM) != NULL && (SYM)->st_shndx != SHN_ABS)))
#define PLT_CIE_LENGTH 20
#define PLT_FDE_LENGTH 36
#define PLT_FDE_START_OFFSET 4 + PLT_CIE_LENGTH + 8
#define PLT_FDE_LEN_OFFSET 4 + PLT_CIE_LENGTH + 12
+#define I386_PCREL_TYPE_P(TYPE) ((TYPE) == R_386_PC32)
+#define X86_64_PCREL_TYPE_P(TYPE) \
+ ((TYPE) == R_X86_64_PC8 \
+ || (TYPE) == R_X86_64_PC16 \
+ || (TYPE) == R_X86_64_PC32 \
+ || (TYPE) == R_X86_64_PC32_BND \
+ || (TYPE) == R_X86_64_PC64)
+
#define ABI_64_P(abfd) \
(get_elf_backend_data (abfd)->s->elfclass == ELFCLASS64)
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.
+ is set).
+
+ If PCREL_PLT is true, don't generate dynamic relocation in PIE for
+ PC-relative relocation against a dynamic function definition in data
+ section when PLT address can be used.
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
We also need to generate dynamic pointer relocation against
STT_GNU_IFUNC symbol in the non-code section. */
-#define NEED_DYNAMIC_RELOCATION_P(INFO, H, SEC, R_TYPE, POINTER_TYPE) \
+#define NEED_DYNAMIC_RELOCATION_P(IS_X86_64, INFO, PCREL_PLT, H, SEC, \
+ R_TYPE, POINTER_TYPE) \
((bfd_link_pic (INFO) \
- && (! X86_PCREL_TYPE_P (R_TYPE) \
+ && (! X86_PCREL_TYPE_P (IS_X86_64, R_TYPE) \
|| ((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) == POINTER_TYPE \
- && ((SEC)->flags & SEC_CODE) == 0) \
- || (ELIMINATE_COPY_RELOCS \
- && !bfd_link_pic (INFO) \
- && (H) != NULL \
- && ((H)->root.type == bfd_link_hash_defweak \
- || !(H)->def_regular)))
+ || (!(bfd_link_pie (INFO) \
+ && (PCREL_PLT) \
+ && (H)->plt.refcount > 0 \
+ && ((SEC)->flags & SEC_CODE) == 0 \
+ && (H)->type == STT_FUNC \
+ && (H)->def_dynamic) \
+ && !(H)->def_regular))))) \
+ || ((H) != NULL \
+ && (H)->type == STT_GNU_IFUNC \
+ && (R_TYPE) == POINTER_TYPE \
+ && ((SEC)->flags & SEC_CODE) == 0) \
+ || (ELIMINATE_COPY_RELOCS \
+ && !bfd_link_pic (INFO) \
+ && (H) != NULL \
+ && ((H)->root.type == bfd_link_hash_defweak \
+ || !(H)->def_regular)))
/* TRUE if dynamic relocation should be generated. Don't copy a
pc-relative relocation into the output file if the symbol needs
Copy dynamic function pointer relocations. Don't generate dynamic
relocations against resolved undefined weak symbols in PIE, except
when PC32_RELOC is TRUE. Undefined weak symbol is bound locally
- when PIC is false. */
-#define GENERATE_DYNAMIC_RELOCATION_P(INFO, EH, R_TYPE, \
- NEED_COPY_RELOC_IN_PIE, \
+ when PIC is false. Don't generate dynamic relocations against
+ non-preemptible absolute symbol. NB: rel_from_abs is set on symbols
+ defined by linker scripts from "dot" (also SEGMENT_START or ORIGIN)
+ outside of an output section statement, which will be converted from
+ absolute to section-relative in set_sym_sections called from
+ ldexp_finalize_syms after ldemul_finish. */
+#define GENERATE_DYNAMIC_RELOCATION_P(IS_X86_64, INFO, EH, R_TYPE, \
+ SEC, NEED_COPY_RELOC_IN_PIE, \
RESOLVED_TO_ZERO, PC32_RELOC) \
((bfd_link_pic (INFO) \
+ && !(bfd_is_abs_section (SEC) \
+ && ((EH) == NULL \
+ || (EH)->elf.root.rel_from_abs == 0) \
+ && ((EH) == NULL \
+ || SYMBOL_REFERENCES_LOCAL (INFO, &(EH)->elf))) \
&& !(NEED_COPY_RELOC_IN_PIE) \
&& ((EH) == NULL \
|| ((ELF_ST_VISIBILITY ((EH)->elf.other) == STV_DEFAULT \
&& (!(RESOLVED_TO_ZERO) || PC32_RELOC)) \
|| (EH)->elf.root.type != bfd_link_hash_undefweak)) \
- && ((!X86_PCREL_TYPE_P (R_TYPE) \
- && !X86_SIZE_TYPE_P (R_TYPE)) \
- || ! SYMBOL_CALLS_LOCAL ((INFO), &(EH)->elf))) \
+ && ((!X86_PCREL_TYPE_P (IS_X86_64, R_TYPE) \
+ && !X86_SIZE_TYPE_P (IS_X86_64, R_TYPE)) \
+ || ! SYMBOL_CALLS_LOCAL ((INFO), \
+ (struct elf_link_hash_entry *) (EH)))) \
|| (ELIMINATE_COPY_RELOCS \
&& !bfd_link_pic (INFO) \
&& (EH) != NULL \
/* TRUE if this input relocation should be copied to output. H->dynindx
may be -1 if this symbol was marked to become local. */
-#define COPY_INPUT_RELOC_P(INFO, H, R_TYPE) \
+#define COPY_INPUT_RELOC_P(IS_X86_64, INFO, H, R_TYPE) \
((H) != NULL \
&& (H)->dynindx != -1 \
- && (X86_PCREL_TYPE_P (R_TYPE) \
+ && (X86_PCREL_TYPE_P (IS_X86_64, R_TYPE) \
|| !(bfd_link_executable (INFO) || SYMBOLIC_BIND ((INFO), (H))) \
|| !(H)->def_regular))
|| (ELF_ST_VISIBILITY ((H)->other) \
&& (H)->root.type == bfd_link_hash_undefweak))
+/* TRUE if this symbol isn't defined by a shared object. */
+#define SYMBOL_DEFINED_NON_SHARED_P(H) \
+ ((H)->def_regular \
+ || (H)->root.linker_def \
+ || (H)->root.ldscript_def \
+ || ((struct elf_x86_link_hash_entry *) (H))->linker_def \
+ || ELF_COMMON_DEF_P (H))
+
+/* Return TRUE if the symbol described by a linker hash entry H is
+ going to be absolute. Similar to bfd_is_abs_symbol, but excluding
+ all linker-script defined symbols. */
+#define ABS_SYMBOL_P(H) \
+ (bfd_is_abs_symbol (&(H)->root) && !(H)->root.ldscript_def)
+
/* TRUE if relative relocation should be generated. GOT reference to
global symbol in PIC will lead to dynamic symbol. It becomes a
problem when "time" or "times" is defined as a variable in an
executable, clashing with functions of the same name in libc. If a
symbol isn't undefined weak symbol, don't make it dynamic in PIC and
- generate relative relocation. */
+ generate relative relocation. Don't generate relative relocation
+ against non-preemptible absolute symbol. */
#define GENERATE_RELATIVE_RELOC_P(INFO, H) \
((H)->dynindx == -1 \
&& !(H)->forced_local \
&& (H)->root.type != bfd_link_hash_undefweak \
- && bfd_link_pic (INFO))
+ && bfd_link_pic (INFO) \
+ && !ABS_SYMBOL_P (H))
/* TRUE if this is a pointer reference to a local IFUNC. */
#define POINTER_LOCAL_IFUNC_P(INFO, H) \
{
struct elf_link_hash_entry elf;
- /* Track dynamic relocs copied for this symbol. */
- struct elf_dyn_relocs *dyn_relocs;
-
unsigned char tls_type;
/* Bit 0: Symbol has no GOT nor PLT relocations.
/* Don't call finish_dynamic_symbol on this symbol. */
unsigned int no_finish_dynamic_symbol : 1;
+ /* R_*_RELATIVE relocation in GOT for this symbol has been
+ processed. */
+ unsigned int got_relative_reloc_done : 1;
+
/* TRUE if symbol is __tls_get_addr. */
unsigned int tls_get_addr : 1;
/* TRUE if symbol is defined by linker. */
unsigned int linker_def : 1;
+ /* TRUE if symbol is referenced by a non-GOT/non-PLT relocation in a
+ relocatable object file without indirect external access marker. */
+ unsigned int non_got_ref_without_indirect_extern_access : 1;
+
/* TRUE if symbol is referenced by R_386_GOTOFF relocation. This is
only used by i386. */
unsigned int gotoff_ref : 1;
struct elf_x86_lazy_plt_layout
{
- /* The first entry in an absolute lazy procedure linkage table looks
- like this. */
+ /* The first entry in a lazy procedure linkage table looks like this. */
const bfd_byte *plt0_entry;
unsigned int plt0_entry_size; /* Size of PLT0 entry. */
- /* Later entries in an absolute lazy procedure linkage table look
- like this. */
+ /* Later entries in a lazy procedure linkage table look like this. */
const bfd_byte *plt_entry;
unsigned int plt_entry_size; /* Size of each PLT entry. */
+ /* The TLSDESC entry in a lazy procedure linkage table looks like
+ this. This is for x86-64 only. */
+ const bfd_byte *plt_tlsdesc_entry;
+ unsigned int plt_tlsdesc_entry_size; /* Size of TLSDESC entry. */
+
+ /* Offsets into the TLSDESC entry that are to be replaced with
+ GOT+8 and GOT+TDG. These are for x86-64 only. */
+ unsigned int plt_tlsdesc_got1_offset;
+ unsigned int plt_tlsdesc_got2_offset;
+
+ /* Offset of the end of the PC-relative instructions containing
+ plt_tlsdesc_got1_offset and plt_tlsdesc_got2_offset. These
+ are for x86-64 only. */
+ unsigned int plt_tlsdesc_got1_insn_end;
+ unsigned int plt_tlsdesc_got2_insn_end;
+
/* Offsets into plt0_entry that are to be replaced with GOT[1] and
GOT[2]. */
unsigned int plt0_got1_offset;
struct elf_x86_non_lazy_plt_layout
{
- /* Entries in an absolute non-lazy procedure linkage table look like
- this. */
+ /* Entries in a non-lazy procedure linkage table look like this. */
const bfd_byte *plt_entry;
- /* Entries in a PIC non-lazy procedure linkage table look like this. */
+ /* Entries in a PIC non-lazy procedure linkage table look like this.
+ This is only used for i386 where absolute PLT and PIC PLT are
+ different. */
const bfd_byte *pic_plt_entry;
unsigned int plt_entry_size; /* Size of each PLT entry. */
struct elf_x86_plt_layout
{
- /* The first entry in a lazy procedure linkage table looks like this.
- This is only used for i386 where absolute PLT0 and PIC PLT0 are
- different. */
+ /* The first entry in a lazy procedure linkage table looks like this. */
const bfd_byte *plt0_entry;
/* Entries in a procedure linkage table look like this. */
const bfd_byte *plt_entry;
This is only used for x86-64. */
unsigned int plt_got_insn_size;
+ /* Alignment of the .iplt section. */
+ unsigned int iplt_alignment;
+
/* .eh_frame covering the .plt section. */
const bfd_byte *eh_frame_plt;
unsigned int eh_frame_plt_size;
#define GOT_TLS_IE_NEG 6
#define GOT_TLS_IE_BOTH 7
#define GOT_TLS_GDESC 8
+#define GOT_ABS 9
#define GOT_TLS_GD_BOTH_P(type) \
((type) == (GOT_TLS_GD | GOT_TLS_GDESC))
#define GOT_TLS_GD_P(type) \
#define elf_x86_hash_entry(ent) \
((struct elf_x86_link_hash_entry *)(ent))
-enum elf_x86_target_os
+/* Information of an input relocation used to compute its contribution
+ to the DT_RELR section size. */
+
+struct elf_x86_relative_reloc_record
{
- is_normal,
- is_vxworks,
- is_nacl
+ /* The original relocation info. */
+ Elf_Internal_Rela rel;
+ /* The input or the GOT section where the relocation is applied. */
+ asection *sec;
+ /* Local symbol info. NULL for global symbol. */
+ Elf_Internal_Sym *sym;
+ union
+ {
+ /* Section where the local symbol is defined. */
+ asection *sym_sec;
+ /* Global symbol hash. */
+ struct elf_link_hash_entry *h;
+ } u;
+ /* The offset into the output section where the relative relocation
+ will be applied at run-time. */
+ bfd_vma offset;
+ /* The run-time address. */
+ bfd_vma address;
+};
+
+struct elf_x86_relative_reloc_data
+{
+ bfd_size_type count;
+ bfd_size_type size;
+ struct elf_x86_relative_reloc_record *data;
+};
+
+/* DT_RELR bitmap. */
+struct elf_dt_relr_bitmap
+{
+ bfd_size_type count;
+ bfd_size_type size;
+ union
+ {
+ /* 32-bit bitmap. */
+ uint32_t *elf32;
+ /* 64-bit bitmap. */
+ uint64_t *elf64;
+ } u;
};
/* x86 ELF linker hash table. */
/* The amount of space used by the jump slots in the GOT. */
bfd_vma sgotplt_jump_table_size;
- /* Small local sym cache. */
- struct sym_cache sym_cache;
-
/* _TLS_MODULE_BASE_ symbol. */
struct bfd_link_hash_entry *tls_module_base;
htab_t loc_hash_table;
void * loc_hash_memory;
- /* The offset into sgot of the GOT entry used by the PLT entry
- above. */
- bfd_vma tlsdesc_got;
-
/* The index of the next R_X86_64_JUMP_SLOT entry in .rela.plt. */
bfd_vma next_jump_slot_index;
/* The index of the next R_X86_64_IRELATIVE entry in .rela.plt. */
bfd_vma next_irelative_index;
- /* TRUE if there are dynamic relocs against IFUNC symbols that apply
- to read-only sections. */
- bfd_boolean readonly_dynrelocs_against_ifunc;
-
/* The (unloaded but important) .rel.plt.unloaded section on VxWorks.
This is used for i386 only. */
asection *srelplt2;
is only used for i386. */
bfd_vma next_tls_desc_index;
- /* The offset into splt of the PLT entry for the TLS descriptor
- resolver. Special values are 0, if not necessary (or not found
- to be necessary yet), and -1 if needed but not determined
- yet. This is only used for x86-64. */
- bfd_vma tlsdesc_plt;
+ /* DT_RELR bitmap. */
+ struct elf_dt_relr_bitmap dt_relr_bitmap;
+
+ /* Relative relocation data. */
+ struct elf_x86_relative_reloc_data relative_reloc;
+
+ /* Unaligned relative relocation data. */
+ struct elf_x86_relative_reloc_data unaligned_relative_reloc;
+
+ /* Number of relative reloc generation pass. */
+ unsigned int generate_relative_reloc_pass;
/* Value used to fill the unused bytes of the first PLT entry. This
is only used for i386. */
bfd_byte plt0_pad_byte;
+ /* TRUE if GOT is referenced. */
+ unsigned int got_referenced : 1;
+
+ /* TRUE if PLT is PC-relative. PLT in PDE and PC-relative PLT in PIE
+ can be used as function address.
+
+ NB: i386 has non-PIC PLT and PIC PLT. Only non-PIC PLT in PDE can
+ be used as function address. PIC PLT in PIE can't be used as
+ function address. */
+ unsigned int pcrel_plt : 1;
+
bfd_vma (*r_info) (bfd_vma, bfd_vma);
bfd_vma (*r_sym) (bfd_vma);
- bfd_boolean (*is_reloc_section) (const char *);
- enum elf_target_id target_id;
- enum elf_x86_target_os target_os;
+ bool (*is_reloc_section) (const char *);
unsigned int sizeof_reloc;
- unsigned int dt_reloc;
- unsigned int dt_reloc_sz;
- unsigned int dt_reloc_ent;
unsigned int got_entry_size;
unsigned int pointer_r_type;
+ unsigned int relative_r_type;
int dynamic_interpreter_size;
const char *dynamic_interpreter;
const char *tls_get_addr;
-};
-
-/* Architecture-specific backend data for x86. */
+ const char *relative_r_name;
+ void (*elf_append_reloc) (bfd *, asection *, Elf_Internal_Rela *);
+ void (*elf_write_addend) (bfd *, uint64_t, void *);
+ void (*elf_write_addend_in_got) (bfd *, uint64_t, void *);
-struct elf_x86_backend_data
-{
- /* Target system. */
- enum elf_x86_target_os target_os;
+ /* Options passed from the linker. */
+ struct elf_linker_x86_params *params;
};
-#define get_elf_x86_backend_data(abfd) \
- ((const struct elf_x86_backend_data *) \
- get_elf_backend_data (abfd)->arch_data)
-
struct elf_x86_init_table
{
/* The lazy PLT layout. */
/* GOTPLT entries for TLS descriptors. */
bfd_vma *local_tlsdesc_gotent;
+
+ /* R_*_RELATIVE relocation in GOT for this local symbol has been
+ processed. */
+ char *relative_reloc_done;
};
enum elf_x86_plt_type
long count;
};
+/* Set if a relocation is converted from a GOTPCREL relocation. */
+#define R_X86_64_converted_reloc_bit (1 << 7)
+
#define elf_x86_tdata(abfd) \
((struct elf_x86_obj_tdata *) (abfd)->tdata.any)
#define elf_x86_local_tlsdesc_gotent(abfd) \
(elf_x86_tdata (abfd)->local_tlsdesc_gotent)
+#define elf_x86_relative_reloc_done(abfd) \
+ (elf_x86_tdata (abfd)->relative_reloc_done)
+
#define elf_x86_compute_jump_table_size(htab) \
((htab)->elf.srelplt->reloc_count * (htab)->got_entry_size)
#define is_x86_elf(bfd, htab) \
(bfd_get_flavour (bfd) == bfd_target_elf_flavour \
&& elf_tdata (bfd) != NULL \
- && elf_object_id (bfd) == (htab)->target_id)
+ && elf_object_id (bfd) == (htab)->elf.hash_table_id)
-extern bfd_boolean _bfd_x86_elf_mkobject
+/* Rename some of the generic section flags to better document how they
+ are used here. */
+#define check_relocs_failed sec_flg0
+#define relative_reloc_packed sec_flg1
+
+extern bool _bfd_x86_elf_mkobject
(bfd *);
extern void _bfd_x86_elf_set_tls_module_base
extern bfd_vma _bfd_x86_elf_dtpoff_base
(struct bfd_link_info *);
-extern bfd_boolean _bfd_x86_elf_readonly_dynrelocs
+extern bool _bfd_x86_elf_readonly_dynrelocs
(struct elf_link_hash_entry *, void *);
extern struct elf_link_hash_entry * _bfd_elf_x86_get_local_sym_hash
(struct elf_x86_link_hash_table *, bfd *, const Elf_Internal_Rela *,
- bfd_boolean);
+ bool);
extern hashval_t _bfd_x86_elf_local_htab_hash
(const void *);
extern int _bfd_x86_elf_compare_relocs
(const void *, const void *);
-extern bfd_boolean _bfd_x86_elf_link_check_relocs
+extern bool _bfd_x86_elf_link_check_relocs
(bfd *, struct bfd_link_info *);
-extern bfd_boolean _bfd_x86_elf_size_dynamic_sections
+extern bool _bfd_x86_elf_check_relocs
+ (bfd *, struct bfd_link_info *, asection *,
+ const Elf_Internal_Rela *);
+
+extern bool _bfd_x86_elf_link_relax_section
+ (bfd *, asection *, struct bfd_link_info *, bool *);
+
+extern bool _bfd_elf_x86_size_relative_relocs
+ (struct bfd_link_info *, bool *);
+
+extern bool _bfd_elf_x86_finish_relative_relocs
+ (struct bfd_link_info *);
+
+extern void _bfd_elf32_write_addend (bfd *, uint64_t, void *);
+extern void _bfd_elf64_write_addend (bfd *, uint64_t, void *);
+
+extern bool _bfd_elf_x86_valid_reloc_p
+ (asection *, struct bfd_link_info *, struct elf_x86_link_hash_table *,
+ const Elf_Internal_Rela *, struct elf_link_hash_entry *,
+ Elf_Internal_Sym *, Elf_Internal_Shdr *, bool *);
+
+extern bool _bfd_x86_elf_size_dynamic_sections
(bfd *, struct bfd_link_info *);
extern struct elf_x86_link_hash_table *_bfd_x86_elf_finish_dynamic_sections
(bfd *, struct bfd_link_info *);
-extern bfd_boolean _bfd_x86_elf_always_size_sections
+extern bool _bfd_x86_elf_always_size_sections
(bfd *, struct bfd_link_info *);
extern void _bfd_x86_elf_merge_symbol_attribute
- (struct elf_link_hash_entry *, const Elf_Internal_Sym *,
- bfd_boolean, bfd_boolean);
+ (struct elf_link_hash_entry *, unsigned int, bool, bool);
extern void _bfd_x86_elf_copy_indirect_symbol
(struct bfd_link_info *, struct elf_link_hash_entry *,
struct elf_link_hash_entry *);
-extern bfd_boolean _bfd_x86_elf_fixup_symbol
+extern bool _bfd_x86_elf_fixup_symbol
(struct bfd_link_info *, struct elf_link_hash_entry *);
-extern bfd_boolean _bfd_x86_elf_hash_symbol
+extern bool _bfd_x86_elf_hash_symbol
(struct elf_link_hash_entry *);
-extern bfd_boolean _bfd_x86_elf_adjust_dynamic_symbol
+extern bool _bfd_x86_elf_adjust_dynamic_symbol
(struct bfd_link_info *, struct elf_link_hash_entry *);
extern void _bfd_x86_elf_hide_symbol
- (struct bfd_link_info *, struct elf_link_hash_entry *, bfd_boolean);
+ (struct bfd_link_info *, struct elf_link_hash_entry *, bool);
-extern bfd_boolean _bfd_x86_elf_link_symbol_references_local
+extern bool _bfd_x86_elf_link_symbol_references_local
(struct bfd_link_info *, struct elf_link_hash_entry *);
extern asection * _bfd_x86_elf_gc_mark_hook
extern enum elf_property_kind _bfd_x86_elf_parse_gnu_properties
(bfd *, unsigned int, bfd_byte *, unsigned int);
-extern bfd_boolean _bfd_x86_elf_merge_gnu_properties
- (struct bfd_link_info *, bfd *, elf_property *, elf_property *);
+extern bool _bfd_x86_elf_merge_gnu_properties
+ (struct bfd_link_info *, bfd *, bfd *, elf_property *, elf_property *);
+
+extern void _bfd_x86_elf_link_fixup_gnu_properties
+ (struct bfd_link_info *, elf_property_list **);
extern bfd * _bfd_x86_elf_link_setup_gnu_properties
(struct bfd_link_info *, struct elf_x86_init_table *);
+extern void _bfd_x86_elf_link_fixup_ifunc_symbol
+ (struct bfd_link_info *, struct elf_x86_link_hash_table *,
+ struct elf_link_hash_entry *, Elf_Internal_Sym *sym);
+
+extern void _bfd_x86_elf_link_report_relative_reloc
+ (struct bfd_link_info *, asection *, struct elf_link_hash_entry *,
+ Elf_Internal_Sym *, const char *, const void *);
+
#define bfd_elf64_mkobject \
_bfd_x86_elf_mkobject
#define bfd_elf32_mkobject \
_bfd_x86_elf_link_check_relocs
#define bfd_elf32_bfd_link_check_relocs \
_bfd_x86_elf_link_check_relocs
+#define bfd_elf32_bfd_relax_section \
+ _bfd_x86_elf_link_relax_section
+#define bfd_elf64_bfd_relax_section \
+ _bfd_x86_elf_link_relax_section
+#define elf_backend_check_relocs \
+ _bfd_x86_elf_check_relocs
#define elf_backend_size_dynamic_sections \
_bfd_x86_elf_size_dynamic_sections
-#define elf_backend_always_size_sections \
- _bfd_x86_elf_always_size_sections
#define elf_backend_merge_symbol_attribute \
_bfd_x86_elf_merge_symbol_attribute
#define elf_backend_copy_indirect_symbol \
#define elf_backend_gc_mark_hook \
_bfd_x86_elf_gc_mark_hook
#define elf_backend_omit_section_dynsym \
- ((bfd_boolean (*) (bfd *, struct bfd_link_info *, asection *)) bfd_true)
+ _bfd_elf_omit_section_dynsym_all
#define elf_backend_parse_gnu_properties \
_bfd_x86_elf_parse_gnu_properties
#define elf_backend_merge_gnu_properties \
_bfd_x86_elf_merge_gnu_properties
+#define elf_backend_fixup_gnu_properties \
+ _bfd_x86_elf_link_fixup_gnu_properties
+#define elf_backend_size_relative_relocs \
+ _bfd_elf_x86_size_relative_relocs
+#define elf_backend_finish_relative_relocs \
+ _bfd_elf_x86_finish_relative_relocs
+
+#define ELF_P_ALIGN ELF_MINPAGESIZE
+
+/* Allocate x86 GOT info for local symbols. */
+
+static inline bool
+elf_x86_allocate_local_got_info (bfd *abfd, bfd_size_type count)
+{
+ bfd_signed_vma *local_got_refcounts = elf_local_got_refcounts (abfd);
+ if (local_got_refcounts == NULL)
+ {
+ bfd_size_type size = count * (sizeof (bfd_signed_vma)
+ + sizeof (bfd_vma)
+ + 2 * sizeof(char));
+ local_got_refcounts = (bfd_signed_vma *) bfd_zalloc (abfd, size);
+ if (local_got_refcounts == NULL)
+ return false;
+ elf_local_got_refcounts (abfd) = local_got_refcounts;
+ elf_x86_local_tlsdesc_gotent (abfd) =
+ (bfd_vma *) (local_got_refcounts + count);
+ elf_x86_local_got_tls_type (abfd) =
+ (char *) (local_got_refcounts + 2 * count);
+ elf_x86_relative_reloc_done (abfd) =
+ ((char *) (local_got_refcounts + 2 * count)) + count;
+ }
+ return true;
+}