This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Re: GOLD handling of weak symbols (including x86 vs. ARM)
Richard Sandiford <richard.sandiford@linaro.org> writes:
> Yeah, that's basically the first-order question. Going back to the
> source code:
>
> extern void foo (void) __attribute__ ((weak));
> int
> main ()
> {
> if (&foo)
> foo ();
>
> return 0;
> }
I agree that this C code has to work one way or another, where by "work"
I mean that the test of &foo has to return 0 if the symbol is not
defined anywhere, not even by a shared library loaded at runtime.
> GCC, when not compiling PIC, traditionally uses absolute accesses for
> the (&foo != 0) test and a non-@PLT call for "foo ()". (The x86 code
> I posted is the output from this testcase, which comes from the GCC
> testsuite.) This approach "works" with both BFD LD and GOLD on x86,
> with neither linker allowing a run-time override of foo. Both linkers
> resolve the &foo reference to zero without any dynamic relocs. The foo ()
> call is never executed, even if foo is defined by an LD_PRELOAD.
>
> That's what I was expecting, but I'm not sure from your response
> whether it's what you were expecting or not.
OK, I may be starting to see what you are getting at. When the linker
sees the relocs generated for &foo, it doesn't know whether the value is
going to be called later or whether it is only going to be compared
against zero. It's ambiguous. If we're going to do a comparison
against zero, then the only correct behaviour is to use a dynamic
relocation, which will evaluate to either zero or the address of the
function in a shared library. If we're going to call the function
later, then we can either use a dynamic relocation or we can refer to
the PLT entry. Putting those together, the only correct behaviour is to
use a dynamic relocation in all cases.
If we are linking code for which we should not generate a dynamic
relocation, then we are screwed. There is no possible way to generate
code which is correct in all cases.
However, over in needs_dynamic_reloc, I see this:
// A reference to an undefined symbol from an executable should be
// statically resolved to 0, and does not need a dynamic relocation.
// This matches gnu ld behavior.
if (this->is_undefined() && !parameters->options().shared())
return false;
So I think we've already decided that we are screwed in this case.
And that means that we should remove these lines from use_plt_offset:
if (this->is_weak_undefined())
return true;
since we've decided that such symbols should be statically resolved to
0.
That seems weird to me but perhaps it makes sense in some universe.
Ian