Exemplo n.º 1
0
 public void HeuristicAdd(Mono.Cecil.ModuleDefinition module)
 {
     // Search module for PFEs and add enclosing method.
     // Find all pfe's in graph.
     foreach (Mono.Cecil.MethodDefinition method in Campy.Types.Utils.ReflectionCecilInterop.GetMethods(module))
     {
         if (method.Body == null)
         {
             return;
         }
         foreach (Mono.Cecil.Cil.Instruction i in method.Body.Instructions)
         {
             Mono.Cecil.Cil.OpCode      op = i.OpCode;
             Mono.Cecil.Cil.FlowControl fc = op.FlowControl;
             object operand = i.Operand;
             Mono.Cecil.MethodReference call_to = operand as Mono.Cecil.MethodReference;
             if (fc == Mono.Cecil.Cil.FlowControl.Call)
             {
                 if (call_to != null && call_to.Name.Equals("For") &&
                     call_to.DeclaringType != null && call_to.DeclaringType.FullName.Equals("Campy.Parallel"))
                 {
                     Add(method);
                 }
             }
         }
     }
 }
Exemplo n.º 2
0
        public void FindNewBlocks(Assembly assembly)
        {
            // Do not analyze Campy modules generally...
            if (Options.Singleton.Get(Options.OptionType.DoNotAnalyzeCampyAssemblies))
            {
                return;
            }

            // Starting from all blocks in this assembly,
            // find all PFE's, then compute control-flow/
            // data-flow analysis in order to compute call
            // structure and new blocks to analyze.

            List <Inst>          pfe_list    = new List <Inst>();
            List <CFG.CFGVertex> pfe_entries = new List <CFGVertex>();

            // Find all pfe's all nodes in assembly.
            foreach (CFG.CFGVertex node in this.VertexNodes)
            {
                foreach (Inst inst in node._instructions)
                {
                    Mono.Cecil.Cil.OpCode      op = inst.OpCode;
                    Mono.Cecil.Cil.FlowControl fc = op.FlowControl;
                    object operand = inst.Operand;
                    Mono.Cecil.MethodReference call_to = operand as Mono.Cecil.MethodReference;
                    if (fc == Mono.Cecil.Cil.FlowControl.Call)
                    {
                        if (call_to != null && call_to.Name.Equals("For") &&
                            call_to.DeclaringType != null && call_to.DeclaringType.FullName.Equals("Campy.Parallel"))
                        {
                            System.Console.WriteLine("Found PFE in block " + node.Name);
                            pfe_list.Add(inst);
                        }
                    }
                }
            }

            // Convert PFE instructions into a list of entries.
            foreach (Inst inst in pfe_list)
            {
                CFG.CFGVertex entry = FindEntry(inst);
                if (!pfe_entries.Contains(entry))
                {
                    pfe_entries.Add(entry);
                }
            }

            // Perform sparse data flow propagation in order to
            // get all indirect calls. Add those blocks to the graph.
            this._cfa.SparseDataFlowPropagation(pfe_entries);
        }
