ReactOS 0.4.16-dev-1946-g52006dd
pseh3.c File Reference
#include <stdarg.h>
#include <windef.h>
#include <winnt.h>
#include "pseh3.h"
#include "pseh3_asmdef.h"
Include dependency graph for pseh3.c:

Go to the source code of this file.

Macros

#define _SEH3   $_FRAME_ALL_NONVOLATILES 1
 
#define ASSERT(exp)   if (!(exp)) __int2c();
 

Enumerations

enum  { _SEH3$_NESTED_HANDLER = 0 , _SEH3$_CPP_HANDLER = 1 , _SEH3$_CLANG_HANDLER = 2 }
 

Functions

 C_ASSERT (SEH3_REGISTRATION_FRAME_Next==FIELD_OFFSET(SEH3$_REGISTRATION_FRAME, Next))
 
 C_ASSERT (SEH3_REGISTRATION_FRAME_Handler==FIELD_OFFSET(SEH3$_REGISTRATION_FRAME, Handler))
 
 C_ASSERT (SEH3_REGISTRATION_FRAME_ScopeTable==FIELD_OFFSET(SEH3$_REGISTRATION_FRAME, ScopeTable))
 
 C_ASSERT (SEH3_REGISTRATION_FRAME_TryLevel==FIELD_OFFSET(SEH3$_REGISTRATION_FRAME, TryLevel))
 
 C_ASSERT (SEH3_REGISTRATION_FRAME_EndOfChain==FIELD_OFFSET(SEH3$_REGISTRATION_FRAME, EndOfChain))
 
 C_ASSERT (SEH3_REGISTRATION_FRAME_ExceptionPointers==FIELD_OFFSET(SEH3$_REGISTRATION_FRAME, ExceptionPointers))
 
 C_ASSERT (SEH3_REGISTRATION_FRAME_ExceptionCode==FIELD_OFFSET(SEH3$_REGISTRATION_FRAME, ExceptionCode))
 
 C_ASSERT (SEH3_REGISTRATION_FRAME_Esp==FIELD_OFFSET(SEH3$_REGISTRATION_FRAME, Esp))
 
 C_ASSERT (SEH3_REGISTRATION_FRAME_Ebp==FIELD_OFFSET(SEH3$_REGISTRATION_FRAME, Ebp))
 
 C_ASSERT (SEH3_REGISTRATION_FRAME_AllocaFrame==FIELD_OFFSET(SEH3$_REGISTRATION_FRAME, AllocaFrame))
 
 C_ASSERT (SEH3_REGISTRATION_FRAME_Ebx==FIELD_OFFSET(SEH3$_REGISTRATION_FRAME, Ebx))
 
 C_ASSERT (SEH3_REGISTRATION_FRAME_Esi==FIELD_OFFSET(SEH3$_REGISTRATION_FRAME, Esi))
 
 C_ASSERT (SEH3_REGISTRATION_FRAME_Edi==FIELD_OFFSET(SEH3$_REGISTRATION_FRAME, Edi))
 
 C_ASSERT (SEH3_SCOPE_TABLE_Filter==FIELD_OFFSET(SEH3$_SCOPE_TABLE, Filter))
 
 C_ASSERT (SEH3_SCOPE_TABLE_Target==FIELD_OFFSET(SEH3$_SCOPE_TABLE, Target))
 
void __attribute__ ((regparm(1)))
 
static LONG _SEH3$_InvokeNestedFunctionFilter (volatile SEH3$_REGISTRATION_FRAME *RegistrationFrame, PVOID Filter)
 
static LONG _SEH3$_GetFilterResult (PSEH3$_REGISTRATION_FRAME Record, int HandlerType)
 
static VOID _SEH3$_CallFinally (PSEH3$_REGISTRATION_FRAME Record, int HandlerType)
 
 __attribute__ ((noreturn))
 
void __fastcall _SEH3$_CallRtlUnwind (PSEH3$_REGISTRATION_FRAME RegistrationFrame)
 
