[GOLD] PATCH: PR gold/10893: gold doesn't support IFUNC

H.J. Lu hjl.tools@gmail.com
Mon Dec 7 17:20:00 GMT 2009


On Fri, Dec 4, 2009 at 9:46 PM, Ian Lance Taylor <iant@google.com> wrote:
> "H.J. Lu" <hongjiu.lu@intel.com> writes:
>
>> elfcpp/
>>
>> 2009-12-03  H.J. Lu  <hongjiu.lu@intel.com>
>>
>>       PR gold/10893
>>       * elfcpp.h (Sym): Add is_func,
>>
>> gold/
>>
>> 2009-12-03  H.J. Lu  <hongjiu.lu@intel.com>
>>
>>       PR gold/10893
>>       * i386.cc (Target_i386::Scan::globa): Use is_func instead
>>       of checking elfcpp::STT_FUNC.
>>       (Target_i386::Relocate::relocate): Likewise.
>>       * reloc.cc (Sized_relobj<size, big_endian>::split_stack_adjust_reltype): Likewise.
>>       (Sized_relobj<size, big_endian>::find_functions): Likewise.
>>       * x86_64.cc (Target_x86_64::Scan::global): Likewise.
>>
>>       * symtab.cc (Symbol_table::sized_write_symbol): Turn IFUNC
>>       symbols from shared libraries into normal FUNC symbols.
>>
>>       * symtab.h (Symbol): Add is_func an use it.
>
>
>> --- a/elfcpp/elfcpp.h
>> +++ b/elfcpp/elfcpp.h
>> @@ -1292,6 +1292,11 @@ class Sym
>>    get_st_shndx() const
>>    { return Convert<16, big_endian>::convert_host(this->p_->st_shndx); }
>>
>> +  bool
>> +  is_func() const
>> +  { return (this->get_st_type() == STT_FUNC
>> +         || this->get_st_type() == STT_GNU_IFUNC); }
>> +
>>   private:
>>    const internal::Sym_data<size>* p_;
>>  };
>
> I don't think you need this one.  In any case, it shouldn't be there,
> and please don't add it.  If you explain why you need it, we can
> figure out where to handle it.
>
>
>> --- a/gold/i386.cc
>> +++ b/gold/i386.cc
>
> You didn't fix anything in arm.cc, powerpc.cc, or sparc.cc.  Why not?
> Is it because STT_GNU_IFUNC does not work for those targets?

STT_GNU_IFUNC works on i386 and x86-64 in Fedora 12. It may
work on PPC. But I can't test it.

My patch only allows gold to work with IFUNC symbols defined
in shared libraries.

