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??