int __cdecl __attribute__ ((__target__("cld")))
 
int __cdecl _SEH3$_C_except_handler (struct _EXCEPTION_RECORD *ExceptionRecord, PSEH3$_REGISTRATION_FRAME EstablisherFrame, struct _CONTEXT *ContextRecord, void *DispatcherContext)
 
int __cdecl _SEH3$_CPP_except_handler (struct _EXCEPTION_RECORD *ExceptionRecord, PSEH3$_REGISTRATION_FRAME EstablisherFrame, struct _CONTEXT *ContextRecord, void *DispatcherContext)
 
void __stdcall _SEH3$_longjmp_unwind (_JUMP_BUFFER *_Buf)
 

Macro Definition Documentation

◆ _SEH3

#define _SEH3   $_FRAME_ALL_NONVOLATILES 1

Definition at line 34 of file pseh3.c.

◆ ASSERT

#define ASSERT (   exp)    if (!(exp)) __int2c();

Definition at line 40 of file pseh3.c.

Enumeration Type Documentation

◆ anonymous enum

anonymous enum
Enumerator
_SEH3$_NESTED_HANDLER 
_SEH3$_CPP_HANDLER 
_SEH3$_CLANG_HANDLER 

Definition at line 67 of file pseh3.c.

68{
72};
@ _SEH3$_CLANG_HANDLER
Definition: pseh3.c:71
@ _SEH3$_CPP_HANDLER
Definition: pseh3.c:70
@ _SEH3$_NESTED_HANDLER
Definition: pseh3.c:69

Function Documentation

◆ __attribute__() [1/3]

int __cdecl __attribute__ ( (__target__("cld"))  )

Definition at line 322 of file pseh3.c.