>
>> @@ -1233,7 +1233,7 @@ Sized_relobj<size, big_endian>::find_functions(
>>
>>        // FIXME: Some targets can have functions which do not have type
>>        // STT_FUNC, e.g., STT_ARM_TFUNC.
>> -      if (isym.get_st_type() != elfcpp::STT_FUNC
>> +      if (!isym.is_func()
>>         || isym.get_st_size() == 0)
>>       continue;
>
> Ah, here is where you are using the elfcpp method.  You should write
> this as
>    if ((isym.get_st_type() != elfcpp::STT_FUNC
>         && isym.get_st_type() != elfcpp::STT_GNU_IFUNC)
>        || isym.get_st_size() == 0)
>
>> --- a/gold/symtab.h
>> +++ b/gold/symtab.h
>> @@ -205,6 +205,12 @@ class Symbol
>>    type() const
>>    { return this->type_; }
>>
>> +  // Return true for function symbol.
>> +  bool
>> +  is_func() const
>> +  { return (this->type_ == elfcpp::STT_FUNC
>> +         || this->type_ == elfcpp::STT_GNU_IFUNC); }
>> +
>
> Format this as:
>
>  bool
>  is_func() const
>  {
>    return (this->type_ == elfcpp::STT_FUNC
>            || this->type_ == elfcpp::STT_GNU_IFUNC);
>  }
>
>
> This patch is OK with those change if it still works.
>

This is the patch I checked in.

Thanks.

-- 
H.J.
---
2009-12-07  H.J. Lu  <hongjiu.lu@intel.com>

	PR gold/10893
	* i386.cc (Target_i386::Scan::globa): Use is_func instead of
	checking elfcpp::STT_FUNC.
	(Target_i386::Relocate::relocate): Likewise.
	* x86_64.cc (Target_x86_64::Scan::global): Likewise.

	* symtab.cc (Symbol_table::sized_write_symbol): Turn IFUNC
	symbols from shared libraries into normal FUNC symbols.

	* symtab.h (Symbol): Add is_func and use it.
-------------- next part --------------
2009-12-07  H.J. Lu  <hongjiu.lu@intel.com>

	PR gold/10893
	* i386.cc (Target_i386::Scan::globa): Use is_func instead
	of checking elfcpp::STT_FUNC.
	(Target_i386::Relocate::relocate): Likewise.
	* x86_64.cc (Target_x86_64::Scan::global): Likewise.

	* symtab.cc (Symbol_table::sized_write_symbol): Turn IFUNC
	symbols from shared libraries into normal FUNC symbols.

	* symtab.h (Symbol): Add is_func an use it.

diff --git a/elfcpp/elfcpp.h b/elfcpp/elfcpp.h
index 0b2c871..e4b8a7c 100644
--- a/elfcpp/elfcpp.h
+++ b/elfcpp/elfcpp.h
@@ -1292,6 +1292,11 @@ class Sym
   get_st_shndx() const
   { return Convert<16, big_endian>::convert_host(this->p_->st_shndx); }
 
+  bool
+  is_func() const
+  { return (this->get_st_type() == STT_FUNC
+	    || this->get_st_type() == STT_GNU_IFUNC); }
+
  private:
   const internal::Sym_data<size>* p_;
 };
diff --git a/gold/i386.cc b/gold/i386.cc
index 3e0ddcb..ad04e21 100644
--- a/gold/i386.cc
+++ b/gold/i386.cc
@@ -1246,7 +1246,7 @@ Target_i386::Scan::global(Symbol_table* symtab,
           }
         // Make a dynamic relocation if necessary.
         int flags = Symbol::NON_PIC_REF;
-        if (gsym->type() == elfcpp::STT_FUNC)
+        if (gsym->is_func())
           flags |= Symbol::FUNCTION_CALL;
         if (gsym->needs_dynamic_reloc(flags))
           {
@@ -1722,7 +1722,7 @@ Target_i386::Relocate::relocate(const Relocate_info<32, false>* relinfo,
     case elfcpp::R_386_PC32:
       {
         int ref_flags = Symbol::NON_PIC_REF;
-        if (gsym != NULL && gsym->type() == elfcpp::STT_FUNC)
+        if (gsym != NULL && gsym->is_func())
           ref_flags |= Symbol::FUNCTION_CALL;
         if (should_apply_static_reloc(gsym, ref_flags, true, output_section))
           Relocate_functions<32, false>::pcrel32(view, object, psymval, address);
@@ -1738,7 +1738,7 @@ Target_i386::Relocate::relocate(const Relocate_info<32, false>* relinfo,
     case elfcpp::R_386_PC16:
       {
         int ref_flags = Symbol::NON_PIC_REF;
-        if (gsym != NULL && gsym->type() == elfcpp::STT_FUNC)
+        if (gsym != NULL && gsym->is_func())
           ref_flags |= Symbol::FUNCTION_CALL;
         if (should_apply_static_reloc(gsym, ref_flags, false, output_section))
           Relocate_functions<32, false>::pcrel16(view, object, psymval, address);
@@ -1754,7 +1754,7 @@ Target_i386::Relocate::relocate(const Relocate_info<32, false>* relinfo,
     case elfcpp::R_386_PC8:
       {
         int ref_flags = Symbol::NON_PIC_REF;
-        if (gsym != NULL && gsym->type() == elfcpp::STT_FUNC)
+        if (gsym != NULL && gsym->is_func())
           ref_flags |= Symbol::FUNCTION_CALL;
         if (should_apply_static_reloc(gsym, ref_flags, false,
 				      output_section))
diff --git a/gold/reloc.cc b/gold/reloc.cc
index 858778e..f863b77 100644
--- a/gold/reloc.cc
+++ b/gold/reloc.cc
@@ -1092,7 +1092,7 @@ Sized_relobj<size, big_endian>::split_stack_adjust_reltype(
       // cases we will ask for a large stack unnecessarily, but this
       // is not fatal.  FIXME: Some targets have symbols which are
       // functions but are not type STT_FUNC, e.g., STT_ARM_TFUNC.
-      if (gsym->type() == elfcpp::STT_FUNC
+      if (gsym->is_func()
 	  && !gsym->is_undefined()
 	  && gsym->source() == Symbol::FROM_OBJECT
 	  && !gsym->object()->uses_split_stack())
@@ -1233,7 +1233,7 @@ Sized_relobj<size, big_endian>::find_functions(
 
       // FIXME: Some targets can have functions which do not have type
       // STT_FUNC, e.g., STT_ARM_TFUNC.
-      if (isym.get_st_type() != elfcpp::STT_FUNC
+      if (!isym.is_func()
 	  || isym.get_st_size() == 0)
 	continue;
 
diff --git a/gold/symtab.cc b/gold/symtab.cc
index dd52145..9a374f1 100644
--- a/gold/symtab.cc
+++ b/gold/symtab.cc
@@ -2809,11 +2809,16 @@ Symbol_table::sized_write_symbol(
     osym.put_st_size(0);
   else
     osym.put_st_size(sym->symsize());
+  elfcpp::STT type = sym->type();
+  // Turn IFUNC symbols from shared libraries into normal FUNC symbols.
+  if (type == elfcpp::STT_GNU_IFUNC
+      && sym->is_from_dynobj())
+    type = elfcpp::STT_FUNC;
   // A version script may have overridden the default binding.
   if (sym->is_forced_local())
-    osym.put_st_info(elfcpp::elf_st_info(elfcpp::STB_LOCAL, sym->type()));
+    osym.put_st_info(elfcpp::elf_st_info(elfcpp::STB_LOCAL, type));
   else
-    osym.put_st_info(elfcpp::elf_st_info(sym->binding(), sym->type()));
+    osym.put_st_info(elfcpp::elf_st_info(sym->binding(), type));
   osym.put_st_other(elfcpp::elf_st_other(sym->visibility(), sym->nonvis()));
   osym.put_st_shndx(shndx);
 }
diff --git a/gold/symtab.h b/gold/symtab.h
index 544712d..f3ea4bc 100644
--- a/gold/symtab.h
+++ b/gold/symtab.h
@@ -205,6 +205,12 @@ class Symbol
   type() const
   { return this->type_; }
 
+  // Return true for function symbol.
+  bool
+  is_func() const
+  { return (this->type_ == elfcpp::STT_FUNC
+	    || this->type_ == elfcpp::STT_GNU_IFUNC); }
+
   // Return the symbol visibility.
   elfcpp::STV
   visibility() const
@@ -543,7 +549,7 @@ class Symbol
 
     return (!parameters->doing_static_link()
 	    && !parameters->options().pie()
-            && this->type() == elfcpp::STT_FUNC
+            && this->is_func()
             && (this->is_from_dynobj()
                 || this->is_undefined()
                 || this->is_preemptible()));
@@ -734,7 +740,7 @@ class Symbol
     return (!parameters->options().shared()
 	    && parameters->options().copyreloc()
 	    && this->is_from_dynobj()
-	    && this->type() != elfcpp::STT_FUNC);
+	    && !this->is_func());
   }
 
  protected:
diff --git a/gold/x86_64.cc b/gold/x86_64.cc
index 5526f6f..8470ede 100644
--- a/gold/x86_64.cc
+++ b/gold/x86_64.cc
@@ -1350,7 +1350,7 @@ Target_x86_64::Scan::global(Symbol_table* symtab,
           target->make_plt_entry(symtab, layout, gsym);
         // Make a dynamic relocation if necessary.
         int flags = Symbol::NON_PIC_REF;
-        if (gsym->type() == elfcpp::STT_FUNC)
+        if (gsym->is_func())
           flags |= Symbol::FUNCTION_CALL;
         if (gsym->needs_dynamic_reloc(flags))
           {


More information about the Binutils mailing list