Convert all Java source files to use Unix line endings; no semantic change
This commit is contained in:
parent
fcab11e5b8
commit
256cd06460
@ -1,303 +1,303 @@
|
||||
/**
|
||||
* Refinement Analysis Tools is Copyright (c) 2007 The Regents of the
|
||||
* University of California (Regents). Provided that this notice and
|
||||
* the following two paragraphs are included in any distribution of
|
||||
* Refinement Analysis Tools or its derivative work, Regents agrees
|
||||
* not to assert any of Regents' copyright rights in Refinement
|
||||
* Analysis Tools against recipient for recipient's reproduction,
|
||||
* preparation of derivative works, public display, public
|
||||
* performance, distribution or sublicensing of Refinement Analysis
|
||||
* Tools and derivative works, in source code and object code form.
|
||||
* This agreement not to assert does not confer, by implication,
|
||||
* estoppel, or otherwise any license or rights in any intellectual
|
||||
* property of Regents, including, but not limited to, any patents
|
||||
* of Regents or Regents' employees.
|
||||
*
|
||||
* IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT,
|
||||
* INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES,
|
||||
* INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE
|
||||
* AND ITS DOCUMENTATION, EVEN IF REGENTS HAS BEEN ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND FURTHER DISCLAIMS ANY STATUTORY
|
||||
* WARRANTY OF NON-INFRINGEMENT. THE SOFTWARE AND ACCOMPANYING
|
||||
* DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS
|
||||
* IS". REGENTS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT,
|
||||
* UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*/
|
||||
package com.ibm.wala.demandpa.driver;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
import com.ibm.wala.core.tests.callGraph.CallGraphTestUtil;
|
||||
import com.ibm.wala.core.tests.util.TestConstants;
|
||||
import com.ibm.wala.demandpa.alg.ContextSensitiveStateMachine;
|
||||
import com.ibm.wala.demandpa.alg.DemandRefinementPointsTo;
|
||||
import com.ibm.wala.demandpa.alg.DemandRefinementPointsTo.PointsToResult;
|
||||
import com.ibm.wala.demandpa.alg.refinepolicy.FieldRefinePolicy;
|
||||
import com.ibm.wala.demandpa.alg.refinepolicy.ManualFieldPolicy;
|
||||
import com.ibm.wala.demandpa.alg.refinepolicy.ManualRefinementPolicy;
|
||||
import com.ibm.wala.demandpa.alg.refinepolicy.RefinementPolicyFactory;
|
||||
import com.ibm.wala.demandpa.alg.refinepolicy.TunedRefinementPolicy;
|
||||
import com.ibm.wala.demandpa.alg.statemachine.StateMachineFactory;
|
||||
import com.ibm.wala.demandpa.flowgraph.IFlowLabel;
|
||||
import com.ibm.wala.demandpa.util.MemoryAccessMap;
|
||||
import com.ibm.wala.demandpa.util.SimpleMemoryAccessMap;
|
||||
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.CallGraphBuilderCancelException;
|
||||
import com.ibm.wala.ipa.callgraph.CallGraphStats;
|
||||
import com.ibm.wala.ipa.callgraph.Entrypoint;
|
||||
import com.ibm.wala.ipa.callgraph.impl.Util;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.HeapModel;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.PointerKey;
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchy;
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchyException;
|
||||
import com.ibm.wala.ipa.cha.IClassHierarchy;
|
||||
import com.ibm.wala.properties.WalaProperties;
|
||||
import com.ibm.wala.ssa.IR;
|
||||
import com.ibm.wala.ssa.SSACheckCastInstruction;
|
||||
import com.ibm.wala.ssa.SSAInstruction;
|
||||
import com.ibm.wala.types.ClassLoaderReference;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
import com.ibm.wala.util.CancelException;
|
||||
import com.ibm.wala.util.NullProgressMonitor;
|
||||
import com.ibm.wala.util.Predicate;
|
||||
import com.ibm.wala.util.ProgressMaster;
|
||||
import com.ibm.wala.util.WalaException;
|
||||
import com.ibm.wala.util.collections.Pair;
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
|
||||
/**
|
||||
* Uses a demand-driven points-to analysis to check the safety of downcasts.
|
||||
*
|
||||
* @author Manu Sridharan
|
||||
*
|
||||
*/
|
||||
public class DemandCastChecker {
|
||||
|
||||
// maximum number of casts to check
|
||||
private static final int MAX_CASTS = Integer.MAX_VALUE;
|
||||
|
||||
/**
|
||||
* @param args
|
||||
* @throws CancelException
|
||||
* @throws IllegalArgumentException
|
||||
* @throws IOException
|
||||
*/
|
||||
public static void main(String[] args) throws IllegalArgumentException, CancelException, IOException {
|
||||
try {
|
||||
Properties p = new Properties();
|
||||
p.putAll(WalaProperties.loadProperties());
|
||||
} catch (WalaException e) {
|
||||
e.printStackTrace();
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
|
||||
runTestCase(TestConstants.JLEX_MAIN, TestConstants.JLEX, "JLex");
|
||||
// runTestCase(TestConstants.HELLO_MAIN, TestConstants.HELLO, "Hello");
|
||||
|
||||
}
|
||||
|
||||
public static void runTestCase(String mainClass, String scopeFile, String benchName) throws IllegalArgumentException,
|
||||
CancelException, IOException {
|
||||
System.err.println("=====BENCHMARK " + benchName + "=====");
|
||||
System.err.println("analyzing " + benchName);
|
||||
DemandRefinementPointsTo dmp = null;
|
||||
try {
|
||||
dmp = makeDemandPointerAnalysis(scopeFile, mainClass, benchName);
|
||||
findFailingCasts(dmp.getBaseCallGraph(), dmp);
|
||||
} catch (ClassHierarchyException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
System.err.println("=*=*=*=*=*=*=*=*=*=*=*=*=*=*");
|
||||
System.err.println("");
|
||||
System.err.println("");
|
||||
}
|
||||
|
||||
private static DemandRefinementPointsTo makeDemandPointerAnalysis(String scopeFile, String mainClass, String benchName)
|
||||
throws ClassHierarchyException, IllegalArgumentException, CancelException, IOException {
|
||||
AnalysisScope scope = CallGraphTestUtil.makeJ2SEAnalysisScope(scopeFile, getExclusions(benchName));
|
||||
// build a type hierarchy
|
||||
ClassHierarchy cha = ClassHierarchy.make(scope);
|
||||
|
||||
// set up call graph construction options; mainly what should be considered
|
||||
// entrypoints?
|
||||
Iterable<Entrypoint> entrypoints = com.ibm.wala.ipa.callgraph.impl.Util.makeMainEntrypoints(scope, cha, mainClass);
|
||||
AnalysisOptions options = CallGraphTestUtil.makeAnalysisOptions(scope, entrypoints);
|
||||
|
||||
System.err.print("constructing call graph...");
|
||||
final Pair<CallGraph, PointerAnalysis> cgAndPA = buildCallGraph(scope, cha, options);
|
||||
CallGraph cg = cgAndPA.fst;
|
||||
System.err.println("done");
|
||||
System.err.println(CallGraphStats.getStats(cg));
|
||||
MemoryAccessMap fam = new SimpleMemoryAccessMap(cg, cgAndPA.snd.getHeapModel(), false);
|
||||
DemandRefinementPointsTo fullDemandPointsTo = DemandRefinementPointsTo.makeWithDefaultFlowGraph(cg, heapModel, fam, cha, options, makeStateMachineFactory());
|
||||
fullDemandPointsTo.setRefinementPolicyFactory(chooseRefinePolicyFactory(cha));
|
||||
return fullDemandPointsTo;
|
||||
}
|
||||
|
||||
private static String getExclusions(String benchName) {
|
||||
return CallGraphTestUtil.REGRESSION_EXCLUSIONS;
|
||||
}
|
||||
|
||||
// if true, construct up-front call graph cheaply (0-CFA)
|
||||
private static final boolean CHEAP_CG = true;
|
||||
|
||||
private static HeapModel heapModel;
|
||||
|
||||
/**
|
||||
* builds a call graph, and sets the corresponding heap model for analysis
|
||||
*
|
||||
* @param scope
|
||||
* @param cha
|
||||
* @param options
|
||||
* @return
|
||||
* @throws CancelException
|
||||
* @throws IllegalArgumentException
|
||||
*/
|
||||
private static Pair<CallGraph, PointerAnalysis> buildCallGraph(AnalysisScope scope, ClassHierarchy cha, AnalysisOptions options)
|
||||
throws IllegalArgumentException, CancelException {
|
||||
CallGraph retCG = null;
|
||||
PointerAnalysis retPA = null;
|
||||
final AnalysisCache cache = new AnalysisCache();
|
||||
CallGraphBuilder builder;
|
||||
if (CHEAP_CG) {
|
||||
builder = Util.makeZeroCFABuilder(options, cache, cha, scope);
|
||||
// we want vanilla 0-1 CFA, which has one abstract loc per allocation
|
||||
heapModel = Util.makeVanillaZeroOneCFABuilder(options, cache, cha, scope);
|
||||
} else {
|
||||
builder = Util.makeZeroOneContainerCFABuilder(options, cache, cha, scope);
|
||||
heapModel = (HeapModel) builder;
|
||||
}
|
||||
ProgressMaster master = ProgressMaster.make(new NullProgressMonitor());
|
||||
master.setMillisPerWorkItem(360000);
|
||||
master.beginTask("runSolver", 1);
|
||||
try {
|
||||
retCG = builder.makeCallGraph(options, master);
|
||||
retPA = builder.getPointerAnalysis();
|
||||
} catch (CallGraphBuilderCancelException e) {
|
||||
System.err.println("TIMED OUT!!");
|
||||
retCG = e.getPartialCallGraph();
|
||||
retPA = e.getPartialPointerAnalysis();
|
||||
}
|
||||
return Pair.make(retCG, retPA);
|
||||
}
|
||||
|
||||
private static RefinementPolicyFactory chooseRefinePolicyFactory(ClassHierarchy cha) {
|
||||
if (true) {
|
||||
return new TunedRefinementPolicy.Factory(cha);
|
||||
} else {
|
||||
return new ManualRefinementPolicy.Factory(cha);
|
||||
}
|
||||
}
|
||||
|
||||
private static StateMachineFactory<IFlowLabel> makeStateMachineFactory() {
|
||||
return new ContextSensitiveStateMachine.Factory();
|
||||
}
|
||||
|
||||
private static List<Pair<CGNode, SSACheckCastInstruction>> findFailingCasts(CallGraph cg, DemandRefinementPointsTo dmp) {
|
||||
final IClassHierarchy cha = dmp.getClassHierarchy();
|
||||
List<Pair<CGNode, SSACheckCastInstruction>> failing = new ArrayList<Pair<CGNode, SSACheckCastInstruction>>();
|
||||
|
||||
int numSafe = 0, numMightFail = 0;
|
||||
outer: for (Iterator<? extends CGNode> nodeIter = cg.iterator(); nodeIter.hasNext();) {
|
||||
CGNode node = nodeIter.next();
|
||||
TypeReference declaringClass = node.getMethod().getReference().getDeclaringClass();
|
||||
// skip library classes
|
||||
if (declaringClass.getClassLoader().equals(ClassLoaderReference.Primordial)) {
|
||||
continue;
|
||||
}
|
||||
IR ir = node.getIR();
|
||||
if (ir == null)
|
||||
continue;
|
||||
SSAInstruction[] instrs = ir.getInstructions();
|
||||
for (int i = 0; i < instrs.length; i++) {
|
||||
if (numSafe + numMightFail > MAX_CASTS)
|
||||
break outer;
|
||||
SSAInstruction instruction = instrs[i];
|
||||
if (instruction instanceof SSACheckCastInstruction) {
|
||||
SSACheckCastInstruction castInstr = (SSACheckCastInstruction) instruction;
|
||||
final TypeReference[] declaredResultTypes = castInstr.getDeclaredResultTypes();
|
||||
|
||||
boolean primOnly = true;
|
||||
for (TypeReference t : declaredResultTypes) {
|
||||
if (! t.isPrimitiveType()) {
|
||||
primOnly = false;
|
||||
}
|
||||
}
|
||||
if (primOnly) {
|
||||
continue;
|
||||
}
|
||||
|
||||
System.err.println("CHECKING " + castInstr + " in " + node.getMethod());
|
||||
PointerKey castedPk = heapModel.getPointerKeyForLocal(node, castInstr.getUse(0));
|
||||
Predicate<InstanceKey> castPred = new Predicate<InstanceKey>() {
|
||||
|
||||
@Override
|
||||
public boolean test(InstanceKey ik) {
|
||||
TypeReference ikTypeRef = ik.getConcreteType().getReference();
|
||||
for (TypeReference t : declaredResultTypes) {
|
||||
if (cha.isAssignableFrom(cha.lookupClass(t), cha.lookupClass(ikTypeRef))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
long startTime = System.currentTimeMillis();
|
||||
Pair<PointsToResult, Collection<InstanceKey>> queryResult = dmp.getPointsTo(castedPk, castPred);
|
||||
long runningTime = System.currentTimeMillis() - startTime;
|
||||
System.err.println("running time: " + runningTime + "ms");
|
||||
final FieldRefinePolicy fieldRefinePolicy = dmp.getRefinementPolicy().getFieldRefinePolicy();
|
||||
switch (queryResult.fst) {
|
||||
case SUCCESS:
|
||||
System.err.println("SAFE: " + castInstr + " in " + node.getMethod());
|
||||
if (fieldRefinePolicy instanceof ManualFieldPolicy) {
|
||||
ManualFieldPolicy hackedFieldPolicy = (ManualFieldPolicy) fieldRefinePolicy;
|
||||
System.err.println(hackedFieldPolicy.getHistory());
|
||||
}
|
||||
System.err.println("TRAVERSED " + dmp.getNumNodesTraversed() + " nodes");
|
||||
numSafe++;
|
||||
break;
|
||||
case NOMOREREFINE:
|
||||
if (queryResult.snd != null) {
|
||||
System.err.println("MIGHT FAIL: no more refinement possible for " + castInstr + " in " + node.getMethod());
|
||||
} else {
|
||||
System.err.println("MIGHT FAIL: exceeded budget for " + castInstr + " in " + node.getMethod());
|
||||
}
|
||||
failing.add(Pair.make(node, castInstr));
|
||||
numMightFail++;
|
||||
break;
|
||||
case BUDGETEXCEEDED:
|
||||
System.err.println("MIGHT FAIL: exceeded budget for " + castInstr + " in " + node.getMethod());
|
||||
failing.add(Pair.make(node, castInstr));
|
||||
numMightFail++;
|
||||
break;
|
||||
default:
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
}
|
||||
}
|
||||
// break outer;
|
||||
}
|
||||
System.err.println("TOTAL SAFE: " + numSafe);
|
||||
System.err.println("TOTAL MIGHT FAIL: " + numMightFail);
|
||||
return failing;
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* Refinement Analysis Tools is Copyright (c) 2007 The Regents of the
|
||||
* University of California (Regents). Provided that this notice and
|
||||
* the following two paragraphs are included in any distribution of
|
||||
* Refinement Analysis Tools or its derivative work, Regents agrees
|
||||
* not to assert any of Regents' copyright rights in Refinement
|
||||
* Analysis Tools against recipient for recipient's reproduction,
|
||||
* preparation of derivative works, public display, public
|
||||
* performance, distribution or sublicensing of Refinement Analysis
|
||||
* Tools and derivative works, in source code and object code form.
|
||||
* This agreement not to assert does not confer, by implication,
|
||||
* estoppel, or otherwise any license or rights in any intellectual
|
||||
* property of Regents, including, but not limited to, any patents
|
||||
* of Regents or Regents' employees.
|
||||
*
|
||||
* IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT,
|
||||
* INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES,
|
||||
* INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE
|
||||
* AND ITS DOCUMENTATION, EVEN IF REGENTS HAS BEEN ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND FURTHER DISCLAIMS ANY STATUTORY
|
||||
* WARRANTY OF NON-INFRINGEMENT. THE SOFTWARE AND ACCOMPANYING
|
||||
* DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS
|
||||
* IS". REGENTS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT,
|
||||
* UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*/
|
||||
package com.ibm.wala.demandpa.driver;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
import com.ibm.wala.core.tests.callGraph.CallGraphTestUtil;
|
||||
import com.ibm.wala.core.tests.util.TestConstants;
|
||||
import com.ibm.wala.demandpa.alg.ContextSensitiveStateMachine;
|
||||
import com.ibm.wala.demandpa.alg.DemandRefinementPointsTo;
|
||||
import com.ibm.wala.demandpa.alg.DemandRefinementPointsTo.PointsToResult;
|
||||
import com.ibm.wala.demandpa.alg.refinepolicy.FieldRefinePolicy;
|
||||
import com.ibm.wala.demandpa.alg.refinepolicy.ManualFieldPolicy;
|
||||
import com.ibm.wala.demandpa.alg.refinepolicy.ManualRefinementPolicy;
|
||||
import com.ibm.wala.demandpa.alg.refinepolicy.RefinementPolicyFactory;
|
||||
import com.ibm.wala.demandpa.alg.refinepolicy.TunedRefinementPolicy;
|
||||
import com.ibm.wala.demandpa.alg.statemachine.StateMachineFactory;
|
||||
import com.ibm.wala.demandpa.flowgraph.IFlowLabel;
|
||||
import com.ibm.wala.demandpa.util.MemoryAccessMap;
|
||||
import com.ibm.wala.demandpa.util.SimpleMemoryAccessMap;
|
||||
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.CallGraphBuilderCancelException;
|
||||
import com.ibm.wala.ipa.callgraph.CallGraphStats;
|
||||
import com.ibm.wala.ipa.callgraph.Entrypoint;
|
||||
import com.ibm.wala.ipa.callgraph.impl.Util;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.HeapModel;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.PointerKey;
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchy;
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchyException;
|
||||
import com.ibm.wala.ipa.cha.IClassHierarchy;
|
||||
import com.ibm.wala.properties.WalaProperties;
|
||||
import com.ibm.wala.ssa.IR;
|
||||
import com.ibm.wala.ssa.SSACheckCastInstruction;
|
||||
import com.ibm.wala.ssa.SSAInstruction;
|
||||
import com.ibm.wala.types.ClassLoaderReference;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
import com.ibm.wala.util.CancelException;
|
||||
import com.ibm.wala.util.NullProgressMonitor;
|
||||
import com.ibm.wala.util.Predicate;
|
||||
import com.ibm.wala.util.ProgressMaster;
|
||||
import com.ibm.wala.util.WalaException;
|
||||
import com.ibm.wala.util.collections.Pair;
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
|
||||
/**
|
||||
* Uses a demand-driven points-to analysis to check the safety of downcasts.
|
||||
*
|
||||
* @author Manu Sridharan
|
||||
*
|
||||
*/
|
||||
public class DemandCastChecker {
|
||||
|
||||
// maximum number of casts to check
|
||||
private static final int MAX_CASTS = Integer.MAX_VALUE;
|
||||
|
||||
/**
|
||||
* @param args
|
||||
* @throws CancelException
|
||||
* @throws IllegalArgumentException
|
||||
* @throws IOException
|
||||
*/
|
||||
public static void main(String[] args) throws IllegalArgumentException, CancelException, IOException {
|
||||
try {
|
||||
Properties p = new Properties();
|
||||
p.putAll(WalaProperties.loadProperties());
|
||||
} catch (WalaException e) {
|
||||
e.printStackTrace();
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
|
||||
runTestCase(TestConstants.JLEX_MAIN, TestConstants.JLEX, "JLex");
|
||||
// runTestCase(TestConstants.HELLO_MAIN, TestConstants.HELLO, "Hello");
|
||||
|
||||
}
|
||||
|
||||
public static void runTestCase(String mainClass, String scopeFile, String benchName) throws IllegalArgumentException,
|
||||
CancelException, IOException {
|
||||
System.err.println("=====BENCHMARK " + benchName + "=====");
|
||||
System.err.println("analyzing " + benchName);
|
||||
DemandRefinementPointsTo dmp = null;
|
||||
try {
|
||||
dmp = makeDemandPointerAnalysis(scopeFile, mainClass, benchName);
|
||||
findFailingCasts(dmp.getBaseCallGraph(), dmp);
|
||||
} catch (ClassHierarchyException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
System.err.println("=*=*=*=*=*=*=*=*=*=*=*=*=*=*");
|
||||
System.err.println("");
|
||||
System.err.println("");
|
||||
}
|
||||
|
||||
private static DemandRefinementPointsTo makeDemandPointerAnalysis(String scopeFile, String mainClass, String benchName)
|
||||
throws ClassHierarchyException, IllegalArgumentException, CancelException, IOException {
|
||||
AnalysisScope scope = CallGraphTestUtil.makeJ2SEAnalysisScope(scopeFile, getExclusions(benchName));
|
||||
// build a type hierarchy
|
||||
ClassHierarchy cha = ClassHierarchy.make(scope);
|
||||
|
||||
// set up call graph construction options; mainly what should be considered
|
||||
// entrypoints?
|
||||
Iterable<Entrypoint> entrypoints = com.ibm.wala.ipa.callgraph.impl.Util.makeMainEntrypoints(scope, cha, mainClass);
|
||||
AnalysisOptions options = CallGraphTestUtil.makeAnalysisOptions(scope, entrypoints);
|
||||
|
||||
System.err.print("constructing call graph...");
|
||||
final Pair<CallGraph, PointerAnalysis> cgAndPA = buildCallGraph(scope, cha, options);
|
||||
CallGraph cg = cgAndPA.fst;
|
||||
System.err.println("done");
|
||||
System.err.println(CallGraphStats.getStats(cg));
|
||||
MemoryAccessMap fam = new SimpleMemoryAccessMap(cg, cgAndPA.snd.getHeapModel(), false);
|
||||
DemandRefinementPointsTo fullDemandPointsTo = DemandRefinementPointsTo.makeWithDefaultFlowGraph(cg, heapModel, fam, cha, options, makeStateMachineFactory());
|
||||
fullDemandPointsTo.setRefinementPolicyFactory(chooseRefinePolicyFactory(cha));
|
||||
return fullDemandPointsTo;
|
||||
}
|
||||
|
||||
private static String getExclusions(String benchName) {
|
||||
return CallGraphTestUtil.REGRESSION_EXCLUSIONS;
|
||||
}
|
||||
|
||||
// if true, construct up-front call graph cheaply (0-CFA)
|
||||
private static final boolean CHEAP_CG = true;
|
||||
|
||||
private static HeapModel heapModel;
|
||||
|
||||
/**
|
||||
* builds a call graph, and sets the corresponding heap model for analysis
|
||||
*
|
||||
* @param scope
|
||||
* @param cha
|
||||
* @param options
|
||||
* @return
|
||||
* @throws CancelException
|
||||
* @throws IllegalArgumentException
|
||||
*/
|
||||
private static Pair<CallGraph, PointerAnalysis> buildCallGraph(AnalysisScope scope, ClassHierarchy cha, AnalysisOptions options)
|
||||
throws IllegalArgumentException, CancelException {
|
||||
CallGraph retCG = null;
|
||||
PointerAnalysis retPA = null;
|
||||
final AnalysisCache cache = new AnalysisCache();
|
||||
CallGraphBuilder builder;
|
||||
if (CHEAP_CG) {
|
||||
builder = Util.makeZeroCFABuilder(options, cache, cha, scope);
|
||||
// we want vanilla 0-1 CFA, which has one abstract loc per allocation
|
||||
heapModel = Util.makeVanillaZeroOneCFABuilder(options, cache, cha, scope);
|
||||
} else {
|
||||
builder = Util.makeZeroOneContainerCFABuilder(options, cache, cha, scope);
|
||||
heapModel = (HeapModel) builder;
|
||||
}
|
||||
ProgressMaster master = ProgressMaster.make(new NullProgressMonitor());
|
||||
master.setMillisPerWorkItem(360000);
|
||||
master.beginTask("runSolver", 1);
|
||||
try {
|
||||
retCG = builder.makeCallGraph(options, master);
|
||||
retPA = builder.getPointerAnalysis();
|
||||
} catch (CallGraphBuilderCancelException e) {
|
||||
System.err.println("TIMED OUT!!");
|
||||
retCG = e.getPartialCallGraph();
|
||||
retPA = e.getPartialPointerAnalysis();
|
||||
}
|
||||
return Pair.make(retCG, retPA);
|
||||
}
|
||||
|
||||
private static RefinementPolicyFactory chooseRefinePolicyFactory(ClassHierarchy cha) {
|
||||
if (true) {
|
||||
return new TunedRefinementPolicy.Factory(cha);
|
||||
} else {
|
||||
return new ManualRefinementPolicy.Factory(cha);
|
||||
}
|
||||
}
|
||||
|
||||
private static StateMachineFactory<IFlowLabel> makeStateMachineFactory() {
|
||||
return new ContextSensitiveStateMachine.Factory();
|
||||
}
|
||||
|
||||
private static List<Pair<CGNode, SSACheckCastInstruction>> findFailingCasts(CallGraph cg, DemandRefinementPointsTo dmp) {
|
||||
final IClassHierarchy cha = dmp.getClassHierarchy();
|
||||
List<Pair<CGNode, SSACheckCastInstruction>> failing = new ArrayList<Pair<CGNode, SSACheckCastInstruction>>();
|
||||
|
||||
int numSafe = 0, numMightFail = 0;
|
||||
outer: for (Iterator<? extends CGNode> nodeIter = cg.iterator(); nodeIter.hasNext();) {
|
||||
CGNode node = nodeIter.next();
|
||||
TypeReference declaringClass = node.getMethod().getReference().getDeclaringClass();
|
||||
// skip library classes
|
||||
if (declaringClass.getClassLoader().equals(ClassLoaderReference.Primordial)) {
|
||||
continue;
|
||||
}
|
||||
IR ir = node.getIR();
|
||||
if (ir == null)
|
||||
continue;
|
||||
SSAInstruction[] instrs = ir.getInstructions();
|
||||
for (int i = 0; i < instrs.length; i++) {
|
||||
if (numSafe + numMightFail > MAX_CASTS)
|
||||
break outer;
|
||||
SSAInstruction instruction = instrs[i];
|
||||
if (instruction instanceof SSACheckCastInstruction) {
|
||||
SSACheckCastInstruction castInstr = (SSACheckCastInstruction) instruction;
|
||||
final TypeReference[] declaredResultTypes = castInstr.getDeclaredResultTypes();
|
||||
|
||||
boolean primOnly = true;
|
||||
for (TypeReference t : declaredResultTypes) {
|
||||
if (! t.isPrimitiveType()) {
|
||||
primOnly = false;
|
||||
}
|
||||
}
|
||||
if (primOnly) {
|
||||
continue;
|
||||
}
|
||||
|
||||
System.err.println("CHECKING " + castInstr + " in " + node.getMethod());
|
||||
PointerKey castedPk = heapModel.getPointerKeyForLocal(node, castInstr.getUse(0));
|
||||
Predicate<InstanceKey> castPred = new Predicate<InstanceKey>() {
|
||||
|
||||
@Override
|
||||
public boolean test(InstanceKey ik) {
|
||||
TypeReference ikTypeRef = ik.getConcreteType().getReference();
|
||||
for (TypeReference t : declaredResultTypes) {
|
||||
if (cha.isAssignableFrom(cha.lookupClass(t), cha.lookupClass(ikTypeRef))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
long startTime = System.currentTimeMillis();
|
||||
Pair<PointsToResult, Collection<InstanceKey>> queryResult = dmp.getPointsTo(castedPk, castPred);
|
||||
long runningTime = System.currentTimeMillis() - startTime;
|
||||
System.err.println("running time: " + runningTime + "ms");
|
||||
final FieldRefinePolicy fieldRefinePolicy = dmp.getRefinementPolicy().getFieldRefinePolicy();
|
||||
switch (queryResult.fst) {
|
||||
case SUCCESS:
|
||||
System.err.println("SAFE: " + castInstr + " in " + node.getMethod());
|
||||
if (fieldRefinePolicy instanceof ManualFieldPolicy) {
|
||||
ManualFieldPolicy hackedFieldPolicy = (ManualFieldPolicy) fieldRefinePolicy;
|
||||
System.err.println(hackedFieldPolicy.getHistory());
|
||||
}
|
||||
System.err.println("TRAVERSED " + dmp.getNumNodesTraversed() + " nodes");
|
||||
numSafe++;
|
||||
break;
|
||||
case NOMOREREFINE:
|
||||
if (queryResult.snd != null) {
|
||||
System.err.println("MIGHT FAIL: no more refinement possible for " + castInstr + " in " + node.getMethod());
|
||||
} else {
|
||||
System.err.println("MIGHT FAIL: exceeded budget for " + castInstr + " in " + node.getMethod());
|
||||
}
|
||||
failing.add(Pair.make(node, castInstr));
|
||||
numMightFail++;
|
||||
break;
|
||||
case BUDGETEXCEEDED:
|
||||
System.err.println("MIGHT FAIL: exceeded budget for " + castInstr + " in " + node.getMethod());
|
||||
failing.add(Pair.make(node, castInstr));
|
||||
numMightFail++;
|
||||
break;
|
||||
default:
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
}
|
||||
}
|
||||
// break outer;
|
||||
}
|
||||
System.err.println("TOTAL SAFE: " + numSafe);
|
||||
System.err.println("TOTAL MIGHT FAIL: " + numMightFail);
|
||||
return failing;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,229 +1,229 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
package com.ibm.wala.cast.java.translator.polyglot;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import polyglot.types.ArrayType;
|
||||
import polyglot.types.ClassType;
|
||||
import polyglot.types.CodeInstance;
|
||||
import polyglot.types.ConstructorInstance;
|
||||
import polyglot.types.FieldInstance;
|
||||
import polyglot.types.InitializerInstance;
|
||||
import polyglot.types.MemberDef;
|
||||
import polyglot.types.MethodInstance;
|
||||
import polyglot.types.PrimitiveType;
|
||||
import polyglot.types.ProcedureInstance;
|
||||
import polyglot.types.Type;
|
||||
|
||||
import com.ibm.wala.cast.java.translator.polyglot.PolyglotJava2CAstTranslator.IdentityMapper;
|
||||
import com.ibm.wala.cast.java.types.JavaPrimitiveTypeMap;
|
||||
import com.ibm.wala.types.ClassLoaderReference;
|
||||
import com.ibm.wala.types.Descriptor;
|
||||
import com.ibm.wala.types.FieldReference;
|
||||
import com.ibm.wala.types.MethodReference;
|
||||
import com.ibm.wala.types.Selector;
|
||||
import com.ibm.wala.types.TypeName;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
import com.ibm.wala.util.collections.HashMapFactory;
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
import com.ibm.wala.util.strings.Atom;
|
||||
|
||||
/**
|
||||
* Class responsible for mapping Polyglot type system objects representing types,
|
||||
* methods and fields to the corresponding WALA TypeReferences, MethodReferences
|
||||
* and FieldReferences. Used during translation and by clients to help correlate
|
||||
* WALA analysis results to the various AST nodes.
|
||||
* @author rfuhrer
|
||||
*/
|
||||
public class PolyglotIdentityMapper implements IdentityMapper<Type, CodeInstance, FieldInstance> {
|
||||
private final Map<Type, TypeReference> fTypeMap = HashMapFactory.make();
|
||||
|
||||
private final Map<FieldInstance, FieldReference> fFieldMap = HashMapFactory.make();
|
||||
|
||||
private final Map<CodeInstance, MethodReference> fMethodMap = HashMapFactory.make();
|
||||
|
||||
/**
|
||||
* Map from Polyglot local ClassTypes to their enclosing methods. Used by localTypeToTypeID().<br>
|
||||
* Needed since Polyglot doesn't provide this information. (It doesn't need to, since it
|
||||
* doesn't need to generate unambiguous names for such entities -- it hands the source
|
||||
* off to javac to generate bytecode. It probably also wouldn't want to, since that would
|
||||
* create back-pointers from Type objects in the TypeSystem to AST's.)
|
||||
*/
|
||||
protected Map<ClassType, CodeInstance> fLocalTypeMap = new LinkedHashMap<ClassType, CodeInstance>();
|
||||
|
||||
protected final ClassLoaderReference fClassLoaderRef;
|
||||
|
||||
public PolyglotIdentityMapper(ClassLoaderReference clr) {
|
||||
fClassLoaderRef= clr;
|
||||
}
|
||||
|
||||
public FieldReference getFieldRef(FieldInstance field) {
|
||||
if (!fFieldMap.containsKey(field)) {
|
||||
FieldReference ref= referenceForField(field);
|
||||
fFieldMap.put(field, ref);
|
||||
return ref;
|
||||
}
|
||||
return fFieldMap.get(field);
|
||||
}
|
||||
|
||||
public TypeReference getTypeRef(Type type) {
|
||||
if (!fTypeMap.containsKey(type)) {
|
||||
TypeReference ref= referenceForType(type);
|
||||
fTypeMap.put(type, ref);
|
||||
return ref;
|
||||
}
|
||||
return fTypeMap.get(type);
|
||||
}
|
||||
|
||||
public MethodReference getMethodRef(CodeInstance method) {
|
||||
if (!fMethodMap.containsKey(method)) {
|
||||
MethodReference sel= referenceForMethod(method);
|
||||
fMethodMap.put(method, sel);
|
||||
return sel;
|
||||
}
|
||||
return fMethodMap.get(method);
|
||||
}
|
||||
|
||||
public void mapLocalAnonTypeToMethod(ClassType anonLocalType, CodeInstance owningProc) {
|
||||
fLocalTypeMap.put(anonLocalType, owningProc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a FieldReference for the given Polyglot FieldInstance.<br>
|
||||
* N.B.: This method <b>does not canonicalize</b> the FieldReferences,
|
||||
* but rather creates a new one for each call.
|
||||
* You more likely want to call getFieldRef(). This method is exposed
|
||||
* so that multiple Polyglot instances can use the translation services
|
||||
* without having FieldInstances collide (producing the dreaded "we are
|
||||
* TypeSystem_c but type Foo is from TypeSystem_c" exception).
|
||||
*/
|
||||
public FieldReference referenceForField(FieldInstance field) {
|
||||
Type targetType= field.container();
|
||||
Type fieldType= field.type();
|
||||
TypeReference targetTypeRef= TypeReference.findOrCreate(fClassLoaderRef, typeToTypeID(targetType));
|
||||
TypeReference fieldTypeRef= TypeReference.findOrCreate(fClassLoaderRef, typeToTypeID(fieldType));
|
||||
Atom fieldName= Atom.findOrCreateUnicodeAtom(field.name().toString());
|
||||
FieldReference fieldRef= FieldReference.findOrCreate(targetTypeRef, fieldName, fieldTypeRef);
|
||||
|
||||
return fieldRef;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a TypeReference for the given Polyglot Type.<br>
|
||||
* N.B.: This method <b>does not canonicalize</b> the TypeReferences,
|
||||
* but rather creates a new one for each call.
|
||||
* You more likely want to call getTypeRef(). This method is exposed
|
||||
* so that multiple Polyglot instances can use the translation services
|
||||
* without having Types collide (producing the dreaded "we are
|
||||
* TypeSystem_c but type Foo is from TypeSystem_c" exception).
|
||||
*/
|
||||
public TypeReference referenceForType(Type type) {
|
||||
TypeName typeName= TypeName.string2TypeName(typeToTypeID(type));
|
||||
TypeReference typeRef= TypeReference.findOrCreate(fClassLoaderRef, typeName);
|
||||
|
||||
return typeRef;
|
||||
}
|
||||
|
||||
private Selector selectorForMethod(CodeInstance procInstance) {
|
||||
Atom name=
|
||||
(procInstance instanceof ConstructorInstance) ?
|
||||
MethodReference.initAtom :
|
||||
(procInstance instanceof InitializerInstance) ?
|
||||
MethodReference.clinitName :
|
||||
Atom.findOrCreateUnicodeAtom(((MethodInstance) procInstance).name().toString());
|
||||
|
||||
TypeName[] argTypeNames = null;
|
||||
if (! (procInstance instanceof InitializerInstance)) {
|
||||
List formalTypes = ((ProcedureInstance)procInstance).formalTypes();
|
||||
int numArgs = formalTypes.size();
|
||||
// Descriptor prefers null to an empty array
|
||||
if (numArgs > 0) {
|
||||
argTypeNames = new TypeName[numArgs];
|
||||
|
||||
int i = 0;
|
||||
for(Iterator iter = formalTypes.iterator(); iter.hasNext(); i++) {
|
||||
Type argType= (Type) iter.next();
|
||||
argTypeNames[i]= TypeName.string2TypeName(typeToTypeID(argType));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Type retType=
|
||||
(procInstance instanceof MethodInstance) ? ((MethodInstance) procInstance).returnType() : procInstance.typeSystem().Void();
|
||||
TypeName retTypeName= TypeName.string2TypeName(typeToTypeID(retType));
|
||||
|
||||
Descriptor desc= Descriptor.findOrCreate(argTypeNames, retTypeName);
|
||||
|
||||
return new Selector(name, desc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a MethodReference for the given Polyglot MethodInstance.<br>
|
||||
* N.B.: This method <b>does not canonicalize</b> the MethodReferences,
|
||||
* but rather creates a new one for each call.
|
||||
* You more likely want to call getMethodRef(). This method is exposed
|
||||
* so that multiple Polyglot instances can use the translation services
|
||||
* without having MethodInstances collide (producing the dreaded "we are
|
||||
* TypeSystem_c but type Foo is from TypeSystem_c" exception).
|
||||
*/
|
||||
public MethodReference referenceForMethod(CodeInstance procInstance) {
|
||||
// Handles both ConstructorInstance's and MethodInstance's
|
||||
TypeName ownerType= TypeName.string2TypeName(typeToTypeID(((MemberDef) procInstance.def()).container().get()));
|
||||
TypeReference ownerTypeRef= TypeReference.findOrCreate(fClassLoaderRef, ownerType);
|
||||
MethodReference methodRef= MethodReference.findOrCreate(ownerTypeRef, selectorForMethod(procInstance));
|
||||
|
||||
return methodRef;
|
||||
}
|
||||
|
||||
/**
|
||||
* Translates the given Polyglot type to a name suitable for use in a WALA TypeReference
|
||||
* (i.e. a bytecode-compliant type name).
|
||||
*/
|
||||
public String typeToTypeID(Type type) {
|
||||
if (type.isPrimitive()) {
|
||||
PrimitiveType ptype= (PrimitiveType) type;
|
||||
|
||||
return JavaPrimitiveTypeMap.getShortName(ptype.name().toString());
|
||||
} else if (type.isArray()) {
|
||||
ArrayType atype= (ArrayType) type;
|
||||
return "[" + typeToTypeID(atype.base());
|
||||
} else if (type.isNull()) {
|
||||
Assertions.UNREACHABLE("typeToTypeID() encountered a null type!");
|
||||
return null;
|
||||
}
|
||||
Assertions.productionAssertion(type.isClass(), "typeToTypeID() encountered the type " + type + " that is neither primitive, array, nor class!");
|
||||
|
||||
ClassType ctype= (ClassType) type;
|
||||
|
||||
return (ctype.isLocal() || ctype.isAnonymous()) ? anonLocalTypeToTypeID(ctype) : composeWALATypeDescriptor(ctype);
|
||||
}
|
||||
|
||||
public String anonLocalTypeToTypeID(ClassType ctype) {
|
||||
CodeInstance procInstance= (CodeInstance) fLocalTypeMap.get(ctype);
|
||||
|
||||
String outerTypeID= typeToTypeID(ctype.outer());
|
||||
String shortName= (ctype.isAnonymous()) ? PolyglotJava2CAstTranslator.anonTypeName(ctype) : ctype.fullName().name().toString();
|
||||
|
||||
return outerTypeID + '/' + getMethodRef(procInstance).getSelector() + '/' + shortName;
|
||||
}
|
||||
|
||||
public String composeWALATypeDescriptor(ClassType ctype) {
|
||||
return "L" + composeWALATypeName(ctype);
|
||||
}
|
||||
|
||||
public String composeWALATypeName(ClassType ctype) {
|
||||
if (ctype.package_() != null) {
|
||||
String packageName = ctype.package_().fullName().toString();
|
||||
|
||||
Assertions.productionAssertion(ctype.fullName().toString().startsWith(packageName));
|
||||
return packageName.replace('.','/') + "/" + ctype.fullName().toString().substring( packageName.length()+1 ).replace('.','$');
|
||||
} else {
|
||||
return ctype.fullName().toString().replace('.', '$');
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
*
|
||||
*/
|
||||
package com.ibm.wala.cast.java.translator.polyglot;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import polyglot.types.ArrayType;
|
||||
import polyglot.types.ClassType;
|
||||
import polyglot.types.CodeInstance;
|
||||
import polyglot.types.ConstructorInstance;
|
||||
import polyglot.types.FieldInstance;
|
||||
import polyglot.types.InitializerInstance;
|
||||
import polyglot.types.MemberDef;
|
||||
import polyglot.types.MethodInstance;
|
||||
import polyglot.types.PrimitiveType;
|
||||
import polyglot.types.ProcedureInstance;
|
||||
import polyglot.types.Type;
|
||||
|
||||
import com.ibm.wala.cast.java.translator.polyglot.PolyglotJava2CAstTranslator.IdentityMapper;
|
||||
import com.ibm.wala.cast.java.types.JavaPrimitiveTypeMap;
|
||||
import com.ibm.wala.types.ClassLoaderReference;
|
||||
import com.ibm.wala.types.Descriptor;
|
||||
import com.ibm.wala.types.FieldReference;
|
||||
import com.ibm.wala.types.MethodReference;
|
||||
import com.ibm.wala.types.Selector;
|
||||
import com.ibm.wala.types.TypeName;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
import com.ibm.wala.util.collections.HashMapFactory;
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
import com.ibm.wala.util.strings.Atom;
|
||||
|
||||
/**
|
||||
* Class responsible for mapping Polyglot type system objects representing types,
|
||||
* methods and fields to the corresponding WALA TypeReferences, MethodReferences
|
||||
* and FieldReferences. Used during translation and by clients to help correlate
|
||||
* WALA analysis results to the various AST nodes.
|
||||
* @author rfuhrer
|
||||
*/
|
||||
public class PolyglotIdentityMapper implements IdentityMapper<Type, CodeInstance, FieldInstance> {
|
||||
private final Map<Type, TypeReference> fTypeMap = HashMapFactory.make();
|
||||
|
||||
private final Map<FieldInstance, FieldReference> fFieldMap = HashMapFactory.make();
|
||||
|
||||
private final Map<CodeInstance, MethodReference> fMethodMap = HashMapFactory.make();
|
||||
|
||||
/**
|
||||
* Map from Polyglot local ClassTypes to their enclosing methods. Used by localTypeToTypeID().<br>
|
||||
* Needed since Polyglot doesn't provide this information. (It doesn't need to, since it
|
||||
* doesn't need to generate unambiguous names for such entities -- it hands the source
|
||||
* off to javac to generate bytecode. It probably also wouldn't want to, since that would
|
||||
* create back-pointers from Type objects in the TypeSystem to AST's.)
|
||||
*/
|
||||
protected Map<ClassType, CodeInstance> fLocalTypeMap = new LinkedHashMap<ClassType, CodeInstance>();
|
||||
|
||||
protected final ClassLoaderReference fClassLoaderRef;
|
||||
|
||||
public PolyglotIdentityMapper(ClassLoaderReference clr) {
|
||||
fClassLoaderRef= clr;
|
||||
}
|
||||
|
||||
public FieldReference getFieldRef(FieldInstance field) {
|
||||
if (!fFieldMap.containsKey(field)) {
|
||||
FieldReference ref= referenceForField(field);
|
||||
fFieldMap.put(field, ref);
|
||||
return ref;
|
||||
}
|
||||
return fFieldMap.get(field);
|
||||
}
|
||||
|
||||
public TypeReference getTypeRef(Type type) {
|
||||
if (!fTypeMap.containsKey(type)) {
|
||||
TypeReference ref= referenceForType(type);
|
||||
fTypeMap.put(type, ref);
|
||||
return ref;
|
||||
}
|
||||
return fTypeMap.get(type);
|
||||
}
|
||||
|
||||
public MethodReference getMethodRef(CodeInstance method) {
|
||||
if (!fMethodMap.containsKey(method)) {
|
||||
MethodReference sel= referenceForMethod(method);
|
||||
fMethodMap.put(method, sel);
|
||||
return sel;
|
||||
}
|
||||
return fMethodMap.get(method);
|
||||
}
|
||||
|
||||
public void mapLocalAnonTypeToMethod(ClassType anonLocalType, CodeInstance owningProc) {
|
||||
fLocalTypeMap.put(anonLocalType, owningProc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a FieldReference for the given Polyglot FieldInstance.<br>
|
||||
* N.B.: This method <b>does not canonicalize</b> the FieldReferences,
|
||||
* but rather creates a new one for each call.
|
||||
* You more likely want to call getFieldRef(). This method is exposed
|
||||
* so that multiple Polyglot instances can use the translation services
|
||||
* without having FieldInstances collide (producing the dreaded "we are
|
||||
* TypeSystem_c but type Foo is from TypeSystem_c" exception).
|
||||
*/
|
||||
public FieldReference referenceForField(FieldInstance field) {
|
||||
Type targetType= field.container();
|
||||
Type fieldType= field.type();
|
||||
TypeReference targetTypeRef= TypeReference.findOrCreate(fClassLoaderRef, typeToTypeID(targetType));
|
||||
TypeReference fieldTypeRef= TypeReference.findOrCreate(fClassLoaderRef, typeToTypeID(fieldType));
|
||||
Atom fieldName= Atom.findOrCreateUnicodeAtom(field.name().toString());
|
||||
FieldReference fieldRef= FieldReference.findOrCreate(targetTypeRef, fieldName, fieldTypeRef);
|
||||
|
||||
return fieldRef;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a TypeReference for the given Polyglot Type.<br>
|
||||
* N.B.: This method <b>does not canonicalize</b> the TypeReferences,
|
||||
* but rather creates a new one for each call.
|
||||
* You more likely want to call getTypeRef(). This method is exposed
|
||||
* so that multiple Polyglot instances can use the translation services
|
||||
* without having Types collide (producing the dreaded "we are
|
||||
* TypeSystem_c but type Foo is from TypeSystem_c" exception).
|
||||
*/
|
||||
public TypeReference referenceForType(Type type) {
|
||||
TypeName typeName= TypeName.string2TypeName(typeToTypeID(type));
|
||||
TypeReference typeRef= TypeReference.findOrCreate(fClassLoaderRef, typeName);
|
||||
|
||||
return typeRef;
|
||||
}
|
||||
|
||||
private Selector selectorForMethod(CodeInstance procInstance) {
|
||||
Atom name=
|
||||
(procInstance instanceof ConstructorInstance) ?
|
||||
MethodReference.initAtom :
|
||||
(procInstance instanceof InitializerInstance) ?
|
||||
MethodReference.clinitName :
|
||||
Atom.findOrCreateUnicodeAtom(((MethodInstance) procInstance).name().toString());
|
||||
|
||||
TypeName[] argTypeNames = null;
|
||||
if (! (procInstance instanceof InitializerInstance)) {
|
||||
List formalTypes = ((ProcedureInstance)procInstance).formalTypes();
|
||||
int numArgs = formalTypes.size();
|
||||
// Descriptor prefers null to an empty array
|
||||
if (numArgs > 0) {
|
||||
argTypeNames = new TypeName[numArgs];
|
||||
|
||||
int i = 0;
|
||||
for(Iterator iter = formalTypes.iterator(); iter.hasNext(); i++) {
|
||||
Type argType= (Type) iter.next();
|
||||
argTypeNames[i]= TypeName.string2TypeName(typeToTypeID(argType));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Type retType=
|
||||
(procInstance instanceof MethodInstance) ? ((MethodInstance) procInstance).returnType() : procInstance.typeSystem().Void();
|
||||
TypeName retTypeName= TypeName.string2TypeName(typeToTypeID(retType));
|
||||
|
||||
Descriptor desc= Descriptor.findOrCreate(argTypeNames, retTypeName);
|
||||
|
||||
return new Selector(name, desc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a MethodReference for the given Polyglot MethodInstance.<br>
|
||||
* N.B.: This method <b>does not canonicalize</b> the MethodReferences,
|
||||
* but rather creates a new one for each call.
|
||||
* You more likely want to call getMethodRef(). This method is exposed
|
||||
* so that multiple Polyglot instances can use the translation services
|
||||
* without having MethodInstances collide (producing the dreaded "we are
|
||||
* TypeSystem_c but type Foo is from TypeSystem_c" exception).
|
||||
*/
|
||||
public MethodReference referenceForMethod(CodeInstance procInstance) {
|
||||
// Handles both ConstructorInstance's and MethodInstance's
|
||||
TypeName ownerType= TypeName.string2TypeName(typeToTypeID(((MemberDef) procInstance.def()).container().get()));
|
||||
TypeReference ownerTypeRef= TypeReference.findOrCreate(fClassLoaderRef, ownerType);
|
||||
MethodReference methodRef= MethodReference.findOrCreate(ownerTypeRef, selectorForMethod(procInstance));
|
||||
|
||||
return methodRef;
|
||||
}
|
||||
|
||||
/**
|
||||
* Translates the given Polyglot type to a name suitable for use in a WALA TypeReference
|
||||
* (i.e. a bytecode-compliant type name).
|
||||
*/
|
||||
public String typeToTypeID(Type type) {
|
||||
if (type.isPrimitive()) {
|
||||
PrimitiveType ptype= (PrimitiveType) type;
|
||||
|
||||
return JavaPrimitiveTypeMap.getShortName(ptype.name().toString());
|
||||
} else if (type.isArray()) {
|
||||
ArrayType atype= (ArrayType) type;
|
||||
return "[" + typeToTypeID(atype.base());
|
||||
} else if (type.isNull()) {
|
||||
Assertions.UNREACHABLE("typeToTypeID() encountered a null type!");
|
||||
return null;
|
||||
}
|
||||
Assertions.productionAssertion(type.isClass(), "typeToTypeID() encountered the type " + type + " that is neither primitive, array, nor class!");
|
||||
|
||||
ClassType ctype= (ClassType) type;
|
||||
|
||||
return (ctype.isLocal() || ctype.isAnonymous()) ? anonLocalTypeToTypeID(ctype) : composeWALATypeDescriptor(ctype);
|
||||
}
|
||||
|
||||
public String anonLocalTypeToTypeID(ClassType ctype) {
|
||||
CodeInstance procInstance= (CodeInstance) fLocalTypeMap.get(ctype);
|
||||
|
||||
String outerTypeID= typeToTypeID(ctype.outer());
|
||||
String shortName= (ctype.isAnonymous()) ? PolyglotJava2CAstTranslator.anonTypeName(ctype) : ctype.fullName().name().toString();
|
||||
|
||||
return outerTypeID + '/' + getMethodRef(procInstance).getSelector() + '/' + shortName;
|
||||
}
|
||||
|
||||
public String composeWALATypeDescriptor(ClassType ctype) {
|
||||
return "L" + composeWALATypeName(ctype);
|
||||
}
|
||||
|
||||
public String composeWALATypeName(ClassType ctype) {
|
||||
if (ctype.package_() != null) {
|
||||
String packageName = ctype.package_().fullName().toString();
|
||||
|
||||
Assertions.productionAssertion(ctype.fullName().toString().startsWith(packageName));
|
||||
return packageName.replace('.','/') + "/" + ctype.fullName().toString().substring( packageName.length()+1 ).replace('.','$');
|
||||
} else {
|
||||
return ctype.fullName().toString().replace('.', '$');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,447 +1,447 @@
|
||||
/******************************************************************************
|
||||
* 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
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* Created on Oct 3, 2005
|
||||
*/
|
||||
package com.ibm.wala.cast.java.test;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.jar.JarFile;
|
||||
|
||||
import org.junit.Assert;
|
||||
|
||||
import com.ibm.wala.cast.java.client.JavaSourceAnalysisEngine;
|
||||
import com.ibm.wala.cast.java.ipa.callgraph.JavaSourceAnalysisScope;
|
||||
import com.ibm.wala.cast.loader.AstClass;
|
||||
import com.ibm.wala.cast.loader.AstMethod;
|
||||
import com.ibm.wala.classLoader.IClass;
|
||||
import com.ibm.wala.classLoader.IClassLoader;
|
||||
import com.ibm.wala.classLoader.IMethod;
|
||||
import com.ibm.wala.classLoader.JarFileModule;
|
||||
import com.ibm.wala.classLoader.Language;
|
||||
import com.ibm.wala.classLoader.SourceDirectoryTreeModule;
|
||||
import com.ibm.wala.classLoader.SourceFileModule;
|
||||
import com.ibm.wala.client.AbstractAnalysisEngine;
|
||||
import com.ibm.wala.ipa.callgraph.CGNode;
|
||||
import com.ibm.wala.ipa.callgraph.CallGraph;
|
||||
import com.ibm.wala.ipa.cha.IClassHierarchy;
|
||||
import com.ibm.wala.properties.WalaProperties;
|
||||
import com.ibm.wala.ssa.IR;
|
||||
import com.ibm.wala.ssa.SSAInstruction;
|
||||
import com.ibm.wala.types.ClassLoaderReference;
|
||||
import com.ibm.wala.types.MethodReference;
|
||||
import com.ibm.wala.types.TypeName;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
import com.ibm.wala.util.CancelException;
|
||||
import com.ibm.wala.util.collections.HashSetFactory;
|
||||
import com.ibm.wala.util.collections.Pair;
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
import com.ibm.wala.util.strings.Atom;
|
||||
|
||||
public abstract class IRTests {
|
||||
|
||||
protected IRTests(String projectName) {
|
||||
this.projectName = projectName;
|
||||
}
|
||||
|
||||
protected final String projectName;
|
||||
|
||||
protected static String javaHomePath;
|
||||
|
||||
private String testSrcPath = "." + File.separator + "src";
|
||||
|
||||
public static List<String> rtJar;
|
||||
|
||||
protected static List<IRAssertion> emptyList = Collections.emptyList();
|
||||
|
||||
static {
|
||||
boolean found = false;
|
||||
try {
|
||||
rtJar = new LinkedList<String>();
|
||||
|
||||
Properties p = WalaProperties.loadProperties();
|
||||
javaHomePath = p.getProperty(WalaProperties.J2SE_DIR);
|
||||
|
||||
if (new File(javaHomePath).isDirectory()) {
|
||||
if ("Mac OS X".equals(System.getProperty("os.name"))) { // nick
|
||||
/**
|
||||
* todo: {@link WalaProperties#getJ2SEJarFiles()}
|
||||
*/
|
||||
rtJar.add(javaHomePath + "/classes.jar");
|
||||
rtJar.add(javaHomePath + "/ui.jar");
|
||||
} else {
|
||||
rtJar.add(javaHomePath + File.separator + "classes.jar");
|
||||
rtJar.add(javaHomePath + File.separator + "rt.jar");
|
||||
rtJar.add(javaHomePath + File.separator + "core.jar");
|
||||
rtJar.add(javaHomePath + File.separator + "vm.jar");
|
||||
}
|
||||
found = true;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// no properties
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
javaHomePath = System.getProperty("java.home");
|
||||
if ("Mac OS X".equals(System.getProperty("os.name"))) { // nick
|
||||
rtJar.add(javaHomePath + "/../Classes/classes.jar");
|
||||
rtJar.add(javaHomePath + "/../Classes/ui.jar");
|
||||
} else {
|
||||
rtJar.add(javaHomePath + File.separator + "lib" + File.separator + "rt.jar");
|
||||
rtJar.add(javaHomePath + File.separator + "lib" + File.separator + "core.jar");
|
||||
rtJar.add(javaHomePath + File.separator + "lib" + File.separator + "vm.jar");
|
||||
rtJar.add(javaHomePath + File.separator + "lib" + File.separator + "classes.jar");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public interface IRAssertion {
|
||||
|
||||
void check(CallGraph cg);
|
||||
|
||||
}
|
||||
|
||||
protected static class EdgeAssertions implements IRAssertion {
|
||||
public final String srcDescriptor;
|
||||
|
||||
public final List/* <String> */<String> tgtDescriptors = new ArrayList<String>();
|
||||
|
||||
public EdgeAssertions(String srcDescriptor) {
|
||||
this.srcDescriptor = srcDescriptor;
|
||||
}
|
||||
|
||||
public static EdgeAssertions make(String srcDescriptor, String tgtDescriptor) {
|
||||
EdgeAssertions ea = new EdgeAssertions(srcDescriptor);
|
||||
ea.tgtDescriptors.add(tgtDescriptor);
|
||||
return ea;
|
||||
}
|
||||
|
||||
public static EdgeAssertions make(String srcDescriptor, String tgtDescriptor1, String tgtDescriptor2) {
|
||||
EdgeAssertions ea = new EdgeAssertions(srcDescriptor);
|
||||
ea.tgtDescriptors.add(tgtDescriptor1);
|
||||
ea.tgtDescriptors.add(tgtDescriptor2);
|
||||
return ea;
|
||||
}
|
||||
|
||||
public static EdgeAssertions make(String srcDescriptor, String tgtDescriptor1, String tgtDescriptor2, String tgtDescriptor3) {
|
||||
EdgeAssertions ea = new EdgeAssertions(srcDescriptor);
|
||||
ea.tgtDescriptors.add(tgtDescriptor1);
|
||||
ea.tgtDescriptors.add(tgtDescriptor2);
|
||||
ea.tgtDescriptors.add(tgtDescriptor3);
|
||||
return ea;
|
||||
}
|
||||
|
||||
public static EdgeAssertions make(String srcDescriptor, String tgtDescriptor1, String tgtDescriptor2, String tgtDescriptor3,
|
||||
String tgtDescriptor4) {
|
||||
EdgeAssertions ea = new EdgeAssertions(srcDescriptor);
|
||||
ea.tgtDescriptors.add(tgtDescriptor1);
|
||||
ea.tgtDescriptors.add(tgtDescriptor2);
|
||||
ea.tgtDescriptors.add(tgtDescriptor3);
|
||||
ea.tgtDescriptors.add(tgtDescriptor4);
|
||||
return ea;
|
||||
}
|
||||
|
||||
public void check(CallGraph callGraph) {
|
||||
MethodReference srcMethod = descriptorToMethodRef(this.srcDescriptor, callGraph.getClassHierarchy());
|
||||
Set<CGNode> srcNodes = callGraph.getNodes(srcMethod);
|
||||
|
||||
if (srcNodes.size() == 0) {
|
||||
System.err.println(("Unreachable/non-existent method: " + srcMethod));
|
||||
return;
|
||||
}
|
||||
if (srcNodes.size() > 1) {
|
||||
System.err.println("Context-sensitive call graph?");
|
||||
}
|
||||
|
||||
// Assume only one node for src method
|
||||
CGNode srcNode = srcNodes.iterator().next();
|
||||
|
||||
for (String target : this.tgtDescriptors) {
|
||||
MethodReference tgtMethod = descriptorToMethodRef(target, callGraph.getClassHierarchy());
|
||||
// Assume only one node for target method
|
||||
Set<CGNode> tgtNodes = callGraph.getNodes(tgtMethod);
|
||||
if (tgtNodes.size() == 0) {
|
||||
System.err.println(("Unreachable/non-existent method: " + tgtMethod));
|
||||
continue;
|
||||
}
|
||||
CGNode tgtNode = tgtNodes.iterator().next();
|
||||
|
||||
boolean found = false;
|
||||
for (Iterator<? extends CGNode> succIter = callGraph.getSuccNodes(srcNode); succIter.hasNext();) {
|
||||
CGNode succ = succIter.next();
|
||||
|
||||
if (tgtNode == succ) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
System.err.println(("Missing edge: " + srcMethod + " -> " + tgtMethod));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected static class SourceMapAssertion implements IRAssertion {
|
||||
private final String method;
|
||||
|
||||
private final String variableName;
|
||||
|
||||
private final int definingLineNumber;
|
||||
|
||||
protected SourceMapAssertion(String method, String variableName, int definingLineNumber) {
|
||||
this.method = method;
|
||||
this.variableName = variableName;
|
||||
this.definingLineNumber = definingLineNumber;
|
||||
}
|
||||
|
||||
public void check(CallGraph cg) {
|
||||
|
||||
MethodReference mref = descriptorToMethodRef(method, cg.getClassHierarchy());
|
||||
|
||||
for (CGNode cgNode : cg.getNodes(mref)) {
|
||||
Assert.assertTrue("failed for " + this.variableName + " in " + cgNode, this.check(cgNode.getMethod(), cgNode.getIR()));
|
||||
}
|
||||
}
|
||||
|
||||
boolean check(IMethod m, IR ir) {
|
||||
System.err.println(("check for " + variableName + " defined at " + definingLineNumber));
|
||||
SSAInstruction[] insts = ir.getInstructions();
|
||||
for (int i = 0; i < insts.length; i++) {
|
||||
if (insts[i] != null) {
|
||||
int ln = m.getLineNumber(i);
|
||||
if (ln == definingLineNumber) {
|
||||
System.err.println((" found " + insts[i] + " at " + ln));
|
||||
for (int j = 0; j < insts[i].getNumberOfDefs(); j++) {
|
||||
int def = insts[i].getDef(j);
|
||||
System.err.println((" looking at def " + j + ": " + def));
|
||||
String[] names = ir.getLocalNames(i, def);
|
||||
if (names != null) {
|
||||
for (String name : names) {
|
||||
System.err.println((" looking at name " + name));
|
||||
if (name.equals(variableName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected Collection<String> singleTestSrc() {
|
||||
return Collections.singletonList(getTestSrcPath() + File.separator + singleJavaInputForTest());
|
||||
}
|
||||
|
||||
protected Collection<String> singleTestSrc(final String folder) {
|
||||
return Collections.singletonList(getTestSrcPath() + File.separator + folder + File.separator + singleJavaInputForTest());
|
||||
}
|
||||
|
||||
protected Collection<String> singlePkgTestSrc(String pkgName) {
|
||||
return Collections.singletonList(getTestSrcPath() + File.separator + singleJavaPkgInputForTest(pkgName));
|
||||
}
|
||||
|
||||
protected String getTestName() {
|
||||
StackTraceElement stack[] = new Throwable().getStackTrace();
|
||||
for(int i = 0; i <= stack.length; i++) {
|
||||
if (stack[i].getMethodName().startsWith("test")) {
|
||||
return stack[i].getMethodName();
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error("test method not found");
|
||||
}
|
||||
|
||||
protected String[] simpleTestEntryPoint() {
|
||||
return new String[] { "L" + getTestName().substring(4) };
|
||||
}
|
||||
|
||||
protected String[] simplePkgTestEntryPoint(String pkgName) {
|
||||
return new String[] { "L" + pkgName + "/" + getTestName().substring(4) };
|
||||
}
|
||||
|
||||
protected abstract AbstractAnalysisEngine getAnalysisEngine(String[] mainClassDescriptors, Collection<String> sources, List<String> libs);
|
||||
|
||||
public Pair runTest(Collection<String> sources, List<String> libs, String[] mainClassDescriptors, List<? extends IRAssertion> ca,
|
||||
boolean assertReachable) {
|
||||
AbstractAnalysisEngine engine = getAnalysisEngine(mainClassDescriptors, sources, libs);
|
||||
|
||||
CallGraph callGraph;
|
||||
try {
|
||||
callGraph = engine.buildDefaultCallGraph();
|
||||
System.err.println(callGraph.toString());
|
||||
|
||||
// If we've gotten this far, IR has been produced.
|
||||
dumpIR(callGraph, sources, assertReachable);
|
||||
|
||||
// Now check any assertions as to source mapping
|
||||
for (IRAssertion IRAssertion : ca) {
|
||||
IRAssertion.check(callGraph);
|
||||
}
|
||||
|
||||
return Pair.make(callGraph, engine.getPointerAnalysis());
|
||||
} catch (IllegalArgumentException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
} catch (CancelException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected static void dumpIR(CallGraph cg, Collection<String> sources, boolean assertReachable) throws IOException {
|
||||
Set<String> sourcePaths = HashSetFactory.make();
|
||||
for(String src : sources) {
|
||||
sourcePaths.add(src.substring(src.lastIndexOf(File.separator)+1));
|
||||
}
|
||||
|
||||
Set<IMethod> unreachable = HashSetFactory.make();
|
||||
IClassHierarchy cha = cg.getClassHierarchy();
|
||||
IClassLoader sourceLoader = cha.getLoader(JavaSourceAnalysisScope.SOURCE);
|
||||
for (Iterator iter = sourceLoader.iterateAllClasses(); iter.hasNext();) {
|
||||
IClass clazz = (IClass) iter.next();
|
||||
|
||||
System.err.println(clazz);
|
||||
if (clazz.isInterface())
|
||||
continue;
|
||||
|
||||
for (IMethod m : clazz.getDeclaredMethods()) {
|
||||
if (m.isAbstract()) {
|
||||
System.err.println(m);
|
||||
} else {
|
||||
Iterator nodeIter = cg.getNodes(m.getReference()).iterator();
|
||||
if (!nodeIter.hasNext()) {
|
||||
if (m instanceof AstMethod) {
|
||||
String fn = ((AstClass)m.getDeclaringClass()).getSourcePosition().getURL().getFile();
|
||||
if (sourcePaths.contains(fn.substring(fn.lastIndexOf(File.separator)+1))) {
|
||||
System.err.println(("Method " + m.getReference() + " not reachable?"));
|
||||
unreachable.add(m);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
CGNode node = (CGNode) nodeIter.next();
|
||||
System.err.println(node.getIR());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (assertReachable) {
|
||||
Assert.assertTrue("unreachable methods: " + unreachable.toString(), unreachable.isEmpty());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param srcMethodDescriptor a full method descriptor of the form ldr#type#methName#methSig example:
|
||||
* Source#Simple1#main#([Ljava/lang/String;)V
|
||||
* @param cha
|
||||
* @return
|
||||
*/
|
||||
public static MethodReference descriptorToMethodRef(String srcMethodDescriptor, IClassHierarchy cha) {
|
||||
String[] ldrTypeMeth = srcMethodDescriptor.split("\\#");
|
||||
|
||||
String loaderName = ldrTypeMeth[0];
|
||||
String typeStr = ldrTypeMeth[1];
|
||||
String methName = ldrTypeMeth[2];
|
||||
String methSig = ldrTypeMeth[3];
|
||||
|
||||
TypeReference typeRef = findOrCreateTypeReference(loaderName, typeStr, cha);
|
||||
|
||||
Language l = cha.getLoader(typeRef.getClassLoader()).getLanguage();
|
||||
return MethodReference.findOrCreate(l, typeRef, methName, methSig);
|
||||
}
|
||||
|
||||
static TypeReference findOrCreateTypeReference(String loaderName, String typeStr, IClassHierarchy cha) {
|
||||
ClassLoaderReference clr = findLoader(loaderName, cha);
|
||||
TypeName typeName = TypeName.string2TypeName("L" + typeStr);
|
||||
TypeReference typeRef = TypeReference.findOrCreate(clr, typeName);
|
||||
return typeRef;
|
||||
}
|
||||
|
||||
private static ClassLoaderReference findLoader(String loaderName, IClassHierarchy cha) {
|
||||
Atom loaderAtom = Atom.findOrCreateUnicodeAtom(loaderName);
|
||||
IClassLoader[] loaders = cha.getLoaders();
|
||||
for (IClassLoader loader : loaders) {
|
||||
if (loader.getName() == loaderAtom) {
|
||||
return loader.getReference();
|
||||
}
|
||||
}
|
||||
Assertions.UNREACHABLE();
|
||||
return null;
|
||||
}
|
||||
|
||||
protected void populateScope(JavaSourceAnalysisEngine engine, Collection<String> sources, List<String> libs) {
|
||||
boolean foundLib = false;
|
||||
for (String lib : libs) {
|
||||
File libFile = new File(lib);
|
||||
if (libFile.exists()) {
|
||||
foundLib = true;
|
||||
try {
|
||||
engine.addSystemModule(new JarFileModule(new JarFile(libFile)));
|
||||
} catch (IOException e) {
|
||||
Assert.fail(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
assert foundLib : "couldn't find library file from " + libs;
|
||||
|
||||
for (String srcFilePath : sources) {
|
||||
String srcFileName = srcFilePath.substring(srcFilePath.lastIndexOf(File.separator) + 1);
|
||||
File f = new File(srcFilePath);
|
||||
Assert.assertTrue("couldn't find " + srcFilePath, f.exists());
|
||||
if (f.isDirectory()) {
|
||||
engine.addSourceModule(new SourceDirectoryTreeModule(f));
|
||||
} else {
|
||||
engine.addSourceModule(new SourceFileModule(f, srcFileName));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void setTestSrcPath(String testSrcPath) {
|
||||
this.testSrcPath = testSrcPath;
|
||||
}
|
||||
|
||||
protected String getTestSrcPath() {
|
||||
return testSrcPath;
|
||||
}
|
||||
|
||||
protected String singleJavaInputForTest() {
|
||||
return getTestName().substring(4) + ".java";
|
||||
}
|
||||
|
||||
protected String singleInputForTest() {
|
||||
return getTestName().substring(4);
|
||||
}
|
||||
|
||||
protected String singleJavaPkgInputForTest(String pkgName) {
|
||||
return pkgName + File.separator + getTestName().substring(4) + ".java";
|
||||
}
|
||||
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* Created on Oct 3, 2005
|
||||
*/
|
||||
package com.ibm.wala.cast.java.test;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.jar.JarFile;
|
||||
|
||||
import org.junit.Assert;
|
||||
|
||||
import com.ibm.wala.cast.java.client.JavaSourceAnalysisEngine;
|
||||
import com.ibm.wala.cast.java.ipa.callgraph.JavaSourceAnalysisScope;
|
||||
import com.ibm.wala.cast.loader.AstClass;
|
||||
import com.ibm.wala.cast.loader.AstMethod;
|
||||
import com.ibm.wala.classLoader.IClass;
|
||||
import com.ibm.wala.classLoader.IClassLoader;
|
||||
import com.ibm.wala.classLoader.IMethod;
|
||||
import com.ibm.wala.classLoader.JarFileModule;
|
||||
import com.ibm.wala.classLoader.Language;
|
||||
import com.ibm.wala.classLoader.SourceDirectoryTreeModule;
|
||||
import com.ibm.wala.classLoader.SourceFileModule;
|
||||
import com.ibm.wala.client.AbstractAnalysisEngine;
|
||||
import com.ibm.wala.ipa.callgraph.CGNode;
|
||||
import com.ibm.wala.ipa.callgraph.CallGraph;
|
||||
import com.ibm.wala.ipa.cha.IClassHierarchy;
|
||||
import com.ibm.wala.properties.WalaProperties;
|
||||
import com.ibm.wala.ssa.IR;
|
||||
import com.ibm.wala.ssa.SSAInstruction;
|
||||
import com.ibm.wala.types.ClassLoaderReference;
|
||||
import com.ibm.wala.types.MethodReference;
|
||||
import com.ibm.wala.types.TypeName;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
import com.ibm.wala.util.CancelException;
|
||||
import com.ibm.wala.util.collections.HashSetFactory;
|
||||
import com.ibm.wala.util.collections.Pair;
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
import com.ibm.wala.util.strings.Atom;
|
||||
|
||||
public abstract class IRTests {
|
||||
|
||||
protected IRTests(String projectName) {
|
||||
this.projectName = projectName;
|
||||
}
|
||||
|
||||
protected final String projectName;
|
||||
|
||||
protected static String javaHomePath;
|
||||
|
||||
private String testSrcPath = "." + File.separator + "src";
|
||||
|
||||
public static List<String> rtJar;
|
||||
|
||||
protected static List<IRAssertion> emptyList = Collections.emptyList();
|
||||
|
||||
static {
|
||||
boolean found = false;
|
||||
try {
|
||||
rtJar = new LinkedList<String>();
|
||||
|
||||
Properties p = WalaProperties.loadProperties();
|
||||
javaHomePath = p.getProperty(WalaProperties.J2SE_DIR);
|
||||
|
||||
if (new File(javaHomePath).isDirectory()) {
|
||||
if ("Mac OS X".equals(System.getProperty("os.name"))) { // nick
|
||||
/**
|
||||
* todo: {@link WalaProperties#getJ2SEJarFiles()}
|
||||
*/
|
||||
rtJar.add(javaHomePath + "/classes.jar");
|
||||
rtJar.add(javaHomePath + "/ui.jar");
|
||||
} else {
|
||||
rtJar.add(javaHomePath + File.separator + "classes.jar");
|
||||
rtJar.add(javaHomePath + File.separator + "rt.jar");
|
||||
rtJar.add(javaHomePath + File.separator + "core.jar");
|
||||
rtJar.add(javaHomePath + File.separator + "vm.jar");
|
||||
}
|
||||
found = true;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// no properties
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
javaHomePath = System.getProperty("java.home");
|
||||
if ("Mac OS X".equals(System.getProperty("os.name"))) { // nick
|
||||
rtJar.add(javaHomePath + "/../Classes/classes.jar");
|
||||
rtJar.add(javaHomePath + "/../Classes/ui.jar");
|
||||
} else {
|
||||
rtJar.add(javaHomePath + File.separator + "lib" + File.separator + "rt.jar");
|
||||
rtJar.add(javaHomePath + File.separator + "lib" + File.separator + "core.jar");
|
||||
rtJar.add(javaHomePath + File.separator + "lib" + File.separator + "vm.jar");
|
||||
rtJar.add(javaHomePath + File.separator + "lib" + File.separator + "classes.jar");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public interface IRAssertion {
|
||||
|
||||
void check(CallGraph cg);
|
||||
|
||||
}
|
||||
|
||||
protected static class EdgeAssertions implements IRAssertion {
|
||||
public final String srcDescriptor;
|
||||
|
||||
public final List/* <String> */<String> tgtDescriptors = new ArrayList<String>();
|
||||
|
||||
public EdgeAssertions(String srcDescriptor) {
|
||||
this.srcDescriptor = srcDescriptor;
|
||||
}
|
||||
|
||||
public static EdgeAssertions make(String srcDescriptor, String tgtDescriptor) {
|
||||
EdgeAssertions ea = new EdgeAssertions(srcDescriptor);
|
||||
ea.tgtDescriptors.add(tgtDescriptor);
|
||||
return ea;
|
||||
}
|
||||
|
||||
public static EdgeAssertions make(String srcDescriptor, String tgtDescriptor1, String tgtDescriptor2) {
|
||||
EdgeAssertions ea = new EdgeAssertions(srcDescriptor);
|
||||
ea.tgtDescriptors.add(tgtDescriptor1);
|
||||
ea.tgtDescriptors.add(tgtDescriptor2);
|
||||
return ea;
|
||||
}
|
||||
|
||||
public static EdgeAssertions make(String srcDescriptor, String tgtDescriptor1, String tgtDescriptor2, String tgtDescriptor3) {
|
||||
EdgeAssertions ea = new EdgeAssertions(srcDescriptor);
|
||||
ea.tgtDescriptors.add(tgtDescriptor1);
|
||||
ea.tgtDescriptors.add(tgtDescriptor2);
|
||||
ea.tgtDescriptors.add(tgtDescriptor3);
|
||||
return ea;
|
||||
}
|
||||
|
||||
public static EdgeAssertions make(String srcDescriptor, String tgtDescriptor1, String tgtDescriptor2, String tgtDescriptor3,
|
||||
String tgtDescriptor4) {
|
||||
EdgeAssertions ea = new EdgeAssertions(srcDescriptor);
|
||||
ea.tgtDescriptors.add(tgtDescriptor1);
|
||||
ea.tgtDescriptors.add(tgtDescriptor2);
|
||||
ea.tgtDescriptors.add(tgtDescriptor3);
|
||||
ea.tgtDescriptors.add(tgtDescriptor4);
|
||||
return ea;
|
||||
}
|
||||
|
||||
public void check(CallGraph callGraph) {
|
||||
MethodReference srcMethod = descriptorToMethodRef(this.srcDescriptor, callGraph.getClassHierarchy());
|
||||
Set<CGNode> srcNodes = callGraph.getNodes(srcMethod);
|
||||
|
||||
if (srcNodes.size() == 0) {
|
||||
System.err.println(("Unreachable/non-existent method: " + srcMethod));
|
||||
return;
|
||||
}
|
||||
if (srcNodes.size() > 1) {
|
||||
System.err.println("Context-sensitive call graph?");
|
||||
}
|
||||
|
||||
// Assume only one node for src method
|
||||
CGNode srcNode = srcNodes.iterator().next();
|
||||
|
||||
for (String target : this.tgtDescriptors) {
|
||||
MethodReference tgtMethod = descriptorToMethodRef(target, callGraph.getClassHierarchy());
|
||||
// Assume only one node for target method
|
||||
Set<CGNode> tgtNodes = callGraph.getNodes(tgtMethod);
|
||||
if (tgtNodes.size() == 0) {
|
||||
System.err.println(("Unreachable/non-existent method: " + tgtMethod));
|
||||
continue;
|
||||
}
|
||||
CGNode tgtNode = tgtNodes.iterator().next();
|
||||
|
||||
boolean found = false;
|
||||
for (Iterator<? extends CGNode> succIter = callGraph.getSuccNodes(srcNode); succIter.hasNext();) {
|
||||
CGNode succ = succIter.next();
|
||||
|
||||
if (tgtNode == succ) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
System.err.println(("Missing edge: " + srcMethod + " -> " + tgtMethod));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected static class SourceMapAssertion implements IRAssertion {
|
||||
private final String method;
|
||||
|
||||
private final String variableName;
|
||||
|
||||
private final int definingLineNumber;
|
||||
|
||||
protected SourceMapAssertion(String method, String variableName, int definingLineNumber) {
|
||||
this.method = method;
|
||||
this.variableName = variableName;
|
||||
this.definingLineNumber = definingLineNumber;
|
||||
}
|
||||
|
||||
public void check(CallGraph cg) {
|
||||
|
||||
MethodReference mref = descriptorToMethodRef(method, cg.getClassHierarchy());
|
||||
|
||||
for (CGNode cgNode : cg.getNodes(mref)) {
|
||||
Assert.assertTrue("failed for " + this.variableName + " in " + cgNode, this.check(cgNode.getMethod(), cgNode.getIR()));
|
||||
}
|
||||
}
|
||||
|
||||
boolean check(IMethod m, IR ir) {
|
||||
System.err.println(("check for " + variableName + " defined at " + definingLineNumber));
|
||||
SSAInstruction[] insts = ir.getInstructions();
|
||||
for (int i = 0; i < insts.length; i++) {
|
||||
if (insts[i] != null) {
|
||||
int ln = m.getLineNumber(i);
|
||||
if (ln == definingLineNumber) {
|
||||
System.err.println((" found " + insts[i] + " at " + ln));
|
||||
for (int j = 0; j < insts[i].getNumberOfDefs(); j++) {
|
||||
int def = insts[i].getDef(j);
|
||||
System.err.println((" looking at def " + j + ": " + def));
|
||||
String[] names = ir.getLocalNames(i, def);
|
||||
if (names != null) {
|
||||
for (String name : names) {
|
||||
System.err.println((" looking at name " + name));
|
||||
if (name.equals(variableName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected Collection<String> singleTestSrc() {
|
||||
return Collections.singletonList(getTestSrcPath() + File.separator + singleJavaInputForTest());
|
||||
}
|
||||
|
||||
protected Collection<String> singleTestSrc(final String folder) {
|
||||
return Collections.singletonList(getTestSrcPath() + File.separator + folder + File.separator + singleJavaInputForTest());
|
||||
}
|
||||
|
||||
protected Collection<String> singlePkgTestSrc(String pkgName) {
|
||||
return Collections.singletonList(getTestSrcPath() + File.separator + singleJavaPkgInputForTest(pkgName));
|
||||
}
|
||||
|
||||
protected String getTestName() {
|
||||
StackTraceElement stack[] = new Throwable().getStackTrace();
|
||||
for(int i = 0; i <= stack.length; i++) {
|
||||
if (stack[i].getMethodName().startsWith("test")) {
|
||||
return stack[i].getMethodName();
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error("test method not found");
|
||||
}
|
||||
|
||||
protected String[] simpleTestEntryPoint() {
|
||||
return new String[] { "L" + getTestName().substring(4) };
|
||||
}
|
||||
|
||||
protected String[] simplePkgTestEntryPoint(String pkgName) {
|
||||
return new String[] { "L" + pkgName + "/" + getTestName().substring(4) };
|
||||
}
|
||||
|
||||
protected abstract AbstractAnalysisEngine getAnalysisEngine(String[] mainClassDescriptors, Collection<String> sources, List<String> libs);
|
||||
|
||||
public Pair runTest(Collection<String> sources, List<String> libs, String[] mainClassDescriptors, List<? extends IRAssertion> ca,
|
||||
boolean assertReachable) {
|
||||
AbstractAnalysisEngine engine = getAnalysisEngine(mainClassDescriptors, sources, libs);
|
||||
|
||||
CallGraph callGraph;
|
||||
try {
|
||||
callGraph = engine.buildDefaultCallGraph();
|
||||
System.err.println(callGraph.toString());
|
||||
|
||||
// If we've gotten this far, IR has been produced.
|
||||
dumpIR(callGraph, sources, assertReachable);
|
||||
|
||||
// Now check any assertions as to source mapping
|
||||
for (IRAssertion IRAssertion : ca) {
|
||||
IRAssertion.check(callGraph);
|
||||
}
|
||||
|
||||
return Pair.make(callGraph, engine.getPointerAnalysis());
|
||||
} catch (IllegalArgumentException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
} catch (CancelException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected static void dumpIR(CallGraph cg, Collection<String> sources, boolean assertReachable) throws IOException {
|
||||
Set<String> sourcePaths = HashSetFactory.make();
|
||||
for(String src : sources) {
|
||||
sourcePaths.add(src.substring(src.lastIndexOf(File.separator)+1));
|
||||
}
|
||||
|
||||
Set<IMethod> unreachable = HashSetFactory.make();
|
||||
IClassHierarchy cha = cg.getClassHierarchy();
|
||||
IClassLoader sourceLoader = cha.getLoader(JavaSourceAnalysisScope.SOURCE);
|
||||
for (Iterator iter = sourceLoader.iterateAllClasses(); iter.hasNext();) {
|
||||
IClass clazz = (IClass) iter.next();
|
||||
|
||||
System.err.println(clazz);
|
||||
if (clazz.isInterface())
|
||||
continue;
|
||||
|
||||
for (IMethod m : clazz.getDeclaredMethods()) {
|
||||
if (m.isAbstract()) {
|
||||
System.err.println(m);
|
||||
} else {
|
||||
Iterator nodeIter = cg.getNodes(m.getReference()).iterator();
|
||||
if (!nodeIter.hasNext()) {
|
||||
if (m instanceof AstMethod) {
|
||||
String fn = ((AstClass)m.getDeclaringClass()).getSourcePosition().getURL().getFile();
|
||||
if (sourcePaths.contains(fn.substring(fn.lastIndexOf(File.separator)+1))) {
|
||||
System.err.println(("Method " + m.getReference() + " not reachable?"));
|
||||
unreachable.add(m);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
CGNode node = (CGNode) nodeIter.next();
|
||||
System.err.println(node.getIR());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (assertReachable) {
|
||||
Assert.assertTrue("unreachable methods: " + unreachable.toString(), unreachable.isEmpty());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param srcMethodDescriptor a full method descriptor of the form ldr#type#methName#methSig example:
|
||||
* Source#Simple1#main#([Ljava/lang/String;)V
|
||||
* @param cha
|
||||
* @return
|
||||
*/
|
||||
public static MethodReference descriptorToMethodRef(String srcMethodDescriptor, IClassHierarchy cha) {
|
||||
String[] ldrTypeMeth = srcMethodDescriptor.split("\\#");
|
||||
|
||||
String loaderName = ldrTypeMeth[0];
|
||||
String typeStr = ldrTypeMeth[1];
|
||||
String methName = ldrTypeMeth[2];
|
||||
String methSig = ldrTypeMeth[3];
|
||||
|
||||
TypeReference typeRef = findOrCreateTypeReference(loaderName, typeStr, cha);
|
||||
|
||||
Language l = cha.getLoader(typeRef.getClassLoader()).getLanguage();
|
||||
return MethodReference.findOrCreate(l, typeRef, methName, methSig);
|
||||
}
|
||||
|
||||
static TypeReference findOrCreateTypeReference(String loaderName, String typeStr, IClassHierarchy cha) {
|
||||
ClassLoaderReference clr = findLoader(loaderName, cha);
|
||||
TypeName typeName = TypeName.string2TypeName("L" + typeStr);
|
||||
TypeReference typeRef = TypeReference.findOrCreate(clr, typeName);
|
||||
return typeRef;
|
||||
}
|
||||
|
||||
private static ClassLoaderReference findLoader(String loaderName, IClassHierarchy cha) {
|
||||
Atom loaderAtom = Atom.findOrCreateUnicodeAtom(loaderName);
|
||||
IClassLoader[] loaders = cha.getLoaders();
|
||||
for (IClassLoader loader : loaders) {
|
||||
if (loader.getName() == loaderAtom) {
|
||||
return loader.getReference();
|
||||
}
|
||||
}
|
||||
Assertions.UNREACHABLE();
|
||||
return null;
|
||||
}
|
||||
|
||||
protected void populateScope(JavaSourceAnalysisEngine engine, Collection<String> sources, List<String> libs) {
|
||||
boolean foundLib = false;
|
||||
for (String lib : libs) {
|
||||
File libFile = new File(lib);
|
||||
if (libFile.exists()) {
|
||||
foundLib = true;
|
||||
try {
|
||||
engine.addSystemModule(new JarFileModule(new JarFile(libFile)));
|
||||
} catch (IOException e) {
|
||||
Assert.fail(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
assert foundLib : "couldn't find library file from " + libs;
|
||||
|
||||
for (String srcFilePath : sources) {
|
||||
String srcFileName = srcFilePath.substring(srcFilePath.lastIndexOf(File.separator) + 1);
|
||||
File f = new File(srcFilePath);
|
||||
Assert.assertTrue("couldn't find " + srcFilePath, f.exists());
|
||||
if (f.isDirectory()) {
|
||||
engine.addSourceModule(new SourceDirectoryTreeModule(f));
|
||||
} else {
|
||||
engine.addSourceModule(new SourceFileModule(f, srcFileName));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void setTestSrcPath(String testSrcPath) {
|
||||
this.testSrcPath = testSrcPath;
|
||||
}
|
||||
|
||||
protected String getTestSrcPath() {
|
||||
return testSrcPath;
|
||||
}
|
||||
|
||||
protected String singleJavaInputForTest() {
|
||||
return getTestName().substring(4) + ".java";
|
||||
}
|
||||
|
||||
protected String singleInputForTest() {
|
||||
return getTestName().substring(4);
|
||||
}
|
||||
|
||||
protected String singleJavaPkgInputForTest(String pkgName) {
|
||||
return pkgName + File.separator + getTestName().substring(4) + ".java";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,165 +1,165 @@
|
||||
/******************************************************************************
|
||||
* 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.cast.java.client;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Set;
|
||||
|
||||
import com.ibm.wala.cast.ir.ssa.AstIRFactory;
|
||||
import com.ibm.wala.cast.java.client.impl.ZeroCFABuilderFactory;
|
||||
import com.ibm.wala.cast.java.ipa.callgraph.JavaSourceAnalysisScope;
|
||||
import com.ibm.wala.classLoader.ClassLoaderFactory;
|
||||
import com.ibm.wala.classLoader.Module;
|
||||
import com.ibm.wala.client.AbstractAnalysisEngine;
|
||||
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.CallGraphBuilder;
|
||||
import com.ibm.wala.ipa.callgraph.Entrypoint;
|
||||
import com.ibm.wala.ipa.callgraph.impl.SetOfClasses;
|
||||
import com.ibm.wala.ipa.callgraph.impl.Util;
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchy;
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchyException;
|
||||
import com.ibm.wala.ipa.cha.IClassHierarchy;
|
||||
import com.ibm.wala.ssa.SSAOptions;
|
||||
import com.ibm.wala.ssa.SymbolTable;
|
||||
import com.ibm.wala.types.ClassLoaderReference;
|
||||
import com.ibm.wala.util.collections.HashSetFactory;
|
||||
import com.ibm.wala.util.config.FileOfClasses;
|
||||
|
||||
/**
|
||||
*/
|
||||
public abstract class JavaSourceAnalysisEngine extends AbstractAnalysisEngine {
|
||||
|
||||
/**
|
||||
* Modules which are user-space code
|
||||
*/
|
||||
private final Set<Module> userEntries = HashSetFactory.make();
|
||||
|
||||
/**
|
||||
* Modules which are source code
|
||||
*/
|
||||
private final Set<Module> sourceEntries = HashSetFactory.make();
|
||||
|
||||
/**
|
||||
* Modules which are system or library code TODO: what about extension loader?
|
||||
*/
|
||||
private final Set<Module> systemEntries = HashSetFactory.make();
|
||||
|
||||
public JavaSourceAnalysisEngine() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the given source module to the source loader's module list. Clients
|
||||
* should/may call this method if they don't supply an IJavaProject to the
|
||||
* constructor.
|
||||
*/
|
||||
public void addSourceModule(Module M) {
|
||||
sourceEntries.add(M);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the given compiled module to the application loader's module list.
|
||||
* Clients should/may call this method if they don't supply an IJavaProject to
|
||||
* the constructor.
|
||||
*/
|
||||
public void addCompiledModule(Module M) {
|
||||
userEntries.add(M);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the given module to the primordial loader's module list. Clients
|
||||
* should/may call this method if they don't supply an IJavaProject to the
|
||||
* constructor.
|
||||
*/
|
||||
public void addSystemModule(Module M) {
|
||||
systemEntries.add(M);
|
||||
}
|
||||
|
||||
protected void addApplicationModulesToScope() {
|
||||
ClassLoaderReference app = scope.getApplicationLoader();
|
||||
for (Module M : userEntries) {
|
||||
scope.addToScope(app, M);
|
||||
}
|
||||
|
||||
ClassLoaderReference src = ((JavaSourceAnalysisScope) scope).getSourceLoader();
|
||||
|
||||
for (Module M : sourceEntries) {
|
||||
scope.addToScope(src, M);
|
||||
}
|
||||
}
|
||||
|
||||
public void buildAnalysisScope() throws IOException {
|
||||
scope = makeSourceAnalysisScope();
|
||||
|
||||
if (getExclusionsFile() != null) {
|
||||
scope.setExclusions(FileOfClasses.createFileOfClasses(new File(getExclusionsFile())));
|
||||
}
|
||||
|
||||
for (Module M : this.systemEntries) {
|
||||
scope.addToScope(scope.getPrimordialLoader(), M);
|
||||
}
|
||||
|
||||
// add user stuff
|
||||
addApplicationModulesToScope();
|
||||
}
|
||||
|
||||
protected AnalysisScope makeSourceAnalysisScope() {
|
||||
return new JavaSourceAnalysisScope();
|
||||
}
|
||||
|
||||
protected abstract ClassLoaderFactory getClassLoaderFactory(SetOfClasses exclusions);
|
||||
|
||||
public IClassHierarchy buildClassHierarchy() {
|
||||
IClassHierarchy cha = null;
|
||||
ClassLoaderFactory factory = getClassLoaderFactory(scope.getExclusions());
|
||||
|
||||
try {
|
||||
cha = ClassHierarchy.make(getScope(), factory);
|
||||
} catch (ClassHierarchyException e) {
|
||||
System.err.println("Class Hierarchy construction failed");
|
||||
System.err.println(e.toString());
|
||||
e.printStackTrace();
|
||||
}
|
||||
return cha;
|
||||
}
|
||||
|
||||
protected Iterable<Entrypoint> makeDefaultEntrypoints(AnalysisScope scope, IClassHierarchy cha) {
|
||||
return Util.makeMainEntrypoints(JavaSourceAnalysisScope.SOURCE, cha);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnalysisCache makeDefaultCache() {
|
||||
return new AnalysisCache(AstIRFactory.makeDefaultFactory());
|
||||
}
|
||||
|
||||
public AnalysisOptions getDefaultOptions(Iterable<Entrypoint> entrypoints) {
|
||||
AnalysisOptions options = new AnalysisOptions(getScope(), entrypoints);
|
||||
|
||||
SSAOptions ssaOptions = new SSAOptions();
|
||||
ssaOptions.setDefaultValues(new SSAOptions.DefaultValues() {
|
||||
public int getDefaultValue(SymbolTable symtab, int valueNumber) {
|
||||
return symtab.getDefaultValue(valueNumber);
|
||||
}
|
||||
});
|
||||
|
||||
options.setSSAOptions(ssaOptions);
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CallGraphBuilder getCallGraphBuilder(IClassHierarchy cha, AnalysisOptions options, AnalysisCache cache) {
|
||||
return new ZeroCFABuilderFactory().make(options, cache, cha, scope, false);
|
||||
}
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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.cast.java.client;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Set;
|
||||
|
||||
import com.ibm.wala.cast.ir.ssa.AstIRFactory;
|
||||
import com.ibm.wala.cast.java.client.impl.ZeroCFABuilderFactory;
|
||||
import com.ibm.wala.cast.java.ipa.callgraph.JavaSourceAnalysisScope;
|
||||
import com.ibm.wala.classLoader.ClassLoaderFactory;
|
||||
import com.ibm.wala.classLoader.Module;
|
||||
import com.ibm.wala.client.AbstractAnalysisEngine;
|
||||
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.CallGraphBuilder;
|
||||
import com.ibm.wala.ipa.callgraph.Entrypoint;
|
||||
import com.ibm.wala.ipa.callgraph.impl.SetOfClasses;
|
||||
import com.ibm.wala.ipa.callgraph.impl.Util;
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchy;
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchyException;
|
||||
import com.ibm.wala.ipa.cha.IClassHierarchy;
|
||||
import com.ibm.wala.ssa.SSAOptions;
|
||||
import com.ibm.wala.ssa.SymbolTable;
|
||||
import com.ibm.wala.types.ClassLoaderReference;
|
||||
import com.ibm.wala.util.collections.HashSetFactory;
|
||||
import com.ibm.wala.util.config.FileOfClasses;
|
||||
|
||||
/**
|
||||
*/
|
||||
public abstract class JavaSourceAnalysisEngine extends AbstractAnalysisEngine {
|
||||
|
||||
/**
|
||||
* Modules which are user-space code
|
||||
*/
|
||||
private final Set<Module> userEntries = HashSetFactory.make();
|
||||
|
||||
/**
|
||||
* Modules which are source code
|
||||
*/
|
||||
private final Set<Module> sourceEntries = HashSetFactory.make();
|
||||
|
||||
/**
|
||||
* Modules which are system or library code TODO: what about extension loader?
|
||||
*/
|
||||
private final Set<Module> systemEntries = HashSetFactory.make();
|
||||
|
||||
public JavaSourceAnalysisEngine() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the given source module to the source loader's module list. Clients
|
||||
* should/may call this method if they don't supply an IJavaProject to the
|
||||
* constructor.
|
||||
*/
|
||||
public void addSourceModule(Module M) {
|
||||
sourceEntries.add(M);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the given compiled module to the application loader's module list.
|
||||
* Clients should/may call this method if they don't supply an IJavaProject to
|
||||
* the constructor.
|
||||
*/
|
||||
public void addCompiledModule(Module M) {
|
||||
userEntries.add(M);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the given module to the primordial loader's module list. Clients
|
||||
* should/may call this method if they don't supply an IJavaProject to the
|
||||
* constructor.
|
||||
*/
|
||||
public void addSystemModule(Module M) {
|
||||
systemEntries.add(M);
|
||||
}
|
||||
|
||||
protected void addApplicationModulesToScope() {
|
||||
ClassLoaderReference app = scope.getApplicationLoader();
|
||||
for (Module M : userEntries) {
|
||||
scope.addToScope(app, M);
|
||||
}
|
||||
|
||||
ClassLoaderReference src = ((JavaSourceAnalysisScope) scope).getSourceLoader();
|
||||
|
||||
for (Module M : sourceEntries) {
|
||||
scope.addToScope(src, M);
|
||||
}
|
||||
}
|
||||
|
||||
public void buildAnalysisScope() throws IOException {
|
||||
scope = makeSourceAnalysisScope();
|
||||
|
||||
if (getExclusionsFile() != null) {
|
||||
scope.setExclusions(FileOfClasses.createFileOfClasses(new File(getExclusionsFile())));
|
||||
}
|
||||
|
||||
for (Module M : this.systemEntries) {
|
||||
scope.addToScope(scope.getPrimordialLoader(), M);
|
||||
}
|
||||
|
||||
// add user stuff
|
||||
addApplicationModulesToScope();
|
||||
}
|
||||
|
||||
protected AnalysisScope makeSourceAnalysisScope() {
|
||||
return new JavaSourceAnalysisScope();
|
||||
}
|
||||
|
||||
protected abstract ClassLoaderFactory getClassLoaderFactory(SetOfClasses exclusions);
|
||||
|
||||
public IClassHierarchy buildClassHierarchy() {
|
||||
IClassHierarchy cha = null;
|
||||
ClassLoaderFactory factory = getClassLoaderFactory(scope.getExclusions());
|
||||
|
||||
try {
|
||||
cha = ClassHierarchy.make(getScope(), factory);
|
||||
} catch (ClassHierarchyException e) {
|
||||
System.err.println("Class Hierarchy construction failed");
|
||||
System.err.println(e.toString());
|
||||
e.printStackTrace();
|
||||
}
|
||||
return cha;
|
||||
}
|
||||
|
||||
protected Iterable<Entrypoint> makeDefaultEntrypoints(AnalysisScope scope, IClassHierarchy cha) {
|
||||
return Util.makeMainEntrypoints(JavaSourceAnalysisScope.SOURCE, cha);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnalysisCache makeDefaultCache() {
|
||||
return new AnalysisCache(AstIRFactory.makeDefaultFactory());
|
||||
}
|
||||
|
||||
public AnalysisOptions getDefaultOptions(Iterable<Entrypoint> entrypoints) {
|
||||
AnalysisOptions options = new AnalysisOptions(getScope(), entrypoints);
|
||||
|
||||
SSAOptions ssaOptions = new SSAOptions();
|
||||
ssaOptions.setDefaultValues(new SSAOptions.DefaultValues() {
|
||||
public int getDefaultValue(SymbolTable symtab, int valueNumber) {
|
||||
return symtab.getDefaultValue(valueNumber);
|
||||
}
|
||||
});
|
||||
|
||||
options.setSSAOptions(ssaOptions);
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CallGraphBuilder getCallGraphBuilder(IClassHierarchy cha, AnalysisOptions options, AnalysisCache cache) {
|
||||
return new ZeroCFABuilderFactory().make(options, cache, cha, scope, false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,75 +1,75 @@
|
||||
/*******************************************************************************
|
||||
* 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.cast.java.ipa.callgraph;
|
||||
|
||||
import com.ibm.wala.ipa.callgraph.AnalysisCache;
|
||||
import com.ibm.wala.ipa.callgraph.AnalysisOptions;
|
||||
import com.ibm.wala.ipa.callgraph.ContextSelector;
|
||||
import com.ibm.wala.ipa.callgraph.impl.DefaultContextSelector;
|
||||
import com.ibm.wala.ipa.callgraph.impl.DelegatingContextSelector;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.SSAContextInterpreter;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.cfa.ContainerContextSelector;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.cfa.ZeroXInstanceKeys;
|
||||
import com.ibm.wala.ipa.cha.IClassHierarchy;
|
||||
|
||||
/**
|
||||
*
|
||||
* 0-1-CFA Call graph builder which analyzes calls to "container methods" in a context which is defined by the receiver
|
||||
* instance.
|
||||
*
|
||||
* @author sfink
|
||||
*/
|
||||
public class AstJavaZeroOneContainerCFABuilder extends AstJavaCFABuilder {
|
||||
|
||||
/**
|
||||
* @param cha governing class hierarchy
|
||||
* @param warnings object to track analysis warnings
|
||||
* @param options call graph construction options
|
||||
* @param appContextSelector application-specific logic to choose contexts
|
||||
* @param appContextInterpreter application-specific logic to interpret a method in context
|
||||
* @param reflect reflection specification
|
||||
*/
|
||||
public AstJavaZeroOneContainerCFABuilder(IClassHierarchy cha, AnalysisOptions options, AnalysisCache cache,
|
||||
ContextSelector appContextSelector, SSAContextInterpreter appContextInterpreter) {
|
||||
super(cha, options, cache);
|
||||
|
||||
ContextSelector def = new DefaultContextSelector(options, cha);
|
||||
ContextSelector contextSelector = appContextSelector == null ? def : new DelegatingContextSelector(appContextSelector, def);
|
||||
|
||||
SSAContextInterpreter contextInterpreter = makeDefaultContextInterpreters(appContextInterpreter, options, cha);
|
||||
setContextInterpreter(contextInterpreter);
|
||||
|
||||
ZeroXInstanceKeys zik = makeInstanceKeys(cha, options, contextInterpreter);
|
||||
setInstanceKeys(new JavaScopeMappingInstanceKeys(cha, this, zik));
|
||||
|
||||
ContextSelector CCS = makeContainerContextSelector(cha, zik);
|
||||
DelegatingContextSelector DCS = new DelegatingContextSelector(CCS, contextSelector);
|
||||
setContextSelector(DCS);
|
||||
}
|
||||
|
||||
protected ZeroXInstanceKeys makeInstanceKeys(IClassHierarchy cha, AnalysisOptions options,
|
||||
SSAContextInterpreter contextInterpreter) {
|
||||
ZeroXInstanceKeys zik = new ZeroXInstanceKeys(options, cha, contextInterpreter, ZeroXInstanceKeys.ALLOCATIONS
|
||||
| ZeroXInstanceKeys.SMUSH_PRIMITIVE_HOLDERS | ZeroXInstanceKeys.SMUSH_STRINGS | ZeroXInstanceKeys.SMUSH_MANY
|
||||
| ZeroXInstanceKeys.SMUSH_THROWABLES);
|
||||
return zik;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param cha
|
||||
* @param keys
|
||||
* @return an object which creates contexts for call graph nodes based on the container disambiguation policy
|
||||
*/
|
||||
protected ContextSelector makeContainerContextSelector(IClassHierarchy cha, ZeroXInstanceKeys keys) {
|
||||
return new ContainerContextSelector(cha, keys);
|
||||
}
|
||||
|
||||
}
|
||||
/*******************************************************************************
|
||||
* 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.cast.java.ipa.callgraph;
|
||||
|
||||
import com.ibm.wala.ipa.callgraph.AnalysisCache;
|
||||
import com.ibm.wala.ipa.callgraph.AnalysisOptions;
|
||||
import com.ibm.wala.ipa.callgraph.ContextSelector;
|
||||
import com.ibm.wala.ipa.callgraph.impl.DefaultContextSelector;
|
||||
import com.ibm.wala.ipa.callgraph.impl.DelegatingContextSelector;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.SSAContextInterpreter;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.cfa.ContainerContextSelector;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.cfa.ZeroXInstanceKeys;
|
||||
import com.ibm.wala.ipa.cha.IClassHierarchy;
|
||||
|
||||
/**
|
||||
*
|
||||
* 0-1-CFA Call graph builder which analyzes calls to "container methods" in a context which is defined by the receiver
|
||||
* instance.
|
||||
*
|
||||
* @author sfink
|
||||
*/
|
||||
public class AstJavaZeroOneContainerCFABuilder extends AstJavaCFABuilder {
|
||||
|
||||
/**
|
||||
* @param cha governing class hierarchy
|
||||
* @param warnings object to track analysis warnings
|
||||
* @param options call graph construction options
|
||||
* @param appContextSelector application-specific logic to choose contexts
|
||||
* @param appContextInterpreter application-specific logic to interpret a method in context
|
||||
* @param reflect reflection specification
|
||||
*/
|
||||
public AstJavaZeroOneContainerCFABuilder(IClassHierarchy cha, AnalysisOptions options, AnalysisCache cache,
|
||||
ContextSelector appContextSelector, SSAContextInterpreter appContextInterpreter) {
|
||||
super(cha, options, cache);
|
||||
|
||||
ContextSelector def = new DefaultContextSelector(options, cha);
|
||||
ContextSelector contextSelector = appContextSelector == null ? def : new DelegatingContextSelector(appContextSelector, def);
|
||||
|
||||
SSAContextInterpreter contextInterpreter = makeDefaultContextInterpreters(appContextInterpreter, options, cha);
|
||||
setContextInterpreter(contextInterpreter);
|
||||
|
||||
ZeroXInstanceKeys zik = makeInstanceKeys(cha, options, contextInterpreter);
|
||||
setInstanceKeys(new JavaScopeMappingInstanceKeys(cha, this, zik));
|
||||
|
||||
ContextSelector CCS = makeContainerContextSelector(cha, zik);
|
||||
DelegatingContextSelector DCS = new DelegatingContextSelector(CCS, contextSelector);
|
||||
setContextSelector(DCS);
|
||||
}
|
||||
|
||||
protected ZeroXInstanceKeys makeInstanceKeys(IClassHierarchy cha, AnalysisOptions options,
|
||||
SSAContextInterpreter contextInterpreter) {
|
||||
ZeroXInstanceKeys zik = new ZeroXInstanceKeys(options, cha, contextInterpreter, ZeroXInstanceKeys.ALLOCATIONS
|
||||
| ZeroXInstanceKeys.SMUSH_PRIMITIVE_HOLDERS | ZeroXInstanceKeys.SMUSH_STRINGS | ZeroXInstanceKeys.SMUSH_MANY
|
||||
| ZeroXInstanceKeys.SMUSH_THROWABLES);
|
||||
return zik;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param cha
|
||||
* @param keys
|
||||
* @return an object which creates contexts for call graph nodes based on the container disambiguation policy
|
||||
*/
|
||||
protected ContextSelector makeContainerContextSelector(IClassHierarchy cha, ZeroXInstanceKeys keys) {
|
||||
return new ContainerContextSelector(cha, keys);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,115 +1,115 @@
|
||||
package com.ibm.wala.cast.java.ipa.slicer;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import com.ibm.wala.cast.ir.ssa.AstAssertInstruction;
|
||||
import com.ibm.wala.cast.java.ipa.modref.AstJavaModRef;
|
||||
import com.ibm.wala.ipa.callgraph.CGNode;
|
||||
import com.ibm.wala.ipa.callgraph.CallGraph;
|
||||
import com.ibm.wala.ipa.callgraph.impl.PartialCallGraph;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis;
|
||||
import com.ibm.wala.ipa.slicer.NormalStatement;
|
||||
import com.ibm.wala.ipa.slicer.SDG;
|
||||
import com.ibm.wala.ipa.slicer.Slicer;
|
||||
import com.ibm.wala.ipa.slicer.Statement;
|
||||
import com.ibm.wala.ssa.IR;
|
||||
import com.ibm.wala.ssa.SSAArrayLoadInstruction;
|
||||
import com.ibm.wala.ssa.SSAArrayStoreInstruction;
|
||||
import com.ibm.wala.ssa.SSAGetInstruction;
|
||||
import com.ibm.wala.ssa.SSAInstruction;
|
||||
import com.ibm.wala.ssa.SSAMonitorInstruction;
|
||||
import com.ibm.wala.ssa.SSAPutInstruction;
|
||||
import com.ibm.wala.util.CancelException;
|
||||
import com.ibm.wala.util.collections.Filter;
|
||||
import com.ibm.wala.util.collections.Pair;
|
||||
import com.ibm.wala.util.graph.traverse.DFS;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public class AstJavaSlicer extends Slicer {
|
||||
|
||||
/*
|
||||
* Use the passed-in SDG
|
||||
*/
|
||||
public static Collection<Statement> computeBackwardSlice(SDG sdg, Collection<Statement> ss) throws IllegalArgumentException,
|
||||
CancelException {
|
||||
return computeSlice(sdg, ss, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ss a collection of statements of interest
|
||||
* @throws CancelException
|
||||
*/
|
||||
public static Collection<Statement> computeSlice(SDG sdg, Collection<Statement> ss, boolean backward) throws CancelException {
|
||||
return new AstJavaSlicer().slice(sdg, ss, backward);
|
||||
}
|
||||
|
||||
public static Set<Statement> gatherStatements(CallGraph CG, Collection<CGNode> partialRoots, Filter<SSAInstruction> filter) {
|
||||
Set<Statement> result = new HashSet<Statement>();
|
||||
for (Iterator<CGNode> ns = DFS.getReachableNodes(CG, partialRoots).iterator(); ns.hasNext();) {
|
||||
CGNode n = ns.next();
|
||||
IR nir = n.getIR();
|
||||
if (nir != null) {
|
||||
SSAInstruction insts[] = nir.getInstructions();
|
||||
for (int i = 0; i < insts.length; i++) {
|
||||
if (filter.accepts(insts[i])) {
|
||||
result.add(new NormalStatement(n, i));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static Set<Statement> gatherAssertions(CallGraph CG, Collection<CGNode> partialRoots) {
|
||||
return gatherStatements(CG, partialRoots, new Filter<SSAInstruction>() {
|
||||
public boolean accepts(SSAInstruction o) {
|
||||
return o instanceof AstAssertInstruction;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static Set<Statement> gatherMonitors(CallGraph CG, Collection<CGNode> partialRoots) {
|
||||
return gatherStatements(CG, partialRoots, new Filter<SSAInstruction>() {
|
||||
public boolean accepts(SSAInstruction o) {
|
||||
return o instanceof SSAMonitorInstruction;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static Set<Statement> gatherWrites(CallGraph CG, Collection<CGNode> partialRoots) {
|
||||
return gatherStatements(CG, partialRoots, new Filter<SSAInstruction>() {
|
||||
public boolean accepts(SSAInstruction o) {
|
||||
return (o instanceof SSAPutInstruction) || (o instanceof SSAArrayStoreInstruction);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static Set<Statement> gatherReads(CallGraph CG, Collection<CGNode> partialRoots) {
|
||||
return gatherStatements(CG, partialRoots, new Filter<SSAInstruction>() {
|
||||
public boolean accepts(SSAInstruction o) {
|
||||
return (o instanceof SSAGetInstruction) || (o instanceof SSAArrayLoadInstruction);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static Pair<Collection<Statement>, SDG> computeAssertionSlice(CallGraph CG, PointerAnalysis pa,
|
||||
Collection<CGNode> partialRoots, boolean multiThreadedCode) throws IllegalArgumentException, CancelException {
|
||||
CallGraph pcg = PartialCallGraph.make(CG, new LinkedHashSet<CGNode>(partialRoots));
|
||||
SDG sdg = new SDG(pcg, pa, new AstJavaModRef(), DataDependenceOptions.FULL, ControlDependenceOptions.FULL);
|
||||
System.err.println(("SDG:\n" + sdg));
|
||||
Set<Statement> stmts = gatherAssertions(CG, partialRoots);
|
||||
if (multiThreadedCode) {
|
||||
// Grab anything that has "side effects" under JMM
|
||||
stmts.addAll(gatherReads(CG, partialRoots));
|
||||
stmts.addAll(gatherWrites(CG, partialRoots));
|
||||
stmts.addAll(gatherMonitors(CG, partialRoots));
|
||||
}
|
||||
return Pair.make(AstJavaSlicer.computeBackwardSlice(sdg, stmts), sdg);
|
||||
}
|
||||
|
||||
}
|
||||
package com.ibm.wala.cast.java.ipa.slicer;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import com.ibm.wala.cast.ir.ssa.AstAssertInstruction;
|
||||
import com.ibm.wala.cast.java.ipa.modref.AstJavaModRef;
|
||||
import com.ibm.wala.ipa.callgraph.CGNode;
|
||||
import com.ibm.wala.ipa.callgraph.CallGraph;
|
||||
import com.ibm.wala.ipa.callgraph.impl.PartialCallGraph;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis;
|
||||
import com.ibm.wala.ipa.slicer.NormalStatement;
|
||||
import com.ibm.wala.ipa.slicer.SDG;
|
||||
import com.ibm.wala.ipa.slicer.Slicer;
|
||||
import com.ibm.wala.ipa.slicer.Statement;
|
||||
import com.ibm.wala.ssa.IR;
|
||||
import com.ibm.wala.ssa.SSAArrayLoadInstruction;
|
||||
import com.ibm.wala.ssa.SSAArrayStoreInstruction;
|
||||
import com.ibm.wala.ssa.SSAGetInstruction;
|
||||
import com.ibm.wala.ssa.SSAInstruction;
|
||||
import com.ibm.wala.ssa.SSAMonitorInstruction;
|
||||
import com.ibm.wala.ssa.SSAPutInstruction;
|
||||
import com.ibm.wala.util.CancelException;
|
||||
import com.ibm.wala.util.collections.Filter;
|
||||
import com.ibm.wala.util.collections.Pair;
|
||||
import com.ibm.wala.util.graph.traverse.DFS;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public class AstJavaSlicer extends Slicer {
|
||||
|
||||
/*
|
||||
* Use the passed-in SDG
|
||||
*/
|
||||
public static Collection<Statement> computeBackwardSlice(SDG sdg, Collection<Statement> ss) throws IllegalArgumentException,
|
||||
CancelException {
|
||||
return computeSlice(sdg, ss, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ss a collection of statements of interest
|
||||
* @throws CancelException
|
||||
*/
|
||||
public static Collection<Statement> computeSlice(SDG sdg, Collection<Statement> ss, boolean backward) throws CancelException {
|
||||
return new AstJavaSlicer().slice(sdg, ss, backward);
|
||||
}
|
||||
|
||||
public static Set<Statement> gatherStatements(CallGraph CG, Collection<CGNode> partialRoots, Filter<SSAInstruction> filter) {
|
||||
Set<Statement> result = new HashSet<Statement>();
|
||||
for (Iterator<CGNode> ns = DFS.getReachableNodes(CG, partialRoots).iterator(); ns.hasNext();) {
|
||||
CGNode n = ns.next();
|
||||
IR nir = n.getIR();
|
||||
if (nir != null) {
|
||||
SSAInstruction insts[] = nir.getInstructions();
|
||||
for (int i = 0; i < insts.length; i++) {
|
||||
if (filter.accepts(insts[i])) {
|
||||
result.add(new NormalStatement(n, i));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static Set<Statement> gatherAssertions(CallGraph CG, Collection<CGNode> partialRoots) {
|
||||
return gatherStatements(CG, partialRoots, new Filter<SSAInstruction>() {
|
||||
public boolean accepts(SSAInstruction o) {
|
||||
return o instanceof AstAssertInstruction;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static Set<Statement> gatherMonitors(CallGraph CG, Collection<CGNode> partialRoots) {
|
||||
return gatherStatements(CG, partialRoots, new Filter<SSAInstruction>() {
|
||||
public boolean accepts(SSAInstruction o) {
|
||||
return o instanceof SSAMonitorInstruction;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static Set<Statement> gatherWrites(CallGraph CG, Collection<CGNode> partialRoots) {
|
||||
return gatherStatements(CG, partialRoots, new Filter<SSAInstruction>() {
|
||||
public boolean accepts(SSAInstruction o) {
|
||||
return (o instanceof SSAPutInstruction) || (o instanceof SSAArrayStoreInstruction);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static Set<Statement> gatherReads(CallGraph CG, Collection<CGNode> partialRoots) {
|
||||
return gatherStatements(CG, partialRoots, new Filter<SSAInstruction>() {
|
||||
public boolean accepts(SSAInstruction o) {
|
||||
return (o instanceof SSAGetInstruction) || (o instanceof SSAArrayLoadInstruction);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static Pair<Collection<Statement>, SDG> computeAssertionSlice(CallGraph CG, PointerAnalysis pa,
|
||||
Collection<CGNode> partialRoots, boolean multiThreadedCode) throws IllegalArgumentException, CancelException {
|
||||
CallGraph pcg = PartialCallGraph.make(CG, new LinkedHashSet<CGNode>(partialRoots));
|
||||
SDG sdg = new SDG(pcg, pa, new AstJavaModRef(), DataDependenceOptions.FULL, ControlDependenceOptions.FULL);
|
||||
System.err.println(("SDG:\n" + sdg));
|
||||
Set<Statement> stmts = gatherAssertions(CG, partialRoots);
|
||||
if (multiThreadedCode) {
|
||||
// Grab anything that has "side effects" under JMM
|
||||
stmts.addAll(gatherReads(CG, partialRoots));
|
||||
stmts.addAll(gatherWrites(CG, partialRoots));
|
||||
stmts.addAll(gatherMonitors(CG, partialRoots));
|
||||
}
|
||||
return Pair.make(AstJavaSlicer.computeBackwardSlice(sdg, stmts), sdg);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,74 +1,74 @@
|
||||
package com.ibm.wala.cast.java.ssa;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
import com.ibm.wala.ssa.SSAInstruction;
|
||||
import com.ibm.wala.ssa.SSAInstructionFactory;
|
||||
import com.ibm.wala.ssa.SymbolTable;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
|
||||
/**
|
||||
* The CAst source language front end for Java has explicit support for lexically-enclosing objects, rather than compiling them
|
||||
* away into extra fields and access-control thwarting accessor methods as is done in bytecode. This instruction represents a read
|
||||
* of the object of the given type that lexically encloses its use value.
|
||||
*
|
||||
* @author Julian Dolby (dolby@us.ibm.com)
|
||||
*/
|
||||
public class EnclosingObjectReference extends SSAInstruction {
|
||||
private final TypeReference type;
|
||||
|
||||
private final int lval;
|
||||
|
||||
public EnclosingObjectReference(int lval, TypeReference type) {
|
||||
this.lval = lval;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public boolean hasDef() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public int getDef() {
|
||||
return lval;
|
||||
}
|
||||
|
||||
public int getDef(int i) {
|
||||
assert i == 0;
|
||||
|
||||
return lval;
|
||||
}
|
||||
|
||||
public int getNumberOfDefs() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
public TypeReference getEnclosingType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public SSAInstruction copyForSSA(SSAInstructionFactory insts, int[] defs, int[] uses) {
|
||||
return ((AstJavaInstructionFactory) insts).EnclosingObjectReference(defs == null ? lval : defs[0], type);
|
||||
}
|
||||
|
||||
public String toString(SymbolTable symbolTable) {
|
||||
return getValueString(symbolTable, lval) + " = enclosing " + type.getName();
|
||||
}
|
||||
|
||||
public void visit(IVisitor v) {
|
||||
((AstJavaInstructionVisitor) v).visitEnclosingObjectReference(this);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return lval * type.hashCode();
|
||||
}
|
||||
|
||||
public Collection<TypeReference> getExceptionTypes() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
public boolean isFallThrough() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
package com.ibm.wala.cast.java.ssa;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
import com.ibm.wala.ssa.SSAInstruction;
|
||||
import com.ibm.wala.ssa.SSAInstructionFactory;
|
||||
import com.ibm.wala.ssa.SymbolTable;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
|
||||
/**
|
||||
* The CAst source language front end for Java has explicit support for lexically-enclosing objects, rather than compiling them
|
||||
* away into extra fields and access-control thwarting accessor methods as is done in bytecode. This instruction represents a read
|
||||
* of the object of the given type that lexically encloses its use value.
|
||||
*
|
||||
* @author Julian Dolby (dolby@us.ibm.com)
|
||||
*/
|
||||
public class EnclosingObjectReference extends SSAInstruction {
|
||||
private final TypeReference type;
|
||||
|
||||
private final int lval;
|
||||
|
||||
public EnclosingObjectReference(int lval, TypeReference type) {
|
||||
this.lval = lval;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public boolean hasDef() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public int getDef() {
|
||||
return lval;
|
||||
}
|
||||
|
||||
public int getDef(int i) {
|
||||
assert i == 0;
|
||||
|
||||
return lval;
|
||||
}
|
||||
|
||||
public int getNumberOfDefs() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
public TypeReference getEnclosingType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public SSAInstruction copyForSSA(SSAInstructionFactory insts, int[] defs, int[] uses) {
|
||||
return ((AstJavaInstructionFactory) insts).EnclosingObjectReference(defs == null ? lval : defs[0], type);
|
||||
}
|
||||
|
||||
public String toString(SymbolTable symbolTable) {
|
||||
return getValueString(symbolTable, lval) + " = enclosing " + type.getName();
|
||||
}
|
||||
|
||||
public void visit(IVisitor v) {
|
||||
((AstJavaInstructionVisitor) v).visitEnclosingObjectReference(this);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return lval * type.hashCode();
|
||||
}
|
||||
|
||||
public Collection<TypeReference> getExceptionTypes() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
public boolean isFallThrough() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,71 +1,71 @@
|
||||
package com.ibm.wala.cast.js.vis;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.Set;
|
||||
|
||||
import com.ibm.wala.cast.ir.ssa.AstIRFactory;
|
||||
import com.ibm.wala.cast.js.html.DefaultSourceExtractor;
|
||||
import com.ibm.wala.cast.js.html.DomLessSourceExtractor;
|
||||
import com.ibm.wala.cast.js.html.IdentityUrlResolver;
|
||||
import com.ibm.wala.cast.js.html.JSSourceExtractor;
|
||||
import com.ibm.wala.cast.js.html.MappedSourceModule;
|
||||
import com.ibm.wala.cast.js.html.WebPageLoaderFactory;
|
||||
import com.ibm.wala.cast.js.html.WebUtil;
|
||||
import com.ibm.wala.cast.js.html.jericho.JerichoHtmlParser;
|
||||
import com.ibm.wala.cast.js.ipa.callgraph.JSCFABuilder;
|
||||
import com.ibm.wala.cast.js.loader.JavaScriptLoader;
|
||||
import com.ibm.wala.cast.js.test.JSCallGraphBuilderUtil;
|
||||
import com.ibm.wala.cast.js.translator.CAstRhinoTranslatorFactory;
|
||||
import com.ibm.wala.classLoader.SourceFileModule;
|
||||
import com.ibm.wala.classLoader.SourceModule;
|
||||
import com.ibm.wala.ipa.callgraph.CallGraph;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis;
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchyException;
|
||||
import com.ibm.wala.util.CancelException;
|
||||
|
||||
public class JsViewerDriver extends JSCallGraphBuilderUtil {
|
||||
public static void main(String args[]) throws ClassHierarchyException, IllegalArgumentException, IOException, CancelException {
|
||||
|
||||
if (args.length != 1){
|
||||
System.out.println("Usage: <URL of html page to analyze>");
|
||||
System.exit(1);
|
||||
}
|
||||
boolean domless = false;
|
||||
|
||||
URL url = new URL(args[0]);
|
||||
|
||||
// computing CG + PA
|
||||
JSCallGraphBuilderUtil.setTranslatorFactory(new CAstRhinoTranslatorFactory());
|
||||
JavaScriptLoader.addBootstrapFile(WebUtil.preamble);
|
||||
|
||||
SourceModule[] sources = getSources(domless, url);
|
||||
|
||||
JSCFABuilder builder = makeCGBuilder(new WebPageLoaderFactory(translatorFactory), sources, CGBuilderType.ZERO_ONE_CFA, AstIRFactory.makeDefaultFactory());
|
||||
builder.setBaseURL(url);
|
||||
|
||||
CallGraph cg = builder.makeCallGraph(builder.getOptions());
|
||||
PointerAnalysis pa = builder.getPointerAnalysis();
|
||||
|
||||
new JsViewer(cg, pa);
|
||||
}
|
||||
|
||||
private static SourceModule[] getSources(boolean domless, URL url)
|
||||
throws IOException {
|
||||
JSSourceExtractor sourceExtractor;
|
||||
if (domless ){
|
||||
sourceExtractor = new DomLessSourceExtractor();
|
||||
} else {
|
||||
sourceExtractor = new DefaultSourceExtractor();
|
||||
}
|
||||
|
||||
Set<MappedSourceModule> sourcesMap = sourceExtractor.extractSources(url, new JerichoHtmlParser(), new IdentityUrlResolver());
|
||||
SourceModule[] sources = new SourceFileModule[sourcesMap.size()];
|
||||
int i = 0;
|
||||
for (SourceModule m : sourcesMap){
|
||||
sources[i++] = m;
|
||||
}
|
||||
return sources;
|
||||
}
|
||||
|
||||
}
|
||||
package com.ibm.wala.cast.js.vis;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.Set;
|
||||
|
||||
import com.ibm.wala.cast.ir.ssa.AstIRFactory;
|
||||
import com.ibm.wala.cast.js.html.DefaultSourceExtractor;
|
||||
import com.ibm.wala.cast.js.html.DomLessSourceExtractor;
|
||||
import com.ibm.wala.cast.js.html.IdentityUrlResolver;
|
||||
import com.ibm.wala.cast.js.html.JSSourceExtractor;
|
||||
import com.ibm.wala.cast.js.html.MappedSourceModule;
|
||||
import com.ibm.wala.cast.js.html.WebPageLoaderFactory;
|
||||
import com.ibm.wala.cast.js.html.WebUtil;
|
||||
import com.ibm.wala.cast.js.html.jericho.JerichoHtmlParser;
|
||||
import com.ibm.wala.cast.js.ipa.callgraph.JSCFABuilder;
|
||||
import com.ibm.wala.cast.js.loader.JavaScriptLoader;
|
||||
import com.ibm.wala.cast.js.test.JSCallGraphBuilderUtil;
|
||||
import com.ibm.wala.cast.js.translator.CAstRhinoTranslatorFactory;
|
||||
import com.ibm.wala.classLoader.SourceFileModule;
|
||||
import com.ibm.wala.classLoader.SourceModule;
|
||||
import com.ibm.wala.ipa.callgraph.CallGraph;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis;
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchyException;
|
||||
import com.ibm.wala.util.CancelException;
|
||||
|
||||
public class JsViewerDriver extends JSCallGraphBuilderUtil {
|
||||
public static void main(String args[]) throws ClassHierarchyException, IllegalArgumentException, IOException, CancelException {
|
||||
|
||||
if (args.length != 1){
|
||||
System.out.println("Usage: <URL of html page to analyze>");
|
||||
System.exit(1);
|
||||
}
|
||||
boolean domless = false;
|
||||
|
||||
URL url = new URL(args[0]);
|
||||
|
||||
// computing CG + PA
|
||||
JSCallGraphBuilderUtil.setTranslatorFactory(new CAstRhinoTranslatorFactory());
|
||||
JavaScriptLoader.addBootstrapFile(WebUtil.preamble);
|
||||
|
||||
SourceModule[] sources = getSources(domless, url);
|
||||
|
||||
JSCFABuilder builder = makeCGBuilder(new WebPageLoaderFactory(translatorFactory), sources, CGBuilderType.ZERO_ONE_CFA, AstIRFactory.makeDefaultFactory());
|
||||
builder.setBaseURL(url);
|
||||
|
||||
CallGraph cg = builder.makeCallGraph(builder.getOptions());
|
||||
PointerAnalysis pa = builder.getPointerAnalysis();
|
||||
|
||||
new JsViewer(cg, pa);
|
||||
}
|
||||
|
||||
private static SourceModule[] getSources(boolean domless, URL url)
|
||||
throws IOException {
|
||||
JSSourceExtractor sourceExtractor;
|
||||
if (domless ){
|
||||
sourceExtractor = new DomLessSourceExtractor();
|
||||
} else {
|
||||
sourceExtractor = new DefaultSourceExtractor();
|
||||
}
|
||||
|
||||
Set<MappedSourceModule> sourcesMap = sourceExtractor.extractSources(url, new JerichoHtmlParser(), new IdentityUrlResolver());
|
||||
SourceModule[] sources = new SourceFileModule[sourcesMap.size()];
|
||||
int i = 0;
|
||||
for (SourceModule m : sourcesMap){
|
||||
sources[i++] = m;
|
||||
}
|
||||
return sources;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,185 +1,185 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) 2002 - 2011 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.cast.js.html;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.Stack;
|
||||
|
||||
import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position;
|
||||
import com.ibm.wala.util.collections.HashMapFactory;
|
||||
import com.ibm.wala.util.collections.Pair;
|
||||
|
||||
public class DefaultSourceExtractor extends DomLessSourceExtractor{
|
||||
|
||||
protected static class HtmlCallBack extends DomLessSourceExtractor.HtmlCallback{
|
||||
|
||||
private final HashMap<String, String> constructors = HashMapFactory.make();
|
||||
|
||||
private final Stack<String> stack = new Stack<String>();
|
||||
|
||||
private final Stack<ITag> forms = new Stack<ITag>();
|
||||
private final Set<Pair<ITag,String>> sets = new HashSet<Pair<ITag,String>>();
|
||||
|
||||
public HtmlCallBack(URL entrypointUrl, IUrlResolver urlResolver) {
|
||||
super(entrypointUrl, urlResolver);
|
||||
constructors.put("FORM", "DOMHTMLFormElement");
|
||||
constructors.put("TABLE", "DOMHTMLTableElement");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleEndTag(ITag tag) {
|
||||
super.handleEndTag(tag);
|
||||
endElement(stack.pop());
|
||||
if (tag.getName().equalsIgnoreCase("FORM")) {
|
||||
forms.pop();
|
||||
}
|
||||
for(Entry<String,Pair<String, Position>> e : tag.getAllAttributes().entrySet()) {
|
||||
String a = e.getKey();
|
||||
String v = e.getValue().fst;
|
||||
if (v != null && v.startsWith("javascript:")) {
|
||||
try {
|
||||
entrypointRegion.println(" " + v.substring(11), e.getValue().snd, new URL(tag.getElementPosition().getURL().toString() + "#" + a));
|
||||
} catch (MalformedURLException ex) {
|
||||
entrypointRegion.println(v.substring(11), e.getValue().snd, entrypointUrl);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleDOM(ITag tag, String funcName) {
|
||||
|
||||
String cons = constructors.get(tag.getName().toUpperCase());
|
||||
if(cons == null) cons = "DOMHTMLElement";
|
||||
writeElement(tag, cons, funcName);
|
||||
newLine();
|
||||
}
|
||||
|
||||
private void printlnIndented(String line, ITag relatedTag){
|
||||
printlnIndented(line, relatedTag==null? null: relatedTag.getElementPosition());
|
||||
}
|
||||
|
||||
private void printlnIndented(String line, Position pos){
|
||||
StringBuilder indentedLine = new StringBuilder();
|
||||
for (int i = 0 ; i < stack.size() ; i++){
|
||||
indentedLine.append(" ");
|
||||
}
|
||||
indentedLine.append(line);
|
||||
|
||||
if (pos == null){
|
||||
domRegion.println(indentedLine.toString());
|
||||
} else {
|
||||
domRegion.println(indentedLine.toString(), pos, entrypointUrl);
|
||||
}
|
||||
}
|
||||
|
||||
private void newLine(){
|
||||
domRegion.println("");
|
||||
}
|
||||
|
||||
protected void writeElement(ITag tag, String cons, String varName){
|
||||
Map<String, Pair<String, Position>> attrs = tag.getAllAttributes();
|
||||
|
||||
printlnIndented("function make_" + varName + "(parent) {", tag);
|
||||
stack.push(varName);
|
||||
|
||||
printlnIndented("this.temp = " + cons + ";", tag);
|
||||
printlnIndented("this.temp(\"" + tag.getName() + "\");", tag);
|
||||
for (Map.Entry<String, Pair<String, Position>> e : attrs.entrySet()){
|
||||
String attr = e.getKey();
|
||||
String value = e.getValue().fst;
|
||||
writeAttribute(tag, e.getValue().snd, attr, value, "this", varName);
|
||||
}
|
||||
|
||||
if (tag.getName().equalsIgnoreCase("FORM")) {
|
||||
forms.push(tag);
|
||||
printlnIndented(" document.forms[document.formCount++] = this;", tag);
|
||||
printlnIndented(" var currentForm = this;", tag);
|
||||
} if (tag.getName().equalsIgnoreCase("INPUT")) {
|
||||
String prop = attrs.containsKey("name") ? attrs.get("name").fst : null;
|
||||
String type = attrs.containsKey("type") ? attrs.get("type").fst : null;
|
||||
|
||||
if (type != null && prop != null) {
|
||||
if (type.equalsIgnoreCase("RADIO")) {
|
||||
if (! sets.contains(Pair.make(forms.peek(), prop))) {
|
||||
sets.add(Pair.make(forms.peek(), prop));
|
||||
printlnIndented(" currentForm." + prop + " = new Array();", tag);
|
||||
printlnIndented(" currentForm." + prop + "Counter = 0;", tag);
|
||||
}
|
||||
printlnIndented(" currentForm." + prop + "[currentForm." + prop + "Counter++] = this;", tag);
|
||||
} else {
|
||||
printlnIndented(" currentForm." + prop + " = this;", tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
printlnIndented(varName + " = this;", tag);
|
||||
printlnIndented("document." + varName + " = this;", tag);
|
||||
printlnIndented("parent.appendChild(this);", tag);
|
||||
}
|
||||
|
||||
protected void writeAttribute(ITag tag, Position pos, String attr, String value, String varName, String varName2) {
|
||||
writePortletAttribute(tag, attr, value, varName);
|
||||
writeEventAttribute(tag, pos, attr, value, varName, varName2);
|
||||
}
|
||||
|
||||
protected void writeEventAttribute(ITag tag, Position pos, String attr, String value, String varName, String varName2){
|
||||
if(attr.substring(0,2).equals("on")) {
|
||||
printlnIndented(varName + "." + attr + " = function " + tag.getName().toLowerCase() + "_" + attr + "(event) {" + value + "};", tag);
|
||||
entrypointRegion.println(varName2 + "." + attr + "(null);", tag.getElementPosition(), entrypointUrl);
|
||||
} else if (value != null) {
|
||||
if (value.indexOf('\'') > 0) {
|
||||
value = value.replaceAll("\\'", "\\\\'");
|
||||
}
|
||||
if (value.indexOf('\n') > 0) {
|
||||
value = value.replaceAll("\\n", "\\\\n");
|
||||
}
|
||||
if (attr.equals(attr.toUpperCase())) {
|
||||
attr = attr.toLowerCase();
|
||||
}
|
||||
printlnIndented(varName + "['" + attr + "'] = '" + value + "';", tag);
|
||||
}
|
||||
}
|
||||
|
||||
protected void writePortletAttribute(ITag tag, String attr, String value, String varName){
|
||||
if(attr.equals("portletid")) {
|
||||
if(value.substring(value.length()-4).equals("vice")) {
|
||||
newLine(); newLine();
|
||||
printlnIndented("function cVice() { var contextVice = " + varName + "; }\ncVice();\n", tag);
|
||||
} else if(value.substring(value.length()-4).equals("root")) {
|
||||
newLine(); newLine();
|
||||
printlnIndented("function cRoot() { var contextRoot = " + varName + "; }\ncRoot();\n", tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void endElement(String name) {
|
||||
printlnIndented("};", (Position)null);
|
||||
if (stack.isEmpty()) {
|
||||
printlnIndented("new make_" + name + "(document);\n\n", (Position)null);
|
||||
} else {
|
||||
printlnIndented("new make_" + name + "(this);\n", (Position)null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IGeneratorCallback createHtmlCallback(URL entrypointUrl, IUrlResolver urlResolver) {
|
||||
return new HtmlCallBack(entrypointUrl, urlResolver);
|
||||
}
|
||||
}
|
||||
/******************************************************************************
|
||||
* Copyright (c) 2002 - 2011 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.cast.js.html;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.Stack;
|
||||
|
||||
import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position;
|
||||
import com.ibm.wala.util.collections.HashMapFactory;
|
||||
import com.ibm.wala.util.collections.Pair;
|
||||
|
||||
public class DefaultSourceExtractor extends DomLessSourceExtractor{
|
||||
|
||||
protected static class HtmlCallBack extends DomLessSourceExtractor.HtmlCallback{
|
||||
|
||||
private final HashMap<String, String> constructors = HashMapFactory.make();
|
||||
|
||||
private final Stack<String> stack = new Stack<String>();
|
||||
|
||||
private final Stack<ITag> forms = new Stack<ITag>();
|
||||
private final Set<Pair<ITag,String>> sets = new HashSet<Pair<ITag,String>>();
|
||||
|
||||
public HtmlCallBack(URL entrypointUrl, IUrlResolver urlResolver) {
|
||||
super(entrypointUrl, urlResolver);
|
||||
constructors.put("FORM", "DOMHTMLFormElement");
|
||||
constructors.put("TABLE", "DOMHTMLTableElement");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleEndTag(ITag tag) {
|
||||
super.handleEndTag(tag);
|
||||
endElement(stack.pop());
|
||||
if (tag.getName().equalsIgnoreCase("FORM")) {
|
||||
forms.pop();
|
||||
}
|
||||
for(Entry<String,Pair<String, Position>> e : tag.getAllAttributes().entrySet()) {
|
||||
String a = e.getKey();
|
||||
String v = e.getValue().fst;
|
||||
if (v != null && v.startsWith("javascript:")) {
|
||||
try {
|
||||
entrypointRegion.println(" " + v.substring(11), e.getValue().snd, new URL(tag.getElementPosition().getURL().toString() + "#" + a));
|
||||
} catch (MalformedURLException ex) {
|
||||
entrypointRegion.println(v.substring(11), e.getValue().snd, entrypointUrl);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleDOM(ITag tag, String funcName) {
|
||||
|
||||
String cons = constructors.get(tag.getName().toUpperCase());
|
||||
if(cons == null) cons = "DOMHTMLElement";
|
||||
writeElement(tag, cons, funcName);
|
||||
newLine();
|
||||
}
|
||||
|
||||
private void printlnIndented(String line, ITag relatedTag){
|
||||
printlnIndented(line, relatedTag==null? null: relatedTag.getElementPosition());
|
||||
}
|
||||
|
||||
private void printlnIndented(String line, Position pos){
|
||||
StringBuilder indentedLine = new StringBuilder();
|
||||
for (int i = 0 ; i < stack.size() ; i++){
|
||||
indentedLine.append(" ");
|
||||
}
|
||||
indentedLine.append(line);
|
||||
|
||||
if (pos == null){
|
||||
domRegion.println(indentedLine.toString());
|
||||
} else {
|
||||
domRegion.println(indentedLine.toString(), pos, entrypointUrl);
|
||||
}
|
||||
}
|
||||
|
||||
private void newLine(){
|
||||
domRegion.println("");
|
||||
}
|
||||
|
||||
protected void writeElement(ITag tag, String cons, String varName){
|
||||
Map<String, Pair<String, Position>> attrs = tag.getAllAttributes();
|
||||
|
||||
printlnIndented("function make_" + varName + "(parent) {", tag);
|
||||
stack.push(varName);
|
||||
|
||||
printlnIndented("this.temp = " + cons + ";", tag);
|
||||
printlnIndented("this.temp(\"" + tag.getName() + "\");", tag);
|
||||
for (Map.Entry<String, Pair<String, Position>> e : attrs.entrySet()){
|
||||
String attr = e.getKey();
|
||||
String value = e.getValue().fst;
|
||||
writeAttribute(tag, e.getValue().snd, attr, value, "this", varName);
|
||||
}
|
||||
|
||||
if (tag.getName().equalsIgnoreCase("FORM")) {
|
||||
forms.push(tag);
|
||||
printlnIndented(" document.forms[document.formCount++] = this;", tag);
|
||||
printlnIndented(" var currentForm = this;", tag);
|
||||
} if (tag.getName().equalsIgnoreCase("INPUT")) {
|
||||
String prop = attrs.containsKey("name") ? attrs.get("name").fst : null;
|
||||
String type = attrs.containsKey("type") ? attrs.get("type").fst : null;
|
||||
|
||||
if (type != null && prop != null) {
|
||||
if (type.equalsIgnoreCase("RADIO")) {
|
||||
if (! sets.contains(Pair.make(forms.peek(), prop))) {
|
||||
sets.add(Pair.make(forms.peek(), prop));
|
||||
printlnIndented(" currentForm." + prop + " = new Array();", tag);
|
||||
printlnIndented(" currentForm." + prop + "Counter = 0;", tag);
|
||||
}
|
||||
printlnIndented(" currentForm." + prop + "[currentForm." + prop + "Counter++] = this;", tag);
|
||||
} else {
|
||||
printlnIndented(" currentForm." + prop + " = this;", tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
printlnIndented(varName + " = this;", tag);
|
||||
printlnIndented("document." + varName + " = this;", tag);
|
||||
printlnIndented("parent.appendChild(this);", tag);
|
||||
}
|
||||
|
||||
protected void writeAttribute(ITag tag, Position pos, String attr, String value, String varName, String varName2) {
|
||||
writePortletAttribute(tag, attr, value, varName);
|
||||
writeEventAttribute(tag, pos, attr, value, varName, varName2);
|
||||
}
|
||||
|
||||
protected void writeEventAttribute(ITag tag, Position pos, String attr, String value, String varName, String varName2){
|
||||
if(attr.substring(0,2).equals("on")) {
|
||||
printlnIndented(varName + "." + attr + " = function " + tag.getName().toLowerCase() + "_" + attr + "(event) {" + value + "};", tag);
|
||||
entrypointRegion.println(varName2 + "." + attr + "(null);", tag.getElementPosition(), entrypointUrl);
|
||||
} else if (value != null) {
|
||||
if (value.indexOf('\'') > 0) {
|
||||
value = value.replaceAll("\\'", "\\\\'");
|
||||
}
|
||||
if (value.indexOf('\n') > 0) {
|
||||
value = value.replaceAll("\\n", "\\\\n");
|
||||
}
|
||||
if (attr.equals(attr.toUpperCase())) {
|
||||
attr = attr.toLowerCase();
|
||||
}
|
||||
printlnIndented(varName + "['" + attr + "'] = '" + value + "';", tag);
|
||||
}
|
||||
}
|
||||
|
||||
protected void writePortletAttribute(ITag tag, String attr, String value, String varName){
|
||||
if(attr.equals("portletid")) {
|
||||
if(value.substring(value.length()-4).equals("vice")) {
|
||||
newLine(); newLine();
|
||||
printlnIndented("function cVice() { var contextVice = " + varName + "; }\ncVice();\n", tag);
|
||||
} else if(value.substring(value.length()-4).equals("root")) {
|
||||
newLine(); newLine();
|
||||
printlnIndented("function cRoot() { var contextRoot = " + varName + "; }\ncRoot();\n", tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void endElement(String name) {
|
||||
printlnIndented("};", (Position)null);
|
||||
if (stack.isEmpty()) {
|
||||
printlnIndented("new make_" + name + "(document);\n\n", (Position)null);
|
||||
} else {
|
||||
printlnIndented("new make_" + name + "(this);\n", (Position)null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IGeneratorCallback createHtmlCallback(URL entrypointUrl, IUrlResolver urlResolver) {
|
||||
return new HtmlCallBack(entrypointUrl, urlResolver);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,279 +1,279 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) 2002 - 2011 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.cast.js.html;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import com.ibm.wala.cast.js.html.jericho.JerichoHtmlParser;
|
||||
import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position;
|
||||
import com.ibm.wala.util.collections.Pair;
|
||||
|
||||
|
||||
public class DomLessSourceExtractor extends JSSourceExtractor {
|
||||
private static final Pattern LEGAL_JS_IDENTIFIER_REGEXP = Pattern.compile("[a-zA-Z$_][a-zA-Z\\d$_]*");
|
||||
protected interface IGeneratorCallback extends IHtmlCallback {
|
||||
void writeToFinalRegion(SourceRegion finalRegion);
|
||||
}
|
||||
|
||||
protected static class HtmlCallback implements IGeneratorCallback{
|
||||
protected final URL entrypointUrl;
|
||||
protected final IUrlResolver urlResolver;
|
||||
|
||||
protected final SourceRegion scriptRegion;
|
||||
protected final SourceRegion domRegion;
|
||||
protected final SourceRegion entrypointRegion;
|
||||
|
||||
private ITag currentScriptTag;
|
||||
|
||||
private int nodeCounter = 0;
|
||||
private int scriptNodeCounter = 0;
|
||||
|
||||
public HtmlCallback(URL entrypointUrl, IUrlResolver urlResolver) {
|
||||
this.entrypointUrl = entrypointUrl;
|
||||
this.urlResolver = urlResolver;
|
||||
this.scriptRegion = new SourceRegion();
|
||||
this.domRegion = new SourceRegion();
|
||||
this.entrypointRegion = new SourceRegion();
|
||||
}
|
||||
|
||||
protected Position makePos(int lineNumber, ITag governingTag) {
|
||||
return makePos(entrypointUrl, lineNumber, governingTag);
|
||||
}
|
||||
|
||||
protected Position makePos(final URL url, final int lineNumber, ITag governingTag) {
|
||||
return governingTag.getElementPosition();
|
||||
}
|
||||
|
||||
public void handleEndTag(ITag tag) {
|
||||
if (tag.getName().equalsIgnoreCase("script")) {
|
||||
assert currentScriptTag != null;
|
||||
currentScriptTag = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void handleText(Position p, String text) {
|
||||
if (currentScriptTag != null) {
|
||||
if (text.startsWith("<![CDATA[")) {
|
||||
assert text.endsWith("]]>");
|
||||
text = text.substring(9, text.length()-11);
|
||||
}
|
||||
|
||||
URL url = entrypointUrl;
|
||||
try {
|
||||
url = new URL(entrypointUrl, "#" + scriptNodeCounter);
|
||||
} catch (MalformedURLException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
scriptRegion.println(text, currentScriptTag.getContentPosition(), url);
|
||||
}
|
||||
}
|
||||
|
||||
public void handleStartTag(ITag tag) {
|
||||
if (tag.getName().equalsIgnoreCase("script")) {
|
||||
handleScript(tag);
|
||||
assert currentScriptTag == null;
|
||||
currentScriptTag = tag;
|
||||
scriptNodeCounter++;
|
||||
}
|
||||
handleDOM(tag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Model the HTML DOM
|
||||
*
|
||||
* @param tag
|
||||
* - the HTML tag to module
|
||||
*/
|
||||
protected void handleDOM(ITag tag) {
|
||||
// Get the name of the modeling function either from the id attribute or a
|
||||
// running counter
|
||||
Pair<String,Position> idAttribute = tag.getAttributeByName("id");
|
||||
String funcName;
|
||||
if (idAttribute != null && LEGAL_JS_IDENTIFIER_REGEXP.matcher(idAttribute.fst).matches()) {
|
||||
funcName = idAttribute.fst;
|
||||
} else {
|
||||
funcName = "node" + (nodeCounter++);
|
||||
}
|
||||
handleDOM(tag, funcName);
|
||||
}
|
||||
|
||||
protected void handleDOM(ITag tag, String funcName) {
|
||||
Map<String, Pair<String,Position>> attributeSet = tag.getAllAttributes();
|
||||
for (Entry<String, Pair<String, Position>> a : attributeSet.entrySet()) {
|
||||
handleAttribute(a, funcName, tag);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleAttribute(Entry<String, Pair<String,Position>> a, String funcName, ITag tag) {
|
||||
URL url = entrypointUrl;
|
||||
try {
|
||||
url = new URL(entrypointUrl, "#" + tag.getElementPosition().getFirstOffset());
|
||||
} catch (MalformedURLException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
Position pos = a.getValue().snd;
|
||||
String attName = a.getKey();
|
||||
String attValue = a.getValue().fst;
|
||||
if (attName.toLowerCase().startsWith("on") || (attValue != null && attValue.toLowerCase().startsWith("javascript:"))) {
|
||||
String fName = tag.getName().toLowerCase() + "_" + attName + "_" + funcName;
|
||||
String signatureLine = "function " + fName + "(event) {";
|
||||
// Defines the function
|
||||
domRegion.println(signatureLine + "\n" + extructJS(attValue) + "\n}", pos, url);
|
||||
// Run it
|
||||
entrypointRegion.println("\t" + fName + "(null);", pos, url);
|
||||
}
|
||||
}
|
||||
|
||||
private String extructJS(String attValue) {
|
||||
if (attValue == null){
|
||||
return "";
|
||||
}
|
||||
String content;
|
||||
if (attValue.toLowerCase().equals("javascript:")) {
|
||||
content = attValue.substring("javascript:".length());
|
||||
} else {
|
||||
content = attValue;
|
||||
}
|
||||
|
||||
return content;
|
||||
}
|
||||
|
||||
protected void handleScript(ITag tag) {
|
||||
|
||||
Pair<String,Position> value = tag.getAttributeByName("src");
|
||||
|
||||
try {
|
||||
if (value != null) {
|
||||
// script is out-of-line
|
||||
getScriptFromUrl(value.fst, tag);
|
||||
}
|
||||
|
||||
} catch (IOException e) {
|
||||
System.err.println("Error reading script file: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void getScriptFromUrl(String urlAsString, ITag scriptTag) throws IOException, MalformedURLException {
|
||||
URL absoluteUrl = UrlManipulator.relativeToAbsoluteUrl(urlAsString, this.entrypointUrl);
|
||||
URL scriptSrc = urlResolver.resolve(absoluteUrl);
|
||||
if (scriptSrc == null) { //Error resolving URL
|
||||
return;
|
||||
}
|
||||
|
||||
InputStream scriptInputStream = scriptSrc.openConnection().getInputStream();
|
||||
try{
|
||||
String line;
|
||||
BufferedReader scriptReader = new BufferedReader(new UnicodeReader(scriptInputStream, "UTF8"));
|
||||
StringBuffer x = new StringBuffer();
|
||||
while ((line = scriptReader.readLine()) != null) {
|
||||
x.append(line).append("\n");
|
||||
}
|
||||
|
||||
scriptRegion.println(x.toString(), scriptTag.getElementPosition(), scriptSrc);
|
||||
|
||||
} finally {
|
||||
scriptInputStream.close();
|
||||
}
|
||||
}
|
||||
|
||||
protected String getScriptName(URL url) throws MalformedURLException {
|
||||
String file = url.getFile();
|
||||
int lastIdxOfSlash = file.lastIndexOf('/');
|
||||
file = (lastIdxOfSlash == (-1)) ? file : file.substring(lastIdxOfSlash + 1);
|
||||
return file;
|
||||
}
|
||||
|
||||
public void writeToFinalRegion(SourceRegion finalRegion) {
|
||||
// wrapping the embedded scripts with a fake method of the window. Required for making this == window.
|
||||
finalRegion.println("window.__MAIN__ = function __WINDOW_MAIN__(){");
|
||||
|
||||
finalRegion.write(scriptRegion);
|
||||
|
||||
finalRegion.write(domRegion);
|
||||
|
||||
finalRegion.println(" document.URL = new String(\"" + entrypointUrl + "\");");
|
||||
|
||||
finalRegion.println("while (true){ ");
|
||||
finalRegion.write(entrypointRegion);
|
||||
finalRegion.println("} // while (true)");
|
||||
|
||||
finalRegion.println("} // end of window.__MAIN__");
|
||||
finalRegion.println("window.__MAIN__();");
|
||||
}
|
||||
}
|
||||
|
||||
public Set<MappedSourceModule> extractSources(URL entrypointUrl, IHtmlParser htmlParser, IUrlResolver urlResolver)
|
||||
throws IOException {
|
||||
|
||||
InputStream inputStreamReader = WebUtil.getStream(entrypointUrl);
|
||||
IGeneratorCallback htmlCallback = createHtmlCallback(entrypointUrl, urlResolver);
|
||||
htmlParser.parse(entrypointUrl, inputStreamReader, htmlCallback, entrypointUrl.getFile());
|
||||
|
||||
SourceRegion finalRegion = new SourceRegion();
|
||||
htmlCallback.writeToFinalRegion(finalRegion);
|
||||
|
||||
// writing the final region into one SourceFileModule.
|
||||
File outputFile = createOutputFile(entrypointUrl, DELETE_UPON_EXIT, USE_TEMP_NAME);
|
||||
FileMapping fileMapping = finalRegion.writeToFile(new PrintStream(outputFile));
|
||||
MappedSourceModule singleFileModule = new MappedSourceFileModule(outputFile, outputFile.getName(), fileMapping);
|
||||
return Collections.singleton(singleFileModule);
|
||||
}
|
||||
|
||||
protected IGeneratorCallback createHtmlCallback(URL entrypointUrl, IUrlResolver urlResolver) {
|
||||
return new HtmlCallback(entrypointUrl, urlResolver);
|
||||
}
|
||||
|
||||
private File createOutputFile(URL url, boolean delete, boolean useTempName) throws IOException {
|
||||
File outputFile;
|
||||
if (useTempName) {
|
||||
outputFile = File.createTempFile(new File(url.getFile()).getName(), ".js");
|
||||
} else {
|
||||
outputFile = new File(new File(url.getFile()).getName());
|
||||
}
|
||||
if (outputFile.exists()){
|
||||
outputFile.delete();
|
||||
}
|
||||
if(delete){
|
||||
outputFile.deleteOnExit();
|
||||
}
|
||||
return outputFile;
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
// DomLessSourceExtractor domLessScopeGenerator = new DomLessSourceExtractor();
|
||||
JSSourceExtractor domLessScopeGenerator = new DefaultSourceExtractor();
|
||||
JSSourceExtractor.DELETE_UPON_EXIT = false;
|
||||
URL entrypointUrl = new URL(args[0]);
|
||||
IHtmlParser htmlParser = new JerichoHtmlParser();
|
||||
IUrlResolver urlResolver = new IdentityUrlResolver();
|
||||
Set<MappedSourceModule> res = domLessScopeGenerator.extractSources(entrypointUrl , htmlParser , urlResolver);
|
||||
MappedSourceModule entry = res.iterator().next();
|
||||
System.out.println(entry);
|
||||
entry.getMapping().dump(System.out);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Copyright (c) 2002 - 2011 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.cast.js.html;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import com.ibm.wala.cast.js.html.jericho.JerichoHtmlParser;
|
||||
import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position;
|
||||
import com.ibm.wala.util.collections.Pair;
|
||||
|
||||
|
||||
public class DomLessSourceExtractor extends JSSourceExtractor {
|
||||
private static final Pattern LEGAL_JS_IDENTIFIER_REGEXP = Pattern.compile("[a-zA-Z$_][a-zA-Z\\d$_]*");
|
||||
protected interface IGeneratorCallback extends IHtmlCallback {
|
||||
void writeToFinalRegion(SourceRegion finalRegion);
|
||||
}
|
||||
|
||||
protected static class HtmlCallback implements IGeneratorCallback{
|
||||
protected final URL entrypointUrl;
|
||||
protected final IUrlResolver urlResolver;
|
||||
|
||||
protected final SourceRegion scriptRegion;
|
||||
protected final SourceRegion domRegion;
|
||||
protected final SourceRegion entrypointRegion;
|
||||
|
||||
private ITag currentScriptTag;
|
||||
|
||||
private int nodeCounter = 0;
|
||||
private int scriptNodeCounter = 0;
|
||||
|
||||
public HtmlCallback(URL entrypointUrl, IUrlResolver urlResolver) {
|
||||
this.entrypointUrl = entrypointUrl;
|
||||
this.urlResolver = urlResolver;
|
||||
this.scriptRegion = new SourceRegion();
|
||||
this.domRegion = new SourceRegion();
|
||||
this.entrypointRegion = new SourceRegion();
|
||||
}
|
||||
|
||||
protected Position makePos(int lineNumber, ITag governingTag) {
|
||||
return makePos(entrypointUrl, lineNumber, governingTag);
|
||||
}
|
||||
|
||||
protected Position makePos(final URL url, final int lineNumber, ITag governingTag) {
|
||||
return governingTag.getElementPosition();
|
||||
}
|
||||
|
||||
public void handleEndTag(ITag tag) {
|
||||
if (tag.getName().equalsIgnoreCase("script")) {
|
||||
assert currentScriptTag != null;
|
||||
currentScriptTag = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void handleText(Position p, String text) {
|
||||
if (currentScriptTag != null) {
|
||||
if (text.startsWith("<![CDATA[")) {
|
||||
assert text.endsWith("]]>");
|
||||
text = text.substring(9, text.length()-11);
|
||||
}
|
||||
|
||||
URL url = entrypointUrl;
|
||||
try {
|
||||
url = new URL(entrypointUrl, "#" + scriptNodeCounter);
|
||||
} catch (MalformedURLException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
scriptRegion.println(text, currentScriptTag.getContentPosition(), url);
|
||||
}
|
||||
}
|
||||
|
||||
public void handleStartTag(ITag tag) {
|
||||
if (tag.getName().equalsIgnoreCase("script")) {
|
||||
handleScript(tag);
|
||||
assert currentScriptTag == null;
|
||||
currentScriptTag = tag;
|
||||
scriptNodeCounter++;
|
||||
}
|
||||
handleDOM(tag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Model the HTML DOM
|
||||
*
|
||||
* @param tag
|
||||
* - the HTML tag to module
|
||||
*/
|
||||
protected void handleDOM(ITag tag) {
|
||||
// Get the name of the modeling function either from the id attribute or a
|
||||
// running counter
|
||||
Pair<String,Position> idAttribute = tag.getAttributeByName("id");
|
||||
String funcName;
|
||||
if (idAttribute != null && LEGAL_JS_IDENTIFIER_REGEXP.matcher(idAttribute.fst).matches()) {
|
||||
funcName = idAttribute.fst;
|
||||
} else {
|
||||
funcName = "node" + (nodeCounter++);
|
||||
}
|
||||
handleDOM(tag, funcName);
|
||||
}
|
||||
|
||||
protected void handleDOM(ITag tag, String funcName) {
|
||||
Map<String, Pair<String,Position>> attributeSet = tag.getAllAttributes();
|
||||
for (Entry<String, Pair<String, Position>> a : attributeSet.entrySet()) {
|
||||
handleAttribute(a, funcName, tag);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleAttribute(Entry<String, Pair<String,Position>> a, String funcName, ITag tag) {
|
||||
URL url = entrypointUrl;
|
||||
try {
|
||||
url = new URL(entrypointUrl, "#" + tag.getElementPosition().getFirstOffset());
|
||||
} catch (MalformedURLException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
Position pos = a.getValue().snd;
|
||||
String attName = a.getKey();
|
||||
String attValue = a.getValue().fst;
|
||||
if (attName.toLowerCase().startsWith("on") || (attValue != null && attValue.toLowerCase().startsWith("javascript:"))) {
|
||||
String fName = tag.getName().toLowerCase() + "_" + attName + "_" + funcName;
|
||||
String signatureLine = "function " + fName + "(event) {";
|
||||
// Defines the function
|
||||
domRegion.println(signatureLine + "\n" + extructJS(attValue) + "\n}", pos, url);
|
||||
// Run it
|
||||
entrypointRegion.println("\t" + fName + "(null);", pos, url);
|
||||
}
|
||||
}
|
||||
|
||||
private String extructJS(String attValue) {
|
||||
if (attValue == null){
|
||||
return "";
|
||||
}
|
||||
String content;
|
||||
if (attValue.toLowerCase().equals("javascript:")) {
|
||||
content = attValue.substring("javascript:".length());
|
||||
} else {
|
||||
content = attValue;
|
||||
}
|
||||
|
||||
return content;
|
||||
}
|
||||
|
||||
protected void handleScript(ITag tag) {
|
||||
|
||||
Pair<String,Position> value = tag.getAttributeByName("src");
|
||||
|
||||
try {
|
||||
if (value != null) {
|
||||
// script is out-of-line
|
||||
getScriptFromUrl(value.fst, tag);
|
||||
}
|
||||
|
||||
} catch (IOException e) {
|
||||
System.err.println("Error reading script file: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void getScriptFromUrl(String urlAsString, ITag scriptTag) throws IOException, MalformedURLException {
|
||||
URL absoluteUrl = UrlManipulator.relativeToAbsoluteUrl(urlAsString, this.entrypointUrl);
|
||||
URL scriptSrc = urlResolver.resolve(absoluteUrl);
|
||||
if (scriptSrc == null) { //Error resolving URL
|
||||
return;
|
||||
}
|
||||
|
||||
InputStream scriptInputStream = scriptSrc.openConnection().getInputStream();
|
||||
try{
|
||||
String line;
|
||||
BufferedReader scriptReader = new BufferedReader(new UnicodeReader(scriptInputStream, "UTF8"));
|
||||
StringBuffer x = new StringBuffer();
|
||||
while ((line = scriptReader.readLine()) != null) {
|
||||
x.append(line).append("\n");
|
||||
}
|
||||
|
||||
scriptRegion.println(x.toString(), scriptTag.getElementPosition(), scriptSrc);
|
||||
|
||||
} finally {
|
||||
scriptInputStream.close();
|
||||
}
|
||||
}
|
||||
|
||||
protected String getScriptName(URL url) throws MalformedURLException {
|
||||
String file = url.getFile();
|
||||
int lastIdxOfSlash = file.lastIndexOf('/');
|
||||
file = (lastIdxOfSlash == (-1)) ? file : file.substring(lastIdxOfSlash + 1);
|
||||
return file;
|
||||
}
|
||||
|
||||
public void writeToFinalRegion(SourceRegion finalRegion) {
|
||||
// wrapping the embedded scripts with a fake method of the window. Required for making this == window.
|
||||
finalRegion.println("window.__MAIN__ = function __WINDOW_MAIN__(){");
|
||||
|
||||
finalRegion.write(scriptRegion);
|
||||
|
||||
finalRegion.write(domRegion);
|
||||
|
||||
finalRegion.println(" document.URL = new String(\"" + entrypointUrl + "\");");
|
||||
|
||||
finalRegion.println("while (true){ ");
|
||||
finalRegion.write(entrypointRegion);
|
||||
finalRegion.println("} // while (true)");
|
||||
|
||||
finalRegion.println("} // end of window.__MAIN__");
|
||||
finalRegion.println("window.__MAIN__();");
|
||||
}
|
||||
}
|
||||
|
||||
public Set<MappedSourceModule> extractSources(URL entrypointUrl, IHtmlParser htmlParser, IUrlResolver urlResolver)
|
||||
throws IOException {
|
||||
|
||||
InputStream inputStreamReader = WebUtil.getStream(entrypointUrl);
|
||||
IGeneratorCallback htmlCallback = createHtmlCallback(entrypointUrl, urlResolver);
|
||||
htmlParser.parse(entrypointUrl, inputStreamReader, htmlCallback, entrypointUrl.getFile());
|
||||
|
||||
SourceRegion finalRegion = new SourceRegion();
|
||||
htmlCallback.writeToFinalRegion(finalRegion);
|
||||
|
||||
// writing the final region into one SourceFileModule.
|
||||
File outputFile = createOutputFile(entrypointUrl, DELETE_UPON_EXIT, USE_TEMP_NAME);
|
||||
FileMapping fileMapping = finalRegion.writeToFile(new PrintStream(outputFile));
|
||||
MappedSourceModule singleFileModule = new MappedSourceFileModule(outputFile, outputFile.getName(), fileMapping);
|
||||
return Collections.singleton(singleFileModule);
|
||||
}
|
||||
|
||||
protected IGeneratorCallback createHtmlCallback(URL entrypointUrl, IUrlResolver urlResolver) {
|
||||
return new HtmlCallback(entrypointUrl, urlResolver);
|
||||
}
|
||||
|
||||
private File createOutputFile(URL url, boolean delete, boolean useTempName) throws IOException {
|
||||
File outputFile;
|
||||
if (useTempName) {
|
||||
outputFile = File.createTempFile(new File(url.getFile()).getName(), ".js");
|
||||
} else {
|
||||
outputFile = new File(new File(url.getFile()).getName());
|
||||
}
|
||||
if (outputFile.exists()){
|
||||
outputFile.delete();
|
||||
}
|
||||
if(delete){
|
||||
outputFile.deleteOnExit();
|
||||
}
|
||||
return outputFile;
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
// DomLessSourceExtractor domLessScopeGenerator = new DomLessSourceExtractor();
|
||||
JSSourceExtractor domLessScopeGenerator = new DefaultSourceExtractor();
|
||||
JSSourceExtractor.DELETE_UPON_EXIT = false;
|
||||
URL entrypointUrl = new URL(args[0]);
|
||||
IHtmlParser htmlParser = new JerichoHtmlParser();
|
||||
IUrlResolver urlResolver = new IdentityUrlResolver();
|
||||
Set<MappedSourceModule> res = domLessScopeGenerator.extractSources(entrypointUrl , htmlParser , urlResolver);
|
||||
MappedSourceModule entry = res.iterator().next();
|
||||
System.out.println(entry);
|
||||
entry.getMapping().dump(System.out);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,31 +1,31 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) 2002 - 2011 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.cast.js.html;
|
||||
|
||||
import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Callback which is implemented by users of the IHtmlParser. The parser traverses the dom-nodes in an in-order.
|
||||
* @author danielk
|
||||
* @author yinnonh
|
||||
*
|
||||
*/
|
||||
public interface IHtmlCallback {
|
||||
|
||||
void handleStartTag(ITag tag);
|
||||
|
||||
void handleText(Position pos, String text);
|
||||
|
||||
void handleEndTag(ITag tag);
|
||||
|
||||
}
|
||||
/******************************************************************************
|
||||
* Copyright (c) 2002 - 2011 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.cast.js.html;
|
||||
|
||||
import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Callback which is implemented by users of the IHtmlParser. The parser traverses the dom-nodes in an in-order.
|
||||
* @author danielk
|
||||
* @author yinnonh
|
||||
*
|
||||
*/
|
||||
public interface IHtmlCallback {
|
||||
|
||||
void handleStartTag(ITag tag);
|
||||
|
||||
void handleText(Position pos, String text);
|
||||
|
||||
void handleEndTag(ITag tag);
|
||||
|
||||
}
|
||||
|
||||
@ -1,31 +1,31 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) 2002 - 2011 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.cast.js.html;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
|
||||
/**
|
||||
* @author danielk
|
||||
* @author yinnonh
|
||||
* Parses an HTML file using call backs
|
||||
*/
|
||||
public interface IHtmlParser {
|
||||
|
||||
/**
|
||||
* Parses a given HTML, calling the given callback.
|
||||
* @param reader
|
||||
* @param callback
|
||||
* @param fileName
|
||||
*/
|
||||
public void parse(URL url, InputStream reader, IHtmlCallback callback, String fileName);
|
||||
|
||||
}
|
||||
/******************************************************************************
|
||||
* Copyright (c) 2002 - 2011 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.cast.js.html;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
|
||||
/**
|
||||
* @author danielk
|
||||
* @author yinnonh
|
||||
* Parses an HTML file using call backs
|
||||
*/
|
||||
public interface IHtmlParser {
|
||||
|
||||
/**
|
||||
* Parses a given HTML, calling the given callback.
|
||||
* @param reader
|
||||
* @param callback
|
||||
* @param fileName
|
||||
*/
|
||||
public void parse(URL url, InputStream reader, IHtmlCallback callback, String fileName);
|
||||
|
||||
}
|
||||
|
||||
@ -1,45 +1,45 @@
|
||||
package com.ibm.wala.cast.js.html;
|
||||
|
||||
/******************************************************************************
|
||||
* Copyright (c) 2002 - 2011 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
|
||||
*****************************************************************************/
|
||||
import java.util.Map;
|
||||
|
||||
import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position;
|
||||
import com.ibm.wala.util.collections.Pair;
|
||||
|
||||
/**
|
||||
* @author danielk
|
||||
* Data structure representing an HTML tag, with its attributes and content. Used by the HTML parser when calling the callback.
|
||||
*/
|
||||
public interface ITag {
|
||||
|
||||
/**
|
||||
* @return tag's name (e.g., "HEAD" / "HTML" / "FORM")
|
||||
*/
|
||||
public String getName();
|
||||
|
||||
/**
|
||||
* Retrieves a specific attribute
|
||||
* @param name
|
||||
* @return null if there is no such attribute
|
||||
*/
|
||||
public Pair<String, Position> getAttributeByName(String name);
|
||||
|
||||
public Map<String, Pair<String, Position>> getAllAttributes();
|
||||
|
||||
/**
|
||||
* Returns the starting line number of the tag.
|
||||
* @return null if no known
|
||||
*/
|
||||
public Position getElementPosition();
|
||||
|
||||
public Position getContentPosition();
|
||||
}
|
||||
package com.ibm.wala.cast.js.html;
|
||||
|
||||
/******************************************************************************
|
||||
* Copyright (c) 2002 - 2011 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
|
||||
*****************************************************************************/
|
||||
import java.util.Map;
|
||||
|
||||
import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position;
|
||||
import com.ibm.wala.util.collections.Pair;
|
||||
|
||||
/**
|
||||
* @author danielk
|
||||
* Data structure representing an HTML tag, with its attributes and content. Used by the HTML parser when calling the callback.
|
||||
*/
|
||||
public interface ITag {
|
||||
|
||||
/**
|
||||
* @return tag's name (e.g., "HEAD" / "HTML" / "FORM")
|
||||
*/
|
||||
public String getName();
|
||||
|
||||
/**
|
||||
* Retrieves a specific attribute
|
||||
* @param name
|
||||
* @return null if there is no such attribute
|
||||
*/
|
||||
public Pair<String, Position> getAttributeByName(String name);
|
||||
|
||||
public Map<String, Pair<String, Position>> getAllAttributes();
|
||||
|
||||
/**
|
||||
* Returns the starting line number of the tag.
|
||||
* @return null if no known
|
||||
*/
|
||||
public Position getElementPosition();
|
||||
|
||||
public Position getContentPosition();
|
||||
}
|
||||
|
||||
@ -1,36 +1,36 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) 2002 - 2011 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.cast.js.html;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
/**
|
||||
* Used for handling resources that were copied from the web to local files (and still contain references to the web)
|
||||
* @author yinnonh
|
||||
* @author danielk
|
||||
*
|
||||
*/
|
||||
public interface IUrlResolver {
|
||||
/**
|
||||
* From Internet to local
|
||||
* @param input
|
||||
* @return
|
||||
*/
|
||||
public URL resolve(URL input);
|
||||
|
||||
/**
|
||||
* From local to Internet
|
||||
* @param input
|
||||
* @return
|
||||
*/
|
||||
public URL deResolve(URL input);
|
||||
|
||||
}
|
||||
/******************************************************************************
|
||||
* Copyright (c) 2002 - 2011 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.cast.js.html;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
/**
|
||||
* Used for handling resources that were copied from the web to local files (and still contain references to the web)
|
||||
* @author yinnonh
|
||||
* @author danielk
|
||||
*
|
||||
*/
|
||||
public interface IUrlResolver {
|
||||
/**
|
||||
* From Internet to local
|
||||
* @param input
|
||||
* @return
|
||||
*/
|
||||
public URL resolve(URL input);
|
||||
|
||||
/**
|
||||
* From local to Internet
|
||||
* @param input
|
||||
* @return
|
||||
*/
|
||||
public URL deResolve(URL input);
|
||||
|
||||
}
|
||||
|
||||
@ -1,25 +1,25 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) 2002 - 2011 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.cast.js.html;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
public class IdentityUrlResolver implements IUrlResolver{
|
||||
|
||||
public URL resolve(URL input) {
|
||||
return input;
|
||||
}
|
||||
|
||||
public URL deResolve(URL input) {
|
||||
return input;
|
||||
}
|
||||
|
||||
}
|
||||
/******************************************************************************
|
||||
* Copyright (c) 2002 - 2011 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.cast.js.html;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
public class IdentityUrlResolver implements IUrlResolver{
|
||||
|
||||
public URL resolve(URL input) {
|
||||
return input;
|
||||
}
|
||||
|
||||
public URL deResolve(URL input) {
|
||||
return input;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,32 +1,32 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) 2002 - 2011 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.cast.js.html;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Extracts scripts from a given URL of an HTML. Retrieves also attached js files.
|
||||
* Provides file and line mapping for each extracted SourceFileModule back to the original file and line number.
|
||||
*
|
||||
* @author yinnonh
|
||||
* @author danielk
|
||||
*/
|
||||
public abstract class JSSourceExtractor {
|
||||
|
||||
public static boolean DELETE_UPON_EXIT = false;
|
||||
|
||||
public static boolean USE_TEMP_NAME = false;
|
||||
|
||||
public abstract Set<MappedSourceModule> extractSources(URL entrypointUrl, IHtmlParser htmlParser, IUrlResolver urlResolver) throws IOException;
|
||||
|
||||
}
|
||||
/******************************************************************************
|
||||
* Copyright (c) 2002 - 2011 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.cast.js.html;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Extracts scripts from a given URL of an HTML. Retrieves also attached js files.
|
||||
* Provides file and line mapping for each extracted SourceFileModule back to the original file and line number.
|
||||
*
|
||||
* @author yinnonh
|
||||
* @author danielk
|
||||
*/
|
||||
public abstract class JSSourceExtractor {
|
||||
|
||||
public static boolean DELETE_UPON_EXIT = false;
|
||||
|
||||
public static boolean USE_TEMP_NAME = false;
|
||||
|
||||
public abstract Set<MappedSourceModule> extractSources(URL entrypointUrl, IHtmlParser htmlParser, IUrlResolver urlResolver) throws IOException;
|
||||
|
||||
}
|
||||
|
||||
@ -1,100 +1,100 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) 2002 - 2011 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.cast.js.html;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.net.URL;
|
||||
|
||||
import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position;
|
||||
|
||||
public class SourceRegion {
|
||||
|
||||
private final StringBuilder source = new StringBuilder();
|
||||
private FileMapping fileMapping;
|
||||
private int currentLine = 1;
|
||||
|
||||
public SourceRegion() {
|
||||
}
|
||||
|
||||
public void print(String text, Position originalPos, URL url){
|
||||
int startOffset = source.length();
|
||||
source.append(text);
|
||||
int endOffset = source.length();
|
||||
|
||||
int numberOfLineDrops = getNumberOfLineDrops(text);
|
||||
|
||||
if (originalPos != null) {
|
||||
RangeFileMapping map = new RangeFileMapping(startOffset, endOffset, currentLine, currentLine+numberOfLineDrops, originalPos, url);
|
||||
if (fileMapping == null) {
|
||||
fileMapping = map;
|
||||
} else {
|
||||
fileMapping = new CompositeFileMapping(map, fileMapping);
|
||||
}
|
||||
}
|
||||
|
||||
currentLine += numberOfLineDrops;
|
||||
}
|
||||
|
||||
public void println(String text, Position originalPos, URL url){
|
||||
print(text + "\n", originalPos, url);
|
||||
}
|
||||
|
||||
public void print(String text){
|
||||
print(text, null, null);
|
||||
}
|
||||
|
||||
public void println(String text){
|
||||
print(text + "\n");
|
||||
}
|
||||
|
||||
public FileMapping writeToFile(PrintStream ps){
|
||||
ps.print(source.toString());
|
||||
return fileMapping;
|
||||
}
|
||||
|
||||
public void write(SourceRegion otherRegion){
|
||||
int rangeStart = source.length();
|
||||
String text = otherRegion.source.toString();
|
||||
source.append(text);
|
||||
int rangeEnd = source.length();
|
||||
|
||||
int numberOfLineDrops = getNumberOfLineDrops(text);
|
||||
|
||||
if (otherRegion.fileMapping != null) {
|
||||
FileMapping map = new NestedRangeMapping(rangeStart, rangeEnd, currentLine, currentLine+numberOfLineDrops, otherRegion.fileMapping);
|
||||
if (fileMapping == null) {
|
||||
fileMapping = map;
|
||||
} else {
|
||||
fileMapping = new CompositeFileMapping(map, fileMapping);
|
||||
}
|
||||
}
|
||||
|
||||
currentLine += numberOfLineDrops;
|
||||
}
|
||||
|
||||
public void dump(PrintStream ps){
|
||||
ps.println(source.toString());
|
||||
}
|
||||
|
||||
private static int getNumberOfLineDrops(String text) {
|
||||
int ret = 0;
|
||||
int i = text.indexOf('\n');
|
||||
while (i != -1){
|
||||
ret++;
|
||||
if (i < text.length()-1){
|
||||
i = text.indexOf('\n', i + 1);
|
||||
} else {
|
||||
break; // CR was the the last character.
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
/******************************************************************************
|
||||
* Copyright (c) 2002 - 2011 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.cast.js.html;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.net.URL;
|
||||
|
||||
import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position;
|
||||
|
||||
public class SourceRegion {
|
||||
|
||||
private final StringBuilder source = new StringBuilder();
|
||||
private FileMapping fileMapping;
|
||||
private int currentLine = 1;
|
||||
|
||||
public SourceRegion() {
|
||||
}
|
||||
|
||||
public void print(String text, Position originalPos, URL url){
|
||||
int startOffset = source.length();
|
||||
source.append(text);
|
||||
int endOffset = source.length();
|
||||
|
||||
int numberOfLineDrops = getNumberOfLineDrops(text);
|
||||
|
||||
if (originalPos != null) {
|
||||
RangeFileMapping map = new RangeFileMapping(startOffset, endOffset, currentLine, currentLine+numberOfLineDrops, originalPos, url);
|
||||
if (fileMapping == null) {
|
||||
fileMapping = map;
|
||||
} else {
|
||||
fileMapping = new CompositeFileMapping(map, fileMapping);
|
||||
}
|
||||
}
|
||||
|
||||
currentLine += numberOfLineDrops;
|
||||
}
|
||||
|
||||
public void println(String text, Position originalPos, URL url){
|
||||
print(text + "\n", originalPos, url);
|
||||
}
|
||||
|
||||
public void print(String text){
|
||||
print(text, null, null);
|
||||
}
|
||||
|
||||
public void println(String text){
|
||||
print(text + "\n");
|
||||
}
|
||||
|
||||
public FileMapping writeToFile(PrintStream ps){
|
||||
ps.print(source.toString());
|
||||
return fileMapping;
|
||||
}
|
||||
|
||||
public void write(SourceRegion otherRegion){
|
||||
int rangeStart = source.length();
|
||||
String text = otherRegion.source.toString();
|
||||
source.append(text);
|
||||
int rangeEnd = source.length();
|
||||
|
||||
int numberOfLineDrops = getNumberOfLineDrops(text);
|
||||
|
||||
if (otherRegion.fileMapping != null) {
|
||||
FileMapping map = new NestedRangeMapping(rangeStart, rangeEnd, currentLine, currentLine+numberOfLineDrops, otherRegion.fileMapping);
|
||||
if (fileMapping == null) {
|
||||
fileMapping = map;
|
||||
} else {
|
||||
fileMapping = new CompositeFileMapping(map, fileMapping);
|
||||
}
|
||||
}
|
||||
|
||||
currentLine += numberOfLineDrops;
|
||||
}
|
||||
|
||||
public void dump(PrintStream ps){
|
||||
ps.println(source.toString());
|
||||
}
|
||||
|
||||
private static int getNumberOfLineDrops(String text) {
|
||||
int ret = 0;
|
||||
int i = text.indexOf('\n');
|
||||
while (i != -1){
|
||||
ret++;
|
||||
if (i < text.length()-1){
|
||||
i = text.indexOf('\n', i + 1);
|
||||
} else {
|
||||
break; // CR was the the last character.
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,122 +1,122 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) 2002 - 2011 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.cast.js.html;
|
||||
|
||||
/**
|
||||
http://www.unicode.org/unicode/faq/utf_bom.html
|
||||
BOMs:
|
||||
00 00 FE FF = UTF-32, big-endian
|
||||
FF FE 00 00 = UTF-32, little-endian
|
||||
FE FF = UTF-16, big-endian
|
||||
FF FE = UTF-16, little-endian
|
||||
EF BB BF = UTF-8
|
||||
|
||||
Win2k Notepad:
|
||||
Unicode format = UTF-16LE
|
||||
***/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.PushbackInputStream;
|
||||
import java.io.Reader;
|
||||
|
||||
/**
|
||||
* Generic unicode textreader, which will use BOM mark to identify the encoding to be used.
|
||||
*/
|
||||
public class UnicodeReader extends Reader {
|
||||
PushbackInputStream internalIn;
|
||||
|
||||
InputStreamReader internalIn2 = null;
|
||||
|
||||
String defaultEnc;
|
||||
|
||||
private static final int BOM_SIZE = 6;
|
||||
|
||||
/*
|
||||
* Default encoding is used only if BOM is not found. If defaultEncoding is NULL then systemdefault is used.
|
||||
*/
|
||||
public UnicodeReader(InputStream in, String defaultEnc) {
|
||||
internalIn = new PushbackInputStream(in, BOM_SIZE);
|
||||
this.defaultEnc = defaultEnc;
|
||||
}
|
||||
|
||||
public String getDefaultEncoding() {
|
||||
return defaultEnc;
|
||||
}
|
||||
|
||||
public String getEncoding() {
|
||||
if (internalIn2 == null)
|
||||
return null;
|
||||
return internalIn2.getEncoding();
|
||||
}
|
||||
|
||||
/**
|
||||
* Read-ahead four bytes and check for BOM marks. Extra bytes are unread back to the stream, only BOM bytes are skipped.
|
||||
*/
|
||||
protected void init() throws IOException {
|
||||
if (internalIn2 != null)
|
||||
return;
|
||||
|
||||
String encoding;
|
||||
byte bom[] = new byte[BOM_SIZE];
|
||||
int n, unread;
|
||||
n = internalIn.read(bom, 0, bom.length);
|
||||
|
||||
if ((bom[0] == (byte) 0xEF) && (bom[1] == (byte) 0xBB) && (bom[2] == (byte) 0xBF) && (bom[3] == (byte) 0xEF) && (bom[4] == (byte) 0xBB) && (bom[5] == (byte) 0xBF)) {
|
||||
encoding = "UTF-8";
|
||||
unread = n - 6;
|
||||
} else if ((bom[0] == (byte) 0xEF) && (bom[1] == (byte) 0xBB) && (bom[2] == (byte) 0xBF)) {
|
||||
encoding = "UTF-8";
|
||||
unread = n - 3;
|
||||
} else if ((bom[0] == (byte) 0xFE) && (bom[1] == (byte) 0xFF)) {
|
||||
encoding = "UTF-16BE";
|
||||
unread = n - 2;
|
||||
} else if ((bom[0] == (byte) 0xFF) && (bom[1] == (byte) 0xFE)) {
|
||||
encoding = "UTF-16LE";
|
||||
unread = n - 2;
|
||||
} else if ((bom[0] == (byte) 0x00) && (bom[1] == (byte) 0x00) && (bom[2] == (byte) 0xFE) && (bom[3] == (byte) 0xFF)) {
|
||||
encoding = "UTF-32BE";
|
||||
unread = n - 4;
|
||||
} else if ((bom[0] == (byte) 0xFF) && (bom[1] == (byte) 0xFE) && (bom[2] == (byte) 0x00) && (bom[3] == (byte) 0x00)) {
|
||||
encoding = "UTF-32LE";
|
||||
unread = n - 4;
|
||||
} else {
|
||||
// Unicode BOM mark not found, unread all bytes
|
||||
encoding = defaultEnc;
|
||||
unread = n;
|
||||
}
|
||||
// System.out.println("read=" + n + ", unread=" + unread);
|
||||
|
||||
if (unread > 0)
|
||||
internalIn.unread(bom, (n - unread), unread);
|
||||
else if (unread < -1)
|
||||
internalIn.unread(bom, 0, 0);
|
||||
|
||||
// Use given encoding
|
||||
if (encoding == null) {
|
||||
internalIn2 = new InputStreamReader(internalIn);
|
||||
} else {
|
||||
internalIn2 = new InputStreamReader(internalIn, encoding);
|
||||
}
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
init();
|
||||
internalIn2.close();
|
||||
}
|
||||
|
||||
public int read(char[] cbuf, int off, int len) throws IOException {
|
||||
init();
|
||||
return internalIn2.read(cbuf, off, len);
|
||||
}
|
||||
|
||||
}
|
||||
/******************************************************************************
|
||||
* Copyright (c) 2002 - 2011 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.cast.js.html;
|
||||
|
||||
/**
|
||||
http://www.unicode.org/unicode/faq/utf_bom.html
|
||||
BOMs:
|
||||
00 00 FE FF = UTF-32, big-endian
|
||||
FF FE 00 00 = UTF-32, little-endian
|
||||
FE FF = UTF-16, big-endian
|
||||
FF FE = UTF-16, little-endian
|
||||
EF BB BF = UTF-8
|
||||
|
||||
Win2k Notepad:
|
||||
Unicode format = UTF-16LE
|
||||
***/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.PushbackInputStream;
|
||||
import java.io.Reader;
|
||||
|
||||
/**
|
||||
* Generic unicode textreader, which will use BOM mark to identify the encoding to be used.
|
||||
*/
|
||||
public class UnicodeReader extends Reader {
|
||||
PushbackInputStream internalIn;
|
||||
|
||||
InputStreamReader internalIn2 = null;
|
||||
|
||||
String defaultEnc;
|
||||
|
||||
private static final int BOM_SIZE = 6;
|
||||
|
||||
/*
|
||||
* Default encoding is used only if BOM is not found. If defaultEncoding is NULL then systemdefault is used.
|
||||
*/
|
||||
public UnicodeReader(InputStream in, String defaultEnc) {
|
||||
internalIn = new PushbackInputStream(in, BOM_SIZE);
|
||||
this.defaultEnc = defaultEnc;
|
||||
}
|
||||
|
||||
public String getDefaultEncoding() {
|
||||
return defaultEnc;
|
||||
}
|
||||
|
||||
public String getEncoding() {
|
||||
if (internalIn2 == null)
|
||||
return null;
|
||||
return internalIn2.getEncoding();
|
||||
}
|
||||
|
||||
/**
|
||||
* Read-ahead four bytes and check for BOM marks. Extra bytes are unread back to the stream, only BOM bytes are skipped.
|
||||
*/
|
||||
protected void init() throws IOException {
|
||||
if (internalIn2 != null)
|
||||
return;
|
||||
|
||||
String encoding;
|
||||
byte bom[] = new byte[BOM_SIZE];
|
||||
int n, unread;
|
||||
n = internalIn.read(bom, 0, bom.length);
|
||||
|
||||
if ((bom[0] == (byte) 0xEF) && (bom[1] == (byte) 0xBB) && (bom[2] == (byte) 0xBF) && (bom[3] == (byte) 0xEF) && (bom[4] == (byte) 0xBB) && (bom[5] == (byte) 0xBF)) {
|
||||
encoding = "UTF-8";
|
||||
unread = n - 6;
|
||||
} else if ((bom[0] == (byte) 0xEF) && (bom[1] == (byte) 0xBB) && (bom[2] == (byte) 0xBF)) {
|
||||
encoding = "UTF-8";
|
||||
unread = n - 3;
|
||||
} else if ((bom[0] == (byte) 0xFE) && (bom[1] == (byte) 0xFF)) {
|
||||
encoding = "UTF-16BE";
|
||||
unread = n - 2;
|
||||
} else if ((bom[0] == (byte) 0xFF) && (bom[1] == (byte) 0xFE)) {
|
||||
encoding = "UTF-16LE";
|
||||
unread = n - 2;
|
||||
} else if ((bom[0] == (byte) 0x00) && (bom[1] == (byte) 0x00) && (bom[2] == (byte) 0xFE) && (bom[3] == (byte) 0xFF)) {
|
||||
encoding = "UTF-32BE";
|
||||
unread = n - 4;
|
||||
} else if ((bom[0] == (byte) 0xFF) && (bom[1] == (byte) 0xFE) && (bom[2] == (byte) 0x00) && (bom[3] == (byte) 0x00)) {
|
||||
encoding = "UTF-32LE";
|
||||
unread = n - 4;
|
||||
} else {
|
||||
// Unicode BOM mark not found, unread all bytes
|
||||
encoding = defaultEnc;
|
||||
unread = n;
|
||||
}
|
||||
// System.out.println("read=" + n + ", unread=" + unread);
|
||||
|
||||
if (unread > 0)
|
||||
internalIn.unread(bom, (n - unread), unread);
|
||||
else if (unread < -1)
|
||||
internalIn.unread(bom, 0, 0);
|
||||
|
||||
// Use given encoding
|
||||
if (encoding == null) {
|
||||
internalIn2 = new InputStreamReader(internalIn);
|
||||
} else {
|
||||
internalIn2 = new InputStreamReader(internalIn, encoding);
|
||||
}
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
init();
|
||||
internalIn2.close();
|
||||
}
|
||||
|
||||
public int read(char[] cbuf, int off, int len) throws IOException {
|
||||
init();
|
||||
return internalIn2.read(cbuf, off, len);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,78 +1,78 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) 2002 - 2011 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.cast.js.html;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
|
||||
public class UrlManipulator {
|
||||
|
||||
|
||||
/**
|
||||
* @param urlFound the link as appear
|
||||
* @param context the URL in which the link appeared
|
||||
* @return
|
||||
* @throws MalformedURLException
|
||||
*/
|
||||
public static URL relativeToAbsoluteUrl(String urlFound, URL context) throws MalformedURLException {
|
||||
urlFound = urlFound.replace("\\", "/").toLowerCase();
|
||||
|
||||
URL absoluteUrl;
|
||||
if (!isAbsoluteUrl(urlFound)) {
|
||||
if (urlFound.startsWith("//")) {
|
||||
//create URL taking only the protocol from the context
|
||||
String origHostAndPath = urlFound.substring(2);// removing "//"
|
||||
String host;
|
||||
String path;
|
||||
int indexOf = origHostAndPath.indexOf("/");
|
||||
if (indexOf > 0) {
|
||||
host = origHostAndPath.substring(0, indexOf);
|
||||
path = origHostAndPath.substring(indexOf);
|
||||
} else {
|
||||
host = origHostAndPath;
|
||||
path = "";
|
||||
}
|
||||
absoluteUrl = new URL(context.getProtocol(), host, path);
|
||||
} else if (urlFound.startsWith("/")) {
|
||||
//create URL taking the protocol and the host from the context
|
||||
absoluteUrl = new URL(context.getProtocol(), context.getHost(), urlFound);
|
||||
} else {
|
||||
//"concat" URL to context
|
||||
int backDir = 0; // removing directories due to "../"
|
||||
while(urlFound.startsWith("../")){
|
||||
urlFound = urlFound.substring(3);
|
||||
backDir++;
|
||||
}
|
||||
StringBuilder contextPath = new StringBuilder();
|
||||
String path = context.getPath().replace("\\", "/");
|
||||
boolean isContextDirectory = path.endsWith("/");
|
||||
String[] split = path.split("/");
|
||||
// we are also removing last element in case of a directory
|
||||
int rightTrimFromPath = (isContextDirectory ? 0 : 1) + backDir;
|
||||
|
||||
for (int i = 0; i < split.length - rightTrimFromPath; i++) {
|
||||
contextPath.append(split[i]);
|
||||
contextPath.append("/");
|
||||
}
|
||||
absoluteUrl = new URL(context.getProtocol(), context.getHost(), contextPath.toString() + urlFound);
|
||||
}
|
||||
} else{
|
||||
absoluteUrl = new URL(urlFound);
|
||||
}
|
||||
return absoluteUrl;
|
||||
}
|
||||
|
||||
private static boolean isAbsoluteUrl(String orig) {
|
||||
return orig.startsWith("http");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
/******************************************************************************
|
||||
* Copyright (c) 2002 - 2011 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.cast.js.html;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
|
||||
public class UrlManipulator {
|
||||
|
||||
|
||||
/**
|
||||
* @param urlFound the link as appear
|
||||
* @param context the URL in which the link appeared
|
||||
* @return
|
||||
* @throws MalformedURLException
|
||||
*/
|
||||
public static URL relativeToAbsoluteUrl(String urlFound, URL context) throws MalformedURLException {
|
||||
urlFound = urlFound.replace("\\", "/").toLowerCase();
|
||||
|
||||
URL absoluteUrl;
|
||||
if (!isAbsoluteUrl(urlFound)) {
|
||||
if (urlFound.startsWith("//")) {
|
||||
//create URL taking only the protocol from the context
|
||||
String origHostAndPath = urlFound.substring(2);// removing "//"
|
||||
String host;
|
||||
String path;
|
||||
int indexOf = origHostAndPath.indexOf("/");
|
||||
if (indexOf > 0) {
|
||||
host = origHostAndPath.substring(0, indexOf);
|
||||
path = origHostAndPath.substring(indexOf);
|
||||
} else {
|
||||
host = origHostAndPath;
|
||||
path = "";
|
||||
}
|
||||
absoluteUrl = new URL(context.getProtocol(), host, path);
|
||||
} else if (urlFound.startsWith("/")) {
|
||||
//create URL taking the protocol and the host from the context
|
||||
absoluteUrl = new URL(context.getProtocol(), context.getHost(), urlFound);
|
||||
} else {
|
||||
//"concat" URL to context
|
||||
int backDir = 0; // removing directories due to "../"
|
||||
while(urlFound.startsWith("../")){
|
||||
urlFound = urlFound.substring(3);
|
||||
backDir++;
|
||||
}
|
||||
StringBuilder contextPath = new StringBuilder();
|
||||
String path = context.getPath().replace("\\", "/");
|
||||
boolean isContextDirectory = path.endsWith("/");
|
||||
String[] split = path.split("/");
|
||||
// we are also removing last element in case of a directory
|
||||
int rightTrimFromPath = (isContextDirectory ? 0 : 1) + backDir;
|
||||
|
||||
for (int i = 0; i < split.length - rightTrimFromPath; i++) {
|
||||
contextPath.append(split[i]);
|
||||
contextPath.append("/");
|
||||
}
|
||||
absoluteUrl = new URL(context.getProtocol(), context.getHost(), contextPath.toString() + urlFound);
|
||||
}
|
||||
} else{
|
||||
absoluteUrl = new URL(urlFound);
|
||||
}
|
||||
return absoluteUrl;
|
||||
}
|
||||
|
||||
private static boolean isAbsoluteUrl(String orig) {
|
||||
return orig.startsWith("http");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -1,78 +1,78 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) 2002 - 2011 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.cast.js.html.jericho;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import net.htmlparser.jericho.Config;
|
||||
import net.htmlparser.jericho.Element;
|
||||
import net.htmlparser.jericho.LoggerProvider;
|
||||
import net.htmlparser.jericho.Source;
|
||||
|
||||
import com.ibm.wala.cast.js.html.IHtmlCallback;
|
||||
import com.ibm.wala.cast.js.html.IHtmlParser;
|
||||
|
||||
|
||||
/**
|
||||
* @author danielk
|
||||
* Uses the Jericho parser to go over the HTML
|
||||
*/
|
||||
public class JerichoHtmlParser implements IHtmlParser{
|
||||
static{
|
||||
Config.LoggerProvider = LoggerProvider.STDERR;
|
||||
}
|
||||
|
||||
public void parse(URL url, InputStream reader, IHtmlCallback callback, String fileName) {
|
||||
Parser parser = new Parser(callback, fileName);
|
||||
Source src;
|
||||
try {
|
||||
src = new Source(reader);
|
||||
List<Element> childElements = src.getChildElements();
|
||||
for (Iterator<Element> nodeIterator = childElements.iterator(); nodeIterator.hasNext();) {
|
||||
Element e = nodeIterator.next();
|
||||
parser.parse(e);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
System.err.println("Error parsing file: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @author danielk
|
||||
* Inner class does the actual traversal of the HTML using recursion
|
||||
*/
|
||||
private static class Parser {
|
||||
private final IHtmlCallback handler;
|
||||
private final String fileName;
|
||||
|
||||
public Parser(IHtmlCallback handler, String fileName) {
|
||||
this.handler = handler;
|
||||
this.fileName = fileName;
|
||||
}
|
||||
|
||||
private void parse(Element root) {
|
||||
JerichoTag tag = new JerichoTag(root, fileName);
|
||||
handler.handleStartTag(tag);
|
||||
handler.handleText(tag.getElementPosition(), tag.getBodyText().snd);
|
||||
List<Element> childElements = root.getChildElements();
|
||||
for (Iterator<Element> nodeIterator = childElements.iterator(); nodeIterator.hasNext();) {
|
||||
Element child = nodeIterator.next();
|
||||
parse(child);
|
||||
}
|
||||
handler.handleEndTag(tag);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
/******************************************************************************
|
||||
* Copyright (c) 2002 - 2011 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.cast.js.html.jericho;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import net.htmlparser.jericho.Config;
|
||||
import net.htmlparser.jericho.Element;
|
||||
import net.htmlparser.jericho.LoggerProvider;
|
||||
import net.htmlparser.jericho.Source;
|
||||
|
||||
import com.ibm.wala.cast.js.html.IHtmlCallback;
|
||||
import com.ibm.wala.cast.js.html.IHtmlParser;
|
||||
|
||||
|
||||
/**
|
||||
* @author danielk
|
||||
* Uses the Jericho parser to go over the HTML
|
||||
*/
|
||||
public class JerichoHtmlParser implements IHtmlParser{
|
||||
static{
|
||||
Config.LoggerProvider = LoggerProvider.STDERR;
|
||||
}
|
||||
|
||||
public void parse(URL url, InputStream reader, IHtmlCallback callback, String fileName) {
|
||||
Parser parser = new Parser(callback, fileName);
|
||||
Source src;
|
||||
try {
|
||||
src = new Source(reader);
|
||||
List<Element> childElements = src.getChildElements();
|
||||
for (Iterator<Element> nodeIterator = childElements.iterator(); nodeIterator.hasNext();) {
|
||||
Element e = nodeIterator.next();
|
||||
parser.parse(e);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
System.err.println("Error parsing file: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @author danielk
|
||||
* Inner class does the actual traversal of the HTML using recursion
|
||||
*/
|
||||
private static class Parser {
|
||||
private final IHtmlCallback handler;
|
||||
private final String fileName;
|
||||
|
||||
public Parser(IHtmlCallback handler, String fileName) {
|
||||
this.handler = handler;
|
||||
this.fileName = fileName;
|
||||
}
|
||||
|
||||
private void parse(Element root) {
|
||||
JerichoTag tag = new JerichoTag(root, fileName);
|
||||
handler.handleStartTag(tag);
|
||||
handler.handleText(tag.getElementPosition(), tag.getBodyText().snd);
|
||||
List<Element> childElements = root.getChildElements();
|
||||
for (Iterator<Element> nodeIterator = childElements.iterator(); nodeIterator.hasNext();) {
|
||||
Element child = nodeIterator.next();
|
||||
parse(child);
|
||||
}
|
||||
handler.handleEndTag(tag);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,147 +1,147 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) 2002 - 2011 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.cast.js.html.jericho;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.Map;
|
||||
|
||||
import net.htmlparser.jericho.Attribute;
|
||||
import net.htmlparser.jericho.Element;
|
||||
import net.htmlparser.jericho.Segment;
|
||||
|
||||
import com.ibm.wala.cast.js.html.ITag;
|
||||
import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position;
|
||||
import com.ibm.wala.cast.tree.impl.AbstractSourcePosition;
|
||||
import com.ibm.wala.util.collections.HashMapFactory;
|
||||
import com.ibm.wala.util.collections.Pair;
|
||||
|
||||
/**
|
||||
* ITag impel for Jericho generated tags
|
||||
* @author danielk
|
||||
*/
|
||||
public class JerichoTag implements ITag {
|
||||
|
||||
private final Element innerElement;
|
||||
private final String sourceFile;
|
||||
private Map<String, Pair<String, Position>> allAttributes = null;
|
||||
|
||||
public JerichoTag(Element root, String sourceFile) {
|
||||
this.innerElement = root;
|
||||
this.sourceFile = sourceFile;
|
||||
}
|
||||
|
||||
private Position getPosition(final Segment e) {
|
||||
return new AbstractSourcePosition() {
|
||||
|
||||
@Override
|
||||
public int getFirstLine() {
|
||||
return e.getSource().getRowColumnVector(e.getBegin()).getRow();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLastLine() {
|
||||
return e.getSource().getRowColumnVector(e.getEnd()).getRow();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFirstCol() {
|
||||
return e.getSource().getRowColumnVector(e.getBegin()).getColumn();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLastCol() {
|
||||
return e.getSource().getRowColumnVector(e.getEnd()).getColumn();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFirstOffset() {
|
||||
return e.getBegin();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLastOffset() {
|
||||
return e.getEnd();
|
||||
}
|
||||
|
||||
@Override
|
||||
public URL getURL() {
|
||||
try {
|
||||
return new URL("file://" + sourceFile);
|
||||
} catch (MalformedURLException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getInputStream() throws IOException {
|
||||
return new FileInputStream(sourceFile);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private Map<String, Pair<String, Position>> makeAllAttributes() {
|
||||
Map<String, Pair<String, Position>> result = HashMapFactory.make();
|
||||
if (innerElement.getStartTag().getAttributes() != null) {
|
||||
for (Attribute a : innerElement.getStartTag().getAttributes()) {
|
||||
result.put(
|
||||
a.getName().toLowerCase(),
|
||||
Pair.make(a.getValue(), getPosition(a.getValueSegment())));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public Map<String, Pair<String, Position>> getAllAttributes() {
|
||||
if (allAttributes == null) {
|
||||
allAttributes = makeAllAttributes();
|
||||
}
|
||||
return allAttributes;
|
||||
}
|
||||
|
||||
public Pair<String, Position> getAttributeByName(String name) {
|
||||
if (allAttributes == null) {
|
||||
allAttributes = makeAllAttributes();
|
||||
}
|
||||
return allAttributes.get(name.toLowerCase());
|
||||
}
|
||||
|
||||
public Pair<Integer, String> getBodyText() {
|
||||
Segment content = innerElement.getContent();
|
||||
Integer lineNum = innerElement.getSource().getRow(content.getBegin());
|
||||
String body = content.toString();
|
||||
return Pair.make(lineNum, body);
|
||||
}
|
||||
|
||||
public String getFilePath() {
|
||||
return sourceFile;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return innerElement.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return innerElement.toString();
|
||||
}
|
||||
|
||||
public Position getElementPosition() {
|
||||
return getPosition(innerElement);
|
||||
}
|
||||
|
||||
public Position getContentPosition() {
|
||||
return getPosition(innerElement.getContent());
|
||||
}
|
||||
}
|
||||
/******************************************************************************
|
||||
* Copyright (c) 2002 - 2011 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.cast.js.html.jericho;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.Map;
|
||||
|
||||
import net.htmlparser.jericho.Attribute;
|
||||
import net.htmlparser.jericho.Element;
|
||||
import net.htmlparser.jericho.Segment;
|
||||
|
||||
import com.ibm.wala.cast.js.html.ITag;
|
||||
import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position;
|
||||
import com.ibm.wala.cast.tree.impl.AbstractSourcePosition;
|
||||
import com.ibm.wala.util.collections.HashMapFactory;
|
||||
import com.ibm.wala.util.collections.Pair;
|
||||
|
||||
/**
|
||||
* ITag impel for Jericho generated tags
|
||||
* @author danielk
|
||||
*/
|
||||
public class JerichoTag implements ITag {
|
||||
|
||||
private final Element innerElement;
|
||||
private final String sourceFile;
|
||||
private Map<String, Pair<String, Position>> allAttributes = null;
|
||||
|
||||
public JerichoTag(Element root, String sourceFile) {
|
||||
this.innerElement = root;
|
||||
this.sourceFile = sourceFile;
|
||||
}
|
||||
|
||||
private Position getPosition(final Segment e) {
|
||||
return new AbstractSourcePosition() {
|
||||
|
||||
@Override
|
||||
public int getFirstLine() {
|
||||
return e.getSource().getRowColumnVector(e.getBegin()).getRow();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLastLine() {
|
||||
return e.getSource().getRowColumnVector(e.getEnd()).getRow();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFirstCol() {
|
||||
return e.getSource().getRowColumnVector(e.getBegin()).getColumn();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLastCol() {
|
||||
return e.getSource().getRowColumnVector(e.getEnd()).getColumn();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFirstOffset() {
|
||||
return e.getBegin();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLastOffset() {
|
||||
return e.getEnd();
|
||||
}
|
||||
|
||||
@Override
|
||||
public URL getURL() {
|
||||
try {
|
||||
return new URL("file://" + sourceFile);
|
||||
} catch (MalformedURLException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getInputStream() throws IOException {
|
||||
return new FileInputStream(sourceFile);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private Map<String, Pair<String, Position>> makeAllAttributes() {
|
||||
Map<String, Pair<String, Position>> result = HashMapFactory.make();
|
||||
if (innerElement.getStartTag().getAttributes() != null) {
|
||||
for (Attribute a : innerElement.getStartTag().getAttributes()) {
|
||||
result.put(
|
||||
a.getName().toLowerCase(),
|
||||
Pair.make(a.getValue(), getPosition(a.getValueSegment())));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public Map<String, Pair<String, Position>> getAllAttributes() {
|
||||
if (allAttributes == null) {
|
||||
allAttributes = makeAllAttributes();
|
||||
}
|
||||
return allAttributes;
|
||||
}
|
||||
|
||||
public Pair<String, Position> getAttributeByName(String name) {
|
||||
if (allAttributes == null) {
|
||||
allAttributes = makeAllAttributes();
|
||||
}
|
||||
return allAttributes.get(name.toLowerCase());
|
||||
}
|
||||
|
||||
public Pair<Integer, String> getBodyText() {
|
||||
Segment content = innerElement.getContent();
|
||||
Integer lineNum = innerElement.getSource().getRow(content.getBegin());
|
||||
String body = content.toString();
|
||||
return Pair.make(lineNum, body);
|
||||
}
|
||||
|
||||
public String getFilePath() {
|
||||
return sourceFile;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return innerElement.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return innerElement.toString();
|
||||
}
|
||||
|
||||
public Position getElementPosition() {
|
||||
return getPosition(innerElement);
|
||||
}
|
||||
|
||||
public Position getContentPosition() {
|
||||
return getPosition(innerElement.getContent());
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,198 +1,198 @@
|
||||
/******************************************************************************
|
||||
* 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.cast.ipa.callgraph;
|
||||
|
||||
import java.util.ConcurrentModificationException;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
import com.ibm.wala.cast.ir.cfg.AstInducedCFG;
|
||||
import com.ibm.wala.cast.ir.ssa.AstLexicalRead;
|
||||
import com.ibm.wala.cfg.InducedCFG;
|
||||
import com.ibm.wala.classLoader.CallSiteReference;
|
||||
import com.ibm.wala.classLoader.IClass;
|
||||
import com.ibm.wala.classLoader.IMethod;
|
||||
import com.ibm.wala.ipa.callgraph.AnalysisCache;
|
||||
import com.ibm.wala.ipa.callgraph.AnalysisOptions;
|
||||
import com.ibm.wala.ipa.callgraph.CGNode;
|
||||
import com.ibm.wala.ipa.callgraph.Context;
|
||||
import com.ibm.wala.ipa.callgraph.impl.AbstractRootMethod;
|
||||
import com.ibm.wala.ipa.callgraph.impl.Everywhere;
|
||||
import com.ibm.wala.ipa.callgraph.impl.ExplicitCallGraph;
|
||||
import com.ibm.wala.ipa.callgraph.impl.FakeRootMethod;
|
||||
import com.ibm.wala.ipa.cha.IClassHierarchy;
|
||||
import com.ibm.wala.ssa.DefUse;
|
||||
import com.ibm.wala.ssa.IR;
|
||||
import com.ibm.wala.ssa.SSAAbstractInvokeInstruction;
|
||||
import com.ibm.wala.ssa.SSAInstruction;
|
||||
import com.ibm.wala.types.MethodReference;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
import com.ibm.wala.util.CancelException;
|
||||
import com.ibm.wala.util.collections.HashSetFactory;
|
||||
import com.ibm.wala.util.functions.Function;
|
||||
|
||||
public class AstCallGraph extends ExplicitCallGraph {
|
||||
public AstCallGraph(IClassHierarchy cha, AnalysisOptions options, AnalysisCache cache) {
|
||||
super(cha, options, cache);
|
||||
}
|
||||
|
||||
public static class AstFakeRoot extends AbstractRootMethod {
|
||||
|
||||
public AstFakeRoot(MethodReference rootMethod, IClass declaringClass, IClassHierarchy cha, AnalysisOptions options, AnalysisCache cache) {
|
||||
super(rootMethod, declaringClass, cha, options, cache);
|
||||
}
|
||||
|
||||
public AstFakeRoot(MethodReference rootMethod, IClassHierarchy cha, AnalysisOptions options, AnalysisCache cache) {
|
||||
super(rootMethod, cha, options, cache);
|
||||
}
|
||||
|
||||
public InducedCFG makeControlFlowGraph(SSAInstruction[] statements) {
|
||||
return new AstInducedCFG(statements, this, Everywhere.EVERYWHERE);
|
||||
}
|
||||
|
||||
public AstLexicalRead addGlobalRead(TypeReference type, String name) {
|
||||
AstLexicalRead s = new AstLexicalRead(nextLocal++, null, name);
|
||||
statements.add(s);
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
public static abstract class ScriptFakeRoot extends AstFakeRoot {
|
||||
|
||||
public ScriptFakeRoot(MethodReference rootMethod, IClass declaringClass, IClassHierarchy cha, AnalysisOptions options, AnalysisCache cache) {
|
||||
super(rootMethod, declaringClass, cha, options, cache);
|
||||
}
|
||||
|
||||
public ScriptFakeRoot(MethodReference rootMethod, IClassHierarchy cha, AnalysisOptions options, AnalysisCache cache) {
|
||||
super(rootMethod, cha, options, cache);
|
||||
}
|
||||
|
||||
public abstract SSAAbstractInvokeInstruction addDirectCall(int functionVn, int[] argVns, CallSiteReference callSite);
|
||||
|
||||
}
|
||||
|
||||
public class AstCGNode extends ExplicitNode {
|
||||
private Set<Function<Object, Object>> callbacks;
|
||||
|
||||
private boolean lexicalScopingChanges = false;
|
||||
|
||||
private IR cachedIR;
|
||||
|
||||
private DefUse cachedDU;
|
||||
|
||||
private AstCGNode(IMethod method, Context context) {
|
||||
super(method, context);
|
||||
}
|
||||
|
||||
private void fireCallbacks() {
|
||||
if (callbacks != null) {
|
||||
boolean done = false;
|
||||
while (!done) {
|
||||
try {
|
||||
for (Iterator<Function<Object, Object>> x = callbacks.iterator(); x.hasNext();) {
|
||||
x.next().apply(null);
|
||||
}
|
||||
} catch (ConcurrentModificationException e) {
|
||||
done = false;
|
||||
continue;
|
||||
}
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasCallback(Function<Object, Object> callback) {
|
||||
return callbacks != null && callbacks.contains(callback);
|
||||
}
|
||||
|
||||
private boolean hasAllCallbacks(Set<Function<Object, Object>> callbacks) {
|
||||
return callbacks != null && callbacks.containsAll(callbacks);
|
||||
}
|
||||
|
||||
public void addCallback(Function<Object, Object> callback) {
|
||||
if (!hasCallback(callback)) {
|
||||
if (callbacks == null) {
|
||||
callbacks = HashSetFactory.make(1);
|
||||
}
|
||||
|
||||
callbacks.add(callback);
|
||||
|
||||
for (Iterator ps = getCallGraph().getPredNodes(this); ps.hasNext();) {
|
||||
((AstCGNode) ps.next()).addCallback(callback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void addAllCallbacks(Set<Function<Object, Object>> callback) {
|
||||
if (!hasAllCallbacks(callbacks)) {
|
||||
if (callbacks == null) {
|
||||
callbacks = HashSetFactory.make(1);
|
||||
}
|
||||
|
||||
callbacks.addAll(callback);
|
||||
|
||||
for (Iterator ps = getCallGraph().getPredNodes(this); ps.hasNext();) {
|
||||
((AstCGNode) ps.next()).addAllCallbacks(callback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setLexicallyMutatedIR(IR ir) {
|
||||
lexicalScopingChanges = true;
|
||||
cachedIR = ir;
|
||||
cachedDU = null;
|
||||
}
|
||||
|
||||
public void clearMutatedCache(CallSiteReference cs) {
|
||||
targets.remove(cs.getProgramCounter());
|
||||
}
|
||||
|
||||
public IR getLexicallyMutatedIR() {
|
||||
if (lexicalScopingChanges) {
|
||||
return cachedIR;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public DefUse getLexicallyMutatedDU() {
|
||||
if (lexicalScopingChanges) {
|
||||
if (cachedDU == null) {
|
||||
cachedDU = new DefUse(cachedIR);
|
||||
}
|
||||
return cachedDU;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean addTarget(CallSiteReference site, CGNode node) {
|
||||
if (super.addTarget(site, node)) {
|
||||
if (((AstCGNode) node).callbacks != null) {
|
||||
((AstCGNode) node).fireCallbacks();
|
||||
addAllCallbacks(((AstCGNode) node).callbacks);
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected ExplicitNode makeNode(IMethod method, Context context) {
|
||||
return new AstCGNode(method, context);
|
||||
}
|
||||
|
||||
protected CGNode makeFakeRootNode() throws CancelException {
|
||||
return findOrCreateNode(new AstFakeRoot(FakeRootMethod.rootMethod, cha, options, getAnalysisCache()), Everywhere.EVERYWHERE);
|
||||
}
|
||||
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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.cast.ipa.callgraph;
|
||||
|
||||
import java.util.ConcurrentModificationException;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
import com.ibm.wala.cast.ir.cfg.AstInducedCFG;
|
||||
import com.ibm.wala.cast.ir.ssa.AstLexicalRead;
|
||||
import com.ibm.wala.cfg.InducedCFG;
|
||||
import com.ibm.wala.classLoader.CallSiteReference;
|
||||
import com.ibm.wala.classLoader.IClass;
|
||||
import com.ibm.wala.classLoader.IMethod;
|
||||
import com.ibm.wala.ipa.callgraph.AnalysisCache;
|
||||
import com.ibm.wala.ipa.callgraph.AnalysisOptions;
|
||||
import com.ibm.wala.ipa.callgraph.CGNode;
|
||||
import com.ibm.wala.ipa.callgraph.Context;
|
||||
import com.ibm.wala.ipa.callgraph.impl.AbstractRootMethod;
|
||||
import com.ibm.wala.ipa.callgraph.impl.Everywhere;
|
||||
import com.ibm.wala.ipa.callgraph.impl.ExplicitCallGraph;
|
||||
import com.ibm.wala.ipa.callgraph.impl.FakeRootMethod;
|
||||
import com.ibm.wala.ipa.cha.IClassHierarchy;
|
||||
import com.ibm.wala.ssa.DefUse;
|
||||
import com.ibm.wala.ssa.IR;
|
||||
import com.ibm.wala.ssa.SSAAbstractInvokeInstruction;
|
||||
import com.ibm.wala.ssa.SSAInstruction;
|
||||
import com.ibm.wala.types.MethodReference;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
import com.ibm.wala.util.CancelException;
|
||||
import com.ibm.wala.util.collections.HashSetFactory;
|
||||
import com.ibm.wala.util.functions.Function;
|
||||
|
||||
public class AstCallGraph extends ExplicitCallGraph {
|
||||
public AstCallGraph(IClassHierarchy cha, AnalysisOptions options, AnalysisCache cache) {
|
||||
super(cha, options, cache);
|
||||
}
|
||||
|
||||
public static class AstFakeRoot extends AbstractRootMethod {
|
||||
|
||||
public AstFakeRoot(MethodReference rootMethod, IClass declaringClass, IClassHierarchy cha, AnalysisOptions options, AnalysisCache cache) {
|
||||
super(rootMethod, declaringClass, cha, options, cache);
|
||||
}
|
||||
|
||||
public AstFakeRoot(MethodReference rootMethod, IClassHierarchy cha, AnalysisOptions options, AnalysisCache cache) {
|
||||
super(rootMethod, cha, options, cache);
|
||||
}
|
||||
|
||||
public InducedCFG makeControlFlowGraph(SSAInstruction[] statements) {
|
||||
return new AstInducedCFG(statements, this, Everywhere.EVERYWHERE);
|
||||
}
|
||||
|
||||
public AstLexicalRead addGlobalRead(TypeReference type, String name) {
|
||||
AstLexicalRead s = new AstLexicalRead(nextLocal++, null, name);
|
||||
statements.add(s);
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
public static abstract class ScriptFakeRoot extends AstFakeRoot {
|
||||
|
||||
public ScriptFakeRoot(MethodReference rootMethod, IClass declaringClass, IClassHierarchy cha, AnalysisOptions options, AnalysisCache cache) {
|
||||
super(rootMethod, declaringClass, cha, options, cache);
|
||||
}
|
||||
|
||||
public ScriptFakeRoot(MethodReference rootMethod, IClassHierarchy cha, AnalysisOptions options, AnalysisCache cache) {
|
||||
super(rootMethod, cha, options, cache);
|
||||
}
|
||||
|
||||
public abstract SSAAbstractInvokeInstruction addDirectCall(int functionVn, int[] argVns, CallSiteReference callSite);
|
||||
|
||||
}
|
||||
|
||||
public class AstCGNode extends ExplicitNode {
|
||||
private Set<Function<Object, Object>> callbacks;
|
||||
|
||||
private boolean lexicalScopingChanges = false;
|
||||
|
||||
private IR cachedIR;
|
||||
|
||||
private DefUse cachedDU;
|
||||
|
||||
private AstCGNode(IMethod method, Context context) {
|
||||
super(method, context);
|
||||
}
|
||||
|
||||
private void fireCallbacks() {
|
||||
if (callbacks != null) {
|
||||
boolean done = false;
|
||||
while (!done) {
|
||||
try {
|
||||
for (Iterator<Function<Object, Object>> x = callbacks.iterator(); x.hasNext();) {
|
||||
x.next().apply(null);
|
||||
}
|
||||
} catch (ConcurrentModificationException e) {
|
||||
done = false;
|
||||
continue;
|
||||
}
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasCallback(Function<Object, Object> callback) {
|
||||
return callbacks != null && callbacks.contains(callback);
|
||||
}
|
||||
|
||||
private boolean hasAllCallbacks(Set<Function<Object, Object>> callbacks) {
|
||||
return callbacks != null && callbacks.containsAll(callbacks);
|
||||
}
|
||||
|
||||
public void addCallback(Function<Object, Object> callback) {
|
||||
if (!hasCallback(callback)) {
|
||||
if (callbacks == null) {
|
||||
callbacks = HashSetFactory.make(1);
|
||||
}
|
||||
|
||||
callbacks.add(callback);
|
||||
|
||||
for (Iterator ps = getCallGraph().getPredNodes(this); ps.hasNext();) {
|
||||
((AstCGNode) ps.next()).addCallback(callback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void addAllCallbacks(Set<Function<Object, Object>> callback) {
|
||||
if (!hasAllCallbacks(callbacks)) {
|
||||
if (callbacks == null) {
|
||||
callbacks = HashSetFactory.make(1);
|
||||
}
|
||||
|
||||
callbacks.addAll(callback);
|
||||
|
||||
for (Iterator ps = getCallGraph().getPredNodes(this); ps.hasNext();) {
|
||||
((AstCGNode) ps.next()).addAllCallbacks(callback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setLexicallyMutatedIR(IR ir) {
|
||||
lexicalScopingChanges = true;
|
||||
cachedIR = ir;
|
||||
cachedDU = null;
|
||||
}
|
||||
|
||||
public void clearMutatedCache(CallSiteReference cs) {
|
||||
targets.remove(cs.getProgramCounter());
|
||||
}
|
||||
|
||||
public IR getLexicallyMutatedIR() {
|
||||
if (lexicalScopingChanges) {
|
||||
return cachedIR;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public DefUse getLexicallyMutatedDU() {
|
||||
if (lexicalScopingChanges) {
|
||||
if (cachedDU == null) {
|
||||
cachedDU = new DefUse(cachedIR);
|
||||
}
|
||||
return cachedDU;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean addTarget(CallSiteReference site, CGNode node) {
|
||||
if (super.addTarget(site, node)) {
|
||||
if (((AstCGNode) node).callbacks != null) {
|
||||
((AstCGNode) node).fireCallbacks();
|
||||
addAllCallbacks(((AstCGNode) node).callbacks);
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected ExplicitNode makeNode(IMethod method, Context context) {
|
||||
return new AstCGNode(method, context);
|
||||
}
|
||||
|
||||
protected CGNode makeFakeRootNode() throws CancelException {
|
||||
return findOrCreateNode(new AstFakeRoot(FakeRootMethod.rootMethod, cha, options, getAnalysisCache()), Everywhere.EVERYWHERE);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,168 +1,168 @@
|
||||
/******************************************************************************
|
||||
* 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.cast.ipa.callgraph;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.ibm.wala.cast.ir.ssa.AstLexicalRead;
|
||||
import com.ibm.wala.cast.util.TargetLanguageSelector;
|
||||
import com.ibm.wala.classLoader.CallSiteReference;
|
||||
import com.ibm.wala.classLoader.IClass;
|
||||
import com.ibm.wala.classLoader.IMethod;
|
||||
import com.ibm.wala.ipa.callgraph.AnalysisCache;
|
||||
import com.ibm.wala.ipa.callgraph.AnalysisOptions;
|
||||
import com.ibm.wala.ipa.callgraph.CGNode;
|
||||
import com.ibm.wala.ipa.callgraph.impl.AbstractRootMethod;
|
||||
import com.ibm.wala.ipa.callgraph.impl.Everywhere;
|
||||
import com.ibm.wala.ipa.callgraph.impl.FakeRootMethod;
|
||||
import com.ibm.wala.ipa.cha.IClassHierarchy;
|
||||
import com.ibm.wala.shrikeBT.IInvokeInstruction;
|
||||
import com.ibm.wala.ssa.SSAAbstractInvokeInstruction;
|
||||
import com.ibm.wala.ssa.SSAInvokeInstruction;
|
||||
import com.ibm.wala.ssa.SSANewInstruction;
|
||||
import com.ibm.wala.types.FieldReference;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
import com.ibm.wala.util.CancelException;
|
||||
import com.ibm.wala.util.collections.HashMapFactory;
|
||||
import com.ibm.wala.util.collections.HashSetFactory;
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
import com.ibm.wala.util.strings.Atom;
|
||||
|
||||
/**
|
||||
* A CallGraph implementation adapted to work for graphs that contain code
|
||||
* entities from multiple languages, and hence multiple specialized forms of IR.
|
||||
* The root node delegates to one of several language-specific root nodes,
|
||||
* allowing each language to use its own specialized IR constructs for entry
|
||||
* points.
|
||||
*
|
||||
* @author Julian Dolby (dolby@us.ibm.com)
|
||||
*/
|
||||
public class CrossLanguageCallGraph extends AstCallGraph {
|
||||
|
||||
public CrossLanguageCallGraph(TargetLanguageSelector<AbstractRootMethod, CrossLanguageCallGraph> roots, IClassHierarchy cha,
|
||||
AnalysisOptions options, AnalysisCache cache) {
|
||||
super(cha, options, cache);
|
||||
this.roots = roots;
|
||||
}
|
||||
|
||||
private final TargetLanguageSelector<AbstractRootMethod, CrossLanguageCallGraph> roots;
|
||||
|
||||
private final Set<CGNode> languageRootNodes = HashSetFactory.make();
|
||||
|
||||
private final Map<Atom,IMethod> languageRoots = HashMapFactory.make();
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public AbstractRootMethod getLanguageRoot(Atom language){
|
||||
if (!languageRoots.containsKey(language)) {
|
||||
AbstractRootMethod languageRoot = roots.get(language, this);
|
||||
|
||||
CGNode languageRootNode = null;
|
||||
try {
|
||||
languageRootNode = findOrCreateNode(languageRoot, Everywhere.EVERYWHERE);
|
||||
} catch (CancelException e) {
|
||||
e.printStackTrace();
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
|
||||
languageRootNodes.add(languageRootNode);
|
||||
|
||||
CallSiteReference site = CallSiteReference.make(1, languageRoot.getReference(), IInvokeInstruction.Dispatch.STATIC);
|
||||
|
||||
CGNode fakeRootNode = getFakeRootNode();
|
||||
CrossLanguageFakeRoot fakeRootMethod = (CrossLanguageFakeRoot) fakeRootNode.getMethod();
|
||||
|
||||
site = fakeRootMethod.addInvocationInternal(new int[0], site).getCallSite();
|
||||
|
||||
fakeRootNode.addTarget(site, languageRootNode);
|
||||
|
||||
languageRoots.put(language, languageRoot);
|
||||
}
|
||||
|
||||
return (AbstractRootMethod) languageRoots.get(language);
|
||||
}
|
||||
|
||||
public class CrossLanguageFakeRoot extends ScriptFakeRoot {
|
||||
|
||||
public CrossLanguageFakeRoot(IClass declaringClass, IClassHierarchy cha, AnalysisOptions options, AnalysisCache cache) {
|
||||
super(FakeRootMethod.rootMethod, declaringClass, cha, options, cache);
|
||||
}
|
||||
|
||||
public CrossLanguageFakeRoot(IClassHierarchy cha, AnalysisOptions options, AnalysisCache cache) {
|
||||
super(FakeRootMethod.rootMethod, cha, options, cache);
|
||||
}
|
||||
|
||||
public int addPhi(TypeReference type, int[] values) {
|
||||
Atom language = type.getClassLoader().getLanguage();
|
||||
AbstractRootMethod root = getLanguageRoot(language);
|
||||
return root.addPhi(values);
|
||||
}
|
||||
|
||||
public int addGetInstance(FieldReference ref, int object) {
|
||||
TypeReference type = ref.getDeclaringClass();
|
||||
Atom language = type.getClassLoader().getLanguage();
|
||||
AbstractRootMethod root = getLanguageRoot(language);
|
||||
return root.addGetInstance(ref, object);
|
||||
}
|
||||
|
||||
public int addGetStatic(FieldReference ref) {
|
||||
TypeReference type = ref.getDeclaringClass();
|
||||
Atom language = type.getClassLoader().getLanguage();
|
||||
AbstractRootMethod root = getLanguageRoot(language);
|
||||
return root.addGetStatic(ref);
|
||||
}
|
||||
|
||||
public int addCheckcast(TypeReference[] type, int rv, boolean isPEI) {
|
||||
Atom language = type[0].getClassLoader().getLanguage();
|
||||
AbstractRootMethod root = getLanguageRoot(language);
|
||||
return root.addCheckcast(type, rv, isPEI);
|
||||
}
|
||||
|
||||
public SSANewInstruction addAllocation(TypeReference type) {
|
||||
Atom language = type.getClassLoader().getLanguage();
|
||||
AbstractRootMethod root = getLanguageRoot(language);
|
||||
return root.addAllocation(type);
|
||||
}
|
||||
|
||||
public SSAInvokeInstruction addInvocation(int[] params, CallSiteReference site) {
|
||||
TypeReference type = site.getDeclaredTarget().getDeclaringClass();
|
||||
Atom language = type.getClassLoader().getLanguage();
|
||||
AbstractRootMethod root = getLanguageRoot(language);
|
||||
return root.addInvocation(params, site);
|
||||
}
|
||||
|
||||
public SSAInvokeInstruction addInvocationInternal(int[] params, CallSiteReference site) {
|
||||
return super.addInvocation(params, site);
|
||||
}
|
||||
|
||||
public AstLexicalRead addGlobalRead(TypeReference type, String name) {
|
||||
Atom language = type.getClassLoader().getLanguage();
|
||||
AbstractRootMethod root = getLanguageRoot(language);
|
||||
return ((AstFakeRoot) root).addGlobalRead(type, name);
|
||||
}
|
||||
|
||||
public SSAAbstractInvokeInstruction addDirectCall(int functionVn, int[] argVns, CallSiteReference callSite) {
|
||||
TypeReference type = callSite.getDeclaredTarget().getDeclaringClass();
|
||||
Atom language = type.getClassLoader().getLanguage();
|
||||
AbstractRootMethod root = getLanguageRoot(language);
|
||||
return ((ScriptFakeRoot) root).addDirectCall(functionVn, argVns, callSite);
|
||||
}
|
||||
}
|
||||
|
||||
Iterator getLanguageRoots() {
|
||||
return languageRootNodes.iterator();
|
||||
}
|
||||
|
||||
protected CGNode makeFakeRootNode() throws CancelException {
|
||||
return findOrCreateNode(new CrossLanguageFakeRoot(cha, options, getAnalysisCache()), Everywhere.EVERYWHERE);
|
||||
}
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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.cast.ipa.callgraph;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.ibm.wala.cast.ir.ssa.AstLexicalRead;
|
||||
import com.ibm.wala.cast.util.TargetLanguageSelector;
|
||||
import com.ibm.wala.classLoader.CallSiteReference;
|
||||
import com.ibm.wala.classLoader.IClass;
|
||||
import com.ibm.wala.classLoader.IMethod;
|
||||
import com.ibm.wala.ipa.callgraph.AnalysisCache;
|
||||
import com.ibm.wala.ipa.callgraph.AnalysisOptions;
|
||||
import com.ibm.wala.ipa.callgraph.CGNode;
|
||||
import com.ibm.wala.ipa.callgraph.impl.AbstractRootMethod;
|
||||
import com.ibm.wala.ipa.callgraph.impl.Everywhere;
|
||||
import com.ibm.wala.ipa.callgraph.impl.FakeRootMethod;
|
||||
import com.ibm.wala.ipa.cha.IClassHierarchy;
|
||||
import com.ibm.wala.shrikeBT.IInvokeInstruction;
|
||||
import com.ibm.wala.ssa.SSAAbstractInvokeInstruction;
|
||||
import com.ibm.wala.ssa.SSAInvokeInstruction;
|
||||
import com.ibm.wala.ssa.SSANewInstruction;
|
||||
import com.ibm.wala.types.FieldReference;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
import com.ibm.wala.util.CancelException;
|
||||
import com.ibm.wala.util.collections.HashMapFactory;
|
||||
import com.ibm.wala.util.collections.HashSetFactory;
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
import com.ibm.wala.util.strings.Atom;
|
||||
|
||||
/**
|
||||
* A CallGraph implementation adapted to work for graphs that contain code
|
||||
* entities from multiple languages, and hence multiple specialized forms of IR.
|
||||
* The root node delegates to one of several language-specific root nodes,
|
||||
* allowing each language to use its own specialized IR constructs for entry
|
||||
* points.
|
||||
*
|
||||
* @author Julian Dolby (dolby@us.ibm.com)
|
||||
*/
|
||||
public class CrossLanguageCallGraph extends AstCallGraph {
|
||||
|
||||
public CrossLanguageCallGraph(TargetLanguageSelector<AbstractRootMethod, CrossLanguageCallGraph> roots, IClassHierarchy cha,
|
||||
AnalysisOptions options, AnalysisCache cache) {
|
||||
super(cha, options, cache);
|
||||
this.roots = roots;
|
||||
}
|
||||
|
||||
private final TargetLanguageSelector<AbstractRootMethod, CrossLanguageCallGraph> roots;
|
||||
|
||||
private final Set<CGNode> languageRootNodes = HashSetFactory.make();
|
||||
|
||||
private final Map<Atom,IMethod> languageRoots = HashMapFactory.make();
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public AbstractRootMethod getLanguageRoot(Atom language){
|
||||
if (!languageRoots.containsKey(language)) {
|
||||
AbstractRootMethod languageRoot = roots.get(language, this);
|
||||
|
||||
CGNode languageRootNode = null;
|
||||
try {
|
||||
languageRootNode = findOrCreateNode(languageRoot, Everywhere.EVERYWHERE);
|
||||
} catch (CancelException e) {
|
||||
e.printStackTrace();
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
|
||||
languageRootNodes.add(languageRootNode);
|
||||
|
||||
CallSiteReference site = CallSiteReference.make(1, languageRoot.getReference(), IInvokeInstruction.Dispatch.STATIC);
|
||||
|
||||
CGNode fakeRootNode = getFakeRootNode();
|
||||
CrossLanguageFakeRoot fakeRootMethod = (CrossLanguageFakeRoot) fakeRootNode.getMethod();
|
||||
|
||||
site = fakeRootMethod.addInvocationInternal(new int[0], site).getCallSite();
|
||||
|
||||
fakeRootNode.addTarget(site, languageRootNode);
|
||||
|
||||
languageRoots.put(language, languageRoot);
|
||||
}
|
||||
|
||||
return (AbstractRootMethod) languageRoots.get(language);
|
||||
}
|
||||
|
||||
public class CrossLanguageFakeRoot extends ScriptFakeRoot {
|
||||
|
||||
public CrossLanguageFakeRoot(IClass declaringClass, IClassHierarchy cha, AnalysisOptions options, AnalysisCache cache) {
|
||||
super(FakeRootMethod.rootMethod, declaringClass, cha, options, cache);
|
||||
}
|
||||
|
||||
public CrossLanguageFakeRoot(IClassHierarchy cha, AnalysisOptions options, AnalysisCache cache) {
|
||||
super(FakeRootMethod.rootMethod, cha, options, cache);
|
||||
}
|
||||
|
||||
public int addPhi(TypeReference type, int[] values) {
|
||||
Atom language = type.getClassLoader().getLanguage();
|
||||
AbstractRootMethod root = getLanguageRoot(language);
|
||||
return root.addPhi(values);
|
||||
}
|
||||
|
||||
public int addGetInstance(FieldReference ref, int object) {
|
||||
TypeReference type = ref.getDeclaringClass();
|
||||
Atom language = type.getClassLoader().getLanguage();
|
||||
AbstractRootMethod root = getLanguageRoot(language);
|
||||
return root.addGetInstance(ref, object);
|
||||
}
|
||||
|
||||
public int addGetStatic(FieldReference ref) {
|
||||
TypeReference type = ref.getDeclaringClass();
|
||||
Atom language = type.getClassLoader().getLanguage();
|
||||
AbstractRootMethod root = getLanguageRoot(language);
|
||||
return root.addGetStatic(ref);
|
||||
}
|
||||
|
||||
public int addCheckcast(TypeReference[] type, int rv, boolean isPEI) {
|
||||
Atom language = type[0].getClassLoader().getLanguage();
|
||||
AbstractRootMethod root = getLanguageRoot(language);
|
||||
return root.addCheckcast(type, rv, isPEI);
|
||||
}
|
||||
|
||||
public SSANewInstruction addAllocation(TypeReference type) {
|
||||
Atom language = type.getClassLoader().getLanguage();
|
||||
AbstractRootMethod root = getLanguageRoot(language);
|
||||
return root.addAllocation(type);
|
||||
}
|
||||
|
||||
public SSAInvokeInstruction addInvocation(int[] params, CallSiteReference site) {
|
||||
TypeReference type = site.getDeclaredTarget().getDeclaringClass();
|
||||
Atom language = type.getClassLoader().getLanguage();
|
||||
AbstractRootMethod root = getLanguageRoot(language);
|
||||
return root.addInvocation(params, site);
|
||||
}
|
||||
|
||||
public SSAInvokeInstruction addInvocationInternal(int[] params, CallSiteReference site) {
|
||||
return super.addInvocation(params, site);
|
||||
}
|
||||
|
||||
public AstLexicalRead addGlobalRead(TypeReference type, String name) {
|
||||
Atom language = type.getClassLoader().getLanguage();
|
||||
AbstractRootMethod root = getLanguageRoot(language);
|
||||
return ((AstFakeRoot) root).addGlobalRead(type, name);
|
||||
}
|
||||
|
||||
public SSAAbstractInvokeInstruction addDirectCall(int functionVn, int[] argVns, CallSiteReference callSite) {
|
||||
TypeReference type = callSite.getDeclaredTarget().getDeclaringClass();
|
||||
Atom language = type.getClassLoader().getLanguage();
|
||||
AbstractRootMethod root = getLanguageRoot(language);
|
||||
return ((ScriptFakeRoot) root).addDirectCall(functionVn, argVns, callSite);
|
||||
}
|
||||
}
|
||||
|
||||
Iterator getLanguageRoots() {
|
||||
return languageRootNodes.iterator();
|
||||
}
|
||||
|
||||
protected CGNode makeFakeRootNode() throws CancelException {
|
||||
return findOrCreateNode(new CrossLanguageFakeRoot(cha, options, getAnalysisCache()), Everywhere.EVERYWHERE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,162 +1,162 @@
|
||||
/******************************************************************************
|
||||
* 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.cast.ir.ssa;
|
||||
|
||||
import com.ibm.wala.cast.ir.ssa.AstLexicalAccess.Access;
|
||||
import com.ibm.wala.classLoader.CallSiteReference;
|
||||
import com.ibm.wala.ssa.SymbolTable;
|
||||
|
||||
/**
|
||||
* This abstract class adds to invoke instructions the ability to handle lexical uses and definitions during call graph
|
||||
* construction. The lexical uses and definitions of these objects are initially empty, and get filled in by the
|
||||
* AstSSAPropagationCallGraphBuilder, particularly its LexicalOperator objects. This class is still abstract since the
|
||||
* lexical scoping functionality is used by multiple languages, each of which has further specializations of invoke
|
||||
* instructions.
|
||||
*
|
||||
* @author Julian Dolby (dolby@us.ibm.com)
|
||||
*
|
||||
*/
|
||||
public abstract class AbstractLexicalInvoke extends MultiReturnValueInvokeInstruction {
|
||||
|
||||
protected Access[] lexicalReads = null;
|
||||
|
||||
protected Access[] lexicalWrites = null;
|
||||
|
||||
protected AbstractLexicalInvoke(int results[], int exception, CallSiteReference site) {
|
||||
super(results, exception, site);
|
||||
}
|
||||
|
||||
protected AbstractLexicalInvoke(int result, int exception, CallSiteReference site) {
|
||||
this(new int[] { result }, exception, site);
|
||||
}
|
||||
|
||||
protected AbstractLexicalInvoke(int results[], int exception, CallSiteReference site, Access[] lexicalReads,
|
||||
Access[] lexicalWrites) {
|
||||
this(results, exception, site);
|
||||
this.lexicalReads = lexicalReads;
|
||||
this.lexicalWrites = lexicalWrites;
|
||||
}
|
||||
|
||||
public int getNumberOfUses() {
|
||||
if (lexicalReads == null)
|
||||
return getNumberOfParameters();
|
||||
else
|
||||
return getNumberOfParameters() + lexicalReads.length;
|
||||
}
|
||||
|
||||
public int getNumberOfLexicalWrites(){
|
||||
if(lexicalWrites == null){
|
||||
return 0;
|
||||
} else {
|
||||
return lexicalWrites.length;
|
||||
}
|
||||
}
|
||||
|
||||
public int getNumberOfLexicalReads() {
|
||||
if(lexicalReads == null){
|
||||
return 0;
|
||||
} else {
|
||||
return lexicalReads.length;
|
||||
}
|
||||
}
|
||||
|
||||
public final int getLastLexicalUse() {
|
||||
if (lexicalReads == null) {
|
||||
return -1;
|
||||
} else {
|
||||
return getNumberOfParameters() + lexicalReads.length - 1;
|
||||
}
|
||||
}
|
||||
|
||||
public int getUse(int j) {
|
||||
assert j >= getNumberOfParameters();
|
||||
assert lexicalReads != null;
|
||||
assert lexicalReads[j - getNumberOfParameters()] != null;
|
||||
return lexicalReads[j - getNumberOfParameters()].valueNumber;
|
||||
}
|
||||
|
||||
public int getNumberOfDefs() {
|
||||
if (lexicalWrites == null)
|
||||
return super.getNumberOfDefs();
|
||||
else
|
||||
return super.getNumberOfDefs() + lexicalWrites.length;
|
||||
}
|
||||
|
||||
public int getDef(int j) {
|
||||
if (j < super.getNumberOfDefs())
|
||||
return super.getDef(j);
|
||||
else
|
||||
return lexicalWrites[j - super.getNumberOfDefs()].valueNumber;
|
||||
}
|
||||
|
||||
private Access[] addAccess(Access[] array, Access access) {
|
||||
if (array == null)
|
||||
return new Access[] { access };
|
||||
else {
|
||||
Access[] result = new Access[array.length + 1];
|
||||
System.arraycopy(array, 0, result, 0, array.length);
|
||||
result[array.length] = access;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isLexicalUse(int use) {
|
||||
return use >= getNumberOfParameters();
|
||||
}
|
||||
|
||||
public void addLexicalUse(Access use) {
|
||||
lexicalReads = addAccess(lexicalReads, use);
|
||||
}
|
||||
|
||||
public Access getLexicalUse(int i) {
|
||||
return lexicalReads[i - getNumberOfParameters()];
|
||||
}
|
||||
|
||||
public boolean isLexicalDef(int def) {
|
||||
return def >= super.getNumberOfDefs();
|
||||
}
|
||||
|
||||
public void addLexicalDef(Access def) {
|
||||
lexicalWrites = addAccess(lexicalWrites, def);
|
||||
}
|
||||
|
||||
public Access getLexicalDef(int i) {
|
||||
return lexicalWrites[i - super.getNumberOfDefs()];
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return site.hashCode() * 7529;
|
||||
}
|
||||
|
||||
public String toString(SymbolTable symbolTable) {
|
||||
StringBuffer s = new StringBuffer(super.toString(symbolTable));
|
||||
|
||||
if (lexicalReads != null) {
|
||||
s.append(" (reads:");
|
||||
for (int i = 0; i < lexicalReads.length; i++) {
|
||||
s.append(" ").append(lexicalReads[i].variableName).append(":").append(
|
||||
getValueString(symbolTable, lexicalReads[i].valueNumber));
|
||||
}
|
||||
s.append(")");
|
||||
}
|
||||
|
||||
if (lexicalWrites != null) {
|
||||
s.append(" (writes:");
|
||||
for (int i = 0; i < lexicalWrites.length; i++) {
|
||||
s.append(" ").append(lexicalWrites[i].variableName).append(":").append(
|
||||
getValueString(symbolTable, lexicalWrites[i].valueNumber));
|
||||
}
|
||||
s.append(")");
|
||||
}
|
||||
|
||||
return s.toString();
|
||||
}
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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.cast.ir.ssa;
|
||||
|
||||
import com.ibm.wala.cast.ir.ssa.AstLexicalAccess.Access;
|
||||
import com.ibm.wala.classLoader.CallSiteReference;
|
||||
import com.ibm.wala.ssa.SymbolTable;
|
||||
|
||||
/**
|
||||
* This abstract class adds to invoke instructions the ability to handle lexical uses and definitions during call graph
|
||||
* construction. The lexical uses and definitions of these objects are initially empty, and get filled in by the
|
||||
* AstSSAPropagationCallGraphBuilder, particularly its LexicalOperator objects. This class is still abstract since the
|
||||
* lexical scoping functionality is used by multiple languages, each of which has further specializations of invoke
|
||||
* instructions.
|
||||
*
|
||||
* @author Julian Dolby (dolby@us.ibm.com)
|
||||
*
|
||||
*/
|
||||
public abstract class AbstractLexicalInvoke extends MultiReturnValueInvokeInstruction {
|
||||
|
||||
protected Access[] lexicalReads = null;
|
||||
|
||||
protected Access[] lexicalWrites = null;
|
||||
|
||||
protected AbstractLexicalInvoke(int results[], int exception, CallSiteReference site) {
|
||||
super(results, exception, site);
|
||||
}
|
||||
|
||||
protected AbstractLexicalInvoke(int result, int exception, CallSiteReference site) {
|
||||
this(new int[] { result }, exception, site);
|
||||
}
|
||||
|
||||
protected AbstractLexicalInvoke(int results[], int exception, CallSiteReference site, Access[] lexicalReads,
|
||||
Access[] lexicalWrites) {
|
||||
this(results, exception, site);
|
||||
this.lexicalReads = lexicalReads;
|
||||
this.lexicalWrites = lexicalWrites;
|
||||
}
|
||||
|
||||
public int getNumberOfUses() {
|
||||
if (lexicalReads == null)
|
||||
return getNumberOfParameters();
|
||||
else
|
||||
return getNumberOfParameters() + lexicalReads.length;
|
||||
}
|
||||
|
||||
public int getNumberOfLexicalWrites(){
|
||||
if(lexicalWrites == null){
|
||||
return 0;
|
||||
} else {
|
||||
return lexicalWrites.length;
|
||||
}
|
||||
}
|
||||
|
||||
public int getNumberOfLexicalReads() {
|
||||
if(lexicalReads == null){
|
||||
return 0;
|
||||
} else {
|
||||
return lexicalReads.length;
|
||||
}
|
||||
}
|
||||
|
||||
public final int getLastLexicalUse() {
|
||||
if (lexicalReads == null) {
|
||||
return -1;
|
||||
} else {
|
||||
return getNumberOfParameters() + lexicalReads.length - 1;
|
||||
}
|
||||
}
|
||||
|
||||
public int getUse(int j) {
|
||||
assert j >= getNumberOfParameters();
|
||||
assert lexicalReads != null;
|
||||
assert lexicalReads[j - getNumberOfParameters()] != null;
|
||||
return lexicalReads[j - getNumberOfParameters()].valueNumber;
|
||||
}
|
||||
|
||||
public int getNumberOfDefs() {
|
||||
if (lexicalWrites == null)
|
||||
return super.getNumberOfDefs();
|
||||
else
|
||||
return super.getNumberOfDefs() + lexicalWrites.length;
|
||||
}
|
||||
|
||||
public int getDef(int j) {
|
||||
if (j < super.getNumberOfDefs())
|
||||
return super.getDef(j);
|
||||
else
|
||||
return lexicalWrites[j - super.getNumberOfDefs()].valueNumber;
|
||||
}
|
||||
|
||||
private Access[] addAccess(Access[] array, Access access) {
|
||||
if (array == null)
|
||||
return new Access[] { access };
|
||||
else {
|
||||
Access[] result = new Access[array.length + 1];
|
||||
System.arraycopy(array, 0, result, 0, array.length);
|
||||
result[array.length] = access;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isLexicalUse(int use) {
|
||||
return use >= getNumberOfParameters();
|
||||
}
|
||||
|
||||
public void addLexicalUse(Access use) {
|
||||
lexicalReads = addAccess(lexicalReads, use);
|
||||
}
|
||||
|
||||
public Access getLexicalUse(int i) {
|
||||
return lexicalReads[i - getNumberOfParameters()];
|
||||
}
|
||||
|
||||
public boolean isLexicalDef(int def) {
|
||||
return def >= super.getNumberOfDefs();
|
||||
}
|
||||
|
||||
public void addLexicalDef(Access def) {
|
||||
lexicalWrites = addAccess(lexicalWrites, def);
|
||||
}
|
||||
|
||||
public Access getLexicalDef(int i) {
|
||||
return lexicalWrites[i - super.getNumberOfDefs()];
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return site.hashCode() * 7529;
|
||||
}
|
||||
|
||||
public String toString(SymbolTable symbolTable) {
|
||||
StringBuffer s = new StringBuffer(super.toString(symbolTable));
|
||||
|
||||
if (lexicalReads != null) {
|
||||
s.append(" (reads:");
|
||||
for (int i = 0; i < lexicalReads.length; i++) {
|
||||
s.append(" ").append(lexicalReads[i].variableName).append(":").append(
|
||||
getValueString(symbolTable, lexicalReads[i].valueNumber));
|
||||
}
|
||||
s.append(")");
|
||||
}
|
||||
|
||||
if (lexicalWrites != null) {
|
||||
s.append(" (writes:");
|
||||
for (int i = 0; i < lexicalWrites.length; i++) {
|
||||
s.append(" ").append(lexicalWrites[i].variableName).append(":").append(
|
||||
getValueString(symbolTable, lexicalWrites[i].valueNumber));
|
||||
}
|
||||
s.append(")");
|
||||
}
|
||||
|
||||
return s.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,317 +1,317 @@
|
||||
/******************************************************************************
|
||||
* 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.cast.ir.ssa.analysis;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import com.ibm.wala.cfg.ControlFlowGraph;
|
||||
import com.ibm.wala.dataflow.graph.AbstractMeetOperator;
|
||||
import com.ibm.wala.dataflow.graph.BitVectorSolver;
|
||||
import com.ibm.wala.dataflow.graph.BitVectorUnion;
|
||||
import com.ibm.wala.dataflow.graph.IKilldallFramework;
|
||||
import com.ibm.wala.dataflow.graph.ITransferFunctionProvider;
|
||||
import com.ibm.wala.fixpoint.BitVectorVariable;
|
||||
import com.ibm.wala.fixpoint.UnaryOperator;
|
||||
import com.ibm.wala.ssa.IR;
|
||||
import com.ibm.wala.ssa.ISSABasicBlock;
|
||||
import com.ibm.wala.ssa.SSAInstruction;
|
||||
import com.ibm.wala.ssa.SSAPhiInstruction;
|
||||
import com.ibm.wala.ssa.SymbolTable;
|
||||
import com.ibm.wala.util.CancelException;
|
||||
import com.ibm.wala.util.CancelRuntimeException;
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
import com.ibm.wala.util.graph.Graph;
|
||||
import com.ibm.wala.util.graph.impl.GraphInverter;
|
||||
import com.ibm.wala.util.intset.BitVector;
|
||||
import com.ibm.wala.util.intset.BitVectorIntSet;
|
||||
import com.ibm.wala.util.intset.IntSet;
|
||||
|
||||
/**
|
||||
* @author Julian Dolby
|
||||
*
|
||||
* Live-value analysis for a method's IR (or {@link ControlFlowGraph} and {@link SymbolTable}) using a {@link IKilldallFramework}
|
||||
* based implementation.
|
||||
*
|
||||
* Pre-requisites
|
||||
* - Knowledge of SSA form: control flow graphs, basic blocks, Phi instructions
|
||||
* - Knowledge of data flow analysis theory: see http://en.wikipedia.org/wiki/Data_flow_analysis
|
||||
*
|
||||
* Implementation notes:
|
||||
*
|
||||
* - The solver uses node transfer functions only.
|
||||
* - Performance: inverts the CFG to traverse backwards (backward analysis).
|
||||
*/
|
||||
public class LiveAnalysis {
|
||||
|
||||
public interface Result {
|
||||
boolean isLiveEntry(ISSABasicBlock bb, int valueNumber);
|
||||
|
||||
boolean isLiveExit(ISSABasicBlock bb, int valueNumber);
|
||||
|
||||
BitVector getLiveBefore(int instr);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public static Result perform(IR ir) {
|
||||
return perform(ir.getControlFlowGraph(), ir.getSymbolTable());
|
||||
}
|
||||
|
||||