use of soot.FastHierarchy in project soot by Sable.
the class LibraryMethodWrappersBuilder method internalTransform.
protected void internalTransform(String phaseName, Map<String, String> options) {
if (isVerbose()) {
logger.info("Building Library Wrapper Methods...");
}
BodyBuilder.retrieveAllBodies();
// iterate through application classes to find library calls
final Iterator<SootClass> applicationClassesIterator = Scene.v().getApplicationClasses().snapshotIterator();
while (applicationClassesIterator.hasNext()) {
final SootClass applicationClass = applicationClassesIterator.next();
if (isVerbose()) {
logger.info("\tProcessing class {}", applicationClass.getName());
}
// create local copy to prevent java.util.ConcurrentModificationException
final List<SootMethod> methods = new ArrayList<>(applicationClass.getMethods());
for (SootMethod method : methods) {
if (!method.isConcrete() || builtByMe.contains(method)) {
continue;
}
final Body body = getBodySafely(method);
if (body == null) {
continue;
}
int localName = 0;
final Unit first = getFirstNotIdentityStmt(body);
final Iterator<Unit> unitIterator = body.getUnits().snapshotIterator();
while (unitIterator.hasNext()) {
final Unit unit = unitIterator.next();
for (ValueBox valueBox : unit.getUseBoxes()) {
final Value value = valueBox.getValue();
// outside (this is prohibited on language level as that would violate encapsulation)
if (!(value instanceof InvokeExpr) || value instanceof SpecialInvokeExpr) {
continue;
}
final InvokeExpr invokeExpr = (InvokeExpr) value;
final SootMethod invokedMethod = getMethodSafely(invokeExpr);
if (invokedMethod == null) {
continue;
}
SootMethodRef invokedMethodRef = getNewMethodRef(invokedMethod);
if (invokedMethodRef == null) {
invokedMethodRef = buildNewMethod(applicationClass, invokedMethod, invokeExpr);
setNewMethodRef(invokedMethod, invokedMethodRef);
newmethods++;
}
if (isVerbose()) {
logger.info("\t\t\tChanging {} to {}\tUnit: ", invokedMethod.getSignature(), invokedMethodRef.getSignature(), unit);
}
List<Value> args = invokeExpr.getArgs();
List<Type> parameterTypes = invokedMethodRef.parameterTypes();
int argsCount = args.size();
int paramCount = parameterTypes.size();
if (invokeExpr instanceof InstanceInvokeExpr || invokeExpr instanceof StaticInvokeExpr) {
if (invokeExpr instanceof InstanceInvokeExpr) {
argsCount++;
args.add(((InstanceInvokeExpr) invokeExpr).getBase());
}
while (argsCount < paramCount) {
Type pType = parameterTypes.get(argsCount);
Local newLocal = Jimple.v().newLocal("newLocal" + localName++, pType);
body.getLocals().add(newLocal);
body.getUnits().insertBeforeNoRedirect(Jimple.v().newAssignStmt(newLocal, getConstantType(pType)), first);
args.add(newLocal);
argsCount++;
}
valueBox.setValue(Jimple.v().newStaticInvokeExpr(invokedMethodRef, args));
}
methodcalls++;
}
}
}
}
Scene.v().releaseActiveHierarchy();
Scene.v().setFastHierarchy(new FastHierarchy());
}
use of soot.FastHierarchy in project soot by Sable.
the class MethodRenamer method internalTransform.
@Override
protected void internalTransform(String phaseName, Map<String, String> options) {
if (isVerbose()) {
logger.info("Transforming method names...");
}
BodyBuilder.retrieveAllBodies();
BodyBuilder.retrieveAllNames();
Scene.v().releaseActiveHierarchy();
// but DO NOT RENAME METHODS YET as it might break searching of declaring classes
for (SootClass applicationClass : Scene.v().getApplicationClasses()) {
final List<String> fieldNames = applicationClass.getFields().stream().map(SootField::getName).collect(collectingAndThen(toList(), Collections::unmodifiableList));
final List<String> leftFieldNames = new ArrayList<>(fieldNames);
// create local copy to avoid ConcurrentModificationException -- methods are being updated
final List<SootMethod> methods = new ArrayList<>(applicationClass.getMethods());
for (SootMethod method : methods) {
if (!isRenamingAllowed(method)) {
continue;
}
final Set<SootClass> declaringClasses = getDeclaringClasses(applicationClass, method);
if (declaringClasses.isEmpty()) {
throw new IllegalStateException("Cannot find classes that declare " + method.getSignature() + ".");
}
final Optional<SootClass> libraryClass = declaringClasses.stream().filter(SootClass::isLibraryClass).findAny();
if (libraryClass.isPresent()) {
if (isVerbose()) {
logger.info("Skipping renaming {} method as it overrides library one from {}.", method.getSignature(), libraryClass.get().getName());
}
continue;
}
// we unite declaringClasses with parents of application class (excluding library ones)
// to be sure that every class in this hierarchy has the only new name
// for all methods (in this hierarchy) with the same old name and different parameters
final Set<SootClass> union = uniteWithApplicationParents(applicationClass, declaringClasses);
String newName = getNewName(union, method.getName());
if (newName == null) {
if (leftFieldNames.isEmpty()) {
newName = getNewName();
} else {
final int randomIndex = Rand.getInt(leftFieldNames.size());
final String randomFieldName = leftFieldNames.remove(randomIndex);
// same name then we likely will fall in trouble when renaming this method before previous
if (isNotUnique(randomFieldName) || fieldNames.contains(randomFieldName)) {
newName = getNewName();
} else {
newName = randomFieldName;
}
}
}
// to rename methods (and their calls) correctly
for (SootClass declaringClass : union) {
classToRenamingMap.computeIfAbsent(declaringClass, RENAMING_MAP_CREATOR).put(method.getName(), newName);
}
}
}
// rename methods AFTER creating mapping
for (SootClass applicationClass : Scene.v().getApplicationClasses()) {
final List<SootMethod> methods = new ArrayList<>(applicationClass.getMethods());
for (SootMethod method : methods) {
final String newName = getNewName(Collections.singleton(applicationClass), method.getName());
if (newName != null) {
if (isVerbose()) {
logger.info("Method \"{}\" is being renamed to \"{}\".", method.getSignature(), newName);
}
method.setName(newName);
}
}
}
// iterate through application classes, update references of renamed methods
for (SootClass applicationClass : Scene.v().getApplicationClasses()) {
final List<SootMethod> methods = new ArrayList<>(applicationClass.getMethods());
for (SootMethod method : methods) {
if (!method.isConcrete() || method.getDeclaringClass().isLibraryClass()) {
continue;
}
final Body body = getActiveBodySafely(method);
if (body == null) {
continue;
}
for (Unit unit : body.getUnits()) {
for (ValueBox valueBox : unit.getUseBoxes()) {
Value v = valueBox.getValue();
if (!(v instanceof InvokeExpr)) {
continue;
}
final InvokeExpr invokeExpr = (InvokeExpr) v;
final SootMethodRef methodRef = invokeExpr.getMethodRef();
final Set<SootClass> parents = getParents(methodRef.declaringClass());
// 1. we check if method overrides one from library directly
// Note: we cannot use getDeclaringClasses(applicationClass, method) as method can be renamed
final Optional<SootClass> declaringLibraryClass = findDeclaringLibraryClass(parents, methodRef);
if (declaringLibraryClass.isPresent()) {
if (isVerbose()) {
logger.info("Skipping replacing method call \"{}\" in \"{}\" as it is overrides one " + " from library {}.", methodRef.getSignature(), method.getSignature(), declaringLibraryClass.get().getName());
}
continue;
}
final String newName = getNewName(parents, methodRef.name());
// we will get new name only if no one from class tree do not overrides library method
if (newName == null) {
continue;
}
final SootMethodRef newMethodRef = Scene.v().makeMethodRef(methodRef.declaringClass(), newName, methodRef.parameterTypes(), methodRef.returnType(), methodRef.isStatic());
invokeExpr.setMethodRef(newMethodRef);
if (isVerbose()) {
logger.info("Method call \"{}\" is being replaced with \"{}\" in {}.", methodRef.getSignature(), newMethodRef.getSignature(), method.getSignature());
}
}
}
}
}
Scene.v().releaseActiveHierarchy();
Scene.v().setFastHierarchy(new FastHierarchy());
if (isVerbose()) {
logger.info("Transforming method names is completed.");
}
}
use of soot.FastHierarchy in project soot by Sable.
the class EvalResults method test_1cfa_call_graph.
/**
* We assess the quality of building the 1-cfa call graph with the geometric
* points-to result.
*/
private void test_1cfa_call_graph(LocalVarNode vn, SootMethod caller, SootMethod callee_signature, Histogram ce_range) {
long l, r;
IVarAbstraction pn = ptsProvider.findInternalNode(vn);
if (pn == null)
return;
pn = pn.getRepresentative();
Set<SootMethod> tgts = new HashSet<SootMethod>();
Set<AllocNode> set = pn.get_all_points_to_objects();
LinkedList<CgEdge> list = ptsProvider.getCallEdgesInto(ptsProvider.getIDFromSootMethod(caller));
FastHierarchy hierarchy = Scene.v().getOrMakeFastHierarchy();
for (Iterator<CgEdge> it = list.iterator(); it.hasNext(); ) {
CgEdge p = it.next();
l = p.map_offset;
r = l + ptsProvider.max_context_size_block[p.s];
tgts.clear();
for (AllocNode obj : set) {
if (!pn.pointer_interval_points_to(l, r, obj))
continue;
Type t = obj.getType();
if (t == null)
continue;
else if (t instanceof AnySubType)
t = ((AnySubType) t).getBase();
else if (t instanceof ArrayType)
t = RefType.v("java.lang.Object");
try {
tgts.add(hierarchy.resolveConcreteDispatch(((RefType) t).getSootClass(), callee_signature));
} catch (Exception e) {
}
}
tgts.remove(null);
ce_range.addNumber(tgts.size());
}
}
use of soot.FastHierarchy in project soot by Sable.
the class PAG method addAllocEdge.
public boolean addAllocEdge(AllocNode from, VarNode to) {
FastHierarchy fh = typeManager.getFastHierarchy();
if (fh == null || to.getType() == null || fh.canStoreType(from.getType(), to.getType())) {
if (doAddAllocEdge(from, to)) {
edgeQueue.add(from);
edgeQueue.add(to);
return true;
}
}
return false;
}
Aggregations