This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

GOLD handling of weak symbols (including x86 vs. ARM)


This may be something that has already been discussed to death.
If so, apologies in advance.  (I tried to search, but couldn't
find anything.)

I notice that GOLD and BFD LD differ in the way they handle PLTs
for undefined weak symbols in executables.  Take this testcase
from the GCC testsuite.

extern void foo (void) __attribute__ ((weak));

int
main ()
{
  if (&foo)
    foo ();

  return 0;
}

If you implement it like this on x86:

	.text
	.globl	main
	.type	main, @function
main:
	pushl	%ebp
	movl	%esp, %ebp
	andl	$-16, %esp
	movl	$foo, %eax
	testl	%eax, %eax
	je	.L2
	call	foo
.L2:
	movl	$0, %eax
	movl	%ebp, %esp
	popl	%ebp
	ret
	.size	main, .-main
	.weak	foo

then it works with both BFD LD and GOLD.  foo is set to 0 and there is
no PLT.  But if you add "@PLT" to the call -- not necessarily a sensible
thing, I realise, but bear with me -- then the two linkers differ.
BFD LD creates the PLT and uses it for the call.  However, it still
resolves the absolute relocation for "movl $foo..." to 0.  GOLD instead
points the absolute relocation to the PLT entry.  So the modified code
still "works" with BFD LD for but crashes with GOLD.

If this happens on x86, then I can see there's an argument for blaming
the assembly code.  The problem comes with targets like Thumb that don't
have separate relocations for PLT vs. non-PLT calls.  AIUI, the linker
has no way of telling whether a given Thumb branch originally had @PLT
attached to it or not.  (@PLT does of course affect assembler behaviour.)

So, in the corresponding code for Thumb:

	.global	main
	.thumb
	.thumb_func
	.type	main, %function
main:
	.fnstart
.LFB0:
	@ args = 0, pretend = 0, frame = 0
	@ frame_needed = 0, uses_anonymous_args = 0
	push	{r3, lr}
	.save {r3, lr}
	movw	r3, #:lower16:foo
	movt	r3, #:upper16:foo
	cbz	r3, .L2
	bl	foo
.L2:
	movs	r0, #0
	pop	{r3, pc}
	.fnend
	.size	main, .-main
	.weak	foo

GOLD effectively handles "bl foo" in the same way that it would handle
"call foo@PLT" on x86.  It creates a PLT for foo, then resolves the
absolute relocations to the PLT rather than 0.

I see that use_plt_offset specifically has:

    // If this is a weak undefined symbol, we need to use the PLT
    // entry; the symbol may be defined by a library loaded at
    // runtime.
    if (this->is_weak_undefined())
      return true;

At this point we have determined that we can't use dynamic relocs.
We've also already dealt with the general case of undefined symbols
in shared libraries:

    // If we are generating a shared object, and this symbol is
    // undefined or preemptible, we need to use the PLT entry.
    if (parameters->options().shared()
	&& (this->is_undefined() || this->is_preemptible()))
      return true;

so it seems the behaviour is to some extent deliberate.  IIRC,
it's part of the code to handle LD_PRELOADs that define weak symbols.

What's the best way out here?

Richard


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]