]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - bfd/elfxx-x86.h
x86: Silence -fsanitize=undefined
[thirdparty/binutils-gdb.git] / bfd / elfxx-x86.h
index a6a8455ba96498a8f41989937b6ee5a91aee4931..c717cd16e56ed18749fd9589410cad42adada3b9 100644 (file)
@@ -1,5 +1,5 @@
 /* x86 specific support for ELF
-   Copyright (C) 2017 Free Software Foundation, Inc.
+   Copyright (C) 2017-2020 Free Software Foundation, Inc.
 
    This file is part of BFD, the Binary File Descriptor library.
 
@@ -23,8 +23,8 @@
 #include "bfdlink.h"
 #include "libbfd.h"
 #include "elf-bfd.h"
-#include "bfd_stdint.h"
 #include "hashtab.h"
+#include "elf-linker-x86.h"
 
 #define PLT_CIE_LENGTH         20
 #define PLT_FDE_LENGTH         36
    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(INFO, PCREL_PLT, H, SEC, R_TYPE, \
+                                 POINTER_TYPE) \
   ((bfd_link_pic (INFO) \
     && (! X86_PCREL_TYPE_P (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, \
+   when PIC is false.  Don't generate dynamic relocations against
+   non-preemptible absolute symbol.  */
+#define GENERATE_DYNAMIC_RELOCATION_P(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 \
+            || 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 (R_TYPE) && !X86_SIZE_TYPE_P (R_TYPE)) \
+       || ! SYMBOL_CALLS_LOCAL ((INFO), \
+                                (struct elf_link_hash_entry *) (EH)))) \
    || (ELIMINATE_COPY_RELOCS \
        && !bfd_link_pic (INFO) \
        && (EH) != NULL \
        && (EH)->elf.dynindx != -1 \
        && (!(EH)->elf.non_got_ref \
-          || (EH)->func_pointer_refcount > 0 \
           || ((EH)->elf.root.type == bfd_link_hash_undefweak \
               && !(RESOLVED_TO_ZERO))) \
               && (((EH)->elf.def_dynamic && !(EH)->elf.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) \
@@ -227,9 +250,6 @@ struct elf_x86_link_hash_entry
 {
   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.
@@ -268,10 +288,6 @@ struct elf_x86_link_hash_entry
      is only used by x86-64.  */
   unsigned int needs_copy : 1;
 
-  /* Reference count of C/C++ function pointer relocations in read-write
-     section which can be resolved at run-time.  */
-  bfd_signed_vma func_pointer_refcount;
-
   /* Information about the GOT PLT entry. Filled when there are both
      GOT and PLT relocations against the same function.  */
   union gotplt_union plt_got;
@@ -286,15 +302,29 @@ struct elf_x86_link_hash_entry
 
 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.  */
+  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.  */
+  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].  */
@@ -337,13 +367,14 @@ struct elf_x86_lazy_plt_layout
 
 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.  */
+  unsigned int plt_entry_size;         /* Size of each PLT entry.  */
 
   /* Offsets into plt_entry that are to be replaced with...  */
   unsigned int plt_got_offset;    /* ... address of this symbol in .got. */
@@ -359,13 +390,11 @@ struct elf_x86_non_lazy_plt_layout
 
 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;
-  unsigned int plt_entry_size;          /* Size of each PLT entry.  */
+  unsigned int plt_entry_size;         /* Size of each PLT entry.  */
 
   /* 1 has PLT0.  */
   unsigned int has_plt0;
@@ -377,6 +406,9 @@ struct elf_x86_plt_layout
      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;
@@ -391,6 +423,7 @@ struct elf_x86_plt_layout
 #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) \
@@ -403,6 +436,14 @@ struct elf_x86_plt_layout
 #define elf_x86_hash_entry(ent) \
   ((struct elf_x86_link_hash_entry *)(ent))
 
+enum elf_x86_target_os
+{
+  is_normal,
+  is_solaris,
+  is_vxworks,
+  is_nacl
+};
+
 /* x86 ELF linker hash table.  */
 
 struct elf_x86_link_hash_table
@@ -458,10 +499,6 @@ struct elf_x86_link_hash_table
      to read-only sections.  */
   bfd_boolean readonly_dynrelocs_against_ifunc;
 
-  /* TRUE if this is a VxWorks x86 target.  This is only used for
-     i386.  */
-  bfd_boolean is_vxworks;
-
   /* The (unloaded but important) .rel.plt.unloaded section on VxWorks.
      This is used for i386 only.  */
   asection *srelplt2;
@@ -476,10 +513,26 @@ struct elf_x86_link_hash_table
      yet.  This is only used for x86-64.  */
   bfd_vma tlsdesc_plt;
 
+   /* 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;
   unsigned int sizeof_reloc;
   unsigned int dt_reloc;
   unsigned int dt_reloc_sz;
@@ -489,8 +542,23 @@ struct elf_x86_link_hash_table
   int dynamic_interpreter_size;
   const char *dynamic_interpreter;
   const char *tls_get_addr;
+
+  /* Options passed from the linker.  */
+  struct elf_linker_x86_params *params;
 };
 
+/* Architecture-specific backend data for x86.  */
+
+struct elf_x86_backend_data
+{
+  /* Target system.  */
+  enum elf_x86_target_os target_os;
+};
+
+#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.  */
@@ -505,11 +573,7 @@ struct elf_x86_init_table
   /* The non-lazy PLT layout for IBT.  */
   const struct elf_x86_non_lazy_plt_layout *non_lazy_ibt_plt;
 
-  /* TRUE if this is a normal x86 target.  */
-  bfd_boolean normal_target;
-
-  /* TRUE if this is a VxWorks x86 target.  */
-  bfd_boolean is_vxworks;
+  bfd_byte plt0_pad_byte;
 
   bfd_vma (*r_info) (bfd_vma, bfd_vma);
   bfd_vma (*r_sym) (bfd_vma);
@@ -547,6 +611,9 @@ struct elf_x86_plt
   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)
 
@@ -598,6 +665,11 @@ extern int _bfd_x86_elf_compare_relocs
 extern bfd_boolean _bfd_x86_elf_link_check_relocs
   (bfd *, struct bfd_link_info *);
 
+extern bfd_boolean _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 *, bfd_boolean *);
+
 extern bfd_boolean _bfd_x86_elf_size_dynamic_sections
   (bfd *, struct bfd_link_info *);
 
@@ -642,11 +714,18 @@ 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 *);
+  (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);
+
 #define bfd_elf64_mkobject \
   _bfd_x86_elf_mkobject
 #define bfd_elf32_mkobject \
@@ -677,8 +756,10 @@ extern bfd * _bfd_x86_elf_link_setup_gnu_properties
 #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