use of soot.SootMethod in project soot by Sable.
the class ClassRenamer method internalTransform.
@Override
protected void internalTransform(String phaseName, Map<String, String> options) {
if (isVerbose()) {
logger.debug("Transforming Class Names...");
}
BodyBuilder.retrieveAllBodies();
BodyBuilder.retrieveAllNames();
final SootClass mainClass = getMainClassSafely();
// iterate through application classes, rename classes with junk
for (SootClass sootClass : Scene.v().getApplicationClasses()) {
final String className = sootClass.getName();
if (sootClass.equals(mainClass) || oldToNewClassNames.containsValue(className) || soot.jbco.Main.getWeight(phaseName, className) == 0) {
continue;
}
String newClassName = oldToNewClassNames.get(className);
if (newClassName == null) {
newClassName = getNewName(getPackageName(className), className);
}
sootClass.setName(newClassName);
RefType crt = RefType.v(newClassName);
crt.setSootClass(sootClass);
sootClass.setRefType(crt);
sootClass.setResolvingLevel(SootClass.BODIES);
// will this fix dangling classes?
// scene.addRefType(sootClass.getType());
newNameToClass.put(newClassName, sootClass);
if (isVerbose()) {
logger.info("\tRenaming " + className + " to " + newClassName);
}
}
Scene.v().releaseActiveHierarchy();
Scene.v().setFastHierarchy(new FastHierarchy());
if (isVerbose()) {
logger.info("\r\tUpdating bytecode class references");
}
for (SootClass sootClass : Scene.v().getApplicationClasses()) {
for (SootMethod sootMethod : sootClass.getMethods()) {
if (!sootMethod.isConcrete()) {
continue;
}
if (isVerbose()) {
logger.info("\t\t" + sootMethod.getSignature());
}
Body aBody;
try {
aBody = sootMethod.getActiveBody();
} catch (Exception e) {
continue;
}
for (Unit u : aBody.getUnits()) {
for (ValueBox vb : u.getUseAndDefBoxes()) {
Value v = vb.getValue();
if (v instanceof ClassConstant) {
ClassConstant constant = (ClassConstant) v;
RefType type = (RefType) constant.toSootType();
RefType updatedType = type.getSootClass().getType();
vb.setValue(ClassConstant.fromType(updatedType));
} else if (v instanceof Expr) {
if (v instanceof CastExpr) {
CastExpr castExpr = (CastExpr) v;
updateType(castExpr.getCastType());
} else if (v instanceof InstanceOfExpr) {
InstanceOfExpr instanceOfExpr = (InstanceOfExpr) v;
updateType(instanceOfExpr.getCheckType());
}
} else if (v instanceof Ref) {
updateType(v.getType());
}
}
}
}
}
Scene.v().releaseActiveHierarchy();
Scene.v().setFastHierarchy(new FastHierarchy());
}
use of soot.SootMethod in project soot by Sable.
the class OnFlyCallGraphBuilder method resolveInvoke.
private void resolveInvoke(Collection<InvokeCallSite> list) {
for (InvokeCallSite ics : list) {
Set<Type> s = reachingBaseTypes.get(ics.base());
if (s == null || s.isEmpty()) {
continue;
}
if (ics.reachingTypes() != null) {
assert ics.nullnessCode() != InvokeCallSite.MUST_BE_NULL;
resolveStaticTypes(s, ics);
continue;
}
boolean mustNotBeNull = ics.nullnessCode() == InvokeCallSite.MUST_NOT_BE_NULL;
boolean mustBeNull = ics.nullnessCode() == InvokeCallSite.MUST_BE_NULL;
// yet, then generate nullary methods
if (mustBeNull || (ics.nullnessCode() == InvokeCallSite.MAY_BE_NULL && (!invokeArgsToSize.containsKey(ics.argArray()) || !reachingArgTypes.containsKey(ics.argArray())))) {
for (Type bType : s) {
assert bType instanceof RefType;
SootClass baseClass = ((RefType) bType).getSootClass();
assert !baseClass.isInterface();
Iterator<SootMethod> mIt = getPublicNullaryMethodIterator(baseClass);
while (mIt.hasNext()) {
SootMethod sm = mIt.next();
cm.addVirtualEdge(ics.container(), ics.stmt(), sm, Kind.REFL_INVOKE, null);
}
}
} else {
/*
* In this branch, either the invoke arg must not be null, or may be null and we
* have size and type information. Invert the above condition: ~mustBeNull &&
* (~mayBeNull || (has-size && has-type)) => (~mustBeNull && ~mayBeNull) ||
* (~mustBeNull && has-size && has-type) => mustNotBeNull || (~mustBeNull &&
* has-types && has-size) => mustNotBeNull || (mayBeNull && has-types &&
* has-size)
*/
Set<Type> reachingTypes = reachingArgTypes.get(ics.argArray());
/*
* the path condition allows must-not-be null without type and size info. Do
* nothing in this case. THIS IS UNSOUND if default null values in an argument
* array are used.
*/
if (reachingTypes == null || !invokeArgsToSize.containsKey(ics.argArray())) {
assert ics.nullnessCode() == InvokeCallSite.MUST_NOT_BE_NULL : ics;
return;
}
assert reachingTypes != null && invokeArgsToSize.containsKey(ics.argArray());
BitSet methodSizes = invokeArgsToSize.get(ics.argArray());
for (Type bType : s) {
assert bType instanceof RefLikeType;
// we do not handle static methods or array reflection
if (bType instanceof NullType || bType instanceof ArrayType) {
continue;
} else {
SootClass baseClass = ((RefType) bType).getSootClass();
Iterator<SootMethod> mIt = getPublicMethodIterator(baseClass, reachingTypes, methodSizes, mustNotBeNull);
while (mIt.hasNext()) {
SootMethod sm = mIt.next();
cm.addVirtualEdge(ics.container(), ics.stmt(), sm, Kind.REFL_INVOKE, null);
}
}
}
}
}
}
use of soot.SootMethod in project soot by Sable.
the class OnFlyCallGraphBuilder method getImplicitTargets.
private void getImplicitTargets(SootMethod source) {
final SootClass scl = source.getDeclaringClass();
if (source.isNative() || source.isPhantom())
return;
if (source.getSubSignature().indexOf("<init>") >= 0) {
handleInit(source, scl);
}
Body b = source.retrieveActiveBody();
for (Unit u : b.getUnits()) {
final Stmt s = (Stmt) u;
if (s.containsInvokeExpr()) {
InvokeExpr ie = s.getInvokeExpr();
SootMethodRef methodRef = ie.getMethodRef();
switch(methodRef.declaringClass().getName()) {
case "java.lang.reflect.Method":
if (methodRef.getSubSignature().getString().equals("java.lang.Object invoke(java.lang.Object,java.lang.Object[])"))
reflectionModel.methodInvoke(source, s);
break;
case "java.lang.Class":
if (methodRef.getSubSignature().getString().equals("java.lang.Object newInstance()"))
reflectionModel.classNewInstance(source, s);
break;
case "java.lang.reflect.Constructor":
if (methodRef.getSubSignature().getString().equals("java.lang.Object newInstance(java.lang.Object[]))"))
reflectionModel.contructorNewInstance(source, s);
break;
}
if (methodRef.getSubSignature() == sigForName) {
reflectionModel.classForName(source, s);
}
if (ie instanceof StaticInvokeExpr) {
SootClass cl = ie.getMethodRef().declaringClass();
for (SootMethod clinit : EntryPoints.v().clinitsOf(cl)) {
addEdge(source, s, clinit, Kind.CLINIT);
}
}
}
if (s.containsFieldRef()) {
FieldRef fr = s.getFieldRef();
if (fr instanceof StaticFieldRef) {
SootClass cl = fr.getFieldRef().declaringClass();
for (SootMethod clinit : EntryPoints.v().clinitsOf(cl)) {
addEdge(source, s, clinit, Kind.CLINIT);
}
}
}
if (s instanceof AssignStmt) {
Value rhs = ((AssignStmt) s).getRightOp();
if (rhs instanceof NewExpr) {
NewExpr r = (NewExpr) rhs;
SootClass cl = r.getBaseType().getSootClass();
for (SootMethod clinit : EntryPoints.v().clinitsOf(cl)) {
addEdge(source, s, clinit, Kind.CLINIT);
}
} else if (rhs instanceof NewArrayExpr || rhs instanceof NewMultiArrayExpr) {
Type t = rhs.getType();
if (t instanceof ArrayType)
t = ((ArrayType) t).baseType;
if (t instanceof RefType) {
SootClass cl = ((RefType) t).getSootClass();
for (SootMethod clinit : EntryPoints.v().clinitsOf(cl)) {
addEdge(source, s, clinit, Kind.CLINIT);
}
}
}
}
}
}
use of soot.SootMethod in project soot by Sable.
the class VirtualCalls method resolveLibrarySignature.
protected void resolveLibrarySignature(Type declaredType, Type sigType, NumberedString subSig, SootMethod container, ChunkedQueue<SootMethod> targets, boolean appOnly, RefType base) {
FastHierarchy fastHierachy = Scene.v().getOrMakeFastHierarchy();
assert (declaredType instanceof RefType);
Pair<Type, NumberedString> pair = new Pair<Type, NumberedString>(base, subSig);
{
Set<Pair<Type, NumberedString>> types = baseToPossibleSubTypes.get(pair);
// just retrieve the previous result.
if (types != null) {
for (Pair<Type, NumberedString> tuple : types) {
Type st = tuple.getO1();
if (!fastHierachy.canStoreType(st, declaredType)) {
resolve(st, st, sigType, subSig, container, targets, appOnly);
} else {
resolve(st, declaredType, sigType, subSig, container, targets, appOnly);
}
}
return;
}
}
Set<Pair<Type, NumberedString>> types = new HashSet<Pair<Type, NumberedString>>();
// get return type; method name; parameter types
String[] split = subSig.getString().replaceAll("(.*) (.*)\\((.*)\\)", "$1;$2;$3").split(";");
Type declaredReturnType = Scene.v().getType(split[0]);
String declaredName = split[1];
List<Type> declaredParamTypes = new ArrayList<Type>();
// separate the parameter types
if (split.length == 3) {
for (String type : split[2].split(",")) {
declaredParamTypes.add(Scene.v().getType(type));
}
}
Chain<SootClass> classes = Scene.v().getClasses();
for (SootClass sc : classes) {
for (SootMethod sm : sc.getMethods()) {
if (sm.isConcrete() || sm.isNative()) {
// method name has to match
if (!sm.getName().equals(declaredName))
continue;
// type or a sub type of it
if (!fastHierachy.canStoreType(sm.getReturnType(), declaredReturnType))
continue;
List<Type> paramTypes = sm.getParameterTypes();
// ones (same type or super type).
if (declaredParamTypes.size() != paramTypes.size())
continue;
boolean check = true;
for (int i = 0; i < paramTypes.size(); i++) {
if (!fastHierachy.canStoreType(declaredParamTypes.get(i), paramTypes.get(i))) {
check = false;
break;
}
}
if (check) {
Type st = sc.getType();
if (!fastHierachy.canStoreType(st, declaredType)) {
// therefore not used in library client
if (!sc.isFinal()) {
NumberedString newSubSig = sm.getNumberedSubSignature();
resolve(st, st, sigType, newSubSig, container, targets, appOnly);
types.add(new Pair<Type, NumberedString>(st, newSubSig));
}
} else {
resolve(st, declaredType, sigType, subSig, container, targets, appOnly);
types.add(new Pair<Type, NumberedString>(st, subSig));
}
}
}
}
}
baseToPossibleSubTypes.putAll(pair, types);
}
use of soot.SootMethod in project soot by Sable.
the class LocalMustAliasAnalysis method trackableFields.
/**
* Computes the set of {@link EquivalentValue}s of all field references that are used
* in this method but not set by the method or any method transitively called by this method.
*/
private Set<Value> trackableFields() {
Set<Value> usedFieldRefs = new HashSet<Value>();
// add all field references that are in use boxes
for (Unit unit : this.graph) {
Stmt s = (Stmt) unit;
List<ValueBox> useBoxes = s.getUseBoxes();
for (ValueBox useBox : useBoxes) {
Value val = useBox.getValue();
if (val instanceof FieldRef) {
FieldRef fieldRef = (FieldRef) val;
if (fieldRef.getType() instanceof RefLikeType)
usedFieldRefs.add(new EquivalentValue(fieldRef));
}
}
}
// prune all fields that are written to
if (!usedFieldRefs.isEmpty()) {
if (!Scene.v().hasCallGraph()) {
throw new IllegalStateException("No call graph found!");
}
CallGraph cg = Scene.v().getCallGraph();
ReachableMethods reachableMethods = new ReachableMethods(cg, Collections.<MethodOrMethodContext>singletonList(container));
reachableMethods.update();
for (Iterator<MethodOrMethodContext> iterator = reachableMethods.listener(); iterator.hasNext(); ) {
SootMethod m = (SootMethod) iterator.next();
if (m.hasActiveBody() && // exclude static initializer of same class (assume that it has already been executed)
!(m.getName().equals(SootMethod.staticInitializerName) && m.getDeclaringClass().equals(container.getDeclaringClass()))) {
for (Unit u : m.getActiveBody().getUnits()) {
List<ValueBox> defBoxes = u.getDefBoxes();
for (ValueBox defBox : defBoxes) {
Value value = defBox.getValue();
if (value instanceof FieldRef) {
usedFieldRefs.remove(new EquivalentValue(value));
}
}
}
}
}
}
return usedFieldRefs;
}
Aggregations