Search in sources :

Example 51 with SootMethod

use of soot.SootMethod in project soot by Sable.

the class PAG method addCallTarget.

public final void addCallTarget(Edge e) {
    if (!e.passesParameters())
        return;
    MethodPAG srcmpag = MethodPAG.v(this, e.src());
    MethodPAG tgtmpag = MethodPAG.v(this, e.tgt());
    Pair<Node, Node> pval;
    if (e.isExplicit() || e.kind() == Kind.THREAD || e.kind() == Kind.ASYNCTASK) {
        addCallTarget(srcmpag, tgtmpag, (Stmt) e.srcUnit(), e.srcCtxt(), e.tgtCtxt(), e);
    } else if (e.kind() == Kind.EXECUTOR) {
        InvokeExpr ie = e.srcStmt().getInvokeExpr();
        boolean virtualCall = callAssigns.containsKey(ie);
        Node parm = srcmpag.nodeFactory().getNode(ie.getArg(0));
        parm = srcmpag.parameterize(parm, e.srcCtxt());
        parm = parm.getReplacement();
        Node thiz = tgtmpag.nodeFactory().caseThis();
        thiz = tgtmpag.parameterize(thiz, e.tgtCtxt());
        thiz = thiz.getReplacement();
        addEdge(parm, thiz);
        pval = addInterproceduralAssignment(parm, thiz, e);
        callAssigns.put(ie, pval);
        callToMethod.put(ie, srcmpag.getMethod());
        if (virtualCall && !virtualCallsToReceivers.containsKey(ie)) {
            virtualCallsToReceivers.put(ie, parm);
        }
    } else if (e.kind() == Kind.HANDLER) {
        InvokeExpr ie = e.srcStmt().getInvokeExpr();
        boolean virtualCall = callAssigns.containsKey(ie);
        assert virtualCall == true;
        Node base = srcmpag.nodeFactory().getNode(((VirtualInvokeExpr) ie).getBase());
        base = srcmpag.parameterize(base, e.srcCtxt());
        base = base.getReplacement();
        Node thiz = tgtmpag.nodeFactory().caseThis();
        thiz = tgtmpag.parameterize(thiz, e.tgtCtxt());
        thiz = thiz.getReplacement();
        addEdge(base, thiz);
        pval = addInterproceduralAssignment(base, thiz, e);
        callAssigns.put(ie, pval);
        callToMethod.put(ie, srcmpag.getMethod());
        virtualCallsToReceivers.put(ie, base);
    } else if (e.kind() == Kind.PRIVILEGED) {
        // Flow from first parameter of doPrivileged() invocation
        // to this of target, and from return of target to the
        // return of doPrivileged()
        InvokeExpr ie = e.srcStmt().getInvokeExpr();
        Node parm = srcmpag.nodeFactory().getNode(ie.getArg(0));
        parm = srcmpag.parameterize(parm, e.srcCtxt());
        parm = parm.getReplacement();
        Node thiz = tgtmpag.nodeFactory().caseThis();
        thiz = tgtmpag.parameterize(thiz, e.tgtCtxt());
        thiz = thiz.getReplacement();
        addEdge(parm, thiz);
        pval = addInterproceduralAssignment(parm, thiz, e);
        callAssigns.put(ie, pval);
        callToMethod.put(ie, srcmpag.getMethod());
        if (e.srcUnit() instanceof AssignStmt) {
            AssignStmt as = (AssignStmt) e.srcUnit();
            Node ret = tgtmpag.nodeFactory().caseRet();
            ret = tgtmpag.parameterize(ret, e.tgtCtxt());
            ret = ret.getReplacement();
            Node lhs = srcmpag.nodeFactory().getNode(as.getLeftOp());
            lhs = srcmpag.parameterize(lhs, e.srcCtxt());
            lhs = lhs.getReplacement();
            addEdge(ret, lhs);
            pval = addInterproceduralAssignment(ret, lhs, e);
            callAssigns.put(ie, pval);
            callToMethod.put(ie, srcmpag.getMethod());
        }
    } else if (e.kind() == Kind.FINALIZE) {
        Node srcThis = srcmpag.nodeFactory().caseThis();
        srcThis = srcmpag.parameterize(srcThis, e.srcCtxt());
        srcThis = srcThis.getReplacement();
        Node tgtThis = tgtmpag.nodeFactory().caseThis();
        tgtThis = tgtmpag.parameterize(tgtThis, e.tgtCtxt());
        tgtThis = tgtThis.getReplacement();
        addEdge(srcThis, tgtThis);
        pval = addInterproceduralAssignment(srcThis, tgtThis, e);
    } else if (e.kind() == Kind.NEWINSTANCE) {
        Stmt s = (Stmt) e.srcUnit();
        InstanceInvokeExpr iie = (InstanceInvokeExpr) s.getInvokeExpr();
        Node cls = srcmpag.nodeFactory().getNode(iie.getBase());
        cls = srcmpag.parameterize(cls, e.srcCtxt());
        cls = cls.getReplacement();
        Node newObject = nodeFactory.caseNewInstance((VarNode) cls);
        Node initThis = tgtmpag.nodeFactory().caseThis();
        initThis = tgtmpag.parameterize(initThis, e.tgtCtxt());
        initThis = initThis.getReplacement();
        addEdge(newObject, initThis);
        if (s instanceof AssignStmt) {
            AssignStmt as = (AssignStmt) s;
            Node asLHS = srcmpag.nodeFactory().getNode(as.getLeftOp());
            asLHS = srcmpag.parameterize(asLHS, e.srcCtxt());
            asLHS = asLHS.getReplacement();
            addEdge(newObject, asLHS);
        }
        pval = addInterproceduralAssignment(newObject, initThis, e);
        callAssigns.put(s.getInvokeExpr(), pval);
        callToMethod.put(s.getInvokeExpr(), srcmpag.getMethod());
    } else if (e.kind() == Kind.REFL_INVOKE) {
        // Flow (1) from first parameter of invoke(..) invocation
        // to this of target, (2) from the contents of the second (array)
        // parameter
        // to all parameters of the target, and (3) from return of target to
        // the
        // return of invoke(..)
        // (1)
        InvokeExpr ie = e.srcStmt().getInvokeExpr();
        Value arg0 = ie.getArg(0);
        // if "null" is passed in, omit the edge
        if (arg0 != NullConstant.v()) {
            Node parm0 = srcmpag.nodeFactory().getNode(arg0);
            parm0 = srcmpag.parameterize(parm0, e.srcCtxt());
            parm0 = parm0.getReplacement();
            Node thiz = tgtmpag.nodeFactory().caseThis();
            thiz = tgtmpag.parameterize(thiz, e.tgtCtxt());
            thiz = thiz.getReplacement();
            addEdge(parm0, thiz);
            pval = addInterproceduralAssignment(parm0, thiz, e);
            callAssigns.put(ie, pval);
            callToMethod.put(ie, srcmpag.getMethod());
        }
        // (2)
        Value arg1 = ie.getArg(1);
        SootMethod tgt = e.getTgt().method();
        // edge
        if (arg1 != NullConstant.v() && tgt.getParameterCount() > 0) {
            Node parm1 = srcmpag.nodeFactory().getNode(arg1);
            parm1 = srcmpag.parameterize(parm1, e.srcCtxt());
            parm1 = parm1.getReplacement();
            FieldRefNode parm1contents = makeFieldRefNode((VarNode) parm1, ArrayElement.v());
            for (int i = 0; i < tgt.getParameterCount(); i++) {
                // if no reference type, create no edge
                if (!(tgt.getParameterType(i) instanceof RefLikeType))
                    continue;
                Node tgtParmI = tgtmpag.nodeFactory().caseParm(i);
                tgtParmI = tgtmpag.parameterize(tgtParmI, e.tgtCtxt());
                tgtParmI = tgtParmI.getReplacement();
                addEdge(parm1contents, tgtParmI);
                pval = addInterproceduralAssignment(parm1contents, tgtParmI, e);
                callAssigns.put(ie, pval);
            }
        }
        // the return type of the callee is actually a reference type
        if (e.srcUnit() instanceof AssignStmt && (tgt.getReturnType() instanceof RefLikeType)) {
            AssignStmt as = (AssignStmt) e.srcUnit();
            Node ret = tgtmpag.nodeFactory().caseRet();
            ret = tgtmpag.parameterize(ret, e.tgtCtxt());
            ret = ret.getReplacement();
            Node lhs = srcmpag.nodeFactory().getNode(as.getLeftOp());
            lhs = srcmpag.parameterize(lhs, e.srcCtxt());
            lhs = lhs.getReplacement();
            addEdge(ret, lhs);
            pval = addInterproceduralAssignment(ret, lhs, e);
            callAssigns.put(ie, pval);
        }
    } else if (e.kind() == Kind.REFL_CLASS_NEWINSTANCE || e.kind() == Kind.REFL_CONSTR_NEWINSTANCE) {
        // (1) create a fresh node for the new object
        // (2) create edge from this object to "this" of the constructor
        // (3) if this is a call to Constructor.newInstance and not
        // Class.newInstance,
        // create edges passing the contents of the arguments array of the
        // call
        // to all possible parameters of the target
        // (4) if we are inside an assign statement,
        // assign the fresh object from (1) to the LHS of the assign
        // statement
        Stmt s = (Stmt) e.srcUnit();
        InstanceInvokeExpr iie = (InstanceInvokeExpr) s.getInvokeExpr();
        // (1)
        Node cls = srcmpag.nodeFactory().getNode(iie.getBase());
        cls = srcmpag.parameterize(cls, e.srcCtxt());
        cls = cls.getReplacement();
        if (cls instanceof ContextVarNode)
            cls = findLocalVarNode(((VarNode) cls).getVariable());
        VarNode newObject = makeGlobalVarNode(cls, RefType.v("java.lang.Object"));
        SootClass tgtClass = e.getTgt().method().getDeclaringClass();
        RefType tgtType = tgtClass.getType();
        AllocNode site = makeAllocNode(new Pair<Node, SootClass>(cls, tgtClass), tgtType, null);
        addEdge(site, newObject);
        // (2)
        Node initThis = tgtmpag.nodeFactory().caseThis();
        initThis = tgtmpag.parameterize(initThis, e.tgtCtxt());
        initThis = initThis.getReplacement();
        addEdge(newObject, initThis);
        addInterproceduralAssignment(newObject, initThis, e);
        // (3)
        if (e.kind() == Kind.REFL_CONSTR_NEWINSTANCE) {
            Value arg = iie.getArg(0);
            SootMethod tgt = e.getTgt().method();
            // edge
            if (arg != NullConstant.v() && tgt.getParameterCount() > 0) {
                Node parm0 = srcmpag.nodeFactory().getNode(arg);
                parm0 = srcmpag.parameterize(parm0, e.srcCtxt());
                parm0 = parm0.getReplacement();
                FieldRefNode parm1contents = makeFieldRefNode((VarNode) parm0, ArrayElement.v());
                for (int i = 0; i < tgt.getParameterCount(); i++) {
                    // if no reference type, create no edge
                    if (!(tgt.getParameterType(i) instanceof RefLikeType))
                        continue;
                    Node tgtParmI = tgtmpag.nodeFactory().caseParm(i);
                    tgtParmI = tgtmpag.parameterize(tgtParmI, e.tgtCtxt());
                    tgtParmI = tgtParmI.getReplacement();
                    addEdge(parm1contents, tgtParmI);
                    pval = addInterproceduralAssignment(parm1contents, tgtParmI, e);
                    callAssigns.put(iie, pval);
                }
            }
        }
        // (4)
        if (s instanceof AssignStmt) {
            AssignStmt as = (AssignStmt) s;
            Node asLHS = srcmpag.nodeFactory().getNode(as.getLeftOp());
            asLHS = srcmpag.parameterize(asLHS, e.srcCtxt());
            asLHS = asLHS.getReplacement();
            addEdge(newObject, asLHS);
        }
        pval = addInterproceduralAssignment(newObject, initThis, e);
        callAssigns.put(s.getInvokeExpr(), pval);
        callToMethod.put(s.getInvokeExpr(), srcmpag.getMethod());
    } else {
        throw new RuntimeException("Unhandled edge " + e);
    }
}
Also used : AssignStmt(soot.jimple.AssignStmt) InstanceInvokeExpr(soot.jimple.InstanceInvokeExpr) SootClass(soot.SootClass) AssignStmt(soot.jimple.AssignStmt) Stmt(soot.jimple.Stmt) RefLikeType(soot.RefLikeType) RefType(soot.RefType) InstanceInvokeExpr(soot.jimple.InstanceInvokeExpr) VirtualInvokeExpr(soot.jimple.VirtualInvokeExpr) InvokeExpr(soot.jimple.InvokeExpr) Value(soot.Value) SootMethod(soot.SootMethod) Pair(soot.toolkits.scalar.Pair)

Example 52 with SootMethod

use of soot.SootMethod 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 53 with SootMethod

use of soot.SootMethod in project soot by Sable.

the class ConstantFieldValueFinder method computeFieldToValuesAssignedList.

/*
	 * Go through all the methods in the application and make a mapping of className+methodName ---> values assigned
	 * There can obviously be more than one value assigned to each field
	 */
private void computeFieldToValuesAssignedList() {
    // go through all the classes
    Iterator classIt = appClasses.iterator();
    while (classIt.hasNext()) {
        SootClass s = (SootClass) classIt.next();
        debug("\ncomputeMethodSummaries", "Processing class " + s.getName());
        // go though all the methods
        Iterator methodIt = s.methodIterator();
        while (methodIt.hasNext()) {
            SootMethod m = (SootMethod) methodIt.next();
            DavaBody body = null;
            if (m.hasActiveBody()) {
                /*
					 * Added to try to fix the no active body found exception
					 */
                body = (DavaBody) m.getActiveBody();
            } else {
                continue;
            }
            ASTNode AST = (ASTNode) body.getUnits().getFirst();
            // find all definitions in the program
            AllDefinitionsFinder defFinder = new AllDefinitionsFinder();
            AST.apply(defFinder);
            Iterator<DefinitionStmt> allDefIt = defFinder.getAllDefs().iterator();
            // go through each definition
            while (allDefIt.hasNext()) {
                DefinitionStmt stmt = allDefIt.next();
                // debug("DefinitionStmt")
                Value left = stmt.getLeftOp();
                /*
					 * Only care if we have fieldRef on the left
					 */
                if (!(left instanceof FieldRef)) {
                    continue;
                }
                // we know definition is to a field
                debug("computeMethodSummaries method: " + m.getName(), "Field ref is: " + left);
                // Information we want to store is class of field and name of field and the right op
                FieldRef ref = (FieldRef) left;
                SootField field = ref.getField();
                /*
					 * Only care about fields with primtype
					 */
                if (!(field.getType() instanceof PrimType))
                    continue;
                String fieldName = field.getName();
                String declaringClass = field.getDeclaringClass().getName();
                debug("\tField Name: " + fieldName);
                debug("\tField DeclaringClass: " + declaringClass);
                // get the valueList for this class+field combo
                String combined = declaringClass + combiner + fieldName;
                Object temp = fieldToValues.get(combined);
                ArrayList valueList;
                if (temp == null) {
                    // no value of this field was yet assigned
                    valueList = new ArrayList();
                    fieldToValues.put(combined, valueList);
                } else {
                    valueList = (ArrayList) temp;
                }
                valueList.add(stmt.getRightOp());
            }
        // going through all the definitions
        }
    // going through methods of class s
    }
// going through  classes
}
Also used : AllDefinitionsFinder(soot.dava.toolkits.base.AST.traversals.AllDefinitionsFinder) FieldRef(soot.jimple.FieldRef) ArrayList(java.util.ArrayList) SootClass(soot.SootClass) DavaBody(soot.dava.DavaBody) Iterator(java.util.Iterator) ASTNode(soot.dava.internal.AST.ASTNode) Value(soot.Value) SootMethod(soot.SootMethod) PrimType(soot.PrimType) SootField(soot.SootField) DefinitionStmt(soot.jimple.DefinitionStmt)

Example 54 with SootMethod

use of soot.SootMethod 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 55 with SootMethod

use of soot.SootMethod in project soot by Sable.

the class LockAllocationBodyTransformer method getLockFor.

public static Value getLockFor(EquivalentValue lockEqVal) {
    Value lock = lockEqVal.getValue();
    if (lock instanceof InstanceFieldRef)
        return lock;
    if (// it would be better to lock the array
    lock instanceof ArrayRef)
        // ref for each value of the index!
        return ((ArrayRef) lock).getBase();
    if (lock instanceof Local)
        return lock;
    if (lock instanceof StaticFieldRef || lock instanceof NewStaticLock) {
        if (lockEqValToLock.containsKey(lockEqVal))
            return lockEqValToLock.get(lockEqVal);
        SootClass lockClass = null;
        if (lock instanceof StaticFieldRef) {
            StaticFieldRef sfrLock = (StaticFieldRef) lock;
            lockClass = sfrLock.getField().getDeclaringClass();
        } else if (lock instanceof NewStaticLock) {
            DeadlockAvoidanceEdge dae = (DeadlockAvoidanceEdge) lock;
            lockClass = dae.getLockClass();
        }
        SootMethod clinitMethod = null;
        JimpleBody clinitBody = null;
        Stmt firstStmt = null;
        boolean addingNewClinit = !lockClass.declaresMethod("void <clinit>()");
        if (addingNewClinit) {
            clinitMethod = Scene.v().makeSootMethod("<clinit>", new ArrayList(), VoidType.v(), Modifier.PUBLIC | Modifier.STATIC);
            clinitBody = Jimple.v().newBody(clinitMethod);
            clinitMethod.setActiveBody(clinitBody);
            lockClass.addMethod(clinitMethod);
        } else {
            clinitMethod = lockClass.getMethod("void <clinit>()");
            clinitBody = (JimpleBody) clinitMethod.getActiveBody();
            firstStmt = clinitBody.getFirstNonIdentityStmt();
        }
        PatchingChain<Unit> clinitUnits = clinitBody.getUnits();
        Local lockLocal = Jimple.v().newLocal("objectLockLocal" + lockNumber, RefType.v("java.lang.Object"));
        // lockNumber is increased below
        // TODO: add name conflict
        clinitBody.getLocals().add(lockLocal);
        // avoidance code
        // assign new object to lock obj
        Stmt newStmt = Jimple.v().newAssignStmt(lockLocal, Jimple.v().newNewExpr(RefType.v("java.lang.Object")));
        if (addingNewClinit)
            clinitUnits.add(newStmt);
        else
            clinitUnits.insertBeforeNoRedirect(newStmt, firstStmt);
        // initialize new object
        SootClass objectClass = Scene.v().loadClassAndSupport("java.lang.Object");
        RefType type = RefType.v(objectClass);
        SootMethod initMethod = objectClass.getMethod("void <init>()");
        Stmt initStmt = Jimple.v().newInvokeStmt(Jimple.v().newSpecialInvokeExpr(lockLocal, initMethod.makeRef(), Collections.EMPTY_LIST));
        if (addingNewClinit)
            clinitUnits.add(initStmt);
        else
            clinitUnits.insertBeforeNoRedirect(initStmt, firstStmt);
        // copy new object to global static lock object (for use by other
        // fns)
        SootField actualLockObject = Scene.v().makeSootField("objectLockGlobal" + lockNumber, RefType.v("java.lang.Object"), Modifier.STATIC | Modifier.PUBLIC);
        lockNumber++;
        lockClass.addField(actualLockObject);
        StaticFieldRef actualLockSfr = Jimple.v().newStaticFieldRef(actualLockObject.makeRef());
        Stmt assignStmt = Jimple.v().newAssignStmt(actualLockSfr, lockLocal);
        if (addingNewClinit)
            clinitUnits.add(assignStmt);
        else
            clinitUnits.insertBeforeNoRedirect(assignStmt, firstStmt);
        if (addingNewClinit)
            clinitUnits.add(Jimple.v().newReturnVoidStmt());
        lockEqValToLock.put(lockEqVal, actualLockSfr);
        return actualLockSfr;
    }
    throw new RuntimeException("Unknown type of lock (" + lock + "): expected FieldRef, ArrayRef, or Local");
}
Also used : ArrayList(java.util.ArrayList) FakeJimpleLocal(soot.jimple.toolkits.infoflow.FakeJimpleLocal) Local(soot.Local) SootClass(soot.SootClass) Unit(soot.Unit) StaticFieldRef(soot.jimple.StaticFieldRef) Stmt(soot.jimple.Stmt) ArrayRef(soot.jimple.ArrayRef) RefType(soot.RefType) EquivalentValue(soot.EquivalentValue) Value(soot.Value) InstanceFieldRef(soot.jimple.InstanceFieldRef) SootMethod(soot.SootMethod) SootField(soot.SootField) JimpleBody(soot.jimple.JimpleBody)

Aggregations

SootMethod (soot.SootMethod)237 SootClass (soot.SootClass)95 RefType (soot.RefType)56 ArrayList (java.util.ArrayList)49 Type (soot.Type)47 Unit (soot.Unit)47 Value (soot.Value)36 Stmt (soot.jimple.Stmt)35 Test (org.junit.Test)34 Local (soot.Local)34 Body (soot.Body)32 VoidType (soot.VoidType)31 PrimType (soot.PrimType)28 SootField (soot.SootField)28 BooleanType (soot.BooleanType)26 Iterator (java.util.Iterator)23 DoubleType (soot.DoubleType)23 FloatType (soot.FloatType)23 LongType (soot.LongType)23 InvokeExpr (soot.jimple.InvokeExpr)23