It looks like GCC with -O2
and __attribute__((weak))
produces different results depending on how you reference your weak symbols. Consider this:
$ cat weak.c
#include <stdio.h>
extern const int weaksym1;
const int weaksym1 __attribute__(( weak )) = 0;
extern const int weaksym2;
const int weaksym2 __attribute__(( weak )) = 0;
extern int weaksym3;
int weaksym3 __attribute__(( weak )) = 0;
void testweak(void)
{
if ( weaksym1 == 0 )
{
printf( "0\n" );
}
else
{
printf( "1\n" );
}
printf( "%d\n", weaksym2 );
if ( weaksym3 == 0 )
{
printf( "0\n" );
}
else
{
printf( "1\n" );
}
}
$ cat test.c
extern const int weaksym1;
const int weaksym1 = 1;
extern const int weaksym2;
const int weaksym2 = 1;
extern int weaksym3;
int weaksym3 = 1;
extern void testweak(void);
void main(void)
{
testweak();
}
$ make
gcc -c weak.c
gcc -c test.c
gcc -o test test.o weak.o
$ ./test
1
1
1
$ make ADD_FLAGS="-O2"
gcc -O2 -c weak.c
gcc -O2 -c test.c
gcc -O2 -o test test.o weak.o
$ ./test
0
1
1
The question is, why the last "./test" produces "0 1 1", not "1 1 1"?
gcc version 5.4.0 (GCC)
Looks like when doing optimizations, the compiler is having trouble with symbols declared const
and having the weak
definition within the same compilation unit.
You can create a separate c file and move the const weak definitions there, it will work around the problem:
weak_def.c
const int weaksym1 __attribute__(( weak )) = 0;
const int weaksym2 __attribute__(( weak )) = 0;
Same issue described in this question: GCC weak attribute on constant variables