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;
}
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;
}
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();
}
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;
}
}
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);
}
}
Aggregations