-Wimplicit-fallthrough warning fixes
[deliverable/binutils-gdb.git] / bfd / elf64-x86-64.c
index 46f723c5d55c47bca805800403a30f384b288664..2a372a6f3f5757bdd8844c9cbb8ce705cc8777ef 100644 (file)
@@ -285,8 +285,8 @@ elf_x86_64_rtype_to_howto (bfd *abfd, unsigned r_type)
     {
       if (r_type >= (unsigned int) R_X86_64_standard)
        {
-         (*_bfd_error_handler) (_("%B: invalid relocation type %d"),
-                                abfd, (int) r_type);
+         _bfd_error_handler (_("%B: invalid relocation type %d"),
+                             abfd, (int) r_type);
          r_type = R_X86_64_NONE;
        }
       i = r_type;
@@ -1162,6 +1162,17 @@ elf_x86_64_create_dynamic_sections (bfd *dynobj,
          || !bfd_set_section_alignment (dynobj, htab->plt_eh_frame, 3))
        return FALSE;
     }
+
+  /* Align .got section to its entry size.  */
+  if (htab->elf.sgot != NULL
+      && !bfd_set_section_alignment (dynobj, htab->elf.sgot, 3))
+    return FALSE;
+
+  /* Align .got.plt section to its entry size.  */
+  if (htab->elf.sgotplt != NULL
+      && !bfd_set_section_alignment (dynobj, htab->elf.sgotplt, 3))
+    return FALSE;
+
   return TRUE;
 }
 
@@ -1642,7 +1653,7 @@ elf_x86_64_tls_transition (struct bfd_link_info *info, bfd *abfd,
            }
        }
 
-      (*_bfd_error_handler)
+      _bfd_error_handler
        (_("%B: TLS transition from %s to %s against `%s' at 0x%lx "
           "in section `%A' failed"),
         abfd, sec, from->name, to->name, name,
@@ -1701,9 +1712,9 @@ elf_x86_64_need_pic (bfd *input_bfd, asection *sec,
       pic = _("; recompile with -fPIC");
     }
 
-  (*_bfd_error_handler) (_("%B: relocation %s against %s%s`%s' can "
-                          "not be used when making a shared object%s"),
-                        input_bfd, howto->name, und, v, name, pic);
+  _bfd_error_handler (_("%B: relocation %s against %s%s`%s' can "
+                       "not be used when making a shared object%s"),
+                     input_bfd, howto->name, und, v, name, pic);
   bfd_set_error (bfd_error_bad_value);
   sec->check_relocs_failed = 1;
   return FALSE;
@@ -2143,6 +2154,15 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
   if (bfd_link_relocatable (info))
     return TRUE;
 
+  /* Don't do anything special with non-loaded, non-alloced sections.
+     In particular, any relocs in such sections should not affect GOT
+     and PLT reference counting (ie. we don't allow them to create GOT
+     or PLT entries), there's no possibility or desire to optimize TLS
+     relocs, and there's not much point in propagating relocs to shared
+     libs that the dynamic linker won't relocate.  */
+  if ((sec->flags & SEC_ALLOC) == 0)
+    return TRUE;
+
   BFD_ASSERT (is_x86_64_elf (abfd));
 
   htab = elf_x86_64_hash_table (info);
@@ -2184,8 +2204,8 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
 
       if (r_symndx >= NUM_SHDR_ENTRIES (symtab_hdr))
        {
-         (*_bfd_error_handler) (_("%B: bad symbol index: %d"),
-                                abfd, r_symndx);
+         _bfd_error_handler (_("%B: bad symbol index: %d"),
+                             abfd, r_symndx);
          goto error_return;
        }
 
@@ -2246,7 +2266,7 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
                else
                  name = bfd_elf_sym_name (abfd, symtab_hdr, isym,
                                           NULL);
-               (*_bfd_error_handler)
+               _bfd_error_handler
                  (_("%B: relocation %s against symbol `%s' isn't "
                     "supported in x32 mode"), abfd,
                   x86_64_elf_howto_table[r_type].name, name);
@@ -2307,6 +2327,7 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
                        goto error_return;
                    }
                }
+             /* Fall through.  */
 
            case R_X86_64_32S:
            case R_X86_64_PC64:
@@ -2434,7 +2455,7 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
                    else
                      name = bfd_elf_sym_name (abfd, symtab_hdr,
                                               isym, NULL);
