[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