hi,
I have a problem with understanding SEH directives. I've read about this issue on MSDN, but i'm not sure do i understood it correctly. As far as i know SEH directives are for handling exceptions. They write informations about procedure frames to xdata and pdata sections. And SEH directives are needed only for procs that are calling other procs.
For example if got proc Main which calls other proc that takes 8 params and Main uses its own params i think that proper prologue and epilogue should look like this:
.data
qwResult dq 0
.code
Main PROC FRAME 1st:QWORD, 2nd:QWORD
push rbp
.pushreg rbp
push rbx
.pushreg rbx
push rdi
.pushreg rdi
mov rbp, rsp
.setframe rbp, 0
sub rsp, 8*8
.allocstack 8*8
.endprolog
mov 1st, rcx
mov 2nd, rdx
xor ebx, ebx
mov qword ptr [rsp+7*8], rbx
mov qword ptr [rsp+6*8], rbx
mov qword ptr [rsp+5*8], rbx
mov qword ptr [rsp+4*8], rbx
mov r9, 100000h
mov r8, 10000h
mov rdx, 1000h
mov rcx, 100h
call EightParamProc
add rax, 1st
add rax, 2nd
mov qwResult, rax
add rsp, 8*8
pop rdi
pop rbx
pop rbp
ret
Main ENDP
END
Could someone correct me if wrong?
Thanks in advance.
Quote from: vogelsang on December 21, 2013, 10:34:36 PM
hi,
I have a problem with understanding SEH directives. I've read about this issue on MSDN, but i'm not sure do i understood it correctly. As far as i know SEH directives are for handling exceptions. They write informations about procedure frames to xdata and pdata sections. And SEH directives are needed only for procs that are calling other procs.
you could check the following link. (http://forum.nasm.us/index.php?topic=1763.0) It's NASM/YASM code, but should be easy to convert. Furthermore, JWasm has a 64 bit SEH example inside the Samples directory (Win64_3.asm). I hope that helps.
Gunther
I saw those examples but i have many lacks in nasm syntax and one example from jwasm is too little for me. I'll try to convert nasm example. Thanks for help.
Quote from: vogelsang on December 22, 2013, 12:18:50 AM
I saw those examples but i have many lacks in nasm syntax and one example from jwasm is too little for me. I'll try to convert nasm example. Thanks for help.
There's another JWasm example (Win64_3e.asm). The translation from NASM to MASM isn't hard. That'll (http://alien.dowling.edu/~rohit/nasmdoc0.html) give you enough help.
Gunther
Quote from: vogelsang on December 21, 2013, 10:34:36 PM
Could someone correct me if wrong?
I'd say your code looks good.
You can make jwasm tell in the listing file what it writes into .xdata and .pdata by adding the -Sg cmdline option.
Quote
I'd say your code looks good.
You write little about my understaning SEH directives, so i guess it's fine. I'll look at file listing. Maybe there i'll find out about that for sure. Thanks.
Quote from: vogelsang on December 22, 2013, 05:01:46 PM
You write little about my understaning SEH directives, so i guess it's fine.
Yes.
However, a second glance at your code reveals an error:
mov _1st, rcx
mov _2nd, rdx
If you setup your own frame AND want to access the proc's parameters by name, you have to comply to the rule that the frame pointer register has to point to the location where the old value is saved, immediately followed by the proc's return address and the proc's arguments.
That means, in your sample you should move the "push rbx" and "push rdi" lines BEHIND the "mov rbp, rsp".
SomeProc PROC
push rbp
mov rbp, rsp
...
True, i saw that piece of code at the start of procs in other sources. I need to complete my knowledge about stack frame. Thanks for pointing this.
Other thing, i've looked at file listing and found this fragment of code where is something about xdata and pdata sections. But i don't understand what this numbers mean. This is too advanced stuff for me but i'm curious. Could you explain a bit? Source is similiar to that from first post but not the same:
;--------MAKE-------------------------------------------------------------------------
;
; assembling:
; jwasm -win64 -Zp8 -Fl -Sg SEH.asm
; linking:
; link /SUBSYSTEM:CONSOLE SEH.obj
;
;--------DATA-------------------------------------------------------------------------
.DATA
00000000 * _DATA segment
* assume cs:ERROR
00000000 0000000000000000 qwResult dq 0
;--------CODE-------------------------------------------------------------------------
00000000 .CODE
00000008 * _DATA ends
00000000 * _TEXT segment
* assume cs:FLAT
00000000 mainCRTStartup PROC FRAME
00000000 4883EC28 sub rsp, 5*8
.allocstack 5*8
.endprolog
00000004 48C7C20A000000 mov rdx, 10
0000000B 48C7C11E000000 mov rcx, 30
00000012 E808000000 call TwoParamProc
00000017 33C9 xor ecx, ecx
00000019 FF1500000000 call __imp_ExitProcess
00000000 * .xdata segment align(8) flat read 'DATA'
00000000 * $xdatasym label near
00000000 01040100 * db 1t + (00h shl 3), 4t, 1t, 00h + (00h shl 4)
00000004 0442 * dw 04204h
00000006 0000 * align 4
00000008 * .xdata ends
00000000 * .pdata segment align(4) flat read 'DATA'
00000000 000000001F00000000* dd imagerel mainCRTStartup, imagerel mainCRTStartup+01Fh, imagerel $xdatasym+00h
0000000C * .pdata ends
0000001F mainCRTStartup ENDP
0000001F TwoParamProc PROC FRAME first:QWORD, second:QWORD
0000001F 55 push rbp
.pushreg rbp
00000020 488BEC mov rbp, rsp
.setframe rbp, 0
00000023 53 push rbx
.pushreg rbx
00000024 57 push rdi
.pushreg rdi
00000025 4883EC40 sub rsp, 8*8
.allocstack 8*8
.endprolog
00000029 48894D10 mov first, rcx
0000002D 48895518 mov second, rdx
00000031 33DB xor ebx, ebx
00000033 48895C2438 mov qword ptr [rsp+7*8], rbx
00000038 48895C2430 mov qword ptr [rsp+6*8], rbx
0000003D 48895C2428 mov qword ptr [rsp+5*8], rbx
00000042 48895C2420 mov qword ptr [rsp+4*8], rbx
00000047 49C7C100001000 mov r9, 100000h
0000004E 49C7C000000100 mov r8, 10000h
00000055 48C7C200100000 mov rdx, 1000h
0000005C 48C7C100010000 mov rcx, 100h
00000063 E817000000 call EightParamProc
00000068 48034510 add rax, first
0000006C 48034518 add rax, second
00000070 48890500000000 mov qwResult, rax
00000077 4883C440 add rsp, 8*8
0000007B 5F pop rdi
0000007C 5B pop rbx
0000007D 5D pop rbp
0000007E ret
0000007E C3 * retn
00000008 * .xdata segment
00000008 010A0505 * db 1t + (00h shl 3), 10t, 5t, 05h + (00h shl 4)
0000000C 0A7206700530045301* dw 0720ah, 07006h, 03005h, 05304h, 05001h
00000016 0000 * align 4
00000018 * .xdata ends
0000000C * .pdata segment
0000000C 000000006000000008* dd imagerel TwoParamProc, imagerel TwoParamProc+060h, imagerel $xdatasym+08h
00000018 * .pdata ends
0000007F TwoParamProc ENDP
0000007F EightParamProc PROC p1:QWORD, p2:QWORD, p3:QWORD, p4:QWORD, p5:QWORD, p6:QWORD, p7:QWORD, p8:QWORD
0000007F 55 * push rbp
00000080 488BEC * mov rbp, rsp
00000083 48C7C00A000000 mov rax, 10
0000008A ret
0000008A C9 * leave
0000008B C3 * retn
0000008C EightParamProc ENDP
END
0000008C * _TEXT ends
Edit 06:05:46 PM
Here was some code added, but I have some delusions :biggrin: and deleted it.
Quote from: vogelsang on December 23, 2013, 03:21:04 AM
Other thing, i've looked at file listing and found this fragment of code where is something about xdata and pdata sections. But i don't understand what this numbers mean. ... Could you explain a bit?
I forgot most of this stuff. But see file win64seh.h from jwasm's source:
/* some structures for Win64 SEH */
/* .pdata items */
typedef struct _IMAGE_RUNTIME_FUNCTION_ENTRY
{
uint_32 BeginAddress;
uint_32 EndAddress;
uint_32 UnwindData; /* RVA of UNWIND_INFO */
} IMAGE_RUNTIME_FUNCTION_ENTRY;
/* .xdata items */
enum {
UWOP_PUSH_NONVOL = 0, /* .PUSHREG - push nonvolative gpr */
UWOP_ALLOC_LARGE = 1, /* .ALLOCSTACK - alloc large-sized area on stack */
UWOP_ALLOC_SMALL = 2, /* .ALLOCSTACK - alloc small-sized area (8-128) on stack */
UWOP_SET_FPREG = 3, /* .SETFRAME - set frame pointer */
UWOP_SAVE_NONVOL = 4, /* .SAVEREG - save nonvolative gpr using MOV instead of PUSH */
UWOP_SAVE_NONVOL_FAR = 5, /* .SAVEREG - save nonvolative gpr using MOV instead of PUSH */
UWOP_SAVE_XMM = 6, /* */
UWOP_SAVE_XMM_FAR = 7, /* */
UWOP_SAVE_XMM128 = 8, /* .SAVEXMM128 - save all 128bits of nonvolative XMM register on stack */
UWOP_SAVE_XMM128_FAR = 9, /* .SAVEXMM128 - save all 128bits of nonvolative XMM register on stack */
UWOP_PUSH_MACHFRAME = 10 /* .PUSHFRAME - push a machine frame ( SS, RSP, EFL, CS, RIP [ERRCODE] ) */
};
typedef union _UNWIND_CODE {
struct {
uint_8 CodeOffset; /* offset within prolog */
uint_8 UnwindOp : 4; /* see UWOP_ values */
uint_8 OpInfo : 4;
};
uint_16 FrameOffset;
} UNWIND_CODE;
enum {
UNW_FLAG_NHANDLER = 0,
UNW_FLAG_EHANDLER = 1, /* function to examine exceptions */
UNW_FLAG_UHANDLER = 2, /* function to unwind an exception */
UNW_FLAG_FHANDLER = 3, /* inofficial, is E+U */
UNW_FLAG_CHAININFO = 4
};
typedef struct _UNWIND_INFO {
uint_8 Version : 3; /* is 1 */
uint_8 Flags : 5; /* see UNW_FLAG_ values */
uint_8 SizeOfProlog; /* size of prolog in bytes */
uint_8 CountOfCodes; /* number of UNWIND_CODE entries */
uint_8 FrameRegister : 4; /* if nonzero, function uses a frame pointer */
uint_8 FrameOffset : 4; /* offset frame reg from RSP * 16 */
#if 0
UNWIND_CODE UnwindCode[1]; /* unwind codes array */
union {
uint_32 ExceptionHandler; /* if UNW_FLAG_EHANDLER or UNW_FLAG_UHANDLER is set: RVA of language specific handler */
uint_32 FunctionEntry; /* if UNW_FLAG_CHAININFO is set: see IMAGE_RUNTIME_FUNCTION_ENTRY */
};
uint_32 ExceptionData[];
#endif
} UNWIND_INFO;
#define UNW_VERSION 1
If you google some of the symbolic constants ( i.e. "UWOP_PUSH" ) I bet that some more detailed info may be found.