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

com.ibm.wala.examples.drivers.PDFSlice Maven / Gradle / Ivy

/*
 * Copyright (c) 2002 - 2006 IBM Corporation.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 */
package com.ibm.wala.examples.drivers;

import com.ibm.wala.classLoader.Language;
import com.ibm.wala.core.tests.callGraph.CallGraphTestUtil;
import com.ibm.wala.core.util.config.AnalysisScopeReader;
import com.ibm.wala.core.util.io.FileProvider;
import com.ibm.wala.core.viz.PDFViewUtil;
import com.ibm.wala.examples.properties.WalaExamplesProperties;
import com.ibm.wala.ipa.callgraph.AnalysisCacheImpl;
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.Entrypoint;
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.callgraph.util.CallGraphSearchUtil;
import com.ibm.wala.ipa.cha.ClassHierarchy;
import com.ibm.wala.ipa.cha.ClassHierarchyFactory;
import com.ibm.wala.ipa.slicer.HeapStatement;
import com.ibm.wala.ipa.slicer.NormalReturnCaller;
import com.ibm.wala.ipa.slicer.NormalStatement;
import com.ibm.wala.ipa.slicer.ParamCallee;
import com.ibm.wala.ipa.slicer.ParamCaller;
import com.ibm.wala.ipa.slicer.SDG;
import com.ibm.wala.ipa.slicer.Slicer;
import com.ibm.wala.ipa.slicer.Slicer.ControlDependenceOptions;
import com.ibm.wala.ipa.slicer.Slicer.DataDependenceOptions;
import com.ibm.wala.ipa.slicer.SlicerUtil;
import com.ibm.wala.ipa.slicer.Statement;
import com.ibm.wala.ipa.slicer.Statement.Kind;
import com.ibm.wala.properties.WalaProperties;
import com.ibm.wala.ssa.SSAAbstractInvokeInstruction;
import com.ibm.wala.ssa.SSAInstruction;
import com.ibm.wala.ssa.SSAInvokeInstruction;
import com.ibm.wala.types.TypeReference;
import com.ibm.wala.util.CancelException;
import com.ibm.wala.util.WalaException;
import com.ibm.wala.util.debug.Assertions;
import com.ibm.wala.util.graph.Graph;
import com.ibm.wala.util.graph.GraphIntegrity;
import com.ibm.wala.util.graph.GraphIntegrity.UnsoundGraphException;
import com.ibm.wala.util.graph.GraphSlicer;
import com.ibm.wala.util.io.CommandLine;
import com.ibm.wala.util.viz.DotUtil;
import com.ibm.wala.util.viz.NodeDecorator;
import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.Properties;

