From fd1dbc4dc5840649dff585c23325f4523e52733e Mon Sep 17 00:00:00 2001 From: Manu Sridharan Date: Sat, 30 Nov 2024 10:29:51 -0800 Subject: [PATCH] Update Gradle and add Spotless / GJF (#20) * Add Spotless / GJF * Update Gradle --- build.gradle | 23 ++- gradle/wrapper/gradle-wrapper.properties | 2 +- .../analysis/SimpleThreadEscapeAnalysis.java | 129 +++++++------ .../ContextInsensitiveReachingDefs.java | 77 ++++---- .../ContextSensitiveReachingDefs.java | 176 +++++++++--------- .../dataflow/IntraprocReachingDefs.java | 58 +++--- .../drivers/BoundedJSCallGraphDriver.java | 34 ++-- .../drivers/CSReachingDefsDriver.java | 118 ++++++------ .../examples/drivers/ConstructAllIRs.java | 36 ++-- .../drivers/DemandPointsToDriver.java | 1 - .../drivers/FieldBasedJSCallGraphDriver.java | 1 - .../examples/drivers/JSCallGraphDriver.java | 41 ++-- .../examples/drivers/PDFTypeHierarchy.java | 49 +++-- .../examples/drivers/PrintTypeHierarchy.java | 5 +- .../examples/drivers/ScopeFileCallGraph.java | 60 +++--- .../examples/drivers/SourceDirCallGraph.java | 9 +- .../ibm/wala/examples/util/ExampleUtil.java | 43 ++--- 17 files changed, 442 insertions(+), 420 deletions(-) diff --git a/build.gradle b/build.gradle index 8fb3c25f..3a687dac 100644 --- a/build.gradle +++ b/build.gradle @@ -1,8 +1,16 @@ -apply plugin: 'java-library' -apply plugin: 'application' -apply plugin: 'eclipse' +plugins { + id 'java-library' + id 'application' + id 'eclipse' + id("com.diffplug.spotless") version "6.25.0" +} + +java { + toolchain { + languageVersion = JavaLanguageVersion.of(11) + } +} -sourceCompatibility = 11 version = '0.1' jar { manifest { @@ -40,3 +48,10 @@ if (project.hasProperty('mainClass')) { // use a default mainClassName = "com.ibm.wala.examples.drivers.PDFTypeHierarchy" } + +spotless { + java { + // apply a specific flavor of google-java-format + googleJavaFormat() + } +} diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index df97d72b..e2847c82 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/src/main/java/com/ibm/wala/examples/analysis/SimpleThreadEscapeAnalysis.java b/src/main/java/com/ibm/wala/examples/analysis/SimpleThreadEscapeAnalysis.java index 752b29ff..3561d91f 100644 --- a/src/main/java/com/ibm/wala/examples/analysis/SimpleThreadEscapeAnalysis.java +++ b/src/main/java/com/ibm/wala/examples/analysis/SimpleThreadEscapeAnalysis.java @@ -11,14 +11,6 @@ *******************************************************************************/ package com.ibm.wala.examples.analysis; -import java.io.File; -import java.io.IOException; -import java.util.Collection; -import java.util.Iterator; -import java.util.Properties; -import java.util.Set; -import java.util.jar.JarFile; - import com.ibm.wala.classLoader.ArrayClass; import com.ibm.wala.classLoader.IClass; import com.ibm.wala.classLoader.IField; @@ -46,36 +38,39 @@ import com.ibm.wala.util.WalaException; import com.ibm.wala.util.collections.HashSetFactory; import com.ibm.wala.util.intset.OrdinalSet; +import java.io.File; +import java.io.IOException; +import java.util.Collection; +import java.util.Iterator; +import java.util.Properties; +import java.util.Set; +import java.util.jar.JarFile; /** - *

- * A simple thread-level escape analysis: this code computes the set of classes of which some instance may be accessed - * by some thread other than the one that created it. - *

- * - *

- * The algorithm is not very bright; it is based on the observation that there are only three ways for an object to pass - * from one thread to another. + * A simple thread-level escape analysis: this code computes the set of classes of which some + * instance may be accessed by some thread other than the one that created it. + * + *

The algorithm is not very bright; it is based on the observation that there are only three + * ways for an object to pass from one thread to another. + * *

- *

- * - *

- * This observation is implemented in the obvious way: + * + *

This observation is implemented in the obvious way: + * *

    - *
  1. All static fields are collected - *
  2. All Thread constructor parameters are collected - *
  3. The points-to sets of these values represent the base set of escapees. - *
  4. All object reachable from fields of these objects are added - *
  5. This process continues until a fixpoint is reached - *
  6. The abstract objects in the points-to sets are converted to types - *
  7. This set of types is returned + *
  8. All static fields are collected + *
  9. All Thread constructor parameters are collected + *
  10. The points-to sets of these values represent the base set of escapees. + *
  11. All object reachable from fields of these objects are added + *
  12. This process continues until a fixpoint is reached + *
  13. The abstract objects in the points-to sets are converted to types + *
  14. This set of types is returned *
- *

- * + * * @author Julian Dolby */ public class SimpleThreadEscapeAnalysis extends AbstractAnalysisEngine { @@ -85,7 +80,8 @@ public class SimpleThreadEscapeAnalysis extends AbstractAnalysisEngine { private final String applicationMainClass; /** - * The two input parameters define the program to analyze: the jars of .class files and the main class to start from. + * The two input parameters define the program to analyze: the jars of .class files and the main + * class to start from. */ public SimpleThreadEscapeAnalysis(Set applicationJarFiles, String applicationMainClass) { this.applicationJarFiles = applicationJarFiles; @@ -94,12 +90,13 @@ public SimpleThreadEscapeAnalysis(Set applicationJarFiles, String appli @Override protected CallGraphBuilder getCallGraphBuilder( - IClassHierarchy cha, AnalysisOptions options, IAnalysisCacheView cache) { + IClassHierarchy cha, AnalysisOptions options, IAnalysisCacheView cache) { return Util.makeZeroCFABuilder(Language.JAVA, options, cache, cha, scope); } /** - * Given a root path, add it to the set if it is a jar, or traverse it recursively if it is a directory. + * Given a root path, add it to the set if it is a jar, or traverse it recursively if it is a + * directory. */ private void collectJars(File f, Set result) throws IOException { if (f.isDirectory()) { @@ -114,9 +111,7 @@ private void collectJars(File f, Set result) throws IOException { } } - /** - * Collect the set of JarFiles that constitute the system libraries of the running JRE. - */ + /** Collect the set of JarFiles that constitute the system libraries of the running JRE. */ private JarFile[] getSystemJars() throws IOException { String javaHomePath = "garbage"; Set jarFiles = HashSetFactory.make(); @@ -148,12 +143,12 @@ private JarFile[] getSystemJars() throws IOException { } /** - * Take the given set of JarFiles that constitute the program, and return a set of Module files as expected by the - * WALA machinery. + * Take the given set of JarFiles that constitute the program, and return a set of Module files as + * expected by the WALA machinery. */ private Set getModuleFiles() { Set result = HashSetFactory.make(); - for (Iterator jars = applicationJarFiles.iterator(); jars.hasNext();) { + for (Iterator jars = applicationJarFiles.iterator(); jars.hasNext(); ) { result.add(new JarFileModule(jars.next())); } @@ -162,11 +157,12 @@ private Set getModuleFiles() { /** * The heart of the analysis. + * * @throws CancelException * @throws IllegalArgumentException */ - public Set gatherThreadEscapingClasses() throws IOException, ClassHierarchyException, IllegalArgumentException, - CancelException { + public Set gatherThreadEscapingClasses() + throws IOException, ClassHierarchyException, IllegalArgumentException, CancelException { // // set the application to analyze @@ -226,7 +222,7 @@ public Set gatherThreadEscapingClasses() throws IOException, ClassHierar // 1) static fields for (IClass cls : cha) { Collection staticFields = cls.getDeclaredStaticFields(); - for (Iterator sfs = staticFields.iterator(); sfs.hasNext();) { + for (Iterator sfs = staticFields.iterator(); sfs.hasNext(); ) { IField sf = sfs.next(); if (sf.getFieldTypeReference().isReferenceType()) { escapeAnalysisRoots.add(heapModel.getPointerKeyForStaticField(sf)); @@ -240,13 +236,13 @@ public Set gatherThreadEscapingClasses() throws IOException, ClassHierar // reachable from fields of types in these pointer keys, and all // Thread objects must be constructed somewhere) Collection threads = cha.computeSubClasses(TypeReference.JavaLangThread); - for (Iterator clss = threads.iterator(); clss.hasNext();) { + for (Iterator clss = threads.iterator(); clss.hasNext(); ) { IClass cls = clss.next(); - for (Iterator ms = cls.getDeclaredMethods().iterator(); ms.hasNext();) { + for (Iterator ms = cls.getDeclaredMethods().iterator(); ms.hasNext(); ) { IMethod m = ms.next(); if (m.isInit()) { Set nodes = cg.getNodes(m.getReference()); - for (Iterator ns = nodes.iterator(); ns.hasNext();) { + for (Iterator ns = nodes.iterator(); ns.hasNext(); ) { CGNode n = ns.next(); escapeAnalysisRoots.add(heapModel.getPointerKeyForLocal(n, 1)); } @@ -254,7 +250,7 @@ public Set gatherThreadEscapingClasses() throws IOException, ClassHierar } } - // + // // compute escaping types: all types flowing to escaping roots and // all types transitively reachable through their fields. // @@ -263,10 +259,10 @@ public Set gatherThreadEscapingClasses() throws IOException, ClassHierar // // pass 1: get abstract objects (instance keys) for escaping locations // - for (Iterator rts = escapeAnalysisRoots.iterator(); rts.hasNext();) { + for (Iterator rts = escapeAnalysisRoots.iterator(); rts.hasNext(); ) { PointerKey root = rts.next(); OrdinalSet objects = pa.getPointsToSet(root); - for (Iterator objs = objects.iterator(); objs.hasNext();) { + for (Iterator objs = objects.iterator(); objs.hasNext(); ) { InstanceKey obj = objs.next(); escapingInstanceKeys.add(obj); } @@ -278,7 +274,7 @@ public Set gatherThreadEscapingClasses() throws IOException, ClassHierar Set newKeys = HashSetFactory.make(); do { newKeys.clear(); - for (Iterator keys = escapingInstanceKeys.iterator(); keys.hasNext();) { + for (Iterator keys = escapingInstanceKeys.iterator(); keys.hasNext(); ) { InstanceKey key = keys.next(); IClass type = key.getConcreteType(); if (type.isReferenceType()) { @@ -286,7 +282,7 @@ public Set gatherThreadEscapingClasses() throws IOException, ClassHierar if (((ArrayClass) type).getElementClass() != null) { PointerKey fk = heapModel.getPointerKeyForArrayContents(key); OrdinalSet fobjects = pa.getPointsToSet(fk); - for (Iterator fobjs = fobjects.iterator(); fobjs.hasNext();) { + for (Iterator fobjs = fobjects.iterator(); fobjs.hasNext(); ) { InstanceKey fobj = fobjs.next(); if (!escapingInstanceKeys.contains(fobj)) { newKeys.add(fobj); @@ -295,12 +291,12 @@ public Set gatherThreadEscapingClasses() throws IOException, ClassHierar } } else { Collection fields = type.getAllInstanceFields(); - for (Iterator fs = fields.iterator(); fs.hasNext();) { + for (Iterator fs = fields.iterator(); fs.hasNext(); ) { IField f = fs.next(); if (f.getFieldTypeReference().isReferenceType()) { PointerKey fk = heapModel.getPointerKeyForInstanceField(key, f); OrdinalSet fobjects = pa.getPointsToSet(fk); - for (Iterator fobjs = fobjects.iterator(); fobjs.hasNext();) { + for (Iterator fobjs = fobjects.iterator(); fobjs.hasNext(); ) { InstanceKey fobj = fobjs.next(); if (!escapingInstanceKeys.contains(fobj)) { newKeys.add(fobj); @@ -318,7 +314,7 @@ public Set gatherThreadEscapingClasses() throws IOException, ClassHierar // get set of types from set of instance keys // Set escapingTypes = HashSetFactory.make(); - for (Iterator keys = escapingInstanceKeys.iterator(); keys.hasNext();) { + for (Iterator keys = escapingInstanceKeys.iterator(); keys.hasNext(); ) { InstanceKey key = keys.next(); escapingTypes.add(key.getConcreteType()); } @@ -327,14 +323,17 @@ public Set gatherThreadEscapingClasses() throws IOException, ClassHierar } /** - * This main program shows one example use of thread escape analysis: producing a set of fields to be monitored for a - * dynamic race detector. The idea is that any field might have a race with two exceptions: final fields do not have - * races since there are no writes to them, and volatile fields have atomic read and write semantics provided by the - * VM. Hence, this piece of code produces a list of all other fields. + * This main program shows one example use of thread escape analysis: producing a set of fields to + * be monitored for a dynamic race detector. The idea is that any field might have a race with two + * exceptions: final fields do not have races since there are no writes to them, and volatile + * fields have atomic read and write semantics provided by the VM. Hence, this piece of code + * produces a list of all other fields. + * * @throws CancelException * @throws IllegalArgumentException */ - public static void main(String[] args) throws IOException, ClassHierarchyException, IllegalArgumentException, CancelException { + public static void main(String[] args) + throws IOException, ClassHierarchyException, IllegalArgumentException, CancelException { String mainClassName = args[0]; Set jars = HashSetFactory.make(); @@ -342,12 +341,13 @@ public static void main(String[] args) throws IOException, ClassHierarchyExcepti jars.add(new JarFile(args[i])); } - Set escapingTypes = (new SimpleThreadEscapeAnalysis(jars, mainClassName)).gatherThreadEscapingClasses(); + Set escapingTypes = + (new SimpleThreadEscapeAnalysis(jars, mainClassName)).gatherThreadEscapingClasses(); - for (Iterator types = escapingTypes.iterator(); types.hasNext();) { + for (Iterator types = escapingTypes.iterator(); types.hasNext(); ) { IClass cls = types.next(); if (!cls.isArrayClass()) { - for (Iterator fs = cls.getAllFields().iterator(); fs.hasNext();) { + for (Iterator fs = cls.getAllFields().iterator(); fs.hasNext(); ) { IField f = fs.next(); if (!f.isVolatile() && !f.isFinal()) { System.err.println(f.getReference()); @@ -356,5 +356,4 @@ public static void main(String[] args) throws IOException, ClassHierarchyExcepti } } } - -} \ No newline at end of file +} diff --git a/src/main/java/com/ibm/wala/examples/analysis/dataflow/ContextInsensitiveReachingDefs.java b/src/main/java/com/ibm/wala/examples/analysis/dataflow/ContextInsensitiveReachingDefs.java index 83615e65..b61b10a5 100644 --- a/src/main/java/com/ibm/wala/examples/analysis/dataflow/ContextInsensitiveReachingDefs.java +++ b/src/main/java/com/ibm/wala/examples/analysis/dataflow/ContextInsensitiveReachingDefs.java @@ -10,9 +10,6 @@ *******************************************************************************/ package com.ibm.wala.examples.analysis.dataflow; -import java.util.ArrayList; -import java.util.Map; - import com.ibm.wala.classLoader.IField; import com.ibm.wala.dataflow.graph.AbstractMeetOperator; import com.ibm.wala.dataflow.graph.BitVectorFramework; @@ -39,30 +36,29 @@ import com.ibm.wala.util.collections.Pair; import com.ibm.wala.util.intset.BitVector; import com.ibm.wala.util.intset.OrdinalSetMapping; +import java.util.ArrayList; +import java.util.Map; /** * Computes interprocedural reaching definitions for static fields in a context-insensitive manner. */ public class ContextInsensitiveReachingDefs { - /** - * the exploded interprocedural control-flow graph on which to compute the analysis - */ + /** the exploded interprocedural control-flow graph on which to compute the analysis */ private final ExplodedInterproceduralCFG icfg; /** - * maps call graph node and instruction index of putstatic instructions to more compact numbering for bitvectors + * maps call graph node and instruction index of putstatic instructions to more compact numbering + * for bitvectors */ private final OrdinalSetMapping> putInstrNumbering; - /** - * for resolving field references in putstatic instructions - */ + /** for resolving field references in putstatic instructions */ private final IClassHierarchy cha; /** - * maps each static field to the numbers of the statements (in {@link #putInstrNumbering}) that define it; used for kills in flow - * functions + * maps each static field to the numbers of the statements (in {@link #putInstrNumbering}) that + * define it; used for kills in flow functions */ private final Map staticField2DefStatements = HashMapFactory.make(); @@ -74,9 +70,7 @@ public ContextInsensitiveReachingDefs(ExplodedInterproceduralCFG icfg, IClassHie this.putInstrNumbering = numberPutStatics(); } - /** - * generate a numbering of the putstatic instructions - */ + /** generate a numbering of the putstatic instructions */ @SuppressWarnings("unchecked") private OrdinalSetMapping> numberPutStatics() { ArrayList> putInstrs = new ArrayList>(); @@ -88,7 +82,8 @@ private OrdinalSetMapping> numberPutStatics() { SSAInstruction[] instructions = ir.getInstructions(); for (int i = 0; i < instructions.length; i++) { SSAInstruction instruction = instructions[i]; - if (instruction instanceof SSAPutInstruction && ((SSAPutInstruction) instruction).isStatic()) { + if (instruction instanceof SSAPutInstruction + && ((SSAPutInstruction) instruction).isStatic()) { SSAPutInstruction putInstr = (SSAPutInstruction) instruction; // instrNum is the number that will be assigned to this putstatic int instrNum = putInstrs.size(); @@ -105,26 +100,29 @@ private OrdinalSetMapping> numberPutStatics() { } } } - return new ObjectArrayMapping>(putInstrs.toArray(new Pair[putInstrs.size()])); + return new ObjectArrayMapping>( + putInstrs.toArray(new Pair[putInstrs.size()])); } - private class TransferFunctions implements ITransferFunctionProvider, BitVectorVariable> { + private class TransferFunctions + implements ITransferFunctionProvider< + BasicBlockInContext, BitVectorVariable> { - /** - * our meet operator is set union - */ + /** our meet operator is set union */ @Override public AbstractMeetOperator getMeetOperator() { return BitVectorUnion.instance(); } @Override - public UnaryOperator getNodeTransferFunction(BasicBlockInContext node) { + public UnaryOperator getNodeTransferFunction( + BasicBlockInContext node) { IExplodedBasicBlock ebb = node.getDelegate(); SSAInstruction instruction = ebb.getInstruction(); int instructionIndex = ebb.getFirstInstructionIndex(); CGNode cgNode = node.getNode(); - if (instruction instanceof SSAPutInstruction && ((SSAPutInstruction) instruction).isStatic()) { + if (instruction instanceof SSAPutInstruction + && ((SSAPutInstruction) instruction).isStatic()) { // kill all defs of the same static field, and gen this instruction final SSAPutInstruction putInstr = (SSAPutInstruction) instruction; final IField field = cha.resolveField(putInstr.getDeclaredField()); @@ -140,8 +138,8 @@ public UnaryOperator getNodeTransferFunction(BasicBlockInCont } /** - * here we need an edge transfer function for call-to-return edges (see - * {@link #getEdgeTransferFunction(BasicBlockInContext, BasicBlockInContext)}) + * here we need an edge transfer function for call-to-return edges (see {@link + * #getEdgeTransferFunction(BasicBlockInContext, BasicBlockInContext)}) */ @Override public boolean hasEdgeTransferFunctions() { @@ -154,11 +152,12 @@ public boolean hasNodeTransferFunctions() { } /** - * for direct call-to-return edges at a call site, the edge transfer function will kill all facts, since we only want to - * consider facts that arise from going through the callee + * for direct call-to-return edges at a call site, the edge transfer function will kill all + * facts, since we only want to consider facts that arise from going through the callee */ @Override - public UnaryOperator getEdgeTransferFunction(BasicBlockInContext src, + public UnaryOperator getEdgeTransferFunction( + BasicBlockInContext src, BasicBlockInContext dst) { if (isCallToReturnEdge(src, dst)) { return BitVectorKillAll.instance(); @@ -167,24 +166,27 @@ public UnaryOperator getEdgeTransferFunction(BasicBlockInCont } } - private boolean isCallToReturnEdge(BasicBlockInContext src, BasicBlockInContext dst) { + private boolean isCallToReturnEdge( + BasicBlockInContext src, + BasicBlockInContext dst) { SSAInstruction srcInst = src.getDelegate().getInstruction(); return srcInst instanceof SSAAbstractInvokeInstruction && src.getNode().equals(dst.getNode()); } - } /** * run the analysis - * + * * @return the solver used for the analysis, which contains the analysis result */ public BitVectorSolver> analyze() { - // the framework describes the dataflow problem, in particular the underlying graph and the transfer functions - BitVectorFramework, Pair> framework = new BitVectorFramework, Pair>( - icfg, new TransferFunctions(), putInstrNumbering); - BitVectorSolver> solver = new BitVectorSolver>( - framework); + // the framework describes the dataflow problem, in particular the underlying graph and the + // transfer functions + BitVectorFramework, Pair> framework = + new BitVectorFramework, Pair>( + icfg, new TransferFunctions(), putInstrNumbering); + BitVectorSolver> solver = + new BitVectorSolver>(framework); try { solver.solve(null); } catch (CancelException e) { @@ -203,7 +205,8 @@ public BitVectorSolver> analyze() { } /** - * gets putstatic instruction corresponding to some fact number from a bitvector in the analysis result + * gets putstatic instruction corresponding to some fact number from a bitvector in the analysis + * result */ public Pair getNodeAndInstrForNumber(int num) { return putInstrNumbering.getMappedObject(num); diff --git a/src/main/java/com/ibm/wala/examples/analysis/dataflow/ContextSensitiveReachingDefs.java b/src/main/java/com/ibm/wala/examples/analysis/dataflow/ContextSensitiveReachingDefs.java index 82f980b3..3907407d 100644 --- a/src/main/java/com/ibm/wala/examples/analysis/dataflow/ContextSensitiveReachingDefs.java +++ b/src/main/java/com/ibm/wala/examples/analysis/dataflow/ContextSensitiveReachingDefs.java @@ -10,8 +10,6 @@ *******************************************************************************/ package com.ibm.wala.examples.analysis.dataflow; -import java.util.Collection; - import com.ibm.wala.classLoader.IField; import com.ibm.wala.dataflow.IFDS.ICFGSupergraph; import com.ibm.wala.dataflow.IFDS.IFlowFunction; @@ -41,51 +39,46 @@ import com.ibm.wala.util.intset.IntSet; import com.ibm.wala.util.intset.MutableMapping; import com.ibm.wala.util.intset.MutableSparseIntSet; +import java.util.Collection; /** - * Computes interprocedural reaching definitions for static fields in a context-sensitive manner via {@link TabulationSolver - * tabulation}. + * Computes interprocedural reaching definitions for static fields in a context-sensitive manner via + * {@link TabulationSolver tabulation}. */ public class ContextSensitiveReachingDefs { - /** - * used for resolving field references in putstatic instructions - */ + /** used for resolving field references in putstatic instructions */ private final IClassHierarchy cha; - /** - * the supergraph over which tabulation is performed - */ + /** the supergraph over which tabulation is performed */ private final ISupergraph, CGNode> supergraph; - /** - * the tabulation domain - */ + /** the tabulation domain */ private final ReachingDefsDomain domain = new ReachingDefsDomain(); public ContextSensitiveReachingDefs(CallGraph cg, AnalysisCache cache) { this.cha = cg.getClassHierarchy(); - // we use an ICFGSupergraph, which basically adapts ExplodedInterproceduralCFG to the ISupergraph interface + // we use an ICFGSupergraph, which basically adapts ExplodedInterproceduralCFG to the + // ISupergraph interface this.supergraph = ICFGSupergraph.make(cg); } - /** - * controls numbering of putstatic instructions for use in tabulation - */ + /** controls numbering of putstatic instructions for use in tabulation */ @SuppressWarnings("serial") -private class ReachingDefsDomain extends MutableMapping> implements - TabulationDomain, BasicBlockInContext> { + private class ReachingDefsDomain extends MutableMapping> + implements TabulationDomain, BasicBlockInContext> { @Override - public boolean hasPriorityOver(PathEdge> p1, + public boolean hasPriorityOver( + PathEdge> p1, PathEdge> p2) { // don't worry about worklist priorities return false; } - } - private class ReachingDefsFlowFunctions implements IPartiallyBalancedFlowFunctions> { + private class ReachingDefsFlowFunctions + implements IPartiallyBalancedFlowFunctions> { private final ReachingDefsDomain domain; @@ -94,50 +87,54 @@ protected ReachingDefsFlowFunctions(ReachingDefsDomain domain) { } /** - * the flow function for flow from a callee to caller where there was no flow from caller to callee; just the identity function - * + * the flow function for flow from a callee to caller where there was no flow from caller to + * callee; just the identity function + * * @see ReachingDefsProblem */ @Override - public IFlowFunction getUnbalancedReturnFlowFunction(BasicBlockInContext src, + public IFlowFunction getUnbalancedReturnFlowFunction( + BasicBlockInContext src, BasicBlockInContext dest) { return IdentityFlowFunction.identity(); } - /** - * flow function from caller to callee; just the identity function - */ + /** flow function from caller to callee; just the identity function */ @Override - public IUnaryFlowFunction getCallFlowFunction(BasicBlockInContext src, - BasicBlockInContext dest, BasicBlockInContext ret) { + public IUnaryFlowFunction getCallFlowFunction( + BasicBlockInContext src, + BasicBlockInContext dest, + BasicBlockInContext ret) { return IdentityFlowFunction.identity(); } /** - * flow function from call node to return node when there are no targets for the call site; not a case we are expecting + * flow function from call node to return node when there are no targets for the call site; not + * a case we are expecting */ @Override - public IUnaryFlowFunction getCallNoneToReturnFlowFunction(BasicBlockInContext src, + public IUnaryFlowFunction getCallNoneToReturnFlowFunction( + BasicBlockInContext src, BasicBlockInContext dest) { // if we're missing callees, just keep what information we have return IdentityFlowFunction.identity(); } /** - * flow function from call node to return node at a call site when callees exist. We kill everything; surviving facts should - * flow out of the callee + * flow function from call node to return node at a call site when callees exist. We kill + * everything; surviving facts should flow out of the callee */ @Override - public IUnaryFlowFunction getCallToReturnFlowFunction(BasicBlockInContext src, + public IUnaryFlowFunction getCallToReturnFlowFunction( + BasicBlockInContext src, BasicBlockInContext dest) { return KillEverything.singleton(); } - /** - * flow function for normal intraprocedural edges - */ + /** flow function for normal intraprocedural edges */ @Override - public IUnaryFlowFunction getNormalFlowFunction(final BasicBlockInContext src, + public IUnaryFlowFunction getNormalFlowFunction( + final BasicBlockInContext src, BasicBlockInContext dest) { final IExplodedBasicBlock ebb = src.getDelegate(); SSAInstruction instruction = ebb.getInstruction(); @@ -149,16 +146,21 @@ public IUnaryFlowFunction getNormalFlowFunction(final BasicBlockInContext otherPutInstrAndNode = domain.getMappedObject(d1); - SSAPutInstruction otherPutInstr = (SSAPutInstruction) otherPutInstrAndNode.fst.getIR().getInstructions()[otherPutInstrAndNode.snd]; + SSAPutInstruction otherPutInstr = + (SSAPutInstruction) + otherPutInstrAndNode.fst.getIR() + .getInstructions()[otherPutInstrAndNode.snd]; IField otherStaticField = cha.resolveField(otherPutInstr.getDeclaredField()); if (!staticField.equals(otherStaticField)) { result.add(d1); @@ -178,57 +180,62 @@ public String toString() { return IdentityFlowFunction.identity(); } - /** - * standard flow function from callee to caller; just identity - */ + /** standard flow function from callee to caller; just identity */ @Override - public IFlowFunction getReturnFlowFunction(BasicBlockInContext call, - BasicBlockInContext src, BasicBlockInContext dest) { + public IFlowFunction getReturnFlowFunction( + BasicBlockInContext call, + BasicBlockInContext src, + BasicBlockInContext dest) { return IdentityFlowFunction.identity(); } - } /** - * Definition of the reaching definitions tabulation problem. Note that we choose to make the problem a partially - * balanced tabulation problem, where the solver is seeded with the putstatic instructions themselves. The problem is partially - * balanced since a definition in a callee used as a seed for the analysis may then reach a caller, yielding a "return" without a - * corresponding "call." An alternative to this approach, used in the Reps-Horwitz-Sagiv POPL95 paper, would be to "lift" the - * domain of putstatic instructions with a 0 (bottom) element, have a 0->0 transition in all transfer functions, and then seed the - * analysis with the path edge (main_entry, 0) -> (main_entry, 0). We choose the partially-balanced approach to avoid pollution of - * the flow functions. - * + * Definition of the reaching definitions tabulation problem. Note that we choose to make the + * problem a partially balanced tabulation problem, where the solver is seeded with the + * putstatic instructions themselves. The problem is partially balanced since a definition in a + * callee used as a seed for the analysis may then reach a caller, yielding a "return" without a + * corresponding "call." An alternative to this approach, used in the Reps-Horwitz-Sagiv POPL95 + * paper, would be to "lift" the domain of putstatic instructions with a 0 (bottom) element, have + * a 0->0 transition in all transfer functions, and then seed the analysis with the path edge + * (main_entry, 0) -> (main_entry, 0). We choose the partially-balanced approach to avoid + * pollution of the flow functions. */ - private class ReachingDefsProblem implements - PartiallyBalancedTabulationProblem, CGNode, Pair> { + private class ReachingDefsProblem + implements PartiallyBalancedTabulationProblem< + BasicBlockInContext, CGNode, Pair> { private ReachingDefsFlowFunctions flowFunctions = new ReachingDefsFlowFunctions(domain); - /** - * path edges corresponding to all putstatic instructions, used as seeds for the analysis - */ - private Collection>> initialSeeds = collectInitialSeeds(); + /** path edges corresponding to all putstatic instructions, used as seeds for the analysis */ + private Collection>> initialSeeds = + collectInitialSeeds(); /** - * we use the entry block of the CGNode as the fake entry when propagating from callee to caller with unbalanced parens + * we use the entry block of the CGNode as the fake entry when propagating from callee to caller + * with unbalanced parens */ @Override - public BasicBlockInContext getFakeEntry(BasicBlockInContext node) { + public BasicBlockInContext getFakeEntry( + BasicBlockInContext node) { final CGNode cgNode = node.getNode(); return getFakeEntry(cgNode); } /** - * we use the entry block of the CGNode as the "fake" entry when propagating from callee to caller with unbalanced parens + * we use the entry block of the CGNode as the "fake" entry when propagating from callee to + * caller with unbalanced parens */ private BasicBlockInContext getFakeEntry(final CGNode cgNode) { - BasicBlockInContext[] entriesForProcedure = supergraph.getEntriesForProcedure(cgNode); + BasicBlockInContext[] entriesForProcedure = + supergraph.getEntriesForProcedure(cgNode); assert entriesForProcedure.length == 1; return entriesForProcedure[0]; } /** - * collect the putstatic instructions in the call graph as {@link PathEdge} seeds for the analysis + * collect the putstatic instructions in the call graph as {@link PathEdge} seeds for the + * analysis */ private Collection>> collectInitialSeeds() { Collection>> result = HashSetFactory.make(); @@ -244,7 +251,6 @@ private Collection>> collectIn BasicBlockInContext fakeEntry = getFakeEntry(cgNode); // note that the fact number used for the source of this path edge doesn't really matter result.add(PathEdge.createPathEdge(fakeEntry, factNum, bb, factNum)); - } } } @@ -252,18 +258,18 @@ private Collection>> collectIn } @Override - public IPartiallyBalancedFlowFunctions> getFunctionMap() { + public IPartiallyBalancedFlowFunctions> + getFunctionMap() { return flowFunctions; } @Override - public TabulationDomain, BasicBlockInContext> getDomain() { + public TabulationDomain, BasicBlockInContext> + getDomain() { return domain; } - /** - * we don't need a merge function; the default unioning of tabulation works fine - */ + /** we don't need a merge function; the default unioning of tabulation works fine */ @Override public IMergeFunction getMergeFunction() { return null; @@ -278,31 +284,33 @@ public ISupergraph, CGNode> getSupergra public Collection>> initialSeeds() { return initialSeeds; } - } - /** - * perform the tabulation analysis and return the {@link TabulationResult} - */ - public TabulationResult, CGNode, Pair> analyze() { - PartiallyBalancedTabulationSolver, CGNode, Pair> solver = PartiallyBalancedTabulationSolver - .createPartiallyBalancedTabulationSolver(new ReachingDefsProblem(), null); - TabulationResult, CGNode, Pair> result = null; + /** perform the tabulation analysis and return the {@link TabulationResult} */ + public TabulationResult, CGNode, Pair> + analyze() { + PartiallyBalancedTabulationSolver< + BasicBlockInContext, CGNode, Pair> + solver = + PartiallyBalancedTabulationSolver.createPartiallyBalancedTabulationSolver( + new ReachingDefsProblem(), null); + TabulationResult, CGNode, Pair> + result = null; try { result = solver.solve(); } catch (CancelException e) { - // this shouldn't happen + // this shouldn't happen assert false; } return result; - } public ISupergraph, CGNode> getSupergraph() { return supergraph; } - public TabulationDomain, BasicBlockInContext> getDomain() { + public TabulationDomain, BasicBlockInContext> + getDomain() { return domain; } } diff --git a/src/main/java/com/ibm/wala/examples/analysis/dataflow/IntraprocReachingDefs.java b/src/main/java/com/ibm/wala/examples/analysis/dataflow/IntraprocReachingDefs.java index eca082f2..66d56c4e 100644 --- a/src/main/java/com/ibm/wala/examples/analysis/dataflow/IntraprocReachingDefs.java +++ b/src/main/java/com/ibm/wala/examples/analysis/dataflow/IntraprocReachingDefs.java @@ -10,9 +10,6 @@ *******************************************************************************/ package com.ibm.wala.examples.analysis.dataflow; -import java.util.ArrayList; -import java.util.Map; - import com.ibm.wala.classLoader.IField; import com.ibm.wala.dataflow.graph.AbstractMeetOperator; import com.ibm.wala.dataflow.graph.BitVectorFramework; @@ -34,19 +31,18 @@ import com.ibm.wala.util.collections.ObjectArrayMapping; import com.ibm.wala.util.intset.BitVector; import com.ibm.wala.util.intset.OrdinalSetMapping; +import java.util.ArrayList; +import java.util.Map; /** - * Compute intraprocedural reaching defs of global variables, i.e., the defs are - * {@link SSAPutInstruction}s on static state. - * + * Compute intraprocedural reaching defs of global variables, i.e., the defs are {@link + * SSAPutInstruction}s on static state. + * * @author manu - * */ public class IntraprocReachingDefs { - /** - * the exploded control-flow graph on which to compute the analysis - */ + /** the exploded control-flow graph on which to compute the analysis */ private final ExplodedControlFlowGraph ecfg; /** @@ -54,14 +50,12 @@ public class IntraprocReachingDefs { */ private final OrdinalSetMapping putInstrNumbering; - /** - * used to resolve references to fields in putstatic instructions - */ + /** used to resolve references to fields in putstatic instructions */ private final IClassHierarchy cha; /** - * maps each static field to the numbers of the statements (in {@link #putInstrNumbering}) that define it; used for kills in flow - * functions + * maps each static field to the numbers of the statements (in {@link #putInstrNumbering}) that + * define it; used for kills in flow functions */ private final Map staticField2DefStatements = HashMapFactory.make(); @@ -73,16 +67,15 @@ public IntraprocReachingDefs(ExplodedControlFlowGraph ecfg, IClassHierarchy cha) this.putInstrNumbering = numberPutStatics(); } - /** - * generate a numbering of the putstatic instructions - */ + /** generate a numbering of the putstatic instructions */ private OrdinalSetMapping numberPutStatics() { ArrayList putInstrs = new ArrayList(); IR ir = ecfg.getIR(); SSAInstruction[] instructions = ir.getInstructions(); for (int i = 0; i < instructions.length; i++) { SSAInstruction instruction = instructions[i]; - if (instruction instanceof SSAPutInstruction && ((SSAPutInstruction) instruction).isStatic()) { + if (instruction instanceof SSAPutInstruction + && ((SSAPutInstruction) instruction).isStatic()) { SSAPutInstruction putInstr = (SSAPutInstruction) instruction; // instrNum is the number that will be assigned to this putstatic int instrNum = putInstrs.size(); @@ -101,16 +94,16 @@ private OrdinalSetMapping numberPutStatics() { return new ObjectArrayMapping(putInstrs.toArray(new Integer[putInstrs.size()])); } - private class TransferFunctions implements ITransferFunctionProvider { + private class TransferFunctions + implements ITransferFunctionProvider { @Override - public UnaryOperator getEdgeTransferFunction(IExplodedBasicBlock src, IExplodedBasicBlock dst) { + public UnaryOperator getEdgeTransferFunction( + IExplodedBasicBlock src, IExplodedBasicBlock dst) { throw new UnsupportedOperationException(); } - /** - * our meet operator is set union - */ + /** our meet operator is set union */ @Override public AbstractMeetOperator getMeetOperator() { return BitVectorUnion.instance(); @@ -120,7 +113,8 @@ public AbstractMeetOperator getMeetOperator() { public UnaryOperator getNodeTransferFunction(IExplodedBasicBlock node) { SSAInstruction instruction = node.getInstruction(); int instructionIndex = node.getFirstInstructionIndex(); - if (instruction instanceof SSAPutInstruction && ((SSAPutInstruction) instruction).isStatic()) { + if (instruction instanceof SSAPutInstruction + && ((SSAPutInstruction) instruction).isStatic()) { // kill all defs of the same static field, and gen this instruction final SSAPutInstruction putInstr = (SSAPutInstruction) instruction; final IField field = cha.resolveField(putInstr.getDeclaredField()); @@ -145,19 +139,21 @@ public boolean hasEdgeTransferFunctions() { public boolean hasNodeTransferFunctions() { return true; } - } /** * run the analysis - * + * * @return the solver used for the analysis, which contains the analysis result */ public BitVectorSolver analyze() { - // the framework describes the dataflow problem, in particular the underlying graph and the transfer functions - BitVectorFramework framework = new BitVectorFramework(ecfg, - new TransferFunctions(), putInstrNumbering); - BitVectorSolver solver = new BitVectorSolver(framework); + // the framework describes the dataflow problem, in particular the underlying graph and the + // transfer functions + BitVectorFramework framework = + new BitVectorFramework( + ecfg, new TransferFunctions(), putInstrNumbering); + BitVectorSolver solver = + new BitVectorSolver(framework); try { solver.solve(null); } catch (CancelException e) { diff --git a/src/main/java/com/ibm/wala/examples/drivers/BoundedJSCallGraphDriver.java b/src/main/java/com/ibm/wala/examples/drivers/BoundedJSCallGraphDriver.java index 25d290c2..035cc1af 100644 --- a/src/main/java/com/ibm/wala/examples/drivers/BoundedJSCallGraphDriver.java +++ b/src/main/java/com/ibm/wala/examples/drivers/BoundedJSCallGraphDriver.java @@ -9,28 +9,26 @@ import com.ibm.wala.util.CancelException; import com.ibm.wala.util.NullProgressMonitor; import com.ibm.wala.util.WalaException; - import java.io.IOException; -import java.net.URL; import java.nio.file.Path; import java.nio.file.Paths; public class BoundedJSCallGraphDriver { - /** - * Driver for building indirection-bounded approximate call graphs. - * - * Usage: BoundedJSCallGraphDriver script_directory bound - */ - public static void main(String[] args) - throws IllegalArgumentException, IOException, CancelException, WalaException { - Path scriptDir = Paths.get(args[0]); - int bound = Integer.parseInt(args[1]); - FieldBasedCGUtil f = new FieldBasedCGUtil(new CAstRhinoTranslatorFactory()); - FieldBasedCallGraphBuilder.CallGraphResult results = - f.buildScriptDirBoundedCG(scriptDir, new NullProgressMonitor(), false, bound); - CallGraph CG = results.getCallGraph(); - System.out.println(CallGraphStats.getStats(CG)); - System.out.println((new CallGraph2JSON()).serialize(CG)); - } + /** + * Driver for building indirection-bounded approximate call graphs. + * + *

Usage: BoundedJSCallGraphDriver script_directory bound + */ + public static void main(String[] args) + throws IllegalArgumentException, IOException, CancelException, WalaException { + Path scriptDir = Paths.get(args[0]); + int bound = Integer.parseInt(args[1]); + FieldBasedCGUtil f = new FieldBasedCGUtil(new CAstRhinoTranslatorFactory()); + FieldBasedCallGraphBuilder.CallGraphResult results = + f.buildScriptDirBoundedCG(scriptDir, new NullProgressMonitor(), false, bound); + CallGraph CG = results.getCallGraph(); + System.out.println(CallGraphStats.getStats(CG)); + System.out.println((new CallGraph2JSON()).serialize(CG)); + } } diff --git a/src/main/java/com/ibm/wala/examples/drivers/CSReachingDefsDriver.java b/src/main/java/com/ibm/wala/examples/drivers/CSReachingDefsDriver.java index ae366d8f..fec1d82f 100644 --- a/src/main/java/com/ibm/wala/examples/drivers/CSReachingDefsDriver.java +++ b/src/main/java/com/ibm/wala/examples/drivers/CSReachingDefsDriver.java @@ -1,8 +1,5 @@ package com.ibm.wala.examples.drivers; -import java.io.IOException; -import java.util.Properties; - import com.ibm.wala.core.util.config.AnalysisScopeReader; import com.ibm.wala.core.util.warnings.Warnings; import com.ibm.wala.dataflow.IFDS.ISupergraph; @@ -28,64 +25,69 @@ import com.ibm.wala.ssa.analysis.IExplodedBasicBlock; import com.ibm.wala.util.collections.Pair; import com.ibm.wala.util.io.CommandLine; +import java.io.IOException; +import java.util.Properties; - -/** - * Driver for running {@link ContextSensitiveReachingDefs} - * - */ +/** Driver for running {@link ContextSensitiveReachingDefs} */ public class CSReachingDefsDriver { - /** - * Usage: CSReachingDefsDriver -scopeFile file_path -mainClass class_name - * - * Uses main() method of class_name as entrypoint. - * - * @throws IOException - * @throws ClassHierarchyException - * @throws CallGraphBuilderCancelException - * @throws IllegalArgumentException - */ - public static void main(String[] args) throws IOException, ClassHierarchyException, IllegalArgumentException, CallGraphBuilderCancelException { - long start = System.currentTimeMillis(); - Properties p = CommandLine.parse(args); - String scopeFile = p.getProperty("scopeFile"); - if (scopeFile == null) { - throw new IllegalArgumentException("must specify scope file"); - } - String mainClass = p.getProperty("mainClass"); - if (mainClass == null) { - throw new IllegalArgumentException("must specify main class"); - } - AnalysisScope scope = AnalysisScopeReader.instance.readJavaScope(scopeFile, null, CSReachingDefsDriver.class.getClassLoader()); - ExampleUtil.addDefaultExclusions(scope); - IClassHierarchy cha = ClassHierarchyFactory.make(scope); - System.out.println(cha.getNumberOfClasses() + " classes"); - System.out.println(Warnings.asString()); - Warnings.clear(); - AnalysisOptions options = new AnalysisOptions(); - Iterable entrypoints = Util.makeMainEntrypoints(cha, mainClass); - options.setEntrypoints(entrypoints); - // you can dial down reflection handling if you like - options.setReflectionOptions(ReflectionOptions.NONE); - AnalysisCache cache = new AnalysisCacheImpl(); - // other builders can be constructed with different Util methods - CallGraphBuilder builder = Util.makeZeroOneContainerCFABuilder(options, cache, cha); -// CallGraphBuilder builder = Util.makeNCFABuilder(2, options, cache, cha, scope); -// CallGraphBuilder builder = Util.makeVanillaNCFABuilder(2, options, cache, cha, scope); - System.out.println("building call graph..."); - CallGraph cg = builder.makeCallGraph(options, null); -// System.out.println(cg); - long end = System.currentTimeMillis(); - System.out.println("done"); - System.out.println("took " + (end-start) + "ms"); - System.out.println(CallGraphStats.getStats(cg)); - - ContextSensitiveReachingDefs reachingDefs = new ContextSensitiveReachingDefs(cg, cache); - TabulationResult, CGNode, Pair> result = reachingDefs.analyze(); - ISupergraph, CGNode> supergraph = reachingDefs.getSupergraph(); + /** + * Usage: CSReachingDefsDriver -scopeFile file_path -mainClass class_name + * + *

Uses main() method of class_name as entrypoint. + * + * @throws IOException + * @throws ClassHierarchyException + * @throws CallGraphBuilderCancelException + * @throws IllegalArgumentException + */ + public static void main(String[] args) + throws IOException, + ClassHierarchyException, + IllegalArgumentException, + CallGraphBuilderCancelException { + long start = System.currentTimeMillis(); + Properties p = CommandLine.parse(args); + String scopeFile = p.getProperty("scopeFile"); + if (scopeFile == null) { + throw new IllegalArgumentException("must specify scope file"); + } + String mainClass = p.getProperty("mainClass"); + if (mainClass == null) { + throw new IllegalArgumentException("must specify main class"); + } + AnalysisScope scope = + AnalysisScopeReader.instance.readJavaScope( + scopeFile, null, CSReachingDefsDriver.class.getClassLoader()); + ExampleUtil.addDefaultExclusions(scope); + IClassHierarchy cha = ClassHierarchyFactory.make(scope); + System.out.println(cha.getNumberOfClasses() + " classes"); + System.out.println(Warnings.asString()); + Warnings.clear(); + AnalysisOptions options = new AnalysisOptions(); + Iterable entrypoints = Util.makeMainEntrypoints(cha, mainClass); + options.setEntrypoints(entrypoints); + // you can dial down reflection handling if you like + options.setReflectionOptions(ReflectionOptions.NONE); + AnalysisCache cache = new AnalysisCacheImpl(); + // other builders can be constructed with different Util methods + CallGraphBuilder builder = Util.makeZeroOneContainerCFABuilder(options, cache, cha); + // CallGraphBuilder builder = Util.makeNCFABuilder(2, options, cache, cha, scope); + // CallGraphBuilder builder = Util.makeVanillaNCFABuilder(2, options, cache, cha, scope); + System.out.println("building call graph..."); + CallGraph cg = builder.makeCallGraph(options, null); + // System.out.println(cg); + long end = System.currentTimeMillis(); + System.out.println("done"); + System.out.println("took " + (end - start) + "ms"); + System.out.println(CallGraphStats.getStats(cg)); - // TODO print out some analysis results - } + ContextSensitiveReachingDefs reachingDefs = new ContextSensitiveReachingDefs(cg, cache); + TabulationResult, CGNode, Pair> + result = reachingDefs.analyze(); + ISupergraph, CGNode> supergraph = + reachingDefs.getSupergraph(); + // TODO print out some analysis results + } } diff --git a/src/main/java/com/ibm/wala/examples/drivers/ConstructAllIRs.java b/src/main/java/com/ibm/wala/examples/drivers/ConstructAllIRs.java index ea76055d..34cdc8ba 100644 --- a/src/main/java/com/ibm/wala/examples/drivers/ConstructAllIRs.java +++ b/src/main/java/com/ibm/wala/examples/drivers/ConstructAllIRs.java @@ -10,8 +10,6 @@ *******************************************************************************/ package com.ibm.wala.examples.drivers; -import java.io.IOException; - import com.ibm.wala.classLoader.IClass; import com.ibm.wala.classLoader.IMethod; import com.ibm.wala.core.util.config.AnalysisScopeReader; @@ -25,31 +23,26 @@ import com.ibm.wala.ipa.cha.ClassHierarchyException; import com.ibm.wala.ipa.cha.ClassHierarchyFactory; import com.ibm.wala.util.perf.Stopwatch; +import java.io.IOException; /** - * An analysis skeleton that simply constructs IRs for all methods in a class hierarchy. Illustrates the use of - * {@link ReferenceCleanser} to improve running time / reduce memory usage. + * An analysis skeleton that simply constructs IRs for all methods in a class hierarchy. Illustrates + * the use of {@link ReferenceCleanser} to improve running time / reduce memory usage. */ public class ConstructAllIRs { - /** - * Should we periodically clear out soft reference caches in an attempt to help the GC? - */ - private final static boolean PERIODIC_WIPE_SOFT_CACHES = true; + /** Should we periodically clear out soft reference caches in an attempt to help the GC? */ + private static final boolean PERIODIC_WIPE_SOFT_CACHES = true; - /** - * Interval which defines the period to clear soft reference caches - */ - private final static int WIPE_SOFT_CACHE_INTERVAL = 2500; + /** Interval which defines the period to clear soft reference caches */ + private static final int WIPE_SOFT_CACHE_INTERVAL = 2500; - /** - * Counter for wiping soft caches - */ + /** Counter for wiping soft caches */ private static int wipeCount = 0; /** * First command-line argument should be location of scope file for application to analyze - * + * * @throws IOException * @throws ClassHierarchyException */ @@ -59,14 +52,17 @@ public static void main(String[] args) throws IOException, ClassHierarchyExcepti // measure running time Stopwatch s = new Stopwatch(); s.start(); - AnalysisScope scope = AnalysisScopeReader.instance.readJavaScope(scopeFile, null, ConstructAllIRs.class.getClassLoader()); + AnalysisScope scope = + AnalysisScopeReader.instance.readJavaScope( + scopeFile, null, ConstructAllIRs.class.getClassLoader()); // build a type hierarchy System.out.print("building class hierarchy..."); ClassHierarchy cha = ClassHierarchyFactory.make(scope); System.out.println("done"); - // register class hierarchy and AnalysisCache with the reference cleanser, so that their soft references are appropriately wiped + // register class hierarchy and AnalysisCache with the reference cleanser, so that their soft + // references are appropriately wiped ReferenceCleanser.registerClassHierarchy(cha); AnalysisOptions options = new AnalysisOptions(); IAnalysisCacheView cache = new AnalysisCacheImpl(options.getSSAOptions()); @@ -83,7 +79,6 @@ public static void main(String[] args) throws IOException, ClassHierarchyExcepti System.out.println("done"); s.stop(); System.out.println("RUNNING TIME: " + s.getElapsedMillis()); - } private static void wipeSoftCaches() { @@ -95,5 +90,4 @@ private static void wipeSoftCaches() { } } } - -} \ No newline at end of file +} diff --git a/src/main/java/com/ibm/wala/examples/drivers/DemandPointsToDriver.java b/src/main/java/com/ibm/wala/examples/drivers/DemandPointsToDriver.java index 447465e5..04abf7d8 100644 --- a/src/main/java/com/ibm/wala/examples/drivers/DemandPointsToDriver.java +++ b/src/main/java/com/ibm/wala/examples/drivers/DemandPointsToDriver.java @@ -31,7 +31,6 @@ import com.ibm.wala.types.ClassLoaderReference; import com.ibm.wala.util.CancelException; import com.ibm.wala.util.collections.Pair; - import java.io.IOException; import java.util.Collection; import java.util.Iterator; diff --git a/src/main/java/com/ibm/wala/examples/drivers/FieldBasedJSCallGraphDriver.java b/src/main/java/com/ibm/wala/examples/drivers/FieldBasedJSCallGraphDriver.java index 0e93afc9..6c914df9 100644 --- a/src/main/java/com/ibm/wala/examples/drivers/FieldBasedJSCallGraphDriver.java +++ b/src/main/java/com/ibm/wala/examples/drivers/FieldBasedJSCallGraphDriver.java @@ -8,7 +8,6 @@ import com.ibm.wala.ipa.callgraph.CallGraphStats; import com.ibm.wala.util.CancelException; import com.ibm.wala.util.WalaException; - import java.io.IOException; import java.net.URL; import java.nio.file.Path; diff --git a/src/main/java/com/ibm/wala/examples/drivers/JSCallGraphDriver.java b/src/main/java/com/ibm/wala/examples/drivers/JSCallGraphDriver.java index 2c1e7b70..4671e49a 100644 --- a/src/main/java/com/ibm/wala/examples/drivers/JSCallGraphDriver.java +++ b/src/main/java/com/ibm/wala/examples/drivers/JSCallGraphDriver.java @@ -1,9 +1,5 @@ package com.ibm.wala.examples.drivers; -import java.io.IOException; -import java.nio.file.Path; -import java.nio.file.Paths; - import com.ibm.wala.cast.js.ipa.callgraph.JSCallGraphUtil; import com.ibm.wala.cast.js.translator.CAstRhinoTranslatorFactory; import com.ibm.wala.cast.js.util.JSCallGraphBuilderUtil; @@ -11,23 +7,28 @@ import com.ibm.wala.ipa.callgraph.CallGraphStats; import com.ibm.wala.util.CancelException; import com.ibm.wala.util.WalaException; +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; public class JSCallGraphDriver { - /** - * Usage: JSCallGraphDriver path_to_js_file - * @param args - * @throws WalaException - * @throws CancelException - * @throws IOException - * @throws IllegalArgumentException - */ - public static void main(String[] args) throws IllegalArgumentException, IOException, CancelException, WalaException { - Path path = Paths.get(args[0]); - JSCallGraphUtil.setTranslatorFactory(new CAstRhinoTranslatorFactory()); - CallGraph CG = JSCallGraphBuilderUtil.makeScriptCG( - path.getParent().toString(), path.getFileName().toString()); - System.out.println(CallGraphStats.getStats(CG)); - } - + /** + * Usage: JSCallGraphDriver path_to_js_file + * + * @param args + * @throws WalaException + * @throws CancelException + * @throws IOException + * @throws IllegalArgumentException + */ + public static void main(String[] args) + throws IllegalArgumentException, IOException, CancelException, WalaException { + Path path = Paths.get(args[0]); + JSCallGraphUtil.setTranslatorFactory(new CAstRhinoTranslatorFactory()); + CallGraph CG = + JSCallGraphBuilderUtil.makeScriptCG( + path.getParent().toString(), path.getFileName().toString()); + System.out.println(CallGraphStats.getStats(CG)); + } } diff --git a/src/main/java/com/ibm/wala/examples/drivers/PDFTypeHierarchy.java b/src/main/java/com/ibm/wala/examples/drivers/PDFTypeHierarchy.java index 49ee85d5..7aab9fce 100644 --- a/src/main/java/com/ibm/wala/examples/drivers/PDFTypeHierarchy.java +++ b/src/main/java/com/ibm/wala/examples/drivers/PDFTypeHierarchy.java @@ -10,11 +10,6 @@ *******************************************************************************/ package com.ibm.wala.examples.drivers; -import java.io.File; -import java.io.IOException; -import java.util.Collection; -import java.util.function.Predicate; - import com.ibm.wala.classLoader.IClass; import com.ibm.wala.core.util.config.AnalysisScopeReader; import com.ibm.wala.core.viz.PDFViewUtil; @@ -30,18 +25,20 @@ import com.ibm.wala.util.graph.GraphSlicer; import com.ibm.wala.util.graph.impl.SlowSparseNumberedGraph; import com.ibm.wala.util.viz.DotUtil; +import java.io.File; +import java.io.IOException; +import java.util.Collection; +import java.util.function.Predicate; /** - * - * This simple example WALA application builds a TypeHierarchy and fires off - * ghostview to viz a DOT representation. - * + * This simple example WALA application builds a TypeHierarchy and fires off ghostview to viz a DOT + * representation. + * * @author sfink */ public class PDFTypeHierarchy { // This example takes one command-line argument, so args[1] should be the "-classpath" parameter - final static int CLASSPATH_INDEX = 1; - + static final int CLASSPATH_INDEX = 1; public static void main(String[] args) throws IOException { run(args); @@ -51,7 +48,8 @@ public static Process run(String[] args) throws IOException { try { validateCommandLine(args); String classpath = args[CLASSPATH_INDEX]; - AnalysisScope scope = AnalysisScopeReader.instance.makeJavaBinaryAnalysisScope(classpath, null); + AnalysisScope scope = + AnalysisScopeReader.instance.makeJavaBinaryAnalysisScope(classpath, null); ExampleUtil.addDefaultExclusions(scope); // invoke WALA to build a class hierarchy @@ -78,20 +76,19 @@ public static Graph pruneGraph(Graph g, Predicate f) { Collection slice = GraphSlicer.slice(g, f); return GraphSlicer.prune(g, new CollectionFilter<>(slice)); } - - /** - * Restrict g to nodes from the Application loader - */ + + /** Restrict g to nodes from the Application loader */ public static Graph pruneForAppLoader(Graph g) throws WalaException { - Predicate f = c -> (c.getClassLoader().getReference().equals(ClassLoaderReference.Application)); + Predicate f = + c -> (c.getClassLoader().getReference().equals(ClassLoaderReference.Application)); return pruneGraph(g, f); } - + /** * Validate that the command-line arguments obey the expected usage. - * - * Usage: args[0] : "-classpath" args[1] : String, a ";"-delimited class path - * + * + *

Usage: args[0] : "-classpath" args[1] : String, a ";"-delimited class path + * * @throws UnsupportedOperationException if command-line is malformed. */ public static void validateCommandLine(String[] args) { @@ -99,12 +96,14 @@ public static void validateCommandLine(String[] args) { throw new UnsupportedOperationException("must have at least 2 command-line arguments"); } if (!args[0].equals("-classpath")) { - throw new UnsupportedOperationException("invalid command-line, args[0] should be -classpath, but is " + args[0]); + throw new UnsupportedOperationException( + "invalid command-line, args[0] should be -classpath, but is " + args[0]); } } - + /** - * Return a view of an {@link IClassHierarchy} as a {@link Graph}, with edges from classes to immediate subtypes + * Return a view of an {@link IClassHierarchy} as a {@link Graph}, with edges from classes to + * immediate subtypes */ public static Graph typeHierarchy2Graph(IClassHierarchy cha) throws WalaException { Graph result = SlowSparseNumberedGraph.make(); @@ -122,5 +121,5 @@ public static Graph typeHierarchy2Graph(IClassHierarchy cha) throws Wala } } return result; - } + } } diff --git a/src/main/java/com/ibm/wala/examples/drivers/PrintTypeHierarchy.java b/src/main/java/com/ibm/wala/examples/drivers/PrintTypeHierarchy.java index aa321094..ef3d1097 100644 --- a/src/main/java/com/ibm/wala/examples/drivers/PrintTypeHierarchy.java +++ b/src/main/java/com/ibm/wala/examples/drivers/PrintTypeHierarchy.java @@ -15,12 +15,9 @@ import com.ibm.wala.ipa.cha.ClassHierarchy; import com.ibm.wala.ipa.cha.ClassHierarchyException; import com.ibm.wala.ipa.cha.ClassHierarchyFactory; - import java.io.IOException; -/** - * Simple WALA driver to build and print out a {@link ClassHierarchy}. - */ +/** Simple WALA driver to build and print out a {@link ClassHierarchy}. */ public class PrintTypeHierarchy { public static void main(String[] args) throws IOException, ClassHierarchyException { diff --git a/src/main/java/com/ibm/wala/examples/drivers/ScopeFileCallGraph.java b/src/main/java/com/ibm/wala/examples/drivers/ScopeFileCallGraph.java index 998b2705..2ed17dbe 100644 --- a/src/main/java/com/ibm/wala/examples/drivers/ScopeFileCallGraph.java +++ b/src/main/java/com/ibm/wala/examples/drivers/ScopeFileCallGraph.java @@ -24,7 +24,6 @@ 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.cha.CHACallGraph; import com.ibm.wala.ipa.callgraph.impl.DefaultEntrypoint; import com.ibm.wala.ipa.callgraph.impl.Util; import com.ibm.wala.ipa.callgraph.propagation.InstanceKey; @@ -35,32 +34,30 @@ import com.ibm.wala.types.TypeReference; import com.ibm.wala.util.CancelException; import com.ibm.wala.util.io.CommandLine; - import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.Properties; /** - * Driver that constructs a call graph for an application specified via a scope file. - * Useful for getting some code to copy-paste. + * Driver that constructs a call graph for an application specified via a scope file. Useful for + * getting some code to copy-paste. */ public class ScopeFileCallGraph { /** - * Usage: ScopeFileCallGraph -scopeFile file_path [-entryClass class_name | - * -mainClass class_name] - * - * If given -mainClass, uses main() method of class_name as entrypoint. If - * given -entryClass, uses all public methods of class_name. - * + * Usage: ScopeFileCallGraph -scopeFile file_path [-entryClass class_name | -mainClass class_name] + * + *

If given -mainClass, uses main() method of class_name as entrypoint. If given -entryClass, + * uses all public methods of class_name. + * * @throws IOException * @throws ClassHierarchyException * @throws CancelException * @throws IllegalArgumentException */ - public static void main(String[] args) throws IOException, ClassHierarchyException, IllegalArgumentException, - CancelException { + public static void main(String[] args) + throws IOException, ClassHierarchyException, IllegalArgumentException, CancelException { long start = System.currentTimeMillis(); Properties p = CommandLine.parse(args); String scopeFile = p.getProperty("scopeFile"); @@ -69,7 +66,9 @@ public static void main(String[] args) throws IOException, ClassHierarchyExcepti if (mainClass != null && entryClass != null) { throw new IllegalArgumentException("only specify one of mainClass or entryClass"); } - AnalysisScope scope = AnalysisScopeReader.instance.readJavaScope(scopeFile, null, ScopeFileCallGraph.class.getClassLoader()); + AnalysisScope scope = + AnalysisScopeReader.instance.readJavaScope( + scopeFile, null, ScopeFileCallGraph.class.getClassLoader()); // set exclusions. we use these exclusions as standard for handling JDK 8 ExampleUtil.addDefaultExclusions(scope); IClassHierarchy cha = ClassHierarchyFactory.make(scope); @@ -77,34 +76,43 @@ public static void main(String[] args) throws IOException, ClassHierarchyExcepti System.out.println(Warnings.asString()); Warnings.clear(); AnalysisOptions options = new AnalysisOptions(); - Iterable entrypoints = entryClass != null ? makePublicEntrypoints(cha, entryClass) : Util.makeMainEntrypoints(cha, mainClass); + Iterable entrypoints = + entryClass != null + ? makePublicEntrypoints(cha, entryClass) + : Util.makeMainEntrypoints(cha, mainClass); options.setEntrypoints(entrypoints); // For a CHA call graph -// CHACallGraph CG = new CHACallGraph(cha); -// CG.init(entrypoints); + // CHACallGraph CG = new CHACallGraph(cha); + // CG.init(entrypoints); // For other call graphs // you can dial down reflection handling if you like -// options.setReflectionOptions(ReflectionOptions.NONE); + // options.setReflectionOptions(ReflectionOptions.NONE); AnalysisCache cache = new AnalysisCacheImpl(); // other builders can be constructed with different Util methods - CallGraphBuilder builder = Util.makeZeroOneContainerCFABuilder(options, cache, cha); -// CallGraphBuilder builder = Util.makeZeroCFABuilder(Language.JAVA, options, cache, cha); -// CallGraphBuilder builder = Util.makeNCFABuilder(2, options, cache, cha, scope); -// CallGraphBuilder builder = Util.makeVanillaNCFABuilder(2, options, cache, cha, scope); -// CallGraphBuilder builder = Util.makeVanillaNCFABuilder(2, options, cache, cha, scope); + CallGraphBuilder builder = + Util.makeZeroOneContainerCFABuilder(options, cache, cha); + // CallGraphBuilder builder = Util.makeZeroCFABuilder(Language.JAVA, options, + // cache, cha); + // CallGraphBuilder builder = Util.makeNCFABuilder(2, options, cache, cha, scope); + // CallGraphBuilder builder = Util.makeVanillaNCFABuilder(2, options, cache, cha, scope); + // CallGraphBuilder builder = Util.makeVanillaNCFABuilder(2, options, cache, cha, scope); System.out.println("building call graph..."); CallGraph cg = builder.makeCallGraph(options, null); long end = System.currentTimeMillis(); System.out.println("done"); - System.out.println("took " + (end-start) + "ms"); + System.out.println("took " + (end - start) + "ms"); System.out.println(CallGraphStats.getStats(cg)); } - private static Iterable makePublicEntrypoints(IClassHierarchy cha, String entryClass) { + private static Iterable makePublicEntrypoints( + IClassHierarchy cha, String entryClass) { Collection result = new ArrayList<>(); - IClass klass = cha.lookupClass(TypeReference.findOrCreate(ClassLoaderReference.Application, - StringStuff.deployment2CanonicalTypeString(entryClass))); + IClass klass = + cha.lookupClass( + TypeReference.findOrCreate( + ClassLoaderReference.Application, + StringStuff.deployment2CanonicalTypeString(entryClass))); for (IMethod m : klass.getDeclaredMethods()) { if (m.isPublic()) { result.add(new DefaultEntrypoint(m, cha)); diff --git a/src/main/java/com/ibm/wala/examples/drivers/SourceDirCallGraph.java b/src/main/java/com/ibm/wala/examples/drivers/SourceDirCallGraph.java index 7aaf4f42..7dd7855e 100644 --- a/src/main/java/com/ibm/wala/examples/drivers/SourceDirCallGraph.java +++ b/src/main/java/com/ibm/wala/examples/drivers/SourceDirCallGraph.java @@ -26,7 +26,6 @@ import com.ibm.wala.ssa.SymbolTable; import com.ibm.wala.types.ClassLoaderReference; import com.ibm.wala.util.io.CommandLine; - import java.io.File; import java.io.IOException; import java.util.Arrays; @@ -53,7 +52,9 @@ public interface Processor { *

Example args: -sourceDir /tmp/srcTest -mainClass LFoo */ public static void main(String[] args) - throws ClassHierarchyException, IllegalArgumentException, CallGraphBuilderCancelException, + throws ClassHierarchyException, + IllegalArgumentException, + CallGraphBuilderCancelException, IOException { System.out.println(Arrays.toString(args)); new SourceDirCallGraph() @@ -71,7 +72,9 @@ protected ClassLoaderFactory getLoaderFactory(AnalysisScope scope) { } public void doit(String[] args, Processor processor) - throws ClassHierarchyException, IllegalArgumentException, CallGraphBuilderCancelException, + throws ClassHierarchyException, + IllegalArgumentException, + CallGraphBuilderCancelException, IOException { long start = System.currentTimeMillis(); Properties p = CommandLine.parse(args); diff --git a/src/main/java/com/ibm/wala/examples/util/ExampleUtil.java b/src/main/java/com/ibm/wala/examples/util/ExampleUtil.java index ca4c9d4d..5ac891e0 100644 --- a/src/main/java/com/ibm/wala/examples/util/ExampleUtil.java +++ b/src/main/java/com/ibm/wala/examples/util/ExampleUtil.java @@ -1,32 +1,33 @@ package com.ibm.wala.examples.util; +import com.ibm.wala.ipa.callgraph.AnalysisScope; +import com.ibm.wala.util.config.FileOfClasses; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.UnsupportedEncodingException; -import com.ibm.wala.ipa.callgraph.AnalysisScope; -import com.ibm.wala.util.config.FileOfClasses; - public class ExampleUtil { - // more aggressive exclusions to avoid library blowup - // in interprocedural tests - private static final String EXCLUSIONS = "java\\/awt\\/.*\n" + - "javax\\/swing\\/.*\n" + - "sun\\/awt\\/.*\n" + - "sun\\/swing\\/.*\n" + - "com\\/sun\\/.*\n" + - "sun\\/.*\n" + - "org\\/netbeans\\/.*\n" + - "org\\/openide\\/.*\n" + - "com\\/ibm\\/crypto\\/.*\n" + - "com\\/ibm\\/security\\/.*\n" + - "org\\/apache\\/xerces\\/.*\n" + - "java\\/security\\/.*\n" + - ""; + // more aggressive exclusions to avoid library blowup + // in interprocedural tests + private static final String EXCLUSIONS = + "java\\/awt\\/.*\n" + + "javax\\/swing\\/.*\n" + + "sun\\/awt\\/.*\n" + + "sun\\/swing\\/.*\n" + + "com\\/sun\\/.*\n" + + "sun\\/.*\n" + + "org\\/netbeans\\/.*\n" + + "org\\/openide\\/.*\n" + + "com\\/ibm\\/crypto\\/.*\n" + + "com\\/ibm\\/security\\/.*\n" + + "org\\/apache\\/xerces\\/.*\n" + + "java\\/security\\/.*\n" + + ""; - public static void addDefaultExclusions(AnalysisScope scope) throws UnsupportedEncodingException, IOException { - scope.setExclusions(new FileOfClasses(new ByteArrayInputStream(ExampleUtil.EXCLUSIONS.getBytes("UTF-8")))); + public static void addDefaultExclusions(AnalysisScope scope) + throws UnsupportedEncodingException, IOException { + scope.setExclusions( + new FileOfClasses(new ByteArrayInputStream(ExampleUtil.EXCLUSIONS.getBytes("UTF-8")))); } - }