Hi,
I'm trying to figure out how SEH works and have written the following code. If I comment out the line that causes the exception it works but exit code is -1 not 0. Else the execution jumps to the ExceptHandler. The problem is the RtlUnwindEx function. An exception is thrown and I cannot figure out what is wrong.
OPTION DOTNAME ; required for macro files
option casemap:none ; case sensitive
include \masm32\include64\win64.inc ; main include file
include \masm32\macros64\vasily.inc ; main macro file
include \masm32\macros64\macros64.inc ; auxillary macro file
STACKFRAME ; create a default stack frame
include \masm32\m64lib\m64lib.inc ; include file for m64lib library
; ------------------------
; system API include64 files
; ------------------------
include \masm32\include64\kernel32.inc
include \masm32\include64\user32.inc
include \masm32\include64\msvcrt.inc
; ------------------------
; system API library files
; ------------------------
includelib \masm32\lib64\msvcrt.lib
dataSEH segment para ".data"
dataSEHStart label near
dataSEH ends
.data
.data?
retValue qword ?
exceptRecord EXCEPTION_RECORD <>
ExceptHandler proto
_SEH textequ <0>
__try macro
local try
try equ $
dataSEH segment
qword try
dataSEH ends
endm
__except macro
local except
except equ $+5
dataSEH segment
qword except
dataSEH ends
.code
%jmp near ptr @end
%@start:
endm
__endtryexcept macro
local endtryexcept
endtryexcept equ $
dataSEH segment
qword endtryexcept
dataSEH ends
.code
%@end:
endm
.code
entry_point proc frame:ExceptHandler
.endprolog
lea rax,dataSEHStart
__try
mov rax,0
mov rax,[rax]
__except
lea r8,exceptRecord
invoke __imp_printf,"exception code: %xh",qword ptr [r8].EXCEPTION_RECORD.ExceptionCode
__endtryexcept
invoke __imp_printf,"It works"
leave
xor rax,rax
call ExitProcess
ret
entry_point endp
OPTION PROLOGUE:PROLOGUEDEF
OPTION EPILOGUE:EPILOGUEDEF
ExceptHandler proc
local pExceptionRecord:ptr
local EstablisherFrame:qword
local pContextRecord:ptr
local pDispatcherContext:ptr
mov pExceptionRecord,rcx
mov EstablisherFrame,rdx
mov pContextRecord,r8
mov pDispatcherContext,r9
invoke RtlMoveMemory,addr exceptRecord,pExceptionRecord,sizeof EXCEPTION_RECORD
sub rsp, 16h
mov rcx,EstablisherFrame
lea rdx,dataSEHStart
add rdx,8
mov rdx,[rdx]
mov r8,pExceptionRecord
lea r9,retValue
mov rax,pContextRecord
mov [rsp+20h],rax
mov rax, pDispatcherContext
mov rax, [rax].DISPATCHER_CONTEXT.HistoryTable
mov [rsp+28h], rax
call RtlUnwindEx
add rsp, 16h
xor eax,eax
mov rsp,rbp
pop rbp
ret
ExceptHandler endp
end
Is there anyone who can explain what the problems are.
Best regards
The problem is not solved yet. Now I have three functions. An ordinary entry_point function, a TestProc function with a guarded part and an exception handler.
STACKFRAME
entry_point proc
local buf[30h]:byte
local var:qword
mov rdi,500h ;to test preservation
mov rsi,300h
invoke lstrcpy,addr buf,"First string from entry_point\n"
lea rax,buf
mov var,rax
invoke TestProc,addr retValue,EXCEPTION_UNWIND,500h,addr buf,addr var
invoke __imp_printf,addr buf
invoke ExitProcess,0
ret
entry_point endp
Now to the TestProc function.
NOSTACKFRAME
TestProc proc frame:ExceptHandler arg1:ptr, arg2:qword, arg3:dword, pBuf:ptr, pVar:ptr
push_reg rbp
mov rbp,rsp
set_frame rbp,0
push_reg rsi
push_reg rdi
alloc_stack 20h+30h
.endprolog
mov pBuf,r9
mov arg3,r8d
mov arg2,rdx
mov arg1,rcx
mov rdi,600h
mov rsi,400h
__try
mov rax,0
mov rax,[rax] ;exception
__except
invoke lstrcat,r9,"exception appended\n"
__endtryexcept
invoke lstrcat,r9,"string appended\n\n"
pop rdi
pop rsi
add rsp,20h+30h
leave
pop r9 ;jmp back instead of return
jmp r9
ret
TestProc endp
If exception is comment out it works. However if the function has locals or/and arguments there is no ret compiled. Must be a bug. Insted pop and jmp.
So far it might be solved. Now to the exception handler
STACKFRAME
ExceptHandler proc pExceptionRecord:ptr,EstablisherFrame:qword,pContextRecord:ptr,pDispatcherContext:ptr
mov rcx,pExceptionRecord
.if dword ptr [rcx].EXCEPTION_RECORD64.ExceptionFlags == EXCEPTION_NONCONTINUABLE ; = 1
invoke ExitProcess,0
.EndIf
invoke RtlMoveMemory,addr exceptRecord,pExceptionRecord,sizeof EXCEPTION_RECORD
invoke RtlMoveMemory,addr exceptContext,pContextRecord,sizeof CONTEXT
mov rcx,EstablisherFrame
lea rdx,dataSEHStart
add rdx,8
mov rdx,[rdx]
lea r8,exceptRecord
mov r9,0 ;retValue
lea rax,exceptContext
mov [rsp+20h],rax
mov rax,pDispatcherContext
mov rax,qword ptr [rax].DISPATCHER_CONTEXT.HistoryTable
mov [rsp+28h],rax
call RtlUnwindEx
invoke ExitProcess,1 ;if ok, should not come here
ret
ExceptHandler endp
Whatever I do the execution either goes to ExitProcess or back to the handler till it exits
Does anyone know anything about how to solve this?
Here is the code. I use vs2019 community.