private void loadClasses() { Date start = new Date(); if (entryClass != null) { SootUtils.loadClassesForEntry(entryClass); } else { for (JavaCriticalSection cs : results) { String clsname = cs.getClassName(); String regex = "\\$\\d"; Pattern pattern = Pattern.compile(regex); Matcher matcher = pattern.matcher(clsname); if (matcher.find()) { System.out.println("can't find the class created randomly by compiler"); continue; } SootClass cls = Scene.v().loadClassAndSupport(clsname); if (setMainClass == true && cls.declaresMethod( Scene.v().getSubSigNumberer().findOrAdd("void main(java.lang.String[])"))) { Scene.v().setMainClass(cls); setMainClass = false; } } Scene.v().loadNecessaryClasses(); } Date end = new Date(); System.out.println( "load " + Scene.v().getClasses().size() + " classes in " + getTimeConsumed(start, end)); }
public void staticBlockInlining(SootClass sootClass) { this.sootClass = sootClass; // retrieve the clinit method if any for sootClass if (!sootClass.declaresMethod("void <clinit>()")) { System.out.println("no clinit"); return; } SootMethod clinit = sootClass.getMethod("void <clinit>()"); // System.out.println(clinit); // retireve the active body if (!clinit.hasActiveBody()) throw new RuntimeException("method " + clinit.getName() + " has no active body!"); Body clinitBody = clinit.getActiveBody(); Chain units = ((DavaBody) clinitBody).getUnits(); if (units.size() != 1) { throw new RuntimeException("DavaBody AST doesn't have single root."); } ASTNode AST = (ASTNode) units.getFirst(); if (!(AST instanceof ASTMethodNode)) throw new RuntimeException("Starting node of DavaBody AST is not an ASTMethodNode"); AST.apply(new MethodCallFinder(this)); }
private static boolean hasFinalizer(SootClass clazz) { // Don't search interfaces or java.lang.Object if (clazz.isInterface() || !clazz.hasSuperclass()) { return false; } return clazz.declaresMethod("finalize", Collections.emptyList(), VoidType.v()); }
/** * Resolve the concrete target of a special invoke using our modified semantics for special invoke * expression. */ private SootMethod resolveSpecialInvokeTarget(SpecialInvokeExpr si) { SootMethod target = null; try { target = SootUtils.resolve(si.getMethodRef()); } catch (CannotFindMethodException e) { logger.error("Cannot find concrete method target for special invoke: {}", si); return null; } String targetSubSig = target.getSubSignature(); SootClass current = target.getDeclaringClass(); while (true) { if (current.declaresMethod(targetSubSig)) { return current.getMethod(targetSubSig); } // not a match in current, try superclass on next loop if (current.hasSuperclass()) current = current.getSuperclass(); else { logger.error("Cannot find concrete method target for special invoke: {}", si); droidsafe.main.Main.exit(1); return null; } } }
/** * Finds in class hierarchy and returns all app and lib concrete methods possibly referenced by * method ref. Method is assumed to be virtual (not special or static). Returns true if there are * library methods among targets found. */ public static boolean getConcreteCallTargets( InvokeExpr instInvExpr, /*OUT*/ Set<SootMethod> appTargets, /*OUT*/ Set<SootMethod> libTargets) { // get class of method ref; we start searching from this class SootMethodRef mref = instInvExpr.getMethodRef(); SootClass cls = mref.declaringClass(); // starting class final NumberedString subsignature = mref.getSubSignature(); // signature to search for // CASE 1: object is of declared class type or inherited from some superclass // find first superclass, starting from current cls, that declares method; there HAS to // be such a class // note that if cls is interface, superclass if java.lang.Object // note that we don't check if there is indeed an interface declaring the method; we assume this // is the case if no superclass declares it while (!cls.declaresMethod(subsignature) && cls.hasSuperclass()) cls = cls.getSuperclass(); // never an interface // now, method might not be in superclass, or might be abstract; in that case, it's not a target SootMethod m; if (cls.declaresMethod(subsignature)) { m = cls.getMethod(subsignature); if (!m.isAbstract()) { if (cls.hasTag(ClassTag.TAG_NAME)) appTargets.add(m); // add app method else libTargets.add(m); // add lib method } } // (only for virtual/interface calls) // CASE 2: object's actual type is a subclass; any subclass declaring the method is a possible // target // we have to check all superclasses of implementers, because starting cls might be // interface if (instInvExpr instanceof VirtualInvokeExpr || instInvExpr instanceof InterfaceInvokeExpr) { cls = mref.declaringClass(); // start again from declaring class List<SootClass> allSubclasses = getAllSubtypes(cls); for (SootClass subCls : allSubclasses) { m = getMethodInClassOrSuperclass(subCls, subsignature); if (m != null && !m.isAbstract()) { if (m.getDeclaringClass().hasTag(ClassTag.TAG_NAME)) appTargets.add(m); // add app method else libTargets.add(m); // add lib method } } } return !libTargets.isEmpty(); }
/** For instance invokes */ public static ArrayList<SootMethod> resolveAppCall(Type tgtType, SootMethodRef methodRef) { final NumberedString mSubsignature = methodRef.getSubSignature(); if (tgtType instanceof RefType) { // find first class upwards in hierarchy, starting from cls, that implements method (i.e., // *concrete* method) SootClass cls = ((RefType) tgtType).getSootClass(); while (!cls.declaresMethod(mSubsignature)) cls = cls .getSuperclass(); // if method not in this class, it HAS to be in a superclass, so a // superclass must exist if (!cls.hasTag(ClassTag.TAG_NAME)) return null; // not an app method // finally, store resolved app method SootMethod m = cls.getMethod(mSubsignature); assert m.hasTag(MethodTag.TAG_NAME); ArrayList<SootMethod> methods = new ArrayList<SootMethod>(); methods.add(m); // just one element, directly resolved return methods; } if (tgtType instanceof AnySubType) { // return set of all app subtypes that implement referenced method SootClass baseCls = ((AnySubType) tgtType).getBase().getSootClass(); List subClasses = baseCls.isInterface() ? Scene.v().getActiveHierarchy().getImplementersOf(baseCls) : Scene.v().getActiveHierarchy().getSubclassesOf(baseCls); ArrayList<SootMethod> methods = new ArrayList<SootMethod>(); for (Object oSubCls : subClasses) { SootClass subCls = (SootClass) oSubCls; if (subCls.hasTag(ClassTag.TAG_NAME)) { try { SootMethod m = subCls.getMethod(mSubsignature); assert m.hasTag(MethodTag.TAG_NAME); if (!m.isAbstract()) methods.add(m); } catch (RuntimeException e) { } } } return methods; } assert tgtType instanceof ArrayType; // only other case observed so far return new ArrayList(); // no array class/method is in app }
public ASTMethodNode inline(SootMethod maybeInline) { // check if this method should be inlined if (sootClass != null) { // 1, method should belong to the same class as the clinit method if (sootClass.declaresMethod(maybeInline.getSubSignature())) { // System.out.println("The method invoked is from the same class"); // 2, method should be static if (Modifier.isStatic(maybeInline.getModifiers())) { // decided to inline // send the ASTMethod node of the TO BE INLINED METHOD // retireve the active body if (!maybeInline.hasActiveBody()) throw new RuntimeException("method " + maybeInline.getName() + " has no active body!"); Body bod = maybeInline.getActiveBody(); Chain units = ((DavaBody) bod).getUnits(); if (units.size() != 1) { throw new RuntimeException("DavaBody AST doesn't have single root."); } ASTNode ASTtemp = (ASTNode) units.getFirst(); if (!(ASTtemp instanceof ASTMethodNode)) throw new RuntimeException("Starting node of DavaBody AST is not an ASTMethodNode"); // restricting to methods which do not have any variables declared ASTMethodNode toReturn = (ASTMethodNode) ASTtemp; ASTStatementSequenceNode declarations = toReturn.getDeclarations(); if (declarations.getStatements().size() == 0) { // inline only if there are no declarations in the method inlined System.out.println("No declarations in the method. we can inline this method"); return toReturn; } } } } return null; // meaning dont inline }
private StructureConstant createClassInfoStruct() { int flags = 0; if (Modifier.isPublic(sootClass.getModifiers())) { flags |= CI_PUBLIC; } if (Modifier.isFinal(sootClass.getModifiers())) { flags |= CI_FINAL; } if (Modifier.isInterface(sootClass.getModifiers())) { flags |= CI_INTERFACE; } if (Modifier.isAbstract(sootClass.getModifiers())) { flags |= CI_ABSTRACT; } if ((sootClass.getModifiers() & 0x1000) > 0) { flags |= CI_SYNTHETIC; } if (Modifier.isAnnotation(sootClass.getModifiers())) { flags |= CI_ANNOTATION; } if (Modifier.isEnum(sootClass.getModifiers())) { flags |= CI_ENUM; } if (attributesEncoder.classHasAttributes()) { flags |= CI_ATTRIBUTES; } if (hasFinalizer(sootClass)) { flags |= CI_FINALIZABLE; } // Create the ClassInfoHeader structure. StructureConstantBuilder header = new StructureConstantBuilder(); header.add(new NullConstant(I8_PTR)); // Points to the runtime Class struct header.add(new IntegerConstant(flags)); header.add(getString(getInternalName(sootClass))); if (sootClass.declaresMethod("<clinit>", Collections.emptyList(), VoidType.v())) { SootMethod method = sootClass.getMethod("<clinit>", Collections.emptyList(), VoidType.v()); header.add(new FunctionRef(mangleMethod(method), getFunctionType(method))); } else { header.add(new NullConstant(I8_PTR)); } header.add(sizeof(classType)); header.add(sizeof(instanceType)); if (!instanceFields.isEmpty()) { header.add(offsetof(instanceType, 1, 1)); } else { header.add(sizeof(instanceType)); } header.add(new IntegerConstant((short) countReferences(classFields))); header.add(new IntegerConstant((short) countReferences(instanceFields))); PackedStructureConstantBuilder body = new PackedStructureConstantBuilder(); body.add(new IntegerConstant((short) sootClass.getInterfaceCount())); body.add(new IntegerConstant((short) sootClass.getFieldCount())); body.add(new IntegerConstant((short) sootClass.getMethodCount())); if (!sootClass.isInterface()) { body.add( getStringOrNull( sootClass.hasSuperclass() ? getInternalName(sootClass.getSuperclass()) : null)); } if (attributesEncoder.classHasAttributes()) { body.add(new ConstantBitcast(attributesEncoder.getClassAttributes().ref(), I8_PTR)); } for (SootClass s : sootClass.getInterfaces()) { body.add(getString(getInternalName(s))); } for (SootField f : sootClass.getFields()) { flags = 0; soot.Type t = f.getType(); if (t instanceof PrimType) { if (t.equals(BooleanType.v())) { flags |= DESC_Z; } else if (t.equals(ByteType.v())) { flags |= DESC_B; } else if (t.equals(ShortType.v())) { flags |= DESC_S; } else if (t.equals(CharType.v())) { flags |= DESC_C; } else if (t.equals(IntType.v())) { flags |= DESC_I; } else if (t.equals(LongType.v())) { flags |= DESC_J; } else if (t.equals(FloatType.v())) { flags |= DESC_F; } else if (t.equals(DoubleType.v())) { flags |= DESC_D; } flags <<= 12; } if (Modifier.isPublic(f.getModifiers())) { flags |= FI_PUBLIC; } else if (Modifier.isPrivate(f.getModifiers())) { flags |= FI_PRIVATE; } else if (Modifier.isProtected(f.getModifiers())) { flags |= FI_PROTECTED; } if (Modifier.isStatic(f.getModifiers())) { flags |= FI_STATIC; } if (Modifier.isFinal(f.getModifiers())) { flags |= FI_FINAL; } if (Modifier.isVolatile(f.getModifiers())) { flags |= FI_VOLATILE; } if (Modifier.isTransient(f.getModifiers())) { flags |= FI_TRANSIENT; } if ((f.getModifiers() & 0x1000) > 0) { flags |= FI_SYNTHETIC; } if (Modifier.isEnum(f.getModifiers())) { flags |= FI_ENUM; } if (attributesEncoder.fieldHasAttributes(f)) { flags |= FI_ATTRIBUTES; } body.add(new IntegerConstant((short) flags)); body.add(getString(f.getName())); if (!(t instanceof PrimType)) { body.add(getString(getDescriptor(f))); } if (f.isStatic()) { int index = classFields.indexOf(f); body.add(offsetof(classType, 1, index, 1)); } else { int index = instanceFields.indexOf(f); body.add(offsetof(instanceType, 1, 1 + index, 1)); } if (attributesEncoder.fieldHasAttributes(f)) { body.add(new ConstantBitcast(attributesEncoder.getFieldAttributes(f).ref(), I8_PTR)); } } for (SootMethod m : sootClass.getMethods()) { soot.Type t = m.getReturnType(); flags = 0; if (Modifier.isPublic(m.getModifiers())) { flags |= MI_PUBLIC; } else if (Modifier.isPrivate(m.getModifiers())) { flags |= MI_PRIVATE; } else if (Modifier.isProtected(m.getModifiers())) { flags |= MI_PROTECTED; } if (Modifier.isStatic(m.getModifiers())) { flags |= MI_STATIC; } if (Modifier.isFinal(m.getModifiers())) { flags |= MI_FINAL; } if (Modifier.isSynchronized(m.getModifiers())) { flags |= MI_SYNCHRONIZED; } if ((m.getModifiers() & 0x0040) > 0) { flags |= MI_BRIDGE; } if ((m.getModifiers() & 0x0080) > 0) { flags |= MI_VARARGS; } if (Modifier.isNative(m.getModifiers())) { if (!isStruct(sootClass) && !isStructMember(m)) { flags |= MI_NATIVE; } } if (Modifier.isAbstract(m.getModifiers())) { flags |= MI_ABSTRACT; } if (Modifier.isStrictFP(m.getModifiers())) { flags |= MI_STRICT; } if ((m.getModifiers() & 0x1000) > 0) { flags |= MI_SYNTHETIC; } if (attributesEncoder.methodHasAttributes(m)) { flags |= MI_ATTRIBUTES; } if (isBridge(m)) { flags |= MI_BRO_BRIDGE; } if (isCallback(m)) { flags |= MI_BRO_CALLBACK; } if ((t instanceof PrimType || t == VoidType.v()) && m.getParameterCount() == 0) { flags |= MI_COMPACT_DESC; } body.add(new IntegerConstant((short) flags)); body.add(getString(m.getName())); if ((flags & MI_COMPACT_DESC) > 0) { int desc = 0; if (t.equals(BooleanType.v())) { desc = DESC_Z; } else if (t.equals(ByteType.v())) { desc = DESC_B; } else if (t.equals(ShortType.v())) { desc = DESC_S; } else if (t.equals(CharType.v())) { desc = DESC_C; } else if (t.equals(IntType.v())) { desc = DESC_I; } else if (t.equals(LongType.v())) { desc = DESC_J; } else if (t.equals(FloatType.v())) { desc = DESC_F; } else if (t.equals(DoubleType.v())) { desc = DESC_D; } else if (t.equals(VoidType.v())) { desc = DESC_V; } body.add(new IntegerConstant((byte) desc)); } else { body.add(getString(getDescriptor(m))); } if (attributesEncoder.methodHasAttributes(m)) { body.add(new ConstantBitcast(attributesEncoder.getMethodAttributes(m).ref(), I8_PTR)); } if (!m.isAbstract()) { body.add(new ConstantBitcast(new FunctionRef(mangleMethod(m), getFunctionType(m)), I8_PTR)); body.add( new IntegerConstant( DUMMY_METHOD_SIZE)); // Size of function. This value will be modified later by // patching the .s file. if (m.isSynchronized()) { body.add( new ConstantBitcast( new FunctionRef(mangleMethod(m) + "_synchronized", getFunctionType(m)), I8_PTR)); } } if (isBridge(m)) { body.add(new GlobalRef(BridgeMethodCompiler.getTargetFnPtrName(m), I8_PTR)); } if (isCallback(m)) { body.add( new ConstantBitcast( new FunctionRef(mangleMethod(m) + "_callback", getCallbackFunctionType(m)), I8_PTR)); } } // Return the struct {header, body}. To be compatible with the C code in classinfo.c // it is important that the header is padded the same as in C so that the body starts // after sizeof(ClassInfoHeader) bytes. return new StructureConstantBuilder().add(header.build()).add(body.build()).build(); }
/** * Returns method in given class or first upwards superclass, or null if not found in any class * (no interface checked) */ private static SootMethod getMethodInClassOrSuperclass( SootClass cls, NumberedString subsignature) { if (cls.declaresMethod(subsignature)) return cls.getMethod(subsignature); if (cls.hasSuperclass()) return getMethodInClassOrSuperclass(cls.getSuperclass(), subsignature); return null; }
private Value mutate(Value value) { if (value instanceof FieldRef) { FieldRef ref = (FieldRef) value; SootField field = ref.getField(); Type type = field.getType(); if (type instanceof RefType) { RefType ref_type = (RefType) type; SootClass soot_class = ref_type.getSootClass(); if (shouldMap(soot_class)) { addField(field, ref); } } else if (type instanceof ArrayType) { ArrayType array_type = (ArrayType) type; Type base_type = array_type.baseType; if (base_type instanceof RefType) { RefType ref_type = (RefType) base_type; SootClass soot_class = ref_type.getSootClass(); if (shouldMap(soot_class)) { addField(field, ref); } } } SootClass soot_class = field.getDeclaringClass(); if (shouldMap(soot_class)) { addField(field, ref); } return value; } else if (value instanceof InvokeExpr) { InvokeExpr expr = (InvokeExpr) value; SootMethodRef ref = expr.getMethodRef(); SootClass soot_class = ref.declaringClass(); final NumberedString subSignature = ref.getSubSignature(); if (shouldMap(soot_class)) { SootClass new_class = getMapping(soot_class); if (new_class.declaresMethod(subSignature)) { SootMethod new_method = RootbeerScene.v().getMethod(new_class, subSignature.getString()); addAddedMethod(new_method); fixArguments(new_method); RootbeerScene.v().getDfsInfo().addReachableMethodSig(new_method.getSignature()); expr.setMethodRef(new_method.makeRef()); } } else { if (soot_class.declaresMethod(ref.getSubSignature())) { SootMethod method = soot_class.getMethod(ref.getSubSignature()); fixArguments(method); } } ref = remapRef(ref); try { if (shouldMap(soot_class)) { soot_class = getMapping(soot_class); } SootMethod method = soot_class.getMethod(ref.getSubSignature()); RootbeerScene.v().getDfsInfo().addReachableMethodSig(method.getSignature()); expr.setMethodRef(method.makeRef()); } catch (Exception ex) { // ex.printStackTrace(); } return value; } else if (value instanceof NewExpr) { NewExpr expr = (NewExpr) value; RefType base_type = expr.getBaseType(); SootClass soot_class = base_type.getSootClass(); if (shouldMap(soot_class)) { SootClass new_class = getMapping(soot_class); expr.setBaseType(new_class.getType()); } return value; } else if (value instanceof NewArrayExpr) { NewArrayExpr expr = (NewArrayExpr) value; Type base_type = expr.getBaseType(); base_type = fixType(base_type); expr.setBaseType(base_type); return value; } else if (value instanceof NewMultiArrayExpr) { NewMultiArrayExpr expr = (NewMultiArrayExpr) value; ArrayType array_type = expr.getBaseType(); Type base_type = array_type.baseType; if (base_type instanceof RefType) { RefType ref_type = (RefType) base_type; SootClass soot_class = ref_type.getSootClass(); if (shouldMap(soot_class)) { SootClass new_class = getMapping(soot_class); ArrayType new_type = ArrayType.v(new_class.getType(), array_type.numDimensions); expr.setBaseType(new_type); } } return value; } else if (value instanceof CastExpr) { CastExpr expr = (CastExpr) value; Type cast_type = expr.getCastType(); cast_type = fixType(cast_type); expr.setCastType(cast_type); return value; } else if (value instanceof ParameterRef) { ParameterRef ref = (ParameterRef) value; Type new_type = fixType(ref.getType()); return new ParameterRef(new_type, ref.getIndex()); } else if (value instanceof ThisRef) { ThisRef ref = (ThisRef) value; Type new_type = fixType(ref.getType()); return new ThisRef((RefType) new_type); } else if (value instanceof Local) { Local local = (Local) value; Type type = local.getType(); local.setType(fixType(type)); return value; } else { return value; } }