Example #1
0
        private static void UpdateLocation(ref FMap <ILocalDefinition, Analysis.Instruction> currentLocals, ref FMap <IParameterDefinition, Analysis.Instruction> currentParameters, object localOrParameter, Analysis.Instruction newValue)
        {
            Contract.Requires(currentParameters != null);
            Contract.Requires(currentLocals != null);
            Contract.Ensures(Contract.ValueAtReturn(out currentParameters) != null);
            Contract.Ensures(Contract.ValueAtReturn(out currentLocals) != null);

            var local = localOrParameter as ILocalDefinition;

            if (local != null)
            {
                currentLocals = currentLocals.Insert(local, newValue);
                return;
            }
            var param = localOrParameter as IParameterDefinition;

            if (param != null)
            {
                currentParameters = currentParameters.Insert(param, newValue);
                return;
            }
        }
Example #2
0
        private static void ComputeDataFlowThroughLocals(ControlAndDataFlowGraph <BasicBlock, Instruction> cdg)
        {
            FMap <ILocalDefinition, Microsoft.Cci.Analysis.Instruction> currentLocals;

            var todo       = new Queue <BlockPC>();
            var seen       = new HashSet <BlockPC>();
            var startBlock = cdg.RootBlocks[0];

            FMap <IParameterDefinition, Microsoft.Cci.Analysis.Instruction> currentParameters = new FMap <IParameterDefinition, Microsoft.Cci.Analysis.Instruction>(k => k.Index);

            var initialLocation = GetStartLocation(startBlock);

            // push parameters onto start block
            foreach (var arg in cdg.MethodBody.MethodDefinition.Parameters)
            {
                var initialOp  = new InitialParameterAssignment(arg, initialLocation);
                var initialDef = new Instruction()
                {
                    Operation = initialOp
                };
                currentParameters = currentParameters.Insert(arg, initialDef);
            }
            startBlock.ParamDefs = currentParameters;
            todo.Enqueue(new BlockPC(startBlock.Offset.Singleton()));

            while (todo.Count > 0)
            {
                var currentPC = todo.Dequeue();
                if (seen.Contains(currentPC))
                {
                    continue;
                }
                seen.Add(currentPC);

                var block = cdg.CurrentBlock(currentPC);
                Contract.Assume(block != null);

                currentLocals     = block.LocalDefs;
                currentParameters = block.ParamDefs;

                foreach (var instr in block.Instructions)
                {
                    if (instr.IsMergeNode)
                    {
                        continue;
                    }
                    switch (instr.Operation.OperationCode)
                    {
                    case OperationCode.Starg:
                    case OperationCode.Starg_S:
                        // without pdb we seem to have no parameter info.
                        var pdef = (IParameterDefinition)instr.Operation.Value;
                        if (pdef != null)
                        {
                            currentParameters = currentParameters.Insert(pdef, instr.Operand1);
                        }
                        break;

                    case OperationCode.Stloc:
                    case OperationCode.Stloc_0:
                    case OperationCode.Stloc_1:
                    case OperationCode.Stloc_2:
                    case OperationCode.Stloc_3:
                    case OperationCode.Stloc_S:
                        var ldef = (ILocalDefinition)instr.Operation.Value;
                        currentLocals = currentLocals.Insert(ldef, instr.Operand1);
                        break;

                    case OperationCode.Ldloc:
                    case OperationCode.Ldloc_0:
                    case OperationCode.Ldloc_1:
                    case OperationCode.Ldloc_2:
                    case OperationCode.Ldloc_3:
                    case OperationCode.Ldloc_S:
                        // save the source in Aux
                    {
                        currentLocals.TryGetValue((ILocalDefinition)instr.Operation.Value, out instr.Aux);
                        break;
                    }

                    case OperationCode.Ldarg:
                    case OperationCode.Ldarg_0:
                    case OperationCode.Ldarg_1:
                    case OperationCode.Ldarg_2:
                    case OperationCode.Ldarg_3:
                    case OperationCode.Ldarg_S:
                        // save the source in Aux
                        var pdef2 = (IParameterDefinition)instr.Operation.Value;
                        if (pdef2 == null)
                        {
                            // this parameter. Assume it's never overwritten
                        }
                        else
                        {
                            currentParameters.TryGetValue(pdef2, out instr.Aux);
                        }
                        break;

                    case OperationCode.Stind_I:
                    case OperationCode.Stind_I1:
                    case OperationCode.Stind_I2:
                    case OperationCode.Stind_I4:
                    case OperationCode.Stind_I8:
                    case OperationCode.Stind_R4:
                    case OperationCode.Stind_R8:
                    case OperationCode.Stind_Ref:
                    {
                        var location = cdg.LocalOrParameter(instr.Operand1);
                        UpdateLocation(ref currentLocals, ref currentParameters, location, (Analysis.Instruction)instr.Operand2);

                        break;
                    }

                    case OperationCode.Ldind_I:
                    case OperationCode.Ldind_I1:
                    case OperationCode.Ldind_I2:
                    case OperationCode.Ldind_I4:
                    case OperationCode.Ldind_I8:
                    case OperationCode.Ldind_R4:
                    case OperationCode.Ldind_R8:
                    case OperationCode.Ldind_Ref:
                    case OperationCode.Ldind_U1:
                    case OperationCode.Ldind_U2:
                    case OperationCode.Ldind_U4:
                    {
                        // save the read value in Aux
                        var location = cdg.LocalOrParameter(instr.Operand1);
                        instr.Aux = ReadLocation(currentLocals, currentParameters, location);
                        break;
                    }

                    case OperationCode.Call:
                    case OperationCode.Callvirt:
                    {
                        // update byref / out parameters
                        var methodRef = instr.Operation.Value as IMethodReference;
                        var args      = instr.Operand2 as Instruction[];
                        if (args != null && methodRef != null)
                        {
                            foreach (var p in methodRef.Parameters)
                            {
                                if (p.IsByReference && p.Index < args.Length)
                                {
                                    var arg = args[p.Index];
                                    if (arg != null)
                                    {
                                        var loc         = cdg.LocalOrParameter(arg);
                                        var syntheticOp = new CallByRefAssignment(instr, p);
                                        UpdateLocation(ref currentLocals, ref currentParameters, loc, new Instruction()
                                            {
                                                Operation = syntheticOp, Type = p.Type
                                            });
                                    }
                                }
                            }
                        }
                        break;
                    }
                    }
                    instr.PostLocalDefs = currentLocals;
                    instr.PostParamDefs = currentParameters;
                }
                foreach (var succ in cdg.Successors(currentPC))
                {
                    MergeLocalsAndParameters(cdg.CurrentBlock(succ), currentLocals, currentParameters);
                    todo.Enqueue(succ);
                }
            }
        }