protected ILOpCode(Code aOpCode, int aPos, int aNextPos, SR.ExceptionHandlingClause aCurrentExceptionHandler) { OpCode = aOpCode; Position = aPos; NextPosition = aNextPos; CurrentExceptionHandler = aCurrentExceptionHandler; }
public OpToken(Code aOpCode, int aPos, int aNextPos, Int32 aValue, Module aModule, Type[] aTypeGenericArgs, Type[] aMethodGenericArgs, ExceptionHandlingClause aCurrentExceptionHandler) : base(aOpCode, aPos, aNextPos, aCurrentExceptionHandler) { Value = aValue; if (ValueIsField) { ValueField = aModule.ResolveField(Value, aTypeGenericArgs, aMethodGenericArgs); } if (ValueIsType) { ValueType = aModule.ResolveType(Value, aTypeGenericArgs, aMethodGenericArgs); } }
public OpInt64(Code aOpCode, int aPos, int aNextPos, UInt64 aValue, System.Reflection.ExceptionHandlingClause aCurrentExceptionHandler) : base(aOpCode, aPos, aNextPos, aCurrentExceptionHandler) { Value = aValue; }
public OpNone(Code aOpCode, int aPos, int aNextPos, ExceptionHandlingClause aCurrentExceptionHandler) : base(aOpCode, aPos, aNextPos, aCurrentExceptionHandler) { }
public static void WriteSeHTinyRow(ExceptionHandlingClause ehc, BinaryWriter bw) { ushort flag = 0; if (ehc.Flags == ExceptionHandlingClauseOptions.Filter) flag += 1; if (ehc.Flags == ExceptionHandlingClauseOptions.Fault) flag += 4; if (ehc.Flags == ExceptionHandlingClauseOptions.Finally) flag += 2; bw.Write(flag); bw.Write((ushort)ehc.TryOffset); bw.Write((byte)ehc.TryLength); bw.Write((ushort)ehc.HandlerOffset); bw.Write((byte)ehc.HandlerLength); object obj = new object(); if (ehc.Flags == ExceptionHandlingClauseOptions.Clause /*|| ehc.CatchType != obj.GetType()*/) bw.Write(GetTypeToken(ehc.CatchType)); else bw.Write(ehc.FilterOffset); }
// Msil.GetRuns が制御フローの要素分解をする private static void GettingControlFlowElement(byte[] il, ExceptionHandlingClause[] exceptionHandlingClauses) { foreach (var run in Msil.GetRuns(il, exceptionHandlingClauses)) { Console.WriteLine("IL_{0:X4}:", run.StartIndex); foreach (var source in run.ControlFlowSources) { var sourceDesc = source.Type == ControlFlowSourceType.ILOperation || source.Type == ControlFlowSourceType.ConditionalNegative ? string.Format("IL_{0:X4}", source.ILOffset) : string.Format("exception block #{0}", source.ClauseIndex); Console.WriteLine("\t// from {0} {1}", source.Type, sourceDesc); } foreach (var inst in run.Instructions) { var opCode = inst.OpCode; Console.WriteLine( " {0}\t// {1} {2}", opCode.Name, opCode.FlowControl, opCode.OperandType); } } }
/// <summary> /// 命令列を制御フロー単位で切り出し /// </summary> /// <param name="il"></param> /// <param name="clauses"></param> /// <returns></returns> public static IEnumerable<ILInstructionRun> GetRuns(byte[] il, ExceptionHandlingClause[] clauses) { var instructions = ILInstructions(il).ToArray(); return GetRuns(instructions, il.Length, clauses); }
public OpNone(Code aOpCode, int aPos, int aNextPos, System.Reflection.ExceptionHandlingClause aCurrentExceptionHandler) : base(aOpCode, aPos, aNextPos, aCurrentExceptionHandler) { }
public OpToken(Code aOpCode, int aPos, int aNextPos, Int32 aValue, Module aModule, Type[] aTypeGenericArgs, Type[] aMethodGenericArgs, System.Reflection.ExceptionHandlingClause aCurrentExceptionHandler) : base(aOpCode, aPos, aNextPos, aCurrentExceptionHandler) { Value = aValue; if (ValueIsField) { ValueField = aModule.ResolveField(Value, aTypeGenericArgs, aMethodGenericArgs); } if (ValueIsType) { ValueType = aModule.ResolveType(Value, aTypeGenericArgs, aMethodGenericArgs); } }
/// <summary> /// Validates an actual exception handling clause (the cloned version) against an expected one (its source). /// </summary> /// <param name="actualExceptionHandlingClause">Exception handling clause to validate.</param> /// <param name="expectedExceptionHandlingClause">Exception handling clause with expected info.</param> private static void ValidateExceptionHandlingClause( ExceptionHandlingClause actualExceptionHandlingClause, ExceptionHandlingClause expectedExceptionHandlingClause) { throw new NotImplementedException("TODO implement exception handling clause validation"); }
public OpSwitch(Code aOpCode, int aPos, int aNextPos, int[] aBranchLocations, ExceptionHandlingClause aCurrentExceptionHandler) : base(aOpCode, aPos, aNextPos, aCurrentExceptionHandler) { BranchLocations = aBranchLocations; }
// TODO: FIXME 再設計 例外処理系 全般実装不足 public static Dictionary<string, List<int>> PopulateControlFlowPath(byte[] il, ExceptionHandlingClause[] exceptionHandlingClauses) { var runs = GetRuns(il, exceptionHandlingClauses).ToArray(); // Queue を介して進行解析する var currentRun = runs.Single(r => r.ControlFlowSources.Any(c => c.Type == ControlFlowSourceType.MethodEntry)); var queueRuns = new Queue<Tuple<ILInstructionRun, List<int>>>(); var controlFows = new Dictionary<string, List<int>>(); queueRuns.Enqueue(Tuple.Create(currentRun, new List<int>())); while (queueRuns.Count != 0) { var qt = queueRuns.Dequeue(); currentRun = qt.Item1; var path = new List<int>(qt.Item2) {currentRun.StartIndex}; // 制御フローを分解して最後の命令に着目すればできる var lastInst = currentRun.Instructions.Last(); OpCode opCode = lastInst.OpCode; // 強制ブランチなら次のフロー要素を解析させる if (opCode.FlowControl == FlowControl.Branch) { var branchLocation = lastInst.GetBranchLocation(); // TODO: FIXME Finally 内の分岐フロー追ってない // ちょっと乱暴すぎる実装、例外もやらないとダメ // Queue の型を直さなきゃいけなくてちょっと大変なので現状放置 var handler = exceptionHandlingClauses.Where( clause => clause.Flags==ExceptionHandlingClauseOptions.Finally && clause.TryOffset <= lastInst.StartIndex && lastInst.StartIndex < clause.TryOffset + clause.TryLength && !(clause.TryOffset <= branchLocation && branchLocation < clause.TryOffset + clause.TryLength)).ToArray() ; if (handler.Any()) { path.Add( handler.First().HandlerOffset ); } var nextRun = runs.Single(r => r.StartIndex == branchLocation); if (path.Count(n => n == nextRun.StartIndex) <= 2) { queueRuns.Enqueue(Tuple.Create(nextRun, path)); } } // 条件ブランチなら、ブランチ先と条件に当たらなかったパス双方に解析が必要 else if (opCode.FlowControl == FlowControl.Cond_Branch) { ILInstructionRun nextRun; if (opCode.Value == OpCodes.Switch.Value) { // switch の遷移先 var branchLocs = lastInst.GetBranchLocations().Distinct(); foreach (var branchLoc in branchLocs) { nextRun = runs.Single(r => r.StartIndex == branchLoc); if (path.Count(n => n == nextRun.StartIndex) <= 2) { queueRuns.Enqueue(Tuple.Create(nextRun, path)); } } } else { // それ以外の条件分岐の遷移先 nextRun = runs.Single(r => r.StartIndex == lastInst.GetBranchLocation()); if (path.Count(n => n == nextRun.StartIndex) <= 2) { queueRuns.Enqueue(Tuple.Create(nextRun, path)); } } // 条件分岐が発生しなかった場合の継続先 if (path.Count(n => n == lastInst.StartIndex + lastInst.SizeWithOperand) <= 2) { nextRun = runs.Single(r => r.StartIndex == lastInst.StartIndex + lastInst.SizeWithOperand); queueRuns.Enqueue(Tuple.Create(nextRun, path)); } } // リターンにたどり着いた、おめでとう else if (opCode.FlowControl == FlowControl.Return) { var pathText = String.Join("=>", path.Select(o => String.Format("IL_{0:X4}", o))); if (!controlFows.ContainsKey(pathText)) { controlFows.Add(pathText, path); } } // それ以外の場合には続く制御フロー要素に実行が流れる else { if (path.Count(n => n == lastInst.StartIndex + lastInst.SizeWithOperand) <= 2) { var nextRun = runs.Single(r => r.StartIndex == lastInst.StartIndex + lastInst.SizeWithOperand); queueRuns.Enqueue(Tuple.Create(nextRun, path)); } } } return controlFows; }
/// <summary> /// 命令列を制御フロー単位で切り出し /// </summary> /// <param name="ilLength"></param> /// <param name="clauses"></param> /// <param name="instructions"></param> /// <returns></returns> public static IEnumerable<ILInstructionRun> GetRuns(ILInstruction[] instructions, int ilLength, ExceptionHandlingClause[] clauses) { // 制御フローの飛び込み先オフセット var offsets = new List<int> {0}; // 最初のメソッド開始点にはデフォルトで飛び込んでくる var controlFrowSouceByTarget = new Dictionary<int, List<ControlFlowSource>>(); Action<int, ControlFlowSource> appendSource = (target, source) => { List<ControlFlowSource> sourceList; if (controlFrowSouceByTarget.TryGetValue(target, out sourceList)) { sourceList.Add(source); } else { sourceList = new List<ControlFlowSource> {source}; controlFrowSouceByTarget.Add(target, sourceList); } }; // 例外ハンドリングでの飛び込みを要素追加 appendSource(0, new ControlFlowSource {Type = ControlFlowSourceType.MethodEntry}); for (int index = 0; index < clauses.Length; index++) { var clause = clauses[index]; offsets.Add(clause.TryOffset); appendSource(clause.TryOffset, new ControlFlowSource {Type = ControlFlowSourceType.BeginTry, ClauseIndex = index}); offsets.Add(clause.HandlerOffset); appendSource(clause.HandlerOffset, new ControlFlowSource {Type = ControlFlowSourceType.BeginHandler, ClauseIndex = index}); if ((clause.Flags & ExceptionHandlingClauseOptions.Filter) != 0) { offsets.Add(clause.FilterOffset); appendSource(clause.HandlerOffset, new ControlFlowSource {Type = ControlFlowSourceType.BeginFilter, ClauseIndex = index}); } } // IL 命令での制御フローを要素追加 foreach (var inst in instructions) { var opCode = inst.OpCode; // switch 命令での分岐先 if (opCode.Value == OpCodes.Switch.Value) { var branchLocations = inst.GetBranchLocations(); offsets.AddRange(branchLocations); foreach (var branchLocation in branchLocations) { Debug.Assert(instructions.Any(i => i.StartIndex == branchLocation)); appendSource(branchLocation, new ControlFlowSource { Type = ControlFlowSourceType.ILOperation, ILOffset = inst.StartIndex }); } } // それ以外での分岐先 if (opCode.OperandType == OperandType.ShortInlineBrTarget || opCode.OperandType == OperandType.InlineBrTarget) { var branchLocation = inst.GetBranchLocation(); Debug.Assert(instructions.Any(i => i.StartIndex == branchLocation)); offsets.Add(branchLocation); appendSource(branchLocation, new ControlFlowSource {Type = ControlFlowSourceType.ILOperation, ILOffset = inst.StartIndex}); } // 条件分岐での条件に当たらなかった側 if (opCode.FlowControl == FlowControl.Cond_Branch) { var nextInstOffset = inst.StartIndex + inst.SizeWithOperand; Debug.Assert(instructions.Any(i => i.StartIndex == nextInstOffset)); offsets.Add(nextInstOffset); appendSource(nextInstOffset, new ControlFlowSource { Type = ControlFlowSourceType.ConditionalNegative, ILOffset = inst.StartIndex }); } } // 飛び込みオフセット毎に命令列を切り出す var runStarts = offsets.Distinct().OrderBy(n => n).ToArray(); for (int i = 0; i < runStarts.Length; i++) { var runStart = runStarts[i]; var nextRunStart = i + 1 == runStarts.Length ? ilLength : runStarts[i + 1]; var ilInstructions = instructions.Where(inst => runStart <= inst.StartIndex && inst.StartIndex < nextRunStart).ToArray(); var lastInst = ilInstructions.Last(); Debug.Assert(lastInst.StartIndex + lastInst.SizeWithOperand == nextRunStart); yield return new ILInstructionRun( ilInstructions, controlFrowSouceByTarget[runStart], runStart); } }
public OpType(Code aOpCode, int aPos, int aNextPos, Type aValue, ExceptionHandlingClause aCurrentExceptionHandler) : base(aOpCode, aPos, aNextPos, aCurrentExceptionHandler) { Value = aValue; }
public OpField(Code aOpCode, int aPos, int aNextPos, FieldInfo aValue, ExceptionHandlingClause aCurrentExceptionHandler) : base(aOpCode, aPos, aNextPos, aCurrentExceptionHandler) { Value = aValue; }
public OpSwitch(Code aOpCode, int aPos, int aNextPos, int[] aBranchLocations, System.Reflection.ExceptionHandlingClause aCurrentExceptionHandler) : base(aOpCode, aPos, aNextPos, aCurrentExceptionHandler) { BranchLocations = aBranchLocations; }