Bug 12980 - bad GOT reloc generation in -shared for STV_PROTECTED with primary PLT/copy reference
Summary: bad GOT reloc generation in -shared for STV_PROTECTED with primary PLT/copy r...
Status: RESOLVED FIXED
Alias: None
Product: binutils
Classification: Unclassified
Component: gold (show other bugs)
Version: 2.22
: P2 normal
Target Milestone: ---
Assignee: Ian Lance Taylor
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2011-07-09 22:59 UTC by Roland McGrath
Modified: 2011-07-12 23:29 UTC (History)
0 users

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Roland McGrath 2011-07-09 22:59:17 UTC
This comes up in a glibc dynamic linker test.
See elf/vis{main,mod[123]}.c in the sourceware glibc tree.

Here vismod1.c generates an STV_PROTECTED definition of "protinmod" and
code with a R_X86_64_GOTPCREL taking its address.  vismain.c generates an
undefined reference to protinmod, and uses both &protinmod and direct calls
to protinmod; so it has a PLT entry for protinmod that is the canonical
function pointer address for &protinmod.

BFD ld -shared building vismod1.so emits an R_X86_64_GLOB_DAT for the
R_X86_64_GOTPCREL referencing protinmod.  gold -shared generates an
R_X86_64_RELATIVE instead.  This yields the wrong address for &protinmind
(the DSO real definition address rather than the non-PIC executable's PLT
entry).

There may be other similar cases, but I suspect all the failures in this test are the same bug or ones obviously related enough you will find them by looking at your code.
Comment 1 Sourceware Commits 2011-07-12 22:29:13 UTC
CVSROOT:	/cvs/src
Module name:	src
Changes by:	ian@sourceware.org	2011-07-12 22:29:09

Modified files:
	gold           : ChangeLog i386.cc x86_64.cc 
	gold/testsuite : protected_1.cc protected_main_1.cc 

Log message:
	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.

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/src/gold/ChangeLog.diff?cvsroot=src&r1=1.803&r2=1.804
http://sourceware.org/cgi-bin/cvsweb.cgi/src/gold/i386.cc.diff?cvsroot=src&r1=1.138&r2=1.139
http://sourceware.org/cgi-bin/cvsweb.cgi/src/gold/x86_64.cc.diff?cvsroot=src&r1=1.136&r2=1.137
http://sourceware.org/cgi-bin/cvsweb.cgi/src/gold/testsuite/protected_1.cc.diff?cvsroot=src&r1=1.1&r2=1.2
http://sourceware.org/cgi-bin/cvsweb.cgi/src/gold/testsuite/protected_main_1.cc.diff?cvsroot=src&r1=1.1&r2=1.2
Comment 2 Ian Lance Taylor 2011-07-12 22:34:43 UTC
I'm not convinced that this case is very interesting.  The test fails when using gcc's visibility attribute, because in that case gcc generates a PC-relative reloc (on x86_64) and there is no way that the function addresses can match.  It only works for glibc because glibc uses .protected in an asm rather than using the visibility attribute.  On the other hand, for the same reason, it doesn't cost very much; normal code will never use a GOT entry for a protected variable.  So I went ahead and implemented this in gold in the spirit of keeping glibc happy.
Comment 3 Roland McGrath 2011-07-12 23:29:46 UTC
I tend to think that the aforementioned GCC behavior is a bug.
But I haven't looked at the spec for visibility handling lately.

At any rate, it is a Good Thing for such subtleties to have the same behavior in both ld implementations.  So if this glibc test's expectation is actually wrong, then BFD ld should be fixed instead.