PR gold/12980
* i386.cc (Target_i386::Scan::global): For a GOT reloc, use a GLOB_DAT relocation rather than a RELATIVE relocation for a protected symbol when creating a shared library. * x86_64.cc (Target_x86_64::Scan::global): Likewise. * testsuite/protected_1.cc (f2, get_f2_addr): New functions. * testsuite/protected_main_1.cc (main): Test that protected function has same address.
This commit is contained in:
parent
a7035dbbd1
commit
07aa62f267
@ -1,3 +1,14 @@
|
||||
2011-07-12 Ian Lance Taylor <iant@google.com>
|
||||
|
||||
PR gold/12980
|
||||
* i386.cc (Target_i386::Scan::global): For a GOT reloc, use a
|
||||
GLOB_DAT relocation rather than a RELATIVE relocation for a
|
||||
protected symbol when creating a shared library.
|
||||
* x86_64.cc (Target_x86_64::Scan::global): Likewise.
|
||||
* testsuite/protected_1.cc (f2, get_f2_addr): New functions.
|
||||
* testsuite/protected_main_1.cc (main): Test that protected
|
||||
function has same address.
|
||||
|
||||
2011-07-11 Ian Lance Taylor <iant@google.com>
|
||||
|
||||
PR gold/12979
|
||||
|
15
gold/i386.cc
15
gold/i386.cc
@ -1985,9 +1985,24 @@ Target_i386::Scan::global(Symbol_table* symtab,
|
||||
// If this symbol is not fully resolved, we need to add a
|
||||
// GOT entry with a dynamic relocation.
|
||||
Reloc_section* rel_dyn = target->rel_dyn_section(layout);
|
||||
|
||||
// Use a GLOB_DAT rather than a RELATIVE reloc if:
|
||||
//
|
||||
// 1) The symbol may be defined in some other module.
|
||||
//
|
||||
// 2) We are building a shared library and this is a
|
||||
// protected symbol; using GLOB_DAT means that the dynamic
|
||||
// linker can use the address of the PLT in the main
|
||||
// executable when appropriate so that function address
|
||||
// comparisons work.
|
||||
//
|
||||
// 3) This is a STT_GNU_IFUNC symbol in position dependent
|
||||
// code, again so that function address comparisons work.
|
||||
if (gsym->is_from_dynobj()
|
||||
|| gsym->is_undefined()
|
||||
|| gsym->is_preemptible()
|
||||
|| (gsym->visibility() == elfcpp::STV_PROTECTED
|
||||
&& parameters->options().shared())
|
||||
|| (gsym->type() == elfcpp::STT_GNU_IFUNC
|
||||
&& parameters->options().output_is_position_independent()))
|
||||
got->add_global_with_rel(gsym, GOT_TYPE_STANDARD,
|
||||
|
@ -31,3 +31,28 @@ f1()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
// The function f2 is used to test that the executable can see the
|
||||
// same function address for a protected function in the executable
|
||||
// and in the shared library. We can't use the visibility attribute
|
||||
// here, becaues that may cause gcc to generate a PC relative reloc;
|
||||
// we need it to get the value from the GOT. I'm not sure this is
|
||||
// really useful, given that it doesn't work with the visibility
|
||||
// attribute. This test exists here mainly because the glibc
|
||||
// testsuite has the same test, and we want to make sure that gold
|
||||
// passes the glibc testsuite.
|
||||
|
||||
extern "C" int f2();
|
||||
asm(".protected f2");
|
||||
|
||||
extern "C" int
|
||||
f2()
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
int
|
||||
(*get_f2_addr())()
|
||||
{
|
||||
return f2;
|
||||
}
|
||||
|
@ -28,9 +28,13 @@
|
||||
extern bool t1();
|
||||
extern bool t2();
|
||||
|
||||
extern "C" int f2();
|
||||
extern int (*get_f2_addr()) ();
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
assert(t1());
|
||||
assert(t2());
|
||||
assert(&f2 == get_f2_addr());
|
||||
}
|
||||
|
@ -2436,9 +2436,24 @@ Target_x86_64::Scan::global(Symbol_table* symtab,
|
||||
// If this symbol is not fully resolved, we need to add a
|
||||
// dynamic relocation for it.
|
||||
Reloc_section* rela_dyn = target->rela_dyn_section(layout);
|
||||
|
||||
// Use a GLOB_DAT rather than a RELATIVE reloc if:
|
||||
//
|
||||
// 1) The symbol may be defined in some other module.
|
||||
//
|
||||
// 2) We are building a shared library and this is a
|
||||
// protected symbol; using GLOB_DAT means that the dynamic
|
||||
// linker can use the address of the PLT in the main
|
||||
// executable when appropriate so that function address
|
||||
// comparisons work.
|
||||
//
|
||||
// 3) This is a STT_GNU_IFUNC symbol in position dependent
|
||||
// code, again so that function address comparisons work.
|
||||
if (gsym->is_from_dynobj()
|
||||
|| gsym->is_undefined()
|
||||
|| gsym->is_preemptible()
|
||||
|| (gsym->visibility() == elfcpp::STV_PROTECTED
|
||||
&& parameters->options().shared())
|
||||
|| (gsym->type() == elfcpp::STT_GNU_IFUNC
|
||||
&& parameters->options().output_is_position_independent()))
|
||||
got->add_global_with_rela(gsym, GOT_TYPE_STANDARD, rela_dyn,
|
||||
|
Loading…
Reference in New Issue
Block a user