PATCH: Make STT_GNU_IFUNC symbol dynamic
H.J. Lu
hongjiu.lu@intel.com
Sat May 23 03:44:00 GMT 2009
Hi,
Even if a STT_GNU_IFUNC symbol is hidden, we have to make it dynamic.
Otherwise, it won't work correctly when it is called within the shared
library.
H.J.
---
2009-05-22 H.J. Lu <hongjiu.lu@intel.com>
* elflink.c (bfd_elf_link_record_dynamic_symbol): Make
STT_GNU_IFUNC symbol dynamic.
(_bfd_elf_fix_symbol_flags): Don't hide STT_GNU_IFUNC symbol.
(elf_link_add_object_symbols): Likewise.
(_bfd_elf_symbol_refs_local_p): Return FALSE on STT_GNU_IFUNC
symbol.
Index: bfd/elflink.c
===================================================================
--- bfd/elflink.c (revision 5928)
+++ bfd/elflink.c (working copy)
@@ -417,7 +417,9 @@ bfd_elf_link_record_dynamic_symbol (stru
&& h->root.type != bfd_link_hash_undefweak)
{
h->forced_local = 1;
- if (!elf_hash_table (info)->is_relocatable_executable)
+ /* STT_GNU_IFUNC symbol must go through PLT. */
+ if (ELF_ST_TYPE (h->type) != STT_GNU_IFUNC
+ && !elf_hash_table (info)->is_relocatable_executable)
return TRUE;
}
@@ -2507,10 +2509,11 @@ _bfd_elf_fix_symbol_flags (struct elf_li
symbol was defined in a regular object, then it actually doesn't
need a PLT entry. Likewise, if the symbol has non-default
visibility. If the symbol has hidden or internal visibility, we
- will force it local. */
+ will force it local. STT_GNU_IFUNC symbol must go through PLT. */
if (h->needs_plt
&& eif->info->shared
&& is_elf_hash_table (eif->info->hash)
+ && ELF_ST_TYPE (h->type) != STT_GNU_IFUNC
&& (SYMBOLIC_BIND (eif->info, h)
|| ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
&& h->def_regular)
@@ -2845,6 +2848,10 @@ _bfd_elf_symbol_refs_local_p (struct elf
if (h == NULL)
return TRUE;
+ /* STT_GNU_IFUNC symbol must go through PLT. */
+ if (h->type == STT_GNU_IFUNC)
+ return FALSE;
+
/* STV_HIDDEN or STV_INTERNAL ones must be local. */
if (ELF_ST_VISIBILITY (h->other) == STV_HIDDEN
|| ELF_ST_VISIBILITY (h->other) == STV_INTERNAL)
@@ -4395,8 +4402,12 @@ elf_link_add_object_symbols (bfd *abfd,
{
case STV_INTERNAL:
case STV_HIDDEN:
- (*bed->elf_backend_hide_symbol) (info, h, TRUE);
- dynsym = FALSE;
+ /* STT_GNU_IFUNC symbol must go through PLT. */
+ if (ELF_ST_TYPE (h->type) != STT_GNU_IFUNC)
+ {
+ (*bed->elf_backend_hide_symbol) (info, h, TRUE);
+ dynsym = FALSE;
+ }
break;
}
More information about the Libc-alpha
mailing list