1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
// Provenance of this code unclear. From crosswin32-dtrans-mingw.diff,
// but from where it got there, I don't know.
#ifndef INCLUDED_WNTGCCI_SEHANDLER_HXX
#define INCLUDED_WNTGCCI_SEHANDLER_HXX
#if !defined( __MINGW32__ ) || defined ( _WIN64 )
#error This file should be included only in a 32-bit MinGW compilation
#endif
#include <windows.h>
#include <setjmp.h>
#ifndef EH_UNWINDING
// See _EH_UNWINDING in MSVS9/VC/crt/src/except.inc
#define EH_UNWINDING 2
#endif
namespace {
class __SEHandler
{
public:
__SEHandler() {}
~__SEHandler() {}
typedef int (*PF)(void *, LPEXCEPTION_POINTERS);
typedef void (*PH)(void *, LPEXCEPTION_POINTERS);
typedef void (*PN)(void *);
void Set(jmp_buf jb, void *pdata=NULL, PF pfilter=NULL, PH phandlerbody=NULL, PN pfinal=NULL)
{
__builtin_memcpy(m_jmpbuf, jb, sizeof(jmp_buf));
m_pData=pdata;
switch (reinterpret_cast<int>(pfilter))
{
default:
m_filter=pfilter;
break;
case EXCEPTION_CONTINUE_EXECUTION:
m_filter=DefaultFilterContinueExecution;
break;
case EXCEPTION_EXECUTE_HANDLER:
m_filter=DefaultFilterExecuteHandler;
break;
case EXCEPTION_CONTINUE_SEARCH:
m_filter=DefaultFilterContinueSearch;
break;
}
if (phandlerbody)
m_handlerbody=phandlerbody;
else
m_handlerbody=DefaultHandler;
if (pfinal)
m_final=pfinal;
else
m_final=DefaultFinal;
m_ER.pHandlerClass = this;
m_ER.hp = handler;
asm("movl %%fs:0, %%eax\n\t"
"movl %%eax, %0": "=m" (m_ER.prev): : "%eax" );
asm("movl %0, %%eax\n\t"
"movl %%eax, %%fs:0": : "r" (&m_ER): "%eax" );
}
void Reset()
{
m_final(m_pData);
asm("movl %0, %%eax \n\t"
"movl %%eax, %%fs:0"
: : "m" (m_ER.prev): "%eax");
}
private:
__SEHandler(const __SEHandler&);
__SEHandler& operator=(const __SEHandler&);
struct _ER {
_ER* prev;
PEXCEPTION_HANDLER hp;
__SEHandler *pHandlerClass;
};
static EXCEPTION_DISPOSITION handler(struct _EXCEPTION_RECORD *pExceptionRecord,
void * EstablisherFrame,
struct _CONTEXT *ContextRecord,
void * /*DispatcherContext*/)
{
__SEHandler* pThis = reinterpret_cast< _ER * >(EstablisherFrame)->pHandlerClass;
if (pExceptionRecord->ExceptionFlags & EH_UNWINDING)
{
pThis->m_final(pThis->m_pData);
return ExceptionContinueSearch;
}
EXCEPTION_POINTERS ep={pExceptionRecord, ContextRecord};
switch (pThis->m_filter(pThis->m_pData, &ep))
{
case EXCEPTION_EXECUTE_HANDLER:
RtlUnwind(EstablisherFrame, &&__set_label, pExceptionRecord, 0);
__set_label:
pThis->m_handlerbody(pThis->m_pData, &ep);
ContextRecord->Ebp = pThis->m_jmpbuf[0];
ContextRecord->Eip = pThis->m_jmpbuf[1];
ContextRecord->Esp = pThis->m_jmpbuf[2];
return ExceptionContinueExecution;
case EXCEPTION_CONTINUE_SEARCH:
return ExceptionContinueSearch;
case EXCEPTION_CONTINUE_EXECUTION:
return ExceptionContinueExecution;
}
return ExceptionContinueExecution;
}
static int DefaultFilterContinueSearch(void *, LPEXCEPTION_POINTERS) { return EXCEPTION_CONTINUE_SEARCH; }
static int DefaultFilterContinueExecution(void *, LPEXCEPTION_POINTERS) { return EXCEPTION_CONTINUE_EXECUTION; }
static int DefaultFilterExecuteHandler(void *, LPEXCEPTION_POINTERS) { return EXCEPTION_EXECUTE_HANDLER; }
static void DefaultHandler(void *, LPEXCEPTION_POINTERS) {}
static void DefaultFinal(void *) {}
typedef int (*handler_p)(struct _EXCEPTION_RECORD *ExceptionRecord,
void * EstablisherFrame,
struct _CONTEXT *ContextRecord,
void * DispatcherContext);
_ER m_ER;
void *m_pData;
PN m_final;
PH m_handlerbody;
PF m_filter;
jmp_buf m_jmpbuf;
};
} // namespace {
#endif // INCLUDED_WNTGCCI_SEHANDLER_HXX
|