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

de.hdu.pvs.crashfinder.analysis.Slicing Maven / Gradle / Ivy

The newest version!
package de.hdu.pvs.crashfinder.analysis;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;

//import com.ibm.wala.core.tests.callGraph.CallGraphTestUtil;
import com.ibm.wala.ipa.callgraph.AnalysisCache;
import com.ibm.wala.ipa.callgraph.AnalysisOptions;
import com.ibm.wala.ipa.callgraph.AnalysisScope;
import com.ibm.wala.ipa.callgraph.CGNode;
import com.ibm.wala.ipa.callgraph.CallGraph;
import com.ibm.wala.ipa.callgraph.CallGraphBuilder;
import com.ibm.wala.ipa.callgraph.CallGraphStats;
import com.ibm.wala.ipa.callgraph.Entrypoint;
import com.ibm.wala.ipa.callgraph.impl.AllApplicationEntrypoints;
import com.ibm.wala.ipa.callgraph.impl.Util;
import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis;
import com.ibm.wala.ipa.cha.ClassHierarchy;
import com.ibm.wala.ipa.slicer.NormalStatement;
import com.ibm.wala.ipa.slicer.Slicer;
import com.ibm.wala.classLoader.IBytecodeMethod;
import com.ibm.wala.classLoader.ShrikeBTMethod;
import com.ibm.wala.ipa.slicer.Slicer.ControlDependenceOptions;
import com.ibm.wala.ipa.slicer.Slicer.DataDependenceOptions;
import com.ibm.wala.ipa.slicer.Statement;
import com.ibm.wala.ipa.slicer.StatementWithInstructionIndex;
import com.ibm.wala.ipa.slicer.thin.CISlicer;
import com.ibm.wala.shrikeCT.InvalidClassFileException;
import com.ibm.wala.ssa.IR;
import com.ibm.wala.ssa.SSAInstruction;
import com.ibm.wala.ssa.SSAInvokeInstruction;
import com.ibm.wala.types.Descriptor;
import com.ibm.wala.util.CancelException;
import com.ibm.wala.util.config.AnalysisScopeReader;
import com.ibm.wala.util.debug.Assertions;
import com.ibm.wala.util.intset.IntSet;
import com.ibm.wala.util.io.FileProvider;
import com.ibm.wala.util.strings.Atom;

import de.hdu.pvs.crashfinder.util.Utils;
import de.hdu.pvs.crashfinder.util.WALAUtils;

/**
 * 
 * This file computes a slice and also maps the result to source code.
 * 
 * For creating a launcher, See the 'PDFSlice' launcher included in the
 * 'launchers' directory in WALA.
 * 
 * @see Slicer, PDFSlicer and SlicerTest from WALA
 * @author Mohammad Ghanavati date: 05.05.2013
 */
public class Slicing {

	public enum CG {
		RTA, ZeroCFA, ZeroContainerCFA, VanillaZeroOneCFA, ZeroOneCFA, ZeroOneContainerCFA, OneCFA, TwoCFA, CFA, TempZeroCFA
	}

	public final String classPath;
	public final String mainClass;
	private String exclusionFile;
	private boolean contextSensitive = true;
	private DataDependenceOptions dataOption = DataDependenceOptions.NO_BASE_NO_HEAP_NO_EXCEPTIONS;
	private ControlDependenceOptions controlOption = ControlDependenceOptions.NONE;
	private CISlicer slicer = null;
	private AnalysisScope scope = null;
	private ClassHierarchy cha = null;
	private Iterable entrypoints = null;
	// private CallGraphBuilder builder = null;
	private AnalysisOptions options = null;
	private CallGraphBuilder cgb = null;
	private CallGraph cg = null;
	private PointerAnalysis pa = null;

	// private Statement s;

	// private String targetPackageName = null;

	public Slicing(String classPath, String mainClass, String exclusionFile) {
		this.classPath = classPath;
		this.mainClass = mainClass;
		this.exclusionFile = exclusionFile;
	}

	public void CallGraphBuilder() {
		try {
			// create an analysis scope representing the appJar as a J2SE
			// application
			this.scope = AnalysisScopeReader.makeJavaBinaryAnalysisScope(
					this.classPath,
					(new FileProvider()).getFile(this.exclusionFile));

			// build the class hierarchy
			this.cha = ClassHierarchy.make(scope);
			// this.entrypoints = com.ibm.wala.ipa.callgraph.impl.Util
			// .makeMainEntrypoints(scope, cha, mainClass);
			this.entrypoints = new AllApplicationEntrypoints(scope, cha);
			// this.options = CallGraphTestUtil.makeAnalysisOptions(scope,
			// entrypoints);
			this.options = new AnalysisOptions(scope, entrypoints);

			// build the call graph
			System.out.println("Building call graph...");
			System.out.println("Number of entry points: "
					+ Utils.countIterable(this.entrypoints));
			this.cgb = Util.makeZeroCFABuilder(options, new AnalysisCache(),
					cha, scope);
			this.cg = cgb.makeCallGraph(options, null);
			this.pa = cgb.getPointerAnalysis();
			System.err.println(CallGraphStats.getStats(this.cg));
		} catch (Throwable e) {
			throw new Error(e);
		}
	}

	public void setExclusionFile(String fileName) {
		this.exclusionFile = fileName;
	}

	public void setContextSensitive(boolean cs) {
		this.contextSensitive = cs;
	}

	public void setDataDependenceOptions(DataDependenceOptions op) {
		this.dataOption = op;
	}

	public void setControlDependenceOptions(ControlDependenceOptions op) {
		this.controlOption = op;
	}

	public ClassHierarchy getClassHierarchy() {
		return this.cha;
	}

	public CallGraph getCallGraph() {
		return this.cg;
	}

	public PointerAnalysis getPointerAnalysis() {
		return this.pa;
	}

	public SlicingOutput outputSlice(Statement seed)
			throws IllegalArgumentException, CancelException {
		long startT = System.currentTimeMillis();
		Collection stmts = computeSlice(seed);
		System.out.println("Time cost for computation of backward slicing: "
				+ (System.currentTimeMillis() - startT) / 1000 + " s");
		Collection irs = convert(stmts);
		SlicingOutput output = new SlicingOutput(irs);
		return output;
	}

	public Collection computeSlice(Statement seed)
			throws IllegalArgumentException, CancelException {
		checkCG();
		// Statement s = this.seed;
		System.err.println("Statement: " + seed);

		// compute the slice as a collection of statements
		try {
			if (this.contextSensitive) {
				return computeContextSensitiveBackwardSlice(seed);
			} else {
				return this.computeContextInsensitiveBackwardThinSlice(seed);
			}
		} catch (Throwable e) {
			throw new RuntimeException(e);
		}
	}

	public Collection computeContextSensitiveBackwardSlice(
			Statement seed) throws IllegalArgumentException, CancelException {
		return computeConetxtSensitiveSlice(seed, this.cg, this.pa,
				this.dataOption, this.controlOption);
	}

	public Collection computeConetxtSensitiveSlice(Statement seed,
			CallGraph cg, PointerAnalysis pa,
			DataDependenceOptions dOptions, ControlDependenceOptions cOptions)
			throws IllegalArgumentException, CancelException {

		checkCG();
		System.err.println("Seed statement in context-sensitive slicing: "
				+ seed);
		System.err.println("Data dependence option: " + dOptions);
		System.err.println("Control dependence option: " + cOptions);

		// compute the slice as a collection of statements
		Collection slice = null;
		slice = Slicer.computeBackwardSlice(seed, cg, pa, dOptions, cOptions);
		return slice;
	}

	public Collection computeContextInsensitiveBackwardThinSlice(
			Statement seed) throws IllegalArgumentException, CancelException {
		return computeConetxtInsensitiveThinSlice(seed, this.cg, this.pa,
				this.dataOption, this.controlOption);
	}

	public Collection computeConetxtInsensitiveThinSlice(
			Statement seed, CallGraph cg, PointerAnalysis pa,
			DataDependenceOptions dOptions, ControlDependenceOptions cOptions)
			throws IllegalArgumentException, CancelException {
		checkCG();
		System.err.println("Seed statement in context-insensitive slicing: "
				+ seed);
		System.err.println("Data dependence option: " + dOptions);
		System.err.println("Control dependence option: " + cOptions);

		// initialize the slice
		if (slicer == null) {
			slicer = new CISlicer(cg, pa, dOptions, cOptions);
		}

		Collection slice = null;
		slice = slicer.computeBackwardThinSlice(seed);
		return slice;
	}

	private void checkCG() {
		if (this.cg == null) {
			throw new RuntimeException("Please call buildAnalysis() first.");
		}
	}

	public static void dumpSlice(Collection slice) {
		dumpSlice(slice, new PrintWriter(System.err));
	}

	public static void dumpSlice(Collection slice, PrintWriter w) {
		w.println("SLICE:\n");
		int i = 1;
		for (Statement s : slice) {
			String line = (i++) + "   " + s;
			w.println(line);
			w.flush();
		}
	}

	// dumping slice to a file
	public static void dumpSliceToFile(Collection slice,
			String fileName) throws FileNotFoundException {
		File f = new File(fileName);
		FileOutputStream fo = new FileOutputStream(f);
		PrintWriter w = new PrintWriter(fo);
		dumpSlice(slice, w);
	}

