private static void SetupEHState(DarksVMContext ctx, object ex) { EHState ehState; if (ctx.EHStates.Count != 0) { ehState = ctx.EHStates[ctx.EHStates.Count - 1]; if (ehState.CurrentFrame != null) { if (ehState.CurrentProcess == EHState.EHProcess.Searching) { ctx.Registers[DarksVMConstants.REG_R1].U1 = 0; } else if (ehState.CurrentProcess == EHState.EHProcess.Unwinding) { ehState.ExceptionObj = ex; } return; } } ehState = new EHState { OldBP = ctx.Registers[DarksVMConstants.REG_BP], OldSP = ctx.Registers[DarksVMConstants.REG_SP], ExceptionObj = ex, CurrentProcess = EHState.EHProcess.Searching, CurrentFrame = null, HandlerFrame = null }; ctx.EHStates.Add(ehState); }
static void SetupEHState(VMContext ctx, object ex) { EHState ehState; if (ctx.EHStates.Count != 0) { ehState = ctx.EHStates[ctx.EHStates.Count - 1]; if (ehState.CurrentFrame != null) { if (ehState.CurrentProcess == EHState.EHProcess.Searching) { // Return from filter => throw exception, default to 0 by Partition III 3.34 ctx.Registers[Constants.REG_R1].U1 = 0; } else if (ehState.CurrentProcess == EHState.EHProcess.Unwinding) { // Return from finally => throw exception, replace current exception // https://stackoverflow.com/questions/2911215/what-happens-if-a-finally-block-throws-an-exception ehState.ExceptionObj = ex; } return; } } ehState = new EHState { OldBP = ctx.Registers[Constants.REG_BP], OldSP = ctx.Registers[Constants.REG_SP], ExceptionObj = ex, CurrentProcess = EHState.EHProcess.Searching, CurrentFrame = null, HandlerFrame = null }; ctx.EHStates.Add(ehState); }
private static void HandleEH(DarksVMContext ctx, ref ExecutionState state) { EHState ehState = ctx.EHStates[ctx.EHStates.Count - 1]; switch (ehState.CurrentProcess) { case EHState.EHProcess.Searching: { if (ehState.CurrentFrame != null) { // Return from filter bool filterResult = ctx.Registers[DarksVMConstants.REG_R1].U1 != 0; if (filterResult) { ehState.CurrentProcess = EHState.EHProcess.Unwinding; ehState.HandlerFrame = ehState.CurrentFrame; ehState.CurrentFrame = ctx.EHStack.Count; state = ExecutionState.Next; goto case EHState.EHProcess.Unwinding; } ehState.CurrentFrame--; } else { ehState.CurrentFrame = ctx.EHStack.Count - 1; } Type exType = ehState.ExceptionObj.GetType(); for (; ehState.CurrentFrame >= 0 && ehState.HandlerFrame == null; ehState.CurrentFrame--) { EHFrame frame = ctx.EHStack[ehState.CurrentFrame.Value]; if (frame.EHType == DarksVMConstants.EH_FILTER) { // Run filter uint sp = ehState.OldSP.U4; ctx.Stack.SetTopPosition(++sp); ctx.Stack[sp] = new DarksVMSlot { O = ehState.ExceptionObj }; ctx.Registers[DarksVMConstants.REG_K1].U1 = 0; ctx.Registers[DarksVMConstants.REG_SP].U4 = sp; ctx.Registers[DarksVMConstants.REG_BP] = frame.BP; ctx.Registers[DarksVMConstants.REG_IP].U8 = frame.FilterAddr; break; } if (frame.EHType == DarksVMConstants.EH_CATCH) { if (frame.CatchType.IsAssignableFrom(exType)) { ehState.CurrentProcess = EHState.EHProcess.Unwinding; ehState.HandlerFrame = ehState.CurrentFrame; ehState.CurrentFrame = ctx.EHStack.Count; goto case EHState.EHProcess.Unwinding; } } } if (ehState.CurrentFrame == -1 && ehState.HandlerFrame == null) { ctx.EHStates.RemoveAt(ctx.EHStates.Count - 1); state = ExecutionState.Rethrow; if (ctx.EHStates.Count == 0) { HandleRethrow(ctx, ehState.ExceptionObj); } } else { state = ExecutionState.Next; } break; } case EHState.EHProcess.Unwinding: { ehState.CurrentFrame--; int i; for (i = ehState.CurrentFrame.Value; i > ehState.HandlerFrame.Value; i--) { EHFrame frame = ctx.EHStack[i]; ctx.EHStack.RemoveAt(i); if (frame.EHType == DarksVMConstants.EH_FAULT || frame.EHType == DarksVMConstants.EH_FINALLY) { // Run finally SetupFinallyFrame(ctx, frame); break; } } ehState.CurrentFrame = i; if (ehState.CurrentFrame == ehState.HandlerFrame) { EHFrame frame = ctx.EHStack[ehState.HandlerFrame.Value]; ctx.EHStack.RemoveAt(ehState.HandlerFrame.Value); // Run handler frame.SP.U4++; ctx.Stack.SetTopPosition(frame.SP.U4); ctx.Stack[frame.SP.U4] = new DarksVMSlot { O = ehState.ExceptionObj }; ctx.Registers[DarksVMConstants.REG_K1].U1 = 0; ctx.Registers[DarksVMConstants.REG_SP] = frame.SP; ctx.Registers[DarksVMConstants.REG_BP] = frame.BP; ctx.Registers[DarksVMConstants.REG_IP].U8 = frame.HandlerAddr; ctx.EHStates.RemoveAt(ctx.EHStates.Count - 1); } state = ExecutionState.Next; break; } default: throw new ExecutionEngineException(); } }