Search in sources :

Example 11 with Chain

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

the class LocalNameStandardizer method internalTransform.

@Override
protected void internalTransform(Body body, String phaseName, Map<String, String> options) {
    boolean onlyStackName = PhaseOptions.getBoolean(options, "only-stack-locals");
    boolean sortLocals = PhaseOptions.getBoolean(options, "sort-locals");
    final BooleanType booleanType = BooleanType.v();
    final ByteType byteType = ByteType.v();
    final ShortType shortType = ShortType.v();
    final CharType charType = CharType.v();
    final IntType intType = IntType.v();
    final LongType longType = LongType.v();
    final DoubleType doubleType = DoubleType.v();
    final FloatType floatType = FloatType.v();
    final ErroneousType erroneousType = ErroneousType.v();
    final UnknownType unknownType = UnknownType.v();
    final StmtAddressType stmtAddressType = StmtAddressType.v();
    final NullType nullType = NullType.v();
    // Change the names to the standard forms now.
    {
        int objectCount = 0;
        int intCount = 0;
        int longCount = 0;
        int floatCount = 0;
        int doubleCount = 0;
        int addressCount = 0;
        int errorCount = 0;
        int nullCount = 0;
        /* The goal of this option is to ensure that local ordering remains
             * consistent between different iterations of soot. This helps to ensure
             * things like stable string representations of instructions and stable
             * jimple representations of a methods body when soot is used to load
             * the same code in different iterations.
             * 
             * First sorts the locals alphabetically by the string representation of
             * their type. Then if there are two locals with the same type, it uses
             * the only other source of structurally stable information (i.e. the 
             * instructions themselves) to produce an ordering for the locals
             * that remains consistent between different soot instances. It achieves
             * this by determining the position of a local's first occurrence in the 
             * instruction's list of definition statements. This position is then used
             * to sort the locals with the same type in an ascending order. 
             * 
             * The only times that this may not produce a consistent ordering for the 
             * locals between different soot instances is if a local is never defined in
             * the instructions or if the instructions themselves are changed in some way
             * that effects the ordering of the locals. In the first case, if a local is 
             * never defined, the other jimple body phases will remove this local as it is 
             * unused. As such, all we have to do is rerun this LocalNameStandardizer after
             * all other jimple body phases to eliminate any ambiguity introduced by these
             * phases and by the removed unused locals. In the second case, if the instructions
             * themselves changed then the user would have had to intentionally told soot to
             * modify the instructions of the code. Otherwise, the instructions would not have
             * changed because we assume the instructions to always be structurally stable
             * between different instances of soot. As such, in this instance, the user should
             * not be expecting soot to produce the same output as the input and thus the
             * ordering of the locals does not matter.
             */
        if (sortLocals) {
            Chain<Local> locals = body.getLocals();
            final List<ValueBox> defs = body.getDefBoxes();
            ArrayList<Local> sortedLocals = new ArrayList<Local>(locals);
            Collections.sort(sortedLocals, new Comparator<Local>() {

                private Map<Local, Integer> firstOccuranceCache = new HashMap<Local, Integer>();

                @Override
                public int compare(Local arg0, Local arg1) {
                    int ret = arg0.getType().toString().compareTo(arg1.getType().toString());
                    if (ret == 0) {
                        ret = Integer.compare(getFirstOccurance(arg0), getFirstOccurance(arg1));
                    }
                    return ret;
                }

                private int getFirstOccurance(Local l) {
                    Integer cur = firstOccuranceCache.get(l);
                    if (cur != null) {
                        return cur;
                    } else {
                        int count = 0;
                        int first = -1;
                        for (ValueBox vb : defs) {
                            Value v = vb.getValue();
                            if (v instanceof Local && v.equals(l)) {
                                first = count;
                                break;
                            }
                            count++;
                        }
                        firstOccuranceCache.put(l, first);
                        return first;
                    }
                }
            });
            locals.clear();
            locals.addAll(sortedLocals);
        }
        for (Local l : body.getLocals()) {
            String prefix = "";
            if (l.getName().startsWith("$"))
                prefix = "$";
            else {
                if (onlyStackName)
                    continue;
            }
            final Type type = l.getType();
            if (type.equals(booleanType))
                l.setName(prefix + "z" + intCount++);
            else if (type.equals(byteType))
                l.setName(prefix + "b" + longCount++);
            else if (type.equals(shortType))
                l.setName(prefix + "s" + longCount++);
            else if (type.equals(charType))
                l.setName(prefix + "c" + longCount++);
            else if (type.equals(intType))
                l.setName(prefix + "i" + longCount++);
            else if (type.equals(longType))
                l.setName(prefix + "l" + longCount++);
            else if (type.equals(doubleType))
                l.setName(prefix + "d" + doubleCount++);
            else if (type.equals(floatType))
                l.setName(prefix + "f" + floatCount++);
            else if (type.equals(stmtAddressType))
                l.setName(prefix + "a" + addressCount++);
            else if (type.equals(erroneousType) || type.equals(unknownType)) {
                l.setName(prefix + "e" + errorCount++);
            } else if (type.equals(nullType))
                l.setName(prefix + "n" + nullCount++);
            else
                l.setName(prefix + "r" + objectCount++);
        }
    }
}
Also used : Chain(soot.util.Chain) LongType(soot.LongType) ArrayList(java.util.ArrayList) ByteType(soot.ByteType) IntType(soot.IntType) FloatType(soot.FloatType) Comparator(java.util.Comparator) ErroneousType(soot.ErroneousType) ArrayList(java.util.ArrayList) List(java.util.List) ShortType(soot.ShortType) BooleanType(soot.BooleanType) Local(soot.Local) UnknownType(soot.UnknownType) UnknownType(soot.UnknownType) DoubleType(soot.DoubleType) FloatType(soot.FloatType) IntType(soot.IntType) ShortType(soot.ShortType) CharType(soot.CharType) LongType(soot.LongType) NullType(soot.NullType) StmtAddressType(soot.StmtAddressType) BooleanType(soot.BooleanType) ErroneousType(soot.ErroneousType) ByteType(soot.ByteType) Type(soot.Type) DoubleType(soot.DoubleType) ValueBox(soot.ValueBox) Value(soot.Value) CharType(soot.CharType) StmtAddressType(soot.StmtAddressType) NullType(soot.NullType) HashMap(java.util.HashMap) Map(java.util.Map)

Example 12 with Chain

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

the class ExitStmt method addAuxiliaryExceptionalEdges.

/**
 * Add an exceptional flow edge for each handler from the corresponding
 * auxiliary nop node to the beginning of the handler.
 */
protected void addAuxiliaryExceptionalEdges() {
    // Do some preparation for each trap in the method
    for (Iterator<Trap> trapIt = body.getTraps().iterator(); trapIt.hasNext(); ) {
        Trap trap = trapIt.next();
        /**
         * Find the real header of this handler block
         */
        Unit handler = trap.getHandlerUnit();
        Unit pred = handler;
        while (this.unitToPreds.get(pred).size() > 0) pred = this.unitToPreds.get(pred).get(0);
        handler2header.put(handler, pred);
        /**
         ********
         */
        /*
			 * Keep this here for possible future changes.
			 */
        /*
			 * GuardedBlock gb = new GuardedBlock(trap.getBeginUnit(),
			 * trap.getEndUnit()); Unit ehnop; if(try2nop.containsKey(gb)) ehnop
			 * = try2nop.get(gb); else { ehnop = new EHNopStmt();
			 * try2nop.put(gb, ehnop); }
			 */
        Unit ehnop;
        if (try2nop.containsKey(trap.getBeginUnit()))
            ehnop = try2nop.get(trap.getBeginUnit());
        else {
            ehnop = new EHNopStmt();
            try2nop.put(trap.getBeginUnit(), ehnop);
        }
    }
    // Only add a nop once
    Hashtable<Unit, Boolean> nop2added = new Hashtable<Unit, Boolean>();
    // Now actually add the edge
    AddExceptionalEdge: for (Iterator<Trap> trapIt = body.getTraps().iterator(); trapIt.hasNext(); ) {
        Trap trap = trapIt.next();
        Unit b = trap.getBeginUnit();
        Unit handler = trap.getHandlerUnit();
        handler = handler2header.get(handler);
        if (this.unitToPreds.containsKey(handler)) {
            List<Unit> handlerPreds = this.unitToPreds.get(handler);
            for (Iterator<Unit> preditr = handlerPreds.iterator(); preditr.hasNext(); ) if (try2nop.containsValue(preditr.next()))
                continue AddExceptionalEdge;
        } else
            continue;
        // GuardedBlock gb = new GuardedBlock(b, e);
        Unit ehnop = try2nop.get(b);
        if (!nop2added.containsKey(ehnop)) {
            List<Unit> predsOfB = getPredsOf(b);
            List<Unit> predsOfehnop = new ArrayList<Unit>(predsOfB);
            for (Unit a : predsOfB) {
                List<Unit> succsOfA = this.unitToSuccs.get(a);
                if (succsOfA == null) {
                    succsOfA = new ArrayList<Unit>();
                    this.unitToSuccs.put(a, succsOfA);
                } else
                    succsOfA.remove(b);
                succsOfA.add((Unit) ehnop);
            }
            predsOfB.clear();
            predsOfB.add((Unit) ehnop);
            this.unitToPreds.put((Unit) ehnop, predsOfehnop);
        }
        List<Unit> succsOfehnop = this.unitToSuccs.get(ehnop);
        if (succsOfehnop == null) {
            succsOfehnop = new ArrayList<Unit>();
            this.unitToSuccs.put(ehnop, succsOfehnop);
        }
        if (!succsOfehnop.contains(b))
            succsOfehnop.add(b);
        succsOfehnop.add(handler);
        List<Unit> predsOfhandler = this.unitToPreds.get(handler);
        if (predsOfhandler == null) {
            predsOfhandler = new ArrayList<Unit>();
            this.unitToPreds.put(handler, predsOfhandler);
        }
        predsOfhandler.add((Unit) ehnop);
        Chain<Unit> units = body.getUnits().getNonPatchingChain();
        if (!units.contains(ehnop))
            units.insertBefore((Unit) ehnop, b);
        nop2added.put(ehnop, Boolean.TRUE);
    }
}
Also used : Chain(soot.util.Chain) Hashtable(java.util.Hashtable) Iterator(java.util.Iterator) ArrayList(java.util.ArrayList) Trap(soot.Trap) ArrayList(java.util.ArrayList) List(java.util.List) Unit(soot.Unit)

