Search in sources :

Example 31 with Body

use of soot.Body in project robovm by robovm.

the class ObjCMemberPlugin method createBridge.

private void createBridge(SootClass sootClass, SootMethod method, String selectorName, boolean strongRefSetter, boolean extensions) {
    Jimple j = Jimple.v();
    boolean usingGenericInstanceMethod = false;
    SootMethod msgSendMethod = getMsgSendMethod(selectorName, method, extensions);
    /*
         * Add the method even if we might remove it later to make marshaler
         * lookup on the method work as expected.
         */
    sootClass.addMethod(msgSendMethod);
    addBridgeAnnotation(msgSendMethod);
    SootMethodRef msgSendMethodRef = getGenericMsgSendReplacementMethod(msgSendMethod);
    if (!msgSendMethodRef.declaringClass().getType().equals(msgSendMethod.getDeclaringClass().getType())) {
        /*
             * There's a generic objc_msgSend method we can use. Remove
             * msgSendMethod from the class.
             */
        sootClass.removeMethod(msgSendMethod);
        /*
             * Can we use a generic <name>_instance method from $M? If we can we
             * won't have to make a call to objc_msgSendSuper.
             */
        if (!method.isStatic()) {
            // Yes!
            msgSendMethodRef = Scene.v().makeMethodRef(msgSendMethodRef.declaringClass(), msgSendMethodRef.name() + "_instance", msgSendMethodRef.parameterTypes(), msgSendMethodRef.returnType(), true);
            usingGenericInstanceMethod = true;
        }
    }
    SootMethodRef msgSendSuperMethodRef = null;
    if (!usingGenericInstanceMethod && !extensions && !method.isStatic()) {
        SootMethod msgSendSuperMethod = getMsgSendSuperMethod(selectorName, method);
        /*
             * Add the method even if we might remove it later to make marshaler
             * lookup on the method work as expected.
             */
        sootClass.addMethod(msgSendSuperMethod);
        addBridgeAnnotation(msgSendSuperMethod);
        msgSendSuperMethodRef = getGenericMsgSendSuperReplacementMethod(msgSendSuperMethod);
        if (!msgSendSuperMethodRef.declaringClass().getType().equals(msgSendSuperMethod.getDeclaringClass().getType())) {
            /*
                 * There's a generic objc_msgSendSuper method we can use. Remove
                 * msgSendSuperMethod from the class.
                 */
            sootClass.removeMethod(msgSendSuperMethod);
        }
    }
    method.setModifiers(method.getModifiers() & ~NATIVE);
    Body body = j.newBody(method);
    method.setActiveBody(body);
    PatchingChain<Unit> units = body.getUnits();
    Local thiz = null;
    if (extensions) {
        thiz = j.newLocal("$this", method.getParameterType(0));
        body.getLocals().add(thiz);
        units.add(j.newIdentityStmt(thiz, j.newParameterRef(method.getParameterType(0), 0)));
    } else if (!method.isStatic()) {
        thiz = j.newLocal("$this", sootClass.getType());
        body.getLocals().add(thiz);
        units.add(j.newIdentityStmt(thiz, j.newThisRef(sootClass.getType())));
    }
    LinkedList<Value> args = new LinkedList<>();
    for (int i = extensions ? 1 : 0; i < method.getParameterCount(); i++) {
        Type t = method.getParameterType(i);
        Local p = j.newLocal("$p" + i, t);
        body.getLocals().add(p);
        units.add(j.newIdentityStmt(p, j.newParameterRef(t, i)));
        args.add(p);
    }
    Local objCClass = null;
    if (!extensions && method.isStatic()) {
        objCClass = j.newLocal("$objCClass", org_robovm_objc_ObjCClass.getType());
        body.getLocals().add(objCClass);
        units.add(j.newAssignStmt(objCClass, j.newStaticFieldRef(Scene.v().makeFieldRef(sootClass, "$objCClass", org_robovm_objc_ObjCClass.getType(), true))));
    }
    if (strongRefSetter) {
        Type propType = method.getParameterType(extensions ? 1 : 0);
        if (propType instanceof RefLikeType) {
            SootMethodRef getter = findStrongRefGetter(sootClass, method, extensions).makeRef();
            Local before = j.newLocal("$before", propType);
            body.getLocals().add(before);
            units.add(j.newAssignStmt(before, extensions ? j.newStaticInvokeExpr(getter, thiz) : (objCClass != null ? j.newStaticInvokeExpr(getter) : j.newVirtualInvokeExpr(thiz, getter))));
            Value after = args.get(0);
            if (extensions) {
                units.add(j.newInvokeStmt(j.newStaticInvokeExpr(org_robovm_objc_ObjCExtensions_updateStrongRef, Arrays.asList(thiz, before, after))));
            } else {
                units.add(j.newInvokeStmt(j.newVirtualInvokeExpr(objCClass != null ? objCClass : thiz, org_robovm_objc_ObjCObject_updateStrongRef, before, after)));
            }
        }
    }
    Local sel = j.newLocal("$sel", org_robovm_objc_Selector.getType());
    body.getLocals().add(sel);
    // $sel = <selector>
    units.add(j.newAssignStmt(sel, j.newStaticFieldRef(Scene.v().makeFieldRef(sootClass, getSelectorFieldName(selectorName), org_robovm_objc_Selector.getType(), true))));
    args.addFirst(sel);
    Local customClass = null;
    if (!usingGenericInstanceMethod && !extensions && !Modifier.isFinal(sootClass.getModifiers()) && !method.isStatic()) {
        customClass = j.newLocal("$customClass", BooleanType.v());
        body.getLocals().add(customClass);
        units.add(j.newAssignStmt(customClass, j.newInstanceFieldRef(thiz, org_robovm_objc_ObjCObject_customClass)));
    }
    Local ret = null;
    if (method.getReturnType() != VoidType.v()) {
        ret = j.newLocal("$ret", msgSendMethodRef.returnType());
        body.getLocals().add(ret);
    }
    Local castRet = null;
    if (!msgSendMethodRef.returnType().equals(method.getReturnType())) {
        /*
             * We're calling a generic method in $M which returns an NSObject.
             * We need to cast that to the return type declared by the method
             * being generated.
             */
        castRet = j.newLocal("$castRet", method.getReturnType());
        body.getLocals().add(castRet);
    }
    StaticInvokeExpr invokeMsgSendExpr = j.newStaticInvokeExpr(msgSendMethodRef, l(thiz != null ? thiz : objCClass, args));
    Stmt invokeMsgSendStmt = ret == null ? j.newInvokeStmt(invokeMsgSendExpr) : j.newAssignStmt(ret, invokeMsgSendExpr);
    if (customClass != null) {
        // if $customClass == 0 goto <invokeMsgSendStmt>
        units.add(j.newIfStmt(j.newEqExpr(customClass, IntConstant.v(0)), invokeMsgSendStmt));
        // $super = this.getSuper()
        Local zuper = j.newLocal("$super", org_robovm_objc_ObjCSuper.getType());
        body.getLocals().add(zuper);
        units.add(j.newAssignStmt(zuper, j.newVirtualInvokeExpr(body.getThisLocal(), org_robovm_objc_ObjCObject_getSuper)));
        StaticInvokeExpr invokeMsgSendSuperExpr = j.newStaticInvokeExpr(msgSendSuperMethodRef, l(zuper, args));
        units.add(ret == null ? j.newInvokeStmt(invokeMsgSendSuperExpr) : j.newAssignStmt(ret, invokeMsgSendSuperExpr));
        if (ret != null) {
            if (castRet != null) {
                units.add(j.newAssignStmt(castRet, j.newCastExpr(ret, castRet.getType())));
                units.add(j.newReturnStmt(castRet));
            } else {
                units.add(j.newReturnStmt(ret));
            }
        } else {
            units.add(j.newReturnVoidStmt());
        }
    }
    units.add(invokeMsgSendStmt);
    if (ret != null) {
        if (castRet != null) {
            units.add(j.newAssignStmt(castRet, j.newCastExpr(ret, castRet.getType())));
            units.add(j.newReturnStmt(castRet));
        } else {
            units.add(j.newReturnStmt(ret));
        }
    } else {
        units.add(j.newReturnVoidStmt());
    }
}
Also used : SootMethodRef(soot.SootMethodRef) Local(soot.Local) Unit(soot.Unit) LinkedList(java.util.LinkedList) InvokeStmt(soot.jimple.InvokeStmt) Stmt(soot.jimple.Stmt) RefLikeType(soot.RefLikeType) StaticInvokeExpr(soot.jimple.StaticInvokeExpr) RefType(soot.RefType) BooleanType(soot.BooleanType) SootMethodType(org.robovm.compiler.util.generic.SootMethodType) Type(soot.Type) DoubleType(soot.DoubleType) FloatType(soot.FloatType) LongType(soot.LongType) RefLikeType(soot.RefLikeType) PrimType(soot.PrimType) VoidType(soot.VoidType) Value(soot.Value) SootMethod(soot.SootMethod) Jimple(soot.jimple.Jimple) Body(soot.Body)

Example 32 with Body

use of soot.Body in project robovm by robovm.

the class ObjCMemberPlugin method registerSelectors.

private void registerSelectors(SootClass sootClass, Set<String> selectors) {
    Jimple j = Jimple.v();
    SootMethod clinit = getOrCreateStaticInitializer(sootClass);
    Body body = clinit.retrieveActiveBody();
    Local sel = Jimple.v().newLocal("$sel", org_robovm_objc_Selector.getType());
    body.getLocals().add(sel);
    Chain<Unit> units = body.getUnits();
    for (String selectorName : selectors) {
        SootField f = getSelectorField(selectorName);
        sootClass.addField(f);
        units.insertBefore(Arrays.<Unit>asList(j.newAssignStmt(sel, j.newStaticInvokeExpr(org_robovm_objc_Selector_register, StringConstant.v(selectorName))), j.newAssignStmt(j.newStaticFieldRef(f.makeRef()), sel)), units.getLast());
    }
}
Also used : SootMethod(soot.SootMethod) Local(soot.Local) Jimple(soot.jimple.Jimple) SootField(soot.SootField) Unit(soot.Unit) Body(soot.Body)

Example 33 with Body

use of soot.Body in project soot by Sable.

the class Main method main.

/**
 * @param args
 */
public static void main(String[] args) {
    PackManager.v().getPack("jtp").add(new Transform("jtp.fixedie", new BodyTransformer() {

        @Override
        protected void internalTransform(Body b, String phaseName, Map<String, String> options) {
            for (Unit u : b.getUnits()) {
                Stmt s = (Stmt) u;
                if (s.containsInvokeExpr()) {
                    InvokeExpr ie = s.getInvokeExpr();
                    if (FixedMethods.isFixed(ie)) {
                        System.err.println("+++ " + ie);
                        yes++;
                    } else {
                        System.err.println(" -  " + ie);
                        no++;
                    }
                }
            }
        }
    }));
    soot.Main.main(args);
    System.err.println("+++ " + yes);
    System.err.println(" -  " + no);
}
Also used : InvokeExpr(soot.jimple.InvokeExpr) BodyTransformer(soot.BodyTransformer) Transform(soot.Transform) Unit(soot.Unit) Body(soot.Body) Map(java.util.Map) Stmt(soot.jimple.Stmt)

