diff --git a/CMakeLists.txt b/CMakeLists.txt index 59a1e695..696d070f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -859,6 +859,10 @@ if (MSVC) ${CMAKE_CURRENT_SOURCE_DIR}/msvc/unicorn/qapi-types.c ${CMAKE_CURRENT_SOURCE_DIR}/msvc/unicorn/qapi-visit.c ) + if(CMAKE_SIZEOF_VOID_P EQUAL 8) + enable_language(ASM_MASM) + set(UNICORN_SRCS ${UNICORN_SRCS} qemu/util/setjmp-wrapper-win32.asm) + endif() else() set(UNICORN_SRCS ${UNICORN_SRCS_COMMON} diff --git a/msvc/unicorn/unicorn/unicorn.vcxproj b/msvc/unicorn/unicorn/unicorn.vcxproj index 27f7762b..4b896c9e 100644 --- a/msvc/unicorn/unicorn/unicorn.vcxproj +++ b/msvc/unicorn/unicorn/unicorn.vcxproj @@ -53,6 +53,7 @@ + @@ -357,7 +358,16 @@ copy "$(SolutionDir)..\include\unicorn\*.h" "$(SolutionDir)distro\include\unicor + + + true + true + false + false + + + - + \ No newline at end of file diff --git a/msvc/unicorn/unicorn/unicorn.vcxproj.filters b/msvc/unicorn/unicorn/unicorn.vcxproj.filters index 149590fc..da3121fc 100644 --- a/msvc/unicorn/unicorn/unicorn.vcxproj.filters +++ b/msvc/unicorn/unicorn/unicorn.vcxproj.filters @@ -499,4 +499,7 @@ + + + \ No newline at end of file diff --git a/msvc/unicorn/unicorn_static/unicorn_static.vcxproj b/msvc/unicorn/unicorn_static/unicorn_static.vcxproj index 08d8cd02..57551e52 100644 --- a/msvc/unicorn/unicorn_static/unicorn_static.vcxproj +++ b/msvc/unicorn/unicorn_static/unicorn_static.vcxproj @@ -169,6 +169,14 @@ + + + true + true + false + false + + {B6EFD6D7-C2D4-4FBB-B363-2E08CE09CC96} Win32Proj @@ -204,6 +212,7 @@ + @@ -363,5 +372,6 @@ copy "$(SolutionDir)..\include\unicorn\*.h" "$(SolutionDir)distro\include\unicor + - + \ No newline at end of file diff --git a/msvc/unicorn/unicorn_static/unicorn_static.vcxproj.filters b/msvc/unicorn/unicorn_static/unicorn_static.vcxproj.filters index 8dd77e0a..121c3eee 100644 --- a/msvc/unicorn/unicorn_static/unicorn_static.vcxproj.filters +++ b/msvc/unicorn/unicorn_static/unicorn_static.vcxproj.filters @@ -498,4 +498,7 @@ qemu + + + \ No newline at end of file diff --git a/qemu/include/sysemu/os-win32.h b/qemu/include/sysemu/os-win32.h index 5d7b1d83..7825c310 100644 --- a/qemu/include/sysemu/os-win32.h +++ b/qemu/include/sysemu/os-win32.h @@ -56,13 +56,27 @@ # define EWOULDBLOCK WSAEWOULDBLOCK #endif -#if defined(_WIN64) && !defined(_MSC_VER) +#if defined(_WIN64) /* On w64, setjmp is implemented by _setjmp which needs a second parameter. * If this parameter is NULL, longjump does no stack unwinding. * That is what we need for QEMU. Passing the value of register rsp (default) * lets longjmp try a stack unwinding which will crash with generated code. */ + +#if defined(_MSC_VER) // MSVC + +// See qemu/include/utils/setjmp-wrapper-win32.asm for details. +extern int _setjmp_wrapper(jmp_buf); + +# undef setjmp +# define setjmp(env) _setjmp_wrapper(env) + +#else // MinGW + +// Original QEMU patch. # undef setjmp # define setjmp(env) _setjmp(env, NULL) +#endif + #endif /* QEMU uses sigsetjmp()/siglongjmp() as the portable way to specify * "longjmp and don't touch the signal masks". Since we know that the diff --git a/qemu/util/setjmp-wrapper-win32.asm b/qemu/util/setjmp-wrapper-win32.asm new file mode 100644 index 00000000..6e6b6ab9 --- /dev/null +++ b/qemu/util/setjmp-wrapper-win32.asm @@ -0,0 +1,26 @@ +EXTERN _setjmp: proc +PUBLIC _setjmp_wrapper + +_TEXT SEGMENT + +_setjmp_wrapper PROC + +; Why do we need this wrapper? +; Short answer: Windows default implementation of setjmp/longjmp is incompatible with generated code. +; A longer answer: https://blog.lazym.io/2020/09/21/Unicorn-Devblog-setjmp-longjmp-on-Windows/. + +; From qemu os-win32 comments: +; > On w64, setjmp is implemented by _setjmp which needs a second parameter. +; > If this parameter is NULL, longjump does no stack unwinding. +; > That is what we need for QEMU. Passing the value of register rsp (default) +; > lets longjmp try a stack unwinding which will crash with generated code. +; It's true indeed, but MSVC doesn't has a setjmp signature which receives two arguements. +; Therefore, we add a wrapper to keep the second argument zero. +xor rdx, rdx +jmp _setjmp + +_setjmp_wrapper ENDP + +_TEXT ENDS + +END \ No newline at end of file