-                   (*_bfd_error_handler)
+                   _bfd_error_handler
                      (_("%B: '%s' accessed both as normal and thread local symbol"),
                       abfd, name);
                    bfd_set_error (bfd_error_bad_value);
@@ -2505,6 +2526,7 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
        case R_X86_64_32:
          if (!ABI_64_P (abfd))
            goto pointer;
+         /* Fall through.  */
        case R_X86_64_8:
        case R_X86_64_16:
        case R_X86_64_32S:
@@ -2518,8 +2540,7 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
                      && h != NULL
                      && !h->def_regular
                      && h->def_dynamic
-                     && (sec->flags & SEC_READONLY) == 0))
-             && (sec->flags & SEC_ALLOC) != 0)
+                     && (sec->flags & SEC_READONLY) == 0)))
            return elf_x86_64_need_pic (abfd, sec, h, symtab_hdr, isym,
                                        &x86_64_elf_howto_table[r_type]);
          /* Fall through.  */
@@ -2533,15 +2554,12 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
 pointer:
          if (eh != NULL && (sec->flags & SEC_CODE) != 0)
            eh->has_non_got_reloc = 1;
-         /* STT_GNU_IFUNC symbol must go through PLT even if it is
-            locally defined and undefined symbol may turn out to be
-            a STT_GNU_IFUNC symbol later.  */
+         /* We are called after all symbols have been resolved.  Only
+            relocation against STT_GNU_IFUNC symbol must go through
+            PLT.  */
          if (h != NULL
              && (bfd_link_executable (info)
-                 || ((h->type == STT_GNU_IFUNC
-                      || h->root.type == bfd_link_hash_undefweak
-                      || h->root.type == bfd_link_hash_undefined)
-                     && SYMBOLIC_BIND (info, h))))
+                 || 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
@@ -2551,9 +2569,13 @@ pointer:
                 adjust_dynamic_symbol.  */
              h->non_got_ref = 1;
 
-             /* We may need a .plt entry if the function this reloc
-                refers to is in a shared lib.  */
-             h->plt.refcount += 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;
+
              if (r_type == R_X86_64_PC32)
                {
                  /* Since something like ".long foo - ." may be used
@@ -2600,18 +2622,23 @@ do_size:
             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.  */
+            symbol.
+
+            Generate dynamic pointer relocation against STT_GNU_IFUNC
+            symbol in the non-code section.  */
          if ((bfd_link_pic (info)
-              && (sec->flags & SEC_ALLOC) != 0
               && (! IS_X86_64_PCREL_TYPE (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 == htab->pointer_r_type
+                 && (sec->flags & SEC_CODE) == 0)
              || (ELIMINATE_COPY_RELOCS
                  && !bfd_link_pic (info)
-                 && (sec->flags & SEC_ALLOC) != 0
                  && h != NULL
                  && (h->root.type == bfd_link_hash_defweak
                      || !h->def_regular)))
@@ -2847,12 +2874,17 @@ elf_x86_64_adjust_dynamic_symbol (struct bfd_link_info *info,
 
          if (pc_count || count)
            {
-             h->needs_plt = 1;
              h->non_got_ref = 1;
-             if (h->plt.refcount <= 0)
-               h->plt.refcount = 1;
-             else
-               h->plt.refcount += 1;
+             if (pc_count)
+               {
+                 /* Increment PLT reference count only for PC-relative
+                    references.  */
+                 h->needs_plt = 1;
+                 if (h->plt.refcount <= 0)
+                   h->plt.refcount = 1;
+                 else
+                   h->plt.refcount += 1;
+               }
            }
        }
 
@@ -3046,7 +3078,7 @@ elf_x86_64_allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
                                              &htab->readonly_dynrelocs_against_ifunc,
                                              plt_entry_size,
                                              plt_entry_size,
-                                             GOT_ENTRY_SIZE))
+                                             GOT_ENTRY_SIZE, TRUE))
        {
          asection *s = htab->plt_bnd;
          if (h->plt.offset != (bfd_vma) -1 && s != NULL)
@@ -4114,7 +4146,7 @@ elf_x86_64_relocate_section (bfd *output_bfd,
 
       if (r_type >= (int) R_X86_64_standard)
        {
-         (*_bfd_error_handler)
+         _bfd_error_handler
            (_("%B: unrecognized relocation (0x%x) in section `%A'"),
             input_bfd, input_section, r_type);
          bfd_set_error (bfd_error_bad_value);
@@ -4230,8 +4262,84 @@ elf_x86_64_relocate_section (bfd *output_bfd,
                continue;
              abort ();
            }
-         else if (h->plt.offset == (bfd_vma) -1)
-           abort ();
+
+         switch (r_type)
+           {
+           default:
+             break;
+
+           case R_X86_64_GOTPCREL:
+           case R_X86_64_GOTPCRELX:
+           case R_X86_64_REX_GOTPCRELX:
+           case R_X86_64_GOTPCREL64:
+             base_got = htab->elf.sgot;
+             off = h->got.offset;
+
+             if (base_got == NULL)
+               abort ();
+
+             if (off == (bfd_vma) -1)
+               {
+                 /* We can't use h->got.offset here to save state, or
+                    even just remember the offset, as finish_dynamic_symbol
+                    would use that as offset into .got.  */
+
+                 if (h->plt.offset == (bfd_vma) -1)
+                   abort ();
+
+                 if (htab->elf.splt != NULL)
+                   {
+                     plt_index = h->plt.offset / plt_entry_size - 1;
+                     off = (plt_index + 3) * GOT_ENTRY_SIZE;
+                     base_got = htab->elf.sgotplt;
+                   }
+                 else
+                   {
+                     plt_index = h->plt.offset / plt_entry_size;
+                     off = plt_index * GOT_ENTRY_SIZE;
+                     base_got = htab->elf.igotplt;
+                   }
+
+                 if (h->dynindx == -1
+                     || h->forced_local
+                     || info->symbolic)
+                   {
+                     /* 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,
+                        we use the least significant bit to record
+                        whether we have initialized it already.
+
+                        When doing a dynamic link, we create a .rela.got
+                        relocation entry to initialize the value.  This
+                        is done in the finish_dynamic_symbol routine.   */
+                     if ((off & 1) != 0)
+                       off &= ~1;
+                     else
+                       {
+                         bfd_put_64 (output_bfd, relocation,
+                                     base_got->contents + off);
+                         /* Note that this is harmless for the GOTPLT64
+                            case, as -1 | 1 still is -1.  */
+                         h->got.offset |= 1;
+                       }
+                   }
+               }
+
+             relocation = (base_got->output_section->vma
+                           + base_got->output_offset + off);
+
+             goto do_relocation;
+           }
+
+         if (h->plt.offset == (bfd_vma) -1)
+           {
+             /* Handle static pointers of STT_GNU_IFUNC symbols.  */
+             if (r_type == htab->pointer_r_type
+                 && (input_section->flags & SEC_CODE) == 0)
+               goto do_ifunc_pointer;
+             goto bad_ifunc_reloc;
+           }
 
          /* STT_GNU_IFUNC symbol must go through PLT.  */
          if (htab->elf.splt != NULL)
@@ -4259,15 +4367,16 @@ elf_x86_64_relocate_section (bfd *output_bfd,
          switch (r_type)
            {
            default:
+bad_ifunc_reloc:
              if (h->root.root.string)
                name = h->root.root.string;
              else
                name = bfd_elf_sym_name (input_bfd, symtab_hdr, sym,
                                         NULL);
-             (*_bfd_error_handler)
+             _bfd_error_handler
                (_("%B: relocation %s against STT_GNU_IFUNC "
-                  "symbol `%s' isn't handled by %s"), input_bfd,
-                howto->name, name, __FUNCTION__);
+                  "symbol `%s' isn't supported"), input_bfd,
+                howto->name, name);
              bfd_set_error (bfd_error_bad_value);
              return FALSE;
 
@@ -4281,6 +4390,7 @@ elf_x86_64_relocate_section (bfd *output_bfd,
                goto do_relocation;
              /* FALLTHROUGH */
            case R_X86_64_64:
+do_ifunc_pointer:
              if (rel->r_addend != 0)
                {
                  if (h->root.root.string)
@@ -4288,7 +4398,7 @@ elf_x86_64_relocate_section (bfd *output_bfd,
                  else
                    name = bfd_elf_sym_name (input_bfd, symtab_hdr,
                                             sym, NULL);
-                 (*_bfd_error_handler)
+                 _bfd_error_handler
                    (_("%B: relocation %s against STT_GNU_IFUNC "
                       "symbol `%s' has non-zero addend: %d"),
                     input_bfd, howto->name, name, rel->r_addend);
@@ -4297,8 +4407,10 @@ elf_x86_64_relocate_section (bfd *output_bfd,
                }
 
              /* Generate dynamic relcoation only when there is a
-                non-GOT reference in a shared object.  */
-             if (bfd_link_pic (info) && h->non_got_ref)
+                non-GOT reference in a shared object or there is no
+                PLT.  */
+             if ((bfd_link_pic (info) && h->non_got_ref)
+                 || h->plt.offset == (bfd_vma) -1)
                {
                  Elf_Internal_Rela outrel;
                  asection *sreloc;
@@ -4332,7 +4444,16 @@ elf_x86_64_relocate_section (bfd *output_bfd,
                      outrel.r_addend = 0;
                    }
 
-                 sreloc = htab->elf.irelifunc;
+                 /* Dynamic relocations are stored in
+                    1. .rela.ifunc section in PIC object.
+                    2. .rela.got section in dynamic executable.
+                    3. .rela.iplt section in static executable.  */
+                 if (bfd_link_pic (info))
+                   sreloc = htab->elf.irelifunc;
+                 else if (htab->elf.splt != NULL)
+                   sreloc = htab->elf.srelgot;
+                 else
+                   sreloc = htab->elf.irelplt;
                  elf_append_rela (output_bfd, sreloc, &outrel);
 
                  /* If this reloc is against an external symbol, we
@@ -4349,66 +4470,6 @@ elf_x86_64_relocate_section (bfd *output_bfd,
            case R_X86_64_PLT32:
            case R_X86_64_PLT32_BND:
              goto do_relocation;
-
-           case R_X86_64_GOTPCREL:
-           case R_X86_64_GOTPCRELX:
-           case R_X86_64_REX_GOTPCRELX:
-           case R_X86_64_GOTPCREL64:
-             base_got = htab->elf.sgot;
-             off = h->got.offset;
-
-             if (base_got == NULL)
-               abort ();
-
-             if (off == (bfd_vma) -1)
-               {
-                 /* We can't use h->got.offset here to save state, or
-                    even just remember the offset, as finish_dynamic_symbol
-                    would use that as offset into .got.  */
-
-                 if (htab->elf.splt != NULL)
-                   {
-                     plt_index = h->plt.offset / plt_entry_size - 1;
-                     off = (plt_index + 3) * GOT_ENTRY_SIZE;
-                     base_got = htab->elf.sgotplt;
-                   }
-                 else
-                   {
-                     plt_index = h->plt.offset / plt_entry_size;
-                     off = plt_index * GOT_ENTRY_SIZE;
-                     base_got = htab->elf.igotplt;
-                   }
-
-                 if (h->dynindx == -1
-                     || h->forced_local
-                     || info->symbolic)
-                   {
-                     /* 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,
-                        we use the least significant bit to record
-                        whether we have initialized it already.
-
-                        When doing a dynamic link, we create a .rela.got
-                        relocation entry to initialize the value.  This
-                        is done in the finish_dynamic_symbol routine.   */
-                     if ((off & 1) != 0)
-                       off &= ~1;
-                     else
-                       {
-                         bfd_put_64 (output_bfd, relocation,
-                                     base_got->contents + off);
-                         /* Note that this is harmless for the GOTPLT64
-                            case, as -1 | 1 still is -1.  */
-                         h->got.offset |= 1;
-                       }
-                   }
-               }
-
-             relocation = (base_got->output_section->vma
-                           + base_got->output_offset + off);
-
-             goto do_relocation;
            }
        }
 
@@ -4572,7 +4633,7 @@ elf_x86_64_relocate_section (bfd *output_bfd,
                      break;
                    }
 
-                 (*_bfd_error_handler)
+                 _bfd_error_handler
                    (_("%B: relocation R_X86_64_GOTOFF64 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);
@@ -4584,7 +4645,7 @@ elf_x86_64_relocate_section (bfd *output_bfd,
                           || h->type == STT_OBJECT)
                       && ELF_ST_VISIBILITY (h->other) == STV_PROTECTED)
                {
-                 (*_bfd_error_handler)
+                 _bfd_error_handler
                    (_("%B: relocation R_X86_64_GOTOFF64 against protected %s `%s' can not be used when making a shared object"),
                     input_bfd,
                     h->type == STT_FUNC ? "function" : "data",
@@ -4759,7 +4820,9 @@ direct:
                    && (h->needs_copy
                        || eh->needs_copy
                        || h->root.type == bfd_link_hash_undefined)
-                   && IS_X86_64_PCREL_TYPE (r_type))
+                   && (IS_X86_64_PCREL_TYPE (r_type)
+                       || r_type == R_X86_64_SIZE32
+                       || r_type == R_X86_64_SIZE64))
               && (h == NULL
                   || ((ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
                        && !resolved_to_zero)
@@ -4849,7 +4912,7 @@ direct:
                            name = bfd_elf_sym_name (input_bfd, symtab_hdr,
                                                     sym, NULL);
                          if (addend < 0)
-                           (*_bfd_error_handler)
+                           _bfd_error_handler
                              (_("%B: addend -0x%x in relocation %s against "
                                 "symbol `%s' at 0x%lx in section `%A' is "
                                 "out of range"),
@@ -4857,7 +4920,7 @@ direct:
                               howto->name, name,
                               (unsigned long) rel->r_offset);
                          else
-                           (*_bfd_error_handler)
+                           _bfd_error_handler
                              (_("%B: addend 0x%x in relocation %s against "
                                 "symbol `%s' at 0x%lx in section `%A' is "
                                 "out of range"),
@@ -5480,7 +5543,7 @@ direct:
          && _bfd_elf_section_offset (output_bfd, info, input_section,
                                      rel->r_offset) != (bfd_vma) -1)
        {
-         (*_bfd_error_handler)
+         _bfd_error_handler
            (_("%B(%A+0x%lx): unresolvable %s relocation against symbol `%s'"),
             input_bfd,
             input_section,
@@ -5519,7 +5582,7 @@ check_relocation_error:
               (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
          else
            {
-             (*_bfd_error_handler)
+             _bfd_error_handler
                (_("%B(%A+0x%lx): reloc against `%s': error %d"),
                 input_bfd, input_section,
                 (long) rel->r_offset, name, (int) r);
@@ -5867,6 +5930,7 @@ elf_x86_64_finish_dynamic_symbol (bfd *output_bfd,
       && !local_undefweak)
     {
       Elf_Internal_Rela rela;
+      asection *relgot = htab->elf.srelgot;
 
       /* This symbol has an entry in the global offset table.  Set it
         up.  */
@@ -5885,7 +5949,27 @@ elf_x86_64_finish_dynamic_symbol (bfd *output_bfd,
       if (h->def_regular
          && h->type == STT_GNU_IFUNC)
        {
-         if (bfd_link_pic (info))
+         if (h->plt.offset == (bfd_vma) -1)
+           {
+             /* STT_GNU_IFUNC is referenced without PLT.  */
+             if (htab->elf.splt == NULL)
+               {
+                 /* use .rel[a].iplt section to store .got relocations
+                    in static executable.  */
+                 relgot = htab->elf.irelplt;
+               }
+             if (SYMBOL_REFERENCES_LOCAL (info, h))
+               {
+                 rela.r_info = htab->r_info (0,
+                                             R_X86_64_IRELATIVE);
+                 rela.r_addend = (h->root.u.def.value
+                                  + h->root.u.def.section->output_section->vma
+                                  + h->root.u.def.section->output_offset);
+               }
+             else
+               goto do_glob_dat;
+           }
+         else if (bfd_link_pic (info))
            {
              /* Generate R_X86_64_GLOB_DAT.  */
              goto do_glob_dat;
@@ -5929,7 +6013,7 @@ do_glob_dat:
          rela.r_addend = 0;
        }
 
-      elf_append_rela (output_bfd, htab->elf.srelgot, &rela);
+      elf_append_rela (output_bfd, relgot, &rela);
     }
 
   if (h->needs_copy)
@@ -6007,19 +6091,24 @@ elf_x86_64_reloc_type_class (const struct bfd_link_info *info,
       /* Check relocation against STT_GNU_IFUNC symbol if there are
          dynamic symbols.  */
       unsigned long r_symndx = htab->r_sym (rela->r_info);
-      Elf_Internal_Sym sym;
-      if (!bed->s->swap_symbol_in (abfd,
-                                  (htab->elf.dynsym->contents
-                                   + r_symndx * bed->s->sizeof_sym),
-                                  0, &sym))
-       abort ();
+      if (r_symndx != STN_UNDEF)
+       {
+         Elf_Internal_Sym sym;
+         if (!bed->s->swap_symbol_in (abfd,
+                                      (htab->elf.dynsym->contents
+                                       + r_symndx * bed->s->sizeof_sym),
+                                      0, &sym))
+           abort ();
 
-      if (ELF_ST_TYPE (sym.st_info) == STT_GNU_IFUNC)
-       return reloc_class_ifunc;
+         if (ELF_ST_TYPE (sym.st_info) == STT_GNU_IFUNC)
+           return reloc_class_ifunc;
+       }
     }
 
   switch ((int) ELF32_R_TYPE (rela->r_info))
     {
+    case R_X86_64_IRELATIVE:
+      return reloc_class_ifunc;
     case R_X86_64_RELATIVE:
     case R_X86_64_RELATIVE64:
       return reloc_class_relative;
@@ -6201,7 +6290,7 @@ elf_x86_64_finish_dynamic_sections (bfd *output_bfd,
     {
       if (bfd_is_abs_section (htab->elf.sgotplt->output_section))
        {
-         (*_bfd_error_handler)
+         _bfd_error_handler
            (_("discarded output section: `%A'"), htab->elf.sgotplt);
          return FALSE;
        }
@@ -6257,11 +6346,6 @@ elf_x86_64_finish_dynamic_sections (bfd *output_bfd,
     elf_section_data (htab->elf.sgot->output_section)->this_hdr.sh_entsize
       = GOT_ENTRY_SIZE;
 
-  /* Fill PLT and GOT entries for local STT_GNU_IFUNC symbols.  */
-  htab_traverse (htab->loc_hash_table,
-                elf_x86_64_finish_local_dynamic_symbol,
-                info);
-
   /* Fill PLT entries for undefined weak symbols in PIE.  */
   if (bfd_link_pie (info))
     bfd_hash_traverse (&info->hash->table,
@@ -6271,6 +6355,33 @@ elf_x86_64_finish_dynamic_sections (bfd *output_bfd,
   return TRUE;
 }
 
+/* Fill PLT/GOT entries and allocate dynamic relocations for local
+   STT_GNU_IFUNC symbols, which aren't in the ELF linker hash table.
+   It has to be done before elf_link_sort_relocs is called so that
+   dynamic relocations are properly sorted.  */
+
+static bfd_boolean
+elf_x86_64_output_arch_local_syms
+  (bfd *output_bfd ATTRIBUTE_UNUSED,
+   struct bfd_link_info *info,
+   void *flaginfo ATTRIBUTE_UNUSED,
+   int (*func) (void *, const char *,
+               Elf_Internal_Sym *,
+               asection *,
+               struct elf_link_hash_entry *) ATTRIBUTE_UNUSED)
+{
+  struct elf_x86_64_link_hash_table *htab = elf_x86_64_hash_table (info);
+  if (htab == NULL)
+    return FALSE;
+
+  /* Fill PLT and GOT entries for local STT_GNU_IFUNC symbols.  */
+  htab_traverse (htab->loc_hash_table,
+                elf_x86_64_finish_local_dynamic_symbol,
+                info);
+
+  return TRUE;
+}
+
 /* Return an array of PLT entry symbol values.  */
 
 static bfd_vma *
@@ -6633,6 +6744,7 @@ static const struct bfd_elf_special_section
 #define elf_backend_create_dynamic_sections elf_x86_64_create_dynamic_sections
 #define elf_backend_finish_dynamic_sections elf_x86_64_finish_dynamic_sections
 #define elf_backend_finish_dynamic_symbol   elf_x86_64_finish_dynamic_symbol
+#define elf_backend_output_arch_local_syms  elf_x86_64_output_arch_local_syms
 #define elf_backend_gc_mark_hook           elf_x86_64_gc_mark_hook
 #define elf_backend_grok_prstatus          elf_x86_64_grok_prstatus
 #define elf_backend_grok_psinfo                    elf_x86_64_grok_psinfo
This page took 0.032849 seconds and 4 git commands to generate.