Пример #1
0
 protected ILOpCode(Code aOpCode, int aPos, int aNextPos, SR.ExceptionHandlingClause aCurrentExceptionHandler)
 {
     OpCode                  = aOpCode;
     Position                = aPos;
     NextPosition            = aNextPos;
     CurrentExceptionHandler = aCurrentExceptionHandler;
 }
Пример #2
0
    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);
      }

    }
Пример #3
0
 public OpInt64(Code aOpCode, int aPos, int aNextPos, UInt64 aValue, System.Reflection.ExceptionHandlingClause aCurrentExceptionHandler)
     : base(aOpCode, aPos, aNextPos, aCurrentExceptionHandler)
 {
     Value = aValue;
 }
Пример #4
0
 public OpNone(Code aOpCode, int aPos, int aNextPos, ExceptionHandlingClause aCurrentExceptionHandler)
   : base(aOpCode, aPos, aNextPos, aCurrentExceptionHandler)
 {
 }
Пример #5
0
        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);
        }
Пример #6
0
 // 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);
         }
     }
 }
Пример #7
0
 protected ILOpCode(Code aOpCode, int aPos, int aNextPos, SR.ExceptionHandlingClause aCurrentExceptionHandler) {
   OpCode = aOpCode;
   Position = aPos;
   NextPosition = aNextPos;
   CurrentExceptionHandler = aCurrentExceptionHandler;
 }
Пример #8
0
        /// <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);
        }
Пример #9
0
 public OpNone(Code aOpCode, int aPos, int aNextPos, System.Reflection.ExceptionHandlingClause aCurrentExceptionHandler)
     : base(aOpCode, aPos, aNextPos, aCurrentExceptionHandler)
 {
 }
Пример #10
0
 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);
     }
 }
Пример #11
0
 /// <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");
 }
Пример #12
0
 public OpSwitch(Code aOpCode, int aPos, int aNextPos, int[] aBranchLocations, ExceptionHandlingClause aCurrentExceptionHandler)
   : base(aOpCode, aPos, aNextPos, aCurrentExceptionHandler) {
   BranchLocations = aBranchLocations;
 }
Пример #13
0
        // 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;
        }
Пример #14
0
        /// <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);
            }
        }
Пример #15
0
 public OpType(Code aOpCode, int aPos, int aNextPos, Type aValue, ExceptionHandlingClause aCurrentExceptionHandler)
   : base(aOpCode, aPos, aNextPos, aCurrentExceptionHandler)
 {
   Value = aValue;
 }
Пример #16
0
 public OpField(Code aOpCode, int aPos, int aNextPos, FieldInfo aValue, ExceptionHandlingClause aCurrentExceptionHandler)
   : base(aOpCode, aPos, aNextPos, aCurrentExceptionHandler) {
   Value = aValue;
 }
Пример #17
0
 public OpSwitch(Code aOpCode, int aPos, int aNextPos, int[] aBranchLocations, System.Reflection.ExceptionHandlingClause aCurrentExceptionHandler)
     : base(aOpCode, aPos, aNextPos, aCurrentExceptionHandler)
 {
     BranchLocations = aBranchLocations;
 }