Search in sources :

Example 1 with ASTParentNodeFinder

use of soot.dava.toolkits.base.AST.traversals.ASTParentNodeFinder 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 ASTParentNodeFinder

use of soot.dava.toolkits.base.AST.traversals.ASTParentNodeFinder in project soot by Sable.

the class IfElseSplitter method outASTIfElseNode.

public void outASTIfElseNode(ASTIfElseNode node) {
    // if some pattern has already matched cant do another one in this go
    if (transform)
        return;
    List<Object> subBodies = node.get_SubBodies();
    if (subBodies.size() != 2)
        throw new DecompilationException("IfelseNode without two subBodies. report to developer");
    List<Object> ifBody = (List<Object>) subBodies.get(0);
    List<Object> elseBody = (List<Object>) subBodies.get(1);
    boolean patternMatched = tryBodyPattern(ifBody, node.get_Label(), elseBody);
    List<Object> newIfBody = null;
    List<Object> outerScopeBody = null;
    boolean negateIfCondition = false;
    if (patternMatched) {
        if (DEBUG)
            System.out.println("First pattern matched");
        newIfBody = ifBody;
        outerScopeBody = elseBody;
        negateIfCondition = false;
    } else {
        patternMatched = tryBodyPattern(elseBody, node.get_Label(), ifBody);
        if (patternMatched) {
            if (DEBUG)
                System.out.println("Second pattern matched");
            newIfBody = elseBody;
            outerScopeBody = ifBody;
            negateIfCondition = true;
        }
    }
    // if at this point newIfBody and outerScopeBody are non null we got ourselves a transformation :)
    if (newIfBody != null && outerScopeBody != null) {
        ASTCondition cond = node.get_Condition();
        if (negateIfCondition)
            cond.flip();
        ASTIfNode newNode = new ASTIfNode(node.get_Label(), cond, newIfBody);
        if (DEBUG) {
            System.out.println("New IF Node is: " + newNode.toString());
            System.out.println("Outer scope body list is:\n");
            for (int i = 0; i < outerScopeBody.size(); i++) System.out.println("\n\n " + outerScopeBody.get(i).toString());
        }
        ASTParentNodeFinder finder = new ASTParentNodeFinder();
        methodNode.apply(finder);
        Object returned = finder.getParentOf(node);
        if (returned == null) {
            // coundnt find parent so cant do anything
            return;
        }
        /*
			 * Setting globals since everything is ready for transformation
			 * BECAUSE we cant modify the parent here we are going to do some 
			 * bad coding style
			 * store the information needed for this into globals
			 * set a flag
			 * and the outASTMethod checks for this
			 */
        parent = (ASTNode) returned;
        toReplace = node;
        toInsert = newNode;
        bodyAfterInsert = outerScopeBody;
        transform = true;
    }
}
Also used : ASTIfNode(soot.dava.internal.AST.ASTIfNode) ASTParentNodeFinder(soot.dava.toolkits.base.AST.traversals.ASTParentNodeFinder) DecompilationException(soot.dava.DecompilationException) List(java.util.List) ASTCondition(soot.dava.internal.AST.ASTCondition)

Example 3 with ASTParentNodeFinder

use of soot.dava.toolkits.base.AST.traversals.ASTParentNodeFinder 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 ASTParentNodeFinder

use of soot.dava.toolkits.base.AST.traversals.ASTParentNodeFinder in project soot by Sable.

the class SuperFirstStmtHandler method inASTStatementSequenceNode.

/*
	 * looking for an init stmt
	 */
public void inASTStatementSequenceNode(ASTStatementSequenceNode node) {
    for (AugmentedStmt as : node.getStatements()) {
        Unit u = as.get_Stmt();
        if (u == originalConstructorUnit) {
            // System.out.println("Found the constructorUnit"+u);
            // ONE: make sure the parent of the super() call is an
            // ASTMethodNode
            ASTParentNodeFinder parentFinder = new ASTParentNodeFinder();
            originalASTMethod.apply(parentFinder);
            Object tempParent = parentFinder.getParentOf(node);
            if (tempParent != originalASTMethod) {
                // System.out.println("ASTMethod node is not the parent of
                // constructorUnit");
                // notice since we cant remove one call of super there is no
                // point
                // in trying to remove any other calls to super
                removeInit();
                return;
            }
            // only gets here if the call to super is not nested within some
            // other construct
            /**
             *******************************************************
             */
            /**
             **************** CREATING PREINIT METHOD **************
             */
            /**
             *******************************************************
             */
            // CREATE UNIQUE METHOD
            // new method is initalized in
            createSootPreInitMethod();
            // newSootPreInitMethod
            // Create ASTMethodNode for this SootMethod
            // the field
            createNewASTPreInitMethod(node);
            if (newASTPreInitMethod == null) {
                // could not create ASTMethodNode for some reason or the
                // other
                // just silently return
                // System.out.println(">>>>>>>>>>>>>>>>Couldnt not create
                // ASTMethodNode for the new PreInitMethod");
                removeInit();
                return;
            }
            if (!finalizePreInitMethod()) {
                // shouldnt be creating PreInit
                // System.out.println(">>>>>>>>>>>>>>SHOULDNT BE CREATING
                // PREINIT");
                removeInit();
                return;
            }
            /**
             *******************************************************
             */
            /**
             ************ CREATING NEW CONSTRUCTOR *****************
             */
            /**
             *******************************************************
             */
            // create SootMethod for the constructor
            createNewConstructor();
            createNewASTConstructor(node);
            if (!createCallToSuper()) {
                // could not create call to super
                // still safe to simply exit
                // System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>Could not
                // create call to super...SuperFirstStmtHandler");
                removeInit();
                return;
            }
            finalizeConstructor();
            /**
             *******************************************************
             */
            if (changeOriginalAST()) {
                // System.out.println("Done Done Done");
                debug("SuperFirstStmtHandler....inASTStatementSeuqneNode", "Added PreInit");
                G.v().SootMethodAddedByDava = true;
                G.v().SootMethodsAdded.add(newSootPreInitMethod);
                G.v().SootMethodsAdded.add(newConstructor);
                /**
                 *******************************************************
                 */
                /**
                 **************** CREATING INNER CLASS *****************
                 */
                /**
                 *******************************************************
                 */
                // notice that inner class is created by DavaPrinter in the
                // printTo method
                // all we do is set a Global to true and later on when the
                // SootClass is being
                // output the inner class will be output also
                G.v().SootClassNeedsDavaSuperHandlerClass.add(originalSootClass);
            // System.out.println("\n\nSet SootMethodAddedByDava to
            // true\n\n");
            }
        }
    }
}
Also used : ASTParentNodeFinder(soot.dava.toolkits.base.AST.traversals.ASTParentNodeFinder) AugmentedStmt(soot.dava.internal.asg.AugmentedStmt) Unit(soot.Unit)

Example 5 with ASTParentNodeFinder

use of soot.dava.toolkits.base.AST.traversals.ASTParentNodeFinder in project soot by Sable.

the class UselessAbruptStmtRemover method caseASTStatementSequenceNode.

public void caseASTStatementSequenceNode(ASTStatementSequenceNode node) {
    Iterator<AugmentedStmt> it = node.getStatements().iterator();
    AugmentedStmt remove = null;
    ASTLabeledNode target = null;
    while (it.hasNext()) {
        AugmentedStmt as = it.next();
        Stmt s = as.get_Stmt();
        // we only care about break and continue stmts
        if (!(s instanceof DAbruptStmt)) {
            continue;
        }
        DAbruptStmt abrupt = (DAbruptStmt) s;
        String label = abrupt.getLabel().toString();
        if (label == null) {
            // analysis with implicit abrupt flow but not needed currently
            continue;
        }
        if (it.hasNext()) {
            // afterwards...that is for sure dead code
            throw new DecompilationException("Dead code detected. Report to developer");
        }
        // get the target node
        Object temp = mapper.getTarget(label);
        if (temp == null) {
            continue;
        // throw new DecompilationException("Could not find target for abrupt stmt"+abrupt.toString());
        }
        target = (ASTLabeledNode) temp;
        // will need to find parents of ancestors see if we need to initialize the finder
        if (finder == null) {
            finder = new ASTParentNodeFinder();
            methodNode.apply(finder);
        }
        if (DEBUG)
            System.out.println("Starting useless check for abrupt stmt: " + abrupt);
        // start condition is that ancestor is the stmt seq node
        ASTNode ancestor = node;
        while (ancestor != target) {
            Object tempParent = finder.getParentOf(ancestor);
            if (tempParent == null)
                throw new DecompilationException("Parent found was null!!. Report to Developer");
            ASTNode ancestorsParent = (ASTNode) tempParent;
            if (DEBUG)
                System.out.println("\tCurrent ancestorsParent has type" + ancestorsParent.getClass());
            // ancestor should be last child of ancestorsParent
            if (!checkChildLastInParent(ancestor, ancestorsParent)) {
                if (DEBUG)
                    System.out.println("\t\tCurrent ancestorParent has more children after this ancestor");
                // return from the method since this is the last stmt and we cant do anything
                return;
            }
            // ancestorsParent should not be a loop of any kind OR A SWITCH
            if (ancestorsParent instanceof ASTWhileNode || ancestorsParent instanceof ASTDoWhileNode || ancestorsParent instanceof ASTUnconditionalLoopNode || ancestorsParent instanceof ASTForLoopNode || ancestorsParent instanceof ASTSwitchNode) {
                if (DEBUG)
                    System.out.println("\t\tAncestorsParent is a loop shouldnt remove abrupt stmt");
                return;
            }
            ancestor = ancestorsParent;
        }
        if (DEBUG)
            System.out.println("\tGot to target without returning means we can remove stmt");
        remove = as;
    }
    if (remove != null) {
        List<AugmentedStmt> stmts = node.getStatements();
        stmts.remove(remove);
        if (DEBUG)
            System.out.println("\tRemoved abrupt stmt");
        if (target != null) {
            if (DEBUG)
                System.out.println("Invoking findAndKill on the target");
            UselessLabelFinder.v().findAndKill(target);
        }
        // TODO what if we just emptied a stmt seq block??
        // not doing this for the moment
        // set modified flag make finder null
        G.v().ASTTransformations_modified = true;
        finder = null;
    }
}
Also used : ASTParentNodeFinder(soot.dava.toolkits.base.AST.traversals.ASTParentNodeFinder) DecompilationException(soot.dava.DecompilationException) ASTLabeledNode(soot.dava.internal.AST.ASTLabeledNode) DAbruptStmt(soot.dava.internal.javaRep.DAbruptStmt) AugmentedStmt(soot.dava.internal.asg.AugmentedStmt) DAbruptStmt(soot.dava.internal.javaRep.DAbruptStmt) Stmt(soot.jimple.Stmt) AugmentedStmt(soot.dava.internal.asg.AugmentedStmt) ASTDoWhileNode(soot.dava.internal.AST.ASTDoWhileNode) ASTWhileNode(soot.dava.internal.AST.ASTWhileNode) ASTNode(soot.dava.internal.AST.ASTNode) ASTUnconditionalLoopNode(soot.dava.internal.AST.ASTUnconditionalLoopNode) ASTForLoopNode(soot.dava.internal.AST.ASTForLoopNode) ASTSwitchNode(soot.dava.internal.AST.ASTSwitchNode)

Aggregations

ASTParentNodeFinder (soot.dava.toolkits.base.AST.traversals.ASTParentNodeFinder)5 AugmentedStmt (soot.dava.internal.asg.AugmentedStmt)3 ArrayList (java.util.ArrayList)2 List (java.util.List)2 DecompilationException (soot.dava.DecompilationException)2 ASTMethodNode (soot.dava.internal.AST.ASTMethodNode)2 ASTStatementSequenceNode (soot.dava.internal.AST.ASTStatementSequenceNode)2 Iterator (java.util.Iterator)1 Local (soot.Local)1 RefType (soot.RefType)1 SootClass (soot.SootClass)1 SootMethod (soot.SootMethod)1 SootMethodRef (soot.SootMethodRef)1 Unit (soot.Unit)1 Value (soot.Value)1 ASTCondition (soot.dava.internal.AST.ASTCondition)1 ASTDoWhileNode (soot.dava.internal.AST.ASTDoWhileNode)1 ASTForLoopNode (soot.dava.internal.AST.ASTForLoopNode)1 ASTIfNode (soot.dava.internal.AST.ASTIfNode)1 ASTLabeledNode (soot.dava.internal.AST.ASTLabeledNode)1