use of soot.ValueBox in project soot by Sable.
the class TypeCastingError method inASTStatementSequenceNode.
public void inASTStatementSequenceNode(ASTStatementSequenceNode node) {
for (AugmentedStmt as : node.getStatements()) {
Stmt s = as.get_Stmt();
if (!(s instanceof DefinitionStmt))
continue;
DefinitionStmt ds = (DefinitionStmt) s;
if (myDebug)
System.out.println("Definition stmt" + ds);
ValueBox rightBox = ds.getRightOpBox();
ValueBox leftBox = ds.getLeftOpBox();
Value right = rightBox.getValue();
Value left = leftBox.getValue();
if (!(left.getType() instanceof PrimType && right.getType() instanceof PrimType)) {
// only interested in prim type casting errors
if (myDebug)
System.out.println("\tDefinition stmt does not contain prims no need to modify");
continue;
}
Type leftType = left.getType();
Type rightType = right.getType();
if (myDebug)
System.out.println("Left type is: " + leftType);
if (myDebug)
System.out.println("Right type is: " + rightType);
if (leftType.equals(rightType)) {
if (myDebug)
System.out.println("\tTypes are the same");
if (myDebug)
System.out.println("Right value is of instance" + right.getClass());
}
if (!leftType.equals(rightType)) {
if (myDebug)
System.out.println("\tDefinition stmt has to be modified");
/*
* byte Byte-length integer 8-bit two's complement
* short Short integer 16-bit two's complement
* int Integer 32-bit two's complement
* long Long integer 64-bit two's complement
* float Single-precision floating point 32-bit IEEE 754
* double Double-precision floating point 64-bit IEEE 754
*/
if (leftType instanceof ByteType && (rightType instanceof DoubleType || rightType instanceof FloatType || rightType instanceof IntType || rightType instanceof LongType || rightType instanceof ShortType)) {
if (DEBUG)
System.out.println("Explicit casting to BYTE required");
rightBox.setValue(new GCastExpr(right, ByteType.v()));
if (DEBUG)
System.out.println("New right expr is " + rightBox.getValue().toString());
continue;
}
if (leftType instanceof ShortType && (rightType instanceof DoubleType || rightType instanceof FloatType || rightType instanceof IntType || rightType instanceof LongType)) {
if (DEBUG)
System.out.println("Explicit casting to SHORT required");
rightBox.setValue(new GCastExpr(right, ShortType.v()));
if (DEBUG)
System.out.println("New right expr is " + rightBox.getValue().toString());
continue;
}
if (leftType instanceof IntType && (rightType instanceof DoubleType || rightType instanceof FloatType || rightType instanceof LongType)) {
if (myDebug)
System.out.println("Explicit casting to INT required");
rightBox.setValue(new GCastExpr(right, IntType.v()));
if (myDebug)
System.out.println("New right expr is " + rightBox.getValue().toString());
continue;
}
if (leftType instanceof LongType && (rightType instanceof DoubleType || rightType instanceof FloatType)) {
if (DEBUG)
System.out.println("Explicit casting to LONG required");
rightBox.setValue(new GCastExpr(right, LongType.v()));
if (DEBUG)
System.out.println("New right expr is " + rightBox.getValue().toString());
continue;
}
if (leftType instanceof FloatType && rightType instanceof DoubleType) {
if (DEBUG)
System.out.println("Explicit casting to FLOAT required");
rightBox.setValue(new GCastExpr(right, FloatType.v()));
if (DEBUG)
System.out.println("New right expr is " + rightBox.getValue().toString());
continue;
}
}
}
}
use of soot.ValueBox in project soot by Sable.
the class DexArrayInitReducer method internalTransform.
@Override
protected void internalTransform(Body b, String phaseName, Map<String, String> options) {
// Make sure that we only have linear control flow
if (!b.getTraps().isEmpty())
return;
// Look for a chain of two constant assignments followed by an array put
Unit u1 = null, u2 = null;
for (Iterator<Unit> uIt = b.getUnits().snapshotIterator(); uIt.hasNext(); ) {
Unit u = uIt.next();
// If this is not an assignment, it does not matter.
if (!(u instanceof AssignStmt) || !((Stmt) u).getBoxesPointingToThis().isEmpty()) {
u1 = null;
u2 = null;
continue;
}
// If this is an assignment to an array, we must already have two
// preceding constant assignments
AssignStmt assignStmt = (AssignStmt) u;
if (assignStmt.getLeftOp() instanceof ArrayRef) {
if (u1 != null && u2 != null && u2.getBoxesPointingToThis().isEmpty() && assignStmt.getBoxesPointingToThis().isEmpty()) {
ArrayRef arrayRef = (ArrayRef) assignStmt.getLeftOp();
Value u1val = u1.getDefBoxes().get(0).getValue();
Value u2val = u2.getDefBoxes().get(0).getValue();
// index
if (arrayRef.getIndex() == u1val)
arrayRef.setIndex(((AssignStmt) u1).getRightOp());
else if (arrayRef.getIndex() == u2val)
arrayRef.setIndex(((AssignStmt) u2).getRightOp());
// value
if (assignStmt.getRightOp() == u1val)
assignStmt.setRightOp(((AssignStmt) u1).getRightOp());
else if (assignStmt.getRightOp() == u2val)
assignStmt.setRightOp(((AssignStmt) u2).getRightOp());
// Remove the unnecessary assignments
Unit checkU = u;
boolean foundU1 = false, foundU2 = false, doneU1 = false, doneU2 = false;
while (!(doneU1 && doneU2) && !(foundU1 && foundU2) && checkU != null) {
// Does the current statement use the value?
for (ValueBox vb : checkU.getUseBoxes()) {
if (!doneU1 && vb.getValue() == u1val)
foundU1 = true;
if (!doneU2 && vb.getValue() == u2val)
foundU2 = true;
}
// Does the current statement overwrite the value?
for (ValueBox vb : checkU.getDefBoxes()) {
if (vb.getValue() == u1val)
doneU1 = true;
else if (vb.getValue() == u2val)
doneU2 = true;
}
// If this statement branches, we abort
if (checkU.branches()) {
foundU1 = true;
foundU2 = true;
break;
}
// Get the next statement
checkU = b.getUnits().getSuccOf(checkU);
}
if (!foundU1) {
// only remove constant assignment if the left value is Local
if (u1val instanceof Local) {
b.getUnits().remove(u1);
if (Options.v().verbose()) {
logger.debug("[" + b.getMethod().getName() + "] remove 1 " + u1);
}
}
}
if (!foundU2) {
// only remove constant assignment if the left value is Local
if (u2val instanceof Local) {
b.getUnits().remove(u2);
if (Options.v().verbose()) {
logger.debug("[" + b.getMethod().getName() + "] remove 2 " + u2);
}
}
}
u1 = null;
u2 = null;
} else {
// No proper initialization before
u1 = null;
u2 = null;
continue;
}
}
// value.
if (!(assignStmt.getRightOp() instanceof Constant)) {
u1 = null;
u2 = null;
continue;
}
if (u1 == null) {
u1 = assignStmt;
} else if (u2 == null) {
u2 = assignStmt;
// If the last value is overwritten again, we start again at the beginning
if (u1 != null) {
Value op1 = ((AssignStmt) u1).getLeftOp();
if (op1 == ((AssignStmt) u2).getLeftOp()) {
u1 = u2;
u2 = null;
}
}
} else {
u1 = u2;
u2 = assignStmt;
}
}
// Remove all locals that are no longer necessary
UnusedLocalEliminator.v().transform(b);
}
use of soot.ValueBox in project soot by Sable.
the class StackFrame method mergeIn.
/**
* Merges the specified operands with the operands used by this frame.
* @param oprs the new operands.
* @throws IllegalArgumentException if the number of new operands is not equal
* to the number of old operands.
*/
void mergeIn(Operand... oprs) {
ArrayList<Operand[]> in = this.in;
if (in.get(0).length != oprs.length)
throw new IllegalArgumentException("Invalid in operands length!");
int nrIn = in.size();
boolean diff = false;
for (int i = 0; i != oprs.length; i++) {
Operand newOp = oprs[i];
diff = true;
/* merge, since prevOp != newOp */
Local stack = inStackLocals[i];
if (stack != null) {
if (newOp.stack == null) {
newOp.stack = stack;
AssignStmt as = Jimple.v().newAssignStmt(stack, newOp.value);
src.setUnit(newOp.insn, as);
newOp.updateBoxes();
} else {
AssignStmt as = Jimple.v().newAssignStmt(stack, newOp.stackOrValue());
src.mergeUnits(newOp.insn, as);
newOp.addBox(as.getRightOpBox());
}
} else {
for (int j = 0; j != nrIn; j++) {
stack = in.get(j)[i].stack;
if (stack != null)
break;
}
if (stack == null) {
stack = newOp.stack;
if (stack == null)
stack = src.newStackLocal();
}
/* add assign statement for prevOp */
ValueBox box = boxes == null ? null : boxes[i];
for (int j = 0; j != nrIn; j++) {
Operand prevOp = in.get(j)[i];
if (prevOp.stack == stack)
continue;
prevOp.removeBox(box);
if (prevOp.stack == null) {
prevOp.stack = stack;
AssignStmt as = Jimple.v().newAssignStmt(stack, prevOp.value);
src.setUnit(prevOp.insn, as);
} else {
Unit u = src.getUnit(prevOp.insn);
DefinitionStmt as = (DefinitionStmt) (u instanceof UnitContainer ? ((UnitContainer) u).getFirstUnit() : u);
ValueBox lvb = as.getLeftOpBox();
assert lvb.getValue() == prevOp.stack : "Invalid stack local!";
lvb.setValue(stack);
prevOp.stack = stack;
}
prevOp.updateBoxes();
}
if (newOp.stack != stack) {
if (newOp.stack == null) {
newOp.stack = stack;
AssignStmt as = Jimple.v().newAssignStmt(stack, newOp.value);
src.setUnit(newOp.insn, as);
} else {
Unit u = src.getUnit(newOp.insn);
DefinitionStmt as = (DefinitionStmt) (u instanceof UnitContainer ? ((UnitContainer) u).getFirstUnit() : u);
ValueBox lvb = as.getLeftOpBox();
assert lvb.getValue() == newOp.stack : "Invalid stack local!";
lvb.setValue(stack);
newOp.stack = stack;
}
newOp.updateBoxes();
}
if (box != null)
box.setValue(stack);
inStackLocals[i] = stack;
}
/*
* this version uses allocates local if it
* finds both operands have stack locals allocated already
*/
/*if (stack == null) {
if (in.size() != 1)
throw new AssertionError("Local h " + in.size());
stack = src.newStackLocal();
inStackLocals[i] = stack;
ValueBox box = boxes == null ? null : boxes[i];
/* add assign statement for prevOp *
for (int j = 0; j != nrIn; j++) {
Operand prevOp = in.get(j)[i];
prevOp.removeBox(box);
if (prevOp.stack == null) {
prevOp.stack = stack;
as = Jimple.v().newAssignStmt(stack, prevOp.value);
src.setUnit(prevOp.insn, as);
prevOp.updateBoxes();
} else {
as = Jimple.v().newAssignStmt(stack, prevOp.stackOrValue());
src.mergeUnits(prevOp.insn, as);
}
prevOp.addBox(as.getRightOpBox());
}
if (box != null)
box.setValue(stack);
}
if (newOp.stack == null) {
newOp.stack = stack;
as = Jimple.v().newAssignStmt(stack, newOp.value);
src.setUnit(newOp.insn, as);
newOp.updateBoxes();
} else {
as = Jimple.v().newAssignStmt(stack, newOp.stackOrValue());
src.mergeUnits(newOp.insn, as);
}
newOp.addBox(as.getRightOpBox());*/
}
if (diff)
in.add(oprs);
}
use of soot.ValueBox in project soot by Sable.
the class IFDSLiveVariables method createFlowFunctionsFactory.
@Override
public FlowFunctions<Unit, Value, SootMethod> createFlowFunctionsFactory() {
return new FlowFunctions<Unit, Value, SootMethod>() {
@Override
public FlowFunction<Value> getNormalFlowFunction(Unit curr, Unit succ) {
if (curr.getUseAndDefBoxes().isEmpty())
return Identity.v();
final Stmt s = (Stmt) curr;
return new FlowFunction<Value>() {
public Set<Value> computeTargets(Value source) {
// kill defs
List<ValueBox> defs = s.getDefBoxes();
if (!defs.isEmpty()) {
if (defs.get(0).getValue().equivTo(source)) {
return Collections.emptySet();
}
}
// gen uses out of zero value
if (source.equals(zeroValue())) {
Set<Value> liveVars = new HashSet<Value>();
for (ValueBox useBox : s.getUseBoxes()) {
Value value = useBox.getValue();
liveVars.add(value);
}
return liveVars;
}
// else just propagate
return Collections.singleton(source);
}
};
}
@Override
public FlowFunction<Value> getCallFlowFunction(Unit callStmt, final SootMethod destinationMethod) {
final Stmt s = (Stmt) callStmt;
return new FlowFunction<Value>() {
public Set<Value> computeTargets(Value source) {
if (!s.getDefBoxes().isEmpty()) {
Value callerSideReturnValue = s.getDefBoxes().get(0).getValue();
if (callerSideReturnValue.equivTo(source)) {
Set<Value> calleeSideReturnValues = new HashSet<Value>();
for (Unit calleeUnit : interproceduralCFG().getStartPointsOf(destinationMethod)) {
if (calleeUnit instanceof ReturnStmt) {
ReturnStmt returnStmt = (ReturnStmt) calleeUnit;
calleeSideReturnValues.add(returnStmt.getOp());
}
}
return calleeSideReturnValues;
}
}
// no return value, nothing to propagate
return Collections.emptySet();
}
};
}
@Override
public FlowFunction<Value> getReturnFlowFunction(final Unit callSite, SootMethod calleeMethod, final Unit exitStmt, Unit returnSite) {
Stmt s = (Stmt) callSite;
InvokeExpr ie = s.getInvokeExpr();
final List<Value> callArgs = ie.getArgs();
final List<Local> paramLocals = new ArrayList<Local>();
for (int i = 0; i < calleeMethod.getParameterCount(); i++) {
paramLocals.add(calleeMethod.getActiveBody().getParameterLocal(i));
}
return new FlowFunction<Value>() {
public Set<Value> computeTargets(Value source) {
Set<Value> liveParamsAtCallee = new HashSet<Value>();
for (int i = 0; i < paramLocals.size(); i++) {
if (paramLocals.get(i).equivTo(source)) {
liveParamsAtCallee.add(callArgs.get(i));
}
}
return liveParamsAtCallee;
}
};
}
@Override
public FlowFunction<Value> getCallToReturnFlowFunction(Unit callSite, Unit returnSite) {
if (callSite.getUseAndDefBoxes().isEmpty())
return Identity.v();
final Stmt s = (Stmt) callSite;
return new FlowFunction<Value>() {
public Set<Value> computeTargets(Value source) {
// kill defs
List<ValueBox> defs = s.getDefBoxes();
if (!defs.isEmpty()) {
if (defs.get(0).getValue().equivTo(source)) {
return Collections.emptySet();
}
}
// gen uses out of zero value
if (source.equals(zeroValue())) {
Set<Value> liveVars = new HashSet<Value>();
// only "gen" those values that are not parameter values;
// the latter are taken care of by the return-flow function
List<Value> args = s.getInvokeExpr().getArgs();
for (ValueBox useBox : s.getUseBoxes()) {
Value value = useBox.getValue();
if (!args.contains(value)) {
liveVars.add(value);
}
}
return liveVars;
}
// else just propagate
return Collections.singleton(source);
}
};
}
};
}
use of soot.ValueBox in project soot by Sable.
the class IFDSUninitializedVariables method createFlowFunctionsFactory.
@Override
public FlowFunctions<Unit, Local, SootMethod> createFlowFunctionsFactory() {
return new FlowFunctions<Unit, Local, SootMethod>() {
@Override
public FlowFunction<Local> getNormalFlowFunction(Unit curr, Unit succ) {
final SootMethod m = interproceduralCFG().getMethodOf(curr);
if (Scene.v().getEntryPoints().contains(m) && interproceduralCFG().isStartPoint(curr)) {
return new FlowFunction<Local>() {
@Override
public Set<Local> computeTargets(Local source) {
if (source == zeroValue()) {
Set<Local> res = new LinkedHashSet<Local>();
res.addAll(m.getActiveBody().getLocals());
for (int i = 0; i < m.getParameterCount(); i++) res.remove(m.getActiveBody().getParameterLocal(i));
return res;
}
return Collections.emptySet();
}
};
}
if (curr instanceof DefinitionStmt) {
final DefinitionStmt definition = (DefinitionStmt) curr;
final Value leftOp = definition.getLeftOp();
if (leftOp instanceof Local) {
final Local leftOpLocal = (Local) leftOp;
return new FlowFunction<Local>() {
@Override
public Set<Local> computeTargets(final Local source) {
List<ValueBox> useBoxes = definition.getUseBoxes();
for (ValueBox valueBox : useBoxes) {
if (valueBox.getValue().equivTo(source)) {
LinkedHashSet<Local> res = new LinkedHashSet<Local>();
res.add(source);
res.add(leftOpLocal);
return res;
}
}
if (leftOp.equivTo(source))
return Collections.emptySet();
return Collections.singleton(source);
}
};
}
}
return Identity.v();
}
@Override
public FlowFunction<Local> getCallFlowFunction(Unit callStmt, final SootMethod destinationMethod) {
Stmt stmt = (Stmt) callStmt;
InvokeExpr invokeExpr = stmt.getInvokeExpr();
final List<Value> args = invokeExpr.getArgs();
final List<Local> localArguments = new ArrayList<Local>();
for (Value value : args) if (value instanceof Local)
localArguments.add((Local) value);
return new FlowFunction<Local>() {
@Override
public Set<Local> computeTargets(final Local source) {
// Do not map parameters for <clinit> edges
if (destinationMethod.getName().equals("<clinit>") || destinationMethod.getSubSignature().equals("void run()"))
return Collections.emptySet();
for (Local localArgument : localArguments) {
if (source.equivTo(localArgument)) {
return Collections.<Local>singleton(destinationMethod.getActiveBody().getParameterLocal(args.indexOf(localArgument)));
}
}
if (source == zeroValue()) {
// gen all locals that are not parameter locals
Collection<Local> locals = destinationMethod.getActiveBody().getLocals();
LinkedHashSet<Local> uninitializedLocals = new LinkedHashSet<Local>(locals);
for (int i = 0; i < destinationMethod.getParameterCount(); i++) {
uninitializedLocals.remove(destinationMethod.getActiveBody().getParameterLocal(i));
}
return uninitializedLocals;
}
return Collections.emptySet();
}
};
}
@Override
public FlowFunction<Local> getReturnFlowFunction(final Unit callSite, SootMethod calleeMethod, final Unit exitStmt, Unit returnSite) {
if (callSite instanceof DefinitionStmt) {
final DefinitionStmt definition = (DefinitionStmt) callSite;
if (definition.getLeftOp() instanceof Local) {
final Local leftOpLocal = (Local) definition.getLeftOp();
if (exitStmt instanceof ReturnStmt) {
final ReturnStmt returnStmt = (ReturnStmt) exitStmt;
return new FlowFunction<Local>() {
@Override
public Set<Local> computeTargets(Local source) {
if (returnStmt.getOp().equivTo(source))
return Collections.singleton(leftOpLocal);
return Collections.emptySet();
}
};
} else if (exitStmt instanceof ThrowStmt) {
// if we throw an exception, LHS of call is undefined
return new FlowFunction<Local>() {
@Override
public Set<Local> computeTargets(final Local source) {
if (source == zeroValue())
return Collections.singleton(leftOpLocal);
else
return Collections.emptySet();
}
};
}
}
}
return KillAll.v();
}
@Override
public FlowFunction<Local> getCallToReturnFlowFunction(Unit callSite, Unit returnSite) {
if (callSite instanceof DefinitionStmt) {
DefinitionStmt definition = (DefinitionStmt) callSite;
if (definition.getLeftOp() instanceof Local) {
final Local leftOpLocal = (Local) definition.getLeftOp();
return new Kill<Local>(leftOpLocal);
}
}
return Identity.v();
}
};
}
Aggregations