Search in sources :

Example 6 with Pair

use of soot.toolkits.scalar.Pair in project soot by Sable.

the class VirtualCalls method resolveLibrarySignature.

protected void resolveLibrarySignature(Type declaredType, Type sigType, NumberedString subSig, SootMethod container, ChunkedQueue<SootMethod> targets, boolean appOnly, RefType base) {
    FastHierarchy fastHierachy = Scene.v().getOrMakeFastHierarchy();
    assert (declaredType instanceof RefType);
    Pair<Type, NumberedString> pair = new Pair<Type, NumberedString>(base, subSig);
    {
        Set<Pair<Type, NumberedString>> types = baseToPossibleSubTypes.get(pair);
        // just retrieve the previous result.
        if (types != null) {
            for (Pair<Type, NumberedString> tuple : types) {
                Type st = tuple.getO1();
                if (!fastHierachy.canStoreType(st, declaredType)) {
                    resolve(st, st, sigType, subSig, container, targets, appOnly);
                } else {
                    resolve(st, declaredType, sigType, subSig, container, targets, appOnly);
                }
            }
            return;
        }
    }
    Set<Pair<Type, NumberedString>> types = new HashSet<Pair<Type, NumberedString>>();
    // get return type; method name; parameter types
    String[] split = subSig.getString().replaceAll("(.*) (.*)\\((.*)\\)", "$1;$2;$3").split(";");
    Type declaredReturnType = Scene.v().getType(split[0]);
    String declaredName = split[1];
    List<Type> declaredParamTypes = new ArrayList<Type>();
    // separate the parameter types
    if (split.length == 3) {
        for (String type : split[2].split(",")) {
            declaredParamTypes.add(Scene.v().getType(type));
        }
    }
    Chain<SootClass> classes = Scene.v().getClasses();
    for (SootClass sc : classes) {
        for (SootMethod sm : sc.getMethods()) {
            if (sm.isConcrete() || sm.isNative()) {
                // method name has to match
                if (!sm.getName().equals(declaredName))
                    continue;
                // type or a sub type of it
                if (!fastHierachy.canStoreType(sm.getReturnType(), declaredReturnType))
                    continue;
                List<Type> paramTypes = sm.getParameterTypes();
                // ones (same type or super type).
                if (declaredParamTypes.size() != paramTypes.size())
                    continue;
                boolean check = true;
                for (int i = 0; i < paramTypes.size(); i++) {
                    if (!fastHierachy.canStoreType(declaredParamTypes.get(i), paramTypes.get(i))) {
                        check = false;
                        break;
                    }
                }
                if (check) {
                    Type st = sc.getType();
                    if (!fastHierachy.canStoreType(st, declaredType)) {
                        // therefore not used in library client
                        if (!sc.isFinal()) {
                            NumberedString newSubSig = sm.getNumberedSubSignature();
                            resolve(st, st, sigType, newSubSig, container, targets, appOnly);
                            types.add(new Pair<Type, NumberedString>(st, newSubSig));
                        }
                    } else {
                        resolve(st, declaredType, sigType, subSig, container, targets, appOnly);
                        types.add(new Pair<Type, NumberedString>(st, subSig));
                    }
                }
            }
        }
    }
    baseToPossibleSubTypes.putAll(pair, types);
}
Also used : NumberedString(soot.util.NumberedString) HashSet(java.util.HashSet) Set(java.util.Set) ArrayList(java.util.ArrayList) NumberedString(soot.util.NumberedString) SootClass(soot.SootClass) RefType(soot.RefType) FastHierarchy(soot.FastHierarchy) RefType(soot.RefType) AnySubType(soot.AnySubType) NullType(soot.NullType) ArrayType(soot.ArrayType) Type(soot.Type) SootMethod(soot.SootMethod) Pair(soot.toolkits.scalar.Pair) HashSet(java.util.HashSet)

Example 7 with Pair

use of soot.toolkits.scalar.Pair in project soot by Sable.

the class IFDSPossibleTypes method createFlowFunctionsFactory.

