x86: Remove _bfd_{i386,x86_64}_elf_convert_load
authorH.J. Lu <hjl.tools@gmail.com>
Thu, 7 Sep 2017 11:03:15 +0000 (04:03 -0700)
committerH.J. Lu <hjl.tools@gmail.com>
Thu, 7 Sep 2017 11:03:30 +0000 (04:03 -0700)
Instead of converting GOT relocations when sizing dynamic sections, we
convert GOT relocations during relocation check.  Add a field, local_ref,
to elf_x86_link_hash_entry to indicate if symbol references are always
local with a new function to check if symbol references are always local,
which works in check_relocs.

* elf32-i386.c (elf_i386_convert_load_reloc): Add an argument,
r_type_p.  Remove the converted argument.  Replace
SYMBOL_REFERENCES_LOCAL with SYMBOL_REFERENCES_LOCAL_P.  Return
the new relocation type via r_type_p.
(elf_i386_relocate_section): Likewise.
(elf_i386_finish_dynamic_symbol): Likewise.
(need_convert_load): Removed.
(check_relocs_failed): Updated.
(elf_i386_check_relocs): Call elf_i386_convert_load_reloc,
instead of setting need_convert_load.
(_bfd_i386_elf_convert_load): Removed.
* elf64-x86-64.c (need_convert_load): Removed.
(check_relocs_failed): Updated.
(elf_x86_64_convert_load_reloc): Add an argument, r_type_p.
Replace SYMBOL_REFERENCES_LOCAL with SYMBOL_REFERENCES_LOCAL_P.
Return the new relocation type via r_type_p.
(elf_x86_64_check_relocs): Call elf_x86_64_convert_load_reloc,
instead of setting need_convert_load.
(elf_x86_64_check_relocs): Don't check PIC if relocation has
been converted.
(_bfd_x86_64_elf_convert_load): Removed.
(elf_x86_64_relocate_section): Replace SYMBOL_REFERENCES_LOCAL
with SYMBOL_REFERENCES_LOCAL_P.
(elf_x86_64_finish_dynamic_symbol): Likewise.
* elfxx-x86.c (_bfd_x86_elf_link_hash_table_create): Don't
set convert_load.
(_bfd_x86_elf_size_dynamic_sections): Don't call convert_load.
(_bfd_x86_elf_link_symbol_references_local): New function.
* elfxx-x86.h (SYMBOL_REFERENCES_LOCAL_P): New.
(UNDEFINED_WEAK_RESOLVED_TO_ZERO): Replace elf.forced_local with
SYMBOL_REFERENCES_LOCAL_P.
(elf_x86_link_hash_entry): Add local_ref.
(elf_x86_link_hash_table): Remove convert_load.
(_bfd_i386_elf_convert_load): Removed.
(_bfd_x86_64_elf_convert_load): Likewise.
(_bfd_x86_elf_link_symbol_references_local): New.

bfd/ChangeLog
bfd/elf32-i386.c
bfd/elf64-x86-64.c
bfd/elfxx-x86.c
bfd/elfxx-x86.h

index 96223833ef5f282afe1d26fbed2acc664ebcee96..a8db91a3fa43c81d2dafbfe6e76eb9ddb1eb2f51 100644 (file)
@@ -1,3 +1,42 @@
+2017-09-07  H.J. Lu  <hongjiu.lu@intel.com>
+
+       * elf32-i386.c (elf_i386_convert_load_reloc): Add an argument,
+       r_type_p.  Remove the converted argument.  Replace
+       SYMBOL_REFERENCES_LOCAL with SYMBOL_REFERENCES_LOCAL_P.  Return
+       the new relocation type via r_type_p.
+       (elf_i386_relocate_section): Likewise.
+       (elf_i386_finish_dynamic_symbol): Likewise.
+       (need_convert_load): Removed.
+       (check_relocs_failed): Updated.
+       (elf_i386_check_relocs): Call elf_i386_convert_load_reloc,
+       instead of setting need_convert_load.
+       (_bfd_i386_elf_convert_load): Removed.
+       * elf64-x86-64.c (need_convert_load): Removed.
+       (check_relocs_failed): Updated.
+       (elf_x86_64_convert_load_reloc): Add an argument, r_type_p.
+       Replace SYMBOL_REFERENCES_LOCAL with SYMBOL_REFERENCES_LOCAL_P.
+       Return the new relocation type via r_type_p.
+       (elf_x86_64_check_relocs): Call elf_x86_64_convert_load_reloc,
+       instead of setting need_convert_load.
+       (elf_x86_64_check_relocs): Don't check PIC if relocation has
+       been converted.
+       (_bfd_x86_64_elf_convert_load): Removed.
+       (elf_x86_64_relocate_section): Replace SYMBOL_REFERENCES_LOCAL
+       with SYMBOL_REFERENCES_LOCAL_P.
+       (elf_x86_64_finish_dynamic_symbol): Likewise.
+       * elfxx-x86.c (_bfd_x86_elf_link_hash_table_create): Don't
+       set convert_load.
+       (_bfd_x86_elf_size_dynamic_sections): Don't call convert_load.
+       (_bfd_x86_elf_link_symbol_references_local): New function.
+       * elfxx-x86.h (SYMBOL_REFERENCES_LOCAL_P): New.
+       (UNDEFINED_WEAK_RESOLVED_TO_ZERO): Replace elf.forced_local with
+       SYMBOL_REFERENCES_LOCAL_P.
+       (elf_x86_link_hash_entry): Add local_ref.
+       (elf_x86_link_hash_table): Remove convert_load.
+       (_bfd_i386_elf_convert_load): Removed.
+       (_bfd_x86_64_elf_convert_load): Likewise.
+       (_bfd_x86_elf_link_symbol_references_local): New.
+
 2017-09-06  H.J. Lu  <hongjiu.lu@intel.com>
 
        * elf64-x86-64.c (R_X86_64_converted_reloc_bit): New.
index 78a5dc4c68c1370c2c6935618668902cc2fc5c5e..cee5182c16c2f2fb463d64be9137bf6e5988d45c 100644 (file)
@@ -1211,9 +1211,9 @@ static
 bfd_boolean
 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,
-                            bfd_boolean *converted,
                             struct bfd_link_info *link_info)
 {
   struct elf_x86_link_hash_table *htab;
@@ -1241,7 +1241,7 @@ elf_i386_convert_load_reloc (bfd *abfd, Elf_Internal_Shdr *symtab_hdr,
   htab = elf_x86_hash_table (link_info, I386_ELF_DATA);
   is_pic = bfd_link_pic (link_info);
 
-  r_type = ELF32_R_TYPE (irel->r_info);
+  r_type = *r_type_p;
   r_symndx = ELF32_R_SYM (irel->r_info);
 
   modrm = bfd_get_8 (abfd, contents + roff - 1);
@@ -1316,7 +1316,7 @@ elf_i386_convert_load_reloc (bfd *abfd, Elf_Internal_Shdr *symtab_hdr,
       /* We have "call/jmp *foo@GOT[(%reg)]".  */
       if ((h->root.type == bfd_link_hash_defined
           || h->root.type == bfd_link_hash_defweak)
-         && SYMBOL_REFERENCES_LOCAL (link_info, h))
+         && SYMBOL_REFERENCES_LOCAL_P (link_info, h))
        {
          /* The function is locally defined.   */
 convert_branch:
@@ -1363,8 +1363,7 @@ convert_branch:
             need to adjust addend by -4.  */
          bfd_put_32 (abfd, -4, contents + irel->r_offset);
          irel->r_info = ELF32_R_INFO (r_symndx, R_386_PC32);
-
-         *converted = TRUE;
+         *r_type_p = R_386_PC32;
        }
     }
   else
@@ -1385,7 +1384,7 @@ convert_branch:
          || ((h->def_regular
               || h->root.type == bfd_link_hash_defined
               || h->root.type == bfd_link_hash_defweak)
-             && SYMBOL_REFERENCES_LOCAL (link_info, h)))
+             && SYMBOL_REFERENCES_LOCAL_P (link_info, h)))
        {
 convert_load:
          if (opcode == 0x8b)
@@ -1435,8 +1434,7 @@ convert_load:
 
          bfd_put_8 (abfd, opcode, contents + roff - 2);
          irel->r_info = ELF32_R_INFO (r_symndx, r_type);
-
-         *converted = TRUE;
+         *r_type_p = r_type;
        }
     }
 
@@ -1445,8 +1443,7 @@ convert_load:
 
 /* Rename some of the generic section flags to better document how they
    are used here.  */
-#define need_convert_load      sec_flg0
-#define check_relocs_failed    sec_flg1
+#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
@@ -1574,6 +1571,15 @@ elf_i386_check_relocs (bfd *abfd,
              |= elf_gnu_symbol_ifunc;
        }
 
+      if (r_type == R_386_GOT32X
+         && (h == NULL || h->type != STT_GNU_IFUNC))
+       {
+         Elf_Internal_Rela *irel = (Elf_Internal_Rela *) rel;
+         if (!elf_i386_convert_load_reloc (abfd, symtab_hdr, contents,
+                                           &r_type, irel, h, info))
+           goto error_return;
+       }
+
       if (! elf_i386_tls_transition (info, abfd, sec, contents,
                                     symtab_hdr, sym_hashes,
                                     &r_type, GOT_UNKNOWN,
@@ -1921,10 +1927,6 @@ do_size:
        default:
          break;
        }
-
-      if (r_type == R_386_GOT32X
-         && (h == NULL || h->type != STT_GNU_IFUNC))
-       sec->need_convert_load = 1;
     }
 
   if (elf_section_data (sec)->this_hdr.contents != contents)
@@ -1947,136 +1949,6 @@ error_return:
   return FALSE;
 }
 
-/* Convert load via the GOT slot to load immediate.  */
-
-bfd_boolean
-_bfd_i386_elf_convert_load (bfd *abfd, asection *sec,
-                           struct bfd_link_info *link_info)
-{
-  struct elf_x86_link_hash_table *htab;
-  Elf_Internal_Shdr *symtab_hdr;
-  Elf_Internal_Rela *internal_relocs;
-  Elf_Internal_Rela *irel, *irelend;
-  bfd_byte *contents;
-  bfd_boolean changed;
-  bfd_signed_vma *local_got_refcounts;
-
-  /* Don't even try to convert non-ELF outputs.  */
-  if (!is_elf_hash_table (link_info->hash))
-    return FALSE;
-
-  /* Nothing to do if there is no need or no output.  */
-  if ((sec->flags & (SEC_CODE | SEC_RELOC)) != (SEC_CODE | SEC_RELOC)
-      || sec->need_convert_load == 0
-      || bfd_is_abs_section (sec->output_section))
-    return TRUE;
-
-  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
-
-  /* Load the relocations for this section.  */
-  internal_relocs = (_bfd_elf_link_read_relocs
-                    (abfd, sec, NULL, (Elf_Internal_Rela *) NULL,
-                     link_info->keep_memory));
-  if (internal_relocs == NULL)
-    return FALSE;
-
-  changed = FALSE;
-  htab = elf_x86_hash_table (link_info, I386_ELF_DATA);
-  local_got_refcounts = elf_local_got_refcounts (abfd);
-
-  /* Get the section contents.  */
-  if (elf_section_data (sec)->this_hdr.contents != NULL)
-    contents = elf_section_data (sec)->this_hdr.contents;
-  else
-    {
-      if (!bfd_malloc_and_get_section (abfd, sec, &contents))
-       goto error_return;
-    }
-
-  irelend = internal_relocs + sec->reloc_count;
-  for (irel = internal_relocs; irel < irelend; irel++)
-    {
-      unsigned int r_type = ELF32_R_TYPE (irel->r_info);
-      unsigned int r_symndx;
-      struct elf_link_hash_entry *h;
-      bfd_boolean converted;
-
-      /* Don't convert R_386_GOT32 since we can't tell if it is applied
-        to "mov $foo@GOT, %reg" which isn't a load via GOT.  */
-      if (r_type != R_386_GOT32X)
-       continue;
-
-      r_symndx = ELF32_R_SYM (irel->r_info);
-      if (r_symndx < symtab_hdr->sh_info)
-       h = _bfd_elf_x86_get_local_sym_hash (htab, sec->owner,
-                                            (const Elf_Internal_Rela *) irel,
-                                            FALSE);
-      else
-       {
-         h = elf_sym_hashes (abfd)[r_symndx - symtab_hdr->sh_info];
-          while (h->root.type == bfd_link_hash_indirect
-                 || h->root.type == bfd_link_hash_warning)
-            h = (struct elf_link_hash_entry *) h->root.u.i.link;
-       }
-
-      /* STT_GNU_IFUNC must keep GOT32 relocations.  */
-      if (h != NULL && h->type == STT_GNU_IFUNC)
-       continue;
-
-      converted = FALSE;
-      if (!elf_i386_convert_load_reloc (abfd, symtab_hdr, contents,
-                                       irel, h, &converted, link_info))
-       goto error_return;
-
-      if (converted)
-       {
-         changed = converted;
-         if (h)
-           {
-             if (h->got.refcount > 0)
-               h->got.refcount -= 1;
-           }
-         else
-           {
-             if (local_got_refcounts != NULL
-                 && local_got_refcounts[r_symndx] > 0)
-               local_got_refcounts[r_symndx] -= 1;
-           }
-       }
-    }
-
-  if (contents != NULL
-      && elf_section_data (sec)->this_hdr.contents != contents)
-    {
-      if (!changed && !link_info->keep_memory)
-       free (contents);
-      else
-       {
-         /* Cache the section contents for elf_link_input_bfd.  */
-         elf_section_data (sec)->this_hdr.contents = contents;
-       }
-    }
-
-  if (elf_section_data (sec)->relocs != internal_relocs)
-    {
-      if (!changed)
-       free (internal_relocs);
-      else
-       elf_section_data (sec)->relocs = internal_relocs;
-    }
-
-  return TRUE;
-
- error_return:
-  if (contents != NULL
-      && elf_section_data (sec)->this_hdr.contents != contents)
-    free (contents);
-  if (internal_relocs != NULL
-      && elf_section_data (sec)->relocs != internal_relocs)
-    free (internal_relocs);
-  return FALSE;
-}
-
 /* Set the correct type for an x86 ELF section.  We do this by the
    section name, which is a hack, but ought to work.  */
 
