I am reading this article about the SEH on Windows. and here is the source code of myseh.cpp
I debugged myseh.cpp. I set 2 breakpoints at printf("Hello from an exception handler\n");
at line:24 and DWORD handler = (DWORD)_except_handler;
at line: 36 respectively.
Then I ran it and it broke at line:36. I saw the stack trace as follows.
As going, AccessViolationException occurred because of mov [eax], 1
Then it broke at line:24. I saw the stack trace as follows.
The same thread but the frame of main
was gone! Instead of _except_handle
. And ESP jumped from 0018f6c8
to 0018ef34
;it's a big gap between 0018f6c8
and 0018ef34
After Exception handled.
I know that _except_handle
must be run at user mode rather than kernel mode.
After _except_handle
returned, the thread turned to ring0 and then windows kernel modified CONTEXT EAX
to &scratch
& and then returned to ring3 . Thus thread ran continually.
I am curious about the mechanism of windows dealing with exception:
WHY the frame calling main
was gone?
WHY the ESP jumped from 0018f6c8
to 0018ef34
?(I mean a big pitch), Do those ESP address belong to same thread's stack??? Did the kernel play some tricks on ESP in ring3??? If so, WHY did it choose the address of 0018ef34
as handler callback's frame? Many thanks!
CONTEXT
andEXCEPTION_RECORD
to the user thread stack. off course bellow Esp of exception - for this already Esp serious decremented. and thenKiUserExceptionDispatcher
callback is called from kernel with pointer to this copiedCONTEXT
andEXCEPTION_RECORD
records. finally your_except_handler
called. but if you look forContextRecord->Esp
you can note that it will be exactly same asEsp
inmain()
. for real handlers implementation look\VC\crt\src\i386\chandler4.c
and\VC\crt\src\amd64\chandler.c
– ExtrusiveContextRecord->Esp==Esp in main()
.In fact, we ought to blame on debugger's default setting which loses stack trace. Btw,I know the modifiability of*ContextRecord
, that's the mean by which kernel recover context of hardware as you wish before back to ring3. but WHY is the 2nd paramExceptionRecord
of type*
rather thanconst *
? – HovercraftExceptionFlags
is modified during exception handling. we walk by stack two time ! first we looking for__try/__except
blocks, until some not returnEXCEPTION_EXECUTE_HANDLER
then_except_handlerX
calledRtlUnwindEx
which setEXCEPTION_UNWIND
flag inExceptionFlags
and again walk stack for__try/__finally
handlers. look forIS_DISPATCHING(Flag)
andIS_UNWINDING(Flag)
macro inwinnt.h
andwdm.h
- also studychandler.c
noteif (IS_DISPATCHING(ExceptionRecord->ExceptionFlags))
switch – ExtrusiveIS_TARGET_UNWIND
used in x64. simply_except_handler
frommyseh.cpp
is very primitive. real handlers which support__try/__except
and__try/__finally
subcalls is for complex and need modify (RtlUnwindEx
)ExceptionFlags
how minimum. also nestedExceptionRecord
too – Extrusive