public void DoStackAnalysis(Stack <Type> aStack, ref uint aStackOffset) { StackOffsetBeforeExecution = aStackOffset; // if current instruction is the first instruction of a filter or catch statement, "push" the exception type now if (CurrentExceptionRegion != null && (CurrentExceptionRegion.HandlerOffset == Position || (CurrentExceptionRegion.FilterOffset == Position && CurrentExceptionRegion.FilterOffset != 0))) { if (CurrentExceptionRegion.Kind != ExceptionRegionKind.Finally) { aStack.Push(typeof(object)); aStackOffset += ILOp.Align(ILOp.SizeOfType(typeof(object)), 4); } } if (StackPopTypes.Length > aStack.Count) { throw new Exception(String.Format("OpCode {0} tries to pop more stuff from analytical stack than there is!", this)); } var pos = 0; foreach (var xPopItem in StackPopTypes) { var popped = aStack.Pop(); if (xPopItem is null) { StackPopTypes[pos] = popped; } else if (xPopItem != popped && xPopItem.IsAssignableTo(popped)) { throw new Exception($"Tried to pop a {xPopItem} from the stack but found a {popped}"); } aStackOffset -= ILOp.Align(ILOp.SizeOfType(popped), 4); pos++; } DoInterpretStackTypes(); foreach (var xPushItem in StackPushTypes) { aStack.Push(xPushItem); aStackOffset += ILOp.Align(ILOp.SizeOfType(xPushItem), 4); } }
public void InterpretStackTypes(IDictionary <int, ILOpCode> aOpCodes, Stack <Type> aStack, ref bool aSituationChanged, int aMaxRecursionDepth) { if (Processed) { ILInterpretationDebugLine(() => String.Format("{0} skipped for reinterpretation", this)); return; } Processed = true; ILInterpretationDebugLine(() => { var sb = new StringBuilder(); sb.AppendFormat("Interpreting {0}. StackCount = {1}. Contents: ", this, aStack.Count); foreach (var item in aStack) { if (item == null) { sb.Append("**NULL**, "); } else { sb.AppendFormat("{0}, ", item.FullName); } } return(sb.ToString().Trim(',', ' ')); }); if (aMaxRecursionDepth == 0) { throw new Exception("Safety Error: MaxRecursionDepth reached!"); } if (StackOffsetBeforeExecution == null) { StackOffsetBeforeExecution = 0; foreach (var item in aStack) { if (item == null) { StackOffsetBeforeExecution = null; break; } StackOffsetBeforeExecution += ILOp.Align(ILOp.SizeOfType(item), 4); } } // if current instruction is the first instruction of a catch statement, "push" the exception type now if (CurrentExceptionHandler != null && CurrentExceptionHandler.HandlerOffset == Position) { if (CurrentExceptionHandler.Flags != SR.ExceptionHandlingClauseOptions.Finally) { aStack.Push(CurrentExceptionHandler.CatchType); } } if (StackPopTypes.Length > aStack.Count) { throw new Exception(String.Format("OpCode {0} tries to pop more stuff from analytical stack than there is!", this)); } for (int i = 0; i < StackPopTypes.Length; i++) { var xActualStackItem = aStack.ElementAt(i); if (xActualStackItem == null) { continue; } if (StackPopTypes[i] == null) { StackPopTypes[i] = xActualStackItem; aSituationChanged = true; } if (StackPopTypes[i] != xActualStackItem && !StackPopTypes[i].IsAssignableFrom(xActualStackItem) && !((StackPopTypes[i].IsPointer || StackPopTypes[i].IsByRef) && (xActualStackItem.IsPointer || xActualStackItem.IsByRef))) { throw new Exception(String.Format("OpCode {0} tries to pop item at stack position {1} with type {2}, but actual type is {3}", this, i, StackPopTypes[i], xActualStackItem)); } } foreach (var xPopItem in StackPopTypes) { aStack.Pop(); } try { DoInterpretStackTypes(ref aSituationChanged); } catch (Exception E) { throw new Exception("Error interpreting stacktypes for " + this, E); } foreach (var xPushItem in StackPushTypes) { aStack.Push(xPushItem); } DoInterpretNextInstructionStackTypes(aOpCodes, aStack, ref aSituationChanged, aMaxRecursionDepth); }