On 2017/11/4 15:24, Adrien Nader wrote:
Good morning,

I was looking at the changelog for OCaml 4.06 and noticed the following
entry:

- MPR#7638: in the Windows Mingw64 port, multithreaded programs
compiled to bytecode could crash when raising an exception from C
code.  This looks like a Mingw64 issue, which we work around with GCC
builtins.  (Xavier Leroy)

This leads to the following pages:
https://caml.inria.fr/mantis/view.php?id=7638
http://www.agardner.me/golang/windows/cgo/64-bit/setjmp/longjmp/2016/02/29/go-windows-setjmp-x86.html
https://sourceforge.net/p/mingw-w64/bugs/406/

Does anyone know if this issue has been fixed and if the bug report
should be closed, or if this has flown under the radar?

Thanks,


I presume this is caused by the x64-Windows-specific `longjmp()` behavior. This reply is merely my presumption. I know nothing about Go or Lua.

The Microsoft documentation (`longjump` in this link is NOT a typo):
<https://docs.microsoft.com/en-us/cpp/build/setjmp-longjump>
says on x64 Windows the `longjmp()` function unwinds the stack, which is less common elsewhere. Hence, on Windows x64 a function must contain stack unwind information, otherwise crash will happen when `longjmp` is called inside it.


Steps to reproduce:

1. Create `test.c`:

```c
#include <setjmp.h>
#include <stdio.h>

jmp_buf buf;

int main(void){
        if(setjmp(buf) == 0){
                puts("about to jump...");
                longjmp(buf, 1);
        } else {
                puts("returned from setjmp()");
        }
}
```

2. Compile it to assembly using `gcc test.c -S -o test.s`:

```
        .file   "test.c"
        .comm   buf, 256, 5
        .def    __main; .scl    2;      .type   32;     .endef
        .section .rdata,"dr"
.LC0:
        .ascii "about to jump...\0"
.LC1:
        .ascii "returned from setjmp()\0"
        .text
        .globl  main
        .def    main;   .scl    2;      .type   32;     .endef
        .seh_proc       main
main:
        pushq   %rbp
        .seh_pushreg    %rbp
        movq    %rsp, %rbp
        .seh_setframe   %rbp, 0
        subq    $32, %rsp
        .seh_stackalloc 32
        .seh_endprologue
        call    __main
        movq    %rbp, %rax
        movq    %rax, %rdx
        leaq    buf(%rip), %rax
        movq    %rax, %rcx
        call    _setjmp
        testl   %eax, %eax
        jne     .L3
        leaq    .LC0(%rip), %rcx
        call    puts
        movl    $1, %edx
        leaq    buf(%rip), %rax
        movq    %rax, %rcx
        call    longjmp
.L3:
        leaq    .LC1(%rip), %rcx
        call    puts
        movl    $0, %eax
        addq    $32, %rsp
        popq    %rbp
        ret
        .seh_endproc
.ident "GCC: (gcc-7-branch HEAD with MCF thread model, built by LH_Mouse.) 7.2.1 20171027"
        .def    _setjmp;        .scl    2;      .type   32;     .endef
        .def    puts;   .scl    2;      .type   32;     .endef
        .def    longjmp;        .scl    2;      .type   32;     .endef
```

3. Note those pseudo instructions that begin with `.seh_`. These instructions set up unwind information for the `main()` function. If you delete them, you get a crash after the first line of text is printed:

```
LH_Mouse@LH_Mouse-PC  /e/Desktop
$ cat test.s | sed "/\\.seh_/d" | as - -o test.o && gcc test.o && "./a.exe"
about to jump...

LH_Mouse@LH_Mouse-PC  /e/Desktop
$ echo $?
127
```




`__builtin_setjmp()` and `__builtin_longjmp()` are GCC-specific implementation that preserves only a minimal set of registers. They differ from those from MSVCRT that, like most other implementations, they do not unwind the stack. Hence they do not require stack unwind information and will not cause crashes in the example above.



--
Best regards,
LH_Mouse


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Mingw-w64-public mailing list
Mingw-w64-public@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public

Reply via email to