330{
331 PSEH3$_REGISTRATION_FRAME CurrentFrame, TargetFrame;
332 SEH3$_EXCEPTION_POINTERS ExceptionPointers;
333 LONG FilterResult;
334
335 /* Clear the direction flag. */
336 asm volatile ("cld" : : : "memory");
337
338 /* Save the exception pointers on the stack */
339 ExceptionPointers.ExceptionRecord = ExceptionRecord;
340 ExceptionPointers.ContextRecord = ContextRecord;
341
342 /* Check if this is an unwind */
343 if (IS_UNWINDING(ExceptionRecord->ExceptionFlags))
344 {
345 /* Unwind all local frames */
346 TargetFrame = EstablisherFrame->Next;
347 }
348 else
349 {
350 /* Loop all frames for this registration */
351 CurrentFrame = EstablisherFrame->EndOfChain;
352 for (;;)
353 {
354 /* Check if we have an exception handler */
355 if (CurrentFrame->ScopeTable->Target != NULL)
356 {
357 /* Set exception pointers and code for this frame */
358 CurrentFrame->ExceptionPointers = &ExceptionPointers;
359 CurrentFrame->ExceptionCode = ExceptionRecord->ExceptionCode;
360
361 /* Get the filter result */
362 FilterResult = _SEH3$_GetFilterResult(CurrentFrame, HandlerType);
363
364 /* Check, if continuuing is requested */
365 if (FilterResult == EXCEPTION_CONTINUE_EXECUTION)
366 {
368 }
369
370 /* Check if the except handler shall be executed */
371 if (FilterResult == EXCEPTION_EXECUTE_HANDLER) break;
372 }
373
374 /* Bail out if this is the last handler */
375 if (CurrentFrame == EstablisherFrame)
377
378 /* Go to the next frame */
379 CurrentFrame = CurrentFrame->Next;
380 }
381
382 /* Call RtlUnwind to unwind the frames below this one */
384
385 /* Do a local unwind up to this frame */
386 TargetFrame = CurrentFrame;
387 }
388
389 /* Loop frames up to the target frame */
390 for (CurrentFrame = EstablisherFrame->EndOfChain;
391 CurrentFrame != TargetFrame;
392 CurrentFrame = CurrentFrame->Next)
393 {
394 /* Manually unregister the frame */
395 _SEH3$_Unregister(CurrentFrame);
396
397 /* Check if this is an unwind frame */
398 if (CurrentFrame->ScopeTable->Target == NULL)
399 {
400 /* Set exception pointers and code for this frame */
401 CurrentFrame->ExceptionPointers = &ExceptionPointers;
402 CurrentFrame->ExceptionCode = ExceptionRecord->ExceptionCode;
403
404 /* Call the finally function */
405 _SEH3$_CallFinally(CurrentFrame, HandlerType);
406 }
407 }
408
409 /* Check if this was an unwind */
410 if (ExceptionRecord->ExceptionFlags & EXCEPTION_UNWINDING)
411 {
413 }
414
415 /* Unregister the frame. It will be unregistered again at the end of the
416 __except block, due to auto cleanup, but that doesn't hurt.
417 All we do is set either fs:[0] or EstablisherFrame->EndOfChain to
418 CurrentFrame->Next, which will not change it's value. */
419 _SEH3$_Unregister(CurrentFrame);
420
421 /* Jump to the __except block (does not return) */
422 _SEH3$_JumpToTarget(CurrentFrame);
423}
ACPI_PHYSICAL_ADDRESS ACPI_SIZE BOOLEAN Warn UINT32 *TableIdx UINT32 ACPI_TABLE_HEADER *OutTableHeader ACPI_TABLE_HEADER **OutTable ACPI_HANDLE UINT32 ACPI_WALK_CALLBACK ACPI_WALK_CALLBACK void void **ReturnValue UINT32 ACPI_BUFFER *RetPathPtr ACPI_OBJECT_HANDLER void *Data ACPI_OBJECT_HANDLER void **Data ACPI_STRING ACPI_OBJECT_LIST ACPI_BUFFER *ReturnObjectBuffer ACPI_DEVICE_INFO **ReturnBuffer ACPI_HANDLE ACPI_HANDLE ACPI_HANDLE *OutHandle ACPI_HANDLE *OutHandle void *Context void *Context ACPI_EVENT_HANDLER Handler UINT32 UINT32 ACPI_GPE_HANDLER void *Context UINT32 HandlerType
Definition: acpixf.h:817
#define NULL
Definition: types.h:112
@ ExceptionContinueSearch
Definition: compat.h:91
@ ExceptionContinueExecution
Definition: compat.h:90
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:90
#define EXCEPTION_CONTINUE_EXECUTION
Definition: excpt.h:92
_IRQL_requires_same_ _In_ PVOID EstablisherFrame
Definition: ntbasedef.h:665
_IRQL_requires_same_ _In_ PVOID _Inout_ struct _CONTEXT * ContextRecord
Definition: ntbasedef.h:666
long LONG
Definition: pedump.c:60
void __fastcall _SEH3$_CallRtlUnwind(PSEH3$_REGISTRATION_FRAME RegistrationFrame)
static VOID _SEH3$_CallFinally(PSEH3$_REGISTRATION_FRAME Record, int HandlerType)
Definition: pseh3.c:259
static LONG _SEH3$_GetFilterResult(PSEH3$_REGISTRATION_FRAME Record, int HandlerType)
Definition: pseh3.c:232
struct _CONTEXT * ContextRecord
Definition: pseh3.h:35
struct _EXCEPTION_RECORD * ExceptionRecord
Definition: pseh3.h:34
PSEH3$_EXCEPTION_POINTERS volatile ExceptionPointers
Definition: pseh3.h:54
struct _SEH3$_REGISTRATION_FRAME * EndOfChain
Definition: pseh3.h:51
PSEH3$_SCOPE_TABLE ScopeTable
Definition: pseh3.h:45
unsigned long ExceptionCode
Definition: pseh3.h:61
struct _SEH3$_REGISTRATION_FRAME * Next
Definition: pseh3.h:41
#define IS_UNWINDING(Flag)
Definition: rtltypes.h:164
#define EXCEPTION_UNWINDING
Definition: rtltypes.h:155