public FlowFunctions<Unit, Pair<Value, Type>, SootMethod> createFlowFunctionsFactory() {
    return new FlowFunctions<Unit, Pair<Value, Type>, SootMethod>() {

        public FlowFunction<Pair<Value, Type>> getNormalFlowFunction(Unit src, Unit dest) {
            if (src instanceof DefinitionStmt) {
                DefinitionStmt defnStmt = (DefinitionStmt) src;
                if (defnStmt.containsInvokeExpr())
                    return Identity.v();
                final Value right = defnStmt.getRightOp();
                final Value left = defnStmt.getLeftOp();
                // won't track primitive-typed variables
                if (right.getType() instanceof PrimType)
                    return Identity.v();
                if (right instanceof Constant || right instanceof NewExpr) {
                    return new FlowFunction<Pair<Value, Type>>() {

                        public Set<Pair<Value, Type>> computeTargets(Pair<Value, Type> source) {
                            if (source == zeroValue()) {
                                Set<Pair<Value, Type>> res = new LinkedHashSet<Pair<Value, Type>>();
                                res.add(new Pair<Value, Type>(left, right.getType()));
                                res.add(zeroValue());
                                return res;
                            } else if (source.getO1() instanceof Local && source.getO1().equivTo(left)) {
                                // strong update for local variables
                                return Collections.emptySet();
                            } else {
                                return Collections.singleton(source);
                            }
                        }
                    };
                } else if (right instanceof Ref || right instanceof Local) {
                    return new FlowFunction<Pair<Value, Type>>() {

                        public Set<Pair<Value, Type>> computeTargets(final Pair<Value, Type> source) {
                            Value value = source.getO1();
                            if (source.getO1() instanceof Local && source.getO1().equivTo(left)) {
                                // strong update for local variables
                                return Collections.emptySet();
                            } else if (maybeSameLocation(value, right)) {
                                return new LinkedHashSet<Pair<Value, Type>>() {

                                    {
                                        add(new Pair<Value, Type>(left, source.getO2()));
                                        add(source);
                                    }
                                };
                            } else {
                                return Collections.singleton(source);
                            }
                        }

                        private boolean maybeSameLocation(Value v1, Value v2) {
                            if (!(v1 instanceof InstanceFieldRef && v2 instanceof InstanceFieldRef) && !(v1 instanceof ArrayRef && v2 instanceof ArrayRef)) {
                                return v1.equivTo(v2);
                            }
                            if (v1 instanceof InstanceFieldRef && v2 instanceof InstanceFieldRef) {
                                InstanceFieldRef ifr1 = (InstanceFieldRef) v1;
                                InstanceFieldRef ifr2 = (InstanceFieldRef) v2;
                                if (!ifr1.getField().getName().equals(ifr2.getField().getName()))
                                    return false;
                                Local base1 = (Local) ifr1.getBase();
                                Local base2 = (Local) ifr2.getBase();
                                PointsToAnalysis pta = Scene.v().getPointsToAnalysis();
                                PointsToSet pts1 = pta.reachingObjects(base1);
                                PointsToSet pts2 = pta.reachingObjects(base2);
                                return pts1.hasNonEmptyIntersection(pts2);
                            } else {
                                // v1 instanceof ArrayRef && v2 instanceof ArrayRef
                                ArrayRef ar1 = (ArrayRef) v1;
                                ArrayRef ar2 = (ArrayRef) v2;
                                Local base1 = (Local) ar1.getBase();
                                Local base2 = (Local) ar2.getBase();
                                PointsToAnalysis pta = Scene.v().getPointsToAnalysis();
                                PointsToSet pts1 = pta.reachingObjects(base1);
                                PointsToSet pts2 = pta.reachingObjects(base2);
                                return pts1.hasNonEmptyIntersection(pts2);
                            }
                        }
                    };
                }
            }
            return Identity.v();
        }

        public FlowFunction<Pair<Value, Type>> getCallFlowFunction(final Unit src, final SootMethod dest) {
            Stmt stmt = (Stmt) src;
            InvokeExpr ie = stmt.getInvokeExpr();
            final List<Value> callArgs = ie.getArgs();
            final List<Local> paramLocals = new ArrayList<Local>();
            for (int i = 0; i < dest.getParameterCount(); i++) {
                paramLocals.add(dest.getActiveBody().getParameterLocal(i));
            }
            return new FlowFunction<Pair<Value, Type>>() {

                public Set<Pair<Value, Type>> computeTargets(Pair<Value, Type> source) {
                    if (!dest.getName().equals("<clinit>") && !dest.getSubSignature().equals("void run()")) {
                        Value value = source.getO1();
                        int argIndex = callArgs.indexOf(value);
                        if (argIndex > -1) {
                            return Collections.singleton(new Pair<Value, Type>(paramLocals.get(argIndex), source.getO2()));
                        }
                    }
                    return Collections.emptySet();
                }
            };
        }

        public FlowFunction<Pair<Value, Type>> getReturnFlowFunction(Unit callSite, SootMethod callee, Unit exitStmt, Unit retSite) {
            if (exitStmt instanceof ReturnStmt) {
                ReturnStmt returnStmt = (ReturnStmt) exitStmt;
                Value op = returnStmt.getOp();
                if (op instanceof Local) {
                    if (callSite instanceof DefinitionStmt) {
                        DefinitionStmt defnStmt = (DefinitionStmt) callSite;
                        Value leftOp = defnStmt.getLeftOp();
                        if (leftOp instanceof Local) {
                            final Local tgtLocal = (Local) leftOp;
                            final Local retLocal = (Local) op;
                            return new FlowFunction<Pair<Value, Type>>() {

                                public Set<Pair<Value, Type>> computeTargets(Pair<Value, Type> source) {
                                    if (source == retLocal)
                                        return Collections.singleton(new Pair<Value, Type>(tgtLocal, source.getO2()));
                                    return Collections.emptySet();
                                }
                            };
                        }
                    }
                }
            }
            return KillAll.v();
        }

        public FlowFunction<Pair<Value, Type>> getCallToReturnFlowFunction(Unit call, Unit returnSite) {
            return Identity.v();
        }
    };
}
Also used : LinkedHashSet(java.util.LinkedHashSet) PointsToSet(soot.PointsToSet) LinkedHashSet(java.util.LinkedHashSet) Set(java.util.Set) Constant(soot.jimple.Constant) ArrayList(java.util.ArrayList) Unit(soot.Unit) FlowFunctions(heros.FlowFunctions) ReturnStmt(soot.jimple.ReturnStmt) Stmt(soot.jimple.Stmt) DefinitionStmt(soot.jimple.DefinitionStmt) ArrayRef(soot.jimple.ArrayRef) InvokeExpr(soot.jimple.InvokeExpr) InstanceFieldRef(soot.jimple.InstanceFieldRef) PrimType(soot.PrimType) PointsToAnalysis(soot.PointsToAnalysis) Pair(soot.toolkits.scalar.Pair) PointsToSet(soot.PointsToSet) FlowFunction(heros.FlowFunction) Local(soot.Local) UnknownType(soot.UnknownType) Type(soot.Type) PrimType(soot.PrimType) ArrayRef(soot.jimple.ArrayRef) Ref(soot.jimple.Ref) InstanceFieldRef(soot.jimple.InstanceFieldRef) Value(soot.Value) NewExpr(soot.jimple.NewExpr) SootMethod(soot.SootMethod) DefinitionStmt(soot.jimple.DefinitionStmt) ReturnStmt(soot.jimple.ReturnStmt)

Example 8 with Pair

use of soot.toolkits.scalar.Pair in project soot by Sable.

the class IFDSReachingDefinitions method createFlowFunctionsFactory.

@Override
public FlowFunctions<Unit, Pair<Value, Set<DefinitionStmt>>, SootMethod> createFlowFunctionsFactory() {
    return new FlowFunctions<Unit, Pair<Value, Set<DefinitionStmt>>, SootMethod>() {

        @Override
        public FlowFunction<Pair<Value, Set<DefinitionStmt>>> getNormalFlowFunction(final Unit curr, Unit succ) {
            if (curr instanceof DefinitionStmt) {
                final DefinitionStmt assignment = (DefinitionStmt) curr;
                return new FlowFunction<Pair<Value, Set<DefinitionStmt>>>() {

                    @Override
                    public Set<Pair<Value, Set<DefinitionStmt>>> computeTargets(Pair<Value, Set<DefinitionStmt>> source) {
                        if (source != zeroValue()) {
                            if (source.getO1().equivTo(assignment.getLeftOp())) {
                                return Collections.emptySet();
                            }
                            return Collections.singleton(source);
                        } else {
                            LinkedHashSet<Pair<Value, Set<DefinitionStmt>>> res = new LinkedHashSet<Pair<Value, Set<DefinitionStmt>>>();
                            res.add(new Pair<Value, Set<DefinitionStmt>>(assignment.getLeftOp(), Collections.<DefinitionStmt>singleton(assignment)));
                            return res;
                        }
                    }
                };
            }
            return Identity.v();
        }

        @Override
        public FlowFunction<Pair<Value, Set<DefinitionStmt>>> getCallFlowFunction(Unit callStmt, final SootMethod destinationMethod) {
            Stmt stmt = (Stmt) callStmt;
            InvokeExpr invokeExpr = stmt.getInvokeExpr();
            final List<Value> args = invokeExpr.getArgs();
            final List<Local> localArguments = new ArrayList<Local>(args.size());
            for (Value value : args) {
                if (value instanceof Local)
                    localArguments.add((Local) value);
                else
                    localArguments.add(null);
            }
            return new FlowFunction<Pair<Value, Set<DefinitionStmt>>>() {

                @Override
                public Set<Pair<Value, Set<DefinitionStmt>>> computeTargets(Pair<Value, Set<DefinitionStmt>> source) {
                    if (!destinationMethod.getName().equals("<clinit>") && !destinationMethod.getSubSignature().equals("void run()"))
                        if (localArguments.contains(source.getO1())) {
                            int paramIndex = args.indexOf(source.getO1());
                            Pair<Value, Set<DefinitionStmt>> pair = new Pair<Value, Set<DefinitionStmt>>(new EquivalentValue(Jimple.v().newParameterRef(destinationMethod.getParameterType(paramIndex), paramIndex)), source.getO2());
                            return Collections.singleton(pair);
                        }
                    return Collections.emptySet();
                }
            };
        }

        @Override
        public FlowFunction<Pair<Value, Set<DefinitionStmt>>> getReturnFlowFunction(final Unit callSite, SootMethod calleeMethod, final Unit exitStmt, Unit returnSite) {
            if (!(callSite instanceof DefinitionStmt))
                return KillAll.v();
            if (exitStmt instanceof ReturnVoidStmt)
                return KillAll.v();
            return new FlowFunction<Pair<Value, Set<DefinitionStmt>>>() {

                @Override
                public Set<Pair<Value, Set<DefinitionStmt>>> computeTargets(Pair<Value, Set<DefinitionStmt>> source) {
                    if (exitStmt instanceof ReturnStmt) {
                        ReturnStmt returnStmt = (ReturnStmt) exitStmt;
                        if (returnStmt.getOp().equivTo(source.getO1())) {
                            DefinitionStmt definitionStmt = (DefinitionStmt) callSite;
                            Pair<Value, Set<DefinitionStmt>> pair = new Pair<Value, Set<DefinitionStmt>>(definitionStmt.getLeftOp(), source.getO2());
                            return Collections.singleton(pair);
                        }
                    }
                    return Collections.emptySet();
                }
            };
        }

        @Override
        public FlowFunction<Pair<Value, Set<DefinitionStmt>>> getCallToReturnFlowFunction(Unit callSite, Unit returnSite) {
            if (!(callSite instanceof DefinitionStmt))
                return Identity.v();
            final DefinitionStmt definitionStmt = (DefinitionStmt) callSite;
            return new FlowFunction<Pair<Value, Set<DefinitionStmt>>>() {

                @Override
                public Set<Pair<Value, Set<DefinitionStmt>>> computeTargets(Pair<Value, Set<DefinitionStmt>> source) {
                    if (source.getO1().equivTo(definitionStmt.getLeftOp())) {
                        return Collections.emptySet();
                    } else {
                        return Collections.singleton(source);
                    }
                }
            };
        }
    };
}
Also used : LinkedHashSet(java.util.LinkedHashSet) EquivalentValue(soot.EquivalentValue) LinkedHashSet(java.util.LinkedHashSet) Set(java.util.Set) FlowFunction(heros.FlowFunction) ReturnVoidStmt(soot.jimple.ReturnVoidStmt) ArrayList(java.util.ArrayList) JimpleLocal(soot.jimple.internal.JimpleLocal) Local(soot.Local) Unit(soot.Unit) FlowFunctions(heros.FlowFunctions) ReturnVoidStmt(soot.jimple.ReturnVoidStmt) ReturnStmt(soot.jimple.ReturnStmt) Stmt(soot.jimple.Stmt) DefinitionStmt(soot.jimple.DefinitionStmt) InvokeExpr(soot.jimple.InvokeExpr) EquivalentValue(soot.EquivalentValue) Value(soot.Value) SootMethod(soot.SootMethod) DefinitionStmt(soot.jimple.DefinitionStmt) ReturnStmt(soot.jimple.ReturnStmt) Pair(soot.toolkits.scalar.Pair)

Example 9 with Pair

use of soot.toolkits.scalar.Pair in project soot by Sable.

the class LockAllocationBodyTransformer method internalTransform.

protected void internalTransform(Body b, FlowSet fs, List<CriticalSectionGroup> groups, boolean[] insertedGlobalLock) {
    // 
    JimpleBody j = (JimpleBody) b;
    SootMethod thisMethod = b.getMethod();
    PatchingChain<Unit> units = b.getUnits();
    Iterator<Unit> unitIt = units.iterator();
    Unit firstUnit = j.getFirstNonIdentityStmt();
    Unit lastUnit = units.getLast();
    // Objects of synchronization, plus book keeping
    Local[] lockObj = new Local[groups.size()];
    boolean[] addedLocalLockObj = new boolean[groups.size()];
    SootField[] globalLockObj = new SootField[groups.size()];
    for (int i = 1; i < groups.size(); i++) {
        lockObj[i] = Jimple.v().newLocal("lockObj" + i, RefType.v("java.lang.Object"));
        addedLocalLockObj[i] = false;
        globalLockObj[i] = null;
    }
    // Get references to them if they do already exist.
    for (int i = 1; i < groups.size(); i++) {
        CriticalSectionGroup tnGroup = groups.get(i);
        if (!tnGroup.useDynamicLock && !tnGroup.useLocksets) {
            if (!insertedGlobalLock[i]) {
                // use it!
                try {
                    globalLockObj[i] = Scene.v().getMainClass().getFieldByName("globalLockObj" + i);
                // field already exists
                } catch (RuntimeException re) {
                    // field does not yet exist (or, as a pre-existing
                    // error, there is more than one field by this name)
                    globalLockObj[i] = Scene.v().makeSootField("globalLockObj" + i, RefType.v("java.lang.Object"), Modifier.STATIC | Modifier.PUBLIC);
                    Scene.v().getMainClass().addField(globalLockObj[i]);
                }
                insertedGlobalLock[i] = true;
            } else {
                globalLockObj[i] = Scene.v().getMainClass().getFieldByName("globalLockObj" + i);
            }
        }
    }
    // local lock object into the global lock object for use by other fns.
    if (// thisMethod.getSubSignature().equals("void
    !addedGlobalLockDefs) // <clinit>()") &&
    // thisMethod.getDeclaringClass() ==
    // Scene.v().getMainClass())
    {
        // Either get or add the <clinit> method to the main class
        SootClass mainClass = Scene.v().getMainClass();
        SootMethod clinitMethod = null;
        JimpleBody clinitBody = null;
        Stmt firstStmt = null;
        boolean addingNewClinit = !mainClass.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);
            mainClass.addMethod(clinitMethod);
        } else {
            clinitMethod = mainClass.getMethod("void <clinit>()");
            clinitBody = (JimpleBody) clinitMethod.getActiveBody();
            firstStmt = clinitBody.getFirstNonIdentityStmt();
        }
        PatchingChain<Unit> clinitUnits = clinitBody.getUnits();
        for (int i = 1; i < groups.size(); i++) {
            CriticalSectionGroup tnGroup = groups.get(i);
            // if( useGlobalLock[i - 1] )
            if (!tnGroup.useDynamicLock && !tnGroup.useLocksets) {
                // add local lock obj
                // addedLocalLockObj[i] = true;
                // TODO: add name
                clinitBody.getLocals().add(lockObj[i]);
                // conflict
                // avoidance code
                // assign new object to lock obj
                Stmt newStmt = Jimple.v().newAssignStmt(lockObj[i], 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(lockObj[i], 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)
                Stmt assignStmt = Jimple.v().newAssignStmt(Jimple.v().newStaticFieldRef(globalLockObj[i].makeRef()), lockObj[i]);
                if (addingNewClinit)
                    clinitUnits.add(assignStmt);
                else
                    clinitUnits.insertBeforeNoRedirect(assignStmt, firstStmt);
            }
        }
        if (addingNewClinit)
            clinitUnits.add(Jimple.v().newReturnVoidStmt());
        addedGlobalLockDefs = true;
    }
    int tempNum = 1;
    // Iterate through all of the transactions in the current method
    Iterator fsIt = fs.iterator();
    Stmt newPrep = null;
    while (fsIt.hasNext()) {
        CriticalSection tn = ((SynchronizedRegionFlowPair) fsIt.next()).tn;
        if (tn.setNumber == -1)
            // this tn should be deleted... for now just skip it!
            continue;
        if (tn.wholeMethod) {
            // remove
            thisMethod.setModifiers(thisMethod.getModifiers() & ~(Modifier.SYNCHRONIZED));
        // synchronized
        // modifier
        // for
        // this
        // method
        }
        // depends on type of locking
        Local clo = null;
        // current synchronized region
        SynchronizedRegion csr = null;
        int lockNum = 0;
        boolean moreLocks = true;
        while (moreLocks) {
            // needed for this transaction, then create one.
            if (tn.group.useDynamicLock) {
                // adds
                Value lock = getLockFor((EquivalentValue) tn.lockObject);
                // needed
                if (lock instanceof Ref) {
                    if (lock instanceof InstanceFieldRef) {
                        InstanceFieldRef ifr = (InstanceFieldRef) lock;
                        if (ifr.getBase() instanceof FakeJimpleLocal)
                            lock = reconstruct(b, units, ifr, (tn.entermonitor != null ? tn.entermonitor : tn.beginning), (tn.entermonitor != null));
                    }
                    if (!b.getLocals().contains(lockObj[tn.setNumber]))
                        b.getLocals().add(lockObj[tn.setNumber]);
                    newPrep = Jimple.v().newAssignStmt(lockObj[tn.setNumber], lock);
                    if (tn.wholeMethod)
                        units.insertBeforeNoRedirect(newPrep, firstUnit);
                    else
                        units.insertBefore(newPrep, tn.entermonitor);
                    clo = lockObj[tn.setNumber];
                } else if (lock instanceof Local)
                    clo = (Local) lock;
                else
                    throw new RuntimeException("Unknown type of lock (" + lock + "): expected Ref or Local");
                csr = tn;
                moreLocks = false;
            } else if (tn.group.useLocksets) {
                // adds
                Value lock = getLockFor((EquivalentValue) tn.lockset.get(lockNum));
                // needed
                if (lock instanceof FieldRef) {
                    if (lock instanceof InstanceFieldRef) {
                        InstanceFieldRef ifr = (InstanceFieldRef) lock;
                        if (ifr.getBase() instanceof FakeJimpleLocal)
                            lock = reconstruct(b, units, ifr, (tn.entermonitor != null ? tn.entermonitor : tn.beginning), (tn.entermonitor != null));
                    }
                    // add a local variable for this lock
                    Local lockLocal = Jimple.v().newLocal("locksetObj" + tempNum, RefType.v("java.lang.Object"));
                    tempNum++;
                    b.getLocals().add(lockLocal);
                    // make it refer to the right lock object
                    newPrep = Jimple.v().newAssignStmt(lockLocal, lock);
                    if (tn.entermonitor != null)
                        units.insertBefore(newPrep, tn.entermonitor);
                    else
                        units.insertBeforeNoRedirect(newPrep, tn.beginning);
                    // use it as the lock
                    clo = lockLocal;
                } else if (lock instanceof Local)
                    clo = (Local) lock;
                else
                    throw new RuntimeException("Unknown type of lock (" + lock + "): expected FieldRef or Local");
                if (lockNum + 1 >= tn.lockset.size())
                    moreLocks = false;
                else
                    moreLocks = true;
                if (lockNum > 0) {
                    SynchronizedRegion nsr = new SynchronizedRegion();
                    nsr.beginning = csr.beginning;
                    for (Pair earlyEnd : csr.earlyEnds) {
                        Stmt earlyExitmonitor = (Stmt) earlyEnd.getO2();
                        // <early
                        nsr.earlyEnds.add(new Pair(earlyExitmonitor, null));
                    // exitmonitor,
                    // null>
                    }
                    // last stmt before exception
                    nsr.last = csr.last;
                    // handling
                    if (csr.end != null) {
                        Stmt endExitmonitor = csr.end.getO2();
                        nsr.after = endExitmonitor;
                    }
                    csr = nsr;
                } else
                    csr = tn;
            } else // global lock
            {
                if (!addedLocalLockObj[tn.setNumber])
                    b.getLocals().add(lockObj[tn.setNumber]);
                addedLocalLockObj[tn.setNumber] = true;
                newPrep = Jimple.v().newAssignStmt(lockObj[tn.setNumber], Jimple.v().newStaticFieldRef(globalLockObj[tn.setNumber].makeRef()));
                if (tn.wholeMethod)
                    units.insertBeforeNoRedirect(newPrep, firstUnit);
                else
                    units.insertBefore(newPrep, tn.entermonitor);
                clo = lockObj[tn.setNumber];
                csr = tn;
                moreLocks = false;
            }
            // monitorenter/monitorexit statements with new ones
            if (true) {
                // Remove old prep stmt
                if (csr.prepStmt != null) {
                // units.remove(clr.prepStmt); // seems to trigger bugs
                // in code generation?
                }
                // Reuse old entermonitor or insert new one, and insert prep
                Stmt newEntermonitor = Jimple.v().newEnterMonitorStmt(clo);
                if (csr.entermonitor != null) {
                    units.insertBefore(newEntermonitor, csr.entermonitor);
                    // redirectTraps(b, clr.entermonitor, newEntermonitor);
                    // // EXPERIMENTAL
                    units.remove(csr.entermonitor);
                    csr.entermonitor = newEntermonitor;
                // units.insertBefore(newEntermonitor, newPrep); //
                // already inserted
                // clr.prepStmt = newPrep;
                } else {
                    units.insertBeforeNoRedirect(newEntermonitor, csr.beginning);
                    csr.entermonitor = newEntermonitor;
                // units.insertBefore(newEntermonitor, newPrep); //
                // already inserted
                // clr.prepStmt = newPrep;
                }
                // For each early end, reuse or insert exitmonitor stmt
                List<Pair<Stmt, Stmt>> newEarlyEnds = new ArrayList<Pair<Stmt, Stmt>>();
                for (Pair<Stmt, Stmt> end : csr.earlyEnds) {
                    Stmt earlyEnd = end.getO1();
                    Stmt exitmonitor = end.getO2();
                    Stmt newExitmonitor = Jimple.v().newExitMonitorStmt(clo);
                    if (exitmonitor != null) {
                        if (newPrep != null) {
                            Stmt tmp = (Stmt) newPrep.clone();
                            // seems
                            units.insertBefore(tmp, exitmonitor);
                        // to
                        // avoid
                        // code
                        // generation
                        // bugs?
                        }
                        units.insertBefore(newExitmonitor, exitmonitor);
                        // redirectTraps(b, exitmonitor, newExitmonitor); //
                        // EXPERIMENTAL
                        units.remove(exitmonitor);
                        newEarlyEnds.add(new Pair<Stmt, Stmt>(earlyEnd, newExitmonitor));
                    } else {
                        if (newPrep != null) {
                            Stmt tmp = (Stmt) newPrep.clone();
                            units.insertBefore(tmp, earlyEnd);
                        }
                        units.insertBefore(newExitmonitor, earlyEnd);
                        newEarlyEnds.add(new Pair<Stmt, Stmt>(earlyEnd, newExitmonitor));
                    }
                }
                csr.earlyEnds = newEarlyEnds;
                // If fallthrough end, reuse or insert goto and exit
                if (csr.after != null) {
                    Stmt newExitmonitor = Jimple.v().newExitMonitorStmt(clo);
                    if (csr.end != null) {
                        Stmt exitmonitor = csr.end.getO2();
                        if (newPrep != null) {
                            Stmt tmp = (Stmt) newPrep.clone();
                            units.insertBefore(tmp, exitmonitor);
                        }
                        units.insertBefore(newExitmonitor, exitmonitor);
                        // redirectTraps(b, exitmonitor, newExitmonitor); //
                        // EXPERIMENTAL
                        units.remove(exitmonitor);
                        csr.end = new Pair<Stmt, Stmt>(csr.end.getO1(), newExitmonitor);
                    } else {
                        if (newPrep != null) {
                            Stmt tmp = (Stmt) newPrep.clone();
                            units.insertBefore(tmp, csr.after);
                        }
                        // steal
                        units.insertBefore(newExitmonitor, csr.after);
                        // jumps
                        // to
                        // end,
                        // send
                        // them
                        // to
                        // monitorexit
                        Stmt newGotoStmt = Jimple.v().newGotoStmt(csr.after);
                        units.insertBeforeNoRedirect(newGotoStmt, csr.after);
                        csr.end = new Pair<Stmt, Stmt>(newGotoStmt, newExitmonitor);
                        csr.last = newGotoStmt;
                    }
                }
                // If exceptional end, reuse it, else insert it and traps
                Stmt newExitmonitor = Jimple.v().newExitMonitorStmt(clo);
                if (csr.exceptionalEnd != null) {
                    Stmt exitmonitor = csr.exceptionalEnd.getO2();
                    if (newPrep != null) {
                        Stmt tmp = (Stmt) newPrep.clone();
                        units.insertBefore(tmp, exitmonitor);
                    }
                    units.insertBefore(newExitmonitor, exitmonitor);
                    units.remove(exitmonitor);
                    csr.exceptionalEnd = new Pair<Stmt, Stmt>(csr.exceptionalEnd.getO1(), newExitmonitor);
                } else {
                    // insert after the last end
                    // last end stmt (not same as last
                    Stmt lastEnd = null;
                    // stmt)
                    if (csr.end != null) {
                        lastEnd = csr.end.getO1();
                    } else {
                        for (Pair earlyEnd : csr.earlyEnds) {
                            Stmt end = (Stmt) earlyEnd.getO1();
                            if (lastEnd == null || (units.contains(lastEnd) && units.contains(end) && units.follows(end, lastEnd)))
                                lastEnd = end;
                        }
                    }
                    if (// || !units.contains(clr.last))
                    csr.last == null)
                        // last stmt and last end are
                        csr.last = lastEnd;
                    // the same
                    if (lastEnd == null)
                        throw new RuntimeException("Lock Region has no ends!  Where should we put the exception handling???");
                    // Add throwable
                    Local throwableLocal = Jimple.v().newLocal("throwableLocal" + (throwableNum++), RefType.v("java.lang.Throwable"));
                    b.getLocals().add(throwableLocal);
                    // Add stmts
                    Stmt newCatch = Jimple.v().newIdentityStmt(throwableLocal, Jimple.v().newCaughtExceptionRef());
                    if (csr.last == null)
                        throw new RuntimeException("WHY IS clr.last NULL???");
                    if (newCatch == null)
                        throw new RuntimeException("WHY IS newCatch NULL???");
                    units.insertAfter(newCatch, csr.last);
                    units.insertAfter(newExitmonitor, newCatch);
                    Stmt newThrow = Jimple.v().newThrowStmt(throwableLocal);
                    units.insertAfter(newThrow, newExitmonitor);
                    // Add traps
                    SootClass throwableClass = Scene.v().loadClassAndSupport("java.lang.Throwable");
                    b.getTraps().addFirst(Jimple.v().newTrap(throwableClass, newExitmonitor, newThrow, newCatch));
                    b.getTraps().addFirst(Jimple.v().newTrap(throwableClass, csr.beginning, lastEnd, newCatch));
                    csr.exceptionalEnd = new Pair<Stmt, Stmt>(newThrow, newExitmonitor);
                }
            }
            lockNum++;
        }
        // deal with waits and notifys
        {
            for (Unit uNotify : tn.notifys) {
                Stmt sNotify = (Stmt) uNotify;
                Stmt newNotify = Jimple.v().newInvokeStmt(Jimple.v().newVirtualInvokeExpr(clo, sNotify.getInvokeExpr().getMethodRef().declaringClass().getMethod("void notifyAll()").makeRef(), Collections.EMPTY_LIST));
                if (newPrep != null) {
                    Stmt tmp = (Stmt) newPrep.clone();
                    units.insertBefore(tmp, sNotify);
                    units.insertBefore(newNotify, tmp);
                } else
                    units.insertBefore(newNotify, sNotify);
                redirectTraps(b, sNotify, newNotify);
                units.remove(sNotify);
            }
            // Replace base object of calls to wait with appropriate lockobj
            for (Unit uWait : tn.waits) {
                Stmt sWait = (Stmt) uWait;
                // WHAT
                ((InstanceInvokeExpr) sWait.getInvokeExpr()).setBase(clo);
                // LOCKS???
                if (newPrep != null)
                    units.insertBefore((Stmt) newPrep.clone(), sWait);
            }
        }
    }
}
Also used : EquivalentValue(soot.EquivalentValue) ArrayList(java.util.ArrayList) Unit(soot.Unit) Stmt(soot.jimple.Stmt) RefType(soot.RefType) Iterator(java.util.Iterator) InstanceFieldRef(soot.jimple.InstanceFieldRef) JimpleBody(soot.jimple.JimpleBody) Pair(soot.toolkits.scalar.Pair) FieldRef(soot.jimple.FieldRef) InstanceFieldRef(soot.jimple.InstanceFieldRef) StaticFieldRef(soot.jimple.StaticFieldRef) FakeJimpleLocal(soot.jimple.toolkits.infoflow.FakeJimpleLocal) Local(soot.Local) SootClass(soot.SootClass) ArrayRef(soot.jimple.ArrayRef) Ref(soot.jimple.Ref) FieldRef(soot.jimple.FieldRef) InstanceFieldRef(soot.jimple.InstanceFieldRef) StaticFieldRef(soot.jimple.StaticFieldRef) EquivalentValue(soot.EquivalentValue) Value(soot.Value) SootMethod(soot.SootMethod) SootField(soot.SootField) FakeJimpleLocal(soot.jimple.toolkits.infoflow.FakeJimpleLocal)

