incorporate changes from other branch
- Annotation support - Properly fix path-with-spaces bug. - fix bug involving paths with spaces - add a simple driver for building a call graph via a scope file - Properly return null as default constructor of an array. - organize imports - better handling of missing bytecodes - javadoc - test fix - small Javadoc fix - added date-property.js - 1) added InstanceKey.getCreation sites and its implementations 2) fixes for issues with keys representing dynamic properties i) all properties are converted to strings, - publicize method makeClasspath(). deprecate quoteStringIfNeeded() - organize imports - javadoc - renamed classes to make relationship to mod-ref analysis clearer - add support for lexical writes - Code to compute transitive lexical accesses of methods. - extract some generally useful code from ModRef - Generate proper InstanceFieldKeys for property accesses with Numbers. - rewrite to make hardest test appear last - fix test to properly check reachability - add an array test that doesn't quite work - add method to get a PointerKey for a global - compare FieldValueDispatch objects based on CGNode as well - Handle duplicate field names between subclass and superclass.
This commit is contained in:
parent
09f82ecec1
commit
d77cfc60fc
|
@ -124,6 +124,7 @@ import com.ibm.wala.cast.java.loader.Util;
|
||||||
import com.ibm.wala.cast.java.translator.JavaProcedureEntity;
|
import com.ibm.wala.cast.java.translator.JavaProcedureEntity;
|
||||||
import com.ibm.wala.cast.java.types.JavaType;
|
import com.ibm.wala.cast.java.types.JavaType;
|
||||||
import com.ibm.wala.cast.tree.CAst;
|
import com.ibm.wala.cast.tree.CAst;
|
||||||
|
import com.ibm.wala.cast.tree.CAstAnnotation;
|
||||||
import com.ibm.wala.cast.tree.CAstControlFlowMap;
|
import com.ibm.wala.cast.tree.CAstControlFlowMap;
|
||||||
import com.ibm.wala.cast.tree.CAstEntity;
|
import com.ibm.wala.cast.tree.CAstEntity;
|
||||||
import com.ibm.wala.cast.tree.CAstNode;
|
import com.ibm.wala.cast.tree.CAstNode;
|
||||||
|
@ -1399,6 +1400,11 @@ public class PolyglotJava2CAstTranslator {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<CAstAnnotation> getAnnotations() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public CAstControlFlowMap getControlFlow() {
|
public CAstControlFlowMap getControlFlow() {
|
||||||
Assertions.UNREACHABLE("CompilationUnitEntity.getControlFlow()");
|
Assertions.UNREACHABLE("CompilationUnitEntity.getControlFlow()");
|
||||||
return null;
|
return null;
|
||||||
|
@ -1578,6 +1584,11 @@ public class PolyglotJava2CAstTranslator {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<CAstAnnotation> getAnnotations() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public Map<CAstNode, Collection<CAstEntity>> getAllScopedEntities() {
|
public Map<CAstNode, Collection<CAstEntity>> getAllScopedEntities() {
|
||||||
return Collections.singletonMap(null, fEntities);
|
return Collections.singletonMap(null, fEntities);
|
||||||
}
|
}
|
||||||
|
@ -1805,6 +1816,11 @@ public class PolyglotJava2CAstTranslator {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<CAstAnnotation> getAnnotations() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected final class FieldEntity implements CAstEntity {
|
protected final class FieldEntity implements CAstEntity {
|
||||||
|
@ -1856,6 +1872,11 @@ public class PolyglotJava2CAstTranslator {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<CAstAnnotation> getAnnotations() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public CAstControlFlowMap getControlFlow() {
|
public CAstControlFlowMap getControlFlow() {
|
||||||
// No AST for a field decl; initializers folded into
|
// No AST for a field decl; initializers folded into
|
||||||
// constructor processing...
|
// constructor processing...
|
||||||
|
|
|
@ -6,6 +6,7 @@ package javaonepointfive;
|
||||||
String date();
|
String date();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestAnnotation (doSomething="The class", count=-1, date="09-09-2001")
|
||||||
public class Annotations {
|
public class Annotations {
|
||||||
|
|
||||||
@TestAnnotation (doSomething="What to do", count=1, date="09-09-2005")
|
@TestAnnotation (doSomething="What to do", count=1, date="09-09-2005")
|
||||||
|
|
|
@ -49,6 +49,7 @@ import com.ibm.wala.types.ClassLoaderReference;
|
||||||
import com.ibm.wala.types.MethodReference;
|
import com.ibm.wala.types.MethodReference;
|
||||||
import com.ibm.wala.types.TypeName;
|
import com.ibm.wala.types.TypeName;
|
||||||
import com.ibm.wala.types.TypeReference;
|
import com.ibm.wala.types.TypeReference;
|
||||||
|
import com.ibm.wala.types.annotations.Annotation;
|
||||||
import com.ibm.wala.util.CancelException;
|
import com.ibm.wala.util.CancelException;
|
||||||
import com.ibm.wala.util.collections.HashSetFactory;
|
import com.ibm.wala.util.collections.HashSetFactory;
|
||||||
import com.ibm.wala.util.collections.Pair;
|
import com.ibm.wala.util.collections.Pair;
|
||||||
|
@ -250,6 +251,63 @@ public abstract class IRTests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected static class AnnotationAssertions implements IRAssertion {
|
||||||
|
|
||||||
|
public static class ClassAnnotation {
|
||||||
|
private final String className;
|
||||||
|
private final String annotationTypeName;
|
||||||
|
|
||||||
|
public ClassAnnotation(String className, String annotationTypeName) {
|
||||||
|
super();
|
||||||
|
this.className = className;
|
||||||
|
this.annotationTypeName = annotationTypeName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class MethodAnnotation {
|
||||||
|
private final String methodSig;
|
||||||
|
private final String annotationTypeName;
|
||||||
|
|
||||||
|
public MethodAnnotation(String methodSig, String annotationTypeName) {
|
||||||
|
super();
|
||||||
|
this.methodSig = methodSig;
|
||||||
|
this.annotationTypeName = annotationTypeName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public final Set<ClassAnnotation> classAnnotations = HashSetFactory.make();
|
||||||
|
public final Set<MethodAnnotation> methodAnnotations = HashSetFactory.make();
|
||||||
|
|
||||||
|
public void check(CallGraph cg) {
|
||||||
|
classes: for(ClassAnnotation ca : classAnnotations) {
|
||||||
|
IClass cls = cg.getClassHierarchy().lookupClass(TypeReference.findOrCreate(ClassLoaderReference.Application, ca.className));
|
||||||
|
IClass at = cg.getClassHierarchy().lookupClass(TypeReference.findOrCreate(ClassLoaderReference.Application, ca.annotationTypeName));
|
||||||
|
for(Annotation a : cls.getAnnotations()) {
|
||||||
|
if (a.getType().equals(at.getReference())) {
|
||||||
|
continue classes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.assertFalse("cannot find " + at + " in " + cls, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(MethodAnnotation ma : methodAnnotations) {
|
||||||
|
IClass at = cg.getClassHierarchy().lookupClass(TypeReference.findOrCreate(ClassLoaderReference.Application, ma.annotationTypeName));
|
||||||
|
annot: for(CGNode n : cg) {
|
||||||
|
if (n.getMethod().getSignature().equals(ma.methodSig)) {
|
||||||
|
for(Annotation a : n.getMethod().getAnnotations()) {
|
||||||
|
if (a.getType().equals(at.getReference())) {
|
||||||
|
continue annot;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.assertFalse("cannot find " + at, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected Collection<String> singleTestSrc() {
|
protected Collection<String> singleTestSrc() {
|
||||||
return Collections.singletonList(getTestSrcPath() + File.separator + singleJavaInputForTest());
|
return Collections.singletonList(getTestSrcPath() + File.separator + singleJavaInputForTest());
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,6 +42,7 @@ import com.ibm.wala.cast.loader.AstClass;
|
||||||
import com.ibm.wala.cast.loader.AstField;
|
import com.ibm.wala.cast.loader.AstField;
|
||||||
import com.ibm.wala.cast.loader.AstMethod;
|
import com.ibm.wala.cast.loader.AstMethod;
|
||||||
import com.ibm.wala.cast.loader.AstMethod.DebuggingInformation;
|
import com.ibm.wala.cast.loader.AstMethod.DebuggingInformation;
|
||||||
|
import com.ibm.wala.cast.tree.CAstAnnotation;
|
||||||
import com.ibm.wala.cast.tree.CAstEntity;
|
import com.ibm.wala.cast.tree.CAstEntity;
|
||||||
import com.ibm.wala.cast.tree.CAstQualifier;
|
import com.ibm.wala.cast.tree.CAstQualifier;
|
||||||
import com.ibm.wala.cast.tree.CAstSourcePositionMap;
|
import com.ibm.wala.cast.tree.CAstSourcePositionMap;
|
||||||
|
@ -61,6 +62,8 @@ import com.ibm.wala.classLoader.ModuleEntry;
|
||||||
import com.ibm.wala.classLoader.NewSiteReference;
|
import com.ibm.wala.classLoader.NewSiteReference;
|
||||||
import com.ibm.wala.ipa.callgraph.impl.SetOfClasses;
|
import com.ibm.wala.ipa.callgraph.impl.SetOfClasses;
|
||||||
import com.ibm.wala.ipa.cha.IClassHierarchy;
|
import com.ibm.wala.ipa.cha.IClassHierarchy;
|
||||||
|
import com.ibm.wala.shrikeCT.AnnotationsReader.ElementValue;
|
||||||
|
import com.ibm.wala.shrikeCT.AnnotationsReader.ConstantElementValue;
|
||||||
import com.ibm.wala.shrikeCT.ClassConstants;
|
import com.ibm.wala.shrikeCT.ClassConstants;
|
||||||
import com.ibm.wala.ssa.SSAThrowInstruction;
|
import com.ibm.wala.ssa.SSAThrowInstruction;
|
||||||
import com.ibm.wala.ssa.SymbolTable;
|
import com.ibm.wala.ssa.SymbolTable;
|
||||||
|
@ -71,7 +74,9 @@ import com.ibm.wala.types.MethodReference;
|
||||||
import com.ibm.wala.types.Selector;
|
import com.ibm.wala.types.Selector;
|
||||||
import com.ibm.wala.types.TypeName;
|
import com.ibm.wala.types.TypeName;
|
||||||
import com.ibm.wala.types.TypeReference;
|
import com.ibm.wala.types.TypeReference;
|
||||||
|
import com.ibm.wala.types.annotations.Annotation;
|
||||||
import com.ibm.wala.util.collections.HashMapFactory;
|
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.debug.Assertions;
|
||||||
import com.ibm.wala.util.strings.Atom;
|
import com.ibm.wala.util.strings.Atom;
|
||||||
|
|
||||||
|
@ -92,11 +97,18 @@ public abstract class JavaSourceLoaderImpl extends ClassLoaderImpl {
|
||||||
|
|
||||||
protected final Collection superTypeNames;
|
protected final Collection superTypeNames;
|
||||||
|
|
||||||
|
private final Collection<Annotation> annotations;
|
||||||
|
|
||||||
public JavaClass(String typeName, Collection superTypeNames, CAstSourcePositionMap.Position position, Collection qualifiers,
|
public JavaClass(String typeName, Collection superTypeNames, CAstSourcePositionMap.Position position, Collection qualifiers,
|
||||||
JavaSourceLoaderImpl loader, IClass enclosingClass) {
|
JavaSourceLoaderImpl loader, IClass enclosingClass, Collection<Annotation> annotations) {
|
||||||
super(position, TypeName.string2TypeName(typeName), loader, (short) mapToInt(qualifiers), new HashMap<Atom, IField>(), new HashMap<Selector, IMethod>());
|
super(position, TypeName.string2TypeName(typeName), loader, (short) mapToInt(qualifiers), new HashMap<Atom, IField>(), new HashMap<Selector, IMethod>());
|
||||||
this.superTypeNames = superTypeNames;
|
this.superTypeNames = superTypeNames;
|
||||||
this.enclosingClass = enclosingClass;
|
this.enclosingClass = enclosingClass;
|
||||||
|
this.annotations = annotations;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<Annotation> getAnnotations() {
|
||||||
|
return annotations;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IClassHierarchy getClassHierarchy() {
|
public IClassHierarchy getClassHierarchy() {
|
||||||
|
@ -157,7 +169,7 @@ public abstract class JavaSourceLoaderImpl extends ClassLoaderImpl {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addField(CAstEntity fieldEntity) {
|
private void addField(CAstEntity fieldEntity) {
|
||||||
declaredFields.put(Util.fieldEntityToAtom(fieldEntity), new JavaField(fieldEntity, JavaSourceLoaderImpl.this, this));
|
declaredFields.put(Util.fieldEntityToAtom(fieldEntity), new JavaField(fieldEntity, JavaSourceLoaderImpl.this, this, JavaSourceLoaderImpl.this.getAnnotations(fieldEntity)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public IClass getEnclosingClass() {
|
public IClass getEnclosingClass() {
|
||||||
|
@ -165,24 +177,53 @@ public abstract class JavaSourceLoaderImpl extends ClassLoaderImpl {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
if (enclosingClass == null) {
|
StringBuffer sb = new StringBuffer("<src-class: " );
|
||||||
return "<src-class: " + getName().toString() + ">";
|
sb.append(getName().toString());
|
||||||
} else {
|
if (enclosingClass != null) {
|
||||||
return "<src-class: " + getName().toString() + "(within " + enclosingClass.getName() + ")>";
|
sb.append(" (within " + enclosingClass.getName() + ")");
|
||||||
}
|
}
|
||||||
|
if (annotations != null && !annotations.isEmpty()) {
|
||||||
|
for(Annotation a : annotations) {
|
||||||
|
sb.append("[" + a.getType().getName().getClassName() + "]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Collection<Annotation> getAnnotations(CAstEntity e) {
|
||||||
|
Collection<CAstAnnotation> annotations = e.getAnnotations();
|
||||||
|
if (annotations == null || annotations.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
Collection<Annotation> result = HashSetFactory.make();
|
||||||
|
for(CAstAnnotation ca : annotations) {
|
||||||
|
TypeName walaTypeName = toWALATypeName(ca.getType());
|
||||||
|
TypeReference ref = TypeReference.findOrCreate(getReference(), walaTypeName);
|
||||||
|
if (ca.getArguments() == null || ca.getArguments().isEmpty()) {
|
||||||
|
result.add(Annotation.make(ref));
|
||||||
|
} else {
|
||||||
|
Map<String,ElementValue> args = HashMapFactory.make();
|
||||||
|
for(Map.Entry<String, Object> a : ca.getArguments().entrySet()) {
|
||||||
|
args.put(a.getKey(), new ConstantElementValue(a.getValue()));
|
||||||
|
}
|
||||||
|
result.add(Annotation.makeWithNamed(ref, args));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DOMO representation of a field on a Java type that resides in a source file
|
* DOMO representation of a field on a Java type that resides in a source file
|
||||||
*
|
*
|
||||||
* @author rfuhrer
|
* @author rfuhrer
|
||||||
*/
|
*/
|
||||||
private class JavaField extends AstField {
|
private class JavaField extends AstField {
|
||||||
private JavaField(CAstEntity fieldEntity, IClassLoader loader, IClass declaringClass) {
|
private JavaField(CAstEntity fieldEntity, IClassLoader loader, IClass declaringClass, Collection<Annotation> annotations) {
|
||||||
super(FieldReference.findOrCreate(declaringClass.getReference(), Atom.findOrCreateUnicodeAtom(fieldEntity.getName()),
|
super(FieldReference.findOrCreate(declaringClass.getReference(), Atom.findOrCreateUnicodeAtom(fieldEntity.getName()),
|
||||||
TypeReference.findOrCreate(loader.getReference(), TypeName.string2TypeName(fieldEntity.getType().getName()))),
|
TypeReference.findOrCreate(loader.getReference(), TypeName.string2TypeName(fieldEntity.getType().getName()))),
|
||||||
fieldEntity.getQualifiers(), declaringClass, declaringClass.getClassHierarchy());
|
fieldEntity.getQualifiers(), declaringClass, declaringClass.getClassHierarchy(), annotations);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -200,14 +241,14 @@ public abstract class JavaSourceLoaderImpl extends ClassLoaderImpl {
|
||||||
public JavaEntityMethod(CAstEntity methodEntity, IClass owner, AbstractCFG cfg, SymbolTable symtab, boolean hasCatchBlock,
|
public JavaEntityMethod(CAstEntity methodEntity, IClass owner, AbstractCFG cfg, SymbolTable symtab, boolean hasCatchBlock,
|
||||||
TypeReference[][] catchTypes, boolean hasMonitorOp, AstLexicalInformation lexicalInfo, DebuggingInformation debugInfo) {
|
TypeReference[][] catchTypes, boolean hasMonitorOp, AstLexicalInformation lexicalInfo, DebuggingInformation debugInfo) {
|
||||||
super(owner, methodEntity.getQualifiers(), cfg, symtab, MethodReference.findOrCreate(owner.getReference(), Util
|
super(owner, methodEntity.getQualifiers(), cfg, symtab, MethodReference.findOrCreate(owner.getReference(), Util
|
||||||
.methodEntityToSelector(methodEntity)), hasCatchBlock, catchTypes, hasMonitorOp, lexicalInfo, debugInfo);
|
.methodEntityToSelector(methodEntity)), hasCatchBlock, catchTypes, hasMonitorOp, lexicalInfo, debugInfo, JavaSourceLoaderImpl.this.getAnnotations(methodEntity));
|
||||||
this.parameterTypes = computeParameterTypes(methodEntity);
|
this.parameterTypes = computeParameterTypes(methodEntity);
|
||||||
this.exceptionTypes = computeExceptionTypes(methodEntity);
|
this.exceptionTypes = computeExceptionTypes(methodEntity);
|
||||||
}
|
}
|
||||||
|
|
||||||
public JavaEntityMethod(CAstEntity methodEntity, IClass owner) {
|
public JavaEntityMethod(CAstEntity methodEntity, IClass owner) {
|
||||||
super(owner, methodEntity.getQualifiers(), MethodReference.findOrCreate(owner.getReference(), Util
|
super(owner, methodEntity.getQualifiers(), MethodReference.findOrCreate(owner.getReference(), Util
|
||||||
.methodEntityToSelector(methodEntity)));
|
.methodEntityToSelector(methodEntity)), JavaSourceLoaderImpl.this.getAnnotations(methodEntity));
|
||||||
this.parameterTypes = computeParameterTypes(methodEntity);
|
this.parameterTypes = computeParameterTypes(methodEntity);
|
||||||
this.exceptionTypes = computeExceptionTypes(methodEntity);
|
this.exceptionTypes = computeExceptionTypes(methodEntity);
|
||||||
}
|
}
|
||||||
|
@ -449,14 +490,18 @@ public abstract class JavaSourceLoaderImpl extends ClassLoaderImpl {
|
||||||
((JavaClass) owner).addField(n);
|
((JavaClass) owner).addField(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private TypeName toWALATypeName(CAstType type) {
|
||||||
|
return TypeName.string2TypeName(type.getName());
|
||||||
|
}
|
||||||
|
|
||||||
public IClass defineType(CAstEntity type, String typeName, CAstEntity owner) {
|
public IClass defineType(CAstEntity type, String typeName, CAstEntity owner) {
|
||||||
Collection<TypeName> superTypeNames = new ArrayList<TypeName>();
|
Collection<TypeName> superTypeNames = new ArrayList<TypeName>();
|
||||||
for (Iterator superTypes = type.getType().getSupertypes().iterator(); superTypes.hasNext();) {
|
for (Iterator superTypes = type.getType().getSupertypes().iterator(); superTypes.hasNext();) {
|
||||||
superTypeNames.add(TypeName.string2TypeName(((CAstType) superTypes.next()).getName()));
|
superTypeNames.add(toWALATypeName(((CAstType) superTypes.next())));
|
||||||
}
|
}
|
||||||
|
|
||||||
JavaClass javaClass = new JavaClass(typeName, superTypeNames, type.getPosition(), type.getQualifiers(), this,
|
JavaClass javaClass = new JavaClass(typeName, superTypeNames, type.getPosition(), type.getQualifiers(), this,
|
||||||
(owner != null) ? (JavaClass) fTypeMap.get(owner) : (JavaClass) null);
|
(owner != null) ? (JavaClass) fTypeMap.get(owner) : (JavaClass) null, getAnnotations(type));
|
||||||
|
|
||||||
if (getParent().lookupClass(javaClass.getName()) != null) {
|
if (getParent().lookupClass(javaClass.getName()) != null) {
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2008 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.test;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
|
||||||
|
import com.ibm.wala.cast.js.translator.CAstRhinoTranslatorFactory;
|
||||||
|
|
||||||
|
public class TestLexicalModRefRhino extends TestLexicalModRef {
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
com.ibm.wala.cast.js.ipa.callgraph.JSCallGraphUtil.setTranslatorFactory(new CAstRhinoTranslatorFactory());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -91,6 +91,7 @@ import com.ibm.wala.cast.js.ipa.callgraph.JSSSAPropagationCallGraphBuilder;
|
||||||
import com.ibm.wala.cast.js.loader.JavaScriptLoader;
|
import com.ibm.wala.cast.js.loader.JavaScriptLoader;
|
||||||
import com.ibm.wala.cast.js.types.JavaScriptTypes;
|
import com.ibm.wala.cast.js.types.JavaScriptTypes;
|
||||||
import com.ibm.wala.cast.tree.CAst;
|
import com.ibm.wala.cast.tree.CAst;
|
||||||
|
import com.ibm.wala.cast.tree.CAstAnnotation;
|
||||||
import com.ibm.wala.cast.tree.CAstControlFlowMap;
|
import com.ibm.wala.cast.tree.CAstControlFlowMap;
|
||||||
import com.ibm.wala.cast.tree.CAstEntity;
|
import com.ibm.wala.cast.tree.CAstEntity;
|
||||||
import com.ibm.wala.cast.tree.CAstNode;
|
import com.ibm.wala.cast.tree.CAstNode;
|
||||||
|
@ -466,6 +467,10 @@ public class RhinoToAstTranslator {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Collection<CAstAnnotation> getAnnotations() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public Collection<CAstQualifier> getQualifiers() {
|
public Collection<CAstQualifier> getQualifiers() {
|
||||||
Assertions.UNREACHABLE("JuliansUnnamedCAstEntity$2.getQualifiers()");
|
Assertions.UNREACHABLE("JuliansUnnamedCAstEntity$2.getQualifiers()");
|
||||||
return null;
|
return null;
|
||||||
|
@ -623,7 +628,7 @@ public class RhinoToAstTranslator {
|
||||||
if (elt instanceof EmptyExpression) {
|
if (elt instanceof EmptyExpression) {
|
||||||
index++;
|
index++;
|
||||||
} else {
|
} else {
|
||||||
eltNodes.add(Ast.makeConstant(index++));
|
eltNodes.add(Ast.makeConstant("" + (index++)));
|
||||||
eltNodes.add(visit(elt, arg));
|
eltNodes.add(visit(elt, arg));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,16 @@
|
||||||
var a = [];
|
var a = [];
|
||||||
a[0] = function reachable() { print("reachable"); };
|
a[0] = function reachable1() { print("reachable"); };
|
||||||
a[1] = function also_reachable() { print("also reachable"); };
|
|
||||||
a[2] = function reachable_too() { print("reachable, too"); };
|
|
||||||
|
|
||||||
var o = { toString: function() { return 2; } };
|
|
||||||
|
|
||||||
a["0"]();
|
a["0"]();
|
||||||
a[1.0]();
|
|
||||||
a[o]();
|
var b = [];
|
||||||
|
b[1] = function reachable2() { print("also reachable"); };
|
||||||
|
b[1.0]();
|
||||||
|
|
||||||
|
var c = [];
|
||||||
|
c["2"] = function reachable3() { print("reachable, too"); };
|
||||||
|
c[2]();
|
||||||
|
|
||||||
|
var d = [];
|
||||||
|
d[3] = function reachable4() { print("reachable4"); };
|
||||||
|
var o = { toString: function() { return 3; } };
|
||||||
|
d[o]();
|
|
@ -0,0 +1,13 @@
|
||||||
|
var t = "this is a long string";
|
||||||
|
|
||||||
|
var bar = t.substring(0, 10);
|
||||||
|
|
||||||
|
var d = new Date("October 13, 1975 11:13:00");
|
||||||
|
|
||||||
|
var document = {
|
||||||
|
fun: function _fun(x) {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
document[d](bar);
|
|
@ -0,0 +1,58 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2008 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.test;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import junit.framework.Assert;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import com.ibm.wala.cast.ipa.lexical.LexicalModRef;
|
||||||
|
import com.ibm.wala.cast.js.ipa.callgraph.JSCFABuilder;
|
||||||
|
import com.ibm.wala.ipa.callgraph.CGNode;
|
||||||
|
import com.ibm.wala.ipa.callgraph.CallGraph;
|
||||||
|
import com.ibm.wala.util.CancelException;
|
||||||
|
import com.ibm.wala.util.collections.Pair;
|
||||||
|
import com.ibm.wala.util.intset.OrdinalSet;
|
||||||
|
|
||||||
|
public abstract class TestLexicalModRef {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSimpleLexical() throws IOException, IllegalArgumentException, CancelException {
|
||||||
|
JSCFABuilder b = JSCallGraphBuilderUtil.makeScriptCGBuilder("tests", "simple-lexical.js");
|
||||||
|
CallGraph CG = b.makeCallGraph(b.getOptions());
|
||||||
|
LexicalModRef lexAccesses = LexicalModRef.make(CG, b.getPointerAnalysis());
|
||||||
|
Map<CGNode, OrdinalSet<Pair<CGNode, String>>> readResult = lexAccesses.computeLexicalRef();
|
||||||
|
Map<CGNode, OrdinalSet<Pair<CGNode, String>>> writeResult = lexAccesses.computeLexicalMod();
|
||||||
|
for (CGNode n : readResult.keySet()) {
|
||||||
|
if (n.toString().contains("Node: <Code body of function Ltests/simple-lexical.js/outer/inner>")) {
|
||||||
|
// function "inner" reads exactly x and z
|
||||||
|
OrdinalSet<Pair<CGNode, String>> readVars = readResult.get(n);
|
||||||
|
Assert.assertEquals(2, readVars.size());
|
||||||
|
Assert.assertEquals("[[Node: <Code body of function Ltests/simple-lexical.js/outer> Context: Everywhere,x], [Node: <Code body of function Ltests/simple-lexical.js/outer> Context: Everywhere,z]]", readVars.toString());
|
||||||
|
// writes x and z as well
|
||||||
|
OrdinalSet<Pair<CGNode, String>> writtenVars = writeResult.get(n);
|
||||||
|
Assert.assertEquals(2, writtenVars.size());
|
||||||
|
Assert.assertEquals("[[Node: <Code body of function Ltests/simple-lexical.js/outer> Context: Everywhere,x], [Node: <Code body of function Ltests/simple-lexical.js/outer> Context: Everywhere,z]]", writtenVars.toString());
|
||||||
|
|
||||||
|
}
|
||||||
|
if (n.toString().contains("Node: <Code body of function Ltests/simple-lexical.js/outer/inner2>")) {
|
||||||
|
// function "inner3" reads exactly innerName, inner3, and x and z via callees
|
||||||
|
OrdinalSet<Pair<CGNode, String>> readVars = readResult.get(n);
|
||||||
|
Assert.assertEquals(4, readVars.size());
|
||||||
|
Assert.assertEquals("[[Node: <Code body of function Ltests/simple-lexical.js/outer> Context: Everywhere,x], [Node: <Code body of function Ltests/simple-lexical.js/outer> Context: Everywhere,inner3], [Node: <Code body of function Ltests/simple-lexical.js/outer> Context: Everywhere,innerName], [Node: <Code body of function Ltests/simple-lexical.js/outer> Context: Everywhere,z]]", readVars.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -19,6 +19,7 @@ import junit.framework.Assert;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import com.ibm.wala.cast.ipa.callgraph.CAstCallGraphUtil;
|
||||||
import com.ibm.wala.cast.js.ipa.callgraph.ForInContextSelector;
|
import com.ibm.wala.cast.js.ipa.callgraph.ForInContextSelector;
|
||||||
import com.ibm.wala.cast.js.ipa.callgraph.JSCFABuilder;
|
import com.ibm.wala.cast.js.ipa.callgraph.JSCFABuilder;
|
||||||
import com.ibm.wala.cast.js.ipa.callgraph.JSCallGraphUtil;
|
import com.ibm.wala.cast.js.ipa.callgraph.JSCallGraphUtil;
|
||||||
|
@ -580,9 +581,10 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape {
|
||||||
|
|
||||||
private static final Object[][] assertionsForArrayIndexConv = new Object[][] {
|
private static final Object[][] assertionsForArrayIndexConv = new Object[][] {
|
||||||
new Object[] { ROOT, new String[] { "tests/array_index_conv.js" } },
|
new Object[] { ROOT, new String[] { "tests/array_index_conv.js" } },
|
||||||
new Object[] { "tests/array_index_conv.js", new String[] { "suffix:reachable",
|
new Object[] { "tests/array_index_conv.js", new String[] { "suffix:reachable1",
|
||||||
"suffix:also_reachable",
|
"suffix:reachable2",
|
||||||
"suffix:reachable_too" } }
|
"suffix:reachable3",
|
||||||
|
"suffix:reachable4" } }
|
||||||
};
|
};
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -605,9 +607,25 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape {
|
||||||
PropagationCallGraphBuilder b = JSCallGraphBuilderUtil.makeScriptCGBuilder("tests", "array_index_conv2.js");
|
PropagationCallGraphBuilder b = JSCallGraphBuilderUtil.makeScriptCGBuilder("tests", "array_index_conv2.js");
|
||||||
b.setContextSelector(new ForInContextSelector(b.getContextSelector()));
|
b.setContextSelector(new ForInContextSelector(b.getContextSelector()));
|
||||||
CallGraph cg = b.makeCallGraph(b.getOptions());
|
CallGraph cg = b.makeCallGraph(b.getOptions());
|
||||||
|
//JSCallGraphUtil.AVOID_DUMP = false;
|
||||||
|
//JSCallGraphUtil.dumpCG(b.getPointerAnalysis(), cg);
|
||||||
verifyGraphAssertions(cg, assertionsForArrayIndexConv2);
|
verifyGraphAssertions(cg, assertionsForArrayIndexConv2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final Object[][] assertionsForDateProperty = new Object[][] {
|
||||||
|
new Object[] { ROOT, new String[] { "tests/date-property.js" } },
|
||||||
|
new Object[] { "tests/date-property.js", new String[] { "suffix:_fun" } }
|
||||||
|
};
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDateAsProperty() throws IllegalArgumentException, IOException, CancelException {
|
||||||
|
PropagationCallGraphBuilder B = JSCallGraphBuilderUtil.makeScriptCGBuilder("tests", "date-property.js");
|
||||||
|
CallGraph CG = B.makeCallGraph(B.getOptions());
|
||||||
|
//JSCallGraphUtil.AVOID_DUMP = false;
|
||||||
|
//JSCallGraphUtil.dumpCG(B.getPointerAnalysis(), CG);
|
||||||
|
verifyGraphAssertions(CG, assertionsForDateProperty);
|
||||||
|
}
|
||||||
|
|
||||||
protected IVector<Set<Pair<CGNode, Integer>>> computeIkIdToVns(PointerAnalysis pa) {
|
protected IVector<Set<Pair<CGNode, Integer>>> computeIkIdToVns(PointerAnalysis pa) {
|
||||||
|
|
||||||
// Created by reversing the points to mapping for local pointer keys.
|
// Created by reversing the points to mapping for local pointer keys.
|
||||||
|
|
|
@ -338,16 +338,18 @@ public class ForInContextSelector implements ContextSelector {
|
||||||
}
|
}
|
||||||
} else if(receiver.length > index) {
|
} else if(receiver.length > index) {
|
||||||
Frequency f = usesFirstArgAsPropertyName(callee);
|
Frequency f = usesFirstArgAsPropertyName(callee);
|
||||||
|
/*
|
||||||
if(f == Frequency.ALWAYS) {
|
if(f == Frequency.ALWAYS) {
|
||||||
return new ForInContext(baseContext, simulateToString(caller.getClassHierarchy(), receiver[index]));
|
return new ForInContext(baseContext, simulateToString(caller.getClassHierarchy(), receiver[index]));
|
||||||
} else if(f == Frequency.SOMETIMES) {
|
} else if(f == Frequency.SOMETIMES) {
|
||||||
|
*/
|
||||||
if(receiver[index] == null) {
|
if(receiver[index] == null) {
|
||||||
IClass undef = caller.getClassHierarchy().lookupClass(JavaScriptTypes.Undefined);
|
IClass undef = caller.getClassHierarchy().lookupClass(JavaScriptTypes.Undefined);
|
||||||
return new ForInContext(baseContext, new ConcreteTypeKey(undef));
|
return new ForInContext(baseContext, new ConcreteTypeKey(undef));
|
||||||
} else {
|
} else {
|
||||||
return new ForInContext(baseContext, receiver[index]);
|
return new ForInContext(baseContext, receiver[index]);
|
||||||
}
|
}
|
||||||
}
|
//}
|
||||||
}
|
}
|
||||||
if (USE_CPA_IN_BODIES && FORIN_MARKER.equals(caller.getContext().get(FORIN_KEY))) {
|
if (USE_CPA_IN_BODIES && FORIN_MARKER.equals(caller.getContext().get(FORIN_KEY))) {
|
||||||
return new SelectiveCPAContext(baseContext, receiver);
|
return new SelectiveCPAContext(baseContext, receiver);
|
||||||
|
|
|
@ -1,7 +1,14 @@
|
||||||
package com.ibm.wala.cast.js.ipa.callgraph;
|
package com.ibm.wala.cast.js.ipa.callgraph;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
import com.ibm.wala.classLoader.IClass;
|
import com.ibm.wala.classLoader.IClass;
|
||||||
|
import com.ibm.wala.classLoader.NewSiteReference;
|
||||||
|
import com.ibm.wala.ipa.callgraph.CGNode;
|
||||||
|
import com.ibm.wala.ipa.callgraph.CallGraph;
|
||||||
import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
|
import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
|
||||||
|
import com.ibm.wala.util.collections.EmptyIterator;
|
||||||
|
import com.ibm.wala.util.collections.Pair;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the JavaScript global object.
|
* Represents the JavaScript global object.
|
||||||
|
@ -23,4 +30,9 @@ public class GlobalObjectKey implements InstanceKey {
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "JS Global Object";
|
return "JS Global Object";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<Pair<CGNode, NewSiteReference>> getCreationSites(CallGraph CG) {
|
||||||
|
return EmptyIterator.instance();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,17 +13,20 @@ package com.ibm.wala.cast.js.ipa.callgraph;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
|
||||||
import com.ibm.wala.cast.ipa.callgraph.AstCFAPointerKeys;
|
import com.ibm.wala.cast.ipa.callgraph.AstCFAPointerKeys;
|
||||||
|
import com.ibm.wala.cast.ipa.callgraph.ReflectedFieldPointerKey;
|
||||||
import com.ibm.wala.cast.js.types.JavaScriptTypes;
|
import com.ibm.wala.cast.js.types.JavaScriptTypes;
|
||||||
import com.ibm.wala.classLoader.IClass;
|
import com.ibm.wala.classLoader.IClass;
|
||||||
import com.ibm.wala.classLoader.IField;
|
import com.ibm.wala.classLoader.IField;
|
||||||
import com.ibm.wala.ipa.callgraph.AnalysisCache;
|
import com.ibm.wala.ipa.callgraph.AnalysisCache;
|
||||||
import com.ibm.wala.ipa.callgraph.AnalysisOptions;
|
import com.ibm.wala.ipa.callgraph.AnalysisOptions;
|
||||||
import com.ibm.wala.ipa.callgraph.propagation.ConcreteTypeKey;
|
import com.ibm.wala.ipa.callgraph.propagation.ConcreteTypeKey;
|
||||||
|
import com.ibm.wala.ipa.callgraph.propagation.ConstantKey;
|
||||||
import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
|
import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
|
||||||
import com.ibm.wala.ipa.callgraph.propagation.PointerKey;
|
import com.ibm.wala.ipa.callgraph.propagation.PointerKey;
|
||||||
import com.ibm.wala.ipa.cha.IClassHierarchy;
|
import com.ibm.wala.ipa.cha.IClassHierarchy;
|
||||||
import com.ibm.wala.types.TypeReference;
|
import com.ibm.wala.types.TypeReference;
|
||||||
import com.ibm.wala.util.collections.EmptyIterator;
|
import com.ibm.wala.util.collections.EmptyIterator;
|
||||||
|
import com.ibm.wala.util.strings.Atom;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Common utilities for CFA-style call graph builders.
|
* Common utilities for CFA-style call graph builders.
|
||||||
|
@ -67,12 +70,8 @@ public abstract class JSCFABuilder extends JSSSAPropagationCallGraphBuilder {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Iterator<PointerKey> getPointerKeysForReflectedFieldRead(InstanceKey I, InstanceKey F) {
|
public Iterator<PointerKey> getPointerKeysForReflectedFieldRead(InstanceKey I, InstanceKey F) {
|
||||||
IClassHierarchy cha = I.getConcreteType().getClassHierarchy();
|
|
||||||
IClass function = cha.lookupClass(JavaScriptTypes.Function);
|
|
||||||
if (isBogusKey(I)) {
|
if (isBogusKey(I)) {
|
||||||
return EmptyIterator.instance();
|
return EmptyIterator.instance();
|
||||||
} else if (cha.isSubclassOf(F.getConcreteType(), function)) {
|
|
||||||
return super.getPointerKeysForReflectedFieldRead(I, new ConcreteTypeKey(function));
|
|
||||||
} else {
|
} else {
|
||||||
return super.getPointerKeysForReflectedFieldRead(I, F);
|
return super.getPointerKeysForReflectedFieldRead(I, F);
|
||||||
}
|
}
|
||||||
|
@ -80,16 +79,57 @@ public abstract class JSCFABuilder extends JSSSAPropagationCallGraphBuilder {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Iterator<PointerKey> getPointerKeysForReflectedFieldWrite(InstanceKey I, InstanceKey F) {
|
public Iterator<PointerKey> getPointerKeysForReflectedFieldWrite(InstanceKey I, InstanceKey F) {
|
||||||
IClassHierarchy cha = I.getConcreteType().getClassHierarchy();
|
if (isBogusKey(I)) {
|
||||||
IClass function = cha.lookupClass(JavaScriptTypes.Function);
|
|
||||||
if (isBogusKey(I)) {
|
|
||||||
return EmptyIterator.instance();
|
return EmptyIterator.instance();
|
||||||
} else if (cha.isSubclassOf(F.getConcreteType(), function)) {
|
|
||||||
return super.getPointerKeysForReflectedFieldWrite(I, new ConcreteTypeKey(function));
|
|
||||||
} else {
|
} else {
|
||||||
return super.getPointerKeysForReflectedFieldWrite(I, F);
|
return super.getPointerKeysForReflectedFieldWrite(I, F);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected PointerKey getInstanceFieldPointerKeyForConstant(InstanceKey I, ConstantKey F) {
|
||||||
|
Object v = F.getValue();
|
||||||
|
String strVal = simulateToStringForPropertyNames(v);
|
||||||
|
// if we know the string representation of the constant, use it...
|
||||||
|
if (strVal != null) {
|
||||||
|
IField f = I.getConcreteType().getField(Atom.findOrCreateUnicodeAtom(strVal));
|
||||||
|
return getPointerKeyForInstanceField(I, f);
|
||||||
|
|
||||||
|
// ...otherwise it is some unknown string
|
||||||
|
} else {
|
||||||
|
return ReflectedFieldPointerKey.mapped(new ConcreteTypeKey(getFieldNameType(F)), I);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All values used as property names get implicitly converted to strings in JavaScript.
|
||||||
|
* @see com.ibm.wala.cast.ipa.callgraph.DelegatingAstPointerKeys#getFieldNameType(com.ibm.wala.ipa.callgraph.propagation.InstanceKey)
|
||||||
|
*/
|
||||||
|
protected IClass getFieldNameType(InstanceKey F) {
|
||||||
|
return F.getConcreteType().getClassHierarchy().lookupClass(JavaScriptTypes.String);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String simulateToStringForPropertyNames(Object v) {
|
||||||
|
// TODO this is very incomplete --MS
|
||||||
|
if (v instanceof String) {
|
||||||
|
return (String)v;
|
||||||
|
} else if (v instanceof Double) {
|
||||||
|
String result = v.toString();
|
||||||
|
if (((double) Math.round((Double)v)) == ((Double)v).doubleValue()) {
|
||||||
|
result = Long.toString(Math.round((Double)v));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
} else if (v instanceof Boolean) {
|
||||||
|
if (((Boolean)v).booleanValue()) {
|
||||||
|
return "true";
|
||||||
|
} else {
|
||||||
|
return "false";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -171,6 +171,13 @@ public class JSSSAPropagationCallGraphBuilder extends AstSSAPropagationCallGraph
|
||||||
|
|
||||||
private final GlobalObjectKey globalObject = new GlobalObjectKey(cha.lookupClass(JavaScriptTypes.Object));
|
private final GlobalObjectKey globalObject = new GlobalObjectKey(cha.lookupClass(JavaScriptTypes.Object));
|
||||||
|
|
||||||
|
public PointerKey getPointerKeyForGlobalVar(String varName) {
|
||||||
|
FieldReference fieldRef = FieldReference.findOrCreate(JavaScriptTypes.Root, Atom.findOrCreateUnicodeAtom(varName),
|
||||||
|
JavaScriptTypes.Root);
|
||||||
|
IField f = cha.resolveField(fieldRef);
|
||||||
|
assert f != null : "couldn't resolve " + varName;
|
||||||
|
return getPointerKeyForInstanceField(globalObject, f);
|
||||||
|
}
|
||||||
protected ExplicitCallGraph createEmptyCallGraph(IClassHierarchy cha, AnalysisOptions options) {
|
protected ExplicitCallGraph createEmptyCallGraph(IClassHierarchy cha, AnalysisOptions options) {
|
||||||
return new JSCallGraph(cha, options, getAnalysisCache());
|
return new JSCallGraph(cha, options, getAnalysisCache());
|
||||||
}
|
}
|
||||||
|
@ -521,6 +528,7 @@ public class JSSSAPropagationCallGraphBuilder extends AstSSAPropagationCallGraph
|
||||||
private JavaScriptInvoke getInstruction() { return instruction; }
|
private JavaScriptInvoke getInstruction() { return instruction; }
|
||||||
private InstanceKey getReceiver() { return receiverType; }
|
private InstanceKey getReceiver() { return receiverType; }
|
||||||
private AbstractFieldPointerKey getProperty() { return fieldKey; }
|
private AbstractFieldPointerKey getProperty() { return fieldKey; }
|
||||||
|
private CGNode getNode() { return node; }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public byte evaluate(PointsToSetVariable lhs, PointsToSetVariable ptrs) {
|
public byte evaluate(PointsToSetVariable lhs, PointsToSetVariable ptrs) {
|
||||||
|
@ -553,6 +561,7 @@ public class JSSSAPropagationCallGraphBuilder extends AstSSAPropagationCallGraph
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
return o instanceof FieldValueDispatch &&
|
return o instanceof FieldValueDispatch &&
|
||||||
|
((FieldValueDispatch)o).getNode().equals(node) &&
|
||||||
((FieldValueDispatch)o).getInstruction() == instruction &&
|
((FieldValueDispatch)o).getInstruction() == instruction &&
|
||||||
((FieldValueDispatch)o).getProperty().equals(fieldKey) &&
|
((FieldValueDispatch)o).getProperty().equals(fieldKey) &&
|
||||||
((FieldValueDispatch)o).getReceiver().equals(receiverType);
|
((FieldValueDispatch)o).getReceiver().equals(receiverType);
|
||||||
|
@ -767,7 +776,11 @@ public class JSSSAPropagationCallGraphBuilder extends AstSSAPropagationCallGraph
|
||||||
if (l.isStringType(left.getConcreteType().getReference()) || l.isStringType(right.getConcreteType().getReference())) {
|
if (l.isStringType(left.getConcreteType().getReference()) || l.isStringType(right.getConcreteType().getReference())) {
|
||||||
return addKey(new ConcreteTypeKey(node.getClassHierarchy().lookupClass(l.getStringType())));
|
return addKey(new ConcreteTypeKey(node.getClassHierarchy().lookupClass(l.getStringType())));
|
||||||
} else if (isNumberType(l, left.getConcreteType().getReference()) && isNumberType(l, right.getConcreteType().getReference())) {
|
} else if (isNumberType(l, left.getConcreteType().getReference()) && isNumberType(l, right.getConcreteType().getReference())) {
|
||||||
return addKey(left) || addKey(right);
|
if (left instanceof ConstantKey && right instanceof ConstantKey) {
|
||||||
|
return addKey(new ConcreteTypeKey(node.getClassHierarchy().lookupClass(JavaScriptTypes.Number)));
|
||||||
|
} else {
|
||||||
|
return addKey(left) || addKey(right);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -934,7 +947,7 @@ public class JSSSAPropagationCallGraphBuilder extends AstSSAPropagationCallGraph
|
||||||
|
|
||||||
// pass actual arguments to formals in the normal way
|
// pass actual arguments to formals in the normal way
|
||||||
for (int i = 0; i < Math.min(paramCount, argCount); i++) {
|
for (int i = 0; i < Math.min(paramCount, argCount); i++) {
|
||||||
InstanceKey[] fn = new InstanceKey[] { getInstanceKeyForConstant(JavaScriptTypes.Number, i-num_pseudoargs) };
|
InstanceKey[] fn = new InstanceKey[] { getInstanceKeyForConstant(JavaScriptTypes.String, ""+(i-num_pseudoargs)) };
|
||||||
PointerKey F = getTargetPointerKey(target, i);
|
PointerKey F = getTargetPointerKey(target, i);
|
||||||
|
|
||||||
if (constParams != null && constParams[i] != null) {
|
if (constParams != null && constParams[i] != null) {
|
||||||
|
@ -960,7 +973,7 @@ public class JSSSAPropagationCallGraphBuilder extends AstSSAPropagationCallGraph
|
||||||
if (paramCount < argCount) {
|
if (paramCount < argCount) {
|
||||||
if (av != -1) {
|
if (av != -1) {
|
||||||
for (int i = paramCount; i < argCount; i++) {
|
for (int i = paramCount; i < argCount; i++) {
|
||||||
InstanceKey[] fn = new InstanceKey[] { getInstanceKeyForConstant(JavaScriptTypes.Number, i-num_pseudoargs) };
|
InstanceKey[] fn = new InstanceKey[] { getInstanceKeyForConstant(JavaScriptTypes.String, ""+(i-num_pseudoargs)) };
|
||||||
if (constParams != null && constParams[i] != null && i >= num_pseudoargs) {
|
if (constParams != null && constParams[i] != null && i >= num_pseudoargs) {
|
||||||
targetVisitor.newFieldWrite(target, av, fn, constParams[i]);
|
targetVisitor.newFieldWrite(target, av, fn, constParams[i]);
|
||||||
} else if(i >= num_pseudoargs) {
|
} else if(i >= num_pseudoargs) {
|
||||||
|
|
|
@ -20,9 +20,8 @@ import com.ibm.wala.cast.js.ipa.callgraph.correlations.CorrelationSummary;
|
||||||
import com.ibm.wala.cast.js.translator.JavaScriptTranslatorFactory;
|
import com.ibm.wala.cast.js.translator.JavaScriptTranslatorFactory;
|
||||||
import com.ibm.wala.cast.tree.CAst;
|
import com.ibm.wala.cast.tree.CAst;
|
||||||
import com.ibm.wala.cast.tree.CAstEntity;
|
import com.ibm.wala.cast.tree.CAstEntity;
|
||||||
import com.ibm.wala.cast.tree.rewrite.CAstRewriter;
|
|
||||||
import com.ibm.wala.cast.tree.rewrite.CAstRewriterFactory;
|
|
||||||
import com.ibm.wala.cast.tree.rewrite.CAstBasicRewriter.NoKey;
|
import com.ibm.wala.cast.tree.rewrite.CAstBasicRewriter.NoKey;
|
||||||
|
import com.ibm.wala.cast.tree.rewrite.CAstRewriterFactory;
|
||||||
import com.ibm.wala.classLoader.IMethod;
|
import com.ibm.wala.classLoader.IMethod;
|
||||||
import com.ibm.wala.ipa.cha.ClassHierarchyException;
|
import com.ibm.wala.ipa.cha.ClassHierarchyException;
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ import java.util.Iterator;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
|
import com.ibm.wala.cast.tree.CAstAnnotation;
|
||||||
import com.ibm.wala.cast.tree.CAstControlFlowMap;
|
import com.ibm.wala.cast.tree.CAstControlFlowMap;
|
||||||
import com.ibm.wala.cast.tree.CAstEntity;
|
import com.ibm.wala.cast.tree.CAstEntity;
|
||||||
import com.ibm.wala.cast.tree.CAstNode;
|
import com.ibm.wala.cast.tree.CAstNode;
|
||||||
|
@ -162,6 +163,11 @@ class ExtractedFunction implements CAstEntity {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
public Collection<CAstAnnotation> getAnnotations() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "<JS function " + name + ">";
|
return "<JS function " + name + ">";
|
||||||
}
|
}
|
||||||
|
|
|
@ -115,6 +115,7 @@ import com.ibm.wala.types.MethodReference;
|
||||||
import com.ibm.wala.types.Selector;
|
import com.ibm.wala.types.Selector;
|
||||||
import com.ibm.wala.types.TypeName;
|
import com.ibm.wala.types.TypeName;
|
||||||
import com.ibm.wala.types.TypeReference;
|
import com.ibm.wala.types.TypeReference;
|
||||||
|
import com.ibm.wala.types.annotations.Annotation;
|
||||||
import com.ibm.wala.util.collections.HashSetFactory;
|
import com.ibm.wala.util.collections.HashSetFactory;
|
||||||
import com.ibm.wala.util.debug.Assertions;
|
import com.ibm.wala.util.debug.Assertions;
|
||||||
import com.ibm.wala.util.strings.Atom;
|
import com.ibm.wala.util.strings.Atom;
|
||||||
|
@ -627,6 +628,11 @@ public class JavaScriptLoader extends CAstAbstractModuleLoader {
|
||||||
public IClass getSuperclass() {
|
public IClass getSuperclass() {
|
||||||
return superClass;
|
return superClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<Annotation> getAnnotations() {
|
||||||
|
return Collections.emptySet();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class JavaScriptRootClass extends AstDynamicPropertyClass {
|
class JavaScriptRootClass extends AstDynamicPropertyClass {
|
||||||
|
@ -652,6 +658,11 @@ public class JavaScriptLoader extends CAstAbstractModuleLoader {
|
||||||
public IClass getSuperclass() {
|
public IClass getSuperclass() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<Annotation> getAnnotations() {
|
||||||
|
return Collections.emptySet();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class JavaScriptCodeBody extends AstFunctionClass {
|
class JavaScriptCodeBody extends AstFunctionClass {
|
||||||
|
@ -676,6 +687,11 @@ public class JavaScriptLoader extends CAstAbstractModuleLoader {
|
||||||
codeBody.translationContext = translationContext;
|
codeBody.translationContext = translationContext;
|
||||||
return codeBody;
|
return codeBody;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<Annotation> getAnnotations() {
|
||||||
|
return Collections.emptySet();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final Set<CAstQualifier> functionQualifiers;
|
private static final Set<CAstQualifier> functionQualifiers;
|
||||||
|
@ -693,7 +709,7 @@ public class JavaScriptLoader extends CAstAbstractModuleLoader {
|
||||||
JavaScriptMethodObject(IClass cls, AbstractCFG cfg, SymbolTable symtab, boolean hasCatchBlock,
|
JavaScriptMethodObject(IClass cls, AbstractCFG cfg, SymbolTable symtab, boolean hasCatchBlock,
|
||||||
TypeReference[][] caughtTypes, boolean hasMonitorOp, AstLexicalInformation lexicalInfo, DebuggingInformation debugInfo) {
|
TypeReference[][] caughtTypes, boolean hasMonitorOp, AstLexicalInformation lexicalInfo, DebuggingInformation debugInfo) {
|
||||||
super(cls, functionQualifiers, cfg, symtab, AstMethodReference.fnReference(cls.getReference()), hasCatchBlock, caughtTypes,
|
super(cls, functionQualifiers, cfg, symtab, AstMethodReference.fnReference(cls.getReference()), hasCatchBlock, caughtTypes,
|
||||||
hasMonitorOp, lexicalInfo, debugInfo);
|
hasMonitorOp, lexicalInfo, debugInfo, null);
|
||||||
|
|
||||||
// force creation of these constants by calling the getter methods
|
// force creation of these constants by calling the getter methods
|
||||||
symtab.getNullConstant();
|
symtab.getNullConstant();
|
||||||
|
|
|
@ -10,8 +10,6 @@
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
package com.ibm.wala.cast.js.translator;
|
package com.ibm.wala.cast.js.translator;
|
||||||
|
|
||||||
import java.io.UTFDataFormatException;
|
|
||||||
|
|
||||||
import com.ibm.wala.cast.ir.translator.AstTranslator;
|
import com.ibm.wala.cast.ir.translator.AstTranslator;
|
||||||
import com.ibm.wala.cast.js.loader.JSCallSiteReference;
|
import com.ibm.wala.cast.js.loader.JSCallSiteReference;
|
||||||
import com.ibm.wala.cast.js.loader.JavaScriptLoader;
|
import com.ibm.wala.cast.js.loader.JavaScriptLoader;
|
||||||
|
@ -29,7 +27,6 @@ import com.ibm.wala.cast.tree.visit.CAstVisitor;
|
||||||
import com.ibm.wala.cast.types.AstMethodReference;
|
import com.ibm.wala.cast.types.AstMethodReference;
|
||||||
import com.ibm.wala.cfg.AbstractCFG;
|
import com.ibm.wala.cfg.AbstractCFG;
|
||||||
import com.ibm.wala.classLoader.NewSiteReference;
|
import com.ibm.wala.classLoader.NewSiteReference;
|
||||||
import com.ibm.wala.ssa.SSAPutInstruction;
|
|
||||||
import com.ibm.wala.ssa.SymbolTable;
|
import com.ibm.wala.ssa.SymbolTable;
|
||||||
import com.ibm.wala.types.FieldReference;
|
import com.ibm.wala.types.FieldReference;
|
||||||
import com.ibm.wala.types.MethodReference;
|
import com.ibm.wala.types.MethodReference;
|
||||||
|
@ -239,6 +236,10 @@ public class JSAstTranslator extends AstTranslator {
|
||||||
String field = (String) elt.getValue();
|
String field = (String) elt.getValue();
|
||||||
if (isPrologueScript(context) && "__proto__".equals(field)) {
|
if (isPrologueScript(context) && "__proto__".equals(field)) {
|
||||||
context.cfg().addInstruction(((JSInstructionFactory) insts).SetPrototype(context.cfg().getCurrentInstruction(), receiver, rval));
|
context.cfg().addInstruction(((JSInstructionFactory) insts).SetPrototype(context.cfg().getCurrentInstruction(), receiver, rval));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
} else {
|
} else {
|
||||||
context.currentScope().getConstantValue(field);
|
context.currentScope().getConstantValue(field);
|
||||||
SSAPutInstruction put = ((JSInstructionFactory) insts).PutInstruction(context.cfg().getCurrentInstruction(), receiver, rval, field);
|
SSAPutInstruction put = ((JSInstructionFactory) insts).PutInstruction(context.cfg().getCurrentInstruction(), receiver, rval, field);
|
||||||
|
@ -250,8 +251,9 @@ public class JSAstTranslator extends AstTranslator {
|
||||||
context.cfg().addInstruction(put);
|
context.cfg().addInstruction(put);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
*/
|
||||||
context.cfg().addInstruction(((JSInstructionFactory) insts).PropertyWrite(context.cfg().getCurrentInstruction(), receiver, context.getValue(elt), rval));
|
context.cfg().addInstruction(((JSInstructionFactory) insts).PropertyWrite(context.cfg().getCurrentInstruction(), receiver, context.getValue(elt), rval));
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
private void doPrimitiveNew(WalkContext context, int resultVal, String typeName) {
|
private void doPrimitiveNew(WalkContext context, int resultVal, String typeName) {
|
||||||
|
|
|
@ -12,6 +12,7 @@ Bundle-ActivationPolicy: lazy
|
||||||
Export-Package: com.ibm.wala.cast.analysis.typeInference,
|
Export-Package: com.ibm.wala.cast.analysis.typeInference,
|
||||||
com.ibm.wala.cast.ipa.callgraph,
|
com.ibm.wala.cast.ipa.callgraph,
|
||||||
com.ibm.wala.cast.ipa.cha,
|
com.ibm.wala.cast.ipa.cha,
|
||||||
|
com.ibm.wala.cast.ipa.lexical,
|
||||||
com.ibm.wala.cast.ipa.modref,
|
com.ibm.wala.cast.ipa.modref,
|
||||||
com.ibm.wala.cast.ir.cfg,
|
com.ibm.wala.cast.ir.cfg,
|
||||||
com.ibm.wala.cast.ir.ssa,
|
com.ibm.wala.cast.ir.ssa,
|
||||||
|
|
|
@ -14,11 +14,13 @@ import java.util.Iterator;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.ibm.wala.classLoader.IClass;
|
||||||
import com.ibm.wala.classLoader.IField;
|
import com.ibm.wala.classLoader.IField;
|
||||||
import com.ibm.wala.ipa.callgraph.CGNode;
|
import com.ibm.wala.ipa.callgraph.CGNode;
|
||||||
import com.ibm.wala.ipa.callgraph.propagation.ConcreteTypeKey;
|
import com.ibm.wala.ipa.callgraph.propagation.ConcreteTypeKey;
|
||||||
import com.ibm.wala.ipa.callgraph.propagation.ConstantKey;
|
import com.ibm.wala.ipa.callgraph.propagation.ConstantKey;
|
||||||
import com.ibm.wala.ipa.callgraph.propagation.FilteredPointerKey;
|
import com.ibm.wala.ipa.callgraph.propagation.FilteredPointerKey;
|
||||||
|
import com.ibm.wala.ipa.callgraph.propagation.InstanceFieldKey;
|
||||||
import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
|
import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
|
||||||
import com.ibm.wala.ipa.callgraph.propagation.PointerKey;
|
import com.ibm.wala.ipa.callgraph.propagation.PointerKey;
|
||||||
import com.ibm.wala.ipa.callgraph.propagation.PointerKeyFactory;
|
import com.ibm.wala.ipa.callgraph.propagation.PointerKeyFactory;
|
||||||
|
@ -64,32 +66,53 @@ public class DelegatingAstPointerKeys implements AstPointerKeyFactory {
|
||||||
return base.getPointerKeyForArrayContents(I);
|
return base.getPointerKeyForArrayContents(I);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Iterator<PointerKey> getPointerKeysForReflectedFieldRead(InstanceKey I, InstanceKey F) {
|
public Iterator<PointerKey> getPointerKeysForReflectedFieldWrite(InstanceKey I, InstanceKey F) {
|
||||||
List<PointerKey> result = new LinkedList<PointerKey>();
|
List<PointerKey> result = new LinkedList<PointerKey>();
|
||||||
|
|
||||||
if (F instanceof ConstantKey) {
|
if (F instanceof ConstantKey) {
|
||||||
Object v = ((ConstantKey) F).getValue();
|
PointerKey ifk = getInstanceFieldPointerKeyForConstant(I, (ConstantKey) F);
|
||||||
if (v instanceof String) {
|
if (ifk != null) {
|
||||||
IField f = I.getConcreteType().getField(Atom.findOrCreateUnicodeAtom((String) v));
|
result.add(ifk);
|
||||||
result.add(getPointerKeyForInstanceField(I, f));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
result.add(ReflectedFieldPointerKey.mapped(new ConcreteTypeKey(F.getConcreteType()), I));
|
result.add(ReflectedFieldPointerKey.mapped(new ConcreteTypeKey(getFieldNameType(F)), I));
|
||||||
|
|
||||||
return result.iterator();
|
return result.iterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Iterator<PointerKey> getPointerKeysForReflectedFieldWrite(InstanceKey I, InstanceKey F) {
|
/**
|
||||||
|
* get type for F appropriate for use in a field name.
|
||||||
|
*
|
||||||
|
* @param F
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
protected IClass getFieldNameType(InstanceKey F) {
|
||||||
|
return F.getConcreteType();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* if F is a supported constant representing a field, return the corresponding {@link InstanceFieldKey} for I. Otherwise, return <code>null</code>.
|
||||||
|
* @param F
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
protected PointerKey getInstanceFieldPointerKeyForConstant(InstanceKey I, ConstantKey F) {
|
||||||
|
Object v = F.getValue();
|
||||||
// FIXME: current only constant string are handled
|
// FIXME: current only constant string are handled
|
||||||
|
if (v instanceof String) {
|
||||||
|
IField f = I.getConcreteType().getField(Atom.findOrCreateUnicodeAtom((String) v));
|
||||||
|
return getPointerKeyForInstanceField(I, f);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Iterator<PointerKey> getPointerKeysForReflectedFieldRead(InstanceKey I, InstanceKey F) {
|
||||||
if (F instanceof ConstantKey) {
|
if (F instanceof ConstantKey) {
|
||||||
Object v = ((ConstantKey) F).getValue();
|
PointerKey ifk = getInstanceFieldPointerKeyForConstant(I, (ConstantKey) F);
|
||||||
if (v instanceof String) {
|
if (ifk != null) {
|
||||||
IField f = I.getConcreteType().getField(Atom.findOrCreateUnicodeAtom((String) v));
|
return new NonNullSingletonIterator<PointerKey>(ifk);
|
||||||
return new NonNullSingletonIterator<PointerKey>(getPointerKeyForInstanceField(I, f));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return new NonNullSingletonIterator<PointerKey>(ReflectedFieldPointerKey.mapped(new ConcreteTypeKey(getFieldNameType(F)), I));
|
||||||
return new NonNullSingletonIterator<PointerKey>(ReflectedFieldPointerKey.mapped(new ConcreteTypeKey(F.getConcreteType()), I));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ import com.ibm.wala.classLoader.IClass;
|
||||||
import com.ibm.wala.classLoader.NewSiteReference;
|
import com.ibm.wala.classLoader.NewSiteReference;
|
||||||
import com.ibm.wala.classLoader.ProgramCounter;
|
import com.ibm.wala.classLoader.ProgramCounter;
|
||||||
import com.ibm.wala.ipa.callgraph.CGNode;
|
import com.ibm.wala.ipa.callgraph.CGNode;
|
||||||
|
import com.ibm.wala.ipa.callgraph.CallGraph;
|
||||||
import com.ibm.wala.ipa.callgraph.ContextItem;
|
import com.ibm.wala.ipa.callgraph.ContextItem;
|
||||||
import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
|
import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
|
||||||
import com.ibm.wala.ipa.callgraph.propagation.InstanceKeyFactory;
|
import com.ibm.wala.ipa.callgraph.propagation.InstanceKeyFactory;
|
||||||
|
@ -27,6 +28,8 @@ import com.ibm.wala.ipa.callgraph.propagation.PropagationCallGraphBuilder;
|
||||||
import com.ibm.wala.types.TypeReference;
|
import com.ibm.wala.types.TypeReference;
|
||||||
import com.ibm.wala.util.collections.CompoundIterator;
|
import com.ibm.wala.util.collections.CompoundIterator;
|
||||||
import com.ibm.wala.util.collections.EmptyIterator;
|
import com.ibm.wala.util.collections.EmptyIterator;
|
||||||
|
import com.ibm.wala.util.collections.Filter;
|
||||||
|
import com.ibm.wala.util.collections.FilterIterator;
|
||||||
import com.ibm.wala.util.collections.NonNullSingletonIterator;
|
import com.ibm.wala.util.collections.NonNullSingletonIterator;
|
||||||
import com.ibm.wala.util.collections.Pair;
|
import com.ibm.wala.util.collections.Pair;
|
||||||
import com.ibm.wala.util.intset.OrdinalSet;
|
import com.ibm.wala.util.intset.OrdinalSet;
|
||||||
|
@ -92,7 +95,7 @@ abstract public class ScopeMappingInstanceKeys implements InstanceKeyFactory {
|
||||||
* @param definer
|
* @param definer
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
Iterator<CGNode> getFunargNodes(Pair<String, String> name) {
|
public Iterator<CGNode> getFunargNodes(Pair<String, String> name) {
|
||||||
if (AstTranslator.NEW_LEXICAL) {
|
if (AstTranslator.NEW_LEXICAL) {
|
||||||
Collection<CGNode> constructorCallers = getConstructorCallers(this, name);
|
Collection<CGNode> constructorCallers = getConstructorCallers(this, name);
|
||||||
assert constructorCallers != null && !constructorCallers.isEmpty() : "no callers for constructor";
|
assert constructorCallers != null && !constructorCallers.isEmpty() : "no callers for constructor";
|
||||||
|
@ -175,6 +178,16 @@ abstract public class ScopeMappingInstanceKeys implements InstanceKeyFactory {
|
||||||
public CGNode getCreator() {
|
public CGNode getCreator() {
|
||||||
return creator;
|
return creator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Iterator<Pair<CGNode, NewSiteReference>> getCreationSites(CallGraph CG) {
|
||||||
|
return new FilterIterator<Pair<CGNode, NewSiteReference>>(
|
||||||
|
base.getCreationSites(CG),
|
||||||
|
new Filter<Pair<CGNode, NewSiteReference>>() {
|
||||||
|
public boolean accepts(Pair<CGNode, NewSiteReference> o) {
|
||||||
|
return o.fst.equals(creator);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public InstanceKey getInstanceKeyForAllocation(CGNode creatorNode, NewSiteReference allocationSite) {
|
public InstanceKey getInstanceKeyForAllocation(CGNode creatorNode, NewSiteReference allocationSite) {
|
||||||
|
|
|
@ -0,0 +1,133 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2008 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.lexical;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.ibm.wala.cast.ipa.callgraph.ScopeMappingInstanceKeys.ScopeMappingInstanceKey;
|
||||||
|
import com.ibm.wala.cast.ir.ssa.AstLexicalAccess.Access;
|
||||||
|
import com.ibm.wala.cast.ir.ssa.AstLexicalRead;
|
||||||
|
import com.ibm.wala.cast.ir.ssa.AstLexicalWrite;
|
||||||
|
import com.ibm.wala.ipa.callgraph.CGNode;
|
||||||
|
import com.ibm.wala.ipa.callgraph.CallGraph;
|
||||||
|
import com.ibm.wala.ipa.callgraph.CallGraphTransitiveClosure;
|
||||||
|
import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
|
||||||
|
import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis;
|
||||||
|
import com.ibm.wala.ssa.IR;
|
||||||
|
import com.ibm.wala.ssa.SSAInstruction;
|
||||||
|
import com.ibm.wala.util.collections.HashSetFactory;
|
||||||
|
import com.ibm.wala.util.collections.Iterator2Iterable;
|
||||||
|
import com.ibm.wala.util.collections.Pair;
|
||||||
|
import com.ibm.wala.util.functions.Function;
|
||||||
|
import com.ibm.wala.util.intset.OrdinalSet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compute mod-ref information limited to accesses of lexical variables.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class LexicalModRef {
|
||||||
|
|
||||||
|
public static LexicalModRef make(CallGraph cg, PointerAnalysis pa) {
|
||||||
|
return new LexicalModRef(cg, pa);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final CallGraph cg;
|
||||||
|
|
||||||
|
private final PointerAnalysis pa;
|
||||||
|
|
||||||
|
protected LexicalModRef(CallGraph cg, PointerAnalysis pa) {
|
||||||
|
this.cg = cg;
|
||||||
|
this.pa = pa;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compute the lexical variables possibly read by each {@link CGNode} and its
|
||||||
|
* transitive callees. A lexical variable is represented as a pair (C,N),
|
||||||
|
* where C is the defining {@link CGNode} and N is the {@link String} name.
|
||||||
|
*/
|
||||||
|
public Map<CGNode, OrdinalSet<Pair<CGNode, String>>> computeLexicalRef() {
|
||||||
|
Map<CGNode, Collection<Pair<CGNode, String>>> scan = CallGraphTransitiveClosure.collectNodeResults(cg,
|
||||||
|
new Function<CGNode, Collection<Pair<CGNode, String>>>() {
|
||||||
|
|
||||||
|
public Collection<Pair<CGNode, String>> apply(CGNode n) {
|
||||||
|
return scanNodeForLexReads(n);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return CallGraphTransitiveClosure.transitiveClosure(cg, scan);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compute the lexical variables possibly modified by each {@link CGNode} and
|
||||||
|
* its transitive callees. A lexical variable is represented as a pair (C,N),
|
||||||
|
* where C is the defining {@link CGNode} and N is the {@link String} name.
|
||||||
|
*/
|
||||||
|
public Map<CGNode, OrdinalSet<Pair<CGNode, String>>> computeLexicalMod() {
|
||||||
|
Map<CGNode, Collection<Pair<CGNode, String>>> scan = CallGraphTransitiveClosure.collectNodeResults(cg,
|
||||||
|
new Function<CGNode, Collection<Pair<CGNode, String>>>() {
|
||||||
|
|
||||||
|
public Collection<Pair<CGNode, String>> apply(CGNode n) {
|
||||||
|
return scanNodeForLexWrites(n);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return CallGraphTransitiveClosure.transitiveClosure(cg, scan);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Collection<Pair<CGNode, String>> scanNodeForLexReads(CGNode n) {
|
||||||
|
Collection<Pair<CGNode, String>> result = HashSetFactory.make();
|
||||||
|
IR ir = n.getIR();
|
||||||
|
if (ir != null) {
|
||||||
|
for (SSAInstruction instr : Iterator2Iterable.make(ir.iterateNormalInstructions())) {
|
||||||
|
if (instr instanceof AstLexicalRead) {
|
||||||
|
AstLexicalRead read = (AstLexicalRead) instr;
|
||||||
|
for (Access a : read.getAccesses()) {
|
||||||
|
Pair<String, String> nameAndDefiner = a.getName();
|
||||||
|
result.addAll(getNodeNamePairsForAccess(n, nameAndDefiner));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Collection<Pair<CGNode, String>> scanNodeForLexWrites(CGNode n) {
|
||||||
|
Collection<Pair<CGNode, String>> result = HashSetFactory.make();
|
||||||
|
IR ir = n.getIR();
|
||||||
|
if (ir != null) {
|
||||||
|
for (SSAInstruction instr : Iterator2Iterable.make(ir.iterateNormalInstructions())) {
|
||||||
|
if (instr instanceof AstLexicalWrite) {
|
||||||
|
AstLexicalWrite write = (AstLexicalWrite) instr;
|
||||||
|
for (Access a : write.getAccesses()) {
|
||||||
|
Pair<String, String> nameAndDefiner = a.getName();
|
||||||
|
result.addAll(getNodeNamePairsForAccess(n, nameAndDefiner));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Collection<Pair<CGNode, String>> getNodeNamePairsForAccess(CGNode n, Pair<String, String> nameAndDefiner) {
|
||||||
|
Collection<Pair<CGNode, String>> result = HashSetFactory.make();
|
||||||
|
// use scope-mapping instance keys in pointer analysis. may need a different
|
||||||
|
// scheme for CG construction not based on pointer analysis
|
||||||
|
OrdinalSet<InstanceKey> functionValues = pa.getPointsToSet(pa.getHeapModel().getPointerKeyForLocal(n, 1));
|
||||||
|
for (InstanceKey ik : functionValues) {
|
||||||
|
if (ik instanceof ScopeMappingInstanceKey) {
|
||||||
|
ScopeMappingInstanceKey smik = (ScopeMappingInstanceKey) ik;
|
||||||
|
for (CGNode definerNode : Iterator2Iterable.make(smik.getFunargNodes(nameAndDefiner))) {
|
||||||
|
result.add(Pair.make(definerNode, nameAndDefiner.fst));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,6 +7,7 @@ import java.util.Collection;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.ibm.wala.cast.tree.CAstAnnotation;
|
||||||
import com.ibm.wala.cast.tree.CAstEntity;
|
import com.ibm.wala.cast.tree.CAstEntity;
|
||||||
import com.ibm.wala.cast.tree.CAstNode;
|
import com.ibm.wala.cast.tree.CAstNode;
|
||||||
import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position;
|
import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position;
|
||||||
|
@ -29,6 +30,11 @@ public abstract class AbstractEntity implements CAstEntity {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Collection<CAstAnnotation> getAnnotations() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public void setPosition(Position pos) {
|
public void setPosition(Position pos) {
|
||||||
sourcePosition = pos;
|
sourcePosition = pos;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,8 @@
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
package com.ibm.wala.cast.loader;
|
package com.ibm.wala.cast.loader;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
@ -23,6 +25,7 @@ import com.ibm.wala.types.FieldReference;
|
||||||
import com.ibm.wala.types.Selector;
|
import com.ibm.wala.types.Selector;
|
||||||
import com.ibm.wala.types.TypeName;
|
import com.ibm.wala.types.TypeName;
|
||||||
import com.ibm.wala.types.TypeReference;
|
import com.ibm.wala.types.TypeReference;
|
||||||
|
import com.ibm.wala.types.annotations.Annotation;
|
||||||
import com.ibm.wala.util.strings.Atom;
|
import com.ibm.wala.util.strings.Atom;
|
||||||
|
|
||||||
public abstract class AstDynamicPropertyClass extends AstClass {
|
public abstract class AstDynamicPropertyClass extends AstClass {
|
||||||
|
@ -89,6 +92,10 @@ public abstract class AstDynamicPropertyClass extends AstClass {
|
||||||
public IClassHierarchy getClassHierarchy() {
|
public IClassHierarchy getClassHierarchy() {
|
||||||
return AstDynamicPropertyClass.this.getClassHierarchy();
|
return AstDynamicPropertyClass.this.getClassHierarchy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Collection<Annotation> getAnnotations() {
|
||||||
|
return Collections.emptySet();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return declaredFields.get(name);
|
return declaredFields.get(name);
|
||||||
|
|
|
@ -19,6 +19,7 @@ import com.ibm.wala.classLoader.IField;
|
||||||
import com.ibm.wala.ipa.cha.IClassHierarchy;
|
import com.ibm.wala.ipa.cha.IClassHierarchy;
|
||||||
import com.ibm.wala.types.FieldReference;
|
import com.ibm.wala.types.FieldReference;
|
||||||
import com.ibm.wala.types.TypeReference;
|
import com.ibm.wala.types.TypeReference;
|
||||||
|
import com.ibm.wala.types.annotations.Annotation;
|
||||||
import com.ibm.wala.util.strings.Atom;
|
import com.ibm.wala.util.strings.Atom;
|
||||||
|
|
||||||
public class AstField implements IField {
|
public class AstField implements IField {
|
||||||
|
@ -26,16 +27,24 @@ public class AstField implements IField {
|
||||||
private final FieldReference ref;
|
private final FieldReference ref;
|
||||||
private final IClass declaringClass;
|
private final IClass declaringClass;
|
||||||
private final IClassHierarchy cha;
|
private final IClassHierarchy cha;
|
||||||
|
private final Collection<Annotation> annotations;
|
||||||
|
|
||||||
public AstField(FieldReference ref,
|
public AstField(FieldReference ref,
|
||||||
Collection qualifiers,
|
Collection qualifiers,
|
||||||
IClass declaringClass,
|
IClass declaringClass,
|
||||||
IClassHierarchy cha)
|
IClassHierarchy cha,
|
||||||
|
Collection<Annotation> annotations)
|
||||||
{
|
{
|
||||||
this.declaringClass = declaringClass;
|
this.declaringClass = declaringClass;
|
||||||
this.qualifiers = qualifiers;
|
this.qualifiers = qualifiers;
|
||||||
this.ref = ref;
|
this.ref = ref;
|
||||||
this.cha = cha;
|
this.cha = cha;
|
||||||
|
this.annotations = annotations;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Collection<Annotation> getAnnotations() {
|
||||||
|
return annotations;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IClass getDeclaringClass() {
|
public IClass getDeclaringClass() {
|
||||||
|
|
|
@ -27,6 +27,7 @@ import com.ibm.wala.types.Descriptor;
|
||||||
import com.ibm.wala.types.MethodReference;
|
import com.ibm.wala.types.MethodReference;
|
||||||
import com.ibm.wala.types.Selector;
|
import com.ibm.wala.types.Selector;
|
||||||
import com.ibm.wala.types.TypeReference;
|
import com.ibm.wala.types.TypeReference;
|
||||||
|
import com.ibm.wala.types.annotations.Annotation;
|
||||||
import com.ibm.wala.util.collections.Pair;
|
import com.ibm.wala.util.collections.Pair;
|
||||||
import com.ibm.wala.util.intset.IntSet;
|
import com.ibm.wala.util.intset.IntSet;
|
||||||
import com.ibm.wala.util.strings.Atom;
|
import com.ibm.wala.util.strings.Atom;
|
||||||
|
@ -114,10 +115,11 @@ public abstract class AstMethod implements IMethod {
|
||||||
private final TypeReference[][] catchTypes;
|
private final TypeReference[][] catchTypes;
|
||||||
private final AstLexicalInformation lexicalInfo;
|
private final AstLexicalInformation lexicalInfo;
|
||||||
private final DebuggingInformation debugInfo;
|
private final DebuggingInformation debugInfo;
|
||||||
|
private final Collection<Annotation> annotations;
|
||||||
|
|
||||||
protected AstMethod(IClass cls, Collection qualifiers, AbstractCFG cfg, SymbolTable symtab, MethodReference ref,
|
protected AstMethod(IClass cls, Collection qualifiers, AbstractCFG cfg, SymbolTable symtab, MethodReference ref,
|
||||||
boolean hasCatchBlock, TypeReference[][] catchTypes, boolean hasMonitorOp, AstLexicalInformation lexicalInfo,
|
boolean hasCatchBlock, TypeReference[][] catchTypes, boolean hasMonitorOp, AstLexicalInformation lexicalInfo,
|
||||||
DebuggingInformation debugInfo) {
|
DebuggingInformation debugInfo, Collection<Annotation> annotations) {
|
||||||
this.cls = cls;
|
this.cls = cls;
|
||||||
this.cfg = cfg;
|
this.cfg = cfg;
|
||||||
this.ref = ref;
|
this.ref = ref;
|
||||||
|
@ -128,12 +130,14 @@ public abstract class AstMethod implements IMethod {
|
||||||
this.hasMonitorOp = hasMonitorOp;
|
this.hasMonitorOp = hasMonitorOp;
|
||||||
this.lexicalInfo = lexicalInfo;
|
this.lexicalInfo = lexicalInfo;
|
||||||
this.debugInfo = debugInfo;
|
this.debugInfo = debugInfo;
|
||||||
|
this.annotations = annotations;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected AstMethod(IClass cls, Collection qualifiers, MethodReference ref) {
|
protected AstMethod(IClass cls, Collection qualifiers, MethodReference ref, Collection<Annotation> annotations) {
|
||||||
this.cls = cls;
|
this.cls = cls;
|
||||||
this.qualifiers = qualifiers;
|
this.qualifiers = qualifiers;
|
||||||
this.ref = ref;
|
this.ref = ref;
|
||||||
|
this.annotations = annotations;
|
||||||
|
|
||||||
this.cfg = null;
|
this.cfg = null;
|
||||||
this.symtab = null;
|
this.symtab = null;
|
||||||
|
@ -174,6 +178,10 @@ public abstract class AstMethod implements IMethod {
|
||||||
return debugInfo;
|
return debugInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Collection<Annotation> getAnnotations() {
|
||||||
|
return annotations;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parents of this method with respect to lexical scoping, that is, methods
|
* Parents of this method with respect to lexical scoping, that is, methods
|
||||||
* containing state possibly referenced lexically in this method
|
* containing state possibly referenced lexically in this method
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
package com.ibm.wala.cast.tree;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public interface CAstAnnotation {
|
||||||
|
|
||||||
|
CAstType getType();
|
||||||
|
|
||||||
|
Map<String,Object> getArguments();
|
||||||
|
|
||||||
|
}
|
|
@ -177,4 +177,10 @@ public interface CAstEntity {
|
||||||
* The CAst type of this entity.
|
* The CAst type of this entity.
|
||||||
*/
|
*/
|
||||||
CAstType getType();
|
CAstType getType();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the set of any annotations this entity may have
|
||||||
|
*/
|
||||||
|
Collection<CAstAnnotation> getAnnotations();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ import java.util.Collection;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.ibm.wala.cast.tree.CAstAnnotation;
|
||||||
import com.ibm.wala.cast.tree.CAstControlFlowMap;
|
import com.ibm.wala.cast.tree.CAstControlFlowMap;
|
||||||
import com.ibm.wala.cast.tree.CAstEntity;
|
import com.ibm.wala.cast.tree.CAstEntity;
|
||||||
import com.ibm.wala.cast.tree.CAstNode;
|
import com.ibm.wala.cast.tree.CAstNode;
|
||||||
|
@ -89,4 +90,8 @@ public class DelegatingEntity implements CAstEntity {
|
||||||
return base.getType();
|
return base.getType();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Collection<CAstAnnotation> getAnnotations() {
|
||||||
|
return base.getAnnotations();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
|
@ -0,0 +1,57 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2008 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.core.tests.cha;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import com.ibm.wala.classLoader.IClass;
|
||||||
|
import com.ibm.wala.classLoader.IMethod;
|
||||||
|
import com.ibm.wala.core.tests.util.TestConstants;
|
||||||
|
import com.ibm.wala.core.tests.util.WalaTestCase;
|
||||||
|
import com.ibm.wala.ipa.callgraph.AnalysisCache;
|
||||||
|
import com.ibm.wala.ipa.callgraph.AnalysisScope;
|
||||||
|
import com.ibm.wala.ipa.cha.ClassHierarchy;
|
||||||
|
import com.ibm.wala.ipa.cha.ClassHierarchyException;
|
||||||
|
import com.ibm.wala.types.ClassLoaderReference;
|
||||||
|
import com.ibm.wala.types.TypeReference;
|
||||||
|
import com.ibm.wala.util.WalaRuntimeException;
|
||||||
|
import com.ibm.wala.util.config.AnalysisScopeReader;
|
||||||
|
import com.ibm.wala.util.io.FileProvider;
|
||||||
|
|
||||||
|
public class CodeDeletedTest extends WalaTestCase {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test handling of an invalid class where a non-abstract method has no code.
|
||||||
|
* We want to throw an exception rather than crash.
|
||||||
|
*
|
||||||
|
* @throws IOException
|
||||||
|
* @throws ClassHierarchyException
|
||||||
|
*/
|
||||||
|
@Test(expected = WalaRuntimeException.class)
|
||||||
|
public void testDeletedCode() throws IOException, ClassHierarchyException {
|
||||||
|
AnalysisScope scope = null;
|
||||||
|
scope = AnalysisScopeReader.readJavaScope(TestConstants.WALA_TESTDATA,
|
||||||
|
(new FileProvider()).getFile("J2SEClassHierarchyExclusions.txt"), DupFieldsTest.class.getClassLoader());
|
||||||
|
ClassHierarchy cha = ClassHierarchy.make(scope);
|
||||||
|
TypeReference ref = TypeReference.findOrCreate(ClassLoaderReference.Application, "LCodeDeleted");
|
||||||
|
IClass klass = cha.lookupClass(ref);
|
||||||
|
AnalysisCache cache = new AnalysisCache();
|
||||||
|
for (IMethod m : klass.getDeclaredMethods()) {
|
||||||
|
if (m.toString().contains("foo")) {
|
||||||
|
// should throw WalaRuntimeException
|
||||||
|
cache.getIR(m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,100 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2008 IBM Corporation.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* IBM Corporation - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
package com.ibm.wala.examples.drivers;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
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.AnalysisScope;
|
||||||
|
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.DefaultEntrypoint;
|
||||||
|
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.types.ClassLoaderReference;
|
||||||
|
import com.ibm.wala.types.TypeReference;
|
||||||
|
import com.ibm.wala.util.config.AnalysisScopeReader;
|
||||||
|
import com.ibm.wala.util.io.CommandLine;
|
||||||
|
import com.ibm.wala.util.strings.StringStuff;
|
||||||
|
import com.ibm.wala.util.warnings.Warnings;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Driver that constructs a call graph for an application specified via a scope file.
|
||||||
|
* Useful for getting some code to copy-paste.
|
||||||
|
*/
|
||||||
|
public class ScopeFileCallGraph {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Usage: ScopeFileCallGraph -scopeFile file_path [-entryClass class_name |
|
||||||
|
* -mainClass class_name]
|
||||||
|
*
|
||||||
|
* If given -mainClass, uses main() method of class_name as entrypoint. If
|
||||||
|
* given -entryClass, uses all public methods of class_name.
|
||||||
|
*
|
||||||
|
* @throws IOException
|
||||||
|
* @throws ClassHierarchyException
|
||||||
|
* @throws CallGraphBuilderCancelException
|
||||||
|
* @throws IllegalArgumentException
|
||||||
|
*/
|
||||||
|
public static void main(String[] args) throws IOException, ClassHierarchyException, IllegalArgumentException,
|
||||||
|
CallGraphBuilderCancelException {
|
||||||
|
Properties p = CommandLine.parse(args);
|
||||||
|
String scopeFile = p.getProperty("scopeFile");
|
||||||
|
String entryClass = p.getProperty("entryClass");
|
||||||
|
String mainClass = p.getProperty("mainClass");
|
||||||
|
if (mainClass != null && entryClass != null) {
|
||||||
|
throw new IllegalArgumentException("only specify one of mainClass or entryClass");
|
||||||
|
}
|
||||||
|
// use exclusions to eliminate certain library packages
|
||||||
|
File exclusionsFile = null;
|
||||||
|
AnalysisScope scope = AnalysisScopeReader.readJavaScope(scopeFile, exclusionsFile, ScopeFileCallGraph.class.getClassLoader());
|
||||||
|
IClassHierarchy cha = ClassHierarchy.make(scope);
|
||||||
|
System.out.println(cha.getNumberOfClasses() + " classes");
|
||||||
|
System.out.println(Warnings.asString());
|
||||||
|
Warnings.clear();
|
||||||
|
AnalysisOptions options = new AnalysisOptions();
|
||||||
|
Iterable<Entrypoint> entrypoints = entryClass != null ? makePublicEntrypoints(scope, cha, entryClass) : Util.makeMainEntrypoints(scope, cha, mainClass);
|
||||||
|
options.setEntrypoints(entrypoints);
|
||||||
|
// you can dial down reflection handling if you like
|
||||||
|
// options.setReflectionOptions(ReflectionOptions.NONE);
|
||||||
|
AnalysisCache cache = new AnalysisCache();
|
||||||
|
// other builders can be constructed with different Util methods
|
||||||
|
CallGraphBuilder builder = Util.makeZeroOneContainerCFABuilder(options, cache, cha, scope);
|
||||||
|
System.out.println("building call graph...");
|
||||||
|
CallGraph cg = builder.makeCallGraph(options, null);
|
||||||
|
System.out.println("done");
|
||||||
|
System.out.println(CallGraphStats.getStats(cg));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Iterable<Entrypoint> makePublicEntrypoints(AnalysisScope scope, IClassHierarchy cha, String entryClass) {
|
||||||
|
Collection<Entrypoint> result = new ArrayList<Entrypoint>();
|
||||||
|
IClass klass = cha.lookupClass(TypeReference.findOrCreate(ClassLoaderReference.Application,
|
||||||
|
StringStuff.deployment2CanonicalTypeString(entryClass)));
|
||||||
|
for (IMethod m : klass.getDeclaredMethods()) {
|
||||||
|
if (m.isPublic()) {
|
||||||
|
result.add(new DefaultEntrypoint(m, cha));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
|
@ -34,5 +34,14 @@ public class FileProviderTest {
|
||||||
assertEquals(expected, actual);
|
assertEquals(expected, actual);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testURLWithSpace() throws MalformedURLException {
|
||||||
|
URL url = new URL("file:///With%20Space/File.jar");
|
||||||
|
String expected = PlatformUtil.onWindows() ? "/C:/With Space/File.jar" : "/With Space/File.jar";
|
||||||
|
// exercise:
|
||||||
|
String actual = (new FileProvider()).filePathFromURL(url);
|
||||||
|
// verify:
|
||||||
|
assertEquals(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -164,7 +164,7 @@ public class ClassNewInstanceContextInterpreter extends AbstractReflectionInterp
|
||||||
|
|
||||||
private IMethod getPublicDefaultCtor(IClass klass) {
|
private IMethod getPublicDefaultCtor(IClass klass) {
|
||||||
IMethod ctorMethod = klass.getMethod(defCtorSelector);
|
IMethod ctorMethod = klass.getMethod(defCtorSelector);
|
||||||
if (ctorMethod != null && ctorMethod.isPublic()) {
|
if (ctorMethod != null && ctorMethod.isPublic() && ctorMethod.getDeclaringClass() == klass) {
|
||||||
return ctorMethod;
|
return ctorMethod;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -24,6 +24,7 @@ import com.ibm.wala.shrikeBT.Constants;
|
||||||
import com.ibm.wala.types.Selector;
|
import com.ibm.wala.types.Selector;
|
||||||
import com.ibm.wala.types.TypeName;
|
import com.ibm.wala.types.TypeName;
|
||||||
import com.ibm.wala.types.TypeReference;
|
import com.ibm.wala.types.TypeReference;
|
||||||
|
import com.ibm.wala.types.annotations.Annotation;
|
||||||
import com.ibm.wala.util.collections.HashSetFactory;
|
import com.ibm.wala.util.collections.HashSetFactory;
|
||||||
import com.ibm.wala.util.debug.Assertions;
|
import com.ibm.wala.util.debug.Assertions;
|
||||||
import com.ibm.wala.util.debug.UnimplementedError;
|
import com.ibm.wala.util.debug.UnimplementedError;
|
||||||
|
@ -332,4 +333,8 @@ public class ArrayClass implements IClass, Constants {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Collection<Annotation> getAnnotations() {
|
||||||
|
return Collections.emptySet();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -223,16 +223,21 @@ public abstract class BytecodeClass<T extends IClassLoader> implements IClass {
|
||||||
|
|
||||||
|
|
||||||
public IField getField(Atom name, TypeName type) {
|
public IField getField(Atom name, TypeName type) {
|
||||||
|
boolean unresolved = false;
|
||||||
try {
|
try {
|
||||||
// typically, there will be at most one field with the name
|
// typically, there will be at most one field with the name
|
||||||
IField field = getField(name);
|
IField field = getField(name);
|
||||||
if (field != null && field.getFieldTypeReference().getName().equals(type)) {
|
if (field != null && field.getFieldTypeReference().getName().equals(type)) {
|
||||||
return field;
|
return field;
|
||||||
} else {
|
} else {
|
||||||
return null;
|
unresolved = true;
|
||||||
}
|
}
|
||||||
} catch (IllegalStateException e) {
|
} catch (IllegalStateException e) {
|
||||||
assert e.getMessage().startsWith("multiple fields with");
|
assert e.getMessage().startsWith("multiple fields with");
|
||||||
|
unresolved = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(unresolved){
|
||||||
// multiple fields. look through all of them and see if any have the appropriate type
|
// multiple fields. look through all of them and see if any have the appropriate type
|
||||||
List<IField> fields = findDeclaredField(name);
|
List<IField> fields = findDeclaredField(name);
|
||||||
for (IField f : fields) {
|
for (IField f : fields) {
|
||||||
|
|
|
@ -19,6 +19,7 @@ import com.ibm.wala.ipa.cha.IClassHierarchyDweller;
|
||||||
import com.ibm.wala.types.Selector;
|
import com.ibm.wala.types.Selector;
|
||||||
import com.ibm.wala.types.TypeName;
|
import com.ibm.wala.types.TypeName;
|
||||||
import com.ibm.wala.types.TypeReference;
|
import com.ibm.wala.types.TypeReference;
|
||||||
|
import com.ibm.wala.types.annotations.Annotation;
|
||||||
import com.ibm.wala.util.strings.Atom;
|
import com.ibm.wala.util.strings.Atom;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -178,4 +179,9 @@ public interface IClass extends IClassHierarchyDweller {
|
||||||
*/
|
*/
|
||||||
boolean isReferenceType();
|
boolean isReferenceType();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get annotations, if any
|
||||||
|
*/
|
||||||
|
Collection<Annotation> getAnnotations();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,10 @@
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package com.ibm.wala.classLoader;
|
package com.ibm.wala.classLoader;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
import com.ibm.wala.ipa.cha.IClassHierarchyDweller;
|
import com.ibm.wala.ipa.cha.IClassHierarchyDweller;
|
||||||
|
import com.ibm.wala.types.annotations.Annotation;
|
||||||
import com.ibm.wala.util.strings.Atom;
|
import com.ibm.wala.util.strings.Atom;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -38,4 +41,9 @@ public interface IMember extends IClassHierarchyDweller {
|
||||||
*/
|
*/
|
||||||
boolean isStatic();
|
boolean isStatic();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the annotations on this member, if any
|
||||||
|
*/
|
||||||
|
Collection<Annotation> getAnnotations();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -418,7 +418,7 @@ public abstract class ShrikeBTMethod implements IMethod, BytecodeConstants {
|
||||||
private void processBytecodesWithShrikeBT(BytecodeInfo info) throws InvalidClassFileException {
|
private void processBytecodesWithShrikeBT(BytecodeInfo info) throws InvalidClassFileException {
|
||||||
info.decoder = makeDecoder();
|
info.decoder = makeDecoder();
|
||||||
if (!isAbstract() && info.decoder == null) {
|
if (!isAbstract() && info.decoder == null) {
|
||||||
Assertions.UNREACHABLE("bad method " + getReference());
|
throw new InvalidClassFileException(-1, "non-abstract method " + getReference() + " has no bytecodes");
|
||||||
}
|
}
|
||||||
if (info.decoder == null) {
|
if (info.decoder == null) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -33,6 +33,7 @@ import com.ibm.wala.shrikeCT.SourcePositionTableReader.Position;
|
||||||
import com.ibm.wala.types.TypeReference;
|
import com.ibm.wala.types.TypeReference;
|
||||||
import com.ibm.wala.types.annotations.Annotation;
|
import com.ibm.wala.types.annotations.Annotation;
|
||||||
import com.ibm.wala.types.generics.MethodTypeSignature;
|
import com.ibm.wala.types.generics.MethodTypeSignature;
|
||||||
|
import com.ibm.wala.util.collections.HashSetFactory;
|
||||||
import com.ibm.wala.util.debug.Assertions;
|
import com.ibm.wala.util.debug.Assertions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -460,6 +461,16 @@ public final class ShrikeCTMethod extends ShrikeBTMethod implements IBytecodeMet
|
||||||
return Annotation.getAnnotationsFromReader(r, getDeclaringClass().getClassLoader().getReference());
|
return Annotation.getAnnotationsFromReader(r, getDeclaringClass().getClassLoader().getReference());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Collection<Annotation> getAnnotations() {
|
||||||
|
Collection<Annotation> result = HashSetFactory.make();
|
||||||
|
try {
|
||||||
|
result.addAll(getAnnotations(true));
|
||||||
|
result.addAll(getAnnotations(false));
|
||||||
|
} catch (InvalidClassFileException e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
private static final IndirectionData NO_INDIRECTIONS = new IndirectionData() {
|
private static final IndirectionData NO_INDIRECTIONS = new IndirectionData() {
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@ import com.ibm.wala.types.TypeName;
|
||||||
import com.ibm.wala.types.TypeReference;
|
import com.ibm.wala.types.TypeReference;
|
||||||
import com.ibm.wala.types.annotations.Annotation;
|
import com.ibm.wala.types.annotations.Annotation;
|
||||||
import com.ibm.wala.types.generics.ClassSignature;
|
import com.ibm.wala.types.generics.ClassSignature;
|
||||||
|
import com.ibm.wala.util.collections.HashSetFactory;
|
||||||
import com.ibm.wala.util.debug.Assertions;
|
import com.ibm.wala.util.debug.Assertions;
|
||||||
import com.ibm.wala.util.shrike.ShrikeClassReaderHandle;
|
import com.ibm.wala.util.shrike.ShrikeClassReaderHandle;
|
||||||
import com.ibm.wala.util.strings.Atom;
|
import com.ibm.wala.util.strings.Atom;
|
||||||
|
@ -226,6 +227,17 @@ public final class ShrikeClass extends JVMClass<IClassLoader> {
|
||||||
return getAnnotations(false);
|
return getAnnotations(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Collection<Annotation> getAnnotations() {
|
||||||
|
Collection<Annotation> result = HashSetFactory.make();
|
||||||
|
try {
|
||||||
|
result.addAll(getAnnotations(true));
|
||||||
|
result.addAll(getAnnotations(false));
|
||||||
|
} catch (InvalidClassFileException e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
public Collection<Annotation> getAnnotations(boolean runtimeInvisible) throws InvalidClassFileException {
|
public Collection<Annotation> getAnnotations(boolean runtimeInvisible) throws InvalidClassFileException {
|
||||||
AnnotationsReader r = getAnnotationsReader(runtimeInvisible);
|
AnnotationsReader r = getAnnotationsReader(runtimeInvisible);
|
||||||
return Annotation.getAnnotationsFromReader(r, getClassLoader().getReference());
|
return Annotation.getAnnotationsFromReader(r, getClassLoader().getReference());
|
||||||
|
|
|
@ -23,7 +23,7 @@ import com.ibm.wala.ssa.SSAOptions;
|
||||||
import com.ibm.wala.ssa.ShrikeIndirectionData;
|
import com.ibm.wala.ssa.ShrikeIndirectionData;
|
||||||
import com.ibm.wala.ssa.SymbolTable;
|
import com.ibm.wala.ssa.SymbolTable;
|
||||||
import com.ibm.wala.ssa.analysis.DeadAssignmentElimination;
|
import com.ibm.wala.ssa.analysis.DeadAssignmentElimination;
|
||||||
import com.ibm.wala.util.debug.Assertions;
|
import com.ibm.wala.util.WalaRuntimeException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An {@link IRFactory} that for methods that originate from Shrike.
|
* An {@link IRFactory} that for methods that originate from Shrike.
|
||||||
|
@ -45,8 +45,7 @@ public class ShrikeIRFactory implements IRFactory<IBytecodeMethod> {
|
||||||
try {
|
try {
|
||||||
shrikeInstructions = method.getInstructions();
|
shrikeInstructions = method.getInstructions();
|
||||||
} catch (InvalidClassFileException e) {
|
} catch (InvalidClassFileException e) {
|
||||||
e.printStackTrace();
|
throw new WalaRuntimeException("bad method bytecodes", e);
|
||||||
Assertions.UNREACHABLE();
|
|
||||||
}
|
}
|
||||||
final ShrikeCFG shrikeCFG = (ShrikeCFG) makeCFG(method, C);
|
final ShrikeCFG shrikeCFG = (ShrikeCFG) makeCFG(method, C);
|
||||||
|
|
||||||
|
|
|
@ -12,11 +12,14 @@
|
||||||
package com.ibm.wala.classLoader;
|
package com.ibm.wala.classLoader;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
import com.ibm.wala.ipa.cha.IClassHierarchy;
|
import com.ibm.wala.ipa.cha.IClassHierarchy;
|
||||||
import com.ibm.wala.types.ClassLoaderReference;
|
import com.ibm.wala.types.ClassLoaderReference;
|
||||||
import com.ibm.wala.types.TypeName;
|
import com.ibm.wala.types.TypeName;
|
||||||
import com.ibm.wala.types.TypeReference;
|
import com.ibm.wala.types.TypeReference;
|
||||||
|
import com.ibm.wala.types.annotations.Annotation;
|
||||||
import com.ibm.wala.util.strings.Atom;
|
import com.ibm.wala.util.strings.Atom;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -129,4 +132,10 @@ public abstract class SyntheticClass implements IClass {
|
||||||
public IField getField(Atom name, TypeName typeName) {
|
public IField getField(Atom name, TypeName typeName) {
|
||||||
return getField(name);
|
return getField(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Collection<Annotation> getAnnotations() {
|
||||||
|
return Collections.emptySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,9 @@
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package com.ibm.wala.classLoader;
|
package com.ibm.wala.classLoader;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
import com.ibm.wala.cfg.InducedCFG;
|
import com.ibm.wala.cfg.InducedCFG;
|
||||||
import com.ibm.wala.ipa.callgraph.Context;
|
import com.ibm.wala.ipa.callgraph.Context;
|
||||||
import com.ibm.wala.ipa.callgraph.impl.Everywhere;
|
import com.ibm.wala.ipa.callgraph.impl.Everywhere;
|
||||||
|
@ -22,6 +25,7 @@ import com.ibm.wala.types.Descriptor;
|
||||||
import com.ibm.wala.types.MethodReference;
|
import com.ibm.wala.types.MethodReference;
|
||||||
import com.ibm.wala.types.Selector;
|
import com.ibm.wala.types.Selector;
|
||||||
import com.ibm.wala.types.TypeReference;
|
import com.ibm.wala.types.TypeReference;
|
||||||
|
import com.ibm.wala.types.annotations.Annotation;
|
||||||
import com.ibm.wala.util.bytecode.BytecodeStream;
|
import com.ibm.wala.util.bytecode.BytecodeStream;
|
||||||
import com.ibm.wala.util.debug.UnimplementedError;
|
import com.ibm.wala.util.debug.UnimplementedError;
|
||||||
import com.ibm.wala.util.strings.Atom;
|
import com.ibm.wala.util.strings.Atom;
|
||||||
|
@ -380,4 +384,8 @@ public class SyntheticMethod implements IMethod {
|
||||||
return getDeclaringClass().getClassHierarchy();
|
return getDeclaringClass().getClassHierarchy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Collection<Annotation> getAnnotations() {
|
||||||
|
return Collections.emptySet();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,11 +37,15 @@
|
||||||
*/
|
*/
|
||||||
package com.ibm.wala.demandpa.util;
|
package com.ibm.wala.demandpa.util;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
import com.ibm.wala.classLoader.IClass;
|
import com.ibm.wala.classLoader.IClass;
|
||||||
import com.ibm.wala.classLoader.IField;
|
import com.ibm.wala.classLoader.IField;
|
||||||
import com.ibm.wala.ipa.cha.ClassHierarchy;
|
import com.ibm.wala.ipa.cha.ClassHierarchy;
|
||||||
import com.ibm.wala.types.FieldReference;
|
import com.ibm.wala.types.FieldReference;
|
||||||
import com.ibm.wala.types.TypeReference;
|
import com.ibm.wala.types.TypeReference;
|
||||||
|
import com.ibm.wala.types.annotations.Annotation;
|
||||||
import com.ibm.wala.util.debug.Assertions;
|
import com.ibm.wala.util.debug.Assertions;
|
||||||
import com.ibm.wala.util.debug.UnimplementedError;
|
import com.ibm.wala.util.debug.UnimplementedError;
|
||||||
import com.ibm.wala.util.strings.Atom;
|
import com.ibm.wala.util.strings.Atom;
|
||||||
|
@ -120,4 +124,8 @@ public class ArrayContents implements IField {
|
||||||
public FieldReference getReference() {
|
public FieldReference getReference() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Collection<Annotation> getAnnotations() {
|
||||||
|
return Collections.emptySet();
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,72 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2007 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.ipa.callgraph;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.ibm.wala.dataflow.graph.BitVectorSolver;
|
||||||
|
import com.ibm.wala.fixpoint.BitVectorVariable;
|
||||||
|
import com.ibm.wala.ipa.modref.GenReach;
|
||||||
|
import com.ibm.wala.util.CancelException;
|
||||||
|
import com.ibm.wala.util.CancelRuntimeException;
|
||||||
|
import com.ibm.wala.util.collections.HashMapFactory;
|
||||||
|
import com.ibm.wala.util.functions.Function;
|
||||||
|
import com.ibm.wala.util.graph.impl.GraphInverter;
|
||||||
|
import com.ibm.wala.util.intset.OrdinalSet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility class for computing an analysis result for call graph nodes and their
|
||||||
|
* transitive callees, given the results for individual nodes.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class CallGraphTransitiveClosure {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compute the transitive closure of an analysis result over all callees.
|
||||||
|
*
|
||||||
|
* @param cg the call graph
|
||||||
|
* @param nodeResults analysis result for each individual node
|
||||||
|
* @return a map from each node to the analysis result for the node and its transitive callees
|
||||||
|
*/
|
||||||
|
public static <T> Map<CGNode, OrdinalSet<T>> transitiveClosure(CallGraph cg, Map<CGNode, Collection<T>> nodeResults) {
|
||||||
|
try {
|
||||||
|
// invert the call graph, to compute the bottom-up result
|
||||||
|
GenReach<CGNode, T> gr = new GenReach<CGNode, T>(GraphInverter.invert(cg), nodeResults);
|
||||||
|
BitVectorSolver<CGNode> solver = new BitVectorSolver<CGNode>(gr);
|
||||||
|
solver.solve(null);
|
||||||
|
Map<CGNode, OrdinalSet<T>> result = HashMapFactory.make();
|
||||||
|
for (Iterator<? extends CGNode> it = cg.iterator(); it.hasNext();) {
|
||||||
|
CGNode n = it.next();
|
||||||
|
BitVectorVariable bv = solver.getOut(n);
|
||||||
|
result.put(n, new OrdinalSet<T>(bv.getValue(), gr.getLatticeValues()));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
} catch (CancelException e) {
|
||||||
|
throw new CancelRuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Collect analysis result for each {@link CGNode} in a {@link Map}.
|
||||||
|
*/
|
||||||
|
public static <T> Map<CGNode, Collection<T>> collectNodeResults(CallGraph cg, Function<CGNode, Collection<T>> nodeResultComputer) {
|
||||||
|
Map<CGNode, Collection<T>> result = HashMapFactory.make();
|
||||||
|
for (Iterator<? extends CGNode> it = cg.iterator(); it.hasNext();) {
|
||||||
|
CGNode n = it.next();
|
||||||
|
result.put(n, nodeResultComputer.apply(n));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -26,6 +26,7 @@ import com.ibm.wala.types.FieldReference;
|
||||||
import com.ibm.wala.types.Selector;
|
import com.ibm.wala.types.Selector;
|
||||||
import com.ibm.wala.types.TypeName;
|
import com.ibm.wala.types.TypeName;
|
||||||
import com.ibm.wala.types.TypeReference;
|
import com.ibm.wala.types.TypeReference;
|
||||||
|
import com.ibm.wala.types.annotations.Annotation;
|
||||||
import com.ibm.wala.util.collections.HashMapFactory;
|
import com.ibm.wala.util.collections.HashMapFactory;
|
||||||
import com.ibm.wala.util.collections.HashSetFactory;
|
import com.ibm.wala.util.collections.HashSetFactory;
|
||||||
import com.ibm.wala.util.debug.Assertions;
|
import com.ibm.wala.util.debug.Assertions;
|
||||||
|
@ -104,6 +105,10 @@ public class FakeRootClass extends SyntheticClass {
|
||||||
public boolean isPublic() {
|
public boolean isPublic() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Collection<Annotation> getAnnotations() {
|
||||||
|
return Collections.emptySet();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,11 +10,19 @@
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package com.ibm.wala.ipa.callgraph.propagation;
|
package com.ibm.wala.ipa.callgraph.propagation;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
import com.ibm.wala.classLoader.IClass;
|
import com.ibm.wala.classLoader.IClass;
|
||||||
import com.ibm.wala.classLoader.IMethod;
|
import com.ibm.wala.classLoader.IMethod;
|
||||||
import com.ibm.wala.classLoader.NewSiteReference;
|
import com.ibm.wala.classLoader.NewSiteReference;
|
||||||
import com.ibm.wala.ipa.callgraph.CGNode;
|
import com.ibm.wala.ipa.callgraph.CGNode;
|
||||||
|
import com.ibm.wala.ipa.callgraph.CallGraph;
|
||||||
import com.ibm.wala.ipa.callgraph.Context;
|
import com.ibm.wala.ipa.callgraph.Context;
|
||||||
|
import com.ibm.wala.util.collections.Filter;
|
||||||
|
import com.ibm.wala.util.collections.FilterIterator;
|
||||||
|
import com.ibm.wala.util.collections.MapIterator;
|
||||||
|
import com.ibm.wala.util.collections.Pair;
|
||||||
|
import com.ibm.wala.util.functions.Function;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An {@link InstanceKey} which represents a {@link NewSiteReference} in some {@link IMethod}. Note that this differs from
|
* An {@link InstanceKey} which represents a {@link NewSiteReference} in some {@link IMethod}. Note that this differs from
|
||||||
|
@ -81,4 +89,21 @@ public class AllocationSite implements InstanceKey {
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Iterator<Pair<CGNode, NewSiteReference>> getCreationSites(CallGraph CG) {
|
||||||
|
return new MapIterator<CGNode, Pair<CGNode, NewSiteReference>>(
|
||||||
|
new FilterIterator<CGNode>(
|
||||||
|
CG.getNodes(method.getReference()).iterator(),
|
||||||
|
new Filter<CGNode>() {
|
||||||
|
public boolean accepts(CGNode o) {
|
||||||
|
return o.getMethod().equals(method);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
),
|
||||||
|
new Function<CGNode, Pair<CGNode, NewSiteReference>>() {
|
||||||
|
public Pair<CGNode, NewSiteReference> apply(CGNode object) {
|
||||||
|
return Pair.make(object, site);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,9 +10,14 @@
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package com.ibm.wala.ipa.callgraph.propagation;
|
package com.ibm.wala.ipa.callgraph.propagation;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
import com.ibm.wala.classLoader.IClass;
|
import com.ibm.wala.classLoader.IClass;
|
||||||
import com.ibm.wala.classLoader.NewSiteReference;
|
import com.ibm.wala.classLoader.NewSiteReference;
|
||||||
import com.ibm.wala.ipa.callgraph.CGNode;
|
import com.ibm.wala.ipa.callgraph.CGNode;
|
||||||
|
import com.ibm.wala.ipa.callgraph.CallGraph;
|
||||||
|
import com.ibm.wala.util.collections.NonNullSingletonIterator;
|
||||||
|
import com.ibm.wala.util.collections.Pair;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An {@link InstanceKey} which represents a {@link NewSiteReference} in some {@link CGNode}.
|
* An {@link InstanceKey} which represents a {@link NewSiteReference} in some {@link CGNode}.
|
||||||
|
@ -42,4 +47,9 @@ public abstract class AllocationSiteInNode extends AbstractTypeInNode {
|
||||||
public NewSiteReference getSite() {
|
public NewSiteReference getSite() {
|
||||||
return site;
|
return site;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Iterator<Pair<CGNode, NewSiteReference>> getCreationSites(CallGraph CG) {
|
||||||
|
return new NonNullSingletonIterator<Pair<CGNode, NewSiteReference>>(Pair.make(getNode(), getSite()));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,11 +14,20 @@ import java.util.Collection;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
|
||||||
import com.ibm.wala.classLoader.IClass;
|
import com.ibm.wala.classLoader.IClass;
|
||||||
|
import com.ibm.wala.classLoader.NewSiteReference;
|
||||||
|
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.ipa.cha.IClassHierarchy;
|
||||||
import com.ibm.wala.ssa.IR;
|
import com.ibm.wala.ssa.IR;
|
||||||
import com.ibm.wala.ssa.SSAInstruction;
|
import com.ibm.wala.ssa.SSAInstruction;
|
||||||
import com.ibm.wala.types.TypeReference;
|
import com.ibm.wala.types.TypeReference;
|
||||||
|
import com.ibm.wala.util.collections.ComposedIterator;
|
||||||
|
import com.ibm.wala.util.collections.Filter;
|
||||||
|
import com.ibm.wala.util.collections.FilterIterator;
|
||||||
|
import com.ibm.wala.util.collections.MapIterator;
|
||||||
|
import com.ibm.wala.util.collections.Pair;
|
||||||
import com.ibm.wala.util.debug.Assertions;
|
import com.ibm.wala.util.debug.Assertions;
|
||||||
|
import com.ibm.wala.util.functions.Function;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An instance key which represents a unique set for each concrete type
|
* An instance key which represents a unique set for each concrete type
|
||||||
|
@ -92,4 +101,26 @@ public final class ConcreteTypeKey implements InstanceKey {
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Iterator<Pair<CGNode, NewSiteReference>> getCreationSites(CallGraph CG) {
|
||||||
|
return new ComposedIterator<CGNode, Pair<CGNode, NewSiteReference>>(CG.iterator()) {
|
||||||
|
@Override
|
||||||
|
public Iterator<? extends Pair<CGNode, NewSiteReference>> makeInner(final CGNode outer) {
|
||||||
|
return new MapIterator<NewSiteReference, Pair<CGNode, NewSiteReference>>(
|
||||||
|
new FilterIterator<NewSiteReference>(
|
||||||
|
outer.iterateNewSites(),
|
||||||
|
new Filter<NewSiteReference>() {
|
||||||
|
public boolean accepts(NewSiteReference o) {
|
||||||
|
return o.getDeclaredType().equals(type.getReference());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
),
|
||||||
|
new Function<NewSiteReference, Pair<CGNode, NewSiteReference>>() {
|
||||||
|
public Pair<CGNode, NewSiteReference> apply(NewSiteReference object) {
|
||||||
|
return Pair.make(outer, object);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -10,7 +10,14 @@
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package com.ibm.wala.ipa.callgraph.propagation;
|
package com.ibm.wala.ipa.callgraph.propagation;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
import com.ibm.wala.classLoader.IClass;
|
import com.ibm.wala.classLoader.IClass;
|
||||||
|
import com.ibm.wala.classLoader.NewSiteReference;
|
||||||
|
import com.ibm.wala.ipa.callgraph.CGNode;
|
||||||
|
import com.ibm.wala.ipa.callgraph.CallGraph;
|
||||||
|
import com.ibm.wala.util.collections.EmptyIterator;
|
||||||
|
import com.ibm.wala.util.collections.Pair;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An instance key which represents a unique, constant object
|
* An instance key which represents a unique, constant object
|
||||||
|
@ -58,4 +65,8 @@ public final class ConstantKey<T> implements InstanceKey {
|
||||||
public T getValue() {
|
public T getValue() {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Iterator<Pair<CGNode, NewSiteReference>> getCreationSites(CallGraph CG) {
|
||||||
|
return EmptyIterator.instance();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,8 +10,14 @@
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package com.ibm.wala.ipa.callgraph.propagation;
|
package com.ibm.wala.ipa.callgraph.propagation;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
import com.ibm.wala.classLoader.IClass;
|
import com.ibm.wala.classLoader.IClass;
|
||||||
|
import com.ibm.wala.classLoader.NewSiteReference;
|
||||||
|
import com.ibm.wala.ipa.callgraph.CGNode;
|
||||||
|
import com.ibm.wala.ipa.callgraph.CallGraph;
|
||||||
import com.ibm.wala.ipa.callgraph.ContextItem;
|
import com.ibm.wala.ipa.callgraph.ContextItem;
|
||||||
|
import com.ibm.wala.util.collections.Pair;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An InstanceKey serves as the representative for an equivalence class of
|
* An InstanceKey serves as the representative for an equivalence class of
|
||||||
|
@ -32,5 +38,14 @@ public interface InstanceKey extends ContextItem {
|
||||||
*/
|
*/
|
||||||
IClass getConcreteType();
|
IClass getConcreteType();
|
||||||
|
|
||||||
}
|
/**
|
||||||
|
* Get the creation sites of <code>this</code>, i.e., the statements that may
|
||||||
|
* allocate objects represented by <code>this</code>. A creation site is a
|
||||||
|
* pair (n,s), where n is the containing {@link CGNode} in the given
|
||||||
|
* {@link CallGraph} <code>CG</code> and s is the allocating
|
||||||
|
* {@link NewSiteReference}.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
Iterator<Pair<CGNode, NewSiteReference>> getCreationSites(CallGraph CG);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -10,8 +10,17 @@
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package com.ibm.wala.ipa.callgraph.propagation;
|
package com.ibm.wala.ipa.callgraph.propagation;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
import com.ibm.wala.classLoader.IClass;
|
import com.ibm.wala.classLoader.IClass;
|
||||||
|
import com.ibm.wala.classLoader.NewSiteReference;
|
||||||
import com.ibm.wala.ipa.callgraph.CGNode;
|
import com.ibm.wala.ipa.callgraph.CGNode;
|
||||||
|
import com.ibm.wala.ipa.callgraph.CallGraph;
|
||||||
|
import com.ibm.wala.util.collections.Filter;
|
||||||
|
import com.ibm.wala.util.collections.FilterIterator;
|
||||||
|
import com.ibm.wala.util.collections.MapIterator;
|
||||||
|
import com.ibm.wala.util.collections.Pair;
|
||||||
|
import com.ibm.wala.util.functions.Function;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An {@link InstanceKey} which represents the set of all allocation sites
|
* An {@link InstanceKey} which represents the set of all allocation sites
|
||||||
|
@ -44,4 +53,20 @@ public class SmushedAllocationSiteInNode extends AbstractTypeInNode {
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "SMUSHED " + getNode() + " : " + getConcreteType();
|
return "SMUSHED " + getNode() + " : " + getConcreteType();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Iterator<Pair<CGNode, NewSiteReference>> getCreationSites(CallGraph CG) {
|
||||||
|
return new MapIterator<NewSiteReference,Pair<CGNode, NewSiteReference>>(
|
||||||
|
new FilterIterator<NewSiteReference>(
|
||||||
|
getNode().iterateNewSites(),
|
||||||
|
new Filter<NewSiteReference>() {
|
||||||
|
public boolean accepts(NewSiteReference o) {
|
||||||
|
return o.getDeclaredType().equals(getConcreteType().getReference());
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
new Function<NewSiteReference,Pair<CGNode, NewSiteReference>>() {
|
||||||
|
public Pair<CGNode, NewSiteReference> apply(NewSiteReference object) {
|
||||||
|
return Pair.make(getNode(), object);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,8 +10,15 @@
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package com.ibm.wala.ipa.callgraph.propagation;
|
package com.ibm.wala.ipa.callgraph.propagation;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
import com.ibm.wala.classLoader.IClass;
|
import com.ibm.wala.classLoader.IClass;
|
||||||
|
import com.ibm.wala.classLoader.NewSiteReference;
|
||||||
|
import com.ibm.wala.ipa.callgraph.CGNode;
|
||||||
|
import com.ibm.wala.ipa.callgraph.CallGraph;
|
||||||
import com.ibm.wala.types.TypeReference;
|
import com.ibm.wala.types.TypeReference;
|
||||||
|
import com.ibm.wala.util.collections.EmptyIterator;
|
||||||
|
import com.ibm.wala.util.collections.Pair;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An {@link InstanceKey} which represents the constant char[] contents
|
* An {@link InstanceKey} which represents the constant char[] contents
|
||||||
|
@ -65,4 +72,8 @@ public class StringConstantCharArray implements InstanceKey {
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "StringConstantCharArray:" + constant;
|
return "StringConstantCharArray:" + constant;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Iterator<Pair<CGNode, NewSiteReference>> getCreationSites(CallGraph CG) {
|
||||||
|
return EmptyIterator.instance();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,10 +17,9 @@ import java.util.Set;
|
||||||
|
|
||||||
import com.ibm.wala.classLoader.IClass;
|
import com.ibm.wala.classLoader.IClass;
|
||||||
import com.ibm.wala.classLoader.IField;
|
import com.ibm.wala.classLoader.IField;
|
||||||
import com.ibm.wala.dataflow.graph.BitVectorSolver;
|
|
||||||
import com.ibm.wala.fixpoint.BitVectorVariable;
|
|
||||||
import com.ibm.wala.ipa.callgraph.CGNode;
|
import com.ibm.wala.ipa.callgraph.CGNode;
|
||||||
import com.ibm.wala.ipa.callgraph.CallGraph;
|
import com.ibm.wala.ipa.callgraph.CallGraph;
|
||||||
|
import com.ibm.wala.ipa.callgraph.CallGraphTransitiveClosure;
|
||||||
import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
|
import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
|
||||||
import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis;
|
import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis;
|
||||||
import com.ibm.wala.ipa.callgraph.propagation.PointerKey;
|
import com.ibm.wala.ipa.callgraph.propagation.PointerKey;
|
||||||
|
@ -33,11 +32,8 @@ import com.ibm.wala.ssa.SSAGetInstruction;
|
||||||
import com.ibm.wala.ssa.SSAInstruction;
|
import com.ibm.wala.ssa.SSAInstruction;
|
||||||
import com.ibm.wala.ssa.SSANewInstruction;
|
import com.ibm.wala.ssa.SSANewInstruction;
|
||||||
import com.ibm.wala.ssa.SSAPutInstruction;
|
import com.ibm.wala.ssa.SSAPutInstruction;
|
||||||
import com.ibm.wala.util.CancelException;
|
|
||||||
import com.ibm.wala.util.CancelRuntimeException;
|
|
||||||
import com.ibm.wala.util.collections.HashMapFactory;
|
|
||||||
import com.ibm.wala.util.collections.HashSetFactory;
|
import com.ibm.wala.util.collections.HashSetFactory;
|
||||||
import com.ibm.wala.util.graph.impl.GraphInverter;
|
import com.ibm.wala.util.functions.Function;
|
||||||
import com.ibm.wala.util.intset.OrdinalSet;
|
import com.ibm.wala.util.intset.OrdinalSet;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -66,7 +62,7 @@ public class ModRef {
|
||||||
throw new IllegalArgumentException("cg is null");
|
throw new IllegalArgumentException("cg is null");
|
||||||
}
|
}
|
||||||
Map<CGNode, Collection<PointerKey>> scan = scanForMod(cg, pa, heapExclude);
|
Map<CGNode, Collection<PointerKey>> scan = scanForMod(cg, pa, heapExclude);
|
||||||
return transitiveClosure(cg, scan);
|
return CallGraphTransitiveClosure.transitiveClosure(cg, scan);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -80,7 +76,7 @@ public class ModRef {
|
||||||
throw new IllegalArgumentException("cg is null");
|
throw new IllegalArgumentException("cg is null");
|
||||||
}
|
}
|
||||||
Map<CGNode, Collection<PointerKey>> scan = scanForRef(cg, pa, heapExclude);
|
Map<CGNode, Collection<PointerKey>> scan = scanForRef(cg, pa, heapExclude);
|
||||||
return transitiveClosure(cg, scan);
|
return CallGraphTransitiveClosure.transitiveClosure(cg, scan);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -99,36 +95,20 @@ public class ModRef {
|
||||||
return computeRef(cg, pa, null);
|
return computeRef(cg, pa, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<CGNode, OrdinalSet<PointerKey>> transitiveClosure(CallGraph cg, Map<CGNode, Collection<PointerKey>> scan) {
|
|
||||||
try {
|
|
||||||
GenReach<CGNode, PointerKey> gr = new GenReach<CGNode, PointerKey>(GraphInverter.invert(cg), scan);
|
|
||||||
BitVectorSolver<CGNode> solver = new BitVectorSolver<CGNode>(gr);
|
|
||||||
solver.solve(null);
|
|
||||||
Map<CGNode, OrdinalSet<PointerKey>> result = HashMapFactory.make();
|
|
||||||
for (Iterator<? extends CGNode> it = cg.iterator(); it.hasNext();) {
|
|
||||||
CGNode n = it.next();
|
|
||||||
BitVectorVariable bv = solver.getOut(n);
|
|
||||||
result.put(n, new OrdinalSet<PointerKey>(bv.getValue(), gr.getLatticeValues()));
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
} catch (CancelException e) {
|
|
||||||
throw new CancelRuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For each call graph node, what heap locations (as determined by a heap model) may it write, <bf> NOT </bf> including its
|
* For each call graph node, what heap locations (as determined by a heap model) may it write, <bf> NOT </bf> including its
|
||||||
* callees transitively
|
* callees transitively
|
||||||
*
|
*
|
||||||
* @param heapExclude
|
* @param heapExclude
|
||||||
*/
|
*/
|
||||||
private Map<CGNode, Collection<PointerKey>> scanForMod(CallGraph cg, PointerAnalysis pa, HeapExclusions heapExclude) {
|
private Map<CGNode, Collection<PointerKey>> scanForMod(CallGraph cg, final PointerAnalysis pa, final HeapExclusions heapExclude) {
|
||||||
Map<CGNode, Collection<PointerKey>> result = HashMapFactory.make();
|
|
||||||
for (Iterator<? extends CGNode> it = cg.iterator(); it.hasNext();) {
|
return CallGraphTransitiveClosure.collectNodeResults(cg, new Function<CGNode, Collection<PointerKey>>() {
|
||||||
CGNode n = it.next();
|
|
||||||
result.put(n, scanNodeForMod(n, pa, heapExclude));
|
public Collection<PointerKey> apply(CGNode n) {
|
||||||
}
|
return scanNodeForMod(n, pa, heapExclude);
|
||||||
return result;
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -137,13 +117,13 @@ public class ModRef {
|
||||||
*
|
*
|
||||||
* @param heapExclude
|
* @param heapExclude
|
||||||
*/
|
*/
|
||||||
private Map<CGNode, Collection<PointerKey>> scanForRef(CallGraph cg, PointerAnalysis pa, HeapExclusions heapExclude) {
|
private Map<CGNode, Collection<PointerKey>> scanForRef(CallGraph cg, final PointerAnalysis pa, final HeapExclusions heapExclude) {
|
||||||
Map<CGNode, Collection<PointerKey>> result = HashMapFactory.make();
|
return CallGraphTransitiveClosure.collectNodeResults(cg, new Function<CGNode, Collection<PointerKey>>() {
|
||||||
for (Iterator<? extends CGNode> it = cg.iterator(); it.hasNext();) {
|
|
||||||
CGNode n = it.next();
|
public Collection<PointerKey> apply(CGNode n) {
|
||||||
result.put(n, scanNodeForRef(n, pa, heapExclude));
|
return scanNodeForRef(n, pa, heapExclude);
|
||||||
}
|
}
|
||||||
return result;
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -12,6 +12,7 @@ package com.ibm.wala.ipa.summaries;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
|
||||||
import com.ibm.wala.classLoader.IClass;
|
import com.ibm.wala.classLoader.IClass;
|
||||||
|
@ -23,6 +24,7 @@ import com.ibm.wala.ipa.cha.IClassHierarchy;
|
||||||
import com.ibm.wala.types.Selector;
|
import com.ibm.wala.types.Selector;
|
||||||
import com.ibm.wala.types.TypeName;
|
import com.ibm.wala.types.TypeName;
|
||||||
import com.ibm.wala.types.TypeReference;
|
import com.ibm.wala.types.TypeReference;
|
||||||
|
import com.ibm.wala.types.annotations.Annotation;
|
||||||
import com.ibm.wala.util.collections.HashSetFactory;
|
import com.ibm.wala.util.collections.HashSetFactory;
|
||||||
import com.ibm.wala.util.debug.Assertions;
|
import com.ibm.wala.util.debug.Assertions;
|
||||||
import com.ibm.wala.util.debug.UnimplementedError;
|
import com.ibm.wala.util.debug.UnimplementedError;
|
||||||
|
@ -244,4 +246,8 @@ public class BypassSyntheticClass extends SyntheticClass {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Collection<Annotation> getAnnotations() {
|
||||||
|
return Collections.emptySet();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -154,7 +154,7 @@ public class AnalysisScopeReader {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param classPath class path to analyze, delimited by File.pathSeparator
|
* @param classPath class path to analyze, delimited by {@link File#pathSeparator}
|
||||||
* @param exclusionsFile file holding class hierarchy exclusions. may be null
|
* @param exclusionsFile file holding class hierarchy exclusions. may be null
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
* @throws IllegalStateException if there are problems reading wala properties
|
* @throws IllegalStateException if there are problems reading wala properties
|
||||||
|
|
|
@ -14,10 +14,12 @@ import java.io.File;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.net.JarURLConnection;
|
import java.net.JarURLConnection;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.net.URLConnection;
|
import java.net.URLConnection;
|
||||||
|
import java.net.URLDecoder;
|
||||||
import java.util.jar.JarEntry;
|
import java.util.jar.JarEntry;
|
||||||
import java.util.jar.JarFile;
|
import java.util.jar.JarFile;
|
||||||
import java.util.jar.JarInputStream;
|
import java.util.jar.JarInputStream;
|
||||||
|
@ -27,6 +29,7 @@ import com.ibm.wala.classLoader.JarFileModule;
|
||||||
import com.ibm.wala.classLoader.JarStreamModule;
|
import com.ibm.wala.classLoader.JarStreamModule;
|
||||||
import com.ibm.wala.classLoader.Module;
|
import com.ibm.wala.classLoader.Module;
|
||||||
import com.ibm.wala.classLoader.NestedJarFileModule;
|
import com.ibm.wala.classLoader.NestedJarFileModule;
|
||||||
|
import com.ibm.wala.util.debug.Assertions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class provides files that are packaged with this plug-in
|
* This class provides files that are packaged with this plug-in
|
||||||
|
@ -190,9 +193,15 @@ public class FileProvider {
|
||||||
// http://www.faqs.org/rfcs/rfc2396.html Section 2.4.3
|
// http://www.faqs.org/rfcs/rfc2396.html Section 2.4.3
|
||||||
// This solution works. See discussion at
|
// This solution works. See discussion at
|
||||||
// http://stackoverflow.com/questions/4494063/how-to-avoid-java-net-urisyntaxexception-in-url-touri
|
// http://stackoverflow.com/questions/4494063/how-to-avoid-java-net-urisyntaxexception-in-url-touri
|
||||||
URI uri = new File(url.getPath()).toURI();
|
// we assume url has been properly encoded, so we decode it
|
||||||
String filePath = uri.getPath();
|
try {
|
||||||
return filePath;
|
URI uri = new File(URLDecoder.decode(url.getPath(), "UTF-8")).toURI();
|
||||||
|
return uri.getPath();
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
// this really shouldn't happen
|
||||||
|
Assertions.UNREACHABLE();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,11 +47,13 @@ import java.util.LinkedHashMap;
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import org.eclipse.core.resources.IFile;
|
import org.eclipse.core.resources.IFile;
|
||||||
import org.eclipse.jdt.core.dom.AST;
|
import org.eclipse.jdt.core.dom.AST;
|
||||||
import org.eclipse.jdt.core.dom.ASTNode;
|
import org.eclipse.jdt.core.dom.ASTNode;
|
||||||
import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
|
import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
|
||||||
|
import org.eclipse.jdt.core.dom.Annotation;
|
||||||
import org.eclipse.jdt.core.dom.AnnotationTypeDeclaration;
|
import org.eclipse.jdt.core.dom.AnnotationTypeDeclaration;
|
||||||
import org.eclipse.jdt.core.dom.AnnotationTypeMemberDeclaration;
|
import org.eclipse.jdt.core.dom.AnnotationTypeMemberDeclaration;
|
||||||
import org.eclipse.jdt.core.dom.AnonymousClassDeclaration;
|
import org.eclipse.jdt.core.dom.AnonymousClassDeclaration;
|
||||||
|
@ -82,6 +84,9 @@ import org.eclipse.jdt.core.dom.ExpressionStatement;
|
||||||
import org.eclipse.jdt.core.dom.FieldAccess;
|
import org.eclipse.jdt.core.dom.FieldAccess;
|
||||||
import org.eclipse.jdt.core.dom.FieldDeclaration;
|
import org.eclipse.jdt.core.dom.FieldDeclaration;
|
||||||
import org.eclipse.jdt.core.dom.ForStatement;
|
import org.eclipse.jdt.core.dom.ForStatement;
|
||||||
|
import org.eclipse.jdt.core.dom.IAnnotationBinding;
|
||||||
|
import org.eclipse.jdt.core.dom.IBinding;
|
||||||
|
import org.eclipse.jdt.core.dom.IMemberValuePairBinding;
|
||||||
import org.eclipse.jdt.core.dom.IMethodBinding;
|
import org.eclipse.jdt.core.dom.IMethodBinding;
|
||||||
import org.eclipse.jdt.core.dom.ITypeBinding;
|
import org.eclipse.jdt.core.dom.ITypeBinding;
|
||||||
import org.eclipse.jdt.core.dom.IVariableBinding;
|
import org.eclipse.jdt.core.dom.IVariableBinding;
|
||||||
|
@ -131,6 +136,7 @@ import com.ibm.wala.cast.java.loader.JavaSourceLoaderImpl;
|
||||||
import com.ibm.wala.cast.java.loader.Util;
|
import com.ibm.wala.cast.java.loader.Util;
|
||||||
import com.ibm.wala.cast.java.translator.JavaProcedureEntity;
|
import com.ibm.wala.cast.java.translator.JavaProcedureEntity;
|
||||||
import com.ibm.wala.cast.tree.CAst;
|
import com.ibm.wala.cast.tree.CAst;
|
||||||
|
import com.ibm.wala.cast.tree.CAstAnnotation;
|
||||||
import com.ibm.wala.cast.tree.CAstControlFlowMap;
|
import com.ibm.wala.cast.tree.CAstControlFlowMap;
|
||||||
import com.ibm.wala.cast.tree.CAstEntity;
|
import com.ibm.wala.cast.tree.CAstEntity;
|
||||||
import com.ibm.wala.cast.tree.CAstNode;
|
import com.ibm.wala.cast.tree.CAstNode;
|
||||||
|
@ -152,6 +158,7 @@ import com.ibm.wala.types.MethodReference;
|
||||||
import com.ibm.wala.types.TypeReference;
|
import com.ibm.wala.types.TypeReference;
|
||||||
import com.ibm.wala.util.collections.EmptyIterator;
|
import com.ibm.wala.util.collections.EmptyIterator;
|
||||||
import com.ibm.wala.util.collections.HashMapFactory;
|
import com.ibm.wala.util.collections.HashMapFactory;
|
||||||
|
import com.ibm.wala.util.collections.HashSetFactory;
|
||||||
import com.ibm.wala.util.collections.Pair;
|
import com.ibm.wala.util.collections.Pair;
|
||||||
import com.ibm.wala.util.debug.Assertions;
|
import com.ibm.wala.util.debug.Assertions;
|
||||||
|
|
||||||
|
@ -268,16 +275,26 @@ public class JDTJava2CAstTranslator {
|
||||||
|
|
||||||
private final JdtPosition fSourcePosition;
|
private final JdtPosition fSourcePosition;
|
||||||
|
|
||||||
|
private final Set<CAstAnnotation> annotations;
|
||||||
|
|
||||||
public ClassEntity(ITypeBinding jdtType, String name, Collection<CAstQualifier> quals, Collection<CAstEntity> entities,
|
public ClassEntity(ITypeBinding jdtType, String name, Collection<CAstQualifier> quals, Collection<CAstEntity> entities,
|
||||||
JdtPosition pos) {
|
JdtPosition pos, Set<CAstAnnotation> annotations) {
|
||||||
fName = name;
|
fName = name;
|
||||||
fQuals = quals;
|
fQuals = quals;
|
||||||
fEntities = entities;
|
fEntities = entities;
|
||||||
fJdtType = jdtType;
|
fJdtType = jdtType;
|
||||||
fSourcePosition = pos;
|
fSourcePosition = pos;
|
||||||
|
this.annotations = annotations;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getKind() {
|
@Override
|
||||||
|
public Collection<CAstAnnotation> getAnnotations() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public int getKind() {
|
||||||
return TYPE_ENTITY;
|
return TYPE_ENTITY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -423,8 +440,10 @@ public class JDTJava2CAstTranslator {
|
||||||
Collection<CAstQualifier> quals = JDT2CAstUtils.mapModifiersToQualifiers(fieldDecl.getModifiers(), false, false);
|
Collection<CAstQualifier> quals = JDT2CAstUtils.mapModifiersToQualifiers(fieldDecl.getModifiers(), false, false);
|
||||||
for (Object f : fieldDecl.fragments()) {
|
for (Object f : fieldDecl.fragments()) {
|
||||||
VariableDeclarationFragment fieldFrag = (VariableDeclarationFragment) f;
|
VariableDeclarationFragment fieldFrag = (VariableDeclarationFragment) f;
|
||||||
memberEntities.add(new FieldEntity(fieldFrag.getName().getIdentifier(), fieldFrag.resolveBinding().getType(), quals,
|
IVariableBinding fieldBinding = fieldFrag.resolveBinding();
|
||||||
makePosition(fieldFrag.getStartPosition(), fieldFrag.getStartPosition() + fieldFrag.getLength())));
|
memberEntities.add(new FieldEntity(fieldFrag.getName().getIdentifier(), fieldBinding.getType(), quals,
|
||||||
|
makePosition(fieldFrag.getStartPosition(), fieldFrag.getStartPosition() + fieldFrag.getLength()),
|
||||||
|
handleAnnotations(fieldBinding)));
|
||||||
}
|
}
|
||||||
} else if (decl instanceof Initializer) {
|
} else if (decl instanceof Initializer) {
|
||||||
// Initializers are inserted into constructors when making constructors.
|
// Initializers are inserted into constructors when making constructors.
|
||||||
|
@ -481,11 +500,14 @@ public class JDTJava2CAstTranslator {
|
||||||
for (int i = 0; i < staticInits.size(); i++)
|
for (int i = 0; i < staticInits.size(); i++)
|
||||||
bodyNodes[i] = visitFieldInitNode(staticInits.get(i), newContext);
|
bodyNodes[i] = visitFieldInitNode(staticInits.get(i), newContext);
|
||||||
CAstNode staticInitAst = makeNode(newContext, fFactory, n, CAstNode.BLOCK_STMT, bodyNodes);
|
CAstNode staticInitAst = makeNode(newContext, fFactory, n, CAstNode.BLOCK_STMT, bodyNodes);
|
||||||
memberEntities.add(new ProcedureEntity(staticInitAst, typeBinding, childEntities, newContext));
|
memberEntities.add(new ProcedureEntity(staticInitAst, typeBinding, childEntities, newContext, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
Collection<CAstQualifier> quals = JDT2CAstUtils.mapModifiersToQualifiers(modifiers, isInterface, isAnnotation);
|
Collection<CAstQualifier> quals = JDT2CAstUtils.mapModifiersToQualifiers(modifiers, isInterface, isAnnotation);
|
||||||
return new ClassEntity(typeBinding, name, quals, memberEntities, makePosition(n));
|
|
||||||
|
Set<CAstAnnotation> annotations = handleAnnotations(typeBinding);
|
||||||
|
|
||||||
|
return new ClassEntity(typeBinding, name, quals, memberEntities, makePosition(n), annotations);
|
||||||
}
|
}
|
||||||
|
|
||||||
private CAstEntity visit(AnonymousClassDeclaration n, WalkContext context) {
|
private CAstEntity visit(AnonymousClassDeclaration n, WalkContext context) {
|
||||||
|
@ -577,7 +599,7 @@ public class JDTJava2CAstTranslator {
|
||||||
|
|
||||||
// finally, make the procedure entity
|
// finally, make the procedure entity
|
||||||
CAstNode ast = makeNode(context, fFactory, n, CAstNode.BLOCK_STMT, bodyNodes);
|
CAstNode ast = makeNode(context, fFactory, n, CAstNode.BLOCK_STMT, bodyNodes);
|
||||||
return new ProcedureEntity(ast, fakeCtor, newType, memberEntities, context, paramTypes, null);
|
return new ProcedureEntity(ast, fakeCtor, newType, memberEntities, context, paramTypes, null, null);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -726,7 +748,7 @@ public class JDTJava2CAstTranslator {
|
||||||
for (ITypeBinding paramType : overridden.getParameterTypes())
|
for (ITypeBinding paramType : overridden.getParameterTypes())
|
||||||
paramCAstTypes.add(fTypeDict.getCAstTypeFor(paramType));
|
paramCAstTypes.add(fTypeDict.getCAstTypeFor(paramType));
|
||||||
return new ProcedureEntity(mdast, overriding, overridingBinding.getDeclaringClass(), memberEntities, context, paramCAstTypes,
|
return new ProcedureEntity(mdast, overriding, overridingBinding.getDeclaringClass(), memberEntities, context, paramCAstTypes,
|
||||||
overridden.getReturnType());
|
overridden.getReturnType(), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -754,10 +776,51 @@ public class JDTJava2CAstTranslator {
|
||||||
// Polyglot comment: Presumably the MethodContext's parent is a ClassContext,
|
// Polyglot comment: Presumably the MethodContext's parent is a ClassContext,
|
||||||
// and he has the list of initializers. Hopefully the following
|
// and he has the list of initializers. Hopefully the following
|
||||||
// will glue that stuff in the right place in any constructor body.
|
// will glue that stuff in the right place in any constructor body.
|
||||||
|
|
||||||
return new ProcedureEntity(mdast, n, classBinding, memberEntities, context);
|
Set<CAstAnnotation> annotations = null;
|
||||||
|
if (n.resolveBinding() != null) {
|
||||||
|
annotations = handleAnnotations(n.resolveBinding());
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ProcedureEntity(mdast, n, classBinding, memberEntities, context, annotations);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Set<CAstAnnotation> handleAnnotations(IBinding binding) {
|
||||||
|
IAnnotationBinding[] annotations = binding.getAnnotations();
|
||||||
|
|
||||||
|
if(annotations == null || annotations.length == 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<CAstAnnotation> castAnnotations = HashSetFactory.make();
|
||||||
|
for(IAnnotationBinding annotation : annotations) {
|
||||||
|
ITypeBinding annotationTypeBinding = annotation.getAnnotationType();
|
||||||
|
final CAstType annotationType = fTypeDict.getCAstTypeFor(annotationTypeBinding);
|
||||||
|
final Map<String,Object> args = HashMapFactory.make();
|
||||||
|
for(IMemberValuePairBinding mvpb : annotation.getAllMemberValuePairs()) {
|
||||||
|
String name = mvpb.getName();
|
||||||
|
Object value = mvpb.getValue();
|
||||||
|
args.put(name, value);
|
||||||
|
}
|
||||||
|
castAnnotations.add(new CAstAnnotation() {
|
||||||
|
@Override
|
||||||
|
public CAstType getType() {
|
||||||
|
return annotationType;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public Map<String, Object> getArguments() {
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return annotationType.getName() + args;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return castAnnotations;
|
||||||
|
}
|
||||||
|
|
||||||
protected final class ProcedureEntity implements JavaProcedureEntity { // TAGALONG (make static, access ast)
|
protected final class ProcedureEntity implements JavaProcedureEntity { // TAGALONG (make static, access ast)
|
||||||
|
|
||||||
// From Code Body Entity
|
// From Code Body Entity
|
||||||
|
@ -795,6 +858,8 @@ public class JDTJava2CAstTranslator {
|
||||||
|
|
||||||
private int fModifiers;
|
private int fModifiers;
|
||||||
|
|
||||||
|
private final Set<CAstAnnotation> annotations;
|
||||||
|
|
||||||
// can be method, constructor, "fake" default constructor, or null decl = static initializer
|
// can be method, constructor, "fake" default constructor, or null decl = static initializer
|
||||||
/**
|
/**
|
||||||
* For a static initializer, pass a null decl.
|
* For a static initializer, pass a null decl.
|
||||||
|
@ -802,22 +867,22 @@ public class JDTJava2CAstTranslator {
|
||||||
// FIXME: get rid of decl and pass in everything instead of having to do two different things with parameters
|
// FIXME: get rid of decl and pass in everything instead of having to do two different things with parameters
|
||||||
// regular case
|
// regular case
|
||||||
private ProcedureEntity(CAstNode mdast, MethodDeclaration decl, ITypeBinding type, Map<CAstNode, CAstEntity> entities,
|
private ProcedureEntity(CAstNode mdast, MethodDeclaration decl, ITypeBinding type, Map<CAstNode, CAstEntity> entities,
|
||||||
MethodContext context) {
|
MethodContext context, Set<CAstAnnotation> annotations) {
|
||||||
this(mdast, decl, type, entities, context, null, null, decl.getModifiers());
|
this(mdast, decl, type, entities, context, null, null, decl.getModifiers(), annotations);
|
||||||
}
|
}
|
||||||
|
|
||||||
// static init
|
// static init
|
||||||
private ProcedureEntity(CAstNode mdast, ITypeBinding type, Map<CAstNode, CAstEntity> entities, MethodContext context) {
|
private ProcedureEntity(CAstNode mdast, ITypeBinding type, Map<CAstNode, CAstEntity> entities, MethodContext context, Set<CAstAnnotation> annotations) {
|
||||||
this(mdast, null, type, entities, context, null, null, 0);
|
this(mdast, null, type, entities, context, null, null, 0, annotations);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ProcedureEntity(CAstNode mdast, MethodDeclaration decl, ITypeBinding type, Map<CAstNode, CAstEntity> entities,
|
private ProcedureEntity(CAstNode mdast, MethodDeclaration decl, ITypeBinding type, Map<CAstNode, CAstEntity> entities,
|
||||||
MethodContext context, ArrayList<CAstType> parameterTypes, ITypeBinding returnType) {
|
MethodContext context, ArrayList<CAstType> parameterTypes, ITypeBinding returnType, Set<CAstAnnotation> annotations) {
|
||||||
this(mdast, decl, type, entities, context, parameterTypes, returnType, decl.getModifiers());
|
this(mdast, decl, type, entities, context, parameterTypes, returnType, decl.getModifiers(), annotations);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ProcedureEntity(CAstNode mdast, MethodDeclaration decl, ITypeBinding type, Map<CAstNode, CAstEntity> entities,
|
private ProcedureEntity(CAstNode mdast, MethodDeclaration decl, ITypeBinding type, Map<CAstNode, CAstEntity> entities,
|
||||||
MethodContext context, ArrayList<CAstType> parameterTypes, ITypeBinding returnType, int modifiers) {
|
MethodContext context, ArrayList<CAstType> parameterTypes, ITypeBinding returnType, int modifiers, Set<CAstAnnotation> annotations) {
|
||||||
// TypeSystem system, CodeInstance pd, String[] argumentNames,
|
// TypeSystem system, CodeInstance pd, String[] argumentNames,
|
||||||
// }
|
// }
|
||||||
// Map<CAstNode, CAstEntity> entities, MethodContext mc) {
|
// Map<CAstNode, CAstEntity> entities, MethodContext mc) {
|
||||||
|
@ -827,6 +892,7 @@ public class JDTJava2CAstTranslator {
|
||||||
fType = type;
|
fType = type;
|
||||||
fReturnType = returnType;
|
fReturnType = returnType;
|
||||||
fModifiers = modifiers;
|
fModifiers = modifiers;
|
||||||
|
this.annotations = annotations;
|
||||||
|
|
||||||
// from CodeBodyEntity
|
// from CodeBodyEntity
|
||||||
fEntities = new LinkedHashMap<CAstNode, Collection<CAstEntity>>();
|
fEntities = new LinkedHashMap<CAstNode, Collection<CAstEntity>>();
|
||||||
|
@ -866,7 +932,12 @@ public class JDTJava2CAstTranslator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString() {
|
@Override
|
||||||
|
public Collection<CAstAnnotation> getAnnotations() {
|
||||||
|
return annotations;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
return fDecl == null ? "<clinit>" : fDecl.toString();
|
return fDecl == null ? "<clinit>" : fDecl.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1034,15 +1105,24 @@ public class JDTJava2CAstTranslator {
|
||||||
|
|
||||||
private final JdtPosition position;
|
private final JdtPosition position;
|
||||||
|
|
||||||
private FieldEntity(String name, ITypeBinding type, Collection<CAstQualifier> quals, JdtPosition position) {
|
private final Set<CAstAnnotation> annotations;
|
||||||
|
|
||||||
|
private FieldEntity(String name, ITypeBinding type, Collection<CAstQualifier> quals, JdtPosition position, Set<CAstAnnotation> annotations) {
|
||||||
super();
|
super();
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.quals = quals;
|
this.quals = quals;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.position = position;
|
this.position = position;
|
||||||
|
this.annotations = annotations;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getKind() {
|
|
||||||
|
@Override
|
||||||
|
public Collection<CAstAnnotation> getAnnotations() {
|
||||||
|
return annotations;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getKind() {
|
||||||
return CAstEntity.FIELD_ENTITY;
|
return CAstEntity.FIELD_ENTITY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2821,7 +2901,12 @@ public class JDTJava2CAstTranslator {
|
||||||
fTopLevelDecls = topLevelDecls;
|
fTopLevelDecls = topLevelDecls;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getKind() {
|
@Override
|
||||||
|
public Collection<CAstAnnotation> getAnnotations() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getKind() {
|
||||||
return FILE_ENTITY;
|
return FILE_ENTITY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3171,7 +3256,7 @@ public class JDTJava2CAstTranslator {
|
||||||
*/
|
*/
|
||||||
private CAstEntity visit(EnumConstantDeclaration decl, WalkContext context) {
|
private CAstEntity visit(EnumConstantDeclaration decl, WalkContext context) {
|
||||||
return new FieldEntity(decl.getName().getIdentifier(), decl.resolveVariable().getType(), enumQuals, makePosition(decl
|
return new FieldEntity(decl.getName().getIdentifier(), decl.resolveVariable().getType(), enumQuals, makePosition(decl
|
||||||
.getStartPosition(), decl.getStartPosition() + decl.getLength()));
|
.getStartPosition(), decl.getStartPosition() + decl.getLength()), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -3248,7 +3333,7 @@ public class JDTJava2CAstTranslator {
|
||||||
ArrayList<CAstType> paramTypes = new ArrayList<CAstType>(1);
|
ArrayList<CAstType> paramTypes = new ArrayList<CAstType>(1);
|
||||||
paramTypes.add(fTypeDict.getCAstTypeFor(ast.resolveWellKnownType("java.lang.String")));
|
paramTypes.add(fTypeDict.getCAstTypeFor(ast.resolveWellKnownType("java.lang.String")));
|
||||||
|
|
||||||
return new ProcedureEntity(bodyNode, fakeMet, enumType, memberEntities, context, paramTypes, enumType, met.getModifiers());
|
return new ProcedureEntity(bodyNode, fakeMet, enumType, memberEntities, context, paramTypes, enumType, met.getModifiers(), handleAnnotations(met));
|
||||||
}
|
}
|
||||||
|
|
||||||
private CAstEntity createEnumValuesMethod(ITypeBinding enumType, ArrayList<IVariableBinding> constants, WalkContext oldContext) {
|
private CAstEntity createEnumValuesMethod(ITypeBinding enumType, ArrayList<IVariableBinding> constants, WalkContext oldContext) {
|
||||||
|
@ -3281,7 +3366,7 @@ public class JDTJava2CAstTranslator {
|
||||||
|
|
||||||
ArrayList<CAstType> paramTypes = new ArrayList<CAstType>(0);
|
ArrayList<CAstType> paramTypes = new ArrayList<CAstType>(0);
|
||||||
return new ProcedureEntity(bodyNode, fakeMet, enumType, memberEntities, context, paramTypes, enumType.createArrayType(1), met
|
return new ProcedureEntity(bodyNode, fakeMet, enumType, memberEntities, context, paramTypes, enumType.createArrayType(1), met
|
||||||
.getModifiers());
|
.getModifiers(), handleAnnotations(enumType));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void doEnumHiddenEntities(ITypeBinding typeBinding, ArrayList<ASTNode> staticInits, List<CAstEntity> memberEntities,
|
private void doEnumHiddenEntities(ITypeBinding typeBinding, ArrayList<ASTNode> staticInits, List<CAstEntity> memberEntities,
|
||||||
|
@ -3431,7 +3516,7 @@ public class JDTJava2CAstTranslator {
|
||||||
|
|
||||||
// finally, make the procedure entity
|
// finally, make the procedure entity
|
||||||
CAstNode ast = makeNode(context, fFactory, n, CAstNode.BLOCK_STMT, bodyNodes);
|
CAstNode ast = makeNode(context, fFactory, n, CAstNode.BLOCK_STMT, bodyNodes);
|
||||||
return new ProcedureEntity(ast, fakeCtor, newType, memberEntities, context, paramTypes, null);
|
return new ProcedureEntity(ast, fakeCtor, newType, memberEntities, context, paramTypes, null, handleAnnotations(ctor));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -117,8 +117,6 @@ public class JDTSourceModuleTranslator implements SourceModuleTranslator {
|
||||||
// TODO: we might need one AST (-> "Object" class) for all files.
|
// TODO: we might need one AST (-> "Object" class) for all files.
|
||||||
// TODO: group by project and send 'em in
|
// TODO: group by project and send 'em in
|
||||||
|
|
||||||
System.out.println(modules);
|
|
||||||
|
|
||||||
// sort files into projects
|
// sort files into projects
|
||||||
Map<IProject, Map<ICompilationUnit,EclipseSourceFileModule>> projectsFiles = new HashMap<IProject, Map<ICompilationUnit,EclipseSourceFileModule>>();
|
Map<IProject, Map<ICompilationUnit,EclipseSourceFileModule>> projectsFiles = new HashMap<IProject, Map<ICompilationUnit,EclipseSourceFileModule>>();
|
||||||
for (ModuleEntry m : modules) {
|
for (ModuleEntry m : modules) {
|
||||||
|
@ -131,12 +129,12 @@ public class JDTSourceModuleTranslator implements SourceModuleTranslator {
|
||||||
projectsFiles.get(proj).put(JavaCore.createCompilationUnitFrom(entry.getIFile()), entry);
|
projectsFiles.get(proj).put(JavaCore.createCompilationUnitFrom(entry.getIFile()), entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
final ASTParser parser = ASTParser.newParser(AST.JLS3);
|
final ASTParser parser = ASTParser.newParser(AST.JLS4);
|
||||||
|
|
||||||
for (final Map.Entry<IProject,Map<ICompilationUnit,EclipseSourceFileModule>> proj : projectsFiles.entrySet()) {
|
for (final Map.Entry<IProject,Map<ICompilationUnit,EclipseSourceFileModule>> proj : projectsFiles.entrySet()) {
|
||||||
parser.setProject(JavaCore.create(proj.getKey()));
|
parser.setProject(JavaCore.create(proj.getKey()));
|
||||||
parser.setResolveBindings(true);
|
parser.setResolveBindings(true);
|
||||||
|
|
||||||
Set<ICompilationUnit> units = proj.getValue().keySet();
|
Set<ICompilationUnit> units = proj.getValue().keySet();
|
||||||
parser.createASTs(units.toArray(new ICompilationUnit[units.size()]), new String[0], new ASTRequestor() {
|
parser.createASTs(units.toArray(new ICompilationUnit[units.size()]), new String[0], new ASTRequestor() {
|
||||||
public void acceptAST(ICompilationUnit source, CompilationUnit ast) {
|
public void acceptAST(ICompilationUnit source, CompilationUnit ast) {
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2008 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.util;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runtime exception for some WALA failure.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class WalaRuntimeException extends RuntimeException {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param s a message describing the failure
|
||||||
|
*/
|
||||||
|
public WalaRuntimeException(String s, Throwable cause) {
|
||||||
|
super(s, cause);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @param string a message describing the failure
|
||||||
|
*/
|
||||||
|
public WalaRuntimeException(String string) {
|
||||||
|
super(string);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -77,6 +77,9 @@ public class Util {
|
||||||
return traceDump.toString();
|
return traceDump.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return those elements of <code>c</code> that are assignable to <code>klass</code>.
|
||||||
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public static <S, T> Set<T> filterByType(Iterable<S> c, Class<T> klass) {
|
public static <S, T> Set<T> filterByType(Iterable<S> c, Class<T> klass) {
|
||||||
Set<T> result = HashSetFactory.make();
|
Set<T> result = HashSetFactory.make();
|
||||||
|
|
|
@ -230,7 +230,7 @@ public class JavaLauncher extends Launcher {
|
||||||
if (libPath == null) {
|
if (libPath == null) {
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
return "-Djava.library.path=" + quoteStringIfNeeded(libPath);
|
return "-Djava.library.path=" + libPath.trim();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -264,16 +264,16 @@ public class JavaLauncher extends Launcher {
|
||||||
/**
|
/**
|
||||||
* Compute the classpath for the spawned process
|
* Compute the classpath for the spawned process
|
||||||
*/
|
*/
|
||||||
private String makeClasspath() {
|
public String makeClasspath() {
|
||||||
String cp = inheritClasspath ? System.getProperty("java.class.path") : "";
|
String cp = inheritClasspath ? System.getProperty("java.class.path") : "";
|
||||||
if (getXtraClassPath() == null || getXtraClassPath().isEmpty()) {
|
if (getXtraClassPath() == null || getXtraClassPath().isEmpty()) {
|
||||||
return quoteStringIfNeeded(cp);
|
return cp.trim();
|
||||||
} else {
|
} else {
|
||||||
for (Iterator<String> it = getXtraClassPath().iterator(); it.hasNext();) {
|
for (Iterator<String> it = getXtraClassPath().iterator(); it.hasNext();) {
|
||||||
cp += File.pathSeparatorChar;
|
cp += File.pathSeparatorChar;
|
||||||
cp += (String) it.next();
|
cp += (String) it.next();
|
||||||
}
|
}
|
||||||
return quoteStringIfNeeded(cp);
|
return cp.trim();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -283,6 +283,7 @@ public class JavaLauncher extends Launcher {
|
||||||
* are unsafe, so we have to escape the last backslash (if present and
|
* are unsafe, so we have to escape the last backslash (if present and
|
||||||
* unescaped), so it doesn't escape the closing quote.
|
* unescaped), so it doesn't escape the closing quote.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public static String quoteStringIfNeeded(String s) {
|
public static String quoteStringIfNeeded(String s) {
|
||||||
s = s.trim();
|
s = s.trim();
|
||||||
// s = s.replaceAll(" ", "\\\\ ");
|
// s = s.replaceAll(" ", "\\\\ ");
|
||||||
|
|
Loading…
Reference in New Issue