mirror of
https://github.com/reactos/reactos.git
synced 2025-02-21 16:04:57 +00:00
[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
This commit is contained in:
parent
d31856cda1
commit
ba74a05a17
14 changed files with 230 additions and 50 deletions
|
@ -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)
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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 }
|
||||
|
|
|
@ -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 */
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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;
|
169
sdk/lib/pseh/include/pseh/pseh2_64.h
Normal file
169
sdk/lib/pseh/include/pseh/pseh2_64.h
Normal file
|
@ -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
|
|
@ -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")
|
||||
|
|
Loading…
Reference in a new issue