Search in sources :

Example 56 with Body

use of soot.Body in project soot by Sable.

the class LibraryMethodWrappersBuilder method internalTransform.

protected void internalTransform(String phaseName, Map<String, String> options) {
    if (isVerbose()) {
        logger.info("Building Library Wrapper Methods...");
    }
    BodyBuilder.retrieveAllBodies();
    // iterate through application classes to find library calls
    final Iterator<SootClass> applicationClassesIterator = Scene.v().getApplicationClasses().snapshotIterator();
    while (applicationClassesIterator.hasNext()) {
        final SootClass applicationClass = applicationClassesIterator.next();
        if (isVerbose()) {
            logger.info("\tProcessing class {}", applicationClass.getName());
        }
        // create local copy to prevent java.util.ConcurrentModificationException
        final List<SootMethod> methods = new ArrayList<>(applicationClass.getMethods());
        for (SootMethod method : methods) {
            if (!method.isConcrete() || builtByMe.contains(method)) {
                continue;
            }
            final Body body = getBodySafely(method);
            if (body == null) {
                continue;
            }
            int localName = 0;
            final Unit first = getFirstNotIdentityStmt(body);
            final Iterator<Unit> unitIterator = body.getUnits().snapshotIterator();
            while (unitIterator.hasNext()) {
                final Unit unit = unitIterator.next();
                for (ValueBox valueBox : unit.getUseBoxes()) {
                    final Value value = valueBox.getValue();
                    // outside (this is prohibited on language level as that would violate encapsulation)
                    if (!(value instanceof InvokeExpr) || value instanceof SpecialInvokeExpr) {
                        continue;
                    }
                    final InvokeExpr invokeExpr = (InvokeExpr) value;
                    final SootMethod invokedMethod = getMethodSafely(invokeExpr);
                    if (invokedMethod == null) {
                        continue;
                    }
                    SootMethodRef invokedMethodRef = getNewMethodRef(invokedMethod);
                    if (invokedMethodRef == null) {
                        invokedMethodRef = buildNewMethod(applicationClass, invokedMethod, invokeExpr);
                        setNewMethodRef(invokedMethod, invokedMethodRef);
                        newmethods++;
                    }
                    if (isVerbose()) {
                        logger.info("\t\t\tChanging {} to {}\tUnit: ", invokedMethod.getSignature(), invokedMethodRef.getSignature(), unit);
                    }
                    List<Value> args = invokeExpr.getArgs();
                    List<Type> parameterTypes = invokedMethodRef.parameterTypes();
                    int argsCount = args.size();
                    int paramCount = parameterTypes.size();
                    if (invokeExpr instanceof InstanceInvokeExpr || invokeExpr instanceof StaticInvokeExpr) {
                        if (invokeExpr instanceof InstanceInvokeExpr) {
                            argsCount++;
                            args.add(((InstanceInvokeExpr) invokeExpr).getBase());
                        }
                        while (argsCount < paramCount) {
                            Type pType = parameterTypes.get(argsCount);
                            Local newLocal = Jimple.v().newLocal("newLocal" + localName++, pType);
                            body.getLocals().add(newLocal);
                            body.getUnits().insertBeforeNoRedirect(Jimple.v().newAssignStmt(newLocal, getConstantType(pType)), first);
                            args.add(newLocal);
                            argsCount++;
                        }
                        valueBox.setValue(Jimple.v().newStaticInvokeExpr(invokedMethodRef, args));
                    }
                    methodcalls++;
                }
            }
        }
    }
    Scene.v().releaseActiveHierarchy();
    Scene.v().setFastHierarchy(new FastHierarchy());
}
Also used : SootMethodRef(soot.SootMethodRef) SpecialInvokeExpr(soot.jimple.SpecialInvokeExpr) ArrayList(java.util.ArrayList) InstanceInvokeExpr(soot.jimple.InstanceInvokeExpr) Local(soot.Local) SootClass(soot.SootClass) Unit(soot.Unit) StaticInvokeExpr(soot.jimple.StaticInvokeExpr) DoubleType(soot.DoubleType) FloatType(soot.FloatType) IntType(soot.IntType) CharType(soot.CharType) LongType(soot.LongType) BooleanType(soot.BooleanType) ByteType(soot.ByteType) Type(soot.Type) VoidType(soot.VoidType) FastHierarchy(soot.FastHierarchy) InstanceInvokeExpr(soot.jimple.InstanceInvokeExpr) InterfaceInvokeExpr(soot.jimple.InterfaceInvokeExpr) SpecialInvokeExpr(soot.jimple.SpecialInvokeExpr) StaticInvokeExpr(soot.jimple.StaticInvokeExpr) VirtualInvokeExpr(soot.jimple.VirtualInvokeExpr) InvokeExpr(soot.jimple.InvokeExpr) ValueBox(soot.ValueBox) Value(soot.Value) SootMethod(soot.SootMethod) Body(soot.Body) JimpleBody(soot.jimple.JimpleBody)

Example 57 with Body

use of soot.Body in project soot by Sable.

the class MethodRenamer method internalTransform.

@Override
protected void internalTransform(String phaseName, Map<String, String> options) {
    if (isVerbose()) {
        logger.info("Transforming method names...");
    }
    BodyBuilder.retrieveAllBodies();
    BodyBuilder.retrieveAllNames();
    Scene.v().releaseActiveHierarchy();
    // but DO NOT RENAME METHODS YET as it might break searching of declaring classes
    for (SootClass applicationClass : Scene.v().getApplicationClasses()) {
        final List<String> fieldNames = applicationClass.getFields().stream().map(SootField::getName).collect(collectingAndThen(toList(), Collections::unmodifiableList));
        final List<String> leftFieldNames = new ArrayList<>(fieldNames);
        // create local copy to avoid ConcurrentModificationException -- methods are being updated
        final List<SootMethod> methods = new ArrayList<>(applicationClass.getMethods());
        for (SootMethod method : methods) {
            if (!isRenamingAllowed(method)) {
                continue;
            }
            final Set<SootClass> declaringClasses = getDeclaringClasses(applicationClass, method);
            if (declaringClasses.isEmpty()) {
                throw new IllegalStateException("Cannot find classes that declare " + method.getSignature() + ".");
            }
            final Optional<SootClass> libraryClass = declaringClasses.stream().filter(SootClass::isLibraryClass).findAny();
            if (libraryClass.isPresent()) {
                if (isVerbose()) {
                    logger.info("Skipping renaming {} method as it overrides library one from {}.", method.getSignature(), libraryClass.get().getName());
                }
                continue;
            }
            // we unite declaringClasses with parents of application class (excluding library ones)
            // to be sure that every class in this hierarchy has the only new name
            // for all methods (in this hierarchy) with the same old name and different parameters
            final Set<SootClass> union = uniteWithApplicationParents(applicationClass, declaringClasses);
            String newName = getNewName(union, method.getName());
            if (newName == null) {
                if (leftFieldNames.isEmpty()) {
                    newName = getNewName();
                } else {
                    final int randomIndex = Rand.getInt(leftFieldNames.size());
                    final String randomFieldName = leftFieldNames.remove(randomIndex);
                    // same name then we likely will fall in trouble when renaming this method before previous
                    if (isNotUnique(randomFieldName) || fieldNames.contains(randomFieldName)) {
                        newName = getNewName();
                    } else {
                        newName = randomFieldName;
                    }
                }
            }
            // to rename methods (and their calls) correctly
            for (SootClass declaringClass : union) {
                classToRenamingMap.computeIfAbsent(declaringClass, RENAMING_MAP_CREATOR).put(method.getName(), newName);
            }
        }
    }
    // rename methods AFTER creating mapping
    for (SootClass applicationClass : Scene.v().getApplicationClasses()) {
        final List<SootMethod> methods = new ArrayList<>(applicationClass.getMethods());
        for (SootMethod method : methods) {
            final String newName = getNewName(Collections.singleton(applicationClass), method.getName());
            if (newName != null) {
                if (isVerbose()) {
                    logger.info("Method \"{}\" is being renamed to \"{}\".", method.getSignature(), newName);
                }
                method.setName(newName);
            }
        }
    }
    // iterate through application classes, update references of renamed methods
    for (SootClass applicationClass : Scene.v().getApplicationClasses()) {
        final List<SootMethod> methods = new ArrayList<>(applicationClass.getMethods());
        for (SootMethod method : methods) {
            if (!method.isConcrete() || method.getDeclaringClass().isLibraryClass()) {
                continue;
            }
            final Body body = getActiveBodySafely(method);
            if (body == null) {
                continue;
            }
            for (Unit unit : body.getUnits()) {
                for (ValueBox valueBox : unit.getUseBoxes()) {
                    Value v = valueBox.getValue();
                    if (!(v instanceof InvokeExpr)) {
                        continue;
                    }
                    final InvokeExpr invokeExpr = (InvokeExpr) v;
                    final SootMethodRef methodRef = invokeExpr.getMethodRef();
                    final Set<SootClass> parents = getParents(methodRef.declaringClass());
                    // 1. we check if method overrides one from library directly
                    // Note: we cannot use getDeclaringClasses(applicationClass, method) as method can be renamed
                    final Optional<SootClass> declaringLibraryClass = findDeclaringLibraryClass(parents, methodRef);
                    if (declaringLibraryClass.isPresent()) {
                        if (isVerbose()) {
                            logger.info("Skipping replacing method call \"{}\" in \"{}\" as it is overrides one " + " from library {}.", methodRef.getSignature(), method.getSignature(), declaringLibraryClass.get().getName());
                        }
                        continue;
                    }
                    final String newName = getNewName(parents, methodRef.name());
                    // we will get new name only if no one from class tree do not overrides library method
                    if (newName == null) {
                        continue;
                    }
                    final SootMethodRef newMethodRef = Scene.v().makeMethodRef(methodRef.declaringClass(), newName, methodRef.parameterTypes(), methodRef.returnType(), methodRef.isStatic());
                    invokeExpr.setMethodRef(newMethodRef);
                    if (isVerbose()) {
                        logger.info("Method call \"{}\" is being replaced with \"{}\" in {}.", methodRef.getSignature(), newMethodRef.getSignature(), method.getSignature());
                    }
                }
            }
        }
    }
    Scene.v().releaseActiveHierarchy();
    Scene.v().setFastHierarchy(new FastHierarchy());
    if (isVerbose()) {
        logger.info("Transforming method names is completed.");
    }
}
Also used : SootMethodRef(soot.SootMethodRef) ArrayList(java.util.ArrayList) SootClass(soot.SootClass) Unit(soot.Unit) FastHierarchy(soot.FastHierarchy) InvokeExpr(soot.jimple.InvokeExpr) ValueBox(soot.ValueBox) Value(soot.Value) SootMethod(soot.SootMethod) Body(soot.Body)

Aggregations

Body (soot.Body)57 Unit (soot.Unit)37 SootMethod (soot.SootMethod)32 Local (soot.Local)20 SootClass (soot.SootClass)19 Value (soot.Value)15 InvokeExpr (soot.jimple.InvokeExpr)14 StaticInvokeExpr (soot.jimple.StaticInvokeExpr)13 Type (soot.Type)12 Stmt (soot.jimple.Stmt)12 InstanceInvokeExpr (soot.jimple.InstanceInvokeExpr)11 JimpleBody (soot.jimple.JimpleBody)11 SpecialInvokeExpr (soot.jimple.SpecialInvokeExpr)11 RefType (soot.RefType)10 VoidType (soot.VoidType)10 VirtualInvokeExpr (soot.jimple.VirtualInvokeExpr)10 LinkedList (java.util.LinkedList)9 SootMethodRef (soot.SootMethodRef)9 ArrayList (java.util.ArrayList)8 PrimType (soot.PrimType)8