https://git.reactos.org/?p=reactos.git;a=commitdiff;h=ba74a05a1761691ff4cc2…
commit ba74a05a1761691ff4cc20cd6e1804cb375c1e36
Author: Jérôme Gardou <jerome.gardou(a)reactos.org>
AuthorDate: Thu Apr 22 11:11:34 2021 +0200
Commit: Jérôme Gardou <zefklop(a)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")