All Downloads are FREE. Search and download functionalities are using the official Maven repository.

soot.jimple.toolkits.infoflow.UseFinder Maven / Gradle / Ivy

There is a newer version: 2.5.0-9
Show newest version
package soot.jimple.toolkits.infoflow;

import soot.*;
import soot.util.*;
import java.util.*;

import soot.toolkits.scalar.*;
import soot.jimple.toolkits.callgraph.*;
import soot.jimple.*;

// UseFinder written by Richard L. Halpert, 2007-03-13
// Compiles a list of all uses of fields of each application class within the
// application classes by looking at every application method.
// Compiles a list of all calls to methods of each application class within the
// application classes by using the call graph.

public class UseFinder
{
	ReachableMethods rm;

	Map classToExtFieldAccesses; // each field access is a Pair 
	Map classToIntFieldAccesses;
	
	Map classToExtCalls; // each call is a Pair 
	Map classToIntCalls;
	
	public UseFinder()
	{
		classToExtFieldAccesses = new HashMap();
		classToIntFieldAccesses = new HashMap();
		classToExtCalls = new HashMap();
		classToIntCalls = new HashMap();
		
		rm = Scene.v().getReachableMethods();
		
		doAnalysis();
	}
	
	public UseFinder(ReachableMethods rm)
	{
		classToExtFieldAccesses = new HashMap();
		classToIntFieldAccesses = new HashMap();
		classToExtCalls = new HashMap();
		classToIntCalls = new HashMap();
		
		this.rm = rm;
		
		doAnalysis();
	}
	
	public List getExtFieldAccesses(SootClass sc)
	{
		if(classToExtFieldAccesses.containsKey(sc))
			return classToExtFieldAccesses.get(sc);
		throw new RuntimeException("UseFinder does not search non-application classes: " + sc);
	}
	
	public List getIntFieldAccesses(SootClass sc)
	{
		if(classToIntFieldAccesses.containsKey(sc))
			return classToIntFieldAccesses.get(sc);
		throw new RuntimeException("UseFinder does not search non-application classes: " + sc);
	}
	
	public List getExtCalls(SootClass sc)
	{
		if(classToExtCalls.containsKey(sc))
			return classToExtCalls.get(sc);
		throw new RuntimeException("UseFinder does not search non-application classes: " + sc);
	}
	
	public List getIntCalls(SootClass sc)
	{
		if(classToIntCalls.containsKey(sc))
			return classToIntCalls.get(sc);
		throw new RuntimeException("UseFinder does not search non-application classes: " + sc);
	}
	
	// This is an incredibly stupid way to do this... we should just use the call graph for faster/better info!
	public List getExtMethods(SootClass sc)
	{
		if(classToExtCalls.containsKey(sc))
		{
			List extCalls = classToExtCalls.get(sc);
			List extMethods = new ArrayList();
			for(Iterator callIt = extCalls.iterator(); callIt.hasNext(); )
			{
				Pair call = (Pair) callIt.next();
				SootMethod calledMethod = ((Stmt) call.getO2()).getInvokeExpr().getMethod();
				if(!extMethods.contains(calledMethod))
					extMethods.add(calledMethod);
			}
			return extMethods;
		}
		throw new RuntimeException("UseFinder does not search non-application classes: " + sc);
	}
	
	public List getExtFields(SootClass sc)
	{
		if(classToExtFieldAccesses.containsKey(sc))
		{
			List extAccesses = classToExtFieldAccesses.get(sc);
			List extFields = new ArrayList();
			for(Iterator accessIt = extAccesses.iterator(); accessIt.hasNext(); )
			{
				Pair access = (Pair) accessIt.next();
				SootField accessedField = ((Stmt) access.getO2()).getFieldRef().getField();
				if(!extFields.contains(accessedField))
					extFields.add(accessedField);
			}
			return extFields;
		}
		throw new RuntimeException("UseFinder does not search non-application classes: " + sc);
	}
	
	private void doAnalysis()
	{
		Chain appClasses = Scene.v().getApplicationClasses();
		
		// Set up lists of internal and external accesses
		Iterator appClassesIt = appClasses.iterator();
		while(appClassesIt.hasNext())
		{
			SootClass appClass = (SootClass) appClassesIt.next();
			classToIntFieldAccesses.put(appClass, new ArrayList());
			classToExtFieldAccesses.put(appClass, new ArrayList());
			classToIntCalls.put(appClass, new ArrayList());
			classToExtCalls.put(appClass, new ArrayList());
		}

		// Find internal and external accesses
		appClassesIt = appClasses.iterator();
		while(appClassesIt.hasNext())
		{
			SootClass appClass = (SootClass) appClassesIt.next();		
    	    Iterator methodsIt = appClass.getMethods().iterator();
    	    while (methodsIt.hasNext())
    	    {
    	    	SootMethod method = (SootMethod) methodsIt.next();
				if(method.isConcrete() && rm.contains(method))
				{
					Body b = method.retrieveActiveBody();
					Iterator unitsIt = b.getUnits().iterator();
					while(unitsIt.hasNext())
					{
						Stmt s = (Stmt) unitsIt.next();
						if(s.containsFieldRef())
						{
							FieldRef fr = s.getFieldRef();
							if(fr.getFieldRef().resolve().getDeclaringClass() == appClass)
							{
								if(fr instanceof StaticFieldRef)
								{
									// static field ref in same class is considered internal
									classToIntFieldAccesses.get(appClass).add(new Pair(method, s));
								}
								else if(fr instanceof InstanceFieldRef)
								{
									InstanceFieldRef ifr = (InstanceFieldRef) fr;
									if( !method.isStatic() && ifr.getBase().equivTo(b.getThisLocal()) )
									{
										// this.field ref is considered internal
										classToIntFieldAccesses.get(appClass).add(new Pair(method, s));
									}
									else
									{
										// o.field ref is considered external
										classToExtFieldAccesses.get(appClass).add(new Pair(method, s));
									}
								}
							}
							else
							{
								// ref to some other class is considered external
								List otherClassList = classToExtFieldAccesses.get(fr.getFieldRef().resolve().getDeclaringClass());
								if(otherClassList == null)
								{
									otherClassList = new ArrayList();
									classToExtFieldAccesses.put(fr.getFieldRef().resolve().getDeclaringClass(), otherClassList);
								}
								otherClassList.add(new Pair(method, s));
							}
						}
						if(s.containsInvokeExpr())
						{
							InvokeExpr ie = s.getInvokeExpr();
							if(ie.getMethodRef().resolve().getDeclaringClass() == appClass) // what about sub/superclasses
							{
								if(ie instanceof StaticInvokeExpr)
								{
									// static field ref in same class is considered internal
									classToIntCalls.get(appClass).add(new Pair(method, s));
								}
								else if(ie instanceof InstanceInvokeExpr)
								{
									InstanceInvokeExpr iie = (InstanceInvokeExpr) ie;
									if( !method.isStatic() && iie.getBase().equivTo(b.getThisLocal()) )
									{
										// this.field ref is considered internal
										classToIntCalls.get(appClass).add(new Pair(method, s));
									}
									else
									{
										// o.field ref is considered external
										classToExtCalls.get(appClass).add(new Pair(method, s));
									}
								}
							}
							else
							{
								// ref to some other class is considered external
								List otherClassList = classToExtCalls.get(ie.getMethodRef().resolve().getDeclaringClass());
								if(otherClassList == null)
								{
									otherClassList = new ArrayList();
									classToExtCalls.put(ie.getMethodRef().resolve().getDeclaringClass(), otherClassList);
								}
								otherClassList.add(new Pair(method, s));
							}
						}
					}
				}
			}
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy