Search in sources :

Example 1 with ASTMethodNode

use of soot.dava.internal.AST.ASTMethodNode in project soot by Sable.

the class MethodCallFinder method inInvokeStmt.

/*
	 * some ASTConstuct{ ASTConstruct{ Some bodies Some Bodies Statement
	 * SequenceNode New Stmt seq node with some stmts some stmts ---------->
	 * Body of method to inline the invoke stmt New Stmt seq node with other
	 * stmts some other stmts Some other bodies Some other bodies End
	 * ASTConstruct End ASTConstruct
	 */
/*
	 * Notice that since this class is only invoked for clinit methods this
	 * invoke statement is some invocation that occured within the clinit method
	 */
public void inInvokeStmt(InvokeStmt s) {
    InvokeExpr invokeExpr = s.getInvokeExpr();
    SootMethod maybeInline = invokeExpr.getMethod();
    // check whether we want to inline
    ASTMethodNode toInlineASTMethod = cleaner.inline(maybeInline);
    if (toInlineASTMethod == null) {
        // not to inline
        return;
    } else {
        // yes we want to inline
        // we know that the method to be inlined has no declarations.
        List<Object> subBodies = toInlineASTMethod.get_SubBodies();
        if (subBodies.size() != 1) {
            throw new RuntimeException("Found ASTMEthod node with more than one subBodies");
        }
        List body = (List) subBodies.get(0);
        ASTParentNodeFinder finder = new ASTParentNodeFinder();
        underAnalysis.apply(finder);
        List<ASTStatementSequenceNode> newChangedBodyPart = createChangedBodyPart(s, body, finder);
        boolean replaced = replaceSubBody(s, newChangedBodyPart, finder);
        if (replaced) {
            // so the invoke stmt has been replaced with the body of the
            // method invoked
            /*
				 * if the inlined method contained an assignment to a static
				 * field we want to replace that with a throw stmt
				 */
            StaticDefinitionFinder defFinder = new StaticDefinitionFinder(maybeInline);
            toInlineASTMethod.apply(defFinder);
            if (defFinder.anyFinalFieldDefined()) {
                // create throw stmt to be added to inlined method
                // create a SootMethodRef
                SootClass runtime = Scene.v().loadClassAndSupport("java.lang.RuntimeException");
                if (runtime.declaresMethod("void <init>(java.lang.String)")) {
                    SootMethod sootMethod = runtime.getMethod("void <init>(java.lang.String)");
                    SootMethodRef methodRef = sootMethod.makeRef();
                    RefType myRefType = RefType.v(runtime);
                    StringConstant tempString = StringConstant.v("This method used to have a definition of a final variable. " + "Dava inlined the definition into the static initializer");
                    List list = new ArrayList();
                    list.add(tempString);
                    GNewInvokeExpr newInvokeExpr = new GNewInvokeExpr(myRefType, methodRef, list);
                    GThrowStmt throwStmt = new GThrowStmt(newInvokeExpr);
                    AugmentedStmt augStmt = new AugmentedStmt(throwStmt);
                    List<AugmentedStmt> sequence = new ArrayList<AugmentedStmt>();
                    sequence.add(augStmt);
                    ASTStatementSequenceNode seqNode = new ASTStatementSequenceNode(sequence);
                    List<Object> subBody = new ArrayList<Object>();
                    subBody.add(seqNode);
                    toInlineASTMethod.replaceBody(subBody);
                }
            }
        }
    }
}
Also used : ASTParentNodeFinder(soot.dava.toolkits.base.AST.traversals.ASTParentNodeFinder) SootMethodRef(soot.SootMethodRef) ArrayList(java.util.ArrayList) ASTStatementSequenceNode(soot.dava.internal.AST.ASTStatementSequenceNode) SootClass(soot.SootClass) AugmentedStmt(soot.dava.internal.asg.AugmentedStmt) RefType(soot.RefType) GNewInvokeExpr(soot.grimp.internal.GNewInvokeExpr) InvokeExpr(soot.jimple.InvokeExpr) GNewInvokeExpr(soot.grimp.internal.GNewInvokeExpr) GThrowStmt(soot.grimp.internal.GThrowStmt) SootMethod(soot.SootMethod) ASTMethodNode(soot.dava.internal.AST.ASTMethodNode) ArrayList(java.util.ArrayList) List(java.util.List) StringConstant(soot.jimple.StringConstant)

Example 2 with ASTMethodNode

use of soot.dava.internal.AST.ASTMethodNode in project soot by Sable.

the class InterProceduralAnalyses method applyInterProceduralAnalyses.

/*
	 * Method is invoked by postProcessDava in PackManager
	 * if the transformations flag is true
	 * 
	 * All interproceduralAnalyses should be applied in here
	 */
public static void applyInterProceduralAnalyses() {
    Chain classes = Scene.v().getApplicationClasses();
    if (DEBUG)
        System.out.println("\n\nInvoking redundantFielduseEliminator");
    ConstantFieldValueFinder finder = new ConstantFieldValueFinder(classes);
    HashMap<String, Object> constantValueFields = finder.getFieldsWithConstantValues();
    if (DEBUG)
        finder.printConstantValueFields();
    /*
		 * The code above this gathers interprocedural information
		 * the code below this USES the interprocedural results
		 */
    Iterator it = classes.iterator();
    while (it.hasNext()) {
        // go though all the methods
        SootClass s = (SootClass) it.next();
        Iterator methodIt = s.methodIterator();
        while (methodIt.hasNext()) {
            SootMethod m = (SootMethod) methodIt.next();
            /*
				 * Adding try block to handle RuntimeException no active body found
				 */
            DavaBody body = null;
            if (m.hasActiveBody()) {
                body = (DavaBody) m.getActiveBody();
            } else {
                continue;
            }
            ASTNode AST = (ASTNode) body.getUnits().getFirst();
            if (!(AST instanceof ASTMethodNode))
                continue;
            Map options = PhaseOptions.v().getPhaseOptions("db.deobfuscate");
            boolean deobfuscate = PhaseOptions.getBoolean(options, "enabled");
            // System.out.println("force is "+force);
            if (deobfuscate) {
                if (DEBUG)
                    System.out.println("\nSTART CP Class:" + s.getName() + " Method: " + m.getName());
                CPApplication CPApp = new CPApplication((ASTMethodNode) AST, constantValueFields, finder.getClassNameFieldNameToSootFieldMapping());
                AST.apply(CPApp);
                if (DEBUG)
                    System.out.println("DONE CP for " + m.getName());
            }
            // expression simplification
            // SimplifyExpressions.DEBUG=true;
            AST.apply(new SimplifyExpressions());
            // SimplifyConditions.DEBUG=true;
            AST.apply(new SimplifyConditions());
            // condition elimination
            // EliminateConditions.DEBUG=true;
            AST.apply(new EliminateConditions((ASTMethodNode) AST));
            // the above should ALWAYS be followed by an unreachable code eliminator
            AST.apply(new UnreachableCodeEliminator(AST));
            // local variable cleanup
            AST.apply(new LocalVariableCleaner(AST));
            // VERY EXPENSIVE STAGE of redoing all analyses!!!!
            if (deobfuscate) {
                if (DEBUG)
                    System.out.println("reinvoking analyzeAST");
                UselessLabelFinder.DEBUG = false;
                body.analyzeAST();
            }
            // renaming should be applied as the last stage
            options = PhaseOptions.v().getPhaseOptions("db.renamer");
            boolean renamer = PhaseOptions.getBoolean(options, "enabled");
            // System.out.println("renaming is"+renamer);
            if (renamer) {
                applyRenamerAnalyses(AST, body);
            }
            // remove returns from void methods
            VoidReturnRemover.cleanClass(s);
        }
    }
}
Also used : Chain(soot.util.Chain) EliminateConditions(soot.dava.toolkits.base.AST.transformations.EliminateConditions) SootClass(soot.SootClass) UnreachableCodeEliminator(soot.dava.toolkits.base.AST.transformations.UnreachableCodeEliminator) DavaBody(soot.dava.DavaBody) SimplifyConditions(soot.dava.toolkits.base.AST.transformations.SimplifyConditions) Iterator(java.util.Iterator) ASTNode(soot.dava.internal.AST.ASTNode) SootMethod(soot.SootMethod) LocalVariableCleaner(soot.dava.toolkits.base.AST.transformations.LocalVariableCleaner) ASTMethodNode(soot.dava.internal.AST.ASTMethodNode) HashMap(java.util.HashMap) Map(java.util.Map) SimplifyExpressions(soot.dava.toolkits.base.AST.transformations.SimplifyExpressions) CPApplication(soot.dava.toolkits.base.AST.transformations.CPApplication)

Example 3 with ASTMethodNode

use of soot.dava.internal.AST.ASTMethodNode in project soot by Sable.

the class SuperFirstStmtHandler method addDefsToLiveVariables.

/*
	 * newASTPreInitMethod at time of invocation just contains body X find all
	 * defs for this body
	 */
private List<Local> addDefsToLiveVariables() {
    // get all defs within x
    AllDefinitionsFinder finder = new AllDefinitionsFinder();
    newASTPreInitMethod.apply(finder);
    List<DefinitionStmt> allDefs = finder.getAllDefs();
    List<Local> uniqueLocals = new ArrayList<Local>();
    List<DefinitionStmt> uniqueLocalDefs = new ArrayList<DefinitionStmt>();
    // remove any defs for fields, and any which are done multiple times
    Iterator<DefinitionStmt> it = allDefs.iterator();
    while (it.hasNext()) {
        DefinitionStmt s = it.next();
        Value left = s.getLeftOp();
        if (left instanceof Local) {
            if (uniqueLocals.contains(left)) {
                // a def for this local already encountered
                int index = uniqueLocals.indexOf(left);
                uniqueLocals.remove(index);
                uniqueLocalDefs.remove(index);
            } else {
                // no def for this local yet
                uniqueLocals.add((Local) left);
                uniqueLocalDefs.add(s);
            }
        }
    }
    // at this point unique locals contains all locals defined and
    // uniqueLocaldef list has a list of the corresponding definitions
    // Now remove those unique locals and localdefs whose stmtseq node does
    // not have the ASTMEthodNode as a parent
    // This is a conservative step!!
    ASTParentNodeFinder parentFinder = new ASTParentNodeFinder();
    newASTPreInitMethod.apply(parentFinder);
    List<DefinitionStmt> toRemoveDefs = new ArrayList<DefinitionStmt>();
    it = uniqueLocalDefs.iterator();
    while (it.hasNext()) {
        DefinitionStmt s = it.next();
        Object parent = parentFinder.getParentOf(s);
        if (parent == null || (!(parent instanceof ASTStatementSequenceNode))) {
            // shouldnt happen but if it does add this s to toRemove list
            toRemoveDefs.add(s);
        }
        // parent is an ASTStatementsequence node. check that its parent is
        // the ASTMethodNode
        Object grandParent = parentFinder.getParentOf(parent);
        if (grandParent == null || (!(grandParent instanceof ASTMethodNode))) {
            // can happen if obfuscators are really smart. add s to toRemove
            // list
            toRemoveDefs.add(s);
        }
    }
    // remove any defs and corresponding locals if present in the
    // toRemoveDefs list
    it = toRemoveDefs.iterator();
    while (it.hasNext()) {
        DefinitionStmt s = it.next();
        int index = uniqueLocalDefs.indexOf(s);
        uniqueLocals.remove(index);
        uniqueLocalDefs.remove(index);
    }
    // the uniqueLocalDefs contains all those definitions to unique locals
    // which are not deeply nested in the X body
    // find all the uses of these definitions in the original method body
    toRemoveDefs = new ArrayList<DefinitionStmt>();
    ASTUsesAndDefs uDdU = new ASTUsesAndDefs(originalASTMethod);
    originalASTMethod.apply(uDdU);
    it = uniqueLocalDefs.iterator();
    while (it.hasNext()) {
        DefinitionStmt s = it.next();
        Object temp = uDdU.getDUChain(s);
        if (temp == null) {
            // couldnt find uses
            toRemoveDefs.add(s);
            continue;
        }
        ArrayList uses = (ArrayList) temp;
        // check if uses is non-empty
        if (uses.size() == 0) {
            toRemoveDefs.add(s);
        }
        // check for all the non zero uses
        Iterator useIt = uses.iterator();
        boolean onlyInConstructorUnit = true;
        while (useIt.hasNext()) {
            // a use is either a statement or a node(condition, synch,
            // switch , for etc)
            Object tempUse = useIt.next();
            if (tempUse != originalConstructorUnit) {
                onlyInConstructorUnit = false;
            }
        }
        if (onlyInConstructorUnit) {
            // mark it to be removed
            toRemoveDefs.add(s);
        }
    }
    // remove any defs and corresponding locals if present in the
    // toRemoveDefs list
    it = toRemoveDefs.iterator();
    while (it.hasNext()) {
        DefinitionStmt s = it.next();
        int index = uniqueLocalDefs.indexOf(s);
        uniqueLocals.remove(index);
        uniqueLocalDefs.remove(index);
    }
    // the remaining uniquelocals are the ones which are needed for body Y
    return uniqueLocals;
}
Also used : ASTParentNodeFinder(soot.dava.toolkits.base.AST.traversals.ASTParentNodeFinder) ASTUsesAndDefs(soot.dava.toolkits.base.AST.traversals.ASTUsesAndDefs) AllDefinitionsFinder(soot.dava.toolkits.base.AST.traversals.AllDefinitionsFinder) ArrayList(java.util.ArrayList) JimpleLocal(soot.jimple.internal.JimpleLocal) Local(soot.Local) ASTStatementSequenceNode(soot.dava.internal.AST.ASTStatementSequenceNode) Value(soot.Value) Iterator(java.util.Iterator) ASTMethodNode(soot.dava.internal.AST.ASTMethodNode) DefinitionStmt(soot.jimple.DefinitionStmt)

Example 4 with ASTMethodNode

use of soot.dava.internal.AST.ASTMethodNode in project soot by Sable.

the class DavaStaticBlockCleaner method inline.

/*
     * Method called with a sootMethod to decide whether this method should be inlined or not
     * returns null if it shouldnt be inlined
     *
     * A method can be inlined if it belongs to the same class and also if its static....(why???)
     */
public ASTMethodNode inline(SootMethod maybeInline) {
    if (sootClass != null) {
        // 1, method should belong to the same class as the clinit method
        if (sootClass.declaresMethod(maybeInline.getSubSignature())) {
            if (Modifier.isStatic(maybeInline.getModifiers())) {
                // 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) {
                    // System.out.println("No declarations in the method. we can inline this method");
                    return toReturn;
                }
            }
        }
    }
    // meaning dont inline
    return null;
}
Also used : Chain(soot.util.Chain) ASTNode(soot.dava.internal.AST.ASTNode) ASTMethodNode(soot.dava.internal.AST.ASTMethodNode) ASTStatementSequenceNode(soot.dava.internal.AST.ASTStatementSequenceNode) Body(soot.Body)

Example 5 with ASTMethodNode

use of soot.dava.internal.AST.ASTMethodNode in project soot by Sable.

the class RemoveEmptyBodyDefaultConstructor method checkAndRemoveDefault.

public static void checkAndRemoveDefault(SootClass s) {
    debug("\n\nRemoveEmptyBodyDefaultConstructor----" + s.getName());
    List methods = s.getMethods();
    Iterator it = methods.iterator();
    List<SootMethod> constructors = new ArrayList<SootMethod>();
    while (it.hasNext()) {
        SootMethod method = (SootMethod) it.next();
        debug("method name is" + method.getName());
        if (method.getName().indexOf("<init>") > -1) {
            // constructor add to constructor list
            constructors.add(method);
        }
    }
    if (constructors.size() != 1) {
        // cant do anything since there are more than one constructors
        debug("class has more than one constructors cant do anything");
        return;
    }
    // only one constructor check its default (no arguments)
    SootMethod constructor = constructors.get(0);
    if (constructor.getParameterCount() != 0) {
        // can only deal with default constructors
        debug("constructor is not the default constructor");
        return;
    }
    debug("Check that the body is empty....and call to super contains no arguments and delete");
    if (!constructor.hasActiveBody()) {
        debug("No active body found for the default constructor");
        return;
    }
    Body body = constructor.getActiveBody();
    Chain units = ((DavaBody) body).getUnits();
    if (units.size() != 1) {
        debug(" DavaBody AST does not have single root");
        return;
    }
    ASTNode AST = (ASTNode) units.getFirst();
    if (!(AST instanceof ASTMethodNode))
        throw new RuntimeException("Starting node of DavaBody AST is not an ASTMethodNode");
    ASTMethodNode methodNode = (ASTMethodNode) AST;
    debug("got methodnode check body is empty and super has nothing in it");
    List<Object> subBodies = methodNode.get_SubBodies();
    if (subBodies.size() != 1) {
        debug("Method node does not have one subBody!!!");
        return;
    }
    List methodBody = (List) subBodies.get(0);
    if (methodBody.size() != 0) {
        debug("Method body size is greater than 1 so cant do nothing");
        return;
    }
    debug("Method body is empty...check super call is empty");
    if (((DavaBody) body).get_ConstructorExpr().getArgCount() != 0) {
        debug("call to super not empty");
        return;
    }
    debug("REMOVE METHOD");
    s.removeMethod(constructor);
}
Also used : Chain(soot.util.Chain) ArrayList(java.util.ArrayList) DavaBody(soot.dava.DavaBody) Iterator(java.util.Iterator) ASTNode(soot.dava.internal.AST.ASTNode) SootMethod(soot.SootMethod) List(java.util.List) ArrayList(java.util.ArrayList) ASTMethodNode(soot.dava.internal.AST.ASTMethodNode) Body(soot.Body) DavaBody(soot.dava.DavaBody)

Aggregations

ASTMethodNode (soot.dava.internal.AST.ASTMethodNode)9 ASTNode (soot.dava.internal.AST.ASTNode)7 ArrayList (java.util.ArrayList)6 List (java.util.List)5 ASTStatementSequenceNode (soot.dava.internal.AST.ASTStatementSequenceNode)5 Iterator (java.util.Iterator)4 SootMethod (soot.SootMethod)4 Body (soot.Body)3 SootClass (soot.SootClass)3 AugmentedStmt (soot.dava.internal.asg.AugmentedStmt)3 DefinitionStmt (soot.jimple.DefinitionStmt)3 Chain (soot.util.Chain)3 Local (soot.Local)2 RefType (soot.RefType)2 SootMethodRef (soot.SootMethodRef)2 Value (soot.Value)2 CorruptASTException (soot.dava.CorruptASTException)2 DavaBody (soot.dava.DavaBody)2 DecompilationException (soot.dava.DecompilationException)2 DVariableDeclarationStmt (soot.dava.internal.javaRep.DVariableDeclarationStmt)2