shark - 2012-10-15

Give the following three codelets,

/* main.c */
__attribute__((weak)) void foo();
int main(int argc, char const *argv[]) {
    foo();
    return 0;
}

/* a.c */
__attribute__((weak)) void foo() {}

/* b.c */
__attribute__((weak)) void foo() {}

when linking with the command line

gcc -o a main.c a.c b.c

,
the linker would complain something like

ccfHPkfI.o:b.c:(.text+0x0): multiple definition of `.weak.foo.'
ccriLvHy.o:a.c:(.text+0x0): first defined here"

but it's okay under linux;

Moreover, it looks like the mingw linker will mangle the weak symbols with the first defined symbol's name, hence I've to add some guard to prevent the multiple definitions error, then i change the
codelets to the following.

/* a.c */
/* Guard workaround for mingw's weak symbols linking.*/
#if defined(__MINGW32__) || defined(__MINGW64__)
char __76dc9de9_9553_4eb6_b09d_ef4e9bbab8f0__;
#endif
__attribute__((weak)) void foo() {}

/* b.c */
/* Guard workaround for mingw's weak symbols linking.*/
#if defined(__MINGW32__) || defined(__MINGW64__)
char __6e108c68_72c3_4b1e_be43_b40e018b4c5a__;
#endif
__attribute__((weak)) void foo() {}

Now finally it links however the executable would cause some "a.exe has stopped working" error.

There are two workarounds about this:

1. Change the declaration to "void foo() __attribute__((section ".gnu.linkonce.0."));", put it into a special section does something similar to variable attribute's "__attribute__((selectany))";
2. For C++, change the declaration to "inline void foo() __attribute__((used));", this is mimicking the c++ template function behavior and resulted in putting pseudo op ".linkonce discard" into the final assembly.

I want to know why weak attribute under mingw would have such strange behavior?

PS: I'm using GCC 4.7.2 and Binutils 2.22.90 under windows.