Search in sources :

Example 36 with SootField

use of soot.SootField in project soot by Sable.

the class AccessManager method createAccessorName.

/**
 * Creates a name for an accessor method.
 *
 * @param member
 * @param setter
 * @return
 */
public static String createAccessorName(ClassMember member, boolean setter) {
    SootClass target = member.getDeclaringClass();
    String name = "access$";
    if (member instanceof SootField) {
        SootField f = (SootField) member;
        if (setter) {
            name += "set$";
        } else {
            name += "get$";
        }
        name += f.getName();
    } else {
        SootMethod m = (SootMethod) member;
        name += m.getName() + "$";
        for (Iterator it = m.getParameterTypes().iterator(); it.hasNext(); ) {
            Type type = (Type) it.next();
            name += type.toString().replaceAll("\\.", "\\$\\$") + "$";
        }
    }
    return name;
}
Also used : Type(soot.Type) VoidType(soot.VoidType) Iterator(java.util.Iterator) SootMethod(soot.SootMethod) SootField(soot.SootField) SootClass(soot.SootClass)

Example 37 with SootField

use of soot.SootField in project soot by Sable.

the class ReflectiveCallsInliner method createNewMethod.

@SuppressWarnings("unchecked")
private SootMethod createNewMethod(Kind callKind, String target, Type fieldSetGetType) {
    List<Type> parameterTypes = new LinkedList<Type>();
    Type returnType = null;
    switch(callKind) {
        case ClassForName:
            returnType = RefType.v("java.lang.Class");
            break;
        case ClassNewInstance:
            returnType = RefType.v("java.lang.Object");
            break;
        case ConstructorNewInstance:
            parameterTypes.add(ArrayType.v(RefType.v("java.lang.Object"), 1));
            returnType = RefType.v("java.lang.Object");
            break;
        case MethodInvoke:
            parameterTypes.add(RefType.v("java.lang.Object"));
            parameterTypes.add(ArrayType.v(RefType.v("java.lang.Object"), 1));
            returnType = RefType.v("java.lang.Object");
            break;
        case FieldSet:
            parameterTypes.add(RefType.v("java.lang.Object"));
            parameterTypes.add(fieldSetGetType);
            returnType = VoidType.v();
            break;
        case FieldGet:
            parameterTypes.add(RefType.v("java.lang.Object"));
            returnType = fieldSetGetType;
            break;
        default:
            throw new IllegalStateException();
    }
    SootMethod newMethod = Scene.v().makeSootMethod("reflectiveCall" + (callNum++), parameterTypes, returnType, Modifier.PUBLIC | Modifier.STATIC);
    Body newBody = Jimple.v().newBody(newMethod);
    newMethod.setActiveBody(newBody);
    reflectiveCallsClass.addMethod(newMethod);
    PatchingChain<Unit> newUnits = newBody.getUnits();
    LocalGenerator localGen = new LocalGenerator(newBody);
    Local freshLocal;
    Value replacement = null;
    Local[] paramLocals = null;
    switch(callKind) {
        case ClassForName:
            {
                // replace by: <Class constant for <target>>
                freshLocal = localGen.generateLocal(RefType.v("java.lang.Class"));
                replacement = ClassConstant.v(target.replace('.', '/'));
                break;
            }
        case ClassNewInstance:
            {
                // replace by: new <target>
                RefType targetType = RefType.v(target);
                freshLocal = localGen.generateLocal(targetType);
                replacement = Jimple.v().newNewExpr(targetType);
                break;
            }
        case ConstructorNewInstance:
            {
                /*
			 * replace r=constr.newInstance(args) by: Object p0 = args[0]; ...
			 * Object pn = args[n]; T0 a0 = (T0)p0; ... Tn an = (Tn)pn;
			 */
                SootMethod constructor = Scene.v().getMethod(target);
                paramLocals = new Local[constructor.getParameterCount()];
                if (constructor.getParameterCount() > 0) {
                    // argArrayLocal = @parameter-0
                    ArrayType arrayType = ArrayType.v(RefType.v("java.lang.Object"), 1);
                    Local argArrayLocal = localGen.generateLocal(arrayType);
                    newUnits.add(Jimple.v().newIdentityStmt(argArrayLocal, Jimple.v().newParameterRef(arrayType, 0)));
                    int i = 0;
                    for (Type paramType : ((Collection<Type>) constructor.getParameterTypes())) {
                        paramLocals[i] = localGen.generateLocal(paramType);
                        unboxParameter(argArrayLocal, i, paramLocals, paramType, newUnits, localGen);
                        i++;
                    }
                }
                RefType targetType = constructor.getDeclaringClass().getType();
                freshLocal = localGen.generateLocal(targetType);
                replacement = Jimple.v().newNewExpr(targetType);
                break;
            }
        case MethodInvoke:
            {
                /*
			 * replace r=m.invoke(obj,args) by: T recv = (T)obj; Object p0 =
			 * args[0]; ... Object pn = args[n]; T0 a0 = (T0)p0; ... Tn an =
			 * (Tn)pn;
			 */
                SootMethod method = Scene.v().getMethod(target);
                // recvObject = @parameter-0
                RefType objectType = RefType.v("java.lang.Object");
                Local recvObject = localGen.generateLocal(objectType);
                newUnits.add(Jimple.v().newIdentityStmt(recvObject, Jimple.v().newParameterRef(objectType, 0)));
                paramLocals = new Local[method.getParameterCount()];
                if (method.getParameterCount() > 0) {
                    // argArrayLocal = @parameter-1
                    ArrayType arrayType = ArrayType.v(RefType.v("java.lang.Object"), 1);
                    Local argArrayLocal = localGen.generateLocal(arrayType);
                    newUnits.add(Jimple.v().newIdentityStmt(argArrayLocal, Jimple.v().newParameterRef(arrayType, 1)));
                    int i = 0;
                    for (Type paramType : ((Collection<Type>) method.getParameterTypes())) {
                        paramLocals[i] = localGen.generateLocal(paramType);
                        unboxParameter(argArrayLocal, i, paramLocals, paramType, newUnits, localGen);
                        i++;
                    }
                }
                RefType targetType = method.getDeclaringClass().getType();
                freshLocal = localGen.generateLocal(targetType);
                replacement = Jimple.v().newCastExpr(recvObject, method.getDeclaringClass().getType());
                break;
            }
        case FieldSet:
        case FieldGet:
            {
                /*
			 * replace f.set(o,v) by: Object obj = @parameter-0; T freshLocal =
			 * (T)obj;
			 */
                RefType objectType = RefType.v("java.lang.Object");
                Local recvObject = localGen.generateLocal(objectType);
                newUnits.add(Jimple.v().newIdentityStmt(recvObject, Jimple.v().newParameterRef(objectType, 0)));
                SootField field = Scene.v().getField(target);
                freshLocal = localGen.generateLocal(field.getDeclaringClass().getType());
                replacement = Jimple.v().newCastExpr(recvObject, field.getDeclaringClass().getType());
                break;
            }
        default:
            throw new InternalError("Unknown kind of reflective call " + callKind);
    }
    AssignStmt replStmt = Jimple.v().newAssignStmt(freshLocal, replacement);
    newUnits.add(replStmt);
    Local retLocal = localGen.generateLocal(returnType);
    switch(callKind) {
        case ClassForName:
            {
                // add: retLocal = freshLocal;
                newUnits.add(Jimple.v().newAssignStmt(retLocal, freshLocal));
                break;
            }
        case ClassNewInstance:
            {
                // add: freshLocal.<init>()
                SootClass targetClass = Scene.v().getSootClass(target);
                SpecialInvokeExpr constrCallExpr = Jimple.v().newSpecialInvokeExpr(freshLocal, Scene.v().makeMethodRef(targetClass, SootMethod.constructorName, Collections.<Type>emptyList(), VoidType.v(), false));
                InvokeStmt constrCallStmt2 = Jimple.v().newInvokeStmt(constrCallExpr);
                newUnits.add(constrCallStmt2);
                // add: retLocal = freshLocal
                newUnits.add(Jimple.v().newAssignStmt(retLocal, freshLocal));
                break;
            }
        case ConstructorNewInstance:
            {
                // add: freshLocal.<target>(a0,...,an);
                SootMethod constructor = Scene.v().getMethod(target);
                SpecialInvokeExpr constrCallExpr = Jimple.v().newSpecialInvokeExpr(freshLocal, constructor.makeRef(), Arrays.asList(paramLocals));
                InvokeStmt constrCallStmt2 = Jimple.v().newInvokeStmt(constrCallExpr);
                newUnits.add(constrCallStmt2);
                // add: retLocal = freshLocal
                newUnits.add(Jimple.v().newAssignStmt(retLocal, freshLocal));
                break;
            }
        case MethodInvoke:
            {
                // add: freshLocal=recv.<target>(a0,...,an);
                SootMethod method = Scene.v().getMethod(target);
                InvokeExpr invokeExpr;
                if (method.isStatic())
                    invokeExpr = Jimple.v().newStaticInvokeExpr(method.makeRef(), Arrays.asList(paramLocals));
                else
                    invokeExpr = Jimple.v().newVirtualInvokeExpr(freshLocal, method.makeRef(), Arrays.<Value>asList(paramLocals));
                if (method.getReturnType().equals(VoidType.v())) {
                    // method returns null; simply invoke it and return null
                    InvokeStmt invokeStmt = Jimple.v().newInvokeStmt(invokeExpr);
                    newUnits.add(invokeStmt);
                    AssignStmt assignStmt = Jimple.v().newAssignStmt(retLocal, NullConstant.v());
                    newUnits.add(assignStmt);
                } else {
                    AssignStmt assignStmt = Jimple.v().newAssignStmt(retLocal, invokeExpr);
                    newUnits.add(assignStmt);
                }
                break;
            }
        case FieldSet:
            {
                // add freshLocal.<f> = v;
                Local value = localGen.generateLocal(fieldSetGetType);
                newUnits.insertBeforeNoRedirect(Jimple.v().newIdentityStmt(value, Jimple.v().newParameterRef(fieldSetGetType, 1)), replStmt);
                SootField field = Scene.v().getField(target);
                Local boxedOrCasted = localGen.generateLocal(field.getType());
                insertCastOrUnboxingCode(boxedOrCasted, value, newUnits);
                FieldRef fieldRef;
                if (field.isStatic()) {
                    fieldRef = Jimple.v().newStaticFieldRef(field.makeRef());
                } else {
                    fieldRef = Jimple.v().newInstanceFieldRef(freshLocal, field.makeRef());
                }
                newUnits.add(Jimple.v().newAssignStmt(fieldRef, boxedOrCasted));
                break;
            }
        case FieldGet:
            {
                /*
			 * add: T2 temp = recv.<f>; return temp;
			 */
                SootField field = Scene.v().getField(target);
                Local value = localGen.generateLocal(field.getType());
                FieldRef fieldRef;
                if (field.isStatic()) {
                    fieldRef = Jimple.v().newStaticFieldRef(field.makeRef());
                } else {
                    fieldRef = Jimple.v().newInstanceFieldRef(freshLocal, field.makeRef());
                }
                newUnits.add(Jimple.v().newAssignStmt(value, fieldRef));
                insertCastOrBoxingCode(retLocal, value, newUnits);
                break;
            }
    }
    if (!returnType.equals(VoidType.v()))
        newUnits.add(Jimple.v().newReturnStmt(retLocal));
    if (Options.v().validate())
        newBody.validate();
    cleanup(newBody);
    return newMethod;
}
Also used : LocalGenerator(soot.javaToJimple.LocalGenerator) FieldRef(soot.jimple.FieldRef) SootFieldRef(soot.SootFieldRef) InstanceFieldRef(soot.jimple.InstanceFieldRef) InvokeStmt(soot.jimple.InvokeStmt) AssignStmt(soot.jimple.AssignStmt) SpecialInvokeExpr(soot.jimple.SpecialInvokeExpr) Local(soot.Local) Unit(soot.Unit) SootClass(soot.SootClass) LinkedList(java.util.LinkedList) RefType(soot.RefType) ArrayType(soot.ArrayType) RefType(soot.RefType) BooleanType(soot.BooleanType) Type(soot.Type) RefLikeType(soot.RefLikeType) ArrayType(soot.ArrayType) PrimType(soot.PrimType) VoidType(soot.VoidType) InstanceInvokeExpr(soot.jimple.InstanceInvokeExpr) InterfaceInvokeExpr(soot.jimple.InterfaceInvokeExpr) VirtualInvokeExpr(soot.jimple.VirtualInvokeExpr) InvokeExpr(soot.jimple.InvokeExpr) SpecialInvokeExpr(soot.jimple.SpecialInvokeExpr) StaticInvokeExpr(soot.jimple.StaticInvokeExpr) Value(soot.Value) SootMethod(soot.SootMethod) Collection(java.util.Collection) SootField(soot.SootField) Body(soot.Body) JimpleBody(soot.jimple.JimpleBody)

Example 38 with SootField

use of soot.SootField in project soot by Sable.

the class FieldDeclaration method jimplify1phase2.

/**
 * @ast method
 * @aspect EmitJimple
 * @declaredat /Users/eric/Documents/workspaces/clara-soot/JastAddExtensions/JimpleBackend/EmitJimple.jrag:329
 */
public void jimplify1phase2() {
    String name = name();
    soot.Type type = type().getSootType();
    int modifiers = sootTypeModifiers();
    if (!hostType().getSootClassDecl().declaresFieldByName(name)) {
        SootField f = Scene.v().makeSootField(name, type, modifiers);
        hostType().getSootClassDecl().addField(f);
        if (isStatic() && isFinal() && isConstant() && (type().isPrimitive() || type().isString())) {
            if (type().isString())
                f.addTag(new soot.tagkit.StringConstantValueTag(constant().stringValue()));
            else if (type().isLong())
                f.addTag(new soot.tagkit.LongConstantValueTag(constant().longValue()));
            else if (type().isDouble())
                f.addTag(new soot.tagkit.DoubleConstantValueTag(constant().doubleValue()));
            else if (type().isFloat())
                f.addTag(new soot.tagkit.FloatConstantValueTag(constant().floatValue()));
            else if (type().isIntegralType())
                f.addTag(new soot.tagkit.IntegerConstantValueTag(constant().intValue()));
        }
        sootField = f;
    } else {
        sootField = hostType().getSootClassDecl().getFieldByName(name);
    }
    addAttributes();
}
Also used : SootField(soot.SootField)

