All Downloads are FREE. Search and download functionalities are using the official Maven repository.

soot.jimple.infoflow.codeOptimization.DeadCodeEliminator Maven / Gradle / Ivy

There is a newer version: 2.9.0
Show newest version
package soot.jimple.infoflow.codeOptimization;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import soot.MethodOrMethodContext;
import soot.Scene;
import soot.SootMethod;
import soot.Unit;
import soot.jimple.Stmt;
import soot.jimple.infoflow.InfoflowConfiguration;
import soot.jimple.infoflow.InfoflowConfiguration.CodeEliminationMode;
import soot.jimple.infoflow.InfoflowConfiguration.ImplicitFlowMode;
import soot.jimple.infoflow.InfoflowManager;
import soot.jimple.infoflow.sourcesSinks.manager.ISourceSinkManager;
import soot.jimple.infoflow.taintWrappers.ITaintPropagationWrapper;
import soot.jimple.infoflow.util.SystemClassHandler;
import soot.jimple.toolkits.scalar.ConditionalBranchFolder;
import soot.jimple.toolkits.scalar.ConstantPropagatorAndFolder;
import soot.jimple.toolkits.scalar.DeadAssignmentEliminator;
import soot.jimple.toolkits.scalar.UnreachableCodeEliminator;
import soot.util.queue.QueueReader;

/**
 * Code optimizer that performs an interprocedural dead-code elimination on all
 * application classes
 * 
 * @author Steven Arzt
 *
 */
public class DeadCodeEliminator implements ICodeOptimizer {

	private InfoflowConfiguration config;

	@Override
	public void initialize(InfoflowConfiguration config) {
		this.config = config;
	}

	@Override
	public void run(InfoflowManager manager, Collection entryPoints, ISourceSinkManager sourcesSinks,
			ITaintPropagationWrapper taintWrapper) {
		// Perform an intra-procedural constant propagation to prepare for the
		// inter-procedural one
		for (QueueReader rdr = Scene.v().getReachableMethods().listener(); rdr.hasNext();) {
			MethodOrMethodContext sm = rdr.next();
			SootMethod method = sm.method();

			if (method == null || !method.hasActiveBody())
				continue;

			// Exclude the dummy main method
			if (entryPoints.contains(method))
				continue;

			List callSites = getCallsInMethod(method);

			ConstantPropagatorAndFolder.v().transform(method.getActiveBody());
			DeadAssignmentEliminator.v().transform(method.getActiveBody());

			// Remove the dead callgraph edges
			removeDeadCallgraphEdges(method, callSites);
		}

		// Perform an inter-procedural constant propagation and code cleanup
		InterproceduralConstantValuePropagator ipcvp = new InterproceduralConstantValuePropagator(manager, entryPoints,
				sourcesSinks, taintWrapper);
		ipcvp.setRemoveSideEffectFreeMethods(
				config.getCodeEliminationMode() == CodeEliminationMode.RemoveSideEffectFreeCode
						&& config.getImplicitFlowMode() != ImplicitFlowMode.AllImplicitFlows);
		ipcvp.setExcludeSystemClasses(config.getIgnoreFlowsInSystemPackages());
		ipcvp.transform();

		// Get rid of all dead code
		for (QueueReader rdr = Scene.v().getReachableMethods().listener(); rdr.hasNext();) {
			MethodOrMethodContext sm = rdr.next();

			SootMethod method = sm.method();

			if (method == null || !method.hasActiveBody())
				continue;
			if (config.getIgnoreFlowsInSystemPackages()
					&& SystemClassHandler.v().isClassInSystemPackage(sm.method().getDeclaringClass().getName()))
				continue;

			ConditionalBranchFolder.v().transform(method.getActiveBody());

			// Delete all dead code. We need to be careful and patch the cfg so
			// that it does not retain edges for call statements we have deleted
			List callSites = getCallsInMethod(method);
			UnreachableCodeEliminator.v().transform(method.getActiveBody());
			removeDeadCallgraphEdges(method, callSites);
		}
	}

	/**
	 * Collects all callsites of the given method and removes all edges from the callgraph that correspond to callsites
	 * which are not in the given set of previously contained callsites.
	 *
	 * @param method The method which's outgoing callgraph edges should be sanitized
	 * @param oldCallSites A list of callsites that where previously contained by the method's body and have to be
	 *                     checked if still existent
	 */
	static void removeDeadCallgraphEdges(SootMethod method, List oldCallSites) {
		List newCallSites = getCallsInMethod(method);
		if (oldCallSites != null)
			for (Unit u : oldCallSites)
				if (newCallSites == null || !newCallSites.contains(u))
					Scene.v().getCallGraph().removeAllEdgesOutOf(u);
	}

	/**
	 * Gets a list of all units that invoke other methods in the given method
	 * 
	 * @param method The method from which to get all invocations
	 * @return The list of units calling other methods in the given method if there
	 *         is at least one such unit. Otherwise null.
	 */
	static List getCallsInMethod(SootMethod method) {
		List callSites = null;
		for (Unit u : method.getActiveBody().getUnits())
			if (((Stmt) u).containsInvokeExpr()) {
				if (callSites == null)
					callSites = new ArrayList();
				callSites.add(u);
			}
		return callSites;
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy