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