From dcc3ed498549e8680e3eb20006beeb73e15038d3 Mon Sep 17 00:00:00 2001 From: Timo Kreuzer Date: Sat, 25 Aug 2012 22:19:02 +0000 Subject: [PATCH] [PSEH2] PSEH2 uses a special mechanism to deal with nested try blocks inside the same function. Instead of pushing a second exception registration record on the exception list, it uses an internal pointer to handle the different try-levels. But when a function using SEH is inlined, the resulting code will push 2 registration frames on the stack. Now it happens with GCC 4.7.1 that these frames get shuffled on the stack, putting one for the inner try on a higher stack address. This is something that RtlUnwind regards as a bug and throws a STATUS_INVALID_UNWIND_TARGET exception. This was the reason for the crashing PSEH2_TEST, when compiled with GCC 4.7.1. To fix this, I added a mechanism that will prevent functions using SEH from being inlined. svn path=/trunk/; revision=57159 --- reactos/include/reactos/libs/pseh/pseh2.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/reactos/include/reactos/libs/pseh/pseh2.h b/reactos/include/reactos/libs/pseh/pseh2.h index 03256bcb24e..6b1a35190db 100644 --- a/reactos/include/reactos/libs/pseh/pseh2.h +++ b/reactos/include/reactos/libs/pseh/pseh2.h @@ -110,6 +110,14 @@ extern void __cdecl _SEH2Return(void); } #endif +/* Prevent gcc from inlining functions that use SEH. */ +#if ((__GNUC__ >= 4) && (__GNUC_MINOR__ >= 7)) +extern inline __attribute__((always_inline)) __attribute__((returns_twice)) void _SEH_DontInline() {} +#define __PREVENT_GCC_FROM_INLINING_SEH_FUNCTIONS() _SEH_DontInline(); +#else +#define __PREVENT_GCC_FROM_INLINING_SEH_FUNCTIONS() +#endif + /* A no-op side effect that scares GCC */ #define __SEH_SIDE_EFFECT __asm__ __volatile__("#") @@ -246,6 +254,7 @@ extern void __cdecl _SEH2Return(void); auto __SEH_DECLARE_FINALLY(_SEHFinally); #define _SEH2_TRY \ + __PREVENT_GCC_FROM_INLINING_SEH_FUNCTIONS() \ __SEH_BEGIN_SCOPE \ { \ __SEH_SCOPE_LOCALS; \