https://git.reactos.org/?p=reactos.git;a=commitdiff;h=ba74a05a1761691ff4cc20cd6e1804cb375c1e36

commit ba74a05a1761691ff4cc20cd6e1804cb375c1e36
Author:     Jérôme Gardou <jerome.gar...@reactos.org>
AuthorDate: Thu Apr 22 11:11:34 2021 +0200
Commit:     Jérôme Gardou <zefk...@users.noreply.github.com>
CommitDate: Wed Apr 28 13:10:23 2021 +0200

    [PSEH] Add implementation for GCC amd64
    
    Also, put include directory next to the library and use
    target_include_directories(.. INTERFACE ..) to get this right.
    This is because :
     - Having includes & implementation in two different places buggers me
     - This makes sure that there is no "if it compiles everything is fine" 
behaviour from anyone
       because now even static libraries need it for GCC amd64 build
    Also add __USE_PSEH2__ define for the non SEH-aware compilers out there and 
use it in a few headers
    where we define macros involving __try
---
 modules/rostests/apitests/include/apitest.h        |  23 ++-
 sdk/cmake/host-tools.cmake                         |   1 +
 sdk/include/psdk/rpc.h                             |   4 +-
 sdk/include/reactos/libs/pseh/pseh2_64.h           |  37 -----
 sdk/include/reactos/wine/exception.h               |  18 ++-
 sdk/lib/pseh/CMakeLists.txt                        |  17 ++-
 .../reactos/libs => lib/pseh/include}/pseh/excpt.h |   0
 .../libs => lib/pseh/include}/pseh/framebased.h    |   0
 .../pseh/include}/pseh/framebased/internal.h       |   0
 .../reactos/libs => lib/pseh/include}/pseh/pseh.h  |   0
 .../reactos/libs => lib/pseh/include}/pseh/pseh2.h |   4 +
 sdk/lib/pseh/include/pseh/pseh2_64.h               | 169 +++++++++++++++++++++
 .../reactos/libs => lib/pseh/include}/pseh/pseh3.h |   0
 sdk/tools/CMakeLists.txt                           |   7 +-
 14 files changed, 230 insertions(+), 50 deletions(-)

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 <wine/test.h>
 #undef WIN32_NO_STATUS
 
-#include <pseh/pseh2.h>
-
 /* See kmtests/include/kmt_test.h */
 #define InvalidPointer ((PVOID)0x5555555555555555ULL)
 // #define InvalidPointer ((PVOID)0x0123456789ABCDEFULL)
 
+#ifdef __USE_PSEH2__
+#include <pseh/pseh2.h>
+
 #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  <pseh/pseh2.h>
 #endif
 
@@ -122,7 +122,7 @@ typedef int RPC_STATUS;
     #include <excpt.h>
     #include <winerror.h>
 
-    #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 <setjmp.h>
 #include <intrin.h>
-#include <pseh/pseh2.h>
-#include <pseh/excpt.h>
+#ifdef __USE_PSEH2__
+# include <pseh/pseh2.h>
+# include <pseh/excpt.h>
+#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=$<TARGET_FILE:native-gcc_plugin_seh>)
 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")

Reply via email to