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);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}
							 |