/**
 * This simple example WALA application computes a slice (see {@link Slicer}) and fires off the PDF
 * viewer to view a dot-ted representation of the slice.
 *
 * 

This is an example program on how to use the slicer. * *

See the 'PDFSlice' launcher included in the 'launchers' directory. * * @see Slicer * @author sfink */ public class PDFSlice { /** Name of the postscript file generated by dot */ private static final String PDF_FILE = "slice.pdf"; /** * Usage: PDFSlice -appJar [jar file name] -mainClass [main class] -srcCaller [method name] * -srcCallee [method name] -dd [data dependence options] -cd [control dependence options] -dir * [forward|backward] * *

    *
  • "jar file name" should be something like "c:/temp/testdata/java_cup.jar" *
  • "main class" should beshould be something like "c:/temp/testdata/java_cup.jar" *
  • "method name" should be the name of a method. This takes a slice from the statement that * calls "srcCallee" from "srcCaller" *
  • "data dependence options" can be one of "-full", "-no_base_ptrs", "-no_base_no_heap", * "-no_heap", "-no_base_no_heap_no_cast", or "-none". *
  • "control dependence options" can be "-full" or "-none" *
  • the -dir argument tells whether to compute a forwards or backwards slice. *
* * @see com.ibm.wala.ipa.slicer.Slicer.DataDependenceOptions */ public static void main(String[] args) throws IllegalArgumentException, CancelException, IOException { run(args); } /** see {@link #main(String[])} for command-line arguments */ public static Process run(String[] args) throws IllegalArgumentException, CancelException, IOException { // parse the command-line into a Properties object Properties p = CommandLine.parse(args); // validate that the command-line has the expected format validateCommandLine(p); // run the applications return run( p.getProperty("appJar"), p.getProperty("mainClass"), p.getProperty("srcCaller"), p.getProperty("srcCallee"), goBackward(p), PDFSDG.getDataDependenceOptions(p), PDFSDG.getControlDependenceOptions(p)); } /** Should the slice be a backwards slice? */ private static boolean goBackward(Properties p) { return !p.getProperty("dir", "backward").equals("forward"); } /** * Compute a slice from a call statements, dot it, and fire off the PDF viewer to visualize the * result * * @param appJar should be something like "c:/temp/testdata/java_cup.jar" * @param mainClass should be something like "c:/temp/testdata/java_cup.jar" * @param srcCaller name of the method containing the statement of interest * @param srcCallee name of the method called by the statement of interest * @param goBackward do a backward slice? * @param dOptions options controlling data dependence * @param cOptions options controlling control dependence * @return a Process running the PDF viewer to visualize the dot'ted representation of the slice */ public static Process run( String appJar, String mainClass, String srcCaller, String srcCallee, boolean goBackward, DataDependenceOptions dOptions, ControlDependenceOptions cOptions) throws IllegalArgumentException, CancelException, IOException { try { // create an analysis scope representing the appJar as a J2SE application AnalysisScope scope = AnalysisScopeReader.instance.makeJavaBinaryAnalysisScope( appJar, new FileProvider().getFile(CallGraphTestUtil.REGRESSION_EXCLUSIONS)); // build a class hierarchy, call graph, and system dependence graph ClassHierarchy cha = ClassHierarchyFactory.make(scope); Iterable entrypoints = com.ibm.wala.ipa.callgraph.impl.Util.makeMainEntrypoints(cha, mainClass); AnalysisOptions options = CallGraphTestUtil.makeAnalysisOptions(scope, entrypoints); CallGraphBuilder builder = Util.makeVanillaZeroOneCFABuilder(Language.JAVA, options, new AnalysisCacheImpl(), cha); // CallGraphBuilder builder = Util.makeZeroOneCFABuilder(options, new // AnalysisCache(), cha, scope); CallGraph cg = builder.makeCallGraph(options, null); SDG sdg = new SDG<>(cg, builder.getPointerAnalysis(), dOptions, cOptions); // find the call statement of interest CGNode callerNode = CallGraphSearchUtil.findMethod(cg, srcCaller); Statement s = SlicerUtil.findCallTo(callerNode, srcCallee); System.err.println("Statement: " + s); // compute the slice as a collection of statements final Collection slice; if (goBackward) { final PointerAnalysis pointerAnalysis = builder.getPointerAnalysis(); slice = Slicer.computeBackwardSlice(s, cg, pointerAnalysis, dOptions, cOptions); } else { // for forward slices ... we actually slice from the return value of // calls. s = getReturnStatementForCall(s); final PointerAnalysis pointerAnalysis = builder.getPointerAnalysis(); slice = Slicer.computeForwardSlice(s, cg, pointerAnalysis, dOptions, cOptions); } SlicerUtil.dumpSlice(slice); // create a view of the SDG restricted to nodes in the slice Graph g = pruneSDG(sdg, slice); sanityCheck(slice, g); // load Properties from standard WALA and the WALA examples project Properties p = null; try { p = WalaExamplesProperties.loadProperties(); p.putAll(WalaProperties.loadProperties()); } catch (WalaException e) { e.printStackTrace(); Assertions.UNREACHABLE(); } // create a dot representation. String psFile = p.getProperty(WalaProperties.OUTPUT_DIR) + File.separatorChar + PDF_FILE; String dotExe = p.getProperty(WalaExamplesProperties.DOT_EXE); DotUtil.dotify(g, makeNodeDecorator(), PDFTypeHierarchy.DOT_FILE, psFile, dotExe); // fire off the PDF viewer String gvExe = p.getProperty(WalaExamplesProperties.PDFVIEW_EXE); return PDFViewUtil.launchPDFView(psFile, gvExe); } catch (WalaException e) { // something bad happened. e.printStackTrace(); return null; } } /** * check that g is a well-formed graph, and that it contains exactly the number of nodes in the * slice */ private static void sanityCheck(Collection slice, Graph g) { try { GraphIntegrity.check(g); } catch (UnsoundGraphException e1) { e1.printStackTrace(); Assertions.UNREACHABLE(); } Assertions.productionAssertion( g.getNumberOfNodes() == slice.size(), "panic " + g.getNumberOfNodes() + " " + slice.size()); } /** If s is a call statement, return the statement representing the normal return from s */ public static Statement getReturnStatementForCall(Statement s) { if (s.getKind() == Kind.NORMAL) { NormalStatement n = (NormalStatement) s; SSAInstruction st = n.getInstruction(); if (st instanceof SSAInvokeInstruction) { SSAAbstractInvokeInstruction call = (SSAAbstractInvokeInstruction) st; if (call.getCallSite().getDeclaredTarget().getReturnType().equals(TypeReference.Void)) { throw new IllegalArgumentException( "this driver computes forward slices from the return value of calls.\n" + "Method " + call.getCallSite().getDeclaredTarget().getSignature() + " returns void."); } return new NormalReturnCaller(s.getNode(), n.getInstructionIndex()); } else { return s; } } else { return s; } } /** return a view of the sdg restricted to the statements in the slice */ public static Graph pruneSDG(SDG sdg, final Collection slice) { return GraphSlicer.prune(sdg, slice::contains); } /** * @return a NodeDecorator that decorates statements in a slice for a dot-ted representation */ public static NodeDecorator makeNodeDecorator() { return s -> { switch (s.getKind()) { case HEAP_PARAM_CALLEE: case HEAP_PARAM_CALLER: case HEAP_RET_CALLEE: case HEAP_RET_CALLER: HeapStatement h = (HeapStatement) s; return s.getKind() + "\\n" + h.getNode() + "\\n" + h.getLocation(); case NORMAL: NormalStatement n = (NormalStatement) s; return n.getInstruction() + "\\n" + n.getNode().getMethod().getSignature(); case PARAM_CALLEE: ParamCallee paramCallee = (ParamCallee) s; return s.getKind() + " " + paramCallee.getValueNumber() + "\\n" + s.getNode().getMethod().getName(); case PARAM_CALLER: ParamCaller paramCaller = (ParamCaller) s; return s.getKind() + " " + paramCaller.getValueNumber() + "\\n" + s.getNode().getMethod().getName() + "\\n" + paramCaller.getInstruction().getCallSite().getDeclaredTarget().getName(); case EXC_RET_CALLEE: case EXC_RET_CALLER: case NORMAL_RET_CALLEE: case NORMAL_RET_CALLER: case PHI: default: return s.toString(); } }; } /** * Validate that the command-line arguments obey the expected usage. * *

Usage: * *

    *
  • args[0] : "-appJar" *
  • args[1] : something like "c:/temp/testdata/java_cup.jar" *
  • args[2] : "-mainClass" *
  • args[3] : something like "Lslice/TestRecursion" * *
  • args[4] : "-srcCallee" *
  • args[5] : something like "print" * *
  • args[4] : "-srcCaller" *
  • args[5] : something like "main" *
* * @throws UnsupportedOperationException if command-line is malformed. */ static void validateCommandLine(Properties p) { if (p.get("appJar") == null) { throw new UnsupportedOperationException("expected command-line to include -appJar"); } if (p.get("mainClass") == null) { throw new UnsupportedOperationException("expected command-line to include -mainClass"); } if (p.get("srcCallee") == null) { throw new UnsupportedOperationException("expected command-line to include -srcCallee"); } if (p.get("srcCaller") == null) { throw new UnsupportedOperationException("expected command-line to include -srcCaller"); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy