/// <summary> /// Execute is the pass's prime mover; all unit-centric processing occurs here. Note that /// Execute might be thought of as a "callback": as the C2 host compiles each FunctionUnit, /// passing it from pass to pass, the plug-in Execute method is called to do its work. /// </summary> /// /// <param name="moduleUnit">The moduleUnit to process.</param> /// <returns>True if successful; false otherwise.</returns> protected override bool Execute(Phx.ModuleUnit moduleUnit) { try { this.ExecuteHelper(moduleUnit); } catch (System.Exception ex) { Console.Out.WriteLine("PHOENIX: Exception occurred:"); Console.Out.WriteLine(ex.Message); Console.Out.WriteLine("PHOENIX: Stack trace:"); Console.Out.WriteLine(ex.StackTrace); Console.Out.WriteLine("PHOENIX: Exiting GameTime..."); Environment.Exit(1); return(false); } return(true); }
/// <summary> /// Private helper workhorse function for <see cref="Execute"/>. /// </summary> /// /// <param name="moduleUnit">The moduleUnit to process.</param> /// <returns>True if successful; false otherwise.</returns> private bool ExecuteHelper(Phx.ModuleUnit moduleUnit) { Console.Out.WriteLine(); Phx.Graphs.CallGraph callGraph = moduleUnit.CallGraph; if (callGraph == null) { Console.Out.WriteLine("PHOENIX: Call graph is null."); Console.Out.WriteLine("Exiting GameTime."); Environment.Exit(1); return(false); } /* Load GameTime configuration. */ string configFile = Console.ReadLine(); Console.Out.WriteLine("PHOENIX: Configuring this GameTime session with " + configFile + "..."); Utilities.Configuration config = Utilities.Configuration.ReadConfigFile(configFile); Console.Out.WriteLine("PHOENIX: Successfully configured this session."); /* Load the project configuration. */ string projectConfigFile = Console.ReadLine(); Console.Out.WriteLine("PHOENIX: Loading project configuration from " + projectConfigFile + "..."); ProjectConfiguration projectConfig = ProjectConfiguration.ReadProjectConfigFile(projectConfigFile, config); Console.Out.WriteLine("PHOENIX: Successfully loaded the project for this session."); /* Determine the current GameTime operation mode. */ string currentMode = Console.ReadLine(); mode = (currentMode.Equals(config.TEMP_PHX_CREATE_DAG)) ? MODES.CREATE_DAG : MODES.FIND_CONDITIONS; Console.Out.WriteLine("PHOENIX: GameTime operation mode is: " + ((mode == MODES.CREATE_DAG) ? "Create DAG." : "Find path conditions.")); /* Find the function to analyze. */ string funcToProcess = projectConfig.func; Console.Out.WriteLine("PHOENIX: Preprocessing " + funcToProcess + "..."); Console.Out.WriteLine(); Console.Out.WriteLine("PHOENIX: Finding the corresponding function unit..."); /* Find the function unit corresponding to the function to be analyzed. */ FunctionUnit functionUnitToProcess = null; /* Traverse the graph in post-order (top-down order). */ Phx.Graphs.NodeFlowOrder nodeOrder = Phx.Graphs.NodeFlowOrder.New(callGraph.Lifetime); nodeOrder.Build(callGraph, Phx.Graphs.Order.PostOrder); Phx.Targets.Runtimes.Runtime runtime = moduleUnit.Runtime; uint functionCount = 0; for (uint i = 1; i <= nodeOrder.NodeCount; ++i) { Phx.Graphs.CallNode node = nodeOrder.Node(i).AsCallNode; if ((node == callGraph.UnknownCallerNode) || (node == callGraph.UnknownCalleeNode)) { continue; } if (node.FunctionSymbol != null) { /* Is this LTCG mode? */ bool isLTCG = false; try { IDictionary env = Environment.GetEnvironmentVariables(); if (env.Contains("LINK_TIME_CODE_GENERATION")) { isLTCG = true; } } catch (ArgumentNullException) { } /* Only perform the check when the LTCG mode is off. */ if (isLTCG || moduleUnit.IsPEModuleUnit) { moduleUnit = node.FunctionSymbol.CompilationUnitParentSymbol.Unit.AsModuleUnit; } /* Create the corresponding function unit. */ Phx.Lifetime lifetime = Phx.Lifetime.New(Phx.LifetimeKind.Function, null); Phx.FunctionUnit functionUnit = Phx.FunctionUnit.New(lifetime, node.FunctionSymbol, Phx.CodeGenerationMode.Native, moduleUnit.TypeTable, runtime.Architecture, runtime, moduleUnit, functionCount++); /* Attach debugging info. */ Phx.Debug.Info.New(functionUnit.Lifetime, functionUnit); node.FunctionSymbol.FunctionUnit = functionUnit; this.PhaseConfiguration.PhaseList.DoPhaseList(functionUnit); functionUnit.Context.PopUnit(); string funcName = FunctionUnitHelper.GetFunctionName(functionUnit); if (funcName == funcToProcess) { functionUnitToProcess = functionUnit; break; } } } if (functionUnitToProcess == null) { Console.Out.WriteLine("PHOENIX: Cannot find function named " + funcToProcess + "."); Console.Out.WriteLine("PHOENIX: Exiting GameTime..."); Environment.Exit(1); return(false); } else { Console.Out.WriteLine("PHOENIX: Function unit found."); } Console.Out.WriteLine("PHOENIX: Preprocessing the function unit..."); FunctionUnitHelper.Preprocess(functionUnitToProcess); Console.Out.WriteLine("PHOENIX: Function unit preprocessing complete."); Console.Out.WriteLine(); Console.Out.WriteLine("PHOENIX: Building the flow graph..."); functionUnitToProcess.BuildFlowGraphWithoutEH(); Phx.Graphs.FlowGraph graph = functionUnitToProcess.FlowGraph; Console.Out.WriteLine("PHOENIX: Flow graph built."); Console.Out.WriteLine("PHOENIX: Snipping the relevant portion of the flow graph..."); uint sourceBlockId = 1; uint sinkBlockId = graph.NodeCount; if (projectConfig.startLabel != "") { Phx.Graphs.BasicBlock sourceBlock = FunctionUnitHelper.SplitAtUserLabel(functionUnitToProcess, projectConfig.startLabel); sourceBlockId = sourceBlock.Id; } if (projectConfig.endLabel != "") { Phx.Graphs.BasicBlock sinkBlock = FunctionUnitHelper.SplitAtUserLabel(functionUnitToProcess, projectConfig.endLabel); /* Correct the sink block: we want the block just before the block * we receive from SplitAtUserLabel. */ Phx.Graphs.FlowEdge edgeToSink = sinkBlock.PredecessorEdgeList; sinkBlock = edgeToSink.PredecessorNode; sinkBlockId = sinkBlock.Id; } Console.Out.WriteLine("PHOENIX: Relevant portion snipped."); Console.Out.WriteLine(); Console.Out.WriteLine("PHOENIX: Starting analysis..."); switch (mode) { case MODES.CREATE_DAG: FunctionUnitHelper.DumpCfgToFile(functionUnitToProcess, sourceBlockId, sinkBlockId, config, projectConfig); break; case MODES.FIND_CONDITIONS: FunctionUnitHelper.FindPathConditions(functionUnitToProcess, config, projectConfig); break; } Console.Out.WriteLine("PHOENIX: Analysis successful."); Console.Out.WriteLine(); Environment.Exit(0); return(true); }