typedef unsigned char UBYTE;
+#ifndef UNW_FLAG_EHANDLER
const UBYTE UNW_FLAG_EHANDLER = 0x1;
+#endif
struct UNWIND_INFO {
- UBYTE Version:3;
- UBYTE Flags:5;
- UBYTE SizeOfProlog;
- UBYTE CountOfCodes;
- UBYTE FrameRegister:4;
- UBYTE FrameOffset:4;
- ULONG ExceptionHandler;
- ULONG ExceptionData[1];
+ UBYTE Version : 3;
+ UBYTE Flags : 5;
+ UBYTE SizeOfProlog;
+ UBYTE CountOfCodes;
+ UBYTE FrameRegister : 4;
+ UBYTE FrameOffset : 4;
+ ULONG ExceptionHandler;
+ ULONG ExceptionData[1];
};
struct seh_data {
- UNWIND_INFO unwind_info;
- RUNTIME_FUNCTION func;
- UBYTE handler[32];
+ UNWIND_INFO unwind_info;
+ RUNTIME_FUNCTION func;
+ UBYTE handler[32];
};
-void factor_vm::c_to_factor_toplevel(cell quot)
-{
- /* The annoying thing about Win64 SEH is that the offsets in
- * function tables are 32-bit integers, and the exception handler
- * itself must reside between the start and end pointers, so
- * we stick everything at the beginning of the code heap and
- * generate a small trampoline that jumps to the real
- * exception handler. */
-
- seh_data *seh_area = (seh_data *)code->seh_area;
- cell base = code->seg->start;
-
- /* Should look at generating this with the Factor assembler */
-
- /* mov rax,0 */
- seh_area->handler[0] = 0x48;
- seh_area->handler[1] = 0xb8;
- seh_area->handler[2] = 0x0;
- seh_area->handler[3] = 0x0;
- seh_area->handler[4] = 0x0;
- seh_area->handler[5] = 0x0;
- seh_area->handler[6] = 0x0;
- seh_area->handler[7] = 0x0;
- seh_area->handler[8] = 0x0;
- seh_area->handler[9] = 0x0;
-
- /* jmp rax */
- seh_area->handler[10] = 0x48;
- seh_area->handler[11] = 0xff;
- seh_area->handler[12] = 0xe0;
-
- /* Store address of exception handler in the operand of the 'mov' */
- cell handler = (cell)&factor::exception_handler;
- memcpy(&seh_area->handler[2],&handler,sizeof(cell));
-
- UNWIND_INFO *unwind_info = &seh_area->unwind_info;
- unwind_info->Version = 1;
- unwind_info->Flags = UNW_FLAG_EHANDLER;
- unwind_info->SizeOfProlog = 0;
- unwind_info->CountOfCodes = 0;
- unwind_info->FrameRegister = 0;
- unwind_info->FrameOffset = 0;
- unwind_info->ExceptionHandler = (DWORD)((cell)&seh_area->handler[0] - base);
- unwind_info->ExceptionData[0] = 0;
-
- RUNTIME_FUNCTION *func = &seh_area->func;
- func->BeginAddress = 0;
- func->EndAddress = (DWORD)(code->seg->end - base);
- func->UnwindData = (DWORD)((cell)&seh_area->unwind_info - base);
-
- if(!RtlAddFunctionTable(func,1,base))
- fatal_error("RtlAddFunctionTable() failed",0);
-
- c_to_factor(quot);
-
- if(!RtlDeleteFunctionTable(func))
- fatal_error("RtlDeleteFunctionTable() failed",0);
+void factor_vm::c_to_factor_toplevel(cell quot) {
+ // The annoying thing about Win64 SEH is that the offsets in
+ // function tables are 32-bit integers, and the exception handler
+ // itself must reside between the start and end pointers, so
+ // we stick everything at the beginning of the code heap and
+ // generate a small trampoline that jumps to the real
+ // exception handler.
+
+ seh_data* seh_area = (seh_data*)code->seh_area;
+ cell base = code->seg->start;
+
+ // Should look at generating this with the Factor assembler
+
+ // mov rax,0
+ seh_area->handler[0] = 0x48;
+ seh_area->handler[1] = 0xb8;
+ seh_area->handler[2] = 0x0;
+ seh_area->handler[3] = 0x0;
+ seh_area->handler[4] = 0x0;
+ seh_area->handler[5] = 0x0;
+ seh_area->handler[6] = 0x0;
+ seh_area->handler[7] = 0x0;
+ seh_area->handler[8] = 0x0;
+ seh_area->handler[9] = 0x0;
+
+ // jmp rax
+ seh_area->handler[10] = 0x48;
+ seh_area->handler[11] = 0xff;
+ seh_area->handler[12] = 0xe0;
+
+ // Store address of exception handler in the operand of the 'mov'
+ cell handler = (cell)&factor::exception_handler;
+ memcpy(&seh_area->handler[2], &handler, sizeof(cell));
+
+ UNWIND_INFO* unwind_info = &seh_area->unwind_info;
+ unwind_info->Version = 1;
+ unwind_info->Flags = UNW_FLAG_EHANDLER;
+ unwind_info->SizeOfProlog = 0;
+ unwind_info->CountOfCodes = 0;
+ unwind_info->FrameRegister = 0;
+ unwind_info->FrameOffset = 0;
+ unwind_info->ExceptionHandler = (DWORD)((cell)&seh_area->handler[0] - base);
+ unwind_info->ExceptionData[0] = 0;
+
+ RUNTIME_FUNCTION* func = &seh_area->func;
+ func->BeginAddress = 0;
+ func->EndAddress = (DWORD)(code->seg->end - base);
+ func->UnwindData = (DWORD)((cell)&seh_area->unwind_info - base);
+
+ if (!RtlAddFunctionTable(func, 1, base))
+ fatal_error("RtlAddFunctionTable() failed", 0);
+
+ c_to_factor(quot);
+
+ if (!RtlDeleteFunctionTable(func))
+ fatal_error("RtlDeleteFunctionTable() failed", 0);
}
}