https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90826
Bug ID: 90826 Summary: Weak symbol does not work reliably on windows Product: gcc Version: 9.1.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: target Assignee: unassigned at gcc dot gnu.org Reporter: yyc1992 at gmail dot com Target Milestone: --- The following code does not link correctly with all optimization levels on windows with the mingw-w64-x86_64-g++ compiler. ``` #include <stdint.h> extern "C" void f() __attribute__((weak)); int main() { return (int)(uintptr_t)f; } ``` The assembly generated is ``` .file "weak.cpp" .text .def __main; .scl 2; .type 32; .endef .section .text.startup,"x" .p2align 4 .globl main .def main; .scl 2; .type 32; .endef .seh_proc main main: .LFB1: subq $56, %rsp .seh_stackalloc 56 .seh_endprologue call __main movq .refptr.f(%rip), %rax movq %rax, 40(%rsp) addq $56, %rsp ret .seh_endproc .ident "GCC: (Rev2, Built by MSYS2 project) 9.1.0" .section .rdata$.refptr.f, "dr" .globl .refptr.f .linkonce discard .refptr.f: .quad f ``` and the error, ``` C:\msys64\tmp\ccQkPfOi.o:weak.cpp:(.rdata$.refptr.f[.refptr.f]+0x0): undefined reference to `f' ``` This should not happen since `f` is declared weak. (I realized that the symbol resolution happens at compile time for weak symbol, which is fine for me, but I just want it to compile...) Another case where the optimization actually makes this work is, ``` #include <stdio.h> extern "C" void f() __attribute__((weak)); int main() { printf("%p\n", f); return 0; } ``` With -O0, the assembly generated is ``` .file "weak.cpp" .text .def __main; .scl 2; .type 32; .endef .section .rdata,"dr" .LC0: .ascii "%p\12\0" .text .globl main .def main; .scl 2; .type 32; .endef .seh_proc main main: .LFB28: pushq %rbp .seh_pushreg %rbp movq %rsp, %rbp .seh_setframe %rbp, 0 subq $32, %rsp .seh_stackalloc 32 .seh_endprologue call __main movq .refptr.f(%rip), %rdx leaq .LC0(%rip), %rcx call printf movl $0, %eax addq $32, %rsp popq %rbp ret .seh_endproc .ident "GCC: (Rev2, Built by MSYS2 project) 9.1.0" .def printf; .scl 2; .type 32; .endef .section .rdata$.refptr.f, "dr" .globl .refptr.f .linkonce discard .refptr.f: .quad f ``` with error, ``` C:\msys64\tmp\ccTiwMKh.o:weak.cpp:(.rdata$.refptr.f[.refptr.f]+0x0): undefined reference to `f' ``` with -O1 or higher, the assembly produced is, ``` .file "weak.cpp" .text .def __main; .scl 2; .type 32; .endef .section .rdata,"dr" .LC0: .ascii "%p\12\0" .text .globl main .def main; .scl 2; .type 32; .endef .seh_proc main main: .LFB30: subq $40, %rsp .seh_stackalloc 40 .seh_endprologue call __main leaq f(%rip), %rdx leaq .LC0(%rip), %rcx call printf movl $0, %eax addq $40, %rsp ret .seh_endproc .weak f .ident "GCC: (Rev2, Built by MSYS2 project) 9.1.0" .def f; .scl 2; .type 32; .endef .def printf; .scl 2; .type 32; .endef .section .rdata$.refptr.f, "dr" .globl .refptr.f .linkonce discard .refptr.f: .quad f ``` The difference between the two assembly is ``` --- weak1.s 2019-06-10 19:42:27.039467600 -0400 +++ weak0.s 2019-06-10 19:42:23.709467500 -0400 @@ -9,21 +9,24 @@ .def main; .scl 2; .type 32; .endef .seh_proc main main: -.LFB30: - subq $40, %rsp - .seh_stackalloc 40 +.LFB28: + pushq %rbp + .seh_pushreg %rbp + movq %rsp, %rbp + .seh_setframe %rbp, 0 + subq $32, %rsp + .seh_stackalloc 32 .seh_endprologue call __main - leaq f(%rip), %rdx + movq .refptr.f(%rip), %rdx leaq .LC0(%rip), %rcx call printf movl $0, %eax - addq $40, %rsp + addq $32, %rsp + popq %rbp ret .seh_endproc - .weak f .ident "GCC: (Rev2, Built by MSYS2 project) 9.1.0" - .def f; .scl 2; .type 32; .endef .def printf; .scl 2; .type 32; .endef .section .rdata$.refptr.f, "dr" .globl .refptr.f ``` where weak1.s (-) is the working one and weak0.s (+) is the error one. The missing `.weak f` seems to be the issue. With that added to `weak0.s` or removed from `weak1.s` the compilation result changes to that of the other version. So it seems that without optimization on gcc just forgot to put in the weak attribute into the assembly file??