| 
									
										
										
										
											2010-04-08 13:32:14 -04:00
										 |  |  | #include "master.hpp"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace factor { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef unsigned char UBYTE; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-13 18:19:52 -04:00
										 |  |  | #ifndef UNW_FLAG_EHANDLER
 | 
					
						
							| 
									
										
										
										
											2010-04-08 13:32:14 -04:00
										 |  |  | const UBYTE UNW_FLAG_EHANDLER = 0x1; | 
					
						
							| 
									
										
										
										
											2013-05-13 18:19:52 -04:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2010-04-08 13:32:14 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | struct UNWIND_INFO { | 
					
						
							| 
									
										
										
										
											2013-05-11 22:24:31 -04:00
										 |  |  |   UBYTE Version : 3; | 
					
						
							|  |  |  |   UBYTE Flags : 5; | 
					
						
							|  |  |  |   UBYTE SizeOfProlog; | 
					
						
							|  |  |  |   UBYTE CountOfCodes; | 
					
						
							|  |  |  |   UBYTE FrameRegister : 4; | 
					
						
							|  |  |  |   UBYTE FrameOffset : 4; | 
					
						
							|  |  |  |   ULONG ExceptionHandler; | 
					
						
							|  |  |  |   ULONG ExceptionData[1]; | 
					
						
							| 
									
										
										
										
											2010-04-08 13:32:14 -04:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct seh_data { | 
					
						
							| 
									
										
										
										
											2013-05-11 22:24:31 -04:00
										 |  |  |   UNWIND_INFO unwind_info; | 
					
						
							|  |  |  |   RUNTIME_FUNCTION func; | 
					
						
							|  |  |  |   UBYTE handler[32]; | 
					
						
							| 
									
										
										
										
											2010-04-08 13:32:14 -04:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 22:24:31 -04:00
										 |  |  | 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' */ | 
					
						
							| 
									
										
										
										
											2013-05-13 00:53:47 -04:00
										 |  |  |   cell handler = (cell)&factor::exception_handler; | 
					
						
							| 
									
										
										
										
											2013-05-11 22:24:31 -04:00
										 |  |  |   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; | 
					
						
							| 
									
										
										
										
											2013-05-13 00:53:47 -04:00
										 |  |  |   unwind_info->ExceptionHandler = (DWORD)((cell)&seh_area->handler[0] - base); | 
					
						
							| 
									
										
										
										
											2013-05-11 22:24:31 -04:00
										 |  |  |   unwind_info->ExceptionData[0] = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   RUNTIME_FUNCTION* func = &seh_area->func; | 
					
						
							|  |  |  |   func->BeginAddress = 0; | 
					
						
							|  |  |  |   func->EndAddress = (DWORD)(code->seg->end - base); | 
					
						
							| 
									
										
										
										
											2013-05-13 00:53:47 -04:00
										 |  |  |   func->UnwindData = (DWORD)((cell)&seh_area->unwind_info - base); | 
					
						
							| 
									
										
										
										
											2013-05-11 22:24:31 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (!RtlAddFunctionTable(func, 1, base)) | 
					
						
							|  |  |  |     fatal_error("RtlAddFunctionTable() failed", 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   c_to_factor(quot); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (!RtlDeleteFunctionTable(func)) | 
					
						
							|  |  |  |     fatal_error("RtlDeleteFunctionTable() failed", 0); | 
					
						
							| 
									
										
										
										
											2010-04-08 13:32:14 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } |