use of soot.jimple.IdentityStmt in project soot by Sable.
the class ThisInliner method internalTransform.
public void internalTransform(Body b, String phaseName, Map options) {
// assure body is a constructor
if (!b.getMethod().getName().equals("<init>"))
return;
// if the first invoke is a this() and not a super() inline the this()
InvokeStmt invokeStmt = getFirstSpecialInvoke(b);
if (invokeStmt == null)
return;
SpecialInvokeExpr specInvokeExpr = (SpecialInvokeExpr) invokeStmt.getInvokeExpr();
if (specInvokeExpr.getMethod().getDeclaringClass().equals(b.getMethod().getDeclaringClass())) {
// put locals from inlinee into container
if (!specInvokeExpr.getMethod().hasActiveBody()) {
specInvokeExpr.getMethod().retrieveActiveBody();
}
HashMap<Local, Local> oldLocalsToNew = new HashMap<Local, Local>();
for (Local l : specInvokeExpr.getMethod().getActiveBody().getLocals()) {
Local newLocal = (Local) l.clone();
b.getLocals().add(newLocal);
oldLocalsToNew.put(l, newLocal);
}
// find identity stmt of original method
IdentityStmt origIdStmt = findIdentityStmt(b);
HashMap<Stmt, Stmt> oldStmtsToNew = new HashMap<Stmt, Stmt>();
// System.out.println("locals: "+b.getLocals());
Chain<Unit> containerUnits = b.getUnits();
for (Unit u : specInvokeExpr.getMethod().getActiveBody().getUnits()) {
Stmt inlineeStmt = (Stmt) u;
// handle identity stmts
if (inlineeStmt instanceof IdentityStmt) {
IdentityStmt idStmt = (IdentityStmt) inlineeStmt;
if (idStmt.getRightOp() instanceof ThisRef) {
Stmt newThis = Jimple.v().newAssignStmt((Local) oldLocalsToNew.get(idStmt.getLeftOp()), origIdStmt.getLeftOp());
containerUnits.insertBefore(newThis, invokeStmt);
oldStmtsToNew.put(inlineeStmt, newThis);
} else if (idStmt.getRightOp() instanceof CaughtExceptionRef) {
Stmt newInlinee = (Stmt) inlineeStmt.clone();
for (ValueBox next : newInlinee.getUseAndDefBoxes()) {
if (next.getValue() instanceof Local) {
next.setValue((Local) oldLocalsToNew.get(next.getValue()));
}
}
containerUnits.insertBefore(newInlinee, invokeStmt);
oldStmtsToNew.put(inlineeStmt, newInlinee);
} else if (idStmt.getRightOp() instanceof ParameterRef) {
Stmt newParam = Jimple.v().newAssignStmt((Local) oldLocalsToNew.get(idStmt.getLeftOp()), specInvokeExpr.getArg(((ParameterRef) idStmt.getRightOp()).getIndex()));
containerUnits.insertBefore(newParam, invokeStmt);
oldStmtsToNew.put(inlineeStmt, newParam);
}
} else // from a constructor)
if (inlineeStmt instanceof ReturnVoidStmt) {
Stmt newRet = Jimple.v().newGotoStmt((Stmt) containerUnits.getSuccOf(invokeStmt));
containerUnits.insertBefore(newRet, invokeStmt);
System.out.println("adding to stmt map: " + inlineeStmt + " and " + newRet);
oldStmtsToNew.put(inlineeStmt, newRet);
} else {
Stmt newInlinee = (Stmt) inlineeStmt.clone();
for (ValueBox next : newInlinee.getUseAndDefBoxes()) {
if (next.getValue() instanceof Local) {
next.setValue((Local) oldLocalsToNew.get(next.getValue()));
}
}
containerUnits.insertBefore(newInlinee, invokeStmt);
oldStmtsToNew.put(inlineeStmt, newInlinee);
}
}
// handleTraps
for (Trap t : specInvokeExpr.getMethod().getActiveBody().getTraps()) {
System.out.println("begin: " + t.getBeginUnit());
Stmt newBegin = oldStmtsToNew.get(t.getBeginUnit());
System.out.println("end: " + t.getEndUnit());
Stmt newEnd = oldStmtsToNew.get(t.getEndUnit());
System.out.println("handler: " + t.getHandlerUnit());
Stmt newHandler = oldStmtsToNew.get(t.getHandlerUnit());
if (newBegin == null || newEnd == null || newHandler == null)
throw new RuntimeException("couldn't map trap!");
b.getTraps().add(Jimple.v().newTrap(t.getException(), newBegin, newEnd, newHandler));
}
// patch gotos
for (Unit u : specInvokeExpr.getMethod().getActiveBody().getUnits()) {
Stmt inlineeStmt = (Stmt) u;
if (inlineeStmt instanceof GotoStmt) {
System.out.println("inlinee goto target: " + ((GotoStmt) inlineeStmt).getTarget());
((GotoStmt) oldStmtsToNew.get(inlineeStmt)).setTarget(oldStmtsToNew.get(((GotoStmt) inlineeStmt).getTarget()));
}
}
// remove original invoke
containerUnits.remove(invokeStmt);
// resolve name collisions
LocalNameStandardizer.v().transform(b, "ji.lns");
}
// System.out.println("locals: "+b.getLocals());
// System.out.println("units: "+b.getUnits());
}
use of soot.jimple.IdentityStmt in project soot by Sable.
the class Body method getParameterRefs.
/**
* Returns the list of parameter references used in this body. The list is as long as
* the number of parameters declared in the associated method's signature.
* The list may have <code>null</code> entries for parameters not referenced in the body.
* The returned list is of fixed size.
*/
public List<Value> getParameterRefs() {
Value[] res = new Value[getMethod().getParameterCount()];
for (Unit s : getUnits()) {
if (s instanceof IdentityStmt) {
Value rightOp = ((IdentityStmt) s).getRightOp();
if (rightOp instanceof ParameterRef) {
ParameterRef parameterRef = (ParameterRef) rightOp;
res[parameterRef.getIndex()] = parameterRef;
}
}
}
return Arrays.asList(res);
}
use of soot.jimple.IdentityStmt in project soot by Sable.
the class Body method getParameterLocal.
/**
* Return LHS of the first identity stmt assigning from \@parameter i. *
*/
public Local getParameterLocal(int i) {
for (Unit s : getUnits()) {
if (s instanceof IdentityStmt && ((IdentityStmt) s).getRightOp() instanceof ParameterRef) {
IdentityStmt is = (IdentityStmt) s;
ParameterRef pr = (ParameterRef) is.getRightOp();
if (pr.getIndex() == i)
return (Local) is.getLeftOp();
}
}
throw new RuntimeException("couldn't find parameterref" + i + "! in " + getMethod());
}
use of soot.jimple.IdentityStmt in project soot by Sable.
the class LibraryMethodWrappersBuilder method getFirstNotIdentityStmt.
private static Unit getFirstNotIdentityStmt(Body body) {
final Iterator<Unit> unitIterator = body.getUnits().snapshotIterator();
while (unitIterator.hasNext()) {
final Unit unit = unitIterator.next();
if (unit instanceof IdentityStmt) {
continue;
}
return unit;
}
logger.debug("There are no non-identity units in the method body.");
return null;
}
use of soot.jimple.IdentityStmt 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");
}
}
}
}
Aggregations