diff options
| -rw-r--r-- | gold/ChangeLog | 11 | ||||
| -rw-r--r-- | gold/i386.cc | 15 | ||||
| -rw-r--r-- | gold/testsuite/protected_1.cc | 25 | ||||
| -rw-r--r-- | gold/testsuite/protected_main_1.cc | 4 | ||||
| -rw-r--r-- | gold/x86_64.cc | 15 | 
5 files changed, 70 insertions, 0 deletions
| diff --git a/gold/ChangeLog b/gold/ChangeLog index 3dc9723..d4b8bc3 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -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 diff --git a/gold/i386.cc b/gold/i386.cc index 8d3b630..84b9f07 100644 --- a/gold/i386.cc +++ b/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, diff --git a/gold/testsuite/protected_1.cc b/gold/testsuite/protected_1.cc index 9183312..049bda7 100644 --- a/gold/testsuite/protected_1.cc +++ b/gold/testsuite/protected_1.cc @@ -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; +} diff --git a/gold/testsuite/protected_main_1.cc b/gold/testsuite/protected_main_1.cc index cc387a4..271446f 100644 --- a/gold/testsuite/protected_main_1.cc +++ b/gold/testsuite/protected_main_1.cc @@ -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());  } diff --git a/gold/x86_64.cc b/gold/x86_64.cc index de204cb..ef66737 100644 --- a/gold/x86_64.cc +++ b/gold/x86_64.cc @@ -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, | 