Example 13 with Chain

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

the class DavaStaticBlockCleaner method staticBlockInlining.

// invoked by the PackManager
public void staticBlockInlining(SootClass sootClass) {
    this.sootClass = sootClass;
    // the clinit method gets converted into the static block which could initialize the final variable
    if (!sootClass.declaresMethod("void <clinit>()")) {
        // System.out.println("no clinit");
        return;
    }
    SootMethod clinit = sootClass.getMethod("void <clinit>()");
    // retireve the active body
    if (!clinit.hasActiveBody())
        throw new RuntimeException("method " + clinit.getName() + " has no active body!");
    Body clinitBody = clinit.getActiveBody();
    Chain units = ((DavaBody) clinitBody).getUnits();
    if (units.size() != 1) {
        throw new RuntimeException("DavaBody AST doesn't have single root.");
    }
    ASTNode AST = (ASTNode) units.getFirst();
    if (!(AST instanceof ASTMethodNode))
        throw new RuntimeException("Starting node of DavaBody AST is not an ASTMethodNode");
    // running methodCallFinder on the Clinit method
    AST.apply(new MethodCallFinder(this));
}
Also used : Chain(soot.util.Chain) ASTNode(soot.dava.internal.AST.ASTNode) SootMethod(soot.SootMethod) ASTMethodNode(soot.dava.internal.AST.ASTMethodNode) Body(soot.Body)

Example 14 with Chain

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

the class BuildIntermediateAppClasses method internalTransform.