	// finding the main method
	public static CGNode findMainMethod(CallGraph cg) {
		Descriptor d = Descriptor.findOrCreateUTF8("([Ljava/lang/String;)V");
		Atom name = Atom.findOrCreateUnicodeAtom("main");
		return findMethod(cg, d, name);
	}

	/**
	 * @param cg
	 * @param d
	 * @param name
	 * @return
	 */
	// finding the method
	private static CGNode findMethod(CallGraph cg, Descriptor d, Atom name) {
		for (Iterator it = cg.getSuccNodes(cg
				.getFakeRootNode()); it.hasNext();) {
			CGNode n = it.next();
			if (n.getMethod().getName().equals(name)
					&& n.getMethod().getDescriptor().equals(d)) {
				return n;
			}
		}
		// if it's not a successor of fake root, just iterate over everything
		for (CGNode n : cg) {
			if (n.getMethod().getName().equals(name)
					&& n.getMethod().getDescriptor().equals(d)) {
				return n;
			}
		}
		Assertions.UNREACHABLE("failed to find method " + name);
		return null;
	}

	public static CGNode findMethod(CallGraph cg, String name) {
		Atom a = Atom.findOrCreateUnicodeAtom(name);
		for (Iterator it = cg.iterator(); it.hasNext();) {
			CGNode n = it.next();
			if (n.getMethod().getName().equals(a)) {
				return n;
			}
		}
		System.err.println("call graph " + cg);
		Assertions.UNREACHABLE("failed to find method " + name);
		return null;
	}

	public static Statement findCallTo(CGNode n, String methodName) {
		IR ir = n.getIR();
		for (Iterator it = ir.iterateAllInstructions(); it
				.hasNext();) {
			SSAInstruction s = it.next();
			if (s instanceof SSAInvokeInstruction) {
				SSAInvokeInstruction call = (SSAInvokeInstruction) s;
				if (call.getCallSite().getDeclaredTarget().getName().toString()
						.equals(methodName)) {
					IntSet indices = ir
							.getCallInstructionIndices(((SSAInvokeInstruction) s)
									.getCallSite());
					Assertions.productionAssertion(indices.size() == 1,
							"expected 1 but got " + indices.size());
					return new NormalStatement(n, indices.intIterator().next());
				}
			}
		}
		Assertions.UNREACHABLE("failed to find call to " + methodName + " in "
				+ n);
		return null;
	}

	public Statement extractStatementfromException(String className, int lineNum)
			throws InvalidClassFileException {

		for (CGNode node : cg) {
			String fullClassName = WALAUtils.getJavaFullClassName(node
					.getMethod().getDeclaringClass());
			if (fullClassName.equals(className)) {
				Iterator ssaIt = node.getIR()
						.iterateAllInstructions();
				while (ssaIt.hasNext()) {
					SSAInstruction inst = ssaIt.next();
					int i = WALAUtils.getInstructionIndex(node, inst);
					IBytecodeMethod method = (IBytecodeMethod) node.getIR()
							.getMethod();
					if (i == -1)
						continue;
					int bytecodeIndex = method.getBytecodeIndex(i);
					int sourceLineNum = method.getLineNumber(bytecodeIndex);
					if (sourceLineNum == lineNum) {
						// find it
						Statement s = new NormalStatement(node, i);
						return s;
					}
				}
			}
		}

		return null;
	}

	public static Collection convert(Collection stmts) {
		Collection irs = new LinkedList();

		for (Statement s : stmts) {
			if (s instanceof StatementWithInstructionIndex) {
				if (s.getNode().getMethod() instanceof ShrikeBTMethod) {
					try {
						IRStatement ir = new IRStatement(
								(StatementWithInstructionIndex) s);
						irs.add(ir);
					} catch (Throwable e) {
						// System.err.println("Error in IR: " + s);
						continue;
					}
				} else {
					// skip fake method
					// Log.logln("skip stmt: " + s + " in method: " +
					// s.getNode().getClass());
				}
			} else {
				// Log.logln("skip non-StatementWithInstructionIndex: " + s);
			}
		}
		return irs;
	}
	
	public Slicing initializeSlicing(final String jar, String pathToExclusionFile) {

		Slicing slicing = null;
		slicing = new Slicing(jar, "", pathToExclusionFile);
		slicing.CallGraphBuilder();
		slicing.setDataDependenceOptions(DataDependenceOptions.NO_BASE_NO_HEAP_NO_EXCEPTIONS);
		slicing.setControlDependenceOptions(ControlDependenceOptions.NO_EXCEPTIONAL_EDGES);
		slicing.setContextSensitive(true); // context-insensitive
		return slicing;

	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy