Search in sources :

Example 6 with Chain

use of soot.util.Chain 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)

Example 7 with Chain

use of soot.util.Chain in project soot by Sable.

the class SynchronizerManager method synchronizeStmtOn.

/**
 * Wraps stmt around a monitor associated with local lock. When inlining or
 * static method binding, this is the former base of the invoke expression.
 */
public void synchronizeStmtOn(Stmt stmt, JimpleBody b, Local lock) {
    Chain units = b.getUnits();
    // TrapManager.splitTrapsAgainst(b, stmt, (Stmt)units.getSuccOf(stmt));
    units.insertBefore(Jimple.v().newEnterMonitorStmt(lock), stmt);
    Stmt exitMon = Jimple.v().newExitMonitorStmt(lock);
    units.insertAfter(exitMon, stmt);
    // Ok. That was the easy part.
    // We also need to modify exception blocks to exit the monitor
    // (they have conveniently been pre-split)
    // Actually, we don't need to do this.
    // {
    // List traps = TrapManager.getTrapsAt(stmt, b);
    // Iterator trapsIt = traps.iterator();
    // while (trapsIt.hasNext())
    // {
    // Trap t = (Trap)trapsIt.next();
    // Stmt s = (Stmt)units.getLast();
    // Stmt newCaughtRef = (Stmt)t.getHandlerUnit().clone();
    // List l = new ArrayList();
    // l.add(newCaughtRef);
    // l.add(exitMon.clone());
    // l.add(Jimple.v().newGotoStmt((Stmt)units.getSuccOf((Stmt)t.getHandlerUnit())));
    // units.insertAfter(l, s);
    // t.setHandlerUnit(newCaughtRef);
    // }
    // }
    // and also we must add a catch Throwable exception block in the
    // appropriate place.
    {
        Stmt newGoto = Jimple.v().newGotoStmt((Stmt) units.getSuccOf(exitMon));
        units.insertAfter(newGoto, exitMon);
        List<Unit> l = new ArrayList<Unit>();
        Local eRef = Jimple.v().newLocal("__exception", RefType.v("java.lang.Throwable"));
        b.getLocals().add(eRef);
        Stmt handlerStmt = Jimple.v().newIdentityStmt(eRef, Jimple.v().newCaughtExceptionRef());
        l.add(handlerStmt);
        l.add((Stmt) exitMon.clone());
        l.add(Jimple.v().newThrowStmt(eRef));
        units.insertAfter(l, newGoto);
        Trap newTrap = Jimple.v().newTrap(Scene.v().getSootClass("java.lang.Throwable"), stmt, (Stmt) units.getSuccOf(stmt), handlerStmt);
        b.getTraps().addFirst(newTrap);
    }
}
Also used : Chain(soot.util.Chain) Local(soot.Local) ArrayList(java.util.ArrayList) LinkedList(java.util.LinkedList) List(java.util.List) Trap(soot.Trap) Unit(soot.Unit) IfStmt(soot.jimple.IfStmt) IdentityStmt(soot.jimple.IdentityStmt) ReturnStmt(soot.jimple.ReturnStmt) Stmt(soot.jimple.Stmt) AssignStmt(soot.jimple.AssignStmt)

Example 8 with Chain

use of soot.util.Chain in project soot by Sable.

the class StaticMethodBinder method internalTransform.

