public static TypeReference getCapsuleMockupClassReference(TypeReference capsuleInterface) { ClassLoaderReference loader = capsuleInterface.getClassLoader(); TypeName interfaceName = capsuleInterface.getName(); String pkg = interfaceName.getPackage().toString(); String name = interfaceName.getClassName().toString() + CAPSULE_MOCKUP_SUFFIX; return TypeReference.findOrCreateClass(loader, pkg, name); }
protected void addFieldToList( List<FieldImpl> L, Atom name, ImmutableByteArray fieldType, int accessFlags, Collection<Annotation> annotations) { TypeName T = null; if (fieldType.get(fieldType.length() - 1) == ';') { T = TypeName.findOrCreate(fieldType, 0, fieldType.length() - 1); } else { T = TypeName.findOrCreate(fieldType); } TypeReference type = TypeReference.findOrCreate(getClassLoader().getReference(), T); FieldReference fr = FieldReference.findOrCreate(getReference(), name, type); FieldImpl f = new FieldImpl(this, fr, accessFlags, annotations); L.add(f); }
private void computeSuperclass() { superclassComputed = true; if (superName == null) { if (!getReference().equals(loader.getLanguage().getRootType())) { superClass = loader.lookupClass(loader.getLanguage().getRootType().getName()); } return; } superClass = loader.lookupClass(TypeName.findOrCreate(superName)); }
protected void doNewObject( WalkContext context, CAstNode newNode, int result, Object type, int[] arguments) { assert arguments == null; TypeReference typeRef = TypeReference.findOrCreate(JavaScriptTypes.jsLoader, TypeName.string2TypeName("L" + type)); context .cfg() .addInstruction( insts.NewInstruction( result, NewSiteReference.make(context.cfg().getCurrentInstruction(), typeRef))); }
/** * @param interfaces a set of class names * @return Set of all IClasses that can be loaded corresponding to the class names in the * interfaces array; raise warnings if classes can not be loaded */ private Collection<IClass> array2IClassSet(ImmutableByteArray[] interfaces) { ArrayList<IClass> result = new ArrayList<IClass>(interfaces.length); for (int i = 0; i < interfaces.length; i++) { ImmutableByteArray name = interfaces[i]; IClass klass = null; klass = loader.lookupClass(TypeName.findOrCreate(name)); if (klass == null) { Warnings.add(ClassNotFoundWarning.create(name)); } else { result.add(klass); } } return result; }
/** * @param m * @return true iff we can treat m as a no-op method */ protected boolean canIgnore(MemberReference m) { TypeReference T = m.getDeclaringClass(); TypeName n = T.getName(); Atom p = n.getPackage(); return (ignoredPackages.contains(p)); }
private IMethod makeFunctionConstructor( IR callerIR, SSAAbstractInvokeInstruction callStmt, IClass cls, int nargs) { SymbolTable ST = callerIR.getSymbolTable(); if (nargs == 0) { return makeFunctionConstructor(cls, cls); } else if (nargs == 1) { if (ST.isStringConstant(callStmt.getUse(1))) { TypeReference ref = TypeReference.findOrCreate( JavaScriptTypes.jsLoader, TypeName.string2TypeName((String) ST.getStringValue(callStmt.getUse(1)))); if (DEBUG) { System.err.println( ("ctor type name is " + (String) ST.getStringValue(callStmt.getUse(1)))); } IClass cls2 = cha.lookupClass(ref); if (cls2 != null) { return makeFunctionConstructor(cls, cls2); } } return makeFunctionConstructor(cls, cls); } else { assert nargs > 1; JavaScriptLoader cl = (JavaScriptLoader) cha.getLoader(JavaScriptTypes.jsLoader); for (int i = 1; i < callStmt.getNumberOfUses(); i++) if (!ST.isStringConstant(callStmt.getUse(i))) return makeFunctionConstructor(cls, cls); StringBuffer fun = new StringBuffer("function _fromctor ("); for (int j = 1; j < callStmt.getNumberOfUses() - 1; j++) { if (j != 1) fun.append(","); fun.append(ST.getStringValue(callStmt.getUse(j))); } fun.append(") {"); fun.append(ST.getStringValue(callStmt.getUse(callStmt.getNumberOfUses() - 1))); fun.append("}"); try { String fileName = "ctor$" + ++ctorCount; File f = new File(System.getProperty("java.io.tmpdir") + File.separator + fileName); FileWriter FO = new FileWriter(f); FO.write(fun.toString()); FO.close(); Set<String> fnNames = JSCallGraphUtil.loadAdditionalFile(cha, cl, fileName, f.toURI().toURL()); IClass fcls = null; for (String nm : fnNames) { if (nm.endsWith("_fromctor")) { fcls = cl.lookupClass(nm, cha); } } assert fcls != null : "cannot find class for " + fileName + " in " + f; f.delete(); if (DEBUG) System.err.println(("looking for ctor " + ctorCount + " and got " + fcls)); if (fcls != null) return makeFunctionConstructor(cls, fcls); } catch (IOException e) { } return makeFunctionConstructor(cls, cls); } }
public class LoadFileTargetSelector implements MethodTargetSelector { private final MethodTargetSelector base; private final JSSSAPropagationCallGraphBuilder builder; private final TypeReference loadFileRef = TypeReference.findOrCreate( JavaScriptTypes.jsLoader, TypeName.string2TypeName("Lprologue.js/loadFile")); private final MethodReference loadFileFunRef = AstMethodReference.fnReference(loadFileRef); private final HashSet<URL> loadedFiles = HashSetFactory.make(); @Override public IMethod getCalleeTarget(CGNode caller, CallSiteReference site, IClass receiver) { IMethod target = base.getCalleeTarget(caller, site, receiver); if (target != null && target.getReference().equals(loadFileFunRef)) { Set<String> names = new HashSet<String>(); SSAInstruction call = caller.getIR() .getInstructions()[ caller.getIR().getCallInstructionIndices(site).intIterator().next()]; if (call.getNumberOfUses() > 1) { LocalPointerKey fileNameV = new LocalPointerKey(caller, call.getUse(1)); OrdinalSet<InstanceKey> ptrs = builder.getPointerAnalysis().getPointsToSet(fileNameV); for (InstanceKey k : ptrs) { if (k instanceof ConstantKey) { Object v = ((ConstantKey) k).getValue(); if (v instanceof String) { names.add((String) v); } } } if (names.size() == 1) { String str = names.iterator().next(); try { JavaScriptLoader cl = (JavaScriptLoader) builder.getClassHierarchy().getLoader(JavaScriptTypes.jsLoader); URL url = new URL(builder.getBaseURL(), str); if (!loadedFiles.contains(url)) { // try to open the input stream for the URL. if it fails, we'll get an IOException // and fall through to default case InputStream inputStream = url.openConnection().getInputStream(); inputStream.close(); JSCallGraphUtil.loadAdditionalFile(builder.getClassHierarchy(), cl, url); loadedFiles.add(url); IClass script = builder .getClassHierarchy() .lookupClass( TypeReference.findOrCreate(cl.getReference(), "L" + url.getFile())); return script.getMethod(JavaScriptMethods.fnSelector); } } catch (MalformedURLException e1) { // do nothing, fall through and return 'target' } catch (IOException e) { // do nothing, fall through and return 'target' } catch (RuntimeException e) { // do nothing, fall through and return 'target' } } } } return target; } public LoadFileTargetSelector( MethodTargetSelector base, JSSSAPropagationCallGraphBuilder builder) { super(); this.base = base; this.builder = builder; } }
private String getClassName(IClass clazz) { TypeName typeName = clazz.getName(); return typeName.getPackage().toString().replaceAll("/", ".") + "." + typeName.getClassName(); }
/** * Flexible class to create {@link InstanceKey}s depending on various policies ranging from * class-based (i.e. 0-CFA) to allocation-site-based (0-1-CFA variants). */ public class ZeroXInstanceKeys implements InstanceKeyFactory { private static final TypeName JavaLangStringBufferName = TypeName.string2TypeName("Ljava/lang/StringBuffer"); public static final TypeReference JavaLangStringBuffer = TypeReference.findOrCreate(ClassLoaderReference.Primordial, JavaLangStringBufferName); private static final TypeName JavaLangStringBuilderName = TypeName.string2TypeName("Ljava/lang/StringBuilder"); public static final TypeReference JavaLangStringBuilder = TypeReference.findOrCreate(ClassLoaderReference.Primordial, JavaLangStringBuilderName); private static final TypeName JavaLangAbstractStringBuilderName = TypeName.string2TypeName("Ljava/lang/AbstractStringBuilder"); public static final TypeReference JavaLangAbstractStringBuilder = TypeReference.findOrCreate( ClassLoaderReference.Primordial, JavaLangAbstractStringBuilderName); /** The NONE policy is not allocation-site based */ public static final int NONE = 0; /** * An ALLOCATIONS - based policy distinguishes instances by allocation site. Otherwise, the policy * distinguishes instances by type. */ public static final int ALLOCATIONS = 1; /** * A policy variant where String and StringBuffers are NOT disambiguated according to allocation * site. */ public static final int SMUSH_STRINGS = 2; /** * A policy variant where {@link Throwable} instances are NOT disambiguated according to * allocation site. */ public static final int SMUSH_THROWABLES = 4; /** * A policy variant where if a type T has only primitive instance fields, then instances of type T * are NOT disambiguated by allocation site. */ public static final int SMUSH_PRIMITIVE_HOLDERS = 8; /** * This variant counts the N, number of allocation sites of a particular type T in each method. If * N > SMUSH_LIMIT, then these N allocation sites are NOT distinguished ... instead there is a * single abstract allocation site for <N,T> * * <p>Probably the best choice in many cases. */ public static final int SMUSH_MANY = 16; /** Should we use constant-specific keys? */ public static final int CONSTANT_SPECIFIC = 32; /** When using smushing, how many sites in a node will be kept distinct before smushing? */ private final int SMUSH_LIMIT = 25; /** The policy choice for instance disambiguation */ private final int policy; /** A delegate object to create class-based abstract instances */ private final ClassBasedInstanceKeys classBased; /** A delegate object to create allocation site-based abstract instances */ private final AllocationSiteInNodeFactory siteBased; /** A delegate object to create "abstract allocation site" - based abstract instances */ private final SmushedAllocationSiteInstanceKeys smushed; /** The governing class hierarchy */ private final IClassHierarchy cha; /** An object which interprets nodes in context. */ private final RTAContextInterpreter contextInterpreter; /** a Map from CGNode->Set<IClass> that should be smushed. */ protected final Map<CGNode, Set<IClass>> smushMap = HashMapFactory.make(); public ZeroXInstanceKeys( AnalysisOptions options, IClassHierarchy cha, RTAContextInterpreter contextInterpreter, int policy) { if (options == null) { throw new IllegalArgumentException("null options"); } this.policy = policy; if (disambiguateConstants()) { // this is an ugly hack. TODO: clean it all up. options.setUseConstantSpecificKeys(true); } classBased = new ClassBasedInstanceKeys(options, cha); siteBased = new AllocationSiteInNodeFactory(options, cha); smushed = new SmushedAllocationSiteInstanceKeys(options, cha); this.cha = cha; this.contextInterpreter = contextInterpreter; } /** @return true iff the policy smushes some allocation sites */ private boolean smushMany() { return (policy & SMUSH_MANY) > 0; } private boolean allocationPolicy() { return (policy & ALLOCATIONS) > 0; } private boolean smushStrings() { return (policy & SMUSH_STRINGS) > 0; } public boolean smushThrowables() { return (policy & SMUSH_THROWABLES) > 0; } private boolean smushPrimHolders() { return (policy & SMUSH_PRIMITIVE_HOLDERS) > 0; } public boolean disambiguateConstants() { return (policy & CONSTANT_SPECIFIC) > 0; } public InstanceKey getInstanceKeyForAllocation(CGNode node, NewSiteReference allocation) { if (allocation == null) { throw new IllegalArgumentException("allocation is null"); } TypeReference t = allocation.getDeclaredType(); IClass C = cha.lookupClass(t); if (C != null && isInteresting(C)) { if (smushMany()) { if (exceedsSmushLimit(C, node)) { return smushed.getInstanceKeyForAllocation(node, allocation); } else { return siteBased.getInstanceKeyForAllocation(node, allocation); } } else { return siteBased.getInstanceKeyForAllocation(node, allocation); } } else { return classBased.getInstanceKeyForAllocation(node, allocation); } } /** * side effect: populates the smush map. * * @return true iff the node contains too many allocation sites of type c */ private boolean exceedsSmushLimit(IClass c, CGNode node) { Set<IClass> s = smushMap.get(node); if (s == null) { Map<IClass, Integer> count = countAllocsByType(node); HashSet<IClass> smushees = HashSetFactory.make(5); for (Iterator<Map.Entry<IClass, Integer>> it = count.entrySet().iterator(); it.hasNext(); ) { Map.Entry<IClass, Integer> e = it.next(); Integer i = e.getValue(); if (i.intValue() > SMUSH_LIMIT) { smushees.add(e.getKey()); } } s = smushees.isEmpty() ? Collections.<IClass>emptySet() : smushees; smushMap.put(node, s); } return s.contains(c); } /** @return Map: IClass -> Integer, the number of allocation sites for each type. */ private Map<IClass, Integer> countAllocsByType(CGNode node) { Map<IClass, Integer> count = HashMapFactory.make(); for (Iterator it = contextInterpreter.iterateNewSites(node); it.hasNext(); ) { NewSiteReference n = (NewSiteReference) it.next(); IClass alloc = cha.lookupClass(n.getDeclaredType()); if (alloc != null) { Integer old = count.get(alloc); if (old == null) { count.put(alloc, new Integer(1)); } else { count.put(alloc, new Integer(old.intValue() + 1)); } } } return count; } public InstanceKey getInstanceKeyForMultiNewArray( CGNode node, NewSiteReference allocation, int dim) { if (allocationPolicy()) { return siteBased.getInstanceKeyForMultiNewArray(node, allocation, dim); } else { return classBased.getInstanceKeyForMultiNewArray(node, allocation, dim); } } public <T> InstanceKey getInstanceKeyForConstant(TypeReference type, T S) { if (type == null) { throw new IllegalArgumentException("null type"); } if (disambiguateConstants() || isReflectiveType(type)) { return new ConstantKey<T>(S, getClassHierarchy().lookupClass(type)); } else { return classBased.getInstanceKeyForConstant(type, S); } } private boolean isReflectiveType(TypeReference type) { return type.equals(TypeReference.JavaLangReflectConstructor) || type.equals(TypeReference.JavaLangReflectMethod); } /* * @see com.ibm.wala.ipa.callgraph.propagation.InstanceKeyFactory#getInstanceKeyForPEI(com.ibm.wala.ipa.callgraph.CGNode, * com.ibm.wala.classLoader.ProgramCounter, com.ibm.wala.types.TypeReference) */ public InstanceKey getInstanceKeyForPEI(CGNode node, ProgramCounter pei, TypeReference type) { return classBased.getInstanceKeyForPEI(node, pei, type); } public InstanceKey getInstanceKeyForClassObject(TypeReference type) { return classBased.getInstanceKeyForClassObject(type); } /** A class is "interesting" iff we distinguish instances of the class */ public boolean isInteresting(IClass C) { if (!allocationPolicy()) { return false; } else { if (smushStrings() && isStringish(C)) { return false; } else if (smushThrowables() && (isThrowable(C) || isStackTraceElement(C))) { return false; } else if (smushPrimHolders() && allFieldsArePrimitive(C)) { return false; } return true; } } public static boolean isStringish(IClass C) { if (C == null) { throw new IllegalArgumentException("C is null"); } return C.getReference().equals(TypeReference.JavaLangString) || C.getReference().equals(JavaLangStringBuffer) || C.getReference().equals(JavaLangStringBuilder) || C.getReference().equals(JavaLangAbstractStringBuilder); } public static boolean isThrowable(IClass c) { if (c == null) { throw new IllegalArgumentException("null c"); } return c.getClassHierarchy() .isSubclassOf(c, c.getClassHierarchy().lookupClass(TypeReference.JavaLangThrowable)); } public boolean isStackTraceElement(IClass c) { if (c == null) { throw new IllegalArgumentException("C is null"); } return c.getReference().equals(TypeReference.JavaLangStackTraceElement); } private boolean allFieldsArePrimitive(IClass c) { if (c.isArrayClass()) { TypeReference t = c.getReference().getArrayElementType(); return t.isPrimitiveType(); } else { if (c.getReference().equals(TypeReference.JavaLangObject)) { return true; } else { for (Iterator<IField> it = c.getDeclaredInstanceFields().iterator(); it.hasNext(); ) { IField f = it.next(); if (f.getReference().getFieldType().isReferenceType()) { return false; } } return allFieldsArePrimitive(c.getSuperclass()); } } } protected IClassHierarchy getClassHierarchy() { return cha; } public ClassBasedInstanceKeys getClassBasedInstanceKeys() { return classBased; } }