<< Back to previous view

[PCC-362] weak references not working right Created: 25/Jun/11  Updated: 07/May/14

Status: Resolved
Project: pcc
Component/s: i386 target
Affects Version/s: None
Fix Version/s: None

Type: Bug Priority: Major
Reporter: Iain Hibbert Assignee: Anders Magnusson
Resolution: Fixed Votes: 0
Environment: NetBSD/i386


 Description   
Weak references, via the __weakref__ attribute do not work correctly,
the example code

#include <stdio.h>

void my_foo(void) __attribute__((__weakref__("foo")));

int
main(int ac, char *av[])
{
    printf("my_foo %p\n", my_foo);

    if (my_foo != NULL)
        my_foo();

    return 0;
}

shows the problem, when compiled with pcc results in undefined references to "foo"
what should happen I think, is that the assembler output references "my_foo" and a

   .weakref my_foo,foo

line is emitted, this allows the linker to decide if foo can be resolved, or if it should
supply a nil value..

 Comments   
Comment by Anders Magnusson [ 25/Jun/11 04:12 PM ]
weakref is not supported except for recent binutils. I have some support for it in pcc, but it should probably be checked in configure whether it exist or not.
Comment by Anders Magnusson [ 01/May/14 05:53 PM ]
i386 target now has weakref attribute.
Comment by Iain Hibbert [ 05/May/14 09:10 PM ]
Hi, there is a further wrinkle wrt this weakref. A variable declared with weakref should not have local storage. The following, I think more complete, example demonstrates

static void foo0(void) __attribute__((__weakref__("FOO0")));
static void foo1(void) __attribute__((__weakref__("FOO1")));
static int bar0 __attribute__((__weakref__("BAR0")));
static int bar1 __attribute__((__weakref__("BAR1")));

int
main(int ac, char *av[])
{
    if (&foo0 == (void *)0L) // FOO0 is defined
        return 1;

    if (&foo1 != (void *)0L) // FOO1 is not defined
        return 1;

    if (&bar0 == (void *)0L) // BAR0 is defined
        return 1;

    if (&bar1 != (void *)0L) // BAR1 is not defined
        return 1;

    return 0; // Ok
}

void
FOO0(void)
{
}

int BAR0;

when compiled with "pcc test.c" fails with

/tmp/ctm.28756b: Assembler messages:
/tmp/ctm.28756b:59: Error: symbol `bar0' is already defined
/tmp/ctm.28756b:61: Error: symbol `bar1' is already defined
as terminated with status 1

this is because the compiler emitted storage commands for bar0 and bar1 even though they are not defined

        .local bar0
        .comm bar0,04,4
        .local bar1
        .comm bar1,04,4
        .comm BAR0,04,4

NB gcc and clang both require the "static" declarator for weak reference attributes
Comment by Anders Magnusson [ 07/May/14 04:11 PM ]
Hm, strange, the gcc manual uses extern for its explanation of weakref :-)

          extern int x() __attribute__ ((weakref ("y")));
          /* is equivalent to... */
          extern int x() __attribute__ ((weak, weakref, alias ("y")));
          /* and to... */
          extern int x() __attribute__ ((weakref));
          extern int x() __attribute__ ((alias ("y")));
Comment by Anders Magnusson [ 07/May/14 06:36 PM ]
Now it won't emit storage for weakref variables.
Generated at Mon Dec 22 01:37:02 CET 2014 using JIRA Enterprise Edition, Version: 3.13.1-#333.