Search in sources :

Example 16 with InstanceInvokeExpr

use of soot.jimple.InstanceInvokeExpr in project soot by Sable.

the class AccessManager method createInvokeAccessor.

private static void createInvokeAccessor(SootMethod container, Stmt stmt) {
    java.util.List parameterTypes = new LinkedList();
    java.util.List<SootClass> thrownExceptions = new LinkedList<SootClass>();
    Type returnType;
    Body accessorBody = Jimple.v().newBody();
    soot.util.Chain accStmts = accessorBody.getUnits();
    LocalGenerator lg = new LocalGenerator(accessorBody);
    Body containerBody = container.getActiveBody();
    soot.util.Chain containerStmts = containerBody.getUnits();
    InvokeExpr expr = stmt.getInvokeExpr();
    SootMethod method = expr.getMethod();
    // System.out.println("method: " + method);
    SootClass target = method.getDeclaringClass();
    // System.out.println("target: " + target);
    // System.out.println("method ref: " + expr.getMethodRef());
    SootMethod accessor;
    String name = createAccessorName(method, true);
    accessor = target.getMethodByNameUnsafe(name);
    if (accessor == null) {
        java.util.List arguments = new LinkedList();
        if (expr instanceof InstanceInvokeExpr) {
            parameterTypes.add(target.getType());
        }
        parameterTypes.addAll(method.getParameterTypes());
        returnType = method.getReturnType();
        thrownExceptions.addAll(method.getExceptions());
        int paramID = 0;
        for (java.util.Iterator it = parameterTypes.iterator(); it.hasNext(); ) {
            Type type = (Type) it.next();
            Local l = lg.generateLocal(type);
            // System.out.println("local type: " + type);
            accStmts.add(Jimple.v().newIdentityStmt(l, Jimple.v().newParameterRef(type, paramID)));
            arguments.add(l);
            paramID++;
        }
        InvokeExpr accExpr;
        if (expr instanceof StaticInvokeExpr) {
            accExpr = Jimple.v().newStaticInvokeExpr(method.makeRef(), arguments);
        } else if (expr instanceof VirtualInvokeExpr) {
            Local thisLocal = (Local) arguments.get(0);
            arguments.remove(0);
            accExpr = Jimple.v().newVirtualInvokeExpr(thisLocal, method.makeRef(), arguments);
        } else if (expr instanceof SpecialInvokeExpr) {
            Local thisLocal = (Local) arguments.get(0);
            arguments.remove(0);
            accExpr = Jimple.v().newSpecialInvokeExpr(thisLocal, method.makeRef(), arguments);
        } else
            throw new RuntimeException("");
        Stmt s;
        if (returnType instanceof VoidType) {
            s = Jimple.v().newInvokeStmt(accExpr);
            accStmts.add(s);
            accStmts.add(Jimple.v().newReturnVoidStmt());
        } else {
            Local resultLocal = lg.generateLocal(returnType);
            s = Jimple.v().newAssignStmt(resultLocal, accExpr);
            accStmts.add(s);
            accStmts.add(Jimple.v().newReturnStmt(resultLocal));
        }
        accessor = Scene.v().makeSootMethod(name, parameterTypes, returnType, Modifier.PUBLIC | Modifier.STATIC, thrownExceptions);
        accessorBody.setMethod(accessor);
        accessor.setActiveBody(accessorBody);
        target.addMethod(accessor);
    }
    java.util.List args = new LinkedList();
    if (expr instanceof InstanceInvokeExpr) {
        args.add(((InstanceInvokeExpr) expr).getBase());
    }
    args.addAll(expr.getArgs());
    InvokeExpr newExpr = Jimple.v().newStaticInvokeExpr(accessor.makeRef(), args);
    stmt.getInvokeExprBox().setValue(newExpr);
}
Also used : VoidType(soot.VoidType) LocalGenerator(soot.javaToJimple.LocalGenerator) Iterator(java.util.Iterator) SpecialInvokeExpr(soot.jimple.SpecialInvokeExpr) InstanceInvokeExpr(soot.jimple.InstanceInvokeExpr) Local(soot.Local) SootClass(soot.SootClass) LinkedList(java.util.LinkedList) Stmt(soot.jimple.Stmt) AssignStmt(soot.jimple.AssignStmt) StaticInvokeExpr(soot.jimple.StaticInvokeExpr) Type(soot.Type) VoidType(soot.VoidType) InstanceInvokeExpr(soot.jimple.InstanceInvokeExpr) SpecialInvokeExpr(soot.jimple.SpecialInvokeExpr) StaticInvokeExpr(soot.jimple.StaticInvokeExpr) VirtualInvokeExpr(soot.jimple.VirtualInvokeExpr) InvokeExpr(soot.jimple.InvokeExpr) SootMethod(soot.SootMethod) VirtualInvokeExpr(soot.jimple.VirtualInvokeExpr) Body(soot.Body)

