use of soot.jimple.FieldRef in project soot by Sable.
the class ArrayIndexLivenessAnalysis method getAllRelatedMaps.
private void getAllRelatedMaps(Body body) {
Iterator unitIt = body.getUnits().iterator();
while (unitIt.hasNext()) {
Stmt stmt = (Stmt) unitIt.next();
if (csin) {
if (stmt instanceof DefinitionStmt) {
Value rhs = ((DefinitionStmt) stmt).getRightOp();
if (rhs instanceof BinopExpr) {
Value op1 = ((BinopExpr) rhs).getOp1();
Value op2 = ((BinopExpr) rhs).getOp2();
if (rhs instanceof AddExpr) {
// op1 + op2 --> a + b
if ((op1 instanceof Local) && (op2 instanceof Local)) {
HashSet<Value> refs = localToExpr.get(op1);
if (refs == null) {
refs = new HashSet<Value>();
localToExpr.put(op1, refs);
}
refs.add(rhs);
refs = localToExpr.get(op2);
if (refs == null) {
refs = new HashSet<Value>();
localToExpr.put(op2, refs);
}
refs.add(rhs);
}
} else // a * b, a * c, c * a
if (rhs instanceof MulExpr) {
HashSet<Value> refs = localToExpr.get(op1);
if (refs == null) {
refs = new HashSet<Value>();
localToExpr.put(op1, refs);
}
refs.add(rhs);
refs = localToExpr.get(op2);
if (refs == null) {
refs = new HashSet<Value>();
localToExpr.put(op2, refs);
}
refs.add(rhs);
} else if (rhs instanceof SubExpr) {
if (op2 instanceof Local) {
HashSet<Value> refs = localToExpr.get(op2);
if (refs == null) {
refs = new HashSet<Value>();
localToExpr.put(op2, refs);
}
refs.add(rhs);
if (op1 instanceof Local) {
refs = localToExpr.get(op1);
if (refs == null) {
refs = new HashSet<Value>();
localToExpr.put(op1, refs);
}
refs.add(rhs);
}
}
}
}
}
}
for (ValueBox vbox : stmt.getUseAndDefBoxes()) {
Value v = vbox.getValue();
if (fieldin) {
if (v instanceof InstanceFieldRef) {
Value base = ((InstanceFieldRef) v).getBase();
SootField field = ((InstanceFieldRef) v).getField();
HashSet<Value> baseset = localToFieldRef.get(base);
if (baseset == null) {
baseset = new HashSet<Value>();
localToFieldRef.put(base, baseset);
}
baseset.add(v);
HashSet<Value> fieldset = fieldToFieldRef.get(field);
if (fieldset == null) {
fieldset = new HashSet<Value>();
fieldToFieldRef.put(field, fieldset);
}
fieldset.add(v);
}
if (v instanceof FieldRef)
allFieldRefs.add(v);
}
if (arrayin) {
// a = ... --> kill all a[x] nodes.
// a[i] = .. --> kill all array references.
// m(a) --> kill all array references
// i = ... --> kill all array reference with index as i
/*
if (v instanceof ArrayRef)
{
Value base = ((ArrayRef)v).getBase();
Value index = ((ArrayRef)v).getIndex();
HashSet refset = (HashSet)localToArrayRef.get(base);
if (refset == null)
{
refset = new HashSet();
localToArrayRef.put(base, refset);
}
refset.add(v);
if (index instanceof Local)
{
refset = (HashSet)localToArrayRef.get(index);
if (refset == null)
{
refset = new HashSet();
localToArrayRef.put(index, refset);
}
refset.add(v);
}
allArrayRefs.add(v);
}
*/
}
}
}
}
use of soot.jimple.FieldRef in project soot by Sable.
the class DeadAssignmentEliminator method internalTransform.
/**
* Eliminates dead code in a linear fashion. Complexity is linear
* with respect to the statements.
*
* Does not work on grimp code because of the check on the right hand
* side for side effects.
*/
@Override
protected void internalTransform(Body b, String phaseName, Map<String, String> options) {
boolean eliminateOnlyStackLocals = PhaseOptions.getBoolean(options, "only-stack-locals");
final Options soptions = Options.v();
if (soptions.verbose()) {
logger.debug("[" + b.getMethod().getName() + "] Eliminating dead code...");
}
if (soptions.time()) {
Timers.v().deadCodeTimer.start();
}
Chain<Unit> units = b.getUnits();
Deque<Unit> q = new ArrayDeque<Unit>(units.size());
// Make a first pass through the statements, noting
// the statements we must absolutely keep.
boolean isStatic = b.getMethod().isStatic();
boolean allEssential = true;
boolean checkInvoke = false;
Local thisLocal = null;
for (Iterator<Unit> it = units.iterator(); it.hasNext(); ) {
Unit s = it.next();
boolean isEssential = true;
if (s instanceof NopStmt) {
// Hack: do not remove nop if is is used for a Trap
// which is at the very end of the code.
boolean removeNop = it.hasNext();
if (!removeNop) {
removeNop = true;
for (Trap t : b.getTraps()) {
if (t.getEndUnit() == s) {
removeNop = false;
break;
}
}
}
if (removeNop) {
it.remove();
continue;
}
} else if (s instanceof AssignStmt) {
AssignStmt as = (AssignStmt) s;
Value lhs = as.getLeftOp();
Value rhs = as.getRightOp();
// Stmt is of the form a = a which is useless
if (lhs == rhs && lhs instanceof Local) {
it.remove();
continue;
}
if (lhs instanceof Local && (!eliminateOnlyStackLocals || ((Local) lhs).getName().startsWith("$") || lhs.getType() instanceof NullType)) {
isEssential = false;
if (!checkInvoke) {
checkInvoke = as.containsInvokeExpr();
}
if (rhs instanceof CastExpr) {
// CastExpr : can trigger ClassCastException, but null-casts never fail
CastExpr ce = (CastExpr) rhs;
Type t = ce.getCastType();
Value v = ce.getOp();
isEssential = !(v instanceof NullConstant && t instanceof RefType);
} else if (rhs instanceof InvokeExpr || rhs instanceof ArrayRef || rhs instanceof NewExpr || rhs instanceof NewArrayExpr || rhs instanceof NewMultiArrayExpr) {
// ArrayRef : can have side effects (like throwing a null pointer exception)
// InvokeExpr : can have side effects (like throwing a null pointer exception)
// NewArrayExpr : can throw exception
// NewMultiArrayExpr : can throw exception
// NewExpr : can trigger class initialization
isEssential = true;
} else if (rhs instanceof FieldRef) {
// Can trigger class initialization
isEssential = true;
if (rhs instanceof InstanceFieldRef) {
InstanceFieldRef ifr = (InstanceFieldRef) rhs;
if (!isStatic && thisLocal == null) {
thisLocal = b.getThisLocal();
}
// Any InstanceFieldRef may have side effects,
// unless the base is reading from 'this'
// in a non-static method
isEssential = (isStatic || thisLocal != ifr.getBase());
}
} else if (rhs instanceof DivExpr || rhs instanceof RemExpr) {
BinopExpr expr = (BinopExpr) rhs;
Type t1 = expr.getOp1().getType();
Type t2 = expr.getOp2().getType();
// Can trigger a division by zero
boolean t2Int = t2 instanceof IntType;
isEssential = t2Int || t1 instanceof IntType || t1 instanceof LongType || t2 instanceof LongType || t1 instanceof UnknownType || t2 instanceof UnknownType;
if (isEssential && t2Int) {
Value v = expr.getOp2();
if (v instanceof IntConstant) {
IntConstant i = (IntConstant) v;
isEssential = (i.value == 0);
} else
// could be 0, we don't know
isEssential = true;
}
if (isEssential && t2 instanceof LongType) {
Value v = expr.getOp2();
if (v instanceof LongConstant) {
LongConstant l = (LongConstant) v;
isEssential = (l.value == 0);
} else
// could be 0, we don't know
isEssential = true;
}
}
}
}
if (isEssential) {
q.addFirst(s);
}
allEssential &= isEssential;
}
if (checkInvoke || !allEssential) {
// Add all the statements which are used to compute values
// for the essential statements, recursively
final LocalDefs localDefs = LocalDefs.Factory.newLocalDefs(b);
if (!allEssential) {
Set<Unit> essential = new HashSet<Unit>(b.getUnits().size());
while (!q.isEmpty()) {
Unit s = q.removeFirst();
if (essential.add(s)) {
for (ValueBox box : s.getUseBoxes()) {
Value v = box.getValue();
if (v instanceof Local) {
Local l = (Local) v;
List<Unit> defs = localDefs.getDefsOfAt(l, s);
if (defs != null)
q.addAll(defs);
}
}
}
}
// Remove the dead statements
units.retainAll(essential);
}
if (checkInvoke) {
final LocalUses localUses = LocalUses.Factory.newLocalUses(b, localDefs);
// Eliminate dead assignments from invokes such as x = f(), where
// x is no longer used
List<AssignStmt> postProcess = new ArrayList<AssignStmt>();
for (Unit u : units) {
if (u instanceof AssignStmt) {
AssignStmt s = (AssignStmt) u;
if (s.containsInvokeExpr()) {
// Just find one use of l which is essential
boolean deadAssignment = true;
for (UnitValueBoxPair pair : localUses.getUsesOf(s)) {
if (units.contains(pair.unit)) {
deadAssignment = false;
break;
}
}
if (deadAssignment) {
postProcess.add(s);
}
}
}
}
final Jimple jimple = Jimple.v();
for (AssignStmt s : postProcess) {
// Transform it into a simple invoke.
Stmt newInvoke = jimple.newInvokeStmt(s.getInvokeExpr());
newInvoke.addAllTagsOf(s);
units.swapWith(s, newInvoke);
// If we have a callgraph, we need to fix it
if (Scene.v().hasCallGraph())
Scene.v().getCallGraph().swapEdgesOutOf(s, newInvoke);
}
}
}
if (soptions.time()) {
Timers.v().deadCodeTimer.end();
}
}
use of soot.jimple.FieldRef in project soot by Sable.
the class Validate method validateArrays.
public static void validateArrays(Body b) {
Set<DefinitionStmt> definitions = new HashSet<DefinitionStmt>();
Set<Unit> unitWithArrayRef = new HashSet<Unit>();
for (Unit u : b.getUnits()) {
if (u instanceof DefinitionStmt) {
DefinitionStmt s = (DefinitionStmt) u;
definitions.add(s);
}
List<ValueBox> uses = u.getUseBoxes();
for (ValueBox vb : uses) {
Value v = vb.getValue();
if (v instanceof ArrayRef) {
unitWithArrayRef.add(u);
}
}
}
final LocalDefs localDefs = LocalDefs.Factory.newLocalDefs(b, true);
Set<Unit> toReplace = new HashSet<Unit>();
for (Unit u : unitWithArrayRef) {
boolean ok = false;
List<ValueBox> uses = u.getUseBoxes();
for (ValueBox vb : uses) {
Value v = vb.getValue();
if (v instanceof ArrayRef) {
ArrayRef ar = (ArrayRef) v;
Local base = (Local) ar.getBase();
List<Unit> defs = localDefs.getDefsOfAt(base, u);
// add aliases
Set<Unit> alreadyHandled = new HashSet<Unit>();
while (true) {
boolean isMore = false;
for (Unit d : defs) {
if (alreadyHandled.contains(d))
continue;
if (d instanceof AssignStmt) {
AssignStmt ass = (AssignStmt) d;
Value r = ass.getRightOp();
if (r instanceof Local) {
defs.addAll(localDefs.getDefsOfAt((Local) r, d));
alreadyHandled.add(d);
isMore = true;
break;
} else if (r instanceof ArrayRef) {
ArrayRef arrayRef = (ArrayRef) r;
Local l = (Local) arrayRef.getBase();
defs.addAll(localDefs.getDefsOfAt(l, d));
alreadyHandled.add(d);
isMore = true;
break;
}
}
}
if (!isMore)
break;
}
// System.out.println("def size "+ defs.size());
for (Unit def : defs) {
// System.out.println("def u "+ def);
Value r = null;
if (def instanceof IdentityStmt) {
IdentityStmt idstmt = (IdentityStmt) def;
r = idstmt.getRightOp();
} else if (def instanceof AssignStmt) {
AssignStmt assStmt = (AssignStmt) def;
r = assStmt.getRightOp();
} else {
throw new RuntimeException("error: definition statement not an IdentityStmt nor an AssignStmt! " + def);
}
Type t = null;
if (r instanceof InvokeExpr) {
InvokeExpr ie = (InvokeExpr) r;
t = ie.getType();
// System.out.println("ie type: "+ t +" "+ t.getClass());
if (t instanceof ArrayType)
ok = true;
} else if (r instanceof FieldRef) {
FieldRef ref = (FieldRef) r;
t = ref.getType();
// System.out.println("fr type: "+ t +" "+ t.getClass());
if (t instanceof ArrayType)
ok = true;
} else if (r instanceof IdentityRef) {
IdentityRef ir = (IdentityRef) r;
t = ir.getType();
if (t instanceof ArrayType)
ok = true;
} else if (r instanceof CastExpr) {
CastExpr c = (CastExpr) r;
t = c.getType();
if (t instanceof ArrayType)
ok = true;
} else if (r instanceof ArrayRef) {
// we also check that this arrayref is correctly defined
} else if (r instanceof NewArrayExpr) {
ok = true;
} else if (r instanceof Local) {
} else if (r instanceof Constant) {
} else {
throw new RuntimeException("error: unknown right hand side of definition stmt " + def);
}
if (ok)
break;
}
if (ok)
break;
}
}
if (!ok) {
toReplace.add(u);
}
}
int i = 0;
for (Unit u : toReplace) {
System.out.println("warning: incorrect array def, replacing unit " + u);
// new object
RefType throwableType = RefType.v("java.lang.Throwable");
Local ttt = Jimple.v().newLocal("ttt_" + ++i, throwableType);
b.getLocals().add(ttt);
Value r = Jimple.v().newNewExpr(throwableType);
Unit initLocalUnit = Jimple.v().newAssignStmt(ttt, r);
// call <init> method with a string parameter for message
List<String> pTypes = new ArrayList<String>();
pTypes.add("java.lang.String");
boolean isStatic = false;
SootMethodRef mRef = Validate.makeMethodRef("java.lang.Throwable", "<init>", "", pTypes, isStatic);
List<Value> parameters = new ArrayList<Value>();
parameters.add(StringConstant.v("Soot updated this instruction"));
InvokeExpr ie = Jimple.v().newSpecialInvokeExpr(ttt, mRef, parameters);
Unit initMethod = Jimple.v().newInvokeStmt(ie);
// throw exception
Unit newUnit = Jimple.v().newThrowStmt(ttt);
// change instruction in body
b.getUnits().swapWith(u, newUnit);
b.getUnits().insertBefore(initMethod, newUnit);
b.getUnits().insertBefore(initLocalUnit, initMethod);
// Exception a = throw new Exception();
}
DeadAssignmentEliminator.v().transform(b);
UnusedLocalEliminator.v().transform(b);
NopEliminator.v().transform(b);
UnreachableCodeEliminator.v().transform(b);
}
use of soot.jimple.FieldRef in project soot by Sable.
the class ConstantValueToInitializerTransformer method getOrCreateInitializer.
private SootMethod getOrCreateInitializer(SootClass sc, Set<SootField> alreadyInitialized) {
SootMethod smInit;
// Create a static initializer if we don't already have one
smInit = sc.getMethodByNameUnsafe("<clinit>");
if (smInit == null) {
smInit = Scene.v().makeSootMethod("<clinit>", Collections.<Type>emptyList(), VoidType.v());
smInit.setActiveBody(Jimple.v().newBody(smInit));
sc.addMethod(smInit);
smInit.setModifiers(Modifier.PUBLIC | Modifier.STATIC);
} else if (smInit.isPhantom())
return null;
else {
smInit.retrieveActiveBody();
// somewhere
for (Unit u : smInit.getActiveBody().getUnits()) {
Stmt s = (Stmt) u;
for (ValueBox vb : s.getDefBoxes()) if (vb.getValue() instanceof FieldRef)
alreadyInitialized.add(((FieldRef) vb.getValue()).getField());
}
}
return smInit;
}
use of soot.jimple.FieldRef in project soot by Sable.
the class BadFields method handleMethod.
private void handleMethod(SootMethod m) {
if (!m.isConcrete())
return;
for (Iterator<ValueBox> bIt = m.retrieveActiveBody().getUseAndDefBoxes().iterator(); bIt.hasNext(); ) {
final ValueBox b = bIt.next();
Value v = b.getValue();
if (!(v instanceof StaticFieldRef))
continue;
StaticFieldRef sfr = (StaticFieldRef) v;
SootField f = sfr.getField();
if (!f.getDeclaringClass().getName().equals("java.lang.System"))
continue;
if (f.getName().equals("err")) {
logger.debug("" + "Use of System.err in " + m);
}
if (f.getName().equals("out")) {
logger.debug("" + "Use of System.out in " + m);
}
}
for (Iterator<Unit> sIt = m.getActiveBody().getUnits().iterator(); sIt.hasNext(); ) {
final Stmt s = (Stmt) sIt.next();
if (!s.containsInvokeExpr())
continue;
InvokeExpr ie = s.getInvokeExpr();
SootMethod target = ie.getMethod();
if (target.getDeclaringClass().getName().equals("java.lang.System") && target.getName().equals("exit")) {
warn("" + m + " calls System.exit");
}
}
if (m.getName().equals("<clinit>")) {
for (Iterator<Unit> sIt = m.getActiveBody().getUnits().iterator(); sIt.hasNext(); ) {
final Stmt s = (Stmt) sIt.next();
for (Iterator<ValueBox> bIt = s.getUseBoxes().iterator(); bIt.hasNext(); ) {
final ValueBox b = bIt.next();
Value v = b.getValue();
if (v instanceof FieldRef) {
warn(m.getName() + " reads field " + v);
}
}
if (!s.containsInvokeExpr())
continue;
InvokeExpr ie = s.getInvokeExpr();
SootMethod target = ie.getMethod();
calls(target);
}
}
}
Aggregations