Search in sources :

Example 51 with Body

use of soot.Body in project soot by Sable.

the class GroupIntPair method emitMethodBody.

@Override
protected void emitMethodBody(SootMethod method) {
    if (Options.v().time())
        Timers.v().buildJasminTimer.end();
    Body activeBody = method.getActiveBody();
    if (!(activeBody instanceof BafBody)) {
        if (activeBody instanceof JimpleBody) {
            if (Options.v().verbose()) {
                logger.debug("Was expecting Baf body for " + method + " but found a Jimple body. Will convert body to Baf on the fly.");
            }
            activeBody = PackManager.v().convertJimpleBodyToBaf(method);
        } else
            throw new RuntimeException("method: " + method.getName() + " has an invalid active body!");
    }
    BafBody body = (BafBody) activeBody;
    if (body == null)
        throw new RuntimeException("method: " + method.getName() + " has no active body!");
    if (Options.v().time())
        Timers.v().buildJasminTimer.start();
    Chain<Unit> instList = body.getUnits();
    int stackLimitIndex = -1;
    subroutineToReturnAddressSlot = new HashMap<Unit, Integer>(10, 0.7f);
    // Determine the unitToLabel map
    {
        unitToLabel = new HashMap<Unit, String>(instList.size() * 2 + 1, 0.7f);
        labelCount = 0;
        for (UnitBox uBox : body.getUnitBoxes(true)) {
            // Assign a label for each statement reference
            {
                InstBox box = (InstBox) uBox;
                if (!unitToLabel.containsKey(box.getUnit()))
                    unitToLabel.put(box.getUnit(), "label" + labelCount++);
            }
        }
    }
    // Emit the exceptions, recording the Units at the beginning
    // of handlers so that later on we can recognize blocks that
    // begin with an exception on the stack.
    Set<Unit> handlerUnits = new ArraySet<Unit>(body.getTraps().size());
    {
        for (Trap trap : body.getTraps()) {
            handlerUnits.add(trap.getHandlerUnit());
            if (trap.getBeginUnit() != trap.getEndUnit()) {
                emit(".catch " + slashify(trap.getException().getName()) + " from " + unitToLabel.get(trap.getBeginUnit()) + " to " + unitToLabel.get(trap.getEndUnit()) + " using " + unitToLabel.get(trap.getHandlerUnit()));
            }
        }
    }
    // Determine where the locals go
    {
        int localCount = 0;
        int[] paramSlots = new int[method.getParameterCount()];
        int thisSlot = 0;
        Set<Local> assignedLocals = new HashSet<Local>();
        localToSlot = new HashMap<Local, Integer>(body.getLocalCount() * 2 + 1, 0.7f);
        // assignColorsToLocals(body);
        // Determine slots for 'this' and parameters
        {
            if (!method.isStatic()) {
                thisSlot = 0;
                localCount++;
            }
            for (int i = 0; i < method.getParameterCount(); i++) {
                paramSlots[i] = localCount;
                localCount += sizeOfType(method.getParameterType(i));
            }
        }
        // Handle identity statements
        {
            for (Unit u : instList) {
                Inst s = (Inst) u;
                if (s instanceof IdentityInst && ((IdentityInst) s).getLeftOp() instanceof Local) {
                    Local l = (Local) ((IdentityInst) s).getLeftOp();
                    IdentityRef identity = (IdentityRef) ((IdentityInst) s).getRightOp();
                    int slot = 0;
                    if (identity instanceof ThisRef) {
                        if (method.isStatic())
                            throw new RuntimeException("Attempting to use 'this' in static method");
                        slot = thisSlot;
                    } else if (identity instanceof ParameterRef)
                        slot = paramSlots[((ParameterRef) identity).getIndex()];
                    else {
                        // Exception ref. Skip over this
                        continue;
                    }
                    localToSlot.put(l, new Integer(slot));
                    assignedLocals.add(l);
                }
            }
        }
        // Assign the rest of the locals
        {
            for (Local local : body.getLocals()) {
                if (assignedLocals.add(local)) {
                    localToSlot.put(local, new Integer(localCount));
                    localCount += sizeOfType(local.getType());
                }
            }
            if (!Modifier.isNative(method.getModifiers()) && !Modifier.isAbstract(method.getModifiers())) {
                emit("    .limit stack ?");
                stackLimitIndex = code.size() - 1;
                emit("    .limit locals " + localCount);
            }
        }
    }
    // Emit code in one pass
    {
        isEmittingMethodCode = true;
        maxStackHeight = 0;
        isNextGotoAJsr = false;
        for (Unit u : instList) {
            Inst s = (Inst) u;
            if (unitToLabel.containsKey(s))
                emit(unitToLabel.get(s) + ":");
            // emit this statement
            {
                emitInst(s);
            }
        }
        isEmittingMethodCode = false;
        // calculate max stack height
        {
            maxStackHeight = 0;
            if (activeBody.getUnits().size() != 0) {
                BlockGraph blockGraph = new BriefBlockGraph(activeBody);
                List<Block> blocks = blockGraph.getBlocks();
                if (blocks.size() != 0) {
                    // set the stack height of the entry points
                    List<Block> entryPoints = ((DirectedGraph<Block>) blockGraph).getHeads();
                    for (Block entryBlock : entryPoints) {
                        Integer initialHeight;
                        if (handlerUnits.contains(entryBlock.getHead())) {
                            initialHeight = new Integer(1);
                        } else {
                            initialHeight = new Integer(0);
                        }
                        if (blockToStackHeight == null) {
                            blockToStackHeight = new HashMap<Block, Integer>();
                        }
                        blockToStackHeight.put(entryBlock, initialHeight);
                        if (blockToLogicalStackHeight == null) {
                            blockToLogicalStackHeight = new HashMap<Block, Integer>();
                        }
                        blockToLogicalStackHeight.put(entryBlock, initialHeight);
                    }
                    // entryPoints list as roots
                    for (Block nextBlock : entryPoints) {
                        calculateStackHeight(nextBlock);
                        calculateLogicalStackHeightCheck(nextBlock);
                    }
                }
            }
        }
        if (!Modifier.isNative(method.getModifiers()) && !Modifier.isAbstract(method.getModifiers()))
            code.set(stackLimitIndex, "    .limit stack " + maxStackHeight);
    }
    // emit code attributes
    {
        for (Tag t : body.getTags()) {
            if (t instanceof JasminAttribute) {
                emit(".code_attribute " + t.getName() + " \"" + ((JasminAttribute) t).getJasminValue(unitToLabel) + "\"");
            }
        }
    }
}
Also used : HashSet(java.util.HashSet) ArraySet(soot.util.ArraySet) Set(java.util.Set) HashMap(java.util.HashMap) Unit(soot.Unit) BriefBlockGraph(soot.toolkits.graph.BriefBlockGraph) BlockGraph(soot.toolkits.graph.BlockGraph) BriefBlockGraph(soot.toolkits.graph.BriefBlockGraph) DirectedGraph(soot.toolkits.graph.DirectedGraph) Body(soot.Body) UnitBox(soot.UnitBox) ArraySet(soot.util.ArraySet) Local(soot.Local) Trap(soot.Trap) JasminAttribute(soot.tagkit.JasminAttribute) Block(soot.toolkits.graph.Block) Tag(soot.tagkit.Tag) LineNumberTag(soot.tagkit.LineNumberTag)

Example 52 with Body

use of soot.Body in project soot by Sable.

the class DavaBody method clone.

public Object clone() {
    Body b = Dava.v().newBody(getMethod());
    b.importBodyContentsFrom(this);
    return b;
}
Also used : GrimpBody(soot.grimp.GrimpBody) Body(soot.Body)

Example 53 with Body

use of soot.Body 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 54 with Body

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

use of soot.Body in project soot by Sable.

the class CollectConstants method addInitializingValue.

private void addInitializingValue(SootClass sc, SootField f, Constant constant) {
    if (constant instanceof NullConstant) {
        return;
    } else if (constant instanceof IntConstant) {
        if (((IntConstant) constant).value == 0)
            return;
    } else if (constant instanceof LongConstant) {
        if (((LongConstant) constant).value == 0)
            return;
    } else if (constant instanceof StringConstant) {
        if (((StringConstant) constant).value == null)
            return;
    } else if (constant instanceof DoubleConstant) {
        if (((DoubleConstant) constant).value == 0)
            return;
    } else if (constant instanceof FloatConstant) {
        if (((FloatConstant) constant).value == 0)
            return;
    }
    Body b;
    boolean newInit = false;
    if (!sc.declaresMethodByName(SootMethod.staticInitializerName)) {
        SootMethod m = Scene.v().makeSootMethod(SootMethod.staticInitializerName, emptyList(), VoidType.v(), Modifier.STATIC);
        sc.addMethod(m);
        b = Jimple.v().newBody(m);
        m.setActiveBody(b);
        newInit = true;
    } else {
        SootMethod m = sc.getMethodByName(SootMethod.staticInitializerName);
        if (!m.hasActiveBody()) {
            b = Jimple.v().newBody(m);
            m.setActiveBody(b);
            newInit = true;
        } else {
            b = m.getActiveBody();
        }
    }
    PatchingChain<Unit> units = b.getUnits();
    units.addFirst(Jimple.v().newAssignStmt(Jimple.v().newStaticFieldRef(f.makeRef()), constant));
    if (newInit)
        units.addLast(Jimple.v().newReturnVoidStmt());
}
Also used : LongConstant(soot.jimple.LongConstant) DoubleConstant(soot.jimple.DoubleConstant) FloatConstant(soot.jimple.FloatConstant) NullConstant(soot.jimple.NullConstant) IntConstant(soot.jimple.IntConstant) SootMethod(soot.SootMethod) StringConstant(soot.jimple.StringConstant) Unit(soot.Unit) Body(soot.Body)

Aggregations

Body (soot.Body)57 Unit (soot.Unit)37 SootMethod (soot.SootMethod)32 Local (soot.Local)20 SootClass (soot.SootClass)19 Value (soot.Value)15 InvokeExpr (soot.jimple.InvokeExpr)14 StaticInvokeExpr (soot.jimple.StaticInvokeExpr)13 Type (soot.Type)12 Stmt (soot.jimple.Stmt)12 InstanceInvokeExpr (soot.jimple.InstanceInvokeExpr)11 JimpleBody (soot.jimple.JimpleBody)11 SpecialInvokeExpr (soot.jimple.SpecialInvokeExpr)11 RefType (soot.RefType)10 VoidType (soot.VoidType)10 VirtualInvokeExpr (soot.jimple.VirtualInvokeExpr)10 LinkedList (java.util.LinkedList)9 SootMethodRef (soot.SootMethodRef)9 ArrayList (java.util.ArrayList)8 PrimType (soot.PrimType)8