Пример #1
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();
        }
Пример #2
0
        public void Add(Mono.Cecil.MethodDefinition definition)
        {
            // Do not analyze Campy modules generally...
            if (Options.Singleton.Get(Options.OptionType.DoNotAnalyzeCampyAssemblies))
            {
                if (definition.Module != null && Analysis.IsCampyModuleName(definition.Module.Name))
                {
                    return;
                }
            }

            if (_done.Contains(definition))
            {
                return;
            }
            if (_to_do.Contains(definition))
            {
                return;
            }

            bool ignore = false;

            foreach (KeyValuePair <String, String> pair in _analysis._filter)
            {
                String pat = pair.Key;
                String ty  = pair.Value;

                // Match based on type "ty".
                if (ty.Equals("-method"))
                {
                    // match on name/parameters.
                    Regex  reg = new Regex(@"^" + pat + @"$");
                    String def = definition.ToString();
                    Match  m   = reg.Match(def);
                    int    ind = m.Index;
                    int    l   = m.Length;
                    if (!(ind >= 0 && l > 0))
                    {
                        continue;
                    }
                    ignore = true;
                    break;
                }
                else if (ty.Equals("+method"))
                {
                    // match on name/parameters.
                    Regex  reg = new Regex(@"^" + pat + @"$");
                    String def = definition.ToString();
                    Match  m   = reg.Match(def);
                    int    ind = m.Index;
                    int    l   = m.Length;
                    if (!(ind >= 0 && l > 0))
                    {
                        continue;
                    }
                    ignore = false;
                    break;
                }
                else if (ty.Equals("-namespace"))
                {
                    // match on name/parameters.
                    Regex  reg = new Regex(@"^" + pat + @"$");
                    String def = definition.DeclaringType.Namespace.ToString();
                    Match  m   = reg.Match(def);
                    int    ind = m.Index;
                    int    l   = m.Length;
                    if (!(ind >= 0 && l > 0))
                    {
                        continue;
                    }
                    ignore = true;
                    break;
                }
                else if (ty.Equals("+namespace"))
                {
                    // match on name/parameters.
                    Regex  reg = new Regex(@"^" + pat + @"$");
                    String def = definition.DeclaringType.Namespace.ToString();
                    Match  m   = reg.Match(def);
                    int    ind = m.Index;
                    int    l   = m.Length;
                    if (!(ind >= 0 && l > 0))
                    {
                        continue;
                    }
                    ignore = false;
                    break;
                }
                else if (ty.Equals("-assembly"))
                {
                    // match on name/parameters.
                    Regex  reg = new Regex(@"^" + pat + @"$");
                    String def = definition.Module.Assembly.ToString();
                    Match  m   = reg.Match(def);
                    int    ind = m.Index;
                    int    l   = m.Length;
                    if (!(ind >= 0 && l > 0))
                    {
                        continue;
                    }
                    ignore = true;
                    break;
                }
                else if (ty.Equals("+assembly"))
                {
                    // match on name/parameters.
                    Regex  reg = new Regex(@"^" + pat + @"$");
                    String def = definition.Module.Assembly.ToString();
                    Match  m   = reg.Match(def);
                    int    ind = m.Index;
                    int    l   = m.Length;
                    if (!(ind >= 0 && l > 0))
                    {
                        continue;
                    }
                    ignore = false;
                    break;
                }
            }

            if (Options.Singleton.Get(Options.OptionType.DisplaySSAComputation))
            {
                System.Console.WriteLine((ignore ? "Ignoring " : "Adding ") + definition);
            }
            if (ignore)
            {
                return;
            }
            _to_do.Push(definition);
        }