protected void internalTransform(String phaseName, Map opts) {
    Filter instanceInvokesFilter = new Filter(new InstanceInvokeEdgesPred());
    SMBOptions options = new SMBOptions(opts);
    String modifierOptions = PhaseOptions.getString(opts, "allowed-modifier-changes");
    HashMap instanceToStaticMap = new HashMap();
    CallGraph cg = Scene.v().getCallGraph();
    Hierarchy hierarchy = Scene.v().getActiveHierarchy();
    Iterator classesIt = Scene.v().getApplicationClasses().iterator();
    while (classesIt.hasNext()) {
        SootClass c = (SootClass) classesIt.next();
        LinkedList methodsList = new LinkedList();
        for (Iterator it = c.methodIterator(); it.hasNext(); ) {
            methodsList.add(it.next());
        }
        while (!methodsList.isEmpty()) {
            SootMethod container = (SootMethod) methodsList.removeFirst();
            if (!container.isConcrete())
                continue;
            if (!instanceInvokesFilter.wrap(cg.edgesOutOf(container)).hasNext())
                continue;
            JimpleBody b = (JimpleBody) container.getActiveBody();
            List<Unit> unitList = new ArrayList<Unit>();
            unitList.addAll(b.getUnits());
            Iterator<Unit> unitIt = unitList.iterator();
            while (unitIt.hasNext()) {
                Stmt s = (Stmt) unitIt.next();
                if (!s.containsInvokeExpr())
                    continue;
                InvokeExpr ie = s.getInvokeExpr();
                if (ie instanceof StaticInvokeExpr || ie instanceof SpecialInvokeExpr)
                    continue;
                Iterator targets = new Targets(instanceInvokesFilter.wrap(cg.edgesOutOf(s)));
                if (!targets.hasNext())
                    continue;
                SootMethod target = (SootMethod) targets.next();
                if (targets.hasNext())
                    continue;
                if (!AccessManager.ensureAccess(container, target, modifierOptions))
                    continue;
                if (!target.getDeclaringClass().isApplicationClass() || !target.isConcrete())
                    continue;
                // Don't modify java.lang.Object
                if (target.getDeclaringClass() == Scene.v().getSootClass("java.lang.Object"))
                    continue;
                if (!instanceToStaticMap.containsKey(target)) {
                    List newParameterTypes = new ArrayList();
                    newParameterTypes.add(RefType.v(target.getDeclaringClass().getName()));
                    newParameterTypes.addAll(target.getParameterTypes());
                    // Check for signature conflicts.
                    String newName = target.getName() + "_static";
                    while (target.getDeclaringClass().declaresMethod(newName, newParameterTypes, target.getReturnType())) newName = newName + "_static";
                    SootMethod ct = Scene.v().makeSootMethod(newName, newParameterTypes, target.getReturnType(), target.getModifiers() | Modifier.STATIC, target.getExceptions());
                    target.getDeclaringClass().addMethod(ct);
                    methodsList.addLast(ct);
                    ct.setActiveBody((Body) target.getActiveBody().clone());
                    // Make the invoke graph take into account the
                    // newly-cloned body.
                    {
                        Iterator oldUnits = target.getActiveBody().getUnits().iterator();
                        Iterator newUnits = ct.getActiveBody().getUnits().iterator();
                        while (newUnits.hasNext()) {
                            Stmt oldStmt, newStmt;
                            oldStmt = (Stmt) oldUnits.next();
                            newStmt = (Stmt) newUnits.next();
                            Iterator edges = cg.edgesOutOf(oldStmt);
                            while (edges.hasNext()) {
                                Edge e = (Edge) edges.next();
                                cg.addEdge(new Edge(ct, newStmt, e.tgt(), e.kind()));
                                cg.removeEdge(e);
                            }
                        }
                    }
                    // Shift the parameter list to apply to the new this
                    // parameter.
                    // If the method uses this, then we replace
                    // the r0 := @this with r0 := @parameter0 & shift.
                    // Otherwise, just zap the r0 := @this.
                    {
                        Body newBody = ct.getActiveBody();
                        Chain units = newBody.getUnits();
                        Iterator unitsIt = newBody.getUnits().snapshotIterator();
                        while (unitsIt.hasNext()) {
                            Stmt st = (Stmt) unitsIt.next();
                            if (st instanceof IdentityStmt) {
                                IdentityStmt is = (IdentityStmt) st;
                                if (is.getRightOp() instanceof ThisRef) {
                                    units.swapWith(st, Jimple.v().newIdentityStmt(is.getLeftOp(), Jimple.v().newParameterRef(is.getRightOp().getType(), 0)));
                                } else {
                                    if (is.getRightOp() instanceof ParameterRef) {
                                        ParameterRef ro = (ParameterRef) is.getRightOp();
                                        ro.setIndex(ro.getIndex() + 1);
                                    }
                                }
                            }
                        }
                    }
                    instanceToStaticMap.put(target, ct);
                }
                SootMethod clonedTarget = (SootMethod) instanceToStaticMap.get(target);
                Value thisToAdd = ((InstanceInvokeExpr) ie).getBase();
                // Insert casts to please the verifier.
                if (options.insert_redundant_casts()) {
                    // The verifier will complain if targetUsesThis, and:
                    // the argument passed to the method is not the same
                    // type.
                    // For instance, Bottle.price_static takes a cost.
                    // Cost is an interface implemented by Bottle.
                    SootClass localType, parameterType;
                    localType = ((RefType) ((InstanceInvokeExpr) ie).getBase().getType()).getSootClass();
                    parameterType = target.getDeclaringClass();
                    if (localType.isInterface() || hierarchy.isClassSuperclassOf(localType, parameterType)) {
                        Local castee = Jimple.v().newLocal("__castee", parameterType.getType());
                        b.getLocals().add(castee);
                        b.getUnits().insertBefore(Jimple.v().newAssignStmt(castee, Jimple.v().newCastExpr(((InstanceInvokeExpr) ie).getBase(), parameterType.getType())), s);
                        thisToAdd = castee;
                    }
                }
                // Now rebind the method call & fix the invoke graph.
                {
                    List newArgs = new ArrayList();
                    newArgs.add(thisToAdd);
                    newArgs.addAll(ie.getArgs());
                    StaticInvokeExpr sie = Jimple.v().newStaticInvokeExpr(clonedTarget.makeRef(), newArgs);
                    ValueBox ieBox = s.getInvokeExprBox();
                    ieBox.setValue(sie);
                    cg.addEdge(new Edge(container, s, clonedTarget));
                }
                // (If enabled), add a null pointer check.
                if (options.insert_null_checks()) {
                    boolean caught = TrapManager.isExceptionCaughtAt(Scene.v().getSootClass("java.lang.NullPointerException"), s, b);
                    /* Ah ha. Caught again! */
                    if (caught) {
                        /*
							 * In this case, we don't use throwPoint; instead,
							 * put the code right there.
							 */
                        Stmt insertee = Jimple.v().newIfStmt(Jimple.v().newNeExpr(((InstanceInvokeExpr) ie).getBase(), NullConstant.v()), s);
                        b.getUnits().insertBefore(insertee, s);
                        // This sucks (but less than before).
                        ((IfStmt) insertee).setTarget(s);
                        ThrowManager.addThrowAfter(b, insertee);
                    } else {
                        Stmt throwPoint = ThrowManager.getNullPointerExceptionThrower(b);
                        b.getUnits().insertBefore(Jimple.v().newIfStmt(Jimple.v().newEqExpr(((InstanceInvokeExpr) ie).getBase(), NullConstant.v()), throwPoint), s);
                    }
                }
                // Add synchronizing stuff.
                {
                    if (target.isSynchronized()) {
                        clonedTarget.setModifiers(clonedTarget.getModifiers() & ~Modifier.SYNCHRONIZED);
                        SynchronizerManager.v().synchronizeStmtOn(s, b, (Local) ((InstanceInvokeExpr) ie).getBase());
                    }
                }
                // Resolve name collisions.
                LocalNameStandardizer.v().transform(b, phaseName + ".lns");
            }
        }
    }
}
Also used : Chain(soot.util.Chain) HashMap(java.util.HashMap) SpecialInvokeExpr(soot.jimple.SpecialInvokeExpr) ArrayList(java.util.ArrayList) Unit(soot.Unit) IfStmt(soot.jimple.IfStmt) IdentityStmt(soot.jimple.IdentityStmt) Stmt(soot.jimple.Stmt) StaticInvokeExpr(soot.jimple.StaticInvokeExpr) Hierarchy(soot.Hierarchy) InstanceInvokeEdgesPred(soot.jimple.toolkits.callgraph.InstanceInvokeEdgesPred) InstanceInvokeExpr(soot.jimple.InstanceInvokeExpr) SpecialInvokeExpr(soot.jimple.SpecialInvokeExpr) StaticInvokeExpr(soot.jimple.StaticInvokeExpr) InvokeExpr(soot.jimple.InvokeExpr) Iterator(java.util.Iterator) ArrayList(java.util.ArrayList) LinkedList(java.util.LinkedList) List(java.util.List) JimpleBody(soot.jimple.JimpleBody) Body(soot.Body) JimpleBody(soot.jimple.JimpleBody) IdentityStmt(soot.jimple.IdentityStmt) SMBOptions(soot.options.SMBOptions) InstanceInvokeExpr(soot.jimple.InstanceInvokeExpr) Local(soot.Local) Targets(soot.jimple.toolkits.callgraph.Targets) SootClass(soot.SootClass) LinkedList(java.util.LinkedList) ParameterRef(soot.jimple.ParameterRef) IfStmt(soot.jimple.IfStmt) Filter(soot.jimple.toolkits.callgraph.Filter) CallGraph(soot.jimple.toolkits.callgraph.CallGraph) ThisRef(soot.jimple.ThisRef) ValueBox(soot.ValueBox) Value(soot.Value) SootMethod(soot.SootMethod) Edge(soot.jimple.toolkits.callgraph.Edge)

Example 9 with Chain

use of soot.util.Chain in project soot by Sable.

the class SynchronizerManager method createClassFetcherFor.

/**
 * Creates a method which calls java.lang.Class.forName(String).
 *
 * The method should look like the following:
 *
 * <pre>
 *	         .static java.lang.Class class$(java.lang.String)
 *	         {
 *	             java.lang.String r0, $r5;
 *	             java.lang.ClassNotFoundException r1, $r3;
 *	             java.lang.Class $r2;
 *	             java.lang.NoClassDefFoundError $r4;
 *
 *	             r0 := @parameter0: java.lang.String;
 *
 *	         label0:
 *	             $r2 = .staticinvoke <java.lang.Class: java.lang.Class forName(java.lang.String)>(r0);
 *	             .return $r2;
 *
 *	         label1:
 *	             $r3 := @caughtexception;
 *	             r1 = $r3;
 *	             $r4 = .new java.lang.NoClassDefFoundError;
 *	             $r5 = .virtualinvoke r1.<java.lang.Throwable: java.lang.String getMessage()>();
 *	             .specialinvoke $r4.<java.lang.NoClassDefFoundError: .void <init>(java.lang.String)>($r5);
 *	             .throw $r4;
 *
 *	             .catch java.lang.ClassNotFoundException .from label0 .to label1 .with label1;
 *	         }
 * </pre>
 */
public SootMethod createClassFetcherFor(SootClass c, String methodName) {
    // Create the method
    SootMethod method = Scene.v().makeSootMethod(methodName, Arrays.asList(new Type[] { RefType.v("java.lang.String") }), RefType.v("java.lang.Class"), Modifier.STATIC);
    c.addMethod(method);
    // Create the method body
    {
        JimpleBody body = Jimple.v().newBody(method);
        method.setActiveBody(body);
        Chain units = body.getUnits();
        Local l_r0, l_r1, l_r2, l_r3, l_r4, l_r5;
        // Add some locals
        l_r0 = Jimple.v().newLocal("r0", RefType.v("java.lang.String"));
        l_r1 = Jimple.v().newLocal("r1", RefType.v("java.lang.ClassNotFoundException"));
        l_r2 = Jimple.v().newLocal("$r2", RefType.v("java.lang.Class"));
        l_r3 = Jimple.v().newLocal("$r3", RefType.v("java.lang.ClassNotFoundException"));
        l_r4 = Jimple.v().newLocal("$r4", RefType.v("java.lang.NoClassDefFoundError"));
        l_r5 = Jimple.v().newLocal("$r5", RefType.v("java.lang.String"));
        body.getLocals().add(l_r0);
        body.getLocals().add(l_r1);
        body.getLocals().add(l_r2);
        body.getLocals().add(l_r3);
        body.getLocals().add(l_r4);
        body.getLocals().add(l_r5);
        // add "r0 := @parameter0: java.lang.String"
        units.add(Jimple.v().newIdentityStmt(l_r0, Jimple.v().newParameterRef(RefType.v("java.lang.String"), 0)));
        // add "$r2 = .staticinvoke <java.lang.Class: java.lang.Class
        // forName(java.lang.String)>(r0);
        AssignStmt asi;
        units.add(asi = Jimple.v().newAssignStmt(l_r2, Jimple.v().newStaticInvokeExpr(Scene.v().getMethod("<java.lang.Class: java.lang.Class" + " forName(java.lang.String)>").makeRef(), Arrays.asList(new Value[] { l_r0 }))));
        // insert "return $r2;"
        units.add(Jimple.v().newReturnStmt(l_r2));
        // add "r3 := @caughtexception;"
        Stmt handlerStart;
        units.add(handlerStart = Jimple.v().newIdentityStmt(l_r3, Jimple.v().newCaughtExceptionRef()));
        // add "r1 = r3;"
        units.add(Jimple.v().newAssignStmt(l_r1, l_r3));
        // add "$r4 = .new java.lang.NoClassDefFoundError;"
        units.add(Jimple.v().newAssignStmt(l_r4, Jimple.v().newNewExpr(RefType.v("java.lang.NoClassDefFoundError"))));
        // add "$r5 = virtualinvoke r1.<java.lang.Throwable:
        // java.lang.String getMessage()>();"
        units.add(Jimple.v().newAssignStmt(l_r5, Jimple.v().newVirtualInvokeExpr(l_r1, Scene.v().getMethod("<java.lang.Throwable: java.lang.String getMessage()>").makeRef(), new LinkedList())));
        // add .specialinvoke $r4.<java.lang.NoClassDefFoundError: .void
        // <init>(java.lang.String)>($r5);
        units.add(Jimple.v().newInvokeStmt(Jimple.v().newSpecialInvokeExpr(l_r4, Scene.v().getMethod("<java.lang.NoClassDefFoundError: void" + " <init>(java.lang.String)>").makeRef(), Arrays.asList(new Value[] { l_r5 }))));
        // add .throw $r4;
        units.add(Jimple.v().newThrowStmt(l_r4));
        body.getTraps().add(Jimple.v().newTrap(Scene.v().getSootClass("java.lang.ClassNotFoundException"), asi, handlerStart, handlerStart));
    }
    return method;
}
Also used : Chain(soot.util.Chain) RefType(soot.RefType) Type(soot.Type) AssignStmt(soot.jimple.AssignStmt) Value(soot.Value) SootMethod(soot.SootMethod) Local(soot.Local) JimpleBody(soot.jimple.JimpleBody) LinkedList(java.util.LinkedList) IfStmt(soot.jimple.IfStmt) IdentityStmt(soot.jimple.IdentityStmt) ReturnStmt(soot.jimple.ReturnStmt) Stmt(soot.jimple.Stmt) AssignStmt(soot.jimple.AssignStmt)