Example 17 with InstanceInvokeExpr

use of soot.jimple.InstanceInvokeExpr in project soot by Sable.

the class SiteInliner method inlineSite.

/**
 *        Inlines the given site.  Note that this method does
 *        not actually check if it's safe (with respect to access modifiers and special invokes)
 *        for it to be inlined.  That functionality is handled by the InlinerSafetyManager.
 */
public static List inlineSite(SootMethod inlinee, Stmt toInline, SootMethod container, Map options) {
    boolean enableNullPointerCheckInsertion = PhaseOptions.getBoolean(options, "insert-null-checks");
    boolean enableRedundantCastInsertion = PhaseOptions.getBoolean(options, "insert-redundant-casts");
    Hierarchy hierarchy = Scene.v().getActiveHierarchy();
    JimpleBody containerB = (JimpleBody) container.getActiveBody();
    Chain<Unit> containerUnits = containerB.getUnits();
    if (!(inlinee.getDeclaringClass().isApplicationClass() || inlinee.getDeclaringClass().isLibraryClass()))
        return null;
    Body inlineeB = inlinee.getActiveBody();
    Chain<Unit> inlineeUnits = inlineeB.getUnits();
    InvokeExpr ie = toInline.getInvokeExpr();
    Value thisToAdd = null;
    if (ie instanceof InstanceInvokeExpr)
        thisToAdd = ((InstanceInvokeExpr) ie).getBase();
    // Insert casts to please the verifier.
    {
        boolean targetUsesThis = true;
        if (enableRedundantCastInsertion && ie instanceof InstanceInvokeExpr && targetUsesThis) {
            // 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 = inlinee.getDeclaringClass();
            if (localType.isInterface() || hierarchy.isClassSuperclassOf(localType, parameterType)) {
                Local castee = Jimple.v().newLocal("__castee", parameterType.getType());
                containerB.getLocals().add(castee);
                containerB.getUnits().insertBefore(Jimple.v().newAssignStmt(castee, Jimple.v().newCastExpr(((InstanceInvokeExpr) ie).getBase(), parameterType.getType())), toInline);
                thisToAdd = castee;
            }
        }
    }
    // (If enabled), add a null pointer check.
    {
        if (enableNullPointerCheckInsertion && ie instanceof InstanceInvokeExpr) {
            boolean caught = TrapManager.isExceptionCaughtAt(Scene.v().getSootClass("java.lang.NullPointerException"), toInline, containerB);
            /* 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()), toInline);
                containerB.getUnits().insertBefore(insertee, toInline);
                // This sucks (but less than before).
                ((IfStmt) insertee).setTarget(toInline);
                ThrowManager.addThrowAfter(containerB, insertee);
            } else {
                Stmt throwPoint = ThrowManager.getNullPointerExceptionThrower(containerB);
                containerB.getUnits().insertBefore(Jimple.v().newIfStmt(Jimple.v().newEqExpr(((InstanceInvokeExpr) ie).getBase(), NullConstant.v()), throwPoint), toInline);
            }
        }
    }
    // Add synchronizing stuff.
    {
        if (inlinee.isSynchronized()) {
            // Need to get the class object if ie is a static invoke.
            if (ie instanceof InstanceInvokeExpr)
                SynchronizerManager.v().synchronizeStmtOn(toInline, containerB, (Local) ((InstanceInvokeExpr) ie).getBase());
            else {
                // synchronization.
                if (!container.getDeclaringClass().isInterface()) {
                    // Whew!
                    Local l = SynchronizerManager.v().addStmtsToFetchClassBefore(containerB, toInline);
                    SynchronizerManager.v().synchronizeStmtOn(toInline, containerB, l);
                }
            }
        }
    }
    Stmt exitPoint = (Stmt) containerUnits.getSuccOf(toInline);
    // First, clone all of the inlinee's units & locals.
    HashMap<Local, Local> oldLocalsToNew = new HashMap<Local, Local>();
    HashMap<Stmt, Stmt> oldUnitsToNew = new HashMap<Stmt, Stmt>();
    {
        Stmt cursor = toInline;
        for (Iterator<Unit> currIt = inlineeUnits.iterator(); currIt.hasNext(); ) {
            final Stmt curr = (Stmt) currIt.next();
            Stmt currPrime = (Stmt) curr.clone();
            if (currPrime == null)
                throw new RuntimeException("getting null from clone!");
            currPrime.addAllTagsOf(curr);
            containerUnits.insertAfter(currPrime, cursor);
            cursor = currPrime;
            oldUnitsToNew.put(curr, currPrime);
        }
        for (Iterator<Local> lIt = inlineeB.getLocals().iterator(); lIt.hasNext(); ) {
            final Local l = lIt.next();
            Local lPrime = (Local) l.clone();
            if (lPrime == null)
                throw new RuntimeException("getting null from local clone!");
            containerB.getLocals().add(lPrime);
            oldLocalsToNew.put(l, lPrime);
        }
    }
    // Backpatch the newly-inserted units using newly-constructed maps.
    {
        Iterator<Unit> it = containerUnits.iterator(containerUnits.getSuccOf(toInline), containerUnits.getPredOf(exitPoint));
        while (it.hasNext()) {
            Stmt patchee = (Stmt) it.next();
            for (ValueBox box : patchee.getUseAndDefBoxes()) {
                if (!(box.getValue() instanceof Local))
                    continue;
                Local lPrime = oldLocalsToNew.get(box.getValue());
                if (lPrime != null)
                    box.setValue(lPrime);
                else
                    throw new RuntimeException("local has no clone!");
            }
            for (UnitBox box : patchee.getUnitBoxes()) {
                Unit uPrime = (oldUnitsToNew.get(box.getUnit()));
                if (uPrime != null)
                    box.setUnit(uPrime);
                else
                    throw new RuntimeException("inlined stmt has no clone!");
            }
        }
    }
    // Copy & backpatch the traps; preserve their same order.
    {
        Trap prevTrap = null;
        for (Trap t : inlineeB.getTraps()) {
            Stmt newBegin = oldUnitsToNew.get(t.getBeginUnit()), newEnd = oldUnitsToNew.get(t.getEndUnit()), newHandler = oldUnitsToNew.get(t.getHandlerUnit());
            if (newBegin == null || newEnd == null || newHandler == null)
                throw new RuntimeException("couldn't map trap!");
            Trap trap = Jimple.v().newTrap(t.getException(), newBegin, newEnd, newHandler);
            if (prevTrap == null)
                containerB.getTraps().addFirst(trap);
            else
                containerB.getTraps().insertAfter(trap, prevTrap);
            prevTrap = trap;
        }
    }
    // Handle identity stmt's and returns.
    {
        Iterator<Unit> it = containerUnits.iterator(containerUnits.getSuccOf(toInline), containerUnits.getPredOf(exitPoint));
        ArrayList<Unit> cuCopy = new ArrayList<Unit>();
        while (it.hasNext()) {
            cuCopy.add(it.next());
        }
        for (Unit u : cuCopy) {
            Stmt s = (Stmt) u;
            if (s instanceof IdentityStmt) {
                IdentityRef rhs = (IdentityRef) ((IdentityStmt) s).getRightOp();
                if (rhs instanceof CaughtExceptionRef)
                    continue;
                else if (rhs instanceof ThisRef) {
                    if (!(ie instanceof InstanceInvokeExpr))
                        throw new RuntimeException("thisref with no receiver!");
                    containerUnits.swapWith(s, Jimple.v().newAssignStmt(((IdentityStmt) s).getLeftOp(), thisToAdd));
                } else if (rhs instanceof ParameterRef) {
                    ParameterRef pref = (ParameterRef) rhs;
                    containerUnits.swapWith(s, Jimple.v().newAssignStmt(((IdentityStmt) s).getLeftOp(), ie.getArg(pref.getIndex())));
                }
            } else if (s instanceof ReturnStmt) {
                if (toInline instanceof InvokeStmt) {
                    // munch, munch.
                    containerUnits.swapWith(s, Jimple.v().newGotoStmt(exitPoint));
                    continue;
                }
                if (!(toInline instanceof AssignStmt))
                    throw new RuntimeException("invoking stmt neither InvokeStmt nor AssignStmt!??!?!");
                Value ro = ((ReturnStmt) s).getOp();
                Value lhs = ((AssignStmt) toInline).getLeftOp();
                AssignStmt as = Jimple.v().newAssignStmt(lhs, ro);
                containerUnits.insertBefore(as, s);
                containerUnits.swapWith(s, Jimple.v().newGotoStmt(exitPoint));
            } else if (s instanceof ReturnVoidStmt)
                containerUnits.swapWith(s, Jimple.v().newGotoStmt(exitPoint));
        }
    }
    List<Unit> newStmts = new ArrayList<Unit>();
    for (Iterator<Unit> i = containerUnits.iterator(containerUnits.getSuccOf(toInline), containerUnits.getPredOf(exitPoint)); i.hasNext(); ) {
        newStmts.add(i.next());
    }
    // Remove the original statement toInline.
    containerUnits.remove(toInline);
    // Resolve name collisions.
    LocalNameStandardizer.v().transform(containerB, "ji.lns");
    return newStmts;
}
Also used : CaughtExceptionRef(soot.jimple.CaughtExceptionRef) InvokeStmt(soot.jimple.InvokeStmt) HashMap(java.util.HashMap) AssignStmt(soot.jimple.AssignStmt) ReturnVoidStmt(soot.jimple.ReturnVoidStmt) ArrayList(java.util.ArrayList) Unit(soot.Unit) ReturnVoidStmt(soot.jimple.ReturnVoidStmt) InvokeStmt(soot.jimple.InvokeStmt) IfStmt(soot.jimple.IfStmt) IdentityStmt(soot.jimple.IdentityStmt) ReturnStmt(soot.jimple.ReturnStmt) Stmt(soot.jimple.Stmt) AssignStmt(soot.jimple.AssignStmt) RefType(soot.RefType) Hierarchy(soot.Hierarchy) InstanceInvokeExpr(soot.jimple.InstanceInvokeExpr) InvokeExpr(soot.jimple.InvokeExpr) IdentityRef(soot.jimple.IdentityRef) Iterator(java.util.Iterator) JimpleBody(soot.jimple.JimpleBody) Body(soot.Body) JimpleBody(soot.jimple.JimpleBody) IdentityStmt(soot.jimple.IdentityStmt) UnitBox(soot.UnitBox) InstanceInvokeExpr(soot.jimple.InstanceInvokeExpr) Local(soot.Local) Trap(soot.Trap) SootClass(soot.SootClass) ParameterRef(soot.jimple.ParameterRef) ThisRef(soot.jimple.ThisRef) ValueBox(soot.ValueBox) Value(soot.Value) ReturnStmt(soot.jimple.ReturnStmt)

Example 18 with InstanceInvokeExpr

use of soot.jimple.InstanceInvokeExpr in project soot by Sable.

the class OnFlyCallGraphBuilder method findReceivers.

private void findReceivers(SootMethod m, Body b) {
    for (final Unit u : b.getUnits()) {
        final Stmt s = (Stmt) u;
        if (s.containsInvokeExpr()) {
            InvokeExpr ie = s.getInvokeExpr();
            if (ie instanceof InstanceInvokeExpr) {
                InstanceInvokeExpr iie = (InstanceInvokeExpr) ie;
                Local receiver = (Local) iie.getBase();
                NumberedString subSig = iie.getMethodRef().getSubSignature();
                addVirtualCallSite(s, m, receiver, iie, subSig, Edge.ieToKind(iie));
                if (subSig == sigStart) {
                    addVirtualCallSite(s, m, receiver, iie, sigRun, Kind.THREAD);
                } else if (subSig == sigExecutorExecute || subSig == sigHandlerPost || subSig == sigHandlerPostAtFrontOfQueue || subSig == sigHandlerPostAtTime || subSig == sigHandlerPostAtTimeWithToken || subSig == sigHandlerPostDelayed) {
                    if (iie.getArgCount() > 0) {
                        Value runnable = iie.getArg(0);
                        if (runnable instanceof Local)
                            addVirtualCallSite(s, m, (Local) runnable, iie, sigRun, Kind.EXECUTOR);
                    }
                } else if (subSig == sigHandlerSendEmptyMessage || subSig == sigHandlerSendEmptyMessageAtTime || subSig == sigHandlerSendEmptyMessageDelayed || subSig == sigHandlerSendMessage || subSig == sigHandlerSendMessageAtFrontOfQueue || subSig == sigHandlerSendMessageAtTime || subSig == sigHandlerSendMessageDelayed) {
                    addVirtualCallSite(s, m, receiver, iie, sigHandlerHandleMessage, Kind.HANDLER);
                } else if (subSig == sigExecute) {
                    addVirtualCallSite(s, m, receiver, iie, sigDoInBackground, Kind.ASYNCTASK);
                }
            } else if (ie instanceof DynamicInvokeExpr) {
                if (options.verbose())
                    logger.debug("" + "WARNING: InvokeDynamic to " + ie + " not resolved during call-graph construction.");
            } else {
                SootMethod tgt = ie.getMethod();
                if (tgt != null) {
                    addEdge(m, s, tgt);
                    String signature = tgt.getSignature();
                    if (signature.equals("<java.security.AccessController: java.lang.Object doPrivileged(java.security.PrivilegedAction)>") || signature.equals("<java.security.AccessController: java.lang.Object doPrivileged(java.security.PrivilegedExceptionAction)>") || signature.equals("<java.security.AccessController: java.lang.Object doPrivileged(java.security.PrivilegedAction,java.security.AccessControlContext)>") || signature.equals("<java.security.AccessController: java.lang.Object doPrivileged(java.security.PrivilegedExceptionAction,java.security.AccessControlContext)>")) {
                        Local receiver = (Local) ie.getArg(0);
                        addVirtualCallSite(s, m, receiver, null, sigObjRun, Kind.PRIVILEGED);
                    }
                } else {
                    if (!Options.v().ignore_resolution_errors()) {
                        throw new InternalError("Unresolved target " + ie.getMethod() + ". Resolution error should have occured earlier.");
                    }
                }
            }
        }
    }
}
Also used : NumberedString(soot.util.NumberedString) InstanceInvokeExpr(soot.jimple.InstanceInvokeExpr) DynamicInvokeExpr(soot.jimple.DynamicInvokeExpr) VirtualInvokeExpr(soot.jimple.VirtualInvokeExpr) InvokeExpr(soot.jimple.InvokeExpr) SpecialInvokeExpr(soot.jimple.SpecialInvokeExpr) StaticInvokeExpr(soot.jimple.StaticInvokeExpr) Value(soot.Value) InstanceInvokeExpr(soot.jimple.InstanceInvokeExpr) Local(soot.Local) SootMethod(soot.SootMethod) DynamicInvokeExpr(soot.jimple.DynamicInvokeExpr) NumberedString(soot.util.NumberedString) Unit(soot.Unit) InvokeStmt(soot.jimple.InvokeStmt) AssignStmt(soot.jimple.AssignStmt) Stmt(soot.jimple.Stmt)

Example 19 with InstanceInvokeExpr

use of soot.jimple.InstanceInvokeExpr in project soot by Sable.

the class NullnessAssumptionAnalysis method handleInvokeExpr.

private void handleInvokeExpr(InvokeExpr invokeExpr, AnalysisInfo out) {
    if (invokeExpr instanceof InstanceInvokeExpr) {
        InstanceInvokeExpr instanceInvokeExpr = (InstanceInvokeExpr) invokeExpr;
        // here we know that the receiver must point to an object
        Value base = instanceInvokeExpr.getBase();
        out.put(base, NON_NULL);
    }
// but the returned object might point to everything
// out.put(invokeExpr, TOP);
}
Also used : Value(soot.Value) InstanceInvokeExpr(soot.jimple.InstanceInvokeExpr)

Example 20 with InstanceInvokeExpr

use of soot.jimple.InstanceInvokeExpr in project soot by Sable.

the class ReflectiveCallsInliner method inlineRelectiveCalls.

private void inlineRelectiveCalls(SootMethod m, Set<String> targets, Kind callKind) {
    if (!m.hasActiveBody())
        m.retrieveActiveBody();
    Body b = m.getActiveBody();
    PatchingChain<Unit> units = b.getUnits();
    Iterator<Unit> iter = units.snapshotIterator();
    LocalGenerator localGen = new LocalGenerator(b);
    // for all units
    while (iter.hasNext()) {
        Chain<Unit> newUnits = new HashChain<Unit>();
        Stmt s = (Stmt) iter.next();
        // reflective invoke expression
        if (s.containsInvokeExpr()) {
            InvokeExpr ie = s.getInvokeExpr();
            boolean found = false;
            Type fieldSetGetType = null;
            if (callKind == Kind.ClassForName && (ie.getMethodRef().getSignature().equals("<java.lang.Class: java.lang.Class forName(java.lang.String)>") || ie.getMethodRef().getSignature().equals("<java.lang.Class: java.lang.Class forName(java.lang.String,boolean,java.lang.ClassLoader)>"))) {
                found = true;
                Value classNameValue = ie.getArg(0);
                newUnits.add(Jimple.v().newInvokeStmt(Jimple.v().newStaticInvokeExpr(Scene.v().getMethod("<soot.rtlib.tamiflex.ReflectiveCalls: void knownClassForName(int,java.lang.String)>").makeRef(), IntConstant.v(callSiteId), classNameValue)));
            } else if (callKind == Kind.ClassNewInstance && ie.getMethodRef().getSignature().equals("<java.lang.Class: java.lang.Object newInstance()>")) {
                found = true;
                Local classLocal = (Local) ((InstanceInvokeExpr) ie).getBase();
                newUnits.add(Jimple.v().newInvokeStmt(Jimple.v().newStaticInvokeExpr(Scene.v().getMethod("<soot.rtlib.tamiflex.ReflectiveCalls: void knownClassNewInstance(int,java.lang.Class)>").makeRef(), IntConstant.v(callSiteId), classLocal)));
            } else if (callKind == Kind.ConstructorNewInstance && ie.getMethodRef().getSignature().equals("<java.lang.reflect.Constructor: java.lang.Object newInstance(java.lang.Object[])>")) {
                found = true;
                Local constrLocal = (Local) ((InstanceInvokeExpr) ie).getBase();
                newUnits.add(Jimple.v().newInvokeStmt(Jimple.v().newStaticInvokeExpr(Scene.v().getMethod("<soot.rtlib.tamiflex.ReflectiveCalls: void knownConstructorNewInstance(int,java.lang.reflect.Constructor)>").makeRef(), IntConstant.v(callSiteId), constrLocal)));
            } else if (callKind == Kind.MethodInvoke && ie.getMethodRef().getSignature().equals("<java.lang.reflect.Method: java.lang.Object invoke(java.lang.Object,java.lang.Object[])>")) {
                found = true;
                Local methodLocal = (Local) ((InstanceInvokeExpr) ie).getBase();
                Value recv = ie.getArg(0);
                newUnits.add(Jimple.v().newInvokeStmt(Jimple.v().newStaticInvokeExpr(Scene.v().getMethod("<soot.rtlib.tamiflex.ReflectiveCalls: void knownMethodInvoke(int,java.lang.Object,java.lang.reflect.Method)>").makeRef(), IntConstant.v(callSiteId), recv, methodLocal)));
            } else if (callKind == Kind.FieldSet) {
                SootMethod sootMethod = ie.getMethodRef().resolve();
                if (sootMethod.getDeclaringClass().getName().equals("java.lang.reflect.Field") && fieldSets.contains(sootMethod.getName())) {
                    found = true;
                    // assign
                    fieldSetGetType = sootMethod.getParameterType(1);
                    // type
                    // of
                    // 2nd
                    // parameter
                    // (1st
                    // is
                    // receiver
                    // object)
                    Value recv = ie.getArg(0);
                    Value field = ((InstanceInvokeExpr) ie).getBase();
                    newUnits.add(Jimple.v().newInvokeStmt(Jimple.v().newStaticInvokeExpr(Scene.v().getMethod("<soot.rtlib.tamiflex.ReflectiveCalls: void knownFieldSet(int,java.lang.Object,java.lang.reflect.Field)>").makeRef(), IntConstant.v(callSiteId), recv, field)));
                }
            } else if (callKind == Kind.FieldGet) {
                SootMethod sootMethod = ie.getMethodRef().resolve();
                if (sootMethod.getDeclaringClass().getName().equals("java.lang.reflect.Field") && fieldGets.contains(sootMethod.getName())) {
                    found = true;
                    // assign
                    fieldSetGetType = sootMethod.getReturnType();
                    // return
                    // type
                    // of
                    // get
                    Value recv = ie.getArg(0);
                    Value field = ((InstanceInvokeExpr) ie).getBase();
                    newUnits.add(Jimple.v().newInvokeStmt(Jimple.v().newStaticInvokeExpr(Scene.v().getMethod("<soot.rtlib.tamiflex.ReflectiveCalls: void knownFieldSet(int,java.lang.Object,java.lang.reflect.Field)>").makeRef(), IntConstant.v(callSiteId), recv, field)));
                }
            }
            if (!found)
                continue;
            NopStmt endLabel = Jimple.v().newNopStmt();
            // for all recorded targets
            for (String target : targets) {
                NopStmt jumpTarget = Jimple.v().newNopStmt();
                // boolean predLocal = Opaque.getFalse();
                Local predLocal = localGen.generateLocal(BooleanType.v());
                StaticInvokeExpr staticInvokeExpr = Jimple.v().newStaticInvokeExpr(UNINTERPRETED_METHOD);
                newUnits.add(Jimple.v().newAssignStmt(predLocal, staticInvokeExpr));
                // if predLocal == 0 goto <original reflective call>
                newUnits.add(Jimple.v().newIfStmt(Jimple.v().newEqExpr(IntConstant.v(0), predLocal), jumpTarget));
                SootMethod newMethod = createNewMethod(callKind, target, fieldSetGetType);
                List<Value> args = new LinkedList<Value>();
                switch(callKind) {
                    case ClassForName:
                    case ClassNewInstance:
                        // no arguments
                        break;
                    case ConstructorNewInstance:
                        // add Object[] argument
                        args.add((Value) ie.getArgs().get(0));
                        break;
                    case MethodInvoke:
                        // add Object argument
                        args.add((Value) ie.getArgs().get(0));
                        // add Object[] argument
                        args.add((Value) ie.getArgs().get(1));
                        break;
                    case FieldSet:
                        // add Object argument
                        args.add((Value) ie.getArgs().get(0));
                        // add value argument
                        args.add((Value) ie.getArgs().get(1));
                        break;
                    case FieldGet:
                        // add Object argument
                        args.add((Value) ie.getArgs().get(0));
                        break;
                    default:
                        throw new IllegalStateException();
                }
                StaticInvokeExpr methodInvokeExpr = Jimple.v().newStaticInvokeExpr(newMethod.makeRef(), args);
                Local retLocal = localGen.generateLocal(newMethod.getReturnType());
                newUnits.add(Jimple.v().newAssignStmt(retLocal, methodInvokeExpr));
                if (s instanceof AssignStmt) {
                    AssignStmt assignStmt = (AssignStmt) s;
                    Value leftOp = assignStmt.getLeftOp();
                    AssignStmt newAssignStmt = Jimple.v().newAssignStmt(leftOp, retLocal);
                    newUnits.add(newAssignStmt);
                }
                GotoStmt gotoStmt = Jimple.v().newGotoStmt(endLabel);
                newUnits.add(gotoStmt);
                newUnits.add(jumpTarget);
            }
            Unit end = newUnits.getLast();
            units.insertAfter(newUnits, s);
            units.remove(s);
            units.insertAfter(s, end);
            units.insertAfter(endLabel, s);
        }
    }
    callSiteId++;
}
Also used : LocalGenerator(soot.javaToJimple.LocalGenerator) HashChain(soot.util.HashChain) AssignStmt(soot.jimple.AssignStmt) Local(soot.Local) InstanceInvokeExpr(soot.jimple.InstanceInvokeExpr) Unit(soot.Unit) LinkedList(java.util.LinkedList) InvokeStmt(soot.jimple.InvokeStmt) NopStmt(soot.jimple.NopStmt) GotoStmt(soot.jimple.GotoStmt) AssignStmt(soot.jimple.AssignStmt) Stmt(soot.jimple.Stmt) StaticInvokeExpr(soot.jimple.StaticInvokeExpr) RefType(soot.RefType) BooleanType(soot.BooleanType) Type(soot.Type) RefLikeType(soot.RefLikeType) ArrayType(soot.ArrayType) PrimType(soot.PrimType) VoidType(soot.VoidType) InstanceInvokeExpr(soot.jimple.InstanceInvokeExpr) InterfaceInvokeExpr(soot.jimple.InterfaceInvokeExpr) VirtualInvokeExpr(soot.jimple.VirtualInvokeExpr) InvokeExpr(soot.jimple.InvokeExpr) SpecialInvokeExpr(soot.jimple.SpecialInvokeExpr) StaticInvokeExpr(soot.jimple.StaticInvokeExpr) NopStmt(soot.jimple.NopStmt) GotoStmt(soot.jimple.GotoStmt) Value(soot.Value) SootMethod(soot.SootMethod) Body(soot.Body) JimpleBody(soot.jimple.JimpleBody)

Aggregations

InstanceInvokeExpr (soot.jimple.InstanceInvokeExpr)25 Value (soot.Value)13 InvokeExpr (soot.jimple.InvokeExpr)13 Stmt (soot.jimple.Stmt)12 Local (soot.Local)11 RefType (soot.RefType)11 SootMethod (soot.SootMethod)10 Type (soot.Type)9 StaticInvokeExpr (soot.jimple.StaticInvokeExpr)9 ArrayList (java.util.ArrayList)8 SootClass (soot.SootClass)8 Unit (soot.Unit)8 AssignStmt (soot.jimple.AssignStmt)8 VirtualInvokeExpr (soot.jimple.VirtualInvokeExpr)8 SpecialInvokeExpr (soot.jimple.SpecialInvokeExpr)7 ValueBox (soot.ValueBox)6 InvokeStmt (soot.jimple.InvokeStmt)6 Iterator (java.util.Iterator)5 SootMethodRef (soot.SootMethodRef)5 InterfaceInvokeExpr (soot.jimple.InterfaceInvokeExpr)5