use of soot.ValueBox in project soot by Sable.
the class AsmMethodSource method assignReadOps.
private void assignReadOps(Local l) {
if (stack.isEmpty())
return;
for (Operand opr : stack) {
if (opr == DWORD_DUMMY || opr.stack != null || (l == null && opr.value instanceof Local))
continue;
if (l != null && !opr.value.equivTo(l)) {
List<ValueBox> uses = opr.value.getUseBoxes();
boolean noref = true;
for (ValueBox use : uses) {
Value val = use.getValue();
if (val.equivTo(l)) {
noref = false;
break;
}
}
if (noref)
continue;
}
int op = opr.insn.getOpcode();
if (l == null && op != GETFIELD && op != GETSTATIC && (op < IALOAD && op > SALOAD))
continue;
Local stack = newStackLocal();
opr.stack = stack;
AssignStmt as = Jimple.v().newAssignStmt(stack, opr.value);
opr.updateBoxes();
setUnit(opr.insn, as);
}
}
use of soot.ValueBox in project soot by Sable.
the class AsmMethodSource method convertTypeInsn.
private void convertTypeInsn(TypeInsnNode insn) {
int op = insn.getOpcode();
StackFrame frame = getFrame(insn);
Operand[] out = frame.out();
Operand opr;
if (out == null) {
Type t = AsmUtil.toJimpleRefType(insn.desc);
Value val;
if (op == NEW) {
val = Jimple.v().newNewExpr((RefType) t);
} else {
Operand op1 = popImmediate();
Value v1 = op1.stackOrValue();
ValueBox vb;
if (op == ANEWARRAY) {
NewArrayExpr expr = Jimple.v().newNewArrayExpr(t, v1);
vb = expr.getSizeBox();
val = expr;
} else if (op == CHECKCAST) {
CastExpr expr = Jimple.v().newCastExpr(v1, t);
vb = expr.getOpBox();
val = expr;
} else if (op == INSTANCEOF) {
InstanceOfExpr expr = Jimple.v().newInstanceOfExpr(v1, t);
vb = expr.getOpBox();
val = expr;
} else {
throw new AssertionError("Unknown type op: " + op);
}
op1.addBox(vb);
frame.in(op1);
frame.boxes(vb);
}
opr = new Operand(insn, val);
frame.out(opr);
} else {
opr = out[0];
if (op != NEW)
frame.mergeIn(pop());
}
push(opr);
}
use of soot.ValueBox in project soot by Sable.
the class ShortcutArrayInit method inASTStatementSequenceNode.
public void inASTStatementSequenceNode(ASTStatementSequenceNode node) {
debug("inASTStatementSequenceNode");
boolean success = false;
ArrayList<AugmentedStmt> toRemove = new ArrayList<AugmentedStmt>();
for (AugmentedStmt as : node.getStatements()) {
success = false;
Stmt s = as.get_Stmt();
if (!(s instanceof DefinitionStmt))
continue;
DefinitionStmt ds = (DefinitionStmt) s;
ValueBox right = ds.getRightOpBox();
Value rightValue = right.getValue();
if (!(rightValue instanceof NewArrayExpr))
continue;
debug("Found a new ArrayExpr" + rightValue);
debug("Type of array is:" + rightValue.getType());
// get type out
Type arrayType = rightValue.getType();
// get size....need to know this statically for sure!!!
Value size = ((NewArrayExpr) rightValue).getSize();
if (!(size instanceof IntConstant))
continue;
if (((IntConstant) size).value == 0) {
debug("Size of array is 0 dont do anything");
continue;
}
if (DEBUG)
System.out.println("Size of array is: " + ((IntConstant) size).value);
Iterator<AugmentedStmt> tempIt = node.getStatements().iterator();
// get to the array creation stmt
while (tempIt.hasNext()) {
AugmentedStmt tempAs = tempIt.next();
Stmt tempS = tempAs.get_Stmt();
if (tempS.equals(s))
break;
}
// have the size have the type, tempIt is poised at the current def
// stmt
ValueBox[] array = new ValueBox[((IntConstant) size).value];
success = true;
for (int i = 0; i < ((IntConstant) size).value; i++) {
if (!tempIt.hasNext()) {
// since its end of the stmt seq node just return
if (DEBUG)
System.out.println("returning");
return;
}
AugmentedStmt aug = tempIt.next();
Stmt augS = aug.get_Stmt();
if (!isInSequenceAssignment(augS, ds.getLeftOp(), i)) {
// initializations
if (DEBUG)
System.out.println("Out of order assignment aborting attempt");
success = false;
break;
} else {
if (DEBUG)
System.out.println("Assignment stmt in order adding to array");
// the augS is the next assignment in the sequence add to
// ValueBox array
array[i] = ((DefinitionStmt) augS).getRightOpBox();
toRemove.add(aug);
}
}
if (success) {
DArrayInitExpr tempExpr = new DArrayInitExpr(array, arrayType);
DArrayInitValueBox tempValueBox = new DArrayInitValueBox(tempExpr);
DAssignStmt newStmt = new DAssignStmt(ds.getLeftOpBox(), tempValueBox);
// stmt
if (DEBUG)
System.out.println("Created new DAssignStmt and replacing it");
InitializationDeclarationShortcut shortcutChecker = new InitializationDeclarationShortcut(as);
methodNode.apply(shortcutChecker);
boolean possible = shortcutChecker.isShortcutPossible();
if (possible) {
if (DEBUG)
System.out.println("Shortcut is possible");
// create shortcut stmt
DShortcutAssignStmt newShortcutStmt = new DShortcutAssignStmt(newStmt, arrayType);
as.set_Stmt(newShortcutStmt);
// make sure to mark the local in the DVariableDeclarations
// so that its not printed
markLocal(ds.getLeftOp());
}
break;
}
}
// end going through stmt seq node
if (success) {
// means we did a transformation remove the stmts
List<AugmentedStmt> newStmtList = new ArrayList<AugmentedStmt>();
for (AugmentedStmt as : node.getStatements()) {
if (toRemove.contains(as)) {
toRemove.remove(as);
} else {
newStmtList.add(as);
}
}
node.setStatements(newStmtList);
// make sure any other possible simplifications are done
inASTStatementSequenceNode(node);
G.v().ASTTransformations_modified = true;
}
// try the second pattern also
secondPattern(node);
}
use of soot.ValueBox in project soot by Sable.
the class DavaBody method javafy_binop_expr.
private void javafy_binop_expr(ValueBox vb) {
BinopExpr boe = (BinopExpr) vb.getValue();
ValueBox leftOpBox = boe.getOp1Box(), rightOpBox = boe.getOp2Box();
Value leftOp = leftOpBox.getValue(), rightOp = rightOpBox.getValue();
if (rightOp instanceof IntConstant) {
if ((leftOp instanceof IntConstant) == false) {
javafy(leftOpBox);
leftOp = leftOpBox.getValue();
if (boe instanceof ConditionExpr)
rightOpBox.setValue(DIntConstant.v(((IntConstant) rightOp).value, leftOp.getType()));
else
rightOpBox.setValue(DIntConstant.v(((IntConstant) rightOp).value, null));
}
} else if (leftOp instanceof IntConstant) {
javafy(rightOpBox);
rightOp = rightOpBox.getValue();
if (boe instanceof ConditionExpr)
leftOpBox.setValue(DIntConstant.v(((IntConstant) leftOp).value, rightOp.getType()));
else
leftOpBox.setValue(DIntConstant.v(((IntConstant) leftOp).value, null));
} else {
javafy(rightOpBox);
rightOp = rightOpBox.getValue();
javafy(leftOpBox);
leftOp = leftOpBox.getValue();
}
if (boe instanceof CmpExpr)
vb.setValue(new DCmpExpr(leftOp, rightOp));
else if (boe instanceof CmplExpr)
vb.setValue(new DCmplExpr(leftOp, rightOp));
else if (boe instanceof CmpgExpr)
vb.setValue(new DCmpgExpr(leftOp, rightOp));
}
use of soot.ValueBox in project soot by Sable.
the class DexBody method jimplify.
/**
* Return the jimple equivalent of this body.
*
* @param m
* the SootMethod that contains this body
*/
public Body jimplify(Body b, SootMethod m) {
final Jimple jimple = Jimple.v();
final UnknownType unknownType = UnknownType.v();
final NullConstant nullConstant = NullConstant.v();
final Options options = Options.v();
/*
* Timer t_whole_jimplification = new Timer(); Timer t_num = new
* Timer(); Timer t_null = new Timer();
*
* t_whole_jimplification.start();
*/
jBody = (JimpleBody) b;
deferredInstructions = new ArrayList<DeferableInstruction>();
instructionsToRetype = new HashSet<RetypeableInstruction>();
if (IDalvikTyper.ENABLE_DVKTYPER) {
DalvikTyper.v().clear();
}
// process method parameters and generate Jimple locals from Dalvik
// registers
List<Local> paramLocals = new LinkedList<Local>();
if (!isStatic) {
int thisRegister = numRegisters - numParameterRegisters - 1;
// generateLocal(UnknownType.v());
Local thisLocal = jimple.newLocal("$u" + thisRegister, unknownType);
jBody.getLocals().add(thisLocal);
registerLocals[thisRegister] = thisLocal;
JIdentityStmt idStmt = (JIdentityStmt) jimple.newIdentityStmt(thisLocal, jimple.newThisRef(declaringClassType));
add(idStmt);
paramLocals.add(thisLocal);
if (IDalvikTyper.ENABLE_DVKTYPER) {
DalvikTyper.v().setType(idStmt.leftBox, jBody.getMethod().getDeclaringClass().getType(), false);
}
}
{
// index of parameter type
int i = 0;
// index
int parameterRegister = numRegisters - numParameterRegisters;
// register
for (Type t : parameterTypes) {
// may
Local gen = jimple.newLocal("$u" + parameterRegister, unknownType);
// only
// use
// UnknownType
// here
// because
// the
// local
// may
// be
// reused
// with
// a
// different
// type
// later
// (before
// splitting)
jBody.getLocals().add(gen);
registerLocals[parameterRegister] = gen;
JIdentityStmt idStmt = (JIdentityStmt) jimple.newIdentityStmt(gen, jimple.newParameterRef(t, i++));
add(idStmt);
paramLocals.add(gen);
if (IDalvikTyper.ENABLE_DVKTYPER) {
DalvikTyper.v().setType(idStmt.leftBox, t, false);
}
// used later in the Dalvik bytecode
if (t instanceof LongType || t instanceof DoubleType) {
parameterRegister++;
// may
Local g = jimple.newLocal("$u" + parameterRegister, unknownType);
// only
// use
// UnknownType
// here
// because
// the
// local
// may
// be
// reused
// with
// a
// different
// type
// later
// (before
// splitting)
jBody.getLocals().add(g);
registerLocals[parameterRegister] = g;
}
parameterRegister++;
}
}
for (int i = 0; i < (numRegisters - numParameterRegisters - (isStatic ? 0 : 1)); i++) {
registerLocals[i] = jimple.newLocal("$u" + i, unknownType);
jBody.getLocals().add(registerLocals[i]);
}
// add local to store intermediate results
storeResultLocal = jimple.newLocal("$u-1", unknownType);
jBody.getLocals().add(storeResultLocal);
// process bytecode instructions
final boolean isOdex = dexFile instanceof DexBackedDexFile ? ((DexBackedDexFile) dexFile).isOdexFile() : false;
ClassPath cp = null;
if (isOdex) {
String[] sootClasspath = options.soot_classpath().split(File.pathSeparator);
List<String> classpathList = new ArrayList<String>();
for (String str : sootClasspath) classpathList.add(str);
try {
ClassPathResolver resolver = new ClassPathResolver(classpathList, classpathList, classpathList, dexFile);
cp = new ClassPath(resolver.getResolvedClassProviders().toArray(new ClassProvider[0]));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
int prevLineNumber = -1;
for (DexlibAbstractInstruction instruction : instructions) {
if (isOdex && instruction instanceof OdexInstruction)
((OdexInstruction) instruction).deOdex(dexFile, method, cp);
if (dangling != null) {
dangling.finalize(this, instruction);
dangling = null;
}
instruction.jimplify(this);
if (instruction.getLineNumber() > 0)
prevLineNumber = instruction.getLineNumber();
else {
instruction.setLineNumber(prevLineNumber);
}
}
for (DeferableInstruction instruction : deferredInstructions) {
instruction.deferredJimplify(this);
}
if (tries != null)
addTraps();
int prevLn = -1;
final boolean keepLineNumber = options.keep_line_number();
for (DexlibAbstractInstruction instruction : instructions) {
Unit unit = instruction.getUnit();
int lineNumber = unit.getJavaSourceStartLineNumber();
if (keepLineNumber && lineNumber < 0) {
if (prevLn >= 0) {
unit.addTag(new LineNumberTag(prevLn));
unit.addTag(new SourceLineNumberTag(prevLn));
}
} else {
prevLn = lineNumber;
}
}
// At this point Jimple code is generated
// Cleaning...
instructions = null;
// registerLocals = null;
// storeResultLocal = null;
instructionAtAddress.clear();
// localGenerator = null;
deferredInstructions = null;
// instructionsToRetype = null;
dangling = null;
tries = null;
/*
* We eliminate dead code. Dead code has been shown to occur under the
* following circumstances.
*
* 0006ec: 0d00 |00a2: move-exception v0 ... 0006f2: 0d00 |00a5:
* move-exception v0 ... 0x0041 - 0x008a Ljava/lang/Throwable; -> 0x00a5
* <any> -> 0x00a2
*
* Here there are two traps both over the same region. But the same
* always fires, hence rendering the code at a2 unreachable. Dead code
* yields problems during local splitting because locals within dead
* code will not be split. Hence we remove all dead code here.
*/
// Fix traps that do not catch exceptions
DexTrapStackFixer.v().transform(jBody);
// Sort out jump chains
DexJumpChainShortener.v().transform(jBody);
// Make sure that we don't have any overlapping uses due to returns
DexReturnInliner.v().transform(jBody);
// Shortcut: Reduce array initializations
DexArrayInitReducer.v().transform(jBody);
// split first to find undefined uses
getLocalSplitter().transform(jBody);
// Remove dead code and the corresponding locals before assigning types
getUnreachableCodeEliminator().transform(jBody);
DeadAssignmentEliminator.v().transform(jBody);
UnusedLocalEliminator.v().transform(jBody);
for (RetypeableInstruction i : instructionsToRetype) i.retype(jBody);
if (IDalvikTyper.ENABLE_DVKTYPER) {
DexReturnValuePropagator.v().transform(jBody);
getCopyPopagator().transform(jBody);
DexNullThrowTransformer.v().transform(jBody);
DalvikTyper.v().typeUntypedConstrantInDiv(jBody);
DeadAssignmentEliminator.v().transform(jBody);
UnusedLocalEliminator.v().transform(jBody);
DalvikTyper.v().assignType(jBody);
// jBody.validate();
jBody.validateUses();
jBody.validateValueBoxes();
// jBody.checkInit();
// Validate.validateArrays(jBody);
// jBody.checkTypes();
// jBody.checkLocals();
} else {
// t_num.start();
DexNumTransformer.v().transform(jBody);
// t_num.end();
DexReturnValuePropagator.v().transform(jBody);
getCopyPopagator().transform(jBody);
DexNullThrowTransformer.v().transform(jBody);
// t_null.start();
DexNullTransformer.v().transform(jBody);
// t_null.end();
DexIfTransformer.v().transform(jBody);
DeadAssignmentEliminator.v().transform(jBody);
UnusedLocalEliminator.v().transform(jBody);
// DexRefsChecker.v().transform(jBody);
DexNullArrayRefTransformer.v().transform(jBody);
}
if (IDalvikTyper.ENABLE_DVKTYPER) {
for (Local l : jBody.getLocals()) {
l.setType(unknownType);
}
}
// Remove "instanceof" checks on the null constant
DexNullInstanceofTransformer.v().transform(jBody);
TypeAssigner.v().transform(jBody);
final RefType objectType = RefType.v("java.lang.Object");
if (IDalvikTyper.ENABLE_DVKTYPER) {
for (Unit u : jBody.getUnits()) {
if (u instanceof IfStmt) {
ConditionExpr expr = (ConditionExpr) ((IfStmt) u).getCondition();
if (((expr instanceof EqExpr) || (expr instanceof NeExpr))) {
Value op1 = expr.getOp1();
Value op2 = expr.getOp2();
if (op1 instanceof Constant && op2 instanceof Local) {
Local l = (Local) op2;
Type ltype = l.getType();
if (ltype instanceof PrimType)
continue;
if (// by default
!(op1 instanceof IntConstant))
// in Dalvik
continue;
IntConstant icst = (IntConstant) op1;
int val = icst.value;
if (val != 0)
continue;
expr.setOp1(nullConstant);
} else if (op1 instanceof Local && op2 instanceof Constant) {
Local l = (Local) op1;
Type ltype = l.getType();
if (ltype instanceof PrimType)
continue;
if (// by default
!(op2 instanceof IntConstant))
// in Dalvik
continue;
IntConstant icst = (IntConstant) op2;
int val = icst.value;
if (val != 0)
continue;
expr.setOp2(nullConstant);
} else if (op1 instanceof Local && op2 instanceof Local) {
// nothing to do
} else if (op1 instanceof Constant && op2 instanceof Constant) {
if (op1 instanceof NullConstant && op2 instanceof NumericConstant) {
IntConstant nc = (IntConstant) op2;
if (nc.value != 0)
throw new RuntimeException("expected value 0 for int constant. Got " + expr);
expr.setOp2(NullConstant.v());
} else if (op2 instanceof NullConstant && op1 instanceof NumericConstant) {
IntConstant nc = (IntConstant) op1;
if (nc.value != 0)
throw new RuntimeException("expected value 0 for int constant. Got " + expr);
expr.setOp1(nullConstant);
}
} else {
throw new RuntimeException("error: do not handle if: " + u);
}
}
}
}
// For null_type locals: replace their use by NullConstant()
List<ValueBox> uses = jBody.getUseBoxes();
// List<ValueBox> defs = jBody.getDefBoxes();
List<ValueBox> toNullConstantify = new ArrayList<ValueBox>();
List<Local> toRemove = new ArrayList<Local>();
for (Local l : jBody.getLocals()) {
if (l.getType() instanceof NullType) {
toRemove.add(l);
for (ValueBox vb : uses) {
Value v = vb.getValue();
if (v == l)
toNullConstantify.add(vb);
}
}
}
for (ValueBox vb : toNullConstantify) {
System.out.println("replace valuebox '" + vb + " with null constant");
vb.setValue(nullConstant);
}
for (Local l : toRemove) {
System.out.println("removing null_type local " + l);
l.setType(objectType);
}
}
// We pack locals that are not used in overlapping regions. This may
// again lead to unused locals which we have to remove.
LocalPacker.v().transform(jBody);
UnusedLocalEliminator.v().transform(jBody);
LocalNameStandardizer.v().transform(jBody);
// on the fly.
if (options.wrong_staticness() == Options.wrong_staticness_fix) {
FieldStaticnessCorrector.v().transform(jBody);
MethodStaticnessCorrector.v().transform(jBody);
}
// Inline PackManager.v().getPack("jb").apply(jBody);
// Keep only transformations that have not been done
// at this point.
TrapTightener.v().transform(jBody);
TrapMinimizer.v().transform(jBody);
// LocalSplitter.v().transform(jBody);
Aggregator.v().transform(jBody);
// UnusedLocalEliminator.v().transform(jBody);
// TypeAssigner.v().transform(jBody);
// LocalPacker.v().transform(jBody);
// LocalNameStandardizer.v().transform(jBody);
// Remove if (null == null) goto x else <madness>. We can only do this
// after we have run the constant propagation as we might not be able
// to statically decide the conditions earlier.
ConditionalBranchFolder.v().transform(jBody);
// Remove unnecessary typecasts
ConstantCastEliminator.v().transform(jBody);
IdentityCastEliminator.v().transform(jBody);
// Remove unnecessary logic operations
IdentityOperationEliminator.v().transform(jBody);
// We need to run this transformer since the conditional branch folder
// might have rendered some code unreachable (well, it was unreachable
// before as well, but we didn't know).
UnreachableCodeEliminator.v().transform(jBody);
// Not sure whether we need this even though we do it earlier on as
// the earlier pass does not have type information
// CopyPropagator.v().transform(jBody);
// we might have gotten new dead assignments and unused locals through
// copy propagation and unreachable code elimination, so we have to do
// this again
DeadAssignmentEliminator.v().transform(jBody);
UnusedLocalEliminator.v().transform(jBody);
NopEliminator.v().transform(jBody);
// Remove unnecessary chains of return statements
DexReturnPacker.v().transform(jBody);
for (Unit u : jBody.getUnits()) {
if (u instanceof AssignStmt) {
AssignStmt ass = (AssignStmt) u;
if (ass.getRightOp() instanceof CastExpr) {
CastExpr c = (CastExpr) ass.getRightOp();
if (c.getType() instanceof NullType) {
ass.setRightOp(nullConstant);
}
}
}
if (u instanceof DefinitionStmt) {
DefinitionStmt def = (DefinitionStmt) u;
// we must manually fix the hierarchy
if (def.getLeftOp() instanceof Local && def.getRightOp() instanceof CaughtExceptionRef) {
Type t = def.getLeftOp().getType();
if (t instanceof RefType) {
RefType rt = (RefType) t;
if (rt.getSootClass().isPhantom() && !rt.getSootClass().hasSuperclass() && !rt.getSootClass().getName().equals("java.lang.Throwable"))
rt.getSootClass().setSuperclass(Scene.v().getSootClass("java.lang.Throwable"));
}
}
}
}
//
for (Local l : jBody.getLocals()) {
Type t = l.getType();
if (t instanceof NullType) {
l.setType(objectType);
}
}
return jBody;
}
Aggregations