[Bug target/90826] New: Weak symbol does not work reliably on windows

yyc1992 at gmail dot com gcc-bugzilla@gcc.gnu.org
Mon Jun 10 23:49:00 GMT 2019


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


More information about the Gcc-bugs mailing list