Example 34 with Body

use of soot.Body in project soot by Sable.

the class SynchronizerManager method getClassFetcherFor.

/**
 * Finds a method which calls java.lang.Class.forName(String). Searches for
 * names class$, _class$, __class$, etc. If no such method is found, creates
 * one and returns it.
 *
 * Uses dumb matching to do search. Not worth doing symbolic analysis for
 * this!
 */
public SootMethod getClassFetcherFor(SootClass c) {
    String methodName = "class$";
    for (; true; methodName = "_" + methodName) {
        SootMethod m = c.getMethodByNameUnsafe(methodName);
        if (m == null)
            return createClassFetcherFor(c, methodName);
        // Check signature.
        if (!m.getSignature().equals("<" + c.getName().replace('.', '$') + ": java.lang.Class " + methodName + "(java.lang.String)>"))
            continue;
        Body b = null;
        b = m.retrieveActiveBody();
        Iterator unitsIt = b.getUnits().iterator();
        if (!unitsIt.hasNext())
            continue;
        Stmt s = (Stmt) unitsIt.next();
        if (!(s instanceof IdentityStmt))
            continue;
        IdentityStmt is = (IdentityStmt) s;
        Value lo = is.getLeftOp(), ro = is.getRightOp();
        if (!(ro instanceof ParameterRef))
            continue;
        ParameterRef pr = (ParameterRef) ro;
        if (pr.getIndex() != 0)
            continue;
        if (!unitsIt.hasNext())
            continue;
        s = (Stmt) unitsIt.next();
        if (!(s instanceof AssignStmt))
            continue;
        AssignStmt as = (AssignStmt) s;
        Value retVal = as.getLeftOp(), ie = as.getRightOp();
        if (!ie.toString().equals(".staticinvoke <java.lang.Class: java.lang.Class forName(java.lang.String)>(" + lo + ")"))
            continue;
        if (!unitsIt.hasNext())
            continue;
        s = (Stmt) unitsIt.next();
        if (!(s instanceof ReturnStmt))
            continue;
        ReturnStmt rs = (ReturnStmt) s;
        if (!rs.getOp().equivTo(retVal))
            continue;
        /* in particular, it certainly returns Class.forName(arg). */
        return m;
    }
}
Also used : ParameterRef(soot.jimple.ParameterRef) AssignStmt(soot.jimple.AssignStmt) Iterator(java.util.Iterator) Value(soot.Value) SootMethod(soot.SootMethod) Body(soot.Body) JimpleBody(soot.jimple.JimpleBody) ReturnStmt(soot.jimple.ReturnStmt) IdentityStmt(soot.jimple.IdentityStmt) IfStmt(soot.jimple.IfStmt) IdentityStmt(soot.jimple.IdentityStmt) ReturnStmt(soot.jimple.ReturnStmt) Stmt(soot.jimple.Stmt) AssignStmt(soot.jimple.AssignStmt)

Example 35 with Body

use of soot.Body in project soot by Sable.

the class MethodStaticnessCorrector method canBeMadeStatic.

/**
 * Checks whether the given method can be made static, i.e., does not
 * reference the "this" object
 *
 * @param target
 *            The method to check
 * @return True if the given method can be made static, otherwise false
 */
private boolean canBeMadeStatic(SootMethod target) {
    if (target.hasActiveBody()) {
        Body body = target.getActiveBody();
        Value thisLocal = body.getThisLocal();
        for (Unit u : body.getUnits()) {
            for (ValueBox vb : u.getUseBoxes()) {
                if (vb.getValue() == thisLocal)
                    return false;
            }
        }
        return true;
    }
    return false;
}
Also used : ValueBox(soot.ValueBox) Value(soot.Value) 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