Exemplo n.º 3
0
        private void ExtractBasicBlocksOfMethod(MethodDefinition definition)
        {
            _done.Add(definition);
            // Make sure definition assembly is loaded.
            String full_name = definition.Module.FullyQualifiedName;

            LoadAssembly(full_name);
            if (definition.Body == null)
            {
                System.Console.WriteLine("WARNING: METHOD BODY NULL! " + definition);
                return;
            }
            int instruction_count = definition.Body.Instructions.Count;
            StackQueue <Mono.Cecil.Cil.Instruction> leader_list = new StackQueue <Mono.Cecil.Cil.Instruction>();

            // Each method is a leader of a block.
            CFGVertex v = (CFGVertex)this.AddVertex(_node_number++);

            v.Method         = definition;
            v.HasReturnValue = definition.IsReuseSlot;
            v._entry         = v;
            this._entries.Add(v);
            v._ordered_list_of_blocks = new List <CFGVertex>();
            v._ordered_list_of_blocks.Add(v);
            for (int j = 0; j < instruction_count; ++j)
            {
                // accumulate jump to locations since these split blocks.
                Mono.Cecil.Cil.Instruction mi = definition.Body.Instructions[j];
                //System.Console.WriteLine(mi);
                Inst i = Inst.Wrap(mi, this);
                Mono.Cecil.Cil.OpCode      op = i.OpCode;
                Mono.Cecil.Cil.FlowControl fc = op.FlowControl;

                v._instructions.Add(i);

                // Verify that mi not owned already.
                CFG.CFGVertex asdfasdf;
                Debug.Assert(!partition_of_instructions.TryGetValue(mi, out asdfasdf));
                // Update ownership.
                partition_of_instructions.Add(mi, v);

                if (fc == Mono.Cecil.Cil.FlowControl.Next)
                {
                    continue;
                }
                if (fc == Mono.Cecil.Cil.FlowControl.Branch ||
                    fc == Mono.Cecil.Cil.FlowControl.Cond_Branch)
                {
                    // Save leader target of branch.
                    object o = i.Operand;
                    // Two cases that I know of: operand is just and instruction,
                    // or operand is an array of instructions (via a switch instruction).

                    Mono.Cecil.Cil.Instruction   oo  = o as Mono.Cecil.Cil.Instruction;
                    Mono.Cecil.Cil.Instruction[] ooa = o as Mono.Cecil.Cil.Instruction[];
                    if (oo != null)
                    {
                        leader_list.Push(oo);
                    }
                    else if (ooa != null)
                    {
                        foreach (Mono.Cecil.Cil.Instruction ins in ooa)
                        {
                            Debug.Assert(ins != null);
                            leader_list.Push(ins);
                        }
                    }
                    else
                    {
                        throw new Exception("Unknown operand type for basic block partitioning.");
                    }
                }
            }
            StackQueue <int> ordered_leader_list = new StackQueue <int>();

            for (int j = 0; j < instruction_count; ++j)
            {
                // Order jump targets. These denote locations
                // where to split blocks. However, it's ordered,
                // so that splitting is done from last instruction in block
                // to first instruction in block.
                Mono.Cecil.Cil.Instruction i = definition.Body.Instructions[j];
                //System.Console.WriteLine("Looking for " + i);
                if (leader_list.Contains(i))
                {
                    ordered_leader_list.Push(j);
                }
            }
            // Split block at jump targets in reverse.
            while (ordered_leader_list.Count > 0)
            {
                int           i        = ordered_leader_list.Pop();
                CFG.CFGVertex new_node = v.Split(i);
            }

            //this.Dump();

            StackQueue <CFG.CFGVertex> stack = new StackQueue <CFG.CFGVertex>();

            foreach (CFG.CFGVertex node in this.VertexNodes)
            {
                stack.Push(node);
            }
            while (stack.Count > 0)
            {
                // Split blocks at branches, not including calls, with following
                // instruction a leader of new block.
                CFG.CFGVertex node = stack.Pop();
                int           node_instruction_count = node._instructions.Count;
                for (int j = 0; j < node_instruction_count; ++j)
                {
                    Inst i = node._instructions[j];
                    Mono.Cecil.Cil.OpCode      op = i.OpCode;
                    Mono.Cecil.Cil.FlowControl fc = op.FlowControl;
                    if (fc == Mono.Cecil.Cil.FlowControl.Next)
                    {
                        continue;
                    }
                    if (fc == Mono.Cecil.Cil.FlowControl.Call)
                    {
                        continue;
                    }
                    if (fc == Mono.Cecil.Cil.FlowControl.Meta)
                    {
                        continue;
                    }
                    if (fc == Mono.Cecil.Cil.FlowControl.Phi)
                    {
                        continue;
                    }
                    if (j + 1 >= node_instruction_count)
                    {
                        continue;
                    }
                    CFG.CFGVertex new_node = node.Split(j + 1);
                    stack.Push(new_node);
                    break;
                }
            }

            //this.Dump();
            stack = new StackQueue <CFG.CFGVertex>();
            foreach (CFG.CFGVertex node in this.VertexNodes)
            {
                stack.Push(node);
            }
            while (stack.Count > 0)
            {
                // Add in all final non-fallthrough branch edges.
                CFG.CFGVertex              node = stack.Pop();
                int                        node_instruction_count = node._instructions.Count;
                Inst                       i  = node._instructions[node_instruction_count - 1];
                Mono.Cecil.Cil.OpCode      op = i.OpCode;
                Mono.Cecil.Cil.FlowControl fc = op.FlowControl;
                switch (fc)
                {
                case Mono.Cecil.Cil.FlowControl.Branch:
                case Mono.Cecil.Cil.FlowControl.Cond_Branch:
                {
                    // Two cases: i.Operand is a single instruction, or an array of instructions.
                    if (i.Operand as Mono.Cecil.Cil.Instruction != null)
                    {
                        Mono.Cecil.Cil.Instruction target_instruction = i.Operand as Mono.Cecil.Cil.Instruction;
                        CFGVertex target_node = this.VertexNodes.First(
                            (CFGVertex x) =>
                            {
                                if (!x._instructions.First().Instruction.Equals(target_instruction))
                                {
                                    return(false);
                                }
                                return(true);
                            });
                        if (Options.Singleton.Get(Options.OptionType.DisplaySSAComputation))
                        {
                            System.Console.WriteLine("Create edge a " + node.Name + " to " + target_node.Name);
                        }
                        this.AddEdge(node, target_node);
                    }
                    else if (i.Operand as Mono.Cecil.Cil.Instruction[] != null)
                    {
                        foreach (Mono.Cecil.Cil.Instruction target_instruction in (i.Operand as Mono.Cecil.Cil.Instruction[]))
                        {
                            CFGVertex target_node = this.VertexNodes.First(
                                (CFGVertex x) =>
                                {
                                    if (!x._instructions.First().Instruction.Equals(target_instruction))
                                    {
                                        return(false);
                                    }
                                    return(true);
                                });
                            System.Console.WriteLine("Create edge a " + node.Name + " to " + target_node.Name);
                            this.AddEdge(node, target_node);
                        }
                    }
                    else
                    {
                        throw new Exception("Unknown operand type for conditional branch.");
                    }
                    break;
                }

                case Mono.Cecil.Cil.FlowControl.Break:
                    break;

                case Mono.Cecil.Cil.FlowControl.Call:
                {
                    // We no longer split at calls. Splitting causes
                    // problems because interprocedural edges are
                    // produced. That's not good because it makes
                    // code too "messy".
                    break;

                    object o = i.Operand;
                    if (o as Mono.Cecil.MethodReference != null)
                    {
                        Mono.Cecil.MethodReference  r = o as Mono.Cecil.MethodReference;
                        Mono.Cecil.MethodDefinition d = r.Resolve();
                        IEnumerable <CFGVertex>     target_node_list = this.VertexNodes.Where(
                            (CFGVertex x) =>
                            {
                                return(x.Method.FullName == r.FullName &&
                                       x._entry == x);
                            });
                        int c = target_node_list.Count();
                        if (c >= 1)
                        {
                            // target_node is the entry for a method. Also get the exit.
                            CFGVertex target_node = target_node_list.First();
                            CFGVertex exit_node   = target_node.Exit;
                            // check if this is a recursive call. DO NOT BOTHER!!
                            if (node.Method == target_node.Method)
                            {
                            }
                            else
                            {
                                // Create edges from exit to successor blocks of the call.
                                foreach (CFGEdge e in node._Successors)
                                {
                                    System.Console.WriteLine("Create edge c " + exit_node.Name + " to " + e.to.Name);
                                    this._interprocedure_graph.AddEdge(exit_node, e.to);
                                }
                                // Create edge from node to method entry.
                                System.Console.WriteLine("Create edge b " + node.Name + " to " + target_node.Name);
                                this._interprocedure_graph.AddEdge(node, target_node);
                            }
                        }
                    }
                    break;
                }

                case Mono.Cecil.Cil.FlowControl.Meta:
                    break;

                case Mono.Cecil.Cil.FlowControl.Next:
                    break;

                case Mono.Cecil.Cil.FlowControl.Phi:
                    break;

                case Mono.Cecil.Cil.FlowControl.Return:
                    break;

                case Mono.Cecil.Cil.FlowControl.Throw:
                    break;
                }
            }

            //this.Dump();
        }