use of soot.jimple.ThisRef 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.jimple.ThisRef in project soot by Sable.
the class SiteInliner method inlineSite.
/**
* Inlines the given site. Note that this method does
* not actually check if it's safe (with respect to access modifiers and special invokes)
* for it to be inlined. That functionality is handled by the InlinerSafetyManager.
*/
public static List inlineSite(SootMethod inlinee, Stmt toInline, SootMethod container, Map options) {
boolean enableNullPointerCheckInsertion = PhaseOptions.getBoolean(options, "insert-null-checks");
boolean enableRedundantCastInsertion = PhaseOptions.getBoolean(options, "insert-redundant-casts");
Hierarchy hierarchy = Scene.v().getActiveHierarchy();
JimpleBody containerB = (JimpleBody) container.getActiveBody();
Chain<Unit> containerUnits = containerB.getUnits();
if (!(inlinee.getDeclaringClass().isApplicationClass() || inlinee.getDeclaringClass().isLibraryClass()))
return null;
Body inlineeB = inlinee.getActiveBody();
Chain<Unit> inlineeUnits = inlineeB.getUnits();
InvokeExpr ie = toInline.getInvokeExpr();
Value thisToAdd = null;
if (ie instanceof InstanceInvokeExpr)
thisToAdd = ((InstanceInvokeExpr) ie).getBase();
// Insert casts to please the verifier.
{
boolean targetUsesThis = true;
if (enableRedundantCastInsertion && ie instanceof InstanceInvokeExpr && targetUsesThis) {
// 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 = inlinee.getDeclaringClass();
if (localType.isInterface() || hierarchy.isClassSuperclassOf(localType, parameterType)) {
Local castee = Jimple.v().newLocal("__castee", parameterType.getType());
containerB.getLocals().add(castee);
containerB.getUnits().insertBefore(Jimple.v().newAssignStmt(castee, Jimple.v().newCastExpr(((InstanceInvokeExpr) ie).getBase(), parameterType.getType())), toInline);
thisToAdd = castee;
}
}
}
// (If enabled), add a null pointer check.
{
if (enableNullPointerCheckInsertion && ie instanceof InstanceInvokeExpr) {
boolean caught = TrapManager.isExceptionCaughtAt(Scene.v().getSootClass("java.lang.NullPointerException"), toInline, containerB);
/* 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()), toInline);
containerB.getUnits().insertBefore(insertee, toInline);
// This sucks (but less than before).
((IfStmt) insertee).setTarget(toInline);
ThrowManager.addThrowAfter(containerB, insertee);
} else {
Stmt throwPoint = ThrowManager.getNullPointerExceptionThrower(containerB);
containerB.getUnits().insertBefore(Jimple.v().newIfStmt(Jimple.v().newEqExpr(((InstanceInvokeExpr) ie).getBase(), NullConstant.v()), throwPoint), toInline);
}
}
}
// Add synchronizing stuff.
{
if (inlinee.isSynchronized()) {
// Need to get the class object if ie is a static invoke.
if (ie instanceof InstanceInvokeExpr)
SynchronizerManager.v().synchronizeStmtOn(toInline, containerB, (Local) ((InstanceInvokeExpr) ie).getBase());
else {
// synchronization.
if (!container.getDeclaringClass().isInterface()) {
// Whew!
Local l = SynchronizerManager.v().addStmtsToFetchClassBefore(containerB, toInline);
SynchronizerManager.v().synchronizeStmtOn(toInline, containerB, l);
}
}
}
}
Stmt exitPoint = (Stmt) containerUnits.getSuccOf(toInline);
// First, clone all of the inlinee's units & locals.
HashMap<Local, Local> oldLocalsToNew = new HashMap<Local, Local>();
HashMap<Stmt, Stmt> oldUnitsToNew = new HashMap<Stmt, Stmt>();
{
Stmt cursor = toInline;
for (Iterator<Unit> currIt = inlineeUnits.iterator(); currIt.hasNext(); ) {
final Stmt curr = (Stmt) currIt.next();
Stmt currPrime = (Stmt) curr.clone();
if (currPrime == null)
throw new RuntimeException("getting null from clone!");
currPrime.addAllTagsOf(curr);
containerUnits.insertAfter(currPrime, cursor);
cursor = currPrime;
oldUnitsToNew.put(curr, currPrime);
}
for (Iterator<Local> lIt = inlineeB.getLocals().iterator(); lIt.hasNext(); ) {
final Local l = lIt.next();
Local lPrime = (Local) l.clone();
if (lPrime == null)
throw new RuntimeException("getting null from local clone!");
containerB.getLocals().add(lPrime);
oldLocalsToNew.put(l, lPrime);
}
}
// Backpatch the newly-inserted units using newly-constructed maps.
{
Iterator<Unit> it = containerUnits.iterator(containerUnits.getSuccOf(toInline), containerUnits.getPredOf(exitPoint));
while (it.hasNext()) {
Stmt patchee = (Stmt) it.next();
for (ValueBox box : patchee.getUseAndDefBoxes()) {
if (!(box.getValue() instanceof Local))
continue;
Local lPrime = oldLocalsToNew.get(box.getValue());
if (lPrime != null)
box.setValue(lPrime);
else
throw new RuntimeException("local has no clone!");
}
for (UnitBox box : patchee.getUnitBoxes()) {
Unit uPrime = (oldUnitsToNew.get(box.getUnit()));
if (uPrime != null)
box.setUnit(uPrime);
else
throw new RuntimeException("inlined stmt has no clone!");
}
}
}
// Copy & backpatch the traps; preserve their same order.
{
Trap prevTrap = null;
for (Trap t : inlineeB.getTraps()) {
Stmt newBegin = oldUnitsToNew.get(t.getBeginUnit()), newEnd = oldUnitsToNew.get(t.getEndUnit()), newHandler = oldUnitsToNew.get(t.getHandlerUnit());
if (newBegin == null || newEnd == null || newHandler == null)
throw new RuntimeException("couldn't map trap!");
Trap trap = Jimple.v().newTrap(t.getException(), newBegin, newEnd, newHandler);
if (prevTrap == null)
containerB.getTraps().addFirst(trap);
else
containerB.getTraps().insertAfter(trap, prevTrap);
prevTrap = trap;
}
}
// Handle identity stmt's and returns.
{
Iterator<Unit> it = containerUnits.iterator(containerUnits.getSuccOf(toInline), containerUnits.getPredOf(exitPoint));
ArrayList<Unit> cuCopy = new ArrayList<Unit>();
while (it.hasNext()) {
cuCopy.add(it.next());
}
for (Unit u : cuCopy) {
Stmt s = (Stmt) u;
if (s instanceof IdentityStmt) {
IdentityRef rhs = (IdentityRef) ((IdentityStmt) s).getRightOp();
if (rhs instanceof CaughtExceptionRef)
continue;
else if (rhs instanceof ThisRef) {
if (!(ie instanceof InstanceInvokeExpr))
throw new RuntimeException("thisref with no receiver!");
containerUnits.swapWith(s, Jimple.v().newAssignStmt(((IdentityStmt) s).getLeftOp(), thisToAdd));
} else if (rhs instanceof ParameterRef) {
ParameterRef pref = (ParameterRef) rhs;
containerUnits.swapWith(s, Jimple.v().newAssignStmt(((IdentityStmt) s).getLeftOp(), ie.getArg(pref.getIndex())));
}
} else if (s instanceof ReturnStmt) {
if (toInline instanceof InvokeStmt) {
// munch, munch.
containerUnits.swapWith(s, Jimple.v().newGotoStmt(exitPoint));
continue;
}
if (!(toInline instanceof AssignStmt))
throw new RuntimeException("invoking stmt neither InvokeStmt nor AssignStmt!??!?!");
Value ro = ((ReturnStmt) s).getOp();
Value lhs = ((AssignStmt) toInline).getLeftOp();
AssignStmt as = Jimple.v().newAssignStmt(lhs, ro);
containerUnits.insertBefore(as, s);
containerUnits.swapWith(s, Jimple.v().newGotoStmt(exitPoint));
} else if (s instanceof ReturnVoidStmt)
containerUnits.swapWith(s, Jimple.v().newGotoStmt(exitPoint));
}
}
List<Unit> newStmts = new ArrayList<Unit>();
for (Iterator<Unit> i = containerUnits.iterator(containerUnits.getSuccOf(toInline), containerUnits.getPredOf(exitPoint)); i.hasNext(); ) {
newStmts.add(i.next());
}
// Remove the original statement toInline.
containerUnits.remove(toInline);
// Resolve name collisions.
LocalNameStandardizer.v().transform(containerB, "ji.lns");
return newStmts;
}
use of soot.jimple.ThisRef in project soot by Sable.
the class LocalMustAliasAnalysis method flowThrough.
@Override
protected void flowThrough(HashMap<Value, Integer> in, Unit u, HashMap<Value, Integer> out) {
Stmt s = (Stmt) u;
out.clear();
out.putAll(in);
if (s instanceof DefinitionStmt) {
DefinitionStmt ds = (DefinitionStmt) s;
Value lhs = ds.getLeftOp();
Value rhs = ds.getRightOp();
if (rhs instanceof CastExpr) {
// un-box casted value
CastExpr castExpr = (CastExpr) rhs;
rhs = castExpr.getOp();
}
if ((lhs instanceof Local || (lhs instanceof FieldRef && this.localsAndFieldRefs.contains(new EquivalentValue(lhs)))) && lhs.getType() instanceof RefLikeType) {
if (rhs instanceof Local) {
// local-assignment - must be aliased...
Integer val = in.get(rhs);
if (val != null)
out.put(lhs, val);
} else if (rhs instanceof ThisRef) {
// ThisRef can never change; assign unique number
out.put(lhs, thisRefNumber());
} else if (rhs instanceof ParameterRef) {
// ParameterRef can never change; assign unique number
out.put(lhs, parameterRefNumber((ParameterRef) rhs));
} else {
// assign number for expression
out.put(lhs, numberOfRhs(rhs));
}
}
} else {
// which other kind of statement has def-boxes? hopefully none...
assert s.getDefBoxes().isEmpty();
}
}
use of soot.jimple.ThisRef in project soot by Sable.
the class StmtVisitor method caseIdentityStmt.
@Override
public void caseIdentityStmt(IdentityStmt stmt) {
Local lhs = (Local) stmt.getLeftOp();
Value rhs = stmt.getRightOp();
if (rhs instanceof CaughtExceptionRef) {
// save the caught exception with move-exception
Register localReg = regAlloc.asLocal(lhs);
addInsn(new Insn11x(Opcode.MOVE_EXCEPTION, localReg), stmt);
this.insnRegisterMap.put(insns.get(insns.size() - 1), LocalRegisterAssignmentInformation.v(localReg, lhs));
} else if (rhs instanceof ThisRef || rhs instanceof ParameterRef) {
/*
* do not save the ThisRef or ParameterRef in a local, because it
* always has a parameter register already. at least use the local
* for further reference in the statements
*/
Local localForThis = lhs;
regAlloc.asParameter(belongingMethod, localForThis);
parameterInstructionsList.add(LocalRegisterAssignmentInformation.v(regAlloc.asLocal(localForThis).clone(), localForThis));
} else {
throw new Error("unknown Value as right-hand side of IdentityStmt: " + rhs);
}
}
use of soot.jimple.ThisRef in project soot by Sable.
the class DavaBody method javafy_ref.
private void javafy_ref(ValueBox vb) {
Ref r = (Ref) vb.getValue();
if (r instanceof StaticFieldRef) {
SootFieldRef fieldRef = ((StaticFieldRef) r).getFieldRef();
// addPackage(fieldRef.declaringClass().getJavaPackageName());
String className = fieldRef.declaringClass().toString();
String packageName = fieldRef.declaringClass().getJavaPackageName();
String classPackageName = packageName;
if (className.lastIndexOf('.') > 0) {
// 0 doesnt make sense
classPackageName = className.substring(0, className.lastIndexOf('.'));
}
if (!packageName.equals(classPackageName))
throw new DecompilationException("Unable to retrieve package name for identifier. Please report to developer.");
addToImportList(className);
vb.setValue(new DStaticFieldRef(fieldRef, getMethod().getDeclaringClass().getName()));
} else if (r instanceof ArrayRef) {
ArrayRef ar = (ArrayRef) r;
javafy(ar.getBaseBox());
javafy(ar.getIndexBox());
} else if (r instanceof InstanceFieldRef) {
InstanceFieldRef ifr = (InstanceFieldRef) r;
javafy(ifr.getBaseBox());
vb.setValue(new DInstanceFieldRef(ifr.getBase(), ifr.getFieldRef(), thisLocals));
} else if (r instanceof ThisRef) {
ThisRef tr = (ThisRef) r;
vb.setValue(new DThisRef((RefType) tr.getType()));
}
}
Aggregations