86 lines
2.2 KiB
C++
86 lines
2.2 KiB
C++
#include "master.hpp"
|
|
|
|
namespace factor {
|
|
|
|
typedef unsigned char UBYTE;
|
|
|
|
const UBYTE UNW_FLAG_EHANDLER = 0x1;
|
|
|
|
struct UNWIND_INFO {
|
|
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];
|
|
};
|
|
|
|
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);
|
|
}
|
|
|
|
}
|