use of soot.util.Chain in project soot by Sable.
the class RemoveEmptyBodyDefaultConstructor method checkAndRemoveDefault.
public static void checkAndRemoveDefault(SootClass s) {
debug("\n\nRemoveEmptyBodyDefaultConstructor----" + s.getName());
List methods = s.getMethods();
Iterator it = methods.iterator();
List<SootMethod> constructors = new ArrayList<SootMethod>();
while (it.hasNext()) {
SootMethod method = (SootMethod) it.next();
debug("method name is" + method.getName());
if (method.getName().indexOf("<init>") > -1) {
// constructor add to constructor list
constructors.add(method);
}
}
if (constructors.size() != 1) {
// cant do anything since there are more than one constructors
debug("class has more than one constructors cant do anything");
return;
}
// only one constructor check its default (no arguments)
SootMethod constructor = constructors.get(0);
if (constructor.getParameterCount() != 0) {
// can only deal with default constructors
debug("constructor is not the default constructor");
return;
}
debug("Check that the body is empty....and call to super contains no arguments and delete");
if (!constructor.hasActiveBody()) {
debug("No active body found for the default constructor");
return;
}
Body body = constructor.getActiveBody();
Chain units = ((DavaBody) body).getUnits();
if (units.size() != 1) {
debug(" DavaBody AST does not have single root");
return;
}
ASTNode AST = (ASTNode) units.getFirst();
if (!(AST instanceof ASTMethodNode))
throw new RuntimeException("Starting node of DavaBody AST is not an ASTMethodNode");
ASTMethodNode methodNode = (ASTMethodNode) AST;
debug("got methodnode check body is empty and super has nothing in it");
List<Object> subBodies = methodNode.get_SubBodies();
if (subBodies.size() != 1) {
debug("Method node does not have one subBody!!!");
return;
}
List methodBody = (List) subBodies.get(0);
if (methodBody.size() != 0) {
debug("Method body size is greater than 1 so cant do nothing");
return;
}
debug("Method body is empty...check super call is empty");
if (((DavaBody) body).get_ConstructorExpr().getArgCount() != 0) {
debug("call to super not empty");
return;
}
debug("REMOVE METHOD");
s.removeMethod(constructor);
}
use of soot.util.Chain in project soot by Sable.
the class SynchronizerManager method synchronizeStmtOn.
/**
* Wraps stmt around a monitor associated with local lock. When inlining or
* static method binding, this is the former base of the invoke expression.
*/
public void synchronizeStmtOn(Stmt stmt, JimpleBody b, Local lock) {
Chain units = b.getUnits();
// TrapManager.splitTrapsAgainst(b, stmt, (Stmt)units.getSuccOf(stmt));
units.insertBefore(Jimple.v().newEnterMonitorStmt(lock), stmt);
Stmt exitMon = Jimple.v().newExitMonitorStmt(lock);
units.insertAfter(exitMon, stmt);
// Ok. That was the easy part.
// We also need to modify exception blocks to exit the monitor
// (they have conveniently been pre-split)
// Actually, we don't need to do this.
// {
// List traps = TrapManager.getTrapsAt(stmt, b);
// Iterator trapsIt = traps.iterator();
// while (trapsIt.hasNext())
// {
// Trap t = (Trap)trapsIt.next();
// Stmt s = (Stmt)units.getLast();
// Stmt newCaughtRef = (Stmt)t.getHandlerUnit().clone();
// List l = new ArrayList();
// l.add(newCaughtRef);
// l.add(exitMon.clone());
// l.add(Jimple.v().newGotoStmt((Stmt)units.getSuccOf((Stmt)t.getHandlerUnit())));
// units.insertAfter(l, s);
// t.setHandlerUnit(newCaughtRef);
// }
// }
// and also we must add a catch Throwable exception block in the
// appropriate place.
{
Stmt newGoto = Jimple.v().newGotoStmt((Stmt) units.getSuccOf(exitMon));
units.insertAfter(newGoto, exitMon);
List<Unit> l = new ArrayList<Unit>();
Local eRef = Jimple.v().newLocal("__exception", RefType.v("java.lang.Throwable"));
b.getLocals().add(eRef);
Stmt handlerStmt = Jimple.v().newIdentityStmt(eRef, Jimple.v().newCaughtExceptionRef());
l.add(handlerStmt);
l.add((Stmt) exitMon.clone());
l.add(Jimple.v().newThrowStmt(eRef));
units.insertAfter(l, newGoto);
Trap newTrap = Jimple.v().newTrap(Scene.v().getSootClass("java.lang.Throwable"), stmt, (Stmt) units.getSuccOf(stmt), handlerStmt);
b.getTraps().addFirst(newTrap);
}
}
use of soot.util.Chain in project soot by Sable.
the class StaticMethodBinder method internalTransform.
protected void internalTransform(String phaseName, Map opts) {
Filter instanceInvokesFilter = new Filter(new InstanceInvokeEdgesPred());
SMBOptions options = new SMBOptions(opts);
String modifierOptions = PhaseOptions.getString(opts, "allowed-modifier-changes");
HashMap instanceToStaticMap = new HashMap();
CallGraph cg = Scene.v().getCallGraph();
Hierarchy hierarchy = Scene.v().getActiveHierarchy();
Iterator classesIt = Scene.v().getApplicationClasses().iterator();
while (classesIt.hasNext()) {
SootClass c = (SootClass) classesIt.next();
LinkedList methodsList = new LinkedList();
for (Iterator it = c.methodIterator(); it.hasNext(); ) {
methodsList.add(it.next());
}
while (!methodsList.isEmpty()) {
SootMethod container = (SootMethod) methodsList.removeFirst();
if (!container.isConcrete())
continue;
if (!instanceInvokesFilter.wrap(cg.edgesOutOf(container)).hasNext())
continue;
JimpleBody b = (JimpleBody) container.getActiveBody();
List<Unit> unitList = new ArrayList<Unit>();
unitList.addAll(b.getUnits());
Iterator<Unit> unitIt = unitList.iterator();
while (unitIt.hasNext()) {
Stmt s = (Stmt) unitIt.next();
if (!s.containsInvokeExpr())
continue;
InvokeExpr ie = s.getInvokeExpr();
if (ie instanceof StaticInvokeExpr || ie instanceof SpecialInvokeExpr)
continue;
Iterator targets = new Targets(instanceInvokesFilter.wrap(cg.edgesOutOf(s)));
if (!targets.hasNext())
continue;
SootMethod target = (SootMethod) targets.next();
if (targets.hasNext())
continue;
if (!AccessManager.ensureAccess(container, target, modifierOptions))
continue;
if (!target.getDeclaringClass().isApplicationClass() || !target.isConcrete())
continue;
// Don't modify java.lang.Object
if (target.getDeclaringClass() == Scene.v().getSootClass("java.lang.Object"))
continue;
if (!instanceToStaticMap.containsKey(target)) {
List newParameterTypes = new ArrayList();
newParameterTypes.add(RefType.v(target.getDeclaringClass().getName()));
newParameterTypes.addAll(target.getParameterTypes());
// Check for signature conflicts.
String newName = target.getName() + "_static";
while (target.getDeclaringClass().declaresMethod(newName, newParameterTypes, target.getReturnType())) newName = newName + "_static";
SootMethod ct = Scene.v().makeSootMethod(newName, newParameterTypes, target.getReturnType(), target.getModifiers() | Modifier.STATIC, target.getExceptions());
target.getDeclaringClass().addMethod(ct);
methodsList.addLast(ct);
ct.setActiveBody((Body) target.getActiveBody().clone());
// Make the invoke graph take into account the
// newly-cloned body.
{
Iterator oldUnits = target.getActiveBody().getUnits().iterator();
Iterator newUnits = ct.getActiveBody().getUnits().iterator();
while (newUnits.hasNext()) {
Stmt oldStmt, newStmt;
oldStmt = (Stmt) oldUnits.next();
newStmt = (Stmt) newUnits.next();
Iterator edges = cg.edgesOutOf(oldStmt);
while (edges.hasNext()) {
Edge e = (Edge) edges.next();
cg.addEdge(new Edge(ct, newStmt, e.tgt(), e.kind()));
cg.removeEdge(e);
}
}
}
// Shift the parameter list to apply to the new this
// parameter.
// If the method uses this, then we replace
// the r0 := @this with r0 := @parameter0 & shift.
// Otherwise, just zap the r0 := @this.
{
Body newBody = ct.getActiveBody();
Chain units = newBody.getUnits();
Iterator unitsIt = newBody.getUnits().snapshotIterator();
while (unitsIt.hasNext()) {
Stmt st = (Stmt) unitsIt.next();
if (st instanceof IdentityStmt) {
IdentityStmt is = (IdentityStmt) st;
if (is.getRightOp() instanceof ThisRef) {
units.swapWith(st, Jimple.v().newIdentityStmt(is.getLeftOp(), Jimple.v().newParameterRef(is.getRightOp().getType(), 0)));
} else {
if (is.getRightOp() instanceof ParameterRef) {
ParameterRef ro = (ParameterRef) is.getRightOp();
ro.setIndex(ro.getIndex() + 1);
}
}
}
}
}
instanceToStaticMap.put(target, ct);
}
SootMethod clonedTarget = (SootMethod) instanceToStaticMap.get(target);
Value thisToAdd = ((InstanceInvokeExpr) ie).getBase();
// Insert casts to please the verifier.
if (options.insert_redundant_casts()) {
// The verifier will complain if targetUsesThis, and:
// the argument passed to the method is not the same
// type.
// For instance, Bottle.price_static takes a cost.
// Cost is an interface implemented by Bottle.
SootClass localType, parameterType;
localType = ((RefType) ((InstanceInvokeExpr) ie).getBase().getType()).getSootClass();
parameterType = target.getDeclaringClass();
if (localType.isInterface() || hierarchy.isClassSuperclassOf(localType, parameterType)) {
Local castee = Jimple.v().newLocal("__castee", parameterType.getType());
b.getLocals().add(castee);
b.getUnits().insertBefore(Jimple.v().newAssignStmt(castee, Jimple.v().newCastExpr(((InstanceInvokeExpr) ie).getBase(), parameterType.getType())), s);
thisToAdd = castee;
}
}
// Now rebind the method call & fix the invoke graph.
{
List newArgs = new ArrayList();
newArgs.add(thisToAdd);
newArgs.addAll(ie.getArgs());
StaticInvokeExpr sie = Jimple.v().newStaticInvokeExpr(clonedTarget.makeRef(), newArgs);
ValueBox ieBox = s.getInvokeExprBox();
ieBox.setValue(sie);
cg.addEdge(new Edge(container, s, clonedTarget));
}
// (If enabled), add a null pointer check.
if (options.insert_null_checks()) {
boolean caught = TrapManager.isExceptionCaughtAt(Scene.v().getSootClass("java.lang.NullPointerException"), s, b);
/* Ah ha. Caught again! */
if (caught) {
/*
* In this case, we don't use throwPoint; instead,
* put the code right there.
*/
Stmt insertee = Jimple.v().newIfStmt(Jimple.v().newNeExpr(((InstanceInvokeExpr) ie).getBase(), NullConstant.v()), s);
b.getUnits().insertBefore(insertee, s);
// This sucks (but less than before).
((IfStmt) insertee).setTarget(s);
ThrowManager.addThrowAfter(b, insertee);
} else {
Stmt throwPoint = ThrowManager.getNullPointerExceptionThrower(b);
b.getUnits().insertBefore(Jimple.v().newIfStmt(Jimple.v().newEqExpr(((InstanceInvokeExpr) ie).getBase(), NullConstant.v()), throwPoint), s);
}
}
// Add synchronizing stuff.
{
if (target.isSynchronized()) {
clonedTarget.setModifiers(clonedTarget.getModifiers() & ~Modifier.SYNCHRONIZED);
SynchronizerManager.v().synchronizeStmtOn(s, b, (Local) ((InstanceInvokeExpr) ie).getBase());
}
}
// Resolve name collisions.
LocalNameStandardizer.v().transform(b, phaseName + ".lns");
}
}
}
}
use of soot.util.Chain in project soot by Sable.
the class SynchronizerManager method createClassFetcherFor.
/**
* Creates a method which calls java.lang.Class.forName(String).
*
* The method should look like the following:
*
* <pre>
* .static java.lang.Class class$(java.lang.String)
* {
* java.lang.String r0, $r5;
* java.lang.ClassNotFoundException r1, $r3;
* java.lang.Class $r2;
* java.lang.NoClassDefFoundError $r4;
*
* r0 := @parameter0: java.lang.String;
*
* label0:
* $r2 = .staticinvoke <java.lang.Class: java.lang.Class forName(java.lang.String)>(r0);
* .return $r2;
*
* label1:
* $r3 := @caughtexception;
* r1 = $r3;
* $r4 = .new java.lang.NoClassDefFoundError;
* $r5 = .virtualinvoke r1.<java.lang.Throwable: java.lang.String getMessage()>();
* .specialinvoke $r4.<java.lang.NoClassDefFoundError: .void <init>(java.lang.String)>($r5);
* .throw $r4;
*
* .catch java.lang.ClassNotFoundException .from label0 .to label1 .with label1;
* }
* </pre>
*/
public SootMethod createClassFetcherFor(SootClass c, String methodName) {
// Create the method
SootMethod method = Scene.v().makeSootMethod(methodName, Arrays.asList(new Type[] { RefType.v("java.lang.String") }), RefType.v("java.lang.Class"), Modifier.STATIC);
c.addMethod(method);
// Create the method body
{
JimpleBody body = Jimple.v().newBody(method);
method.setActiveBody(body);
Chain units = body.getUnits();
Local l_r0, l_r1, l_r2, l_r3, l_r4, l_r5;
// Add some locals
l_r0 = Jimple.v().newLocal("r0", RefType.v("java.lang.String"));
l_r1 = Jimple.v().newLocal("r1", RefType.v("java.lang.ClassNotFoundException"));
l_r2 = Jimple.v().newLocal("$r2", RefType.v("java.lang.Class"));
l_r3 = Jimple.v().newLocal("$r3", RefType.v("java.lang.ClassNotFoundException"));
l_r4 = Jimple.v().newLocal("$r4", RefType.v("java.lang.NoClassDefFoundError"));
l_r5 = Jimple.v().newLocal("$r5", RefType.v("java.lang.String"));
body.getLocals().add(l_r0);
body.getLocals().add(l_r1);
body.getLocals().add(l_r2);
body.getLocals().add(l_r3);
body.getLocals().add(l_r4);
body.getLocals().add(l_r5);
// add "r0 := @parameter0: java.lang.String"
units.add(Jimple.v().newIdentityStmt(l_r0, Jimple.v().newParameterRef(RefType.v("java.lang.String"), 0)));
// add "$r2 = .staticinvoke <java.lang.Class: java.lang.Class
// forName(java.lang.String)>(r0);
AssignStmt asi;
units.add(asi = Jimple.v().newAssignStmt(l_r2, Jimple.v().newStaticInvokeExpr(Scene.v().getMethod("<java.lang.Class: java.lang.Class" + " forName(java.lang.String)>").makeRef(), Arrays.asList(new Value[] { l_r0 }))));
// insert "return $r2;"
units.add(Jimple.v().newReturnStmt(l_r2));
// add "r3 := @caughtexception;"
Stmt handlerStart;
units.add(handlerStart = Jimple.v().newIdentityStmt(l_r3, Jimple.v().newCaughtExceptionRef()));
// add "r1 = r3;"
units.add(Jimple.v().newAssignStmt(l_r1, l_r3));
// add "$r4 = .new java.lang.NoClassDefFoundError;"
units.add(Jimple.v().newAssignStmt(l_r4, Jimple.v().newNewExpr(RefType.v("java.lang.NoClassDefFoundError"))));
// add "$r5 = virtualinvoke r1.<java.lang.Throwable:
// java.lang.String getMessage()>();"
units.add(Jimple.v().newAssignStmt(l_r5, Jimple.v().newVirtualInvokeExpr(l_r1, Scene.v().getMethod("<java.lang.Throwable: java.lang.String getMessage()>").makeRef(), new LinkedList())));
// add .specialinvoke $r4.<java.lang.NoClassDefFoundError: .void
// <init>(java.lang.String)>($r5);
units.add(Jimple.v().newInvokeStmt(Jimple.v().newSpecialInvokeExpr(l_r4, Scene.v().getMethod("<java.lang.NoClassDefFoundError: void" + " <init>(java.lang.String)>").makeRef(), Arrays.asList(new Value[] { l_r5 }))));
// add .throw $r4;
units.add(Jimple.v().newThrowStmt(l_r4));
body.getTraps().add(Jimple.v().newTrap(Scene.v().getSootClass("java.lang.ClassNotFoundException"), asi, handlerStart, handlerStart));
}
return method;
}
use of soot.util.Chain in project soot by Sable.
the class SynchronizerManager method addStmtsToFetchClassBefore.
/**
* Adds code to fetch the static Class object to the given JimpleBody before
* the target Stmt.
*
* Uses our custom classToClassField field to cache the results.
*
* The code will look like this:
*
* <pre>
* $r3 = <quack: java.lang.Class class$quack>;
* .if $r3 != .null .goto label2;
*
* $r3 = .staticinvoke <quack: java.lang.Class class$(java.lang.String)>("quack");
* <quack: java.lang.Class class$quack> = $r3;
*
* label2:
* </pre>
*/
public Local addStmtsToFetchClassBefore(JimpleBody jb, Stmt target) {
SootClass sc = jb.getMethod().getDeclaringClass();
SootField classCacher = classToClassField.get(sc);
if (classCacher == null) {
// Add a unique field named [__]class$name
String n = "class$" + sc.getName().replace('.', '$');
while (sc.declaresFieldByName(n)) n = "_" + n;
classCacher = Scene.v().makeSootField(n, RefType.v("java.lang.Class"), Modifier.STATIC);
sc.addField(classCacher);
classToClassField.put(sc, classCacher);
}
String lName = "$uniqueClass";
// Find unique name. Not strictly necessary unless we parse Jimple code.
while (true) {
Iterator it = jb.getLocals().iterator();
boolean oops = false;
while (it.hasNext()) {
Local jbLocal = (Local) it.next();
if (jbLocal.getName().equals(lName))
oops = true;
}
if (!oops)
break;
lName = "_" + lName;
}
Local l = Jimple.v().newLocal(lName, RefType.v("java.lang.Class"));
jb.getLocals().add(l);
Chain units = jb.getUnits();
units.insertBefore(Jimple.v().newAssignStmt(l, Jimple.v().newStaticFieldRef(classCacher.makeRef())), target);
IfStmt ifStmt;
units.insertBefore(ifStmt = Jimple.v().newIfStmt(Jimple.v().newNeExpr(l, NullConstant.v()), target), target);
units.insertBefore(Jimple.v().newAssignStmt(l, Jimple.v().newStaticInvokeExpr(getClassFetcherFor(sc).makeRef(), Arrays.asList(new Value[] { StringConstant.v(sc.getName()) }))), target);
units.insertBefore(Jimple.v().newAssignStmt(Jimple.v().newStaticFieldRef(classCacher.makeRef()), l), target);
ifStmt.setTarget(target);
return l;
}
Aggregations