use of soot.jimple.AssignStmt in project soot by Sable.
the class DexNumTransformer method internalTransform.
@Override
protected void internalTransform(final Body body, String phaseName, Map<String, String> options) {
final DexDefUseAnalysis localDefs = new DexDefUseAnalysis(body);
for (Local loc : getNumCandidates(body)) {
usedAsFloatingPoint = false;
Set<Unit> defs = localDefs.collectDefinitionsWithAliases(loc);
// process normally
doBreak = false;
for (Unit u : defs) {
// put correct local in l
final Local l = u instanceof DefinitionStmt ? (Local) ((DefinitionStmt) u).getLeftOp() : null;
// check defs
u.apply(new AbstractStmtSwitch() {
@Override
public void caseAssignStmt(AssignStmt stmt) {
Value r = stmt.getRightOp();
if (r instanceof BinopExpr && !(r instanceof CmpExpr)) {
usedAsFloatingPoint = examineBinopExpr(stmt);
doBreak = true;
} else if (r instanceof FieldRef) {
usedAsFloatingPoint = isFloatingPointLike(((FieldRef) r).getFieldRef().type());
doBreak = true;
} else if (r instanceof NewArrayExpr) {
NewArrayExpr nae = (NewArrayExpr) r;
Type t = nae.getType();
usedAsFloatingPoint = isFloatingPointLike(t);
doBreak = true;
} else if (r instanceof ArrayRef) {
ArrayRef ar = (ArrayRef) r;
Type arType = ar.getType();
if (arType instanceof UnknownType) {
Type t = findArrayType(localDefs, stmt, 0, // TODO:
Collections.<Unit>emptySet());
// check
// where
// else
// to
// update
// if(ArrayRef...
usedAsFloatingPoint = isFloatingPointLike(t);
} else {
usedAsFloatingPoint = isFloatingPointLike(ar.getType());
}
doBreak = true;
} else if (r instanceof CastExpr) {
usedAsFloatingPoint = isFloatingPointLike(((CastExpr) r).getCastType());
doBreak = true;
} else if (r instanceof InvokeExpr) {
usedAsFloatingPoint = isFloatingPointLike(((InvokeExpr) r).getType());
doBreak = true;
} else if (r instanceof LengthExpr) {
usedAsFloatingPoint = false;
doBreak = true;
}
}
@Override
public void caseIdentityStmt(IdentityStmt stmt) {
if (stmt.getLeftOp() == l) {
usedAsFloatingPoint = isFloatingPointLike(stmt.getRightOp().getType());
doBreak = true;
}
}
});
if (doBreak) {
break;
}
// check uses
for (Unit use : localDefs.getUsesOf(l)) {
use.apply(new AbstractStmtSwitch() {
private boolean examineInvokeExpr(InvokeExpr e) {
List<Value> args = e.getArgs();
List<Type> argTypes = e.getMethodRef().parameterTypes();
assert args.size() == argTypes.size();
for (int i = 0; i < args.size(); i++) {
if (args.get(i) == l && isFloatingPointLike(argTypes.get(i))) {
return true;
}
}
return false;
}
@Override
public void caseInvokeStmt(InvokeStmt stmt) {
InvokeExpr e = stmt.getInvokeExpr();
usedAsFloatingPoint = examineInvokeExpr(e);
}
@Override
public void caseAssignStmt(AssignStmt stmt) {
// only case where 'l' could be on the left side is
// arrayRef with 'l' as the index
Value left = stmt.getLeftOp();
if (left instanceof ArrayRef) {
ArrayRef ar = (ArrayRef) left;
if (ar.getIndex() == l) {
doBreak = true;
return;
}
}
// from this point, we only check the right hand
// side of the assignment
Value r = stmt.getRightOp();
if (r instanceof ArrayRef) {
if (((ArrayRef) r).getIndex() == l) {
doBreak = true;
return;
}
} else if (r instanceof InvokeExpr) {
usedAsFloatingPoint = examineInvokeExpr((InvokeExpr) r);
doBreak = true;
return;
} else if (r instanceof BinopExpr) {
usedAsFloatingPoint = examineBinopExpr(stmt);
doBreak = true;
return;
} else if (r instanceof CastExpr) {
usedAsFloatingPoint = stmt.hasTag("FloatOpTag") || stmt.hasTag("DoubleOpTag");
doBreak = true;
return;
} else if (r instanceof Local && r == l) {
if (left instanceof FieldRef) {
FieldRef fr = (FieldRef) left;
if (isFloatingPointLike(fr.getType())) {
usedAsFloatingPoint = true;
}
doBreak = true;
return;
} else if (left instanceof ArrayRef) {
ArrayRef ar = (ArrayRef) left;
Type arType = ar.getType();
if (arType instanceof UnknownType) {
arType = findArrayType(localDefs, stmt, 0, Collections.<Unit>emptySet());
}
usedAsFloatingPoint = isFloatingPointLike(arType);
doBreak = true;
return;
}
}
}
@Override
public void caseReturnStmt(ReturnStmt stmt) {
usedAsFloatingPoint = stmt.getOp() == l && isFloatingPointLike(body.getMethod().getReturnType());
doBreak = true;
return;
}
});
if (doBreak)
break;
}
// for uses
if (doBreak)
break;
}
// change values
if (usedAsFloatingPoint) {
for (Unit u : defs) {
replaceWithFloatingPoint(u);
}
}
// end if
}
}
use of soot.jimple.AssignStmt in project soot by Sable.
the class DexNumTransformer method replaceWithFloatingPoint.
/**
* Replace 0 with null in the given unit.
*
* @param u
* the unit where 0 will be replaced with null.
*/
private void replaceWithFloatingPoint(Unit u) {
if (u instanceof AssignStmt) {
AssignStmt s = (AssignStmt) u;
Value v = s.getRightOp();
if ((v instanceof IntConstant)) {
int vVal = ((IntConstant) v).value;
s.setRightOp(FloatConstant.v(Float.intBitsToFloat(vVal)));
} else if (v instanceof LongConstant) {
long vVal = ((LongConstant) v).value;
s.setRightOp(DoubleConstant.v(Double.longBitsToDouble(vVal)));
}
}
}
use of soot.jimple.AssignStmt in project soot by Sable.
the class DexTransformer method findArrayType.
protected Type findArrayType(LocalDefs localDefs, Stmt arrayStmt, int depth, Set<Unit> alreadyVisitedDefs) {
ArrayRef aRef = null;
if (arrayStmt.containsArrayRef()) {
aRef = arrayStmt.getArrayRef();
}
Local aBase = null;
if (null == aRef) {
if (arrayStmt instanceof AssignStmt) {
AssignStmt stmt = (AssignStmt) arrayStmt;
aBase = (Local) stmt.getRightOp();
} else {
throw new RuntimeException("ERROR: not an assign statement: " + arrayStmt);
}
} else {
aBase = (Local) aRef.getBase();
}
List<Unit> defsOfaBaseList = localDefs.getDefsOfAt(aBase, arrayStmt);
if (defsOfaBaseList == null || defsOfaBaseList.isEmpty()) {
throw new RuntimeException("ERROR: no def statement found for array base local " + arrayStmt);
}
// We should find an answer only by processing the first item of the
// list
Type aType = null;
int nullDefCount = 0;
for (Unit baseDef : defsOfaBaseList) {
if (alreadyVisitedDefs.contains(baseDef))
continue;
Set<Unit> newVisitedDefs = new HashSet<Unit>(alreadyVisitedDefs);
newVisitedDefs.add(baseDef);
// statement
if (baseDef instanceof AssignStmt) {
AssignStmt stmt = (AssignStmt) baseDef;
Value r = stmt.getRightOp();
if (r instanceof FieldRef) {
Type t = ((FieldRef) r).getFieldRef().type();
if (t instanceof ArrayType) {
ArrayType at = (ArrayType) t;
t = at.getArrayElementType();
}
if (depth == 0) {
aType = t;
break;
} else {
return t;
}
} else if (r instanceof ArrayRef) {
ArrayRef ar = (ArrayRef) r;
if (ar.getType().toString().equals(".unknown") || ar.getType().toString().equals("unknown")) {
// ||
// ar.getType())
// {
Type t = findArrayType(localDefs, stmt, ++depth, // TODO: which type should be
newVisitedDefs);
// returned?
if (t instanceof ArrayType) {
ArrayType at = (ArrayType) t;
t = at.getArrayElementType();
}
if (depth == 0) {
aType = t;
break;
} else {
return t;
}
} else {
ArrayType at = (ArrayType) stmt.getRightOp().getType();
Type t = at.getArrayElementType();
if (depth == 0) {
aType = t;
break;
} else {
return t;
}
}
} else if (r instanceof NewArrayExpr) {
NewArrayExpr expr = (NewArrayExpr) r;
Type t = expr.getBaseType();
if (depth == 0) {
aType = t;
break;
} else {
return t;
}
} else if (r instanceof CastExpr) {
Type t = (((CastExpr) r).getCastType());
if (t instanceof ArrayType) {
ArrayType at = (ArrayType) t;
t = at.getArrayElementType();
}
if (depth == 0) {
aType = t;
break;
} else {
return t;
}
} else if (r instanceof InvokeExpr) {
Type t = ((InvokeExpr) r).getMethodRef().returnType();
if (t instanceof ArrayType) {
ArrayType at = (ArrayType) t;
t = at.getArrayElementType();
}
if (depth == 0) {
aType = t;
break;
} else {
return t;
}
// introduces alias. We look whether there is any type
// information associated with the alias.
} else if (r instanceof Local) {
Type t = findArrayType(localDefs, stmt, ++depth, newVisitedDefs);
if (depth == 0) {
aType = t;
// break;
} else {
// return t;
aType = t;
}
} else if (r instanceof Constant) {
// If the right side is a null constant, we might have a
// case of broken code, e.g.,
// a = null;
// a[12] = 42;
nullDefCount++;
} else {
throw new RuntimeException("ERROR: def statement not possible! " + stmt);
}
} else if (baseDef instanceof IdentityStmt) {
IdentityStmt stmt = (IdentityStmt) baseDef;
ArrayType at = (ArrayType) stmt.getRightOp().getType();
Type t = at.getArrayElementType();
if (depth == 0) {
aType = t;
break;
} else {
return t;
}
} else {
throw new RuntimeException("ERROR: base local def must be AssignStmt or IdentityStmt! " + baseDef);
}
if (aType != null)
break;
}
if (depth == 0 && aType == null) {
if (nullDefCount == defsOfaBaseList.size()) {
return NullType.v();
} else {
throw new RuntimeException("ERROR: could not find type of array from statement '" + arrayStmt + "'");
}
} else
return aType;
}
use of soot.jimple.AssignStmt in project soot by Sable.
the class DexTransformer method collectDefinitionsWithAliases.
/**
* Collect definitions of l in body including the definitions of aliases of
* l.
*
* In this context an alias is a local that propagates its value to l.
*
* @param l
* the local whose definitions are to collect
* @param localDefs
* the LocalDefs object
* @param body
* the body that contains the local
*/
protected List<Unit> collectDefinitionsWithAliases(Local l, LocalDefs localDefs, LocalUses localUses, Body body) {
Set<Local> seenLocals = new HashSet<Local>();
List<Local> newLocals = new ArrayList<Local>();
List<Unit> defs = new ArrayList<Unit>();
newLocals.add(l);
seenLocals.add(l);
while (!newLocals.isEmpty()) {
Local local = newLocals.remove(0);
for (Unit u : collectDefinitions(local, localDefs)) {
if (u instanceof AssignStmt) {
Value r = ((AssignStmt) u).getRightOp();
if (r instanceof Local && seenLocals.add((Local) r))
newLocals.add((Local) r);
}
defs.add(u);
//
List<UnitValueBoxPair> usesOf = localUses.getUsesOf(u);
for (UnitValueBoxPair pair : usesOf) {
Unit unit = pair.getUnit();
if (unit instanceof AssignStmt) {
AssignStmt assignStmt = ((AssignStmt) unit);
Value right = assignStmt.getRightOp();
Value left = assignStmt.getLeftOp();
if (right == local && left instanceof Local && seenLocals.add((Local) left))
newLocals.add((Local) left);
}
}
//
}
}
return defs;
}
use of soot.jimple.AssignStmt in project soot by Sable.
the class AputInstruction method jimplify.
@Override
public void jimplify(DexBody body) {
if (!(instruction instanceof Instruction23x))
throw new IllegalArgumentException("Expected Instruction23x but got: " + instruction.getClass());
Instruction23x aPutInstr = (Instruction23x) instruction;
int source = aPutInstr.getRegisterA();
Local arrayBase = body.getRegisterLocal(aPutInstr.getRegisterB());
Local index = body.getRegisterLocal(aPutInstr.getRegisterC());
ArrayRef arrayRef = Jimple.v().newArrayRef(arrayBase, index);
Local sourceValue = body.getRegisterLocal(source);
AssignStmt assign = getAssignStmt(body, sourceValue, arrayRef);
if (aPutInstr.getOpcode() == Opcode.APUT_OBJECT)
assign.addTag(new ObjectOpTag());
setUnit(assign);
addTags(assign);
body.add(assign);
if (IDalvikTyper.ENABLE_DVKTYPER) {
DalvikTyper.v().addConstraint(assign.getLeftOpBox(), assign.getRightOpBox());
DalvikTyper.v().setType(arrayRef.getIndexBox(), IntType.v(), true);
}
}
Aggregations