weak symbol support of mingw gcc

shark
2012-10-15
2013-06-06
  • shark
    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.