Make a variant of TypeInference which supports dalvik bytecode
Dalvik bytecode represents 'null' as 0 which may lead to problems in phi instructions. This variant of TypeInference fixes these problems by - tracking whether an SSA value is constant zero and - ignoring constant zeros in the transfer function of phi instructions when meeting with non-primitive types
This commit is contained in:
parent
9ca450de48
commit
6d0ba7d371
|
@ -22,6 +22,7 @@ Export-Package: com.google.common.annotations,
|
|||
com.google.common.primitives,
|
||||
com.google.common.reflect,
|
||||
com.google.common.util.concurrent,
|
||||
com.ibm.wala.dalvik.analysis.typeInference,
|
||||
com.ibm.wala.dalvik.classLoader,
|
||||
com.ibm.wala.dalvik.dex.instructions,
|
||||
com.ibm.wala.dalvik.dex.util.config,
|
||||
|
|
|
@ -0,0 +1,130 @@
|
|||
package com.ibm.wala.dalvik.analysis.typeInference;
|
||||
|
||||
import com.ibm.wala.analysis.typeInference.TypeAbstraction;
|
||||
import com.ibm.wala.analysis.typeInference.TypeInference;
|
||||
import com.ibm.wala.analysis.typeInference.TypeVariable;
|
||||
import com.ibm.wala.fixpoint.AbstractOperator;
|
||||
import com.ibm.wala.fixpoint.IVariable;
|
||||
import com.ibm.wala.ssa.IR;
|
||||
import com.ibm.wala.ssa.IVisitorWithAddresses;
|
||||
import com.ibm.wala.ssa.SSAPhiInstruction;
|
||||
import com.ibm.wala.ssa.SymbolTable;
|
||||
|
||||
public class DalvikTypeInference extends TypeInference {
|
||||
@Override
|
||||
protected TypeVariable[] makeStmtRHS(int size) {
|
||||
return new DalvikTypeVariable[size];
|
||||
}
|
||||
|
||||
private static AbstractOperator<TypeVariable> dalvikPhiOp = new DalvikPhiOperator();
|
||||
|
||||
protected DalvikTypeInference(IR ir, boolean doPrimitives) {
|
||||
super(ir, doPrimitives);
|
||||
}
|
||||
|
||||
protected void initialize() {
|
||||
init(ir, this.new DalvikTypeVarFactory(), this.new TypeOperatorFactory());
|
||||
}
|
||||
|
||||
public static DalvikTypeInference make(IR ir, boolean doPrimitives) {
|
||||
return new DalvikTypeInference(ir, doPrimitives);
|
||||
}
|
||||
|
||||
public class DalvikTypeVarFactory extends TypeInference.TypeVarFactory {
|
||||
|
||||
@Override
|
||||
public IVariable makeVariable(int valueNumber) {
|
||||
SymbolTable st = ir.getSymbolTable();
|
||||
if (st.isIntegerConstant(valueNumber) && st.isZero(valueNumber)) {
|
||||
return new DalvikTypeVariable(language.getPrimitive(language.getConstantType(Integer.valueOf(0))), true);
|
||||
} else {
|
||||
if (doPrimitives) {
|
||||
if (st.isConstant(valueNumber)) {
|
||||
if (st.isBooleanConstant(valueNumber)) {
|
||||
return new DalvikTypeVariable(language.getPrimitive(language.getConstantType(Boolean.TRUE)));
|
||||
}
|
||||
}
|
||||
}
|
||||
return new DalvikTypeVariable(TypeAbstraction.TOP);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected class TypeOperatorFactory extends TypeInference.TypeOperatorFactory implements IVisitorWithAddresses, OperatorFactory<TypeVariable> {
|
||||
|
||||
@Override
|
||||
public void visitPhi(SSAPhiInstruction instruction) {
|
||||
assert dalvikPhiOp != null;
|
||||
this.result = dalvikPhiOp;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static final class DalvikPhiOperator extends AbstractOperator<TypeVariable> {
|
||||
private DalvikPhiOperator() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte evaluate(TypeVariable _lhs, TypeVariable[] _rhs) {
|
||||
/**
|
||||
* TODO: Find a better solution than downcasting. Downcasting is
|
||||
* really ugly, although I can be sure here that it succeeds because
|
||||
* I control what type the parameters have. There must be a cleaner
|
||||
* solution which does not cause tons of changes in WALA's code, but
|
||||
* I don't see it yet...
|
||||
*/
|
||||
assert _lhs instanceof DalvikTypeVariable;
|
||||
assert _rhs instanceof DalvikTypeVariable[];
|
||||
DalvikTypeVariable lhs = (DalvikTypeVariable) _lhs;
|
||||
DalvikTypeVariable[] rhs = (DalvikTypeVariable[]) _rhs;
|
||||
TypeAbstraction lhsType = lhs.getType();
|
||||
TypeAbstraction meet = TypeAbstraction.TOP;
|
||||
boolean ignoreZero = containsNonPrimitiveAndZero(rhs);
|
||||
for (int i = 0; i < rhs.length; i++) {
|
||||
if (rhs[i] != null && rhs[i].getType() != null && !(ignoreZero && rhs[i].isIntZeroConstant())) {
|
||||
TypeVariable r = rhs[i];
|
||||
meet = meet.meet(r.getType());
|
||||
}
|
||||
}
|
||||
if (lhsType.equals(meet)) {
|
||||
return NOT_CHANGED;
|
||||
} else {
|
||||
lhs.setType(meet);
|
||||
return CHANGED;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean containsNonPrimitiveAndZero(DalvikTypeVariable[] types) {
|
||||
boolean containsNonPrimitive = false;
|
||||
boolean containsZero = false;
|
||||
for (int i = 0; i < types.length; i++) {
|
||||
if (types[i] != null) {
|
||||
if (types[i].getType() != null && types[i].getType().getTypeReference() != null
|
||||
&& !types[i].getType().getTypeReference().isPrimitiveType()) {
|
||||
containsNonPrimitive = true;
|
||||
}
|
||||
if (types[i].isIntZeroConstant()) {
|
||||
containsZero = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return containsNonPrimitive && containsZero;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "phi meet (dalvik)";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return 2297;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return (o instanceof DalvikPhiOperator);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
package com.ibm.wala.dalvik.analysis.typeInference;
|
||||
|
||||
import com.ibm.wala.analysis.typeInference.TypeAbstraction;
|
||||
import com.ibm.wala.analysis.typeInference.TypeVariable;
|
||||
|
||||
public class DalvikTypeVariable extends TypeVariable {
|
||||
private final boolean isIntZeroConstant;
|
||||
|
||||
public DalvikTypeVariable(TypeAbstraction type, boolean isIntZeroConstant) {
|
||||
super(type);
|
||||
this.isIntZeroConstant = isIntZeroConstant;
|
||||
}
|
||||
|
||||
public DalvikTypeVariable(TypeAbstraction type) {
|
||||
this(type, false);
|
||||
}
|
||||
public boolean isIntZeroConstant() {
|
||||
return isIntZeroConstant;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue