use of soot.Body 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.Body in project soot by Sable.
the class AccessManager method createGetAccessor.
private static void createGetAccessor(SootMethod container, AssignStmt as, FieldRef ref) {
java.util.List parameterTypes = new LinkedList();
java.util.List<SootClass> thrownExceptions = new LinkedList<SootClass>();
Body accessorBody = Jimple.v().newBody();
soot.util.Chain accStmts = accessorBody.getUnits();
LocalGenerator lg = new LocalGenerator(accessorBody);
Body containerBody = container.getActiveBody();
soot.util.Chain containerStmts = containerBody.getUnits();
SootClass target = ref.getField().getDeclaringClass();
SootMethod accessor;
String name = createAccessorName(ref.getField(), false);
accessor = target.getMethodByNameUnsafe(name);
if (accessor == null) {
Type returnType = ref.getField().getType();
Local thisLocal = lg.generateLocal(target.getType());
if (ref instanceof InstanceFieldRef) {
parameterTypes.add(target.getType());
accStmts.addFirst(Jimple.v().newIdentityStmt(thisLocal, Jimple.v().newParameterRef(target.getType(), 0)));
}
Local l = lg.generateLocal(ref.getField().getType());
Value v;
if (ref instanceof InstanceFieldRef) {
v = Jimple.v().newInstanceFieldRef(thisLocal, ref.getFieldRef());
} else {
v = Jimple.v().newStaticFieldRef(ref.getFieldRef());
}
accStmts.add(Jimple.v().newAssignStmt(l, v));
accStmts.add(Jimple.v().newReturnStmt(l));
accessor = Scene.v().makeSootMethod(name, parameterTypes, returnType, Modifier.PUBLIC | Modifier.STATIC, thrownExceptions);
accessorBody.setMethod(accessor);
accessor.setActiveBody(accessorBody);
target.addMethod(accessor);
}
java.util.List args = new LinkedList();
if (ref instanceof InstanceFieldRef) {
args.add(((InstanceFieldRef) ref).getBase());
}
InvokeExpr newExpr = Jimple.v().newStaticInvokeExpr(accessor.makeRef(), args);
as.setRightOp(newExpr);
}
use of soot.Body in project soot by Sable.
the class StaticMethodBinder method internalTransform.
protected void internalTransform(String phaseName, Map opts) {
Filter instanceInvokesFilter = new Filter(new InstanceInvokeEdgesPred());
SMBOptions options = new SMBOptions(opts);
String modifierOptions = PhaseOptions.getString(opts, "allowed-modifier-changes");
HashMap instanceToStaticMap = new HashMap();
CallGraph cg = Scene.v().getCallGraph();
Hierarchy hierarchy = Scene.v().getActiveHierarchy();
Iterator classesIt = Scene.v().getApplicationClasses().iterator();
while (classesIt.hasNext()) {
SootClass c = (SootClass) classesIt.next();
LinkedList methodsList = new LinkedList();
for (Iterator it = c.methodIterator(); it.hasNext(); ) {
methodsList.add(it.next());
}
while (!methodsList.isEmpty()) {
SootMethod container = (SootMethod) methodsList.removeFirst();
if (!container.isConcrete())
continue;
if (!instanceInvokesFilter.wrap(cg.edgesOutOf(container)).hasNext())
continue;
JimpleBody b = (JimpleBody) container.getActiveBody();
List<Unit> unitList = new ArrayList<Unit>();
unitList.addAll(b.getUnits());
Iterator<Unit> unitIt = unitList.iterator();
while (unitIt.hasNext()) {
Stmt s = (Stmt) unitIt.next();
if (!s.containsInvokeExpr())
continue;
InvokeExpr ie = s.getInvokeExpr();
if (ie instanceof StaticInvokeExpr || ie instanceof SpecialInvokeExpr)
continue;
Iterator targets = new Targets(instanceInvokesFilter.wrap(cg.edgesOutOf(s)));
if (!targets.hasNext())
continue;
SootMethod target = (SootMethod) targets.next();
if (targets.hasNext())
continue;
if (!AccessManager.ensureAccess(container, target, modifierOptions))
continue;
if (!target.getDeclaringClass().isApplicationClass() || !target.isConcrete())
continue;
// Don't modify java.lang.Object
if (target.getDeclaringClass() == Scene.v().getSootClass("java.lang.Object"))
continue;
if (!instanceToStaticMap.containsKey(target)) {
List newParameterTypes = new ArrayList();
newParameterTypes.add(RefType.v(target.getDeclaringClass().getName()));
newParameterTypes.addAll(target.getParameterTypes());
// Check for signature conflicts.
String newName = target.getName() + "_static";
while (target.getDeclaringClass().declaresMethod(newName, newParameterTypes, target.getReturnType())) newName = newName + "_static";
SootMethod ct = Scene.v().makeSootMethod(newName, newParameterTypes, target.getReturnType(), target.getModifiers() | Modifier.STATIC, target.getExceptions());
target.getDeclaringClass().addMethod(ct);
methodsList.addLast(ct);
ct.setActiveBody((Body) target.getActiveBody().clone());
// Make the invoke graph take into account the
// newly-cloned body.
{
Iterator oldUnits = target.getActiveBody().getUnits().iterator();
Iterator newUnits = ct.getActiveBody().getUnits().iterator();
while (newUnits.hasNext()) {
Stmt oldStmt, newStmt;
oldStmt = (Stmt) oldUnits.next();
newStmt = (Stmt) newUnits.next();
Iterator edges = cg.edgesOutOf(oldStmt);
while (edges.hasNext()) {
Edge e = (Edge) edges.next();
cg.addEdge(new Edge(ct, newStmt, e.tgt(), e.kind()));
cg.removeEdge(e);
}
}
}
// Shift the parameter list to apply to the new this
// parameter.
// If the method uses this, then we replace
// the r0 := @this with r0 := @parameter0 & shift.
// Otherwise, just zap the r0 := @this.
{
Body newBody = ct.getActiveBody();
Chain units = newBody.getUnits();
Iterator unitsIt = newBody.getUnits().snapshotIterator();
while (unitsIt.hasNext()) {
Stmt st = (Stmt) unitsIt.next();
if (st instanceof IdentityStmt) {
IdentityStmt is = (IdentityStmt) st;
if (is.getRightOp() instanceof ThisRef) {
units.swapWith(st, Jimple.v().newIdentityStmt(is.getLeftOp(), Jimple.v().newParameterRef(is.getRightOp().getType(), 0)));
} else {
if (is.getRightOp() instanceof ParameterRef) {
ParameterRef ro = (ParameterRef) is.getRightOp();
ro.setIndex(ro.getIndex() + 1);
}
}
}
}
}
instanceToStaticMap.put(target, ct);
}
SootMethod clonedTarget = (SootMethod) instanceToStaticMap.get(target);
Value thisToAdd = ((InstanceInvokeExpr) ie).getBase();
// Insert casts to please the verifier.
if (options.insert_redundant_casts()) {
// The verifier will complain if targetUsesThis, and:
// the argument passed to the method is not the same
// type.
// For instance, Bottle.price_static takes a cost.
// Cost is an interface implemented by Bottle.
SootClass localType, parameterType;
localType = ((RefType) ((InstanceInvokeExpr) ie).getBase().getType()).getSootClass();
parameterType = target.getDeclaringClass();
if (localType.isInterface() || hierarchy.isClassSuperclassOf(localType, parameterType)) {
Local castee = Jimple.v().newLocal("__castee", parameterType.getType());
b.getLocals().add(castee);
b.getUnits().insertBefore(Jimple.v().newAssignStmt(castee, Jimple.v().newCastExpr(((InstanceInvokeExpr) ie).getBase(), parameterType.getType())), s);
thisToAdd = castee;
}
}
// Now rebind the method call & fix the invoke graph.
{
List newArgs = new ArrayList();
newArgs.add(thisToAdd);
newArgs.addAll(ie.getArgs());
StaticInvokeExpr sie = Jimple.v().newStaticInvokeExpr(clonedTarget.makeRef(), newArgs);
ValueBox ieBox = s.getInvokeExprBox();
ieBox.setValue(sie);
cg.addEdge(new Edge(container, s, clonedTarget));
}
// (If enabled), add a null pointer check.
if (options.insert_null_checks()) {
boolean caught = TrapManager.isExceptionCaughtAt(Scene.v().getSootClass("java.lang.NullPointerException"), s, b);
/* Ah ha. Caught again! */
if (caught) {
/*
* In this case, we don't use throwPoint; instead,
* put the code right there.
*/
Stmt insertee = Jimple.v().newIfStmt(Jimple.v().newNeExpr(((InstanceInvokeExpr) ie).getBase(), NullConstant.v()), s);
b.getUnits().insertBefore(insertee, s);
// This sucks (but less than before).
((IfStmt) insertee).setTarget(s);
ThrowManager.addThrowAfter(b, insertee);
} else {
Stmt throwPoint = ThrowManager.getNullPointerExceptionThrower(b);
b.getUnits().insertBefore(Jimple.v().newIfStmt(Jimple.v().newEqExpr(((InstanceInvokeExpr) ie).getBase(), NullConstant.v()), throwPoint), s);
}
}
// Add synchronizing stuff.
{
if (target.isSynchronized()) {
clonedTarget.setModifiers(clonedTarget.getModifiers() & ~Modifier.SYNCHRONIZED);
SynchronizerManager.v().synchronizeStmtOn(s, b, (Local) ((InstanceInvokeExpr) ie).getBase());
}
}
// Resolve name collisions.
LocalNameStandardizer.v().transform(b, phaseName + ".lns");
}
}
}
}
use of soot.Body in project soot by Sable.
the class ReflectiveCallsInliner method createNewMethod.
@SuppressWarnings("unchecked")
private SootMethod createNewMethod(Kind callKind, String target, Type fieldSetGetType) {
List<Type> parameterTypes = new LinkedList<Type>();
Type returnType = null;
switch(callKind) {
case ClassForName:
returnType = RefType.v("java.lang.Class");
break;
case ClassNewInstance:
returnType = RefType.v("java.lang.Object");
break;
case ConstructorNewInstance:
parameterTypes.add(ArrayType.v(RefType.v("java.lang.Object"), 1));
returnType = RefType.v("java.lang.Object");
break;
case MethodInvoke:
parameterTypes.add(RefType.v("java.lang.Object"));
parameterTypes.add(ArrayType.v(RefType.v("java.lang.Object"), 1));
returnType = RefType.v("java.lang.Object");
break;
case FieldSet:
parameterTypes.add(RefType.v("java.lang.Object"));
parameterTypes.add(fieldSetGetType);
returnType = VoidType.v();
break;
case FieldGet:
parameterTypes.add(RefType.v("java.lang.Object"));
returnType = fieldSetGetType;
break;
default:
throw new IllegalStateException();
}
SootMethod newMethod = Scene.v().makeSootMethod("reflectiveCall" + (callNum++), parameterTypes, returnType, Modifier.PUBLIC | Modifier.STATIC);
Body newBody = Jimple.v().newBody(newMethod);
newMethod.setActiveBody(newBody);
reflectiveCallsClass.addMethod(newMethod);
PatchingChain<Unit> newUnits = newBody.getUnits();
LocalGenerator localGen = new LocalGenerator(newBody);
Local freshLocal;
Value replacement = null;
Local[] paramLocals = null;
switch(callKind) {
case ClassForName:
{
// replace by: <Class constant for <target>>
freshLocal = localGen.generateLocal(RefType.v("java.lang.Class"));
replacement = ClassConstant.v(target.replace('.', '/'));
break;
}
case ClassNewInstance:
{
// replace by: new <target>
RefType targetType = RefType.v(target);
freshLocal = localGen.generateLocal(targetType);
replacement = Jimple.v().newNewExpr(targetType);
break;
}
case ConstructorNewInstance:
{
/*
* replace r=constr.newInstance(args) by: Object p0 = args[0]; ...
* Object pn = args[n]; T0 a0 = (T0)p0; ... Tn an = (Tn)pn;
*/
SootMethod constructor = Scene.v().getMethod(target);
paramLocals = new Local[constructor.getParameterCount()];
if (constructor.getParameterCount() > 0) {
// argArrayLocal = @parameter-0
ArrayType arrayType = ArrayType.v(RefType.v("java.lang.Object"), 1);
Local argArrayLocal = localGen.generateLocal(arrayType);
newUnits.add(Jimple.v().newIdentityStmt(argArrayLocal, Jimple.v().newParameterRef(arrayType, 0)));
int i = 0;
for (Type paramType : ((Collection<Type>) constructor.getParameterTypes())) {
paramLocals[i] = localGen.generateLocal(paramType);
unboxParameter(argArrayLocal, i, paramLocals, paramType, newUnits, localGen);
i++;
}
}
RefType targetType = constructor.getDeclaringClass().getType();
freshLocal = localGen.generateLocal(targetType);
replacement = Jimple.v().newNewExpr(targetType);
break;
}
case MethodInvoke:
{
/*
* replace r=m.invoke(obj,args) by: T recv = (T)obj; Object p0 =
* args[0]; ... Object pn = args[n]; T0 a0 = (T0)p0; ... Tn an =
* (Tn)pn;
*/
SootMethod method = Scene.v().getMethod(target);
// recvObject = @parameter-0
RefType objectType = RefType.v("java.lang.Object");
Local recvObject = localGen.generateLocal(objectType);
newUnits.add(Jimple.v().newIdentityStmt(recvObject, Jimple.v().newParameterRef(objectType, 0)));
paramLocals = new Local[method.getParameterCount()];
if (method.getParameterCount() > 0) {
// argArrayLocal = @parameter-1
ArrayType arrayType = ArrayType.v(RefType.v("java.lang.Object"), 1);
Local argArrayLocal = localGen.generateLocal(arrayType);
newUnits.add(Jimple.v().newIdentityStmt(argArrayLocal, Jimple.v().newParameterRef(arrayType, 1)));
int i = 0;
for (Type paramType : ((Collection<Type>) method.getParameterTypes())) {
paramLocals[i] = localGen.generateLocal(paramType);
unboxParameter(argArrayLocal, i, paramLocals, paramType, newUnits, localGen);
i++;
}
}
RefType targetType = method.getDeclaringClass().getType();
freshLocal = localGen.generateLocal(targetType);
replacement = Jimple.v().newCastExpr(recvObject, method.getDeclaringClass().getType());
break;
}
case FieldSet:
case FieldGet:
{
/*
* replace f.set(o,v) by: Object obj = @parameter-0; T freshLocal =
* (T)obj;
*/
RefType objectType = RefType.v("java.lang.Object");
Local recvObject = localGen.generateLocal(objectType);
newUnits.add(Jimple.v().newIdentityStmt(recvObject, Jimple.v().newParameterRef(objectType, 0)));
SootField field = Scene.v().getField(target);
freshLocal = localGen.generateLocal(field.getDeclaringClass().getType());
replacement = Jimple.v().newCastExpr(recvObject, field.getDeclaringClass().getType());
break;
}
default:
throw new InternalError("Unknown kind of reflective call " + callKind);
}
AssignStmt replStmt = Jimple.v().newAssignStmt(freshLocal, replacement);
newUnits.add(replStmt);
Local retLocal = localGen.generateLocal(returnType);
switch(callKind) {
case ClassForName:
{
// add: retLocal = freshLocal;
newUnits.add(Jimple.v().newAssignStmt(retLocal, freshLocal));
break;
}
case ClassNewInstance:
{
// add: freshLocal.<init>()
SootClass targetClass = Scene.v().getSootClass(target);
SpecialInvokeExpr constrCallExpr = Jimple.v().newSpecialInvokeExpr(freshLocal, Scene.v().makeMethodRef(targetClass, SootMethod.constructorName, Collections.<Type>emptyList(), VoidType.v(), false));
InvokeStmt constrCallStmt2 = Jimple.v().newInvokeStmt(constrCallExpr);
newUnits.add(constrCallStmt2);
// add: retLocal = freshLocal
newUnits.add(Jimple.v().newAssignStmt(retLocal, freshLocal));
break;
}
case ConstructorNewInstance:
{
// add: freshLocal.<target>(a0,...,an);
SootMethod constructor = Scene.v().getMethod(target);
SpecialInvokeExpr constrCallExpr = Jimple.v().newSpecialInvokeExpr(freshLocal, constructor.makeRef(), Arrays.asList(paramLocals));
InvokeStmt constrCallStmt2 = Jimple.v().newInvokeStmt(constrCallExpr);
newUnits.add(constrCallStmt2);
// add: retLocal = freshLocal
newUnits.add(Jimple.v().newAssignStmt(retLocal, freshLocal));
break;
}
case MethodInvoke:
{
// add: freshLocal=recv.<target>(a0,...,an);
SootMethod method = Scene.v().getMethod(target);
InvokeExpr invokeExpr;
if (method.isStatic())
invokeExpr = Jimple.v().newStaticInvokeExpr(method.makeRef(), Arrays.asList(paramLocals));
else
invokeExpr = Jimple.v().newVirtualInvokeExpr(freshLocal, method.makeRef(), Arrays.<Value>asList(paramLocals));
if (method.getReturnType().equals(VoidType.v())) {
// method returns null; simply invoke it and return null
InvokeStmt invokeStmt = Jimple.v().newInvokeStmt(invokeExpr);
newUnits.add(invokeStmt);
AssignStmt assignStmt = Jimple.v().newAssignStmt(retLocal, NullConstant.v());
newUnits.add(assignStmt);
} else {
AssignStmt assignStmt = Jimple.v().newAssignStmt(retLocal, invokeExpr);
newUnits.add(assignStmt);
}
break;
}
case FieldSet:
{
// add freshLocal.<f> = v;
Local value = localGen.generateLocal(fieldSetGetType);
newUnits.insertBeforeNoRedirect(Jimple.v().newIdentityStmt(value, Jimple.v().newParameterRef(fieldSetGetType, 1)), replStmt);
SootField field = Scene.v().getField(target);
Local boxedOrCasted = localGen.generateLocal(field.getType());
insertCastOrUnboxingCode(boxedOrCasted, value, newUnits);
FieldRef fieldRef;
if (field.isStatic()) {
fieldRef = Jimple.v().newStaticFieldRef(field.makeRef());
} else {
fieldRef = Jimple.v().newInstanceFieldRef(freshLocal, field.makeRef());
}
newUnits.add(Jimple.v().newAssignStmt(fieldRef, boxedOrCasted));
break;
}
case FieldGet:
{
/*
* add: T2 temp = recv.<f>; return temp;
*/
SootField field = Scene.v().getField(target);
Local value = localGen.generateLocal(field.getType());
FieldRef fieldRef;
if (field.isStatic()) {
fieldRef = Jimple.v().newStaticFieldRef(field.makeRef());
} else {
fieldRef = Jimple.v().newInstanceFieldRef(freshLocal, field.makeRef());
}
newUnits.add(Jimple.v().newAssignStmt(value, fieldRef));
insertCastOrBoxingCode(retLocal, value, newUnits);
break;
}
}
if (!returnType.equals(VoidType.v()))
newUnits.add(Jimple.v().newReturnStmt(retLocal));
if (Options.v().validate())
newBody.validate();
cleanup(newBody);
return newMethod;
}
use of soot.Body in project soot by Sable.
the class AbstractJimpleBasedICFG method getSuccsOf.
@Override
public List<Unit> getSuccsOf(Unit u) {
Body body = unitToOwner.get(u);
if (body == null)
return Collections.emptyList();
DirectedGraph<Unit> unitGraph = getOrCreateUnitGraph(body);
return unitGraph.getSuccsOf(u);
}
Aggregations