Example 10 with Chain

use of soot.util.Chain in project soot by Sable.

the class SynchronizerManager method addStmtsToFetchClassBefore.

/**
 * Adds code to fetch the static Class object to the given JimpleBody before
 * the target Stmt.
 *
 * Uses our custom classToClassField field to cache the results.
 *
 * The code will look like this:
 *
 * <pre>
 *	        $r3 = <quack: java.lang.Class class$quack>;
 *	        .if $r3 != .null .goto label2;
 *
 *	        $r3 = .staticinvoke <quack: java.lang.Class class$(java.lang.String)>("quack");
 *	        <quack: java.lang.Class class$quack> = $r3;
 *
 *	     label2:
 * </pre>
 */
public Local addStmtsToFetchClassBefore(JimpleBody jb, Stmt target) {
    SootClass sc = jb.getMethod().getDeclaringClass();
    SootField classCacher = classToClassField.get(sc);
    if (classCacher == null) {
        // Add a unique field named [__]class$name
        String n = "class$" + sc.getName().replace('.', '$');
        while (sc.declaresFieldByName(n)) n = "_" + n;
        classCacher = Scene.v().makeSootField(n, RefType.v("java.lang.Class"), Modifier.STATIC);
        sc.addField(classCacher);
        classToClassField.put(sc, classCacher);
    }
    String lName = "$uniqueClass";
    // Find unique name. Not strictly necessary unless we parse Jimple code.
    while (true) {
        Iterator it = jb.getLocals().iterator();
        boolean oops = false;
        while (it.hasNext()) {
            Local jbLocal = (Local) it.next();
            if (jbLocal.getName().equals(lName))
                oops = true;
        }
        if (!oops)
            break;
        lName = "_" + lName;
    }
    Local l = Jimple.v().newLocal(lName, RefType.v("java.lang.Class"));
    jb.getLocals().add(l);
    Chain units = jb.getUnits();
    units.insertBefore(Jimple.v().newAssignStmt(l, Jimple.v().newStaticFieldRef(classCacher.makeRef())), target);
    IfStmt ifStmt;
    units.insertBefore(ifStmt = Jimple.v().newIfStmt(Jimple.v().newNeExpr(l, NullConstant.v()), target), target);
    units.insertBefore(Jimple.v().newAssignStmt(l, Jimple.v().newStaticInvokeExpr(getClassFetcherFor(sc).makeRef(), Arrays.asList(new Value[] { StringConstant.v(sc.getName()) }))), target);
    units.insertBefore(Jimple.v().newAssignStmt(Jimple.v().newStaticFieldRef(classCacher.makeRef()), l), target);
    ifStmt.setTarget(target);
    return l;
}
Also used : Chain(soot.util.Chain) IfStmt(soot.jimple.IfStmt) Iterator(java.util.Iterator) Value(soot.Value) Local(soot.Local) SootField(soot.SootField) SootClass(soot.SootClass)

Aggregations

Chain (soot.util.Chain)15 Iterator (java.util.Iterator)8 ArrayList (java.util.ArrayList)7 List (java.util.List)7 Local (soot.Local)7 SootMethod (soot.SootMethod)6 Value (soot.Value)6 Body (soot.Body)5 SootClass (soot.SootClass)5 Unit (soot.Unit)5 HashMap (java.util.HashMap)4 LinkedList (java.util.LinkedList)4 Type (soot.Type)4 IfStmt (soot.jimple.IfStmt)4 Map (java.util.Map)3 ValueBox (soot.ValueBox)3 ASTMethodNode (soot.dava.internal.AST.ASTMethodNode)3 ASTNode (soot.dava.internal.AST.ASTNode)3 JimpleBody (soot.jimple.JimpleBody)3 Stmt (soot.jimple.Stmt)3