◆ __attribute__() [2/3]

__attribute__ ( (noreturn)  )

Definition at line 266 of file pseh3.c.

271{
272#ifdef __clang__
273 asm volatile (
274 /* Load the registers */
275 "movl 24(%%ecx), %%esp\n\t"
276 "movl 28(%%ecx), %%ebp\n\t"
277
278 "movl 36(%%ecx), %%ebx\n\t"
279 "movl 40(%%ecx), %%esi\n\t"
280 "movl 44(%%ecx), %%edi\n\t"
281
282 /* Stack pointer is 4 off from the call to __SEH3$_RegisterFrame */
283 "addl $4, %%esp\n\t"
284
285 /* Jump into the exception handler */
286 "jmp *%[Target]"
287 : :
288 "c" (RegistrationFrame),
289 "a" (RegistrationFrame->ScopeTable),
290 [Target] "m" (RegistrationFrame->ScopeTable->Target)
291 );
292#else
293 asm volatile (
294 /* Load the registers */
295 "movl 24(%%ecx), %%esp\n\t"
296 "movl 28(%%ecx), %%ebp\n\t"
297
298 /* Stack pointer is 4 off from the call to __SEH3$_RegisterFrame */
299 "addl $4, %%esp\n\t"
300
301 /* Jump into the exception handler */
302 "jmp *%[Target]"
303 : :
304 "c" (RegistrationFrame),
305 "a" (RegistrationFrame->ScopeTable),
306 [Target] "m" (RegistrationFrame->ScopeTable->Target)
307 );
308#endif
309
310 __builtin_unreachable();
311}
_In_ WDFIOTARGET Target
Definition: wdfrequest.h:306

◆ __attribute__() [3/3]

void __attribute__ ( (regparm(1))  )

Definition at line 75 of file pseh3.c.

78{
79 volatile SEH3$_REGISTRATION_FRAME *CurrentFrame;
80
81 /* Check if the frame has a handler (then it's the registered frame) */
82 if (Frame->Handler != NULL)
83 {
84 /* There shouldn't be any more nested try-level frames */
85 ASSERT(Frame->EndOfChain == Frame);
86
87 /* During unwinding on Windows ExecuteHandler2 installs its own EH frame,
88 so there can be one or even multiple frames before our own one and we
89 need to search for the link that points to our head frame. */
90 CurrentFrame = (SEH3$_REGISTRATION_FRAME*)__readfsdword(0);
91 if (Frame == CurrentFrame)
92 {
93 /* The target frame is the first installed frame, remove it */
94 __writefsdword(0, (ULONG)Frame->Next);
95 return;
96 }
97
98 /* Loop to find the frame that links the target frame */
99 while (CurrentFrame->Next != Frame)
100 {
101 CurrentFrame = CurrentFrame->Next;
102 }
103
104 /* Remove the frame from the linked list */
105 CurrentFrame->Next = Frame->Next;
106 }
107 else
108 {
109 /* Search for the head frame */
110 CurrentFrame = Frame->Next;
111 while (CurrentFrame->Handler == NULL)
112 {
113 CurrentFrame = CurrentFrame->Next;
114 }
115
116 /* Make sure the head frame points to our frame */
117 ASSERT(CurrentFrame->EndOfChain == Frame);
118
119 /* Remove this frame from the internal linked list */
120 CurrentFrame->EndOfChain = Frame->Next;
121 }
122}
HRESULT Next([in] ULONG celt, [out, size_is(celt), length_is(*pceltFetched)] STATPROPSETSTG *rgelt, [out] ULONG *pceltFetched)
PPC_QUAL void __writefsdword(const unsigned long Offset, const unsigned long Data)
Definition: intrin_ppc.h:354
PPC_QUAL unsigned long __readfsdword(const unsigned long Offset)
Definition: intrin_ppc.h:382
#define ASSERT(exp)
Definition: pseh3.c:40
uint32_t ULONG
Definition: typedefs.h:59

◆ _SEH3$_C_except_handler()

int __cdecl _SEH3$_C_except_handler ( struct _EXCEPTION_RECORD ExceptionRecord,
PSEH3$_REGISTRATION_FRAME  EstablisherFrame,
struct _CONTEXT ContextRecord,
void DispatcherContext 
)

Definition at line 427 of file pseh3.c.

432{
433#ifdef __clang__
434 return _SEH3$_common_except_handler(ExceptionRecord, EstablisherFrame, ContextRecord, DispatcherContext, _SEH3$_CLANG_HANDLER);
435#else
436 return _SEH3$_common_except_handler(ExceptionRecord, EstablisherFrame, ContextRecord, DispatcherContext, _SEH3$_NESTED_HANDLER);
437#endif
438}
_IRQL_requires_same_ _In_ PVOID _Inout_ struct _CONTEXT _In_ PVOID DispatcherContext
Definition: ntbasedef.h:667

Referenced by _SEH3$_longjmp_unwind().

◆ _SEH3$_CallFinally()

static VOID _SEH3$_CallFinally ( PSEH3$_REGISTRATION_FRAME  Record,
int  HandlerType 
)
inlinestatic

Definition at line 259 of file pseh3.c.

262{
263 _SEH3$_InvokeFilter(Record, Record->ScopeTable->Filter, HandlerType);
264}
_In_ struct _KBUGCHECK_REASON_CALLBACK_RECORD * Record
Definition: ketypes.h:320

Referenced by __attribute__(), and _SEH3$_longjmp_unwind().

◆ _SEH3$_CallRtlUnwind()

void __fastcall _SEH3$_CallRtlUnwind ( PSEH3$_REGISTRATION_FRAME  RegistrationFrame)

Referenced by __attribute__().

◆ _SEH3$_CPP_except_handler()

int __cdecl _SEH3$_CPP_except_handler ( struct _EXCEPTION_RECORD ExceptionRecord,
PSEH3$_REGISTRATION_FRAME  EstablisherFrame,
struct _CONTEXT ContextRecord,
void DispatcherContext 
)

Definition at line 442 of file pseh3.c.

447{
448 return _SEH3$_common_except_handler(ExceptionRecord, EstablisherFrame, ContextRecord, DispatcherContext, _SEH3$_CPP_HANDLER);
449}

Referenced by _SEH3$_longjmp_unwind().

◆ _SEH3$_GetFilterResult()

static LONG _SEH3$_GetFilterResult ( PSEH3$_REGISTRATION_FRAME  Record,
int  HandlerType 
)
inlinestatic

Definition at line 232 of file pseh3.c.

235{
236 PVOID Filter = Record->ScopeTable->Filter;
237 LONG Result;
238
239 /* Check if we have a constant filter */
240 if (((ULONG)Filter & 0xFFFFFF00) == 0)
241 {
242 /* Lowest 8 bit are sign extended to give the result */
244 }
245 else
246 {
247 /* Call the filter function */
248 Result = _SEH3$_InvokeFilter(Record, Filter, HandlerType);
249 }
250
251 /* Normalize the result */
252 if (Result < 0) return EXCEPTION_CONTINUE_EXECUTION;
253 else if (Result > 0) return EXCEPTION_EXECUTE_HANDLER;
254 else return EXCEPTION_CONTINUE_SEARCH;
255}
_Must_inspect_result_ _In_opt_ PFLT_FILTER Filter
Definition: fltkernel.h:1801
#define EXCEPTION_CONTINUE_SEARCH
Definition: excpt.h:91
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:409
char CHAR
Definition: xmlstorage.h:175

Referenced by __attribute__().

◆ _SEH3$_InvokeNestedFunctionFilter()

static LONG _SEH3$_InvokeNestedFunctionFilter ( volatile SEH3$_REGISTRATION_FRAME RegistrationFrame,
PVOID  Filter 
)
inlinestatic

Definition at line 126 of file pseh3.c.

129{
130 LONG FilterResult;
131
132 asm volatile (
133 /* First call with param = 0 to get the frame layout */
134 "xorl %%ecx, %%ecx\n\t"
135 "xorl %%eax, %%eax\n\t"
136 "call *%[Filter]\n\t"
137
138 /* The result is the frame base address that we passed in (0) plus the
139 offset to the registration record. */
140 "negl %%eax\n\t"
141 "addl %[RegistrationFrame], %%eax\n\t"
142
143 /* Second call to get the filter result */
144 "mov $1, %%ecx\n\t"
145 "call *%[Filter]"
146 : "=a" (FilterResult)
147 : [RegistrationFrame] "m" (RegistrationFrame), [Filter] "m" (Filter)
148 : "ecx", "edx");
149
150 return FilterResult;
151}

◆ _SEH3$_longjmp_unwind()

void __stdcall _SEH3$_longjmp_unwind ( _JUMP_BUFFER *  _Buf)

Definition at line 453 of file pseh3.c.

454{
455 PSEH3$_REGISTRATION_FRAME RegisteredFrame = (PSEH3$_REGISTRATION_FRAME)_Buf->Registration;
456 PSEH3$_REGISTRATION_FRAME CurrentFrame;
457
458 /* Native SEH registers the EH frame at the start of the function, so a call to
459 _setjmp(3) will always save that EH frame. PSEH only registers the frame
460 when entering a try block, so a call to _setjmp outside of a try block
461 would save a previously installed EH frame, which can be of a different
462 type (e.g. native EH3/EH4). We need to check whether the frame is ours
463 by comparing its address to the saved ebp value, which marks the boundary
464 of the stack frame for the caller of _setjmp. */
465 if (_Buf->Registration > _Buf->Ebp)
466 {
467 /* The registration frame is not ours, we don't need to do anything */
468 return;
469 }
470
471 /* Loop all frames for this registration */
472 for (CurrentFrame = RegisteredFrame->EndOfChain;
473 CurrentFrame->TryLevel != _Buf->TryLevel;
474 CurrentFrame = CurrentFrame->Next)
475 {
476 /* Check if this is a termination handler */
477 if (CurrentFrame->ScopeTable->Target == NULL)
478 {
479 /* Call the termination handler */
480 if (RegisteredFrame->Handler == _SEH3$_C_except_handler)
481 {
482#ifdef __clang__
484#else
486#endif
487 }
488 else
489 {
490 ASSERT(CurrentFrame->Handler == _SEH3$_CPP_except_handler);
492 }
493 }
494 }
495}
if(dx< 0)
Definition: linetemp.h:194
int __cdecl _SEH3$_C_except_handler(struct _EXCEPTION_RECORD *ExceptionRecord, PSEH3$_REGISTRATION_FRAME EstablisherFrame, struct _CONTEXT *ContextRecord, void *DispatcherContext)
Definition: pseh3.c:427
int __cdecl _SEH3$_CPP_except_handler(struct _EXCEPTION_RECORD *ExceptionRecord, PSEH3$_REGISTRATION_FRAME EstablisherFrame, struct _CONTEXT *ContextRecord, void *DispatcherContext)
Definition: pseh3.c:442
struct _SEH3$_REGISTRATION_FRAME * PSEH3$_REGISTRATION_FRAME

◆ C_ASSERT() [1/15]

◆ C_ASSERT() [2/15]

◆ C_ASSERT() [3/15]

◆ C_ASSERT() [4/15]

◆ C_ASSERT() [5/15]

◆ C_ASSERT() [6/15]

◆ C_ASSERT() [7/15]

◆ C_ASSERT() [8/15]

◆ C_ASSERT() [9/15]

◆ C_ASSERT() [10/15]

◆ C_ASSERT() [11/15]

◆ C_ASSERT() [12/15]

◆ C_ASSERT() [13/15]

◆ C_ASSERT() [14/15]

◆ C_ASSERT() [15/15]