diff --git a/modules/rostests/apitests/include/apitest.h b/modules/rostests/apitests/include/apitest.h index 27777f7a730..50bf98b5930 100644 --- a/modules/rostests/apitests/include/apitest.h +++ b/modules/rostests/apitests/include/apitest.h @@ -8,12 +8,13 @@ #include #undef WIN32_NO_STATUS -#include - /* See kmtests/include/kmt_test.h */ #define InvalidPointer ((PVOID)0x5555555555555555ULL) // #define InvalidPointer ((PVOID)0x0123456789ABCDEFULL) +#ifdef __USE_PSEH2__ +#include + #define StartSeh() \ { \ NTSTATUS ExceptionStatus = STATUS_SUCCESS; \ @@ -31,6 +32,24 @@ "Exception 0x%08lx, expected 0x%08lx\n", \ ExceptionStatus, (ExpectedStatus)); \ } +#else +#define StartSeh() \ +{ \ + NTSTATUS ExceptionStatus = STATUS_SUCCESS; \ + __try \ + { + +#define EndSeh(ExpectedStatus) \ + } \ + __except(EXCEPTION_EXECUTE_HANDLER) \ + { \ + ExceptionStatus = GetExceptionCode(); \ + } \ + ok(ExceptionStatus == (ExpectedStatus), \ + "Exception 0x%08lx, expected 0x%08lx\n", \ + ExceptionStatus, (ExpectedStatus)); \ +} +#endif #define ok_hr(status, expected) ok_hex(status, expected) #define ok_hr_(file, line, status, expected) ok_hex_(file, line, status, expected) diff --git a/sdk/cmake/host-tools.cmake b/sdk/cmake/host-tools.cmake index 4633b1097d1..5d426e1b863 100644 --- a/sdk/cmake/host-tools.cmake +++ b/sdk/cmake/host-tools.cmake @@ -35,6 +35,7 @@ function(setup_host_tools) -DCMAKE_INSTALL_PREFIX=${REACTOS_BINARY_DIR}/host-tools -DTOOLS_FOLDER=${REACTOS_BINARY_DIR}/host-tools/bin -DGCC_PLUGIN_DIR=${GCC_PLUGIN_DIR} + -DTARGET_COMPILER_ID=${CMAKE_C_COMPILER_ID} BUILD_ALWAYS TRUE INSTALL_COMMAND ${CMAKE_COMMAND} -E true BUILD_BYPRODUCTS ${HOST_TOOLS_OUTPUT} diff --git a/sdk/include/psdk/rpc.h b/sdk/include/psdk/rpc.h index 800abf44fe2..b35c35fcad1 100644 --- a/sdk/include/psdk/rpc.h +++ b/sdk/include/psdk/rpc.h @@ -5,7 +5,7 @@ #endif /* _INC_WINDOWS */ #endif -#ifndef RC_INVOKED +#if defined(__USE_PSEH2__) && !defined(RC_INVOKED) #include #endif @@ -122,7 +122,7 @@ typedef int RPC_STATUS; #include #include - #ifndef __GNUC__ + #ifndef __USE_PSEH2__ #define RpcTryExcept __try { #define RpcExcept(expr) } __except (expr) { #define RpcEndExcept } diff --git a/sdk/include/reactos/libs/pseh/pseh2_64.h b/sdk/include/reactos/libs/pseh/pseh2_64.h deleted file mode 100644 index fd582a1e1f3..00000000000 --- a/sdk/include/reactos/libs/pseh/pseh2_64.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef KJK_PSEH2_H_ -#define KJK_PSEH2_H_ - - -#define _SEH2_TRY if(1) { -#define _SEH2_EXCEPT(...) } if(0) { -#define _SEH2_END } -#define _SEH2_YIELD(STMT_) STMT_ -#define _SEH2_LEAVE -#define _SEH2_FINALLY } if(1) { -#define _SEH2_GetExceptionInformation() (GetExceptionInformation()) -#define _SEH2_GetExceptionCode() (0) -#define _SEH2_AbnormalTermination() (0) - -struct _EXCEPTION_RECORD; -struct _EXCEPTION_POINTERS; -struct _CONTEXT; - -typedef int (__cdecl * _SEH2FrameHandler_t) -( - struct _EXCEPTION_RECORD *, - void *, - struct _CONTEXT *, - void * -); - -typedef struct __SEH2Registration -{ - struct __SEH2Registration * SER_Prev; - _SEH2FrameHandler_t SER_Handler; -} -_SEH2Registration_t; - - -#endif - -/* EOF */ diff --git a/sdk/include/reactos/wine/exception.h b/sdk/include/reactos/wine/exception.h index 9b29f2e470f..f9333e8ff2a 100644 --- a/sdk/include/reactos/wine/exception.h +++ b/sdk/include/reactos/wine/exception.h @@ -3,8 +3,10 @@ #include #include -#include -#include +#ifdef __USE_PSEH2__ +# include +# include +#endif #ifdef __cplusplus extern "C" { @@ -56,6 +58,7 @@ typedef struct _WINE_EXCEPTION_REGISTRATION_RECORD #define PEXCEPTION_REGISTRATION_RECORD PWINE_EXCEPTION_REGISTRATION_RECORD #endif +#ifdef __USE_PSEH2__ #define __TRY _SEH2_TRY #define __EXCEPT(func) _SEH2_EXCEPT(func(_SEH2_GetExceptionInformation())) #define __EXCEPT_CTX(func, ctx) _SEH2_EXCEPT((func)(GetExceptionInformation(), ctx)) @@ -76,7 +79,16 @@ typedef struct _WINE_EXCEPTION_REGISTRATION_RECORD #ifndef AbnormalTermination #define AbnormalTermination() _SEH2_AbnormalTermination() #endif - +#else +#define __TRY __try +#define __EXCEPT(func) __except(func(GetExceptionInformation())) +#define __EXCEPT_CTX(func, ctx) __except((func)(GetExceptionInformation(), ctx)) +#define __EXCEPT_PAGE_FAULT __except(GetExceptionCode() == STATUS_ACCESS_VIOLATION) +#define __EXCEPT_ALL __except(1) +#define __ENDTRY +#define __FINALLY(func) __finally { func(!AbnormalTermination()); } +#define __FINALLY_CTX(func, ctx) __finally { func(!AbnormalTermination(), ctx); } +#endif #if defined(__MINGW32__) || defined(__CYGWIN__) #define sigjmp_buf jmp_buf diff --git a/sdk/lib/pseh/CMakeLists.txt b/sdk/lib/pseh/CMakeLists.txt index 3a5f46e282e..604e56614ed 100644 --- a/sdk/lib/pseh/CMakeLists.txt +++ b/sdk/lib/pseh/CMakeLists.txt @@ -12,13 +12,15 @@ elseif(ARCH STREQUAL "arm") arm/seh_prolog.s) endif() -if(MSVC OR ARCH STREQUAL "amd64") - +if(MSVC OR ((CMAKE_C_COMPILER_ID STREQUAL "Clang") AND (ARCH STREQUAL "amd64"))) list(APPEND SOURCE dummy.c) add_asm_files(pseh_asm ${ASM_SOURCE}) add_library(pseh ${SOURCE} ${pseh_asm}) add_dependencies(pseh asm) - +elseif((CMAKE_C_COMPILER_ID STREQUAL "GNU") AND (ARCH STREQUAL "amd64")) + # for GCC amd64 this is just an interface library, with our home-made plugin + add_library(pseh INTERFACE) + target_compile_options(pseh INTERFACE -fplugin=$) else() if(USE_PSEH3) @@ -43,4 +45,13 @@ else() target_link_libraries(pseh chkstk) add_dependencies(pseh psdk) + target_include_directories(pseh PRIVATE include/pseh) +endif() + +target_include_directories(pseh INTERFACE include) + +# Make it clear that we are using PSEH2 +if ((CMAKE_C_COMPILER_ID STREQUAL "GNU") OR + ((CMAKE_C_COMPILER_ID STREQUAL "Clang") AND (NOT (ARCH STREQUAL "amd64")))) + target_compile_definitions(pseh INTERFACE __USE_PSEH2__) endif() diff --git a/sdk/include/reactos/libs/pseh/excpt.h b/sdk/lib/pseh/include/pseh/excpt.h similarity index 100% rename from sdk/include/reactos/libs/pseh/excpt.h rename to sdk/lib/pseh/include/pseh/excpt.h diff --git a/sdk/include/reactos/libs/pseh/framebased.h b/sdk/lib/pseh/include/pseh/framebased.h similarity index 100% rename from sdk/include/reactos/libs/pseh/framebased.h rename to sdk/lib/pseh/include/pseh/framebased.h diff --git a/sdk/include/reactos/libs/pseh/framebased/internal.h b/sdk/lib/pseh/include/pseh/framebased/internal.h similarity index 100% rename from sdk/include/reactos/libs/pseh/framebased/internal.h rename to sdk/lib/pseh/include/pseh/framebased/internal.h diff --git a/sdk/include/reactos/libs/pseh/pseh.h b/sdk/lib/pseh/include/pseh/pseh.h similarity index 100% rename from sdk/include/reactos/libs/pseh/pseh.h rename to sdk/lib/pseh/include/pseh/pseh.h diff --git a/sdk/include/reactos/libs/pseh/pseh2.h b/sdk/lib/pseh/include/pseh/pseh2.h similarity index 99% rename from sdk/include/reactos/libs/pseh/pseh2.h rename to sdk/lib/pseh/include/pseh/pseh2.h index 45f872e7757..fd985dd8702 100644 --- a/sdk/include/reactos/libs/pseh/pseh2.h +++ b/sdk/lib/pseh/include/pseh/pseh2.h @@ -37,6 +37,10 @@ #define _SEH2_LEAVE __leave #define _SEH2_VOLATILE +#elif defined(__GNUC__) && !defined(__clang__) && defined(_M_AMD64) + +#include "pseh2_64.h" + #elif defined(_USE_DUMMY_PSEH) || defined (__arm__) || defined(_M_AMD64) extern int _SEH2_Volatile0; diff --git a/sdk/lib/pseh/include/pseh/pseh2_64.h b/sdk/lib/pseh/include/pseh/pseh2_64.h new file mode 100644 index 00000000000..21be52477ca --- /dev/null +++ b/sdk/lib/pseh/include/pseh/pseh2_64.h @@ -0,0 +1,169 @@ + +#pragma once + +/* Declare our global trampoline function for filter and unwinder */ +__asm__( + ".p2align 4, 0x90\n" + ".seh_proc __seh2_global_filter_func\n" + "__seh2_global_filter_func:\n" + "\tpush %rbp\n" + "\t.seh_pushreg %rbp\n" + "\tsub $32, %rsp\n" + "\t.seh_stackalloc 32\n" + "\t.seh_endprologue\n" + /* Restore frame pointer. */ + "\tmov %rdx, %rbp\n" + /* Actually execute the filter funclet */ + "\tjmp *%rax\n" + "__seh2_global_filter_func_exit:\n" + "\t.p2align 4\n" + "\tadd $32, %rsp\n" + "\tpop %rbp\n" + "\tret\n" + "\t.seh_endproc"); + +#define _SEH2_TRY \ +{ \ + __label__ __seh2$$begin_try__; \ + __label__ __seh2$$end_try__; \ + /* \ + * We close the current SEH block for this function and install our own. \ + * At this point GCC emitted its prologue, and if it saves more \ + * registers, the relevant instruction will be valid for our scope as well. \ + * We also count the number of try blocks at assembly level \ + * to properly set the handler data when we're done. \ + */ \ +__seh2$$begin_try__: \ + { \ + __label__ __seh2$$leave_scope__; + +#define _SEH2_EXCEPT(...) \ +__seh2$$leave_scope__: __MINGW_ATTRIB_UNUSED; \ + } \ +__seh2$$end_try__: \ + /* Call our home-made pragma */ \ + _Pragma("REACTOS seh(except)") \ + if (0) \ + { \ + __label__ __seh2$$leave_scope__; \ + __label__ __seh2$$filter__; \ + __label__ __seh2$$begin_except__; \ + LONG __MINGW_ATTRIB_UNUSED __seh2$$exception_code__ = 0; \ + /* Add our handlers to the list */ \ + __asm__ __volatile__ goto ("\n" \ + "\t.seh_handlerdata\n" \ + "\t.rva %l0\n" /* Begin of tried code */ \ + "\t.rva %l1 + 1\n" /* End of tried code */ \ + "\t.rva %l2\n" /* Filter function */ \ + "\t.rva %l3\n" /* Called on except */ \ + "\t.seh_code\n" \ + : /* No output */ \ + : /* No input */ \ + : /* No clobber */ \ + : __seh2$$begin_try__, \ + __seh2$$end_try__, \ + __seh2$$filter__, \ + __seh2$$begin_except__); \ + if (0) \ + { \ + /* Jump to the global filter. Tell it where the filter funclet lies */ \ + __label__ __seh2$$filter_funclet__; \ + __seh2$$filter__: \ + __asm__ __volatile__ goto( \ + "\tleaq %l0(%%rip), %%rax\n" \ + "\tjmp __seh2_global_filter_func\n" \ + : /* No output */ \ + : /* No input */ \ + : "%rax" \ + : __seh2$$filter_funclet__); \ + /* Actually declare our filter funclet */ \ + struct _EXCEPTION_POINTERS* __seh2$$exception_ptr__; \ + __seh2$$filter_funclet__: \ + /* At this point, the compiler can't count on any register being valid */ \ + __asm__ __volatile__("" \ + : "=c"(__seh2$$exception_ptr__) /* First argument of the filter function */ \ + : /* No input */ \ + : /* Everything */ \ + "%rax", "%rbx","%rdx", "%rdi", "%rsi", \ + "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"); \ + /* Save exception code */ \ + __seh2$$exception_code__ = __seh2$$exception_ptr__->ExceptionRecord->ExceptionCode; \ + /* Actually evaluate our filter */ \ + register long __MINGW_ATTRIB_UNUSED __seh2$$filter_funclet_ret __asm__("eax") = \ + ((__VA_ARGS__)); \ + /* Go back to the global filter function */ \ + __asm__("jmp __seh2_global_filter_func_exit"); \ + } \ + /* Protect us from emitting instructions to jump back to the filter function */ \ + enum \ + { \ + __seh2$$abnormal_termination__ = 0 \ + }; \ + __seh2$$begin_except__: + +#define _SEH2_FINALLY \ +__seh2$$leave_scope__: __MINGW_ATTRIB_UNUSED; \ + } \ +__seh2$$end_try__: \ + /* Call our home-made pragma */ \ + _Pragma("REACTOS seh(finally)") \ + if (1) \ + { \ + __label__ __seh2$$finally__; \ + __label__ __seh2$$begin_finally__; \ + __label__ __seh2$$leave_scope__; \ + int __seh2$$abnormal_termination__; \ + /* Add our handlers to the list */ \ + __asm__ __volatile__ goto ("\n" \ + "\t.seh_handlerdata\n" \ + "\t.rva %l0\n" /* Begin of tried code */ \ + "\t.rva %l1 + 1\n" /* End of tried code */ \ + "\t.rva %l2\n" /* Filter function */ \ + "\t.long 0\n" /* Nothing for unwind code */ \ + "\t.seh_code\n" \ + : /* No output */ \ + : /* No input */ \ + : /* No clobber */ \ + : __seh2$$begin_try__, \ + __seh2$$end_try__, \ + __seh2$$finally__); \ + if (0) \ + { \ + /* Jump to the global trampoline. Tell it where the unwind code really lies */ \ + __seh2$$finally__: \ + __asm__ __volatile__ goto( \ + "\tleaq %l0(%%rip), %%rax\n" \ + "\tjmp __seh2_global_filter_func\n" \ + : /* No output */ \ + : /* No input */ \ + : /* No clobber */ \ + : __seh2$$begin_finally__); \ + } \ + \ + /* Zero-out rcx to indicate normal termination */ \ + __asm__ __volatile__("xor %%rcx, %%rcx" \ + : /* No output */ \ + : /* No input */ \ + : /* Everything - We might come from __C_specific_handler here */ \ + "%rax", "%rbx", "%rcx", "%rdx", "%rdi", "%rsi", \ + "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"); \ + /* Actually declare our finally funclet */ \ + __seh2$$begin_finally__: \ + __asm__ __volatile__("" \ + : "=c" (__seh2$$abnormal_termination__)); + +#define _SEH2_END \ + __seh2$$leave_scope__: __MINGW_ATTRIB_UNUSED; \ + if (__seh2$$abnormal_termination__) \ + { \ + __asm__("jmp __seh2_global_filter_func_exit"); \ + } \ + } \ +} + +#define _SEH2_GetExceptionInformation() __seh2$$exception_ptr__ +#define _SEH2_GetExceptionCode() __seh2$$exception_code__ +#define _SEH2_AbnormalTermination() __seh2$$abnormal_termination__ +#define _SEH2_LEAVE goto __seh2$$leave_scope__ +#define _SEH2_YIELD(__stmt) __stmt +#define _SEH2_VOLATILE volatile diff --git a/sdk/include/reactos/libs/pseh/pseh3.h b/sdk/lib/pseh/include/pseh/pseh3.h similarity index 100% rename from sdk/include/reactos/libs/pseh/pseh3.h rename to sdk/lib/pseh/include/pseh/pseh3.h diff --git a/sdk/tools/CMakeLists.txt b/sdk/tools/CMakeLists.txt index 956a6dc7060..c27c9ac3683 100644 --- a/sdk/tools/CMakeLists.txt +++ b/sdk/tools/CMakeLists.txt @@ -40,12 +40,13 @@ add_subdirectory(widl) add_subdirectory(wpp) add_subdirectory(xml2sdb) +if ((ARCH STREQUAL "amd64") AND (TARGET_COMPILER_ID STREQUAL "GNU")) + add_subdirectory(gcc_plugin_seh) +endif() + if(NOT MSVC) add_subdirectory(log2lines) add_subdirectory(rsym) -if (ARCH STREQUAL "amd64") - add_subdirectory(gcc_plugin_seh) -endif() add_host_tool(pefixup pefixup.c) if (ARCH STREQUAL "amd64")