Example 10 with Pair

use of soot.toolkits.scalar.Pair in project soot by Sable.

the class StoreChainOptimizer method internalTransform.

@Override
protected void internalTransform(Body b, String phaseName, Map<String, String> options) {
    // We keep track of all the stored values
    Map<Local, Pair<Unit, Unit>> stores = new HashMap<Local, Pair<Unit, Unit>>();
    Set<Unit> toRemove = new HashSet<Unit>();
    Unit lastPush = null;
    for (Unit u : b.getUnits()) {
        // If we can jump here from somewhere, do not modify this code
        if (!u.getBoxesPointingToThis().isEmpty()) {
            stores.clear();
            lastPush = null;
        } else // Emulate pushing stuff on the stack
        if (u instanceof PushInst) {
            lastPush = u;
        } else if (u instanceof StoreInst && lastPush != null) {
            StoreInst si = (StoreInst) u;
            Pair<Unit, Unit> pushStorePair = stores.get(si.getLocal());
            if (pushStorePair != null) {
                // We can remove the push and the store
                toRemove.add(pushStorePair.getO1());
                toRemove.add(pushStorePair.getO2());
            }
            stores.put(si.getLocal(), new Pair<Unit, Unit>(lastPush, u));
        } else {
            // We're outside of the trivial initialization chain
            stores.clear();
            lastPush = null;
        }
    }
    b.getUnits().removeAll(toRemove);
}
Also used : PushInst(soot.baf.PushInst) StoreInst(soot.baf.StoreInst) HashMap(java.util.HashMap) Local(soot.Local) Unit(soot.Unit) Pair(soot.toolkits.scalar.Pair) HashSet(java.util.HashSet)

Aggregations

Pair (soot.toolkits.scalar.Pair)11 SootMethod (soot.SootMethod)6 Value (soot.Value)5 InvokeExpr (soot.jimple.InvokeExpr)5 Stmt (soot.jimple.Stmt)5 ArrayList (java.util.ArrayList)4 Local (soot.Local)4 RefType (soot.RefType)4 Unit (soot.Unit)4 Set (java.util.Set)3 SootClass (soot.SootClass)3 Type (soot.Type)3 NewExpr (soot.jimple.NewExpr)3 VirtualInvokeExpr (soot.jimple.VirtualInvokeExpr)3 AllocNode (soot.jimple.spark.pag.AllocNode)3 Node (soot.jimple.spark.pag.Node)3 VarNode (soot.jimple.spark.pag.VarNode)3 FlowFunction (heros.FlowFunction)2 FlowFunctions (heros.FlowFunctions)2 HashSet (java.util.HashSet)2