use of soot.jimple.CaughtExceptionRef in project soot by Sable.
the class TypeResolver method applyAssignmentConstraints.
private Collection<Typing> applyAssignmentConstraints(Typing tg, IEvalFunction ef, IHierarchy h) {
final int numAssignments = this.assignments.size();
LinkedList<Typing> sigma = new LinkedList<Typing>(), r = new LinkedList<Typing>();
if (numAssignments == 0)
return sigma;
HashMap<Typing, BitSet> worklists = new HashMap<Typing, BitSet>();
sigma.add(tg);
BitSet wl = new BitSet(numAssignments - 1);
wl.set(0, numAssignments);
worklists.put(tg, wl);
while (!sigma.isEmpty()) {
tg = sigma.element();
wl = worklists.get(tg);
if (wl.isEmpty()) {
r.add(tg);
sigma.remove();
worklists.remove(tg);
} else {
// Get the next definition statement
int defIdx = wl.nextSetBit(0);
wl.clear(defIdx);
DefinitionStmt stmt = this.assignments.get(defIdx);
Value lhs = stmt.getLeftOp(), rhs = stmt.getRightOp();
Local v;
if (lhs instanceof Local)
v = (Local) lhs;
else
v = (Local) ((ArrayRef) lhs).getBase();
Type told = tg.get(v);
Collection<Type> eval = new ArrayList<Type>(ef.eval(tg, rhs, stmt));
boolean isFirstType = true;
for (Type t_ : eval) {
if (lhs instanceof ArrayRef) {
/* We only need to consider array references on the LHS
of assignments where there is supertyping between array
types, which is only for arrays of reference types and
multidimensional arrays. */
if (!(t_ instanceof RefType || t_ instanceof ArrayType)) {
continue;
}
t_ = t_.makeArrayType();
}
// Special handling for exception objects with phantom types
final Collection<Type> lcas;
if (!typesEqual(told, t_) && told instanceof RefType && t_ instanceof RefType && (((RefType) told).getSootClass().isPhantom() || ((RefType) t_).getSootClass().isPhantom()) && (stmt.getRightOp() instanceof CaughtExceptionRef))
lcas = Collections.<Type>singleton(RefType.v("java.lang.Throwable"));
else
lcas = h.lcas(told, t_);
for (Type t : lcas) {
if (!typesEqual(t, told)) {
Typing tg_;
BitSet wl_;
if (/*(eval.size() == 1 && lcas.size() == 1) ||*/
isFirstType) {
// The types agree, we have a type we can directly use
tg_ = tg;
wl_ = wl;
} else {
// The types do not agree, add all supertype candidates
tg_ = new Typing(tg);
wl_ = new BitSet(numAssignments - 1);
wl_.or(wl);
sigma.add(tg_);
worklists.put(tg_, wl_);
}
tg_.set(v, t);
BitSet dependsV = this.depends.get(v);
if (dependsV != null)
wl_.or(dependsV);
}
isFirstType = false;
}
}
// end for
}
}
Typing.minimize(r, h);
return r;
}
use of soot.jimple.CaughtExceptionRef in project soot by Sable.
the class NullnessAnalysis method handleRefTypeAssignment.
private void handleRefTypeAssignment(DefinitionStmt assignStmt, AnalysisInfo out) {
Value left = assignStmt.getLeftOp();
Value right = assignStmt.getRightOp();
// unbox casted value
if (right instanceof JCastExpr) {
JCastExpr castExpr = (JCastExpr) right;
right = castExpr.getOp();
}
// if we have a definition (assignment) statement to a ref-like type, handle it,
if (isAlwaysNonNull(right) || right instanceof NewExpr || right instanceof NewArrayExpr || right instanceof NewMultiArrayExpr || right instanceof ThisRef || right instanceof StringConstant || right instanceof ClassConstant || right instanceof CaughtExceptionRef) {
// if we assign new... or @this, the result is non-null
out.put(left, NON_NULL);
} else if (right == NullConstant.v()) {
// if we assign null, well, it's null
out.put(left, NULL);
} else if (left instanceof Local && right instanceof Local) {
out.put(left, out.get(right));
} else if (left instanceof Local && right instanceof PhiExpr) {
handlePhiExpr(out, left, (PhiExpr) right);
} else {
out.put(left, TOP);
}
}
use of soot.jimple.CaughtExceptionRef 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.CaughtExceptionRef 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.CaughtExceptionRef 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);
}
}
Aggregations