public ITable get(SootClass clazz) { if (!clazz.isInterface()) { throw new IllegalArgumentException("Not an interface: " + clazz.getName()); } ITable itable = cache.get(clazz.getName()); if (itable != null) { return itable; } itable = new ITable(clazz); cache.put(clazz.getName(), itable); return itable; }
public static HashSet<SootMethod> getAllImplementations(SootMethod method) { Chain appClasses = Scene.v().getApplicationClasses(); HashSet<SootClass> implementingClasses = new HashSet<SootClass>(1); HashSet<SootMethod> overridingMethods = new HashSet<SootMethod>(1); SootClass t = method.getDeclaringClass(); if ( /*t.isAbstract() || */ t.isPhantom() || t.isPhantomClass()) { boolean b1 = t.isAbstract(); boolean be = t.isPhantom(); boolean b3 = t.isPhantomClass(); try { throw new Exception("Need to implement for Plantom Classes"); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } if (t.isAbstract()) { for (Object object : appClasses) { SootClass clazz = (SootClass) object; SootClass superClass = clazz.getSuperclass(); { if (superClass.getName().equals(t.toString())) { implementingClasses.add(clazz); SootMethod m2 = clazz.getMethod( method.getName(), method.getParameterTypes(), method.getReturnType()); overridingMethods.add(m2); } } } } if (t.isInterface()) { for (Object object : appClasses) { SootClass clazz = (SootClass) object; Chain<SootClass> interfaces = clazz.getInterfaces(); for (SootClass sootClass : interfaces) { if (sootClass.getName().equals(t.toString())) { implementingClasses.add(clazz); SootMethod m2 = clazz.getMethod( method.getName(), method.getParameterTypes(), method.getReturnType()); overridingMethods.add(m2); } } } } return overridingMethods; }
public static boolean isInstanceOfClass(SootClass sc, String className) { SootClass clazz = sc; if (className.equals(clazz.getName())) { return true; } return isSubclass(sc, className); }
public VTable get(SootClass clazz) { if (clazz.isInterface()) { throw new IllegalArgumentException("Expected a class got an interface: " + clazz.getName()); } VTable vtable = cache.get(clazz.getName()); if (vtable != null) { return vtable; } VTable parent = null; if (clazz.hasSuperclass()) { parent = get(clazz.getSuperclass()); } vtable = new VTable(clazz, parent); cache.put(clazz.getName(), vtable); return vtable; }
protected List<OpenCLField> getRefFields(SootClass soot_class) { OpenCLClass ocl_class = OpenCLScene.v().getOpenCLClass(soot_class); if (ocl_class == null) { System.out.println("ocl_class == null: " + soot_class.getName()); } return ocl_class.getInstanceRefFields(); }
public void caseStaticInvokeExpr(StaticInvokeExpr arg0) { SootMethod soot_method = arg0.getMethod(); SootClass soot_class = soot_method.getDeclaringClass(); if (soot_class.getName().equals("java.lang.Object")) return; OpenCLMethod ocl_method = new OpenCLMethod(soot_method, soot_class); m_output.append(ocl_method.getStaticInvokeString(arg0)); setCheckException(); }
public static boolean isAccessRestricted(SootClass sc) { for (String pkg : restrictedPackages) { String name = sc.getName(); if (name.startsWith(pkg)) { return true; } } return false; }
private boolean isImportantJavaAlloc(SootClass clz) { String packageName = clz.getName(); for (String packPrefix : IMPORTANT_ALLOCATORS_FROM_JAVA) { if (packageName.startsWith(packPrefix)) return true; } return false; }
private String buildImportantAllocs() { StringBuffer sb = new StringBuffer(); for (SootClass clz : Scene.v().getClasses()) { if (Project.v().isSrcClass(clz) || /*isImportantJavaAlloc(clz) ||*/ clz.getName().startsWith(Project.DS_GENERATED_CLASSES_PREFIX) || clz.getName().startsWith("droidsafe.runtime")) { logger.info("Adding class to important alloc list of spark: {}", clz); sb.append(clz + ","); } } String ret = sb.toString(); ret = ret.substring(0, ret.length() - 1); return ret; }
public static boolean isSubclass(SootClass sc, String className) { SootClass clazz = sc; while (clazz.hasSuperclass()) { clazz = clazz.getSuperclass(); if (className.equals(clazz.getName())) { return true; } } return false; }
private boolean shouldMap(SootClass soot_class) { if (m_classRemapping.containsKey(soot_class.getName())) { String curr_class = m_currMethod.getDeclaringClass().toString(); if (m_modified.contains(curr_class) == false) { m_modified.add(curr_class); } return true; } else { return false; } }
public void caseAFile(AFile node) { inAFile(node); { Object temp[] = node.getModifier().toArray(); for (int i = 0; i < temp.length; i++) { ((PModifier) temp[i]).apply(this); } } if (node.getFileType() != null) { node.getFileType().apply(this); } if (node.getClassName() != null) { node.getClassName().apply(this); } String className = (String) mProductions.removeLast(); if (mSootClass == null) { mSootClass = new SootClass(className); mSootClass.setResolvingLevel(SootClass.BODIES); } else { if (!mSootClass.getName().equals(className)) throw new RuntimeException( "Invalid SootClass for this JimpleAST. The SootClass provided is of type: >" + mSootClass.getName() + "< whereas this parse tree is for type: >" + className + "<"); } if (node.getExtendsClause() != null) { node.getExtendsClause().apply(this); } if (node.getImplementsClause() != null) { node.getImplementsClause().apply(this); } if (node.getFileBody() != null) { node.getFileBody().apply(this); } outAFile(node); }
protected void readNonRefField(OpenCLField field) { SootField soot_field = field.getSootField(); String function_name = "read" + getTypeString(soot_field); BytecodeLanguage bcl = m_bcl.top(); bcl.pushMethod(m_currMem.top(), function_name, soot_field.getType()); Local data = bcl.invokeMethodRet(m_currMem.top()); SootClass soot_class = Scene.v().getSootClass(soot_field.getDeclaringClass().getName()); if (soot_class.isApplicationClass()) { if (field.isInstance()) { bcl.setInstanceField(soot_field, m_objSerializing.top(), data); } else { bcl.setStaticField(soot_field, data); } } else { SootClass obj = Scene.v().getSootClass("java.lang.Object"); SootClass string = Scene.v().getSootClass("java.lang.String"); String static_str; SootClass first_param_type; Value first_param; if (field.isInstance()) { static_str = ""; first_param_type = obj; first_param = m_objSerializing.top(); } else { static_str = "Static"; first_param_type = Scene.v().getSootClass("java.lang.Class"); first_param = ClassConstant.v(soot_class.getName()); } String private_field_fun_name = "write" + static_str + getTypeString(soot_field); Local private_fields = bcl.newInstance("org.trifort.rootbeer.runtime.PrivateFields"); bcl.pushMethod( private_fields, private_field_fun_name, VoidType.v(), first_param_type.getType(), string.getType(), string.getType(), soot_field.getType()); bcl.invokeMethodNoRet( private_fields, first_param, StringConstant.v(soot_field.getName()), StringConstant.v(soot_field.getDeclaringClass().getName()), data); } }
public StructureConstant getStruct(SootClass clazz) { if (clazz.isInterface()) { throw new IllegalArgumentException("Expected a class got an interface: " + clazz.getName()); } ArrayConstantBuilder table = new ArrayConstantBuilder(I8_PTR); for (Entry entry : entries) { ResolvedEntry resolvedEntry = entry.resolve(clazz); if (resolvedEntry == null || Modifier.isAbstract(resolvedEntry.getModifiers())) { table.add(new ConstantBitcast(BC_ABSTRACT_METHOD_CALLED, I8_PTR)); } else if (!Modifier.isPublic(resolvedEntry.getModifiers())) { table.add(new ConstantBitcast(BC_NON_PUBLIC_METHOD_CALLED, I8_PTR)); } else { table.add(new ConstantBitcast(resolvedEntry.getFunctionRef(), I8_PTR)); } } return new StructureConstantBuilder() .add(new IntegerConstant((short) entries.length)) .add(table.build()) .build(); }
public ReverseClassHierarchy(Map<String, OpenCLClass> classes) { m_Hierarchy = new ArrayList<TreeNode>(); m_Classes = classes; addClass("java.lang.String"); Set<String> key_set = classes.keySet(); Set<String> visited = new HashSet<String>(); for (String key : key_set) { OpenCLClass ocl_class = classes.get(key); SootClass soot_class = Scene.v().getSootClass(ocl_class.getJavaName()); if (soot_class.hasSuperclass() == false) continue; SootClass parent = soot_class.getSuperclass(); if (parent.getName().equals("java.lang.Object")) { TreeNode tree = new TreeNode(soot_class, ocl_class); m_Hierarchy.add(tree); visited.add(key); } } boolean modified; do { modified = false; key_set = classes.keySet(); for (String key : key_set) { if (visited.contains(key)) continue; OpenCLClass ocl_class = classes.get(key); SootClass soot_class = Scene.v().getSootClass(ocl_class.getJavaName()); if (soot_class.hasSuperclass() == false) continue; SootClass parent = soot_class.getSuperclass(); TreeNode node = getNode(parent); if (node == null) continue; node.addChild(soot_class, ocl_class); modified = true; visited.add(key); } } while (modified); }
private void visit(SootMethod method) { SootClass soot_class = method.getDeclaringClass(); if (m_classRemapping.containsKey(soot_class.getName())) { return; } if (method.isConcrete() == false) { return; } Body body = method.retrieveActiveBody(); if (body == null) return; m_currMethod = method; fixArguments(method); Iterator<Unit> iter = body.getUnits().iterator(); while (iter.hasNext()) { Unit curr = iter.next(); List<ValueBox> boxes = curr.getUseAndDefBoxes(); for (ValueBox box : boxes) { Value value = box.getValue(); value = mutate(value); box.setValue(value); } } }
public static String getInternalName(SootClass sc) { return sc.getName().replace('.', '/'); }
private SootClass getMapping(SootClass soot_class) { String new_class = m_classRemapping.get(soot_class.getName()); return Scene.v().getSootClass(new_class); }
private StructureType getStructType(SootClass clazz, boolean checkEmpty) { int n = 0; for (SootMethod method : clazz.getMethods()) { n = Math.max(getStructMemberOffset(method) + 1, n); } Type[] result = new Type[n + 1]; StructureType superType = null; if (clazz.hasSuperclass()) { SootClass superclass = clazz.getSuperclass(); if (!superclass.getName().equals("org.robovm.rt.bro.Struct")) { superType = getStructType(superclass, false); } } result[0] = superType != null ? superType : new StructureType(); for (SootMethod method : clazz.getMethods()) { int offset = getStructMemberOffset(method); if (offset != -1) { if (!method.isNative() && !method.isStatic()) { throw new IllegalArgumentException( "@StructMember annotated method " + method + " must be native and not static"); } Type type = null; if (method.getParameterCount() == 0) { soot.Type sootType = method.getReturnType(); // Possibly a getter if (hasPointerAnnotation(method) && !sootType.equals(LongType.v())) { throw new IllegalArgumentException( "@StructMember(" + offset + ") annotated getter " + method + " must be of type long when annotated with @Pointer"); } if (hasMachineSizedFloatAnnotation(method) && !sootType.equals(DoubleType.v()) && !sootType.equals(FloatType.v())) { throw new IllegalArgumentException( "@StructMember(" + offset + ") annotated getter " + method + " must be of type float or double when annotated with @MachineSizedFloat"); } if ((hasMachineSizedSIntAnnotation(method) || hasMachineSizedUIntAnnotation(method)) && !sootType.equals(LongType.v())) { throw new IllegalArgumentException( "@StructMember(" + offset + ") annotated getter " + method + " must be of type long when annotated with @MachineSizedSInt or @MachineSizedUInt"); } if (sootType instanceof soot.ArrayType && !hasArrayAnnotation(method)) { throw new IllegalArgumentException( "@Array annotation expected on struct member getter " + method); } } else if (method.getParameterCount() == 1) { soot.Type sootType = method.getParameterType(0); if (hasPointerAnnotation(method, 0) && !sootType.equals(LongType.v())) { throw new IllegalArgumentException( "@StructMember(" + offset + ") annotated setter " + method + " must be of type long when annotated with @Pointer"); } if (hasMachineSizedFloatAnnotation(method, 0) && !sootType.equals(DoubleType.v()) && !sootType.equals(FloatType.v())) { throw new IllegalArgumentException( "@StructMember(" + offset + ") annotated setter " + method + " must be of type float or double when annotated with @MachineSizedFloat"); } if ((hasMachineSizedSIntAnnotation(method, 0) || hasMachineSizedUIntAnnotation(method)) && !sootType.equals(LongType.v())) { throw new IllegalArgumentException( "@StructMember(" + offset + ") annotated setter " + method + " must be of type long when annotated with @MachineSizedSInt or @MachineSizedUInt"); } if (sootType instanceof soot.ArrayType && !hasArrayAnnotation(method, 0)) { throw new IllegalArgumentException( "@Array annotation expected on first parameter of struct member setter " + method); } soot.Type retType = method.getReturnType(); // The return type of the setter must be void or this if (!retType.equals(VoidType.v()) && !(retType instanceof RefType && ((RefType) retType).getSootClass().equals(clazz))) { throw new IllegalArgumentException( "Setter " + method + " for " + "@StructMember(" + offset + ") " + " must either return nothing or return a " + clazz); } } else { throw new IllegalArgumentException( "@StructMember annotated method " + method + " has too many parameters"); } type = getStructMemberType(method); int index = offset + 1; if (result[index] == null) { result[index] = type; } else if (type != result[index]) { // Two members mapped to the same offset (union). Pick // the type with the largest alignment and pad with bytes // up to the largest size. result[index] = mergeStructMemberTypes(config.getDataLayout(), type, result[index]); } } } for (int i = 1; i < result.length; i++) { if (result[i] == null) { throw new IllegalArgumentException("No @StructMember(" + i + ") defined in class " + clazz); } } if (!clazz.isAbstract() && checkEmpty && n == 0 && superType == null) { throw new IllegalArgumentException( "Struct class " + clazz + " has no @StructMember annotated methods"); } return new StructureType(result); }
protected SootClass getClassForType(RefType ref_type) { SootClass soot_class = ref_type.getSootClass(); soot_class = Scene.v().getSootClass(soot_class.getName()); return soot_class; }
public boolean DoAnalysis(boolean verbose) { Stack<List<Set<SootClass>>> current_exception_sets = new Stack<List<Set<SootClass>>>(); { List<Set<SootClass>> exception_sets = new ArrayList<Set<SootClass>>(); exception_sets.add(method_exception_set); current_exception_sets.push(exception_sets); } PatchingChain<Unit> chain = body.getUnits(); Unit next = chain.getFirst(); int previous_class_count = method_exception_set.size(); for (Map.Entry<Unit, List<TwoValuePair<Trap, Set<SootClass>>>> entry : trap_begin_exception_sets.entrySet()) { for (TwoValuePair<Trap, Set<SootClass>> tvp : entry.getValue()) { previous_class_count += tvp.w.size(); } } do { if (trap_begin_exception_sets.containsKey(next)) { List<TwoValuePair<Trap, Set<SootClass>>> tvps = trap_begin_exception_sets.get(next); List<Set<SootClass>> sets_to_add = new ArrayList<Set<SootClass>>(); for (TwoValuePair<Trap, Set<SootClass>> tvp : tvps) { sets_to_add.add(tvp.w); } current_exception_sets.push(sets_to_add); } if (next instanceof InvokeStmt || next instanceof AssignStmt) { SootMethod callee = null; if (next instanceof AssignStmt) { if (((AssignStmt) next).getRightOp() instanceof InvokeExpr) { callee = ((InvokeExpr) ((AssignStmt) next).getRightOp()).getMethod(); } } else { callee = ((InvokeStmt) next).getInvokeExpr().getMethod(); } if (callee != null) { // invocation only Collection<SootClass> exception_classes; if (class_map.containsKey(callee.getDeclaringClass())) { assert class_map.get(callee.getDeclaringClass()).method_analysis.containsKey(callee); exception_classes = class_map .get(callee.getDeclaringClass()) .method_analysis .get(callee) .method_exception_set; } else { exception_classes = callee.getExceptions(); } for (SootClass exception_class : exception_classes) { for (Set<SootClass> current_exception_set : current_exception_sets.peek()) { current_exception_set.add(exception_class); } } } } else if (next instanceof ThrowStmt) { assert chain.getPredOf(next) instanceof JInvokeStmt; assert ((JInvokeStmt) chain.getPredOf(next)).getInvokeExpr() instanceof SpecialInvokeExpr; assert ((SpecialInvokeExpr) ((JInvokeStmt) chain.getPredOf(next)).getInvokeExpr()).getBase() instanceof JimpleLocal; assert ((JimpleLocal) ((SpecialInvokeExpr) ((JInvokeStmt) chain.getPredOf(next)).getInvokeExpr()) .getBase()) .getType() instanceof RefType; SootClass exception_class = ((RefType) ((JimpleLocal) ((SpecialInvokeExpr) ((JInvokeStmt) chain.getPredOf(next)).getInvokeExpr()) .getBase()) .getType()) .getSootClass(); for (Set<SootClass> current_exception_set : current_exception_sets.peek()) { current_exception_set.add(exception_class); } } if (trap_end_exception_sets.containsKey(next)) { List<TwoValuePair<Trap, Set<SootClass>>> tvps = trap_end_exception_sets.get(next); if (verbose) { for (Set<SootClass> current_exception_set : current_exception_sets.peek()) { if (current_exception_set.size() == 0) { for (TwoValuePair<Trap, Set<SootClass>> tvp : tvps) { if (!tvp.v.getException().getName().equals("java.lang.RuntimeException")) System.out.println( "Warning: In " + method.toString() + ": Unncessary exception handler for catching " + tvp.v.getException().getName()); } } } } for (TwoValuePair<Trap, Set<SootClass>> tvp : tvps) { Iterator<SootClass> i = tvp.w.iterator(); while (i.hasNext()) { SootClass exception_class = i.next(); if (tvp.v.getException() == exception_class) { // getting properly caught by the handler. i.remove(); } else { SootClass super_exception_class = exception_class; while (super_exception_class != null) { if (tvp.v.getException() == super_exception_class) { i.remove(); if (verbose && super_exception_class != exception_class && GetMostRestrictiveFormOfException(tvps, exception_class) == tvp.v.getException() && !super_exception_class.getName().equals("java.lang.RuntimeException")) { System.out.println( "Warning: In " + method.toString() + ": attempting to catch " + exception_class.getName() + " with " + super_exception_class.getName() + " Consider catching the most restrictive exception class"); } break; } try { super_exception_class = super_exception_class.getSuperclass(); } catch ( RuntimeException e) { // unfortunately soot doesn't have a specific exception class for "no // superclass for java.lang.Object" exception super_exception_class = null; } } } } } current_exception_sets.pop(); for (Set<SootClass> current_exception_set : current_exception_sets .peek()) { // This list iteration is not necessary if we are still making the // assumption that there's only one unique set that contains exception // classes if the range for traps are the same for (TwoValuePair<Trap, Set<SootClass>> tvp : tvps) { for (SootClass exception_class : tvp.w) { current_exception_set.add(exception_class); } } } } next = chain.getSuccOf(next); } while (next != null); int new_class_count = method_exception_set.size(); for (Map.Entry<Unit, List<TwoValuePair<Trap, Set<SootClass>>>> entry : trap_begin_exception_sets.entrySet()) { for (TwoValuePair<Trap, Set<SootClass>> tvp : entry.getValue()) { new_class_count += tvp.w.size(); } } return new_class_count != previous_class_count; }
private StructureConstant createClassInfoErrorStruct() { /* * Check that clazz can be loaded, i.e. that the superclass * and interfaces of the class exist and are accessible to the * class. Also check that any exception the class uses in catch * clauses exist and is accessible to the class. If the class * cannot be loaded we override the ClassInfoHeader struct * produced by the ClassCompiler for the class with one which * tells the code in bc.c to throw an appropriate exception * whenever clazz is accessed. */ int errorType = ClassCompiler.CI_ERROR_TYPE_NONE; String errorMessage = null; if (!sootClass.isInterface() && sootClass.hasSuperclass()) { // Check superclass SootClass superclazz = sootClass.getSuperclass(); if (superclazz.isPhantom()) { errorType = ClassCompiler.CI_ERROR_TYPE_NO_CLASS_DEF_FOUND; errorMessage = superclazz.getName(); } else if (!checkClassAccessible(superclazz, sootClass)) { errorType = ClassCompiler.CI_ERROR_TYPE_ILLEGAL_ACCESS; errorMessage = String.format(ILLEGAL_ACCESS_ERROR_CLASS, superclazz, sootClass); } else if (superclazz.isInterface()) { errorType = ClassCompiler.CI_ERROR_TYPE_INCOMPATIBLE_CLASS_CHANGE; errorMessage = String.format("class %s has interface %s as super class", sootClass, superclazz); } // No need to check for ClassCircularityError. Soot doesn't handle // such problems so the compilation will fail earlier. } if (errorType == ClassCompiler.CI_ERROR_TYPE_NONE) { // Check interfaces for (SootClass interfaze : sootClass.getInterfaces()) { if (interfaze.isPhantom()) { errorType = ClassCompiler.CI_ERROR_TYPE_NO_CLASS_DEF_FOUND; errorMessage = interfaze.getName(); break; } else if (!checkClassAccessible(interfaze, sootClass)) { errorType = ClassCompiler.CI_ERROR_TYPE_ILLEGAL_ACCESS; errorMessage = String.format(ILLEGAL_ACCESS_ERROR_CLASS, interfaze, sootClass); break; } else if (!interfaze.isInterface()) { errorType = ClassCompiler.CI_ERROR_TYPE_INCOMPATIBLE_CLASS_CHANGE; errorMessage = String.format( "class %s tries to implement class %s as interface", sootClass, interfaze); break; } } } if (errorType == ClassCompiler.CI_ERROR_TYPE_NONE) { // Check exceptions used in catch clauses. I cannot find any info in // the VM spec specifying that this has to be done when the class is loaded. // However, this is how it's done in other VMs so we do it too. for (String exName : catches) { Clazz ex = config.getClazzes().load(exName); if (ex == null || ex.getSootClass().isPhantom()) { errorType = ClassCompiler.CI_ERROR_TYPE_NO_CLASS_DEF_FOUND; errorMessage = exName; break; } else if (!checkClassAccessible(ex.getSootClass(), sootClass)) { errorType = ClassCompiler.CI_ERROR_TYPE_ILLEGAL_ACCESS; errorMessage = String.format(ILLEGAL_ACCESS_ERROR_CLASS, ex, sootClass); break; } } } if (errorType == ClassCompiler.CI_ERROR_TYPE_NONE) { return null; } // Create a ClassInfoError struct StructureConstantBuilder error = new StructureConstantBuilder(); error.add(new NullConstant(I8_PTR)); // Points to the runtime Class struct error.add(new IntegerConstant(ClassCompiler.CI_ERROR)); error.add(getString(getInternalName(sootClass))); error.add(new IntegerConstant(errorType)); error.add(getString(errorMessage)); return error.build(); }