News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Use of RtlUnwind ?

Started by rags, August 29, 2009, 12:33:12 AM

Previous topic - Next topic

rags

Can anyone explain in plain English what the heck RtlUnwind is used for?

MSDN says: "Initiates an unwind of procedure call frames."

But what exactly is an unwind?

Thanks....Rags
God made Man, but the monkey applied the glue -DEVO

ecube

Something to do with exception handling

"Catching an exception using __try/__except SEH handler will result in RtlUnwind being called without exception record"

dedndave

it may have something to do with the prologue/epilogue
i bet Erol would know - lol

dedndave

here's a guess....
an error occurs
it finds a new esp value to balance the stack to the point prior to the call
restores ebp, ebx, esi, edi (maybe - lol)
in order to do that, it has to examine the prologue in order to find those values on the stack

MichaelW

eschew obfuscation

rags

Thank you for the link Michael.
God made Man, but the monkey applied the glue -DEVO

japheth

Hello,

I once had to write several test cases for SEH emulation in my DOS extender (HX). Perhaps this one is useful to seen what RtlUnwind() does:


;*** Win32 Exception Handling
;*** - without help from CRT
;*** - 2 exception handlers
;*** - RtlUnwind() is called

.386
.Model flat, stdcall
option casemap:none

WIN32_LEAN_AND_MEAN equ 1
.nolist
.nocref
if 0
include windows.inc
else
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\user32.inc
ExceptionRecord equ <pExceptionRecord>
endif
.cref
.list

;--- 1=continue search,0=continue execution

?CONTINUE1 equ 1 ;action in unhandled exception handler
?CONTINUE2 equ 0 ;action in first exception handler
?CONTINUE3 equ 1 ;action in second exception handler

XCPT_CONTINUE_EXECUTION equ 0
XCPT_CONTINUE_SEARCH    equ 1

CStr macro text
local l
.const
l db text, 0
.code
exitm <offset l>
endm

.data

g_hConOut HANDLE 0

.code

assume fs:nothing

printf proc c pszFormat:ptr byte, args:VARARG

local dwWritten:dword
local szText[256]:byte

invoke wvsprintfA, addr szText, pszFormat, addr args
lea ecx, dwWritten
invoke WriteConsole, g_hConOut, addr szText, eax, ecx, 0
ret
align 4
       
printf endp

myuef proc stdcall pEP:ptr EXCEPTION_POINTERS

mov ecx, pEP
mov ecx, [ecx].EXCEPTION_POINTERS.ExceptionRecord
invoke printf, CStr(<"myuef: pExcRecord=%X code=%X flags=%X addr=%X, ebp=%X",13,10>), ecx, \
[ecx].EXCEPTION_RECORD.ExceptionCode,\
[ecx].EXCEPTION_RECORD.ExceptionFlags,\
[ecx].EXCEPTION_RECORD.ExceptionAddress,\
dword ptr [ebp+0]
if ?CONTINUE1
mov eax, EXCEPTION_CONTINUE_SEARCH
else
mov eax, EXCEPTION_CONTINUE_EXECUTION
endif
ret
align 4

myuef endp

DispExcFrame proc uses esi

mov esi, fs:[0]
.while (1)
.if (esi != -1)
invoke printf, CStr(<"eh frame %X, handler=%X",13,10>),esi, dword ptr [esi+4]
.else
invoke printf, CStr(<"eh frame %X",13,10>), esi
.break
.endif
mov esi,[esi+0]
.endw
ret
align 4

DispExcFrame endp

main2_eh proc c pReport:ptr EXCEPTION_RECORD, pFrame:ptr, pContext:ptr CONTEXT
mov ecx, pReport
invoke printf, CStr(<"main2_eh: ebp=%X pExcRecord=%X [code=%X flags=%X prevRec=%X addr=%X], [ebp]=%X",13,10>), ebp, ecx,\
[ecx].EXCEPTION_RECORD.ExceptionCode,\
[ecx].EXCEPTION_RECORD.ExceptionFlags,\
[ecx].EXCEPTION_RECORD.ExceptionRecord,\
[ecx].EXCEPTION_RECORD.ExceptionAddress, \
dword ptr [ebp+0]
if ?CONTINUE3
mov eax, XCPT_CONTINUE_SEARCH
else
mov eax, XCPT_CONTINUE_EXECUTION
endif
ret
align 4
main2_eh endp

main2 proc c

local var1:dword

invoke printf, CStr(<"main2: ebp=%X",13,10>), ebp
push offset main2_eh
push dword ptr fs:[0]
mov fs:[0],esp
call DispExcFrame
invoke RaiseException, 0E2003456h, 0, 0, 0
pop dword ptr fs:[0]
pop ecx
invoke printf, CStr(<"main2: exit, ebp=%X",13,10>), ebp
ret
align 4

main2  endp

main_eh proc c pReport:ptr EXCEPTION_RECORD, pFrame:ptr, pContext:ptr CONTEXT

mov ecx, pReport
invoke printf, CStr(<"main_eh: ebp=%X pExcRecord=%X [code=%X flags=%X prevRec=%X addr=%X], [ebp]=%X",13,10>), ebp, ecx,\
[ecx].EXCEPTION_RECORD.ExceptionCode,\
[ecx].EXCEPTION_RECORD.ExceptionFlags,\
[ecx].EXCEPTION_RECORD.ExceptionRecord,\
[ecx].EXCEPTION_RECORD.ExceptionAddress,\
dword ptr [ebp+0]
mov ecx, pContext
invoke printf, CStr(<"main_eh: context.flags=%X",13,10>), [ecx].CONTEXT.ContextFlags
if ?CONTINUE2
mov eax, XCPT_CONTINUE_SEARCH
else
invoke printf, CStr(<"main_eh: calling RtlUnwind()",13,10>)
invoke RtlUnwind, pFrame, returnaddr, NULL, 0
returnaddr:
invoke printf, CStr(<"main_eh: back from RtlUnwind()",13,10>)
mov eax, XCPT_CONTINUE_EXECUTION
endif
ret
align 4

main_eh endp

main proc c

local var1:dword

invoke GetStdHandle, STD_OUTPUT_HANDLE
mov g_hConOut, eax
invoke GetModuleHandle, CStr("KERNEL32")
.if (eax)
invoke GetProcAddress, eax, CStr("UnhandledExceptionFilter")
invoke printf, CStr(<"GetProcAddress('UnhandledExceptionFilter')=%X",13,10>),eax
.endif
invoke SetUnhandledExceptionFilter, offset myuef
invoke printf, CStr(<"SetUnhandledExceptionFilter(%X)=%X",13,10>), myuef, eax
invoke printf, CStr(<"main: ebp=%X",13,10>), ebp
push offset main_eh
push dword ptr fs:[0]
mov fs:[0],esp
call DispExcFrame
call main2
pop dword ptr fs:[0]
pop ecx
invoke printf, CStr(<"main: exit, ebp=%X",13,10>), ebp
ret
align 4

main endp

mainCRTStartup proc c
call main
invoke ExitProcess, 0
mainCRTStartup endp

end mainCRTStartup