Example 39 with SootField

use of soot.SootField in project robovm by robovm.

the class MethodCompiler method canAccessDirectly.

//    private Value callOrInvoke(Unit unit, Value fn, Value ... args) {
//        Variable result = null;
//        Type returnType = ((FunctionType) fn.getType()).getReturnType();
//        if (returnType != VOID) {
//            result = this.function.newVariable(returnType);
//        }
//        List<Trap> traps = getTrapsAt(unit);
//        if (!traps.isEmpty()) {
//            Label label = new Label();
//            BasicBlockRef to = function.newBasicBlockRef(label);
//            BasicBlockRef unwind = function.newBasicBlockRef(new Label(traps));
//            function.add(new Invoke(result, fn, to, unwind, args));
//            function.newBasicBlock(label);
//            recordedTraps.add(traps);
//        } else {
//            function.add(new Call(result, fn, args));
//        }
//        return result == null ? null : result.ref();
//    }
private boolean canAccessDirectly(FieldRef ref) {
    SootClass sootClass = this.sootMethod.getDeclaringClass();
    SootFieldRef fieldRef = ref.getFieldRef();
    if (!fieldRef.declaringClass().equals(sootClass)) {
        return false;
    }
    try {
        SootField field = sootClass.getField(fieldRef.name(), fieldRef.type());
        /* 
             * The field exists.
             */
        if (field.isStatic()) {
            // If not we want an exception to be thrown so we need a trampoline.
            return ref instanceof StaticFieldRef;
        }
        // If not we want an exception to be thrown so we need a trampoline.
        return ref instanceof InstanceFieldRef;
    } catch (RuntimeException e) {
        // isn't declared in the class.
        return false;
    }
}
Also used : InstanceFieldRef(soot.jimple.InstanceFieldRef) SootField(soot.SootField) SootClass(soot.SootClass) SootFieldRef(soot.SootFieldRef) StaticFieldRef(soot.jimple.StaticFieldRef)

