ReactOS  0.4.13-dev-257-gfabbd7c
framebased-gcchack.c
Go to the documentation of this file.
1 /*
2  Copyright (c) 2008 KJK::Hyperion
3 
4  Permission is hereby granted, free of charge, to any person obtaining a
5  copy of this software and associated documentation files (the "Software"),
6  to deal in the Software without restriction, including without limitation
7  the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  and/or sell copies of the Software, and to permit persons to whom the
9  Software is furnished to do so, subject to the following conditions:
10 
11  The above copyright notice and this permission notice shall be included in
12  all copies or substantial portions of the Software.
13 
14  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20  DEALINGS IN THE SOFTWARE.
21 */
22 
23 #define _NTSYSTEM_ /* removes dllimport attribute from RtlUnwind */
24 
25 #define STRICT
26 #include <windef.h>
27 #include <stdarg.h>
28 
29 #include <pseh/pseh2.h>
30 #include <excpt.h>
31 #include <intrin.h>
32 
33 #ifndef EXCEPTION_EXIT_UNWIND
34 #define EXCEPTION_EXIT_UNWIND 4
35 #endif
36 
37 #ifndef EXCEPTION_UNWINDING
38 #define EXCEPTION_UNWINDING 2
39 #endif
40 
41 extern DECLSPEC_NORETURN int __SEH2Handle(void *, void *, void *, void *, void *, void *);
42 extern int __cdecl __SEH2FrameHandler(struct _EXCEPTION_RECORD *, void *, struct _CONTEXT *, void *);
43 extern int __cdecl __SEH2UnwindHandler(struct _EXCEPTION_RECORD *, void *, struct _CONTEXT *, void *);
44 
45 typedef struct __SEHTrampoline
46 {
47  unsigned char STR_MovEcx;
48  unsigned char * STR_Closure;
49  unsigned char STR_Jmp;
50  unsigned char * STR_Function;
51 }
53 _SEHTrampoline_t;
54 
56 int _SEHIsTrampoline(_SEHTrampoline_t * trampoline_)
57 {
58  return trampoline_->STR_MovEcx == 0xb9 && trampoline_->STR_Jmp == 0xe9;
59 }
60 
62 void * _SEHFunctionFromTrampoline(_SEHTrampoline_t * trampoline_)
63 {
64  return (int)(trampoline_ + 1) + trampoline_->STR_Function;
65 }
66 
68 void * _SEHClosureFromTrampoline(_SEHTrampoline_t * trampoline_)
69 {
70  return trampoline_->STR_Closure;
71 }
72 
75 {
77 }
78 
81 {
82  frame->SER_Prev = _SEH2CurrentRegistration();
83  __writefsdword(0, (unsigned long)frame);
84 }
85 
88 {
89  __writefsdword(0, (unsigned long)_SEH2CurrentRegistration()->SER_Prev);
90 }
91 
94 {
95  __asm__ __volatile__
96  (
97  "push %%ebp\n\t"
98  "push $0\n\t"
99  "push $0\n\t"
100  "push $Return%=\n\t"
101  "push %[target]\n\t"
102  "call %c[RtlUnwind]\n"
103  "Return%=:\n\t"
104  "pop %%ebp" :
105  :
106  [target] "g" (target), [RtlUnwind] "g" (&RtlUnwind) :
107  "eax", "ebx", "ecx", "edx", "esi", "edi", "flags", "memory"
108  );
109 }
110 
111 static
112 __SEH_EXCEPT_RET _SEH2Except(_SEH2Frame_t * frame, volatile _SEH2TryLevel_t * trylevel, struct _EXCEPTION_POINTERS * ep)
113 {
114  void * filter = trylevel->ST_Filter;
115  void * context = NULL;
116  __SEH_EXCEPT_RET ret;
117 
118  if(filter == (void *)0)
119  return 0;
120 
121  if(filter == (void *)1)
122  return 1;
123 
124  if(filter == (void *)-1)
125  return -1;
126 
127  if(_SEHIsTrampoline((_SEHTrampoline_t *)filter))
128  {
129  context = _SEHClosureFromTrampoline((_SEHTrampoline_t *)filter);
130  filter = _SEHFunctionFromTrampoline((_SEHTrampoline_t *)filter);
131  }
132 
133  __asm__ __volatile__
134  (
135  "push %[ep]\n\t"
136  "push %[frame]\n\t"
137  "call *%[filter]\n\t"
138  "pop %%edx\n\t"
139  "pop %%edx" :
140  [ret] "=a" (ret) :
141  "c" (context), [filter] "r" (filter), [frame] "r" (frame), [ep] "r" (ep) :
142  "edx", "flags", "memory"
143  );
144 
145  return ret;
146 }
147 
148 static
149 void _SEH2Finally(_SEH2Frame_t * frame, volatile _SEH2TryLevel_t * trylevel)
150 {
151  if(trylevel->ST_Filter == NULL && trylevel->ST_Body != NULL)
152  {
153  void * body = trylevel->ST_Body;
154  void * context = NULL;
155 
156  if(_SEHIsTrampoline((_SEHTrampoline_t *)body))
157  {
158  context = _SEHClosureFromTrampoline((_SEHTrampoline_t *)body);
159  body = _SEHFunctionFromTrampoline((_SEHTrampoline_t *)body);
160  }
161 
162  __asm__ __volatile__("call *%1" : : "c" (context), "r" (body) : "eax", "edx", "flags", "memory");
163  }
164 }
165 
166 typedef struct __SEH2UnwindFrame
167 {
169  _SEH2Frame_t * SUF_Frame;
170  volatile _SEH2TryLevel_t * SUF_TargetTryLevel;
171 }
173 
174 static void _SEH2LocalUnwind(_SEH2Frame_t *, volatile _SEH2TryLevel_t *);
175 
176 extern
178 (
179  struct _EXCEPTION_RECORD * ExceptionRecord,
180  void * EstablisherFrame,
181  struct _CONTEXT * ContextRecord,
182  void * DispatcherContext
183 )
184 {
185  if(ExceptionRecord->ExceptionFlags & (EXCEPTION_EXIT_UNWIND | EXCEPTION_UNWINDING))
186  {
187  _SEH2UnwindFrame_t * unwindframe = CONTAINING_RECORD(EstablisherFrame, _SEH2UnwindFrame_t, SUF_Registration);
188  _SEH2LocalUnwind(unwindframe->SUF_Frame, unwindframe->SUF_TargetTryLevel);
189  *((void **)DispatcherContext) = EstablisherFrame;
191  }
192 
194 }
195 
196 static
197 void _SEH2LocalUnwind(_SEH2Frame_t * frame, volatile _SEH2TryLevel_t * dsttrylevel)
198 {
199  volatile _SEH2TryLevel_t * trylevel;
200  _SEH2UnwindFrame_t unwindframe;
201 
202  unwindframe.SUF_Frame = frame;
203  unwindframe.SUF_TargetTryLevel = dsttrylevel;
204 
205  unwindframe.SUF_Registration.SER_Handler = &__SEH2UnwindHandler;
206  __SEH2EnterFrame(&unwindframe.SUF_Registration);
207 
208  for(trylevel = frame->SF_TopTryLevel; trylevel && trylevel != dsttrylevel; trylevel = trylevel->ST_Next)
209  {
210  frame->SF_TopTryLevel = trylevel->ST_Next;
211  _SEH2Finally(frame, trylevel);
212  }
213 
215 }
216 
217 static DECLSPEC_NORETURN
218 void _SEH2Handle(_SEH2Frame_t * frame, volatile _SEH2TryLevel_t * trylevel)
219 {
220  volatile _SEH2HandleTryLevel_t * fulltrylevel = CONTAINING_RECORD(trylevel, _SEH2HandleTryLevel_t, SHT_Common);
221 
222  _SEH2GlobalUnwind(frame);
223  _SEH2LocalUnwind(frame, &fulltrylevel->SHT_Common);
224  frame->SF_TopTryLevel = fulltrylevel->SHT_Common.ST_Next;
225 
227  (
228  fulltrylevel->SHT_Common.ST_Body,
229  fulltrylevel->SHT_Esp,
230  fulltrylevel->SHT_Ebp,
231  fulltrylevel->SHT_Ebx,
232  fulltrylevel->SHT_Esi,
233  fulltrylevel->SHT_Edi
234  );
235 }
236 
237 extern
239 (
240  struct _EXCEPTION_RECORD * ExceptionRecord,
241  void * EstablisherFrame,
242  struct _CONTEXT * ContextRecord,
243  void * DispatcherContext
244 )
245 {
246  _SEH2Frame_t * frame;
247 
248  frame = EstablisherFrame;
249 
250  /* Unwinding */
251  if(ExceptionRecord->ExceptionFlags & (EXCEPTION_EXIT_UNWIND | EXCEPTION_UNWINDING))
252  {
253  _SEH2LocalUnwind(frame, NULL);
254  }
255  /* Handling */
256  else
257  {
258  int ret = 0;
259  volatile _SEH2TryLevel_t * trylevel;
261 
262  ep.ExceptionRecord = ExceptionRecord;
264 
265  frame->SF_Code = ExceptionRecord->ExceptionCode;
266 
267  for(trylevel = frame->SF_TopTryLevel; trylevel != NULL; trylevel = trylevel->ST_Next)
268  {
269  ret = _SEH2Except(frame, trylevel, &ep);
270 
271  if(ret < 0)
273  else if(ret > 0)
274  _SEH2Handle(frame, trylevel);
275  }
276  }
277 
279 }
280 
281 extern
282 void __cdecl _SEH2EnterFrame(_SEH2Frame_t * frame)
283 {
284  frame->SF_Registration.SER_Handler = __SEH2FrameHandler;
285  frame->SF_Code = 0;
286  __SEH2EnterFrame(&frame->SF_Registration);
287 }
288 
289 extern
290 int __cdecl _SEH2EnterFrameAndTrylevel(_SEH2Frame_t * frame, volatile _SEH2TryLevel_t * trylevel)
291 {
292  frame->SF_TopTryLevel = trylevel;
293  _SEH2EnterFrame(frame);
294  return 0;
295 }
296 
297 extern
299 {
301 }
302 
303 extern
305 {
306  _SEH2LocalUnwind(CONTAINING_RECORD(_SEH2CurrentRegistration(), _SEH2Frame_t, SF_Registration), NULL);
307  _SEH2LeaveFrame();
308 }
309 
310 /* EOF */
int __cdecl __SEH2FrameHandler(struct _EXCEPTION_RECORD *, void *, struct _CONTEXT *, void *)
DECLSPEC_NORETURN int __SEH2Handle(void *, void *, void *, void *, void *, void *)
FORCEINLINE void __cdecl __SEH2LeaveFrame(void)
FORCEINLINE _SEH2Registration_t *__cdecl _SEH2CurrentRegistration(void)
#define EXCEPTION_UNWINDING
_IRQL_requires_same_ _In_ PVOID EstablisherFrame
Definition: ntbasedef.h:660
#define __cdecl
Definition: accygwin.h:79
GLuint GLenum GLsizei GLsizei GLint GLint GLboolean packed
Definition: glext.h:9271
Definition: http.c:6587
unsigned char * STR_Closure
static __SEH_EXCEPT_RET _SEH2Except(_SEH2Frame_t *frame, volatile _SEH2TryLevel_t *trylevel, struct _EXCEPTION_POINTERS *ep)
NTSYSAPI VOID NTAPI RtlUnwind(_In_opt_ PVOID TargetFrame, _In_opt_ PVOID TargetIp, _In_opt_ PEXCEPTION_RECORD ExceptionRecord, _In_ PVOID ReturnValue)
Definition: except.c:47
FORCEINLINE void * _SEHFunctionFromTrampoline(_SEHTrampoline_t *trampoline_)
void __cdecl _SEH2EnterFrame(_SEH2Frame_t *frame)
#define DECLSPEC_NORETURN
Definition: ntbasedef.h:176
volatile _SEH2TryLevel_t * SUF_TargetTryLevel
void __cdecl _SEH2Return(void)
DWORD ExceptionCode
Definition: compat.h:196
struct __SEH2UnwindFrame _SEH2UnwindFrame_t
static void _SEH2Finally(_SEH2Frame_t *frame, volatile _SEH2TryLevel_t *trylevel)
_IRQL_requires_same_ _In_ PVOID _Inout_ struct _CONTEXT _In_ PVOID DispatcherContext
Definition: ntbasedef.h:661
__asm__("\t.globl GetPhys\n" "GetPhys:\t\n" "mflr 0\n\t" "stwu 0,-16(1)\n\t" "mfmsr 5\n\t" "andi. 6,5,0xffef\n\t" "mtmsr 6\n\t" "isync\n\t" "sync\n\t" "lwz 3,0(3)\n\t" "mtmsr 5\n\t" "isync\n\t" "sync\n\t" "lwz 0,0(1)\n\t" "addi 1,1,16\n\t" "mtlr 0\n\t" "blr")
typedef void struct _CONTEXT void *struct __SEH2Registration _SEH2Registration_t
smooth NULL
Definition: ftsmooth.c:416
unsigned char STR_MovEcx
#define FORCEINLINE
Definition: ntbasedef.h:221
PPC_QUAL unsigned long __readfsdword(const unsigned long Offset)
Definition: intrin_ppc.h:382
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
PCONTEXT ContextRecord
Definition: rtltypes.h:197
_SEH2Frame_t * SUF_Frame
unsigned char STR_Jmp
_SEH2Registration_t SUF_Registration
#define EXCEPTION_EXIT_UNWIND
FORCEINLINE void __cdecl __SEH2EnterFrame(_SEH2Registration_t *frame)
static DECLSPEC_NORETURN void _SEH2Handle(_SEH2Frame_t *frame, volatile _SEH2TryLevel_t *trylevel)
unsigned char * STR_Function
FORCEINLINE void _SEH2GlobalUnwind(void *target)
int __cdecl _SEH2UnwindHandler(struct _EXCEPTION_RECORD *ExceptionRecord, void *EstablisherFrame, struct _CONTEXT *ContextRecord, void *DispatcherContext)
_IRQL_requires_same_ _In_ PVOID _Inout_ struct _CONTEXT * ContextRecord
Definition: ntbasedef.h:661
int ret
FORCEINLINE void * _SEHClosureFromTrampoline(_SEHTrampoline_t *trampoline_)
int __cdecl __SEH2UnwindHandler(struct _EXCEPTION_RECORD *, void *, struct _CONTEXT *, void *)
void __cdecl _SEH2LeaveFrame(void)
int __cdecl _SEH2EnterFrameAndTrylevel(_SEH2Frame_t *frame, volatile _SEH2TryLevel_t *trylevel)
static const void * body(MD5_CTX *ctx, const void *data, unsigned long size)
Definition: md5.c:100
PPC_QUAL void __writefsdword(const unsigned long Offset, const unsigned long Data)
Definition: intrin_ppc.h:354
struct __SEHTrampoline __attribute__((packed))
int __cdecl _SEH2FrameHandler(struct _EXCEPTION_RECORD *ExceptionRecord, void *EstablisherFrame, struct _CONTEXT *ContextRecord, void *DispatcherContext)
GLenum target
Definition: glext.h:7315
DWORD ExceptionFlags
Definition: compat.h:197
PEXCEPTION_RECORD ExceptionRecord
Definition: rtltypes.h:196
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
Definition: glext.h:7005
static void _SEH2LocalUnwind(_SEH2Frame_t *, volatile _SEH2TryLevel_t *)