protected void internalTransform(String phaseName, Map<String, String> options) {
    if (output) {
        out.println("Building Intermediate Classes...");
    }
    BodyBuilder.retrieveAllBodies();
    // iterate through application classes, build intermediate classes
    Iterator<SootClass> it = Scene.v().getApplicationClasses().snapshotIterator();
    while (it.hasNext()) {
        List<SootMethod> initMethodsToRewrite = new ArrayList<>();
        Map<String, SootMethod> methodsToAdd = new HashMap<>();
        SootClass sc = it.next();
        SootClass originalSuperclass = sc.getSuperclass();
        if (output) {
            out.println("Processing " + sc.getName() + " with super " + originalSuperclass.getName());
        }
        Iterator<SootMethod> methodIterator = sc.methodIterator();
        while (methodIterator.hasNext()) {
            SootMethod method = methodIterator.next();
            if (!method.isConcrete()) {
                continue;
            }
            try {
                method.getActiveBody();
            } catch (Exception e) {
                if (method.retrieveActiveBody() == null)
                    throw new RuntimeException(method.getSignature() + " has no body. This was not expected dude.");
            }
            String subSig = method.getSubSignature();
            if (subSig.equals("void main(java.lang.String[])") && method.isPublic() && method.isStatic()) {
                // skip the main method - it needs to be named 'main'
                continue;
            } else if (subSig.indexOf("init>(") > 0) {
                if (subSig.startsWith("void <init>(")) {
                    initMethodsToRewrite.add(method);
                }
                // skip constructors, just add for rewriting at the end
                continue;
            } else {
                Scene.v().releaseActiveHierarchy();
                findAccessibleInSuperClassesBySubSig(sc, subSig).ifPresent(m -> methodsToAdd.put(subSig, m));
            }
        }
        if (methodsToAdd.size() > 0) {
            final String fullName = ClassRenamer.v().getNewName(ClassRenamer.getPackageName(sc.getName()), null);
            if (output) {
                out.println("\tBuilding " + fullName);
            }
            // make non-final soot class
            SootClass mediatingClass = new SootClass(fullName, sc.getModifiers() & (~Modifier.FINAL));
            Main.IntermediateAppClasses.add(mediatingClass);
            mediatingClass.setSuperclass(originalSuperclass);
            Scene.v().addClass(mediatingClass);
            mediatingClass.setApplicationClass();
            mediatingClass.setInScene(true);
            ThisRef thisRef = new ThisRef(mediatingClass.getType());
            for (String subSig : methodsToAdd.keySet()) {
                SootMethod originalSuperclassMethod = methodsToAdd.get(subSig);
                List<Type> paramTypes = originalSuperclassMethod.getParameterTypes();
                Type returnType = originalSuperclassMethod.getReturnType();
                List<SootClass> exceptions = originalSuperclassMethod.getExceptions();
                int modifiers = originalSuperclassMethod.getModifiers() & ~Modifier.ABSTRACT & ~Modifier.NATIVE;
                SootMethod newMethod;
                {
                    // build new junk method to call original method
                    String newMethodName = MethodRenamer.v().getNewName();
                    newMethod = Scene.v().makeSootMethod(newMethodName, paramTypes, returnType, modifiers, exceptions);
                    mediatingClass.addMethod(newMethod);
                    Body body = Jimple.v().newBody(newMethod);
                    newMethod.setActiveBody(body);
                    Chain<Local> locals = body.getLocals();
                    PatchingChain<Unit> units = body.getUnits();
                    BodyBuilder.buildThisLocal(units, thisRef, locals);
                    BodyBuilder.buildParameterLocals(units, locals, paramTypes);
                    if (returnType instanceof VoidType) {
                        units.add(Jimple.v().newReturnVoidStmt());
                    } else if (returnType instanceof PrimType) {
                        units.add(Jimple.v().newReturnStmt(IntConstant.v(0)));
                    } else {
                        units.add(Jimple.v().newReturnStmt(NullConstant.v()));
                    }
                    newmethods++;
                }
                // end build new junk method to call original method
                {
                    // build copy of old method
                    newMethod = Scene.v().makeSootMethod(originalSuperclassMethod.getName(), paramTypes, returnType, modifiers, exceptions);
                    mediatingClass.addMethod(newMethod);
                    Body body = Jimple.v().newBody(newMethod);
                    newMethod.setActiveBody(body);
                    Chain<Local> locals = body.getLocals();
                    PatchingChain<Unit> units = body.getUnits();
                    Local ths = BodyBuilder.buildThisLocal(units, thisRef, locals);
                    List<Local> args = BodyBuilder.buildParameterLocals(units, locals, paramTypes);
                    SootMethodRef superclassMethodRef = originalSuperclassMethod.makeRef();
                    if (returnType instanceof VoidType) {
                        units.add(Jimple.v().newInvokeStmt(Jimple.v().newSpecialInvokeExpr(ths, superclassMethodRef, args)));
                        units.add(Jimple.v().newReturnVoidStmt());
                    } else {
                        Local loc = Jimple.v().newLocal("retValue", returnType);
                        body.getLocals().add(loc);
                        units.add(Jimple.v().newAssignStmt(loc, Jimple.v().newSpecialInvokeExpr(ths, superclassMethodRef, args)));
                        units.add(Jimple.v().newReturnStmt(loc));
                    }
                    newmethods++;
                }
            // end build copy of old method
            }
            sc.setSuperclass(mediatingClass);
            // rewrite class init methods to call the proper superclass inits
            int i = initMethodsToRewrite.size();
            while (i-- > 0) {
                SootMethod im = initMethodsToRewrite.remove(i);
                Body b = im.getActiveBody();
                Local thisLocal = b.getThisLocal();
                Iterator<Unit> uIt = b.getUnits().snapshotIterator();
                while (uIt.hasNext()) {
                    for (ValueBox valueBox : uIt.next().getUseBoxes()) {
                        Value v = valueBox.getValue();
                        if (v instanceof SpecialInvokeExpr) {
                            SpecialInvokeExpr sie = (SpecialInvokeExpr) v;
                            SootMethodRef smr = sie.getMethodRef();
                            if (sie.getBase().equivTo(thisLocal) && smr.declaringClass().getName().equals(originalSuperclass.getName()) && smr.getSubSignature().getString().startsWith("void " + constructorName)) {
                                SootMethod newSuperInit;
                                if (!mediatingClass.declaresMethod(constructorName, smr.parameterTypes())) {
                                    List<Type> paramTypes = smr.parameterTypes();
                                    newSuperInit = Scene.v().makeSootMethod(constructorName, paramTypes, smr.returnType());
                                    mediatingClass.addMethod(newSuperInit);
                                    JimpleBody body = Jimple.v().newBody(newSuperInit);
                                    newSuperInit.setActiveBody(body);
                                    PatchingChain<Unit> initUnits = body.getUnits();
                                    Collection<Local> locals = body.getLocals();
                                    Local ths = BodyBuilder.buildThisLocal(initUnits, thisRef, locals);
                                    List<Local> args = BodyBuilder.buildParameterLocals(initUnits, locals, paramTypes);
                                    initUnits.add(Jimple.v().newInvokeStmt(Jimple.v().newSpecialInvokeExpr(ths, smr, args)));
                                    initUnits.add(Jimple.v().newReturnVoidStmt());
                                } else {
                                    newSuperInit = mediatingClass.getMethod(constructorName, smr.parameterTypes());
                                }
                                sie.setMethodRef(newSuperInit.makeRef());
                            }
                        }
                    }
                }
            }
        // end of rewrite class init methods to call the proper superclass inits
        }
    }
    newclasses = Main.IntermediateAppClasses.size();
    Scene.v().releaseActiveHierarchy();
    Scene.v().getActiveHierarchy();
    Scene.v().setFastHierarchy(new FastHierarchy());
}
Also used : Body(soot.Body) ThisRef(soot.jimple.ThisRef) PatchingChain(soot.PatchingChain) Main(soot.jbco.Main) BodyBuilder(soot.jbco.util.BodyBuilder) HashMap(java.util.HashMap) NullConstant(soot.jimple.NullConstant) FastHierarchy(soot.FastHierarchy) Modifier(soot.Modifier) SootMethodRef(soot.SootMethodRef) ArrayList(java.util.ArrayList) SootMethod(soot.SootMethod) IJbcoTransform(soot.jbco.IJbcoTransform) Chain(soot.util.Chain) Map(java.util.Map) Local(soot.Local) Scene(soot.Scene) IntConstant(soot.jimple.IntConstant) Value(soot.Value) SpecialInvokeExpr(soot.jimple.SpecialInvokeExpr) Iterator(java.util.Iterator) Unit(soot.Unit) Collection(java.util.Collection) Jimple(soot.jimple.Jimple) SootClass(soot.SootClass) ValueBox(soot.ValueBox) Type(soot.Type) List(java.util.List) JimpleBody(soot.jimple.JimpleBody) SootMethod.constructorName(soot.SootMethod.constructorName) PrimType(soot.PrimType) VoidType(soot.VoidType) Hierarchy(soot.Hierarchy) Optional(java.util.Optional) SceneTransformer(soot.SceneTransformer) VoidType(soot.VoidType) PatchingChain(soot.PatchingChain) Chain(soot.util.Chain) HashMap(java.util.HashMap) SpecialInvokeExpr(soot.jimple.SpecialInvokeExpr) ArrayList(java.util.ArrayList) Unit(soot.Unit) PrimType(soot.PrimType) ArrayList(java.util.ArrayList) List(java.util.List) Body(soot.Body) JimpleBody(soot.jimple.JimpleBody) JimpleBody(soot.jimple.JimpleBody) PatchingChain(soot.PatchingChain) SootMethodRef(soot.SootMethodRef) Local(soot.Local) SootClass(soot.SootClass) Type(soot.Type) PrimType(soot.PrimType) VoidType(soot.VoidType) FastHierarchy(soot.FastHierarchy) ThisRef(soot.jimple.ThisRef) ValueBox(soot.ValueBox) Value(soot.Value) SootMethod(soot.SootMethod)

Example 15 with Chain

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

the class SootUtil method hasRecursiveField.

public static boolean hasRecursiveField(SootClass sootClass) {
    Chain fields = sootClass.getFields();
    for (Iterator iter = fields.iterator(); iter.hasNext(); ) {
        SootField sootField = (SootField) iter.next();
        Type type = sootField.getType();
        if (type instanceof RefType) {
            RefType refType = (RefType) type;
            SootClass sootClass2 = refType.getSootClass();
            if (sootClass == sootClass2) {
                return true;
            }
        }
    }
    return false;
}
Also used : RefType(soot.RefType) Chain(soot.util.Chain) RefType(soot.RefType) ArrayType(soot.ArrayType) Type(soot.Type) Iterator(java.util.Iterator) 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