Example 40 with SootField

use of soot.SootField in project robovm by robovm.

the class TrampolineCompiler method compile.

public void compile(ModuleBuilder mb, Clazz currentClass, Trampoline t, Set<String> dependencies, Set<Triple<String, String, String>> methodDependencies) {
    this.mb = mb;
    addDependencyIfNeeded(dependencies, currentClass, t);
    /*
         * Check if the target class exists and is accessible. Also check that
         * field accesses and method calls are compatible with the target 
         * field/method and that the field/method is accessible to the caller.
         * If any of the tests fail the weak trampoline function created by the
         * ClassCompiler will be overridden with a function which throws an
         * appropriate exception.
         */
    Function errorFn = new FunctionBuilder(t).linkage(external).build();
    if (!checkClassExists(errorFn, t) || !checkClassAccessible(errorFn, t)) {
        mb.addFunction(errorFn);
        return;
    }
    if (t instanceof New) {
        SootClass target = config.getClazzes().load(t.getTarget()).getSootClass();
        if (target.isAbstract() || target.isInterface()) {
            call(errorFn, BC_THROW_INSTANTIATION_ERROR, errorFn.getParameterRef(0), mb.getString(t.getTarget().replace('/', '.')));
            errorFn.add(new Unreachable());
            mb.addFunction(errorFn);
            return;
        }
        String fnName = Symbols.clinitWrapperSymbol(Symbols.allocatorSymbol(t.getTarget()));
        alias(t, fnName);
    } else if (t instanceof Instanceof) {
        if (isArray(t.getTarget())) {
            FunctionRef fnRef = createInstanceofArray((Instanceof) t);
            alias(t, fnRef.getName());
        } else {
            String fnName = Symbols.instanceofSymbol(t.getTarget());
            alias(t, fnName);
        }
    } else if (t instanceof Checkcast) {
        if (isArray(t.getTarget())) {
            FunctionRef fnRef = createCheckcastArray((Checkcast) t);
            alias(t, fnRef.getName());
        } else {
            String fnName = Symbols.checkcastSymbol(t.getTarget());
            alias(t, fnName);
        }
    } else if (t instanceof LdcClass) {
        if (isArray(t.getTarget())) {
            FunctionRef fnRef = createLdcArray((LdcClass) t);
            alias(t, fnRef.getName());
        } else {
            String fnName = Symbols.ldcExternalSymbol(t.getTarget());
            alias(t, fnName);
        }
    } else if (t instanceof Anewarray) {
        FunctionRef fnRef = createAnewarray((Anewarray) t);
        alias(t, fnRef.getName());
    } else if (t instanceof Multianewarray) {
        FunctionRef fnRef = createMultianewarray((Multianewarray) t);
        alias(t, fnRef.getName());
    } else if (t instanceof FieldAccessor) {
        SootField field = resolveField(errorFn, (FieldAccessor) t);
        if (field != null) {
            dependencies.add(getInternalName(field.getDeclaringClass()));
        }
        if (field == null || !checkMemberAccessible(errorFn, t, field)) {
            mb.addFunction(errorFn);
            return;
        }
        Clazz caller = config.getClazzes().load(t.getCallingClass());
        Clazz target = config.getClazzes().load(t.getTarget());
        if (!((FieldAccessor) t).isGetter() && field.isFinal() && caller != target) {
            // Only the class declaring a final field may write to it.
            // (Actually only <init>/<clinit> methods may write to it but we 
            // don't know which method is accessing the field at this point)
            throwIllegalAccessError(errorFn, ATTEMPT_TO_WRITE_TO_FINAL_FIELD, target, field.getName(), caller);
            mb.addFunction(errorFn);
            return;
        }
        if (!field.isStatic()) {
            createInlinedAccessorForInstanceField((FieldAccessor) t, field);
        } else {
            createTrampolineAliasForField((FieldAccessor) t, field);
        }
    } else if (t instanceof Invokeinterface) {
        SootMethod rm = resolveInterfaceMethod(errorFn, (Invokeinterface) t);
        if (rm != null) {
            methodDependencies.add(new ImmutableTriple<String, String, String>(getInternalName(rm.getDeclaringClass()), rm.getName(), getDescriptor(rm)));
        }
        if (rm == null || !checkMemberAccessible(errorFn, t, rm)) {
            mb.addFunction(errorFn);
            return;
        }
        createTrampolineAliasForMethod((Invoke) t, rm);
    } else if (t instanceof Invoke) {
        SootMethod method = resolveMethod(errorFn, (Invoke) t);
        if (method != null) {
            methodDependencies.add(new ImmutableTriple<String, String, String>(getInternalName(method.getDeclaringClass()), method.getName(), getDescriptor(method)));
        }
        if (method == null || !checkMemberAccessible(errorFn, t, method)) {
            mb.addFunction(errorFn);
            return;
        }
        if (t instanceof Invokespecial && method.isAbstract()) {
            call(errorFn, BC_THROW_ABSTRACT_METHOD_ERROR, errorFn.getParameterRef(0), mb.getString(String.format(NO_SUCH_METHOD_ERROR, method.getDeclaringClass(), method.getName(), getDescriptor(method))));
            errorFn.add(new Unreachable());
            mb.addFunction(errorFn);
            return;
        }
        createTrampolineAliasForMethod((Invoke) t, method);
    }
}
Also used : New(org.robovm.compiler.trampoline.New) ImmutableTriple(org.apache.commons.lang3.tuple.ImmutableTriple) Anewarray(org.robovm.compiler.trampoline.Anewarray) Multianewarray(org.robovm.compiler.trampoline.Multianewarray) SootClass(soot.SootClass) FieldAccessor(org.robovm.compiler.trampoline.FieldAccessor) Invokeinterface(org.robovm.compiler.trampoline.Invokeinterface) Invoke(org.robovm.compiler.trampoline.Invoke) Invokespecial(org.robovm.compiler.trampoline.Invokespecial) Function(org.robovm.compiler.llvm.Function) Unreachable(org.robovm.compiler.llvm.Unreachable) LdcClass(org.robovm.compiler.trampoline.LdcClass) Instanceof(org.robovm.compiler.trampoline.Instanceof) SootMethod(soot.SootMethod) SootField(soot.SootField) Clazz(org.robovm.compiler.clazz.Clazz) Checkcast(org.robovm.compiler.trampoline.Checkcast) FunctionRef(org.robovm.compiler.llvm.FunctionRef)

Aggregations

SootField (soot.SootField)73 SootMethod (soot.SootMethod)29 SootClass (soot.SootClass)26 RefType (soot.RefType)22 ArrayList (java.util.ArrayList)19 Value (soot.Value)17 Iterator (java.util.Iterator)15 Local (soot.Local)14 Type (soot.Type)14 Unit (soot.Unit)13 FieldRef (soot.jimple.FieldRef)12 BooleanType (soot.BooleanType)10 PrimType (soot.PrimType)10 VoidType (soot.VoidType)10 Stmt (soot.jimple.Stmt)10 ByteType (soot.ByteType)8 CharType (soot.CharType)8 DoubleType (soot.DoubleType)8 FloatType (soot.FloatType)8 IntType (soot.IntType)8