@@ -2672,7 +2544,7 @@ r_386_got32:
                                                     bfd_link_pic (info),
                                                     h)
                  || (bfd_link_pic (info)
-                     && SYMBOL_REFERENCES_LOCAL (info, h))
+                     && SYMBOL_REFERENCES_LOCAL_P (info, h))
                  || (ELF_ST_VISIBILITY (h->other)
                      && h->root.type == bfd_link_hash_undefweak))
                {
@@ -2831,7 +2703,7 @@ disallow_got32:
                  bfd_set_error (bfd_error_bad_value);
                  return FALSE;
                }
-             else if (!SYMBOL_REFERENCES_LOCAL (info, h)
+             else if (!SYMBOL_REFERENCES_LOCAL_P (info, h)
                       && (h->type == STT_FUNC
                           || h->type == STT_OBJECT)
                       && ELF_ST_VISIBILITY (h->other) == STV_PROTECTED)
@@ -4045,7 +3917,7 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd,
                     in static executable.  */
                  relgot = htab->elf.irelplt;
                }
-             if (SYMBOL_REFERENCES_LOCAL (info, h))
+             if (SYMBOL_REFERENCES_LOCAL_P (info, h))
                {
                  info->callbacks->minfo (_("Local IFUNC function `%s' in %B\n"),
                                          h->root.root.string,
@@ -4095,7 +3967,7 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd,
            }
        }
       else if (bfd_link_pic (info)
-              && SYMBOL_REFERENCES_LOCAL (info, h))
+              && SYMBOL_REFERENCES_LOCAL_P (info, h))
        {
          BFD_ASSERT((h->got.offset & 1) != 0);
          rel.r_info = ELF32_R_INFO (0, R_386_RELATIVE);
index 8f1ac1a3587fcaa77a7582982dca2e8db0d08ab1..a2a4be84d67e1ce9b4fbf1c39c5eac0349adcf68 100644 (file)
@@ -1362,8 +1362,7 @@ elf_x86_64_tls_transition (struct bfd_link_info *info, bfd *abfd,
 
 /* Rename some of the generic section flags to better document how they
    are used here.  */
-#define need_convert_load      sec_flg0
-#define check_relocs_failed    sec_flg1
+#define check_relocs_failed    sec_flg0
 
 static bfd_boolean
 elf_x86_64_need_pic (struct bfd_link_info *info,
@@ -1450,6 +1449,7 @@ elf_x86_64_need_pic (struct bfd_link_info *info,
 static bfd_boolean
 elf_x86_64_convert_load_reloc (bfd *abfd,
                               bfd_byte *contents,
+                              unsigned int *r_type_p,
                               Elf_Internal_Rela *irel,
                               struct elf_link_hash_entry *h,
                               bfd_boolean *converted,
@@ -1464,7 +1464,7 @@ elf_x86_64_convert_load_reloc (bfd *abfd,
   bfd_signed_vma raddend;
   unsigned int opcode;
   unsigned int modrm;
-  unsigned int r_type = ELF32_R_TYPE (irel->r_info);
+  unsigned int r_type = *r_type_p;
   unsigned int r_symndx;
   bfd_vma roff = irel->r_offset;
 
@@ -1572,7 +1572,7 @@ elf_x86_64_convert_load_reloc (bfd *abfd,
                    || h->root.type == bfd_link_hash_defined
                    || h->root.type == bfd_link_hash_defweak)
                   && h != htab->elf.hdynamic
-                  && SYMBOL_REFERENCES_LOCAL (link_info, h)))
+                  && SYMBOL_REFERENCES_LOCAL_P (link_info, h)))
        {
          /* bfd_link_hash_new or bfd_link_hash_undefined is
             set by an assignment in a linker script in
@@ -1749,6 +1749,7 @@ rewrite_modrm_rex:
       bfd_put_8 (abfd, opcode, contents + roff - 2);
     }
 
+  *r_type_p = r_type;
   irel->r_info = htab->r_info (r_symndx,
                               r_type | R_X86_64_converted_reloc_bit);
 
@@ -1819,6 +1820,7 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
       Elf_Internal_Sym *isym;
       const char *name;
       bfd_boolean size_reloc;
+      bfd_boolean converted_reloc;
 
       r_symndx = htab->r_sym (rel->r_info);
       r_type = ELF32_R_TYPE (rel->r_info);
@@ -1912,6 +1914,19 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
              |= elf_gnu_symbol_ifunc;
        }
 
+      converted_reloc = FALSE;
+      if ((r_type == R_X86_64_GOTPCREL
+          || r_type == R_X86_64_GOTPCRELX
+          || r_type == R_X86_64_REX_GOTPCRELX)
+         && (h == NULL || h->type != STT_GNU_IFUNC))
+       {
+         Elf_Internal_Rela *irel = (Elf_Internal_Rela *) rel;
+         if (!elf_x86_64_convert_load_reloc (abfd, contents, &r_type,
+                                             irel, h, &converted_reloc,
+                                             info))
+           goto error_return;
+       }
+
       if (! elf_x86_64_tls_transition (info, abfd, sec, contents,
                                       symtab_hdr, sym_hashes,
                                       &r_type, GOT_UNKNOWN,
@@ -2087,6 +2102,7 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
             sections we don't care about, such as debug sections or
             when relocation overflow check is disabled.  */
          if (!info->no_reloc_overflow_check
+             && !converted_reloc
              && (bfd_link_pic (info)
                  || (bfd_link_executable (info)
                      && h != NULL
@@ -2280,12 +2296,6 @@ do_size:
        default:
          break;
        }
-
-      if ((r_type == R_X86_64_GOTPCREL
-          || r_type == R_X86_64_GOTPCRELX
-          || r_type == R_X86_64_REX_GOTPCRELX)
-         && (h == NULL || h->type != STT_GNU_IFUNC))
-       sec->need_convert_load = 1;
     }
 
   if (elf_section_data (sec)->this_hdr.contents != contents)
@@ -2308,136 +2318,6 @@ error_return:
   return FALSE;
 }
 
-/* Convert load via the GOT slot to load immediate.  */
-
-bfd_boolean
-_bfd_x86_64_elf_convert_load (bfd *abfd, asection *sec,
-                             struct bfd_link_info *link_info)
-{
-  Elf_Internal_Shdr *symtab_hdr;
-  Elf_Internal_Rela *internal_relocs;
-  Elf_Internal_Rela *irel, *irelend;
-  bfd_byte *contents;
-  struct elf_x86_link_hash_table *htab;
-  bfd_boolean changed;
-  bfd_signed_vma *local_got_refcounts;
-
-  /* Don't even try to convert non-ELF outputs.  */
-  if (!is_elf_hash_table (link_info->hash))
-    return FALSE;
-
-  /* Nothing to do if there is no need or no output.  */
-  if ((sec->flags & (SEC_CODE | SEC_RELOC)) != (SEC_CODE | SEC_RELOC)
-      || sec->need_convert_load == 0
-      || bfd_is_abs_section (sec->output_section))
-    return TRUE;
-
-  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
-
-  /* Load the relocations for this section.  */
-  internal_relocs = (_bfd_elf_link_read_relocs
-                    (abfd, sec, NULL, (Elf_Internal_Rela *) NULL,
-                     link_info->keep_memory));
-  if (internal_relocs == NULL)
-    return FALSE;
-
-  changed = FALSE;
-  htab = elf_x86_hash_table (link_info, X86_64_ELF_DATA);
-  local_got_refcounts = elf_local_got_refcounts (abfd);
-
-  /* Get the section contents.  */
-  if (elf_section_data (sec)->this_hdr.contents != NULL)
-    contents = elf_section_data (sec)->this_hdr.contents;
-  else
-    {
-      if (!bfd_malloc_and_get_section (abfd, sec, &contents))
-       goto error_return;
-    }
-
-  irelend = internal_relocs + sec->reloc_count;
-  for (irel = internal_relocs; irel < irelend; irel++)
-    {
-      unsigned int r_type = ELF32_R_TYPE (irel->r_info);
-      unsigned int r_symndx;
-      struct elf_link_hash_entry *h;
-      bfd_boolean converted;
-
-      if (r_type != R_X86_64_GOTPCRELX
-         && r_type != R_X86_64_REX_GOTPCRELX
-         && r_type != R_X86_64_GOTPCREL)
-       continue;
-
-      r_symndx = htab->r_sym (irel->r_info);
-      if (r_symndx < symtab_hdr->sh_info)
-       h = _bfd_elf_x86_get_local_sym_hash (htab, sec->owner,
-                                            (const Elf_Internal_Rela *) irel,
-                                            FALSE);
-      else
-       {
-         h = elf_sym_hashes (abfd)[r_symndx - symtab_hdr->sh_info];
-         while (h->root.type == bfd_link_hash_indirect
-                || h->root.type == bfd_link_hash_warning)
-           h = (struct elf_link_hash_entry *) h->root.u.i.link;
-       }
-
-      /* STT_GNU_IFUNC must keep GOTPCREL relocations.  */
-      if (h != NULL && h->type == STT_GNU_IFUNC)
-       continue;
-
-      converted = FALSE;
-      if (!elf_x86_64_convert_load_reloc (abfd, contents, irel, h,
-                                         &converted, link_info))
-       goto error_return;
-
-      if (converted)
-       {
-         changed = converted;
-         if (h)
-           {
-             if (h->got.refcount > 0)
-               h->got.refcount -= 1;
-           }
-         else
-           {
-             if (local_got_refcounts != NULL
-                 && local_got_refcounts[r_symndx] > 0)
-               local_got_refcounts[r_symndx] -= 1;
-           }
-       }
-    }
-
-  if (contents != NULL
-      && elf_section_data (sec)->this_hdr.contents != contents)
-    {
-      if (!changed && !link_info->keep_memory)
-       free (contents);
-      else
-       {
-         /* Cache the section contents for elf_link_input_bfd.  */
-         elf_section_data (sec)->this_hdr.contents = contents;
-       }
-    }
-
-  if (elf_section_data (sec)->relocs != internal_relocs)
-    {
-      if (!changed)
-       free (internal_relocs);
-      else
-       elf_section_data (sec)->relocs = internal_relocs;
-    }
-
-  return TRUE;
-
- error_return:
-  if (contents != NULL
-      && elf_section_data (sec)->this_hdr.contents != contents)
-    free (contents);
-  if (internal_relocs != NULL
-      && elf_section_data (sec)->relocs != internal_relocs)
-    free (internal_relocs);
-  return FALSE;
-}
-
 /* Return the relocation value for @tpoff relocation
    if STT_TLS virtual address is ADDRESS.  */
 
@@ -2929,7 +2809,7 @@ do_ifunc_pointer:
 
              if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, bfd_link_pic (info), h)
                  || (bfd_link_pic (info)
-                     && SYMBOL_REFERENCES_LOCAL (info, h))
+                     && SYMBOL_REFERENCES_LOCAL_P (info, h))
                  || (ELF_ST_VISIBILITY (h->other)
                      && h->root.type == bfd_link_hash_undefweak))
                {
@@ -3064,7 +2944,7 @@ do_ifunc_pointer:
                  return FALSE;
                }
              else if (!bfd_link_executable (info)
-                      && !SYMBOL_REFERENCES_LOCAL (info, h)
+                      && !SYMBOL_REFERENCES_LOCAL_P (info, h)
                       && (h->type == STT_FUNC
                           || h->type == STT_OBJECT)
                       && ELF_ST_VISIBILITY (h->other) == STV_PROTECTED)
@@ -3212,7 +3092,7 @@ do_ifunc_pointer:
                    || r_type == R_X86_64_PC32_BND)
                   && is_32bit_relative_branch (contents, rel->r_offset));
 
-             if (SYMBOL_REFERENCES_LOCAL (info, h))
+             if (SYMBOL_REFERENCES_LOCAL_P (info, h))
                {
                  /* Symbol is referenced locally.  Make sure it is
                     defined locally or for a branch.  */
@@ -4379,7 +4259,7 @@ elf_x86_64_finish_dynamic_symbol (bfd *output_bfd,
                     in static executable.  */
                  relgot = htab->elf.irelplt;
                }
-             if (SYMBOL_REFERENCES_LOCAL (info, h))
+             if (SYMBOL_REFERENCES_LOCAL_P (info, h))
                {
                  info->callbacks->minfo (_("Local IFUNC function `%s' in %B\n"),
                                          output_bfd,
@@ -4429,7 +4309,7 @@ elf_x86_64_finish_dynamic_symbol (bfd *output_bfd,
            }
        }
       else if (bfd_link_pic (info)
-              && SYMBOL_REFERENCES_LOCAL (info, h))
+              && SYMBOL_REFERENCES_LOCAL_P (info, h))
        {
          if (!(h->def_regular || ELF_COMMON_DEF_P (h)))
            return FALSE;
index a7e9eda47f06b0ab822b1706480d9289b2bd3bab..4f6b09e1d0a7f80b21df1c0af27ad1f09daf23e6 100644 (file)
@@ -766,7 +766,6 @@ _bfd_x86_elf_link_hash_table_create (bfd *abfd)
   /* NB: If BFD64 isn't defined, only i386 will be supported.  */
   if (bed->target_id == X86_64_ELF_DATA)
     {
-      ret->convert_load = _bfd_x86_64_elf_convert_load;
       ret->is_reloc_section = elf_x86_64_is_reloc_section;
       ret->dt_reloc = DT_RELA;
       ret->dt_reloc_sz = DT_RELASZ;
@@ -798,7 +797,6 @@ _bfd_x86_elf_link_hash_table_create (bfd *abfd)
        }
       else
        {
-         ret->convert_load = _bfd_i386_elf_convert_load;
          ret->is_reloc_section = elf_i386_is_reloc_section;
          ret->dt_reloc = DT_REL;
          ret->dt_reloc_sz = DT_RELSZ;
@@ -909,9 +907,6 @@ _bfd_x86_elf_size_dynamic_sections (bfd *output_bfd,
        {
          struct elf_dyn_relocs *p;
 
-         if (!htab->convert_load (ibfd, s, info))
-           return FALSE;
-
          for (p = ((struct elf_dyn_relocs *)
                     elf_section_data (s)->local_dynrel);
               p != NULL;
@@ -1677,6 +1672,45 @@ _bfd_x86_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
   return _bfd_elf_adjust_dynamic_copy (info, h, s);
 }
 
+/* Return TRUE if a symbol is referenced locally.  It is similar to
+   SYMBOL_REFERENCES_LOCAL, but it also checks version script.  It
+   works in check_relocs.  */
+
+bfd_boolean
+_bfd_x86_elf_link_symbol_references_local (struct bfd_link_info *info,
+                                          struct elf_link_hash_entry *h)
+{
+  struct elf_x86_link_hash_entry *eh
+    = (struct elf_x86_link_hash_entry *) h;
+
+  if (eh->local_ref > 1)
+    return TRUE;
+
+  if (eh->local_ref == 1)
+    return FALSE;
+
+  /* Unversioned symbols defined in regular objects can be forced local
+     by linker version script.  A weak undefined symbol can fored local
+     if it has non-default visibility or "-z nodynamic-undefined-weak"
+     is used.  */
+  if (SYMBOL_REFERENCES_LOCAL (info, h)
+      || ((ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
+          || info->dynamic_undefined_weak == 0)
+         && h->root.type == bfd_link_hash_undefweak)
+      || ((h->def_regular || ELF_COMMON_DEF_P (h))
+         && h->versioned == unversioned
+         && info->version_info != NULL
+         && bfd_hide_sym_by_version (info->version_info,
+                                     h->root.root.string)))
+    {
+      eh->local_ref = 2;
+      return TRUE;
+    }
+
+  eh->local_ref = 1;
+  return FALSE;
+}
+
 /* Return the section that should be marked against GC for a given
    relocation. */
 
index 9c0dcbbe8792baa7d244d5c0a4c01ec252bbba6c..5d0a28a3eb2dd9987a4de3ecb727671e09cbcf65 100644 (file)
    && elf_hash_table_id ((struct elf_link_hash_table *) ((p)->hash)) == (id) \
     ? ((struct elf_x86_link_hash_table *) ((p)->hash)) : NULL)
 
+/* Will references to this symbol always be local in this object?  */
+#define SYMBOL_REFERENCES_LOCAL_P(INFO, H) \
+  _bfd_x86_elf_link_symbol_references_local ((INFO), (H))
+
 /* Is a undefined weak symbol which is resolved to 0.  Reference to an
    undefined weak symbol is resolved to 0 when building executable if
    it isn't dynamic and
@@ -54,7 +58,7 @@
  */
 #define UNDEFINED_WEAK_RESOLVED_TO_ZERO(INFO, ID, GOT_RELOC, EH) \
   ((EH)->elf.root.type == bfd_link_hash_undefweak               \
-   && ((EH)->elf.forced_local                                   \
+   && (SYMBOL_REFERENCES_LOCAL_P ((INFO), &(EH)->elf)           \
        || (bfd_link_executable (INFO)                           \
           && (elf_x86_hash_table ((INFO), (ID))->interp == NULL \
               || !(GOT_RELOC)                                   \
@@ -98,6 +102,12 @@ struct elf_x86_link_hash_entry
   /* TRUE if symbol is defined as a protected symbol.  */
   unsigned int def_protected : 1;
 
+  /* 0: Symbol references are unknown.
+     1: Symbol references aren't local.
+     2: Symbol references are local.
+   */
+  unsigned int local_ref : 2;
+
   /* Symbol is referenced by R_386_GOTOFF relocation.  This is only used
      by i386.  */
   unsigned int gotoff_ref : 1;
@@ -320,8 +330,6 @@ struct elf_x86_link_hash_table
 
   bfd_vma (*r_info) (bfd_vma, bfd_vma);
   bfd_vma (*r_sym) (bfd_vma);
-  bfd_boolean (*convert_load) (bfd *, asection *,
-                              struct bfd_link_info *);
   bfd_boolean (*is_reloc_section) (const char *);
   enum elf_target_id target_id;
   unsigned int sizeof_reloc;
@@ -405,12 +413,6 @@ struct elf_x86_plt
    && elf_tdata (bfd) != NULL                          \
    && elf_object_id (bfd) == (htab)->target_id)
 
-extern bfd_boolean _bfd_i386_elf_convert_load
-  (bfd *, asection *, struct bfd_link_info *);
-
-extern bfd_boolean _bfd_x86_64_elf_convert_load
-  (bfd *, asection *, struct bfd_link_info *);
-
 extern bfd_boolean _bfd_x86_elf_mkobject
   (bfd *);
 
@@ -468,6 +470,9 @@ extern bfd_boolean _bfd_x86_elf_hash_symbol
 extern bfd_boolean _bfd_x86_elf_adjust_dynamic_symbol
   (struct bfd_link_info *, struct elf_link_hash_entry *);
 
+extern bfd_boolean _bfd_x86_elf_link_symbol_references_local
+  (struct bfd_link_info *, struct elf_link_hash_entry *);
+
 extern asection * _bfd_x86_elf_gc_mark_hook
   (asection *, struct bfd_link_info *, Elf_Internal_Rela *,
    struct elf_link_hash_entry *, Elf_Internal_Sym *);