use of soot.SootMethod in project soot by Sable.
the class PAG method addCallTarget.
public final void addCallTarget(Edge e) {
if (!e.passesParameters())
return;
MethodPAG srcmpag = MethodPAG.v(this, e.src());
MethodPAG tgtmpag = MethodPAG.v(this, e.tgt());
Pair<Node, Node> pval;
if (e.isExplicit() || e.kind() == Kind.THREAD || e.kind() == Kind.ASYNCTASK) {
addCallTarget(srcmpag, tgtmpag, (Stmt) e.srcUnit(), e.srcCtxt(), e.tgtCtxt(), e);
} else if (e.kind() == Kind.EXECUTOR) {
InvokeExpr ie = e.srcStmt().getInvokeExpr();
boolean virtualCall = callAssigns.containsKey(ie);
Node parm = srcmpag.nodeFactory().getNode(ie.getArg(0));
parm = srcmpag.parameterize(parm, e.srcCtxt());
parm = parm.getReplacement();
Node thiz = tgtmpag.nodeFactory().caseThis();
thiz = tgtmpag.parameterize(thiz, e.tgtCtxt());
thiz = thiz.getReplacement();
addEdge(parm, thiz);
pval = addInterproceduralAssignment(parm, thiz, e);
callAssigns.put(ie, pval);
callToMethod.put(ie, srcmpag.getMethod());
if (virtualCall && !virtualCallsToReceivers.containsKey(ie)) {
virtualCallsToReceivers.put(ie, parm);
}
} else if (e.kind() == Kind.HANDLER) {
InvokeExpr ie = e.srcStmt().getInvokeExpr();
boolean virtualCall = callAssigns.containsKey(ie);
assert virtualCall == true;
Node base = srcmpag.nodeFactory().getNode(((VirtualInvokeExpr) ie).getBase());
base = srcmpag.parameterize(base, e.srcCtxt());
base = base.getReplacement();
Node thiz = tgtmpag.nodeFactory().caseThis();
thiz = tgtmpag.parameterize(thiz, e.tgtCtxt());
thiz = thiz.getReplacement();
addEdge(base, thiz);
pval = addInterproceduralAssignment(base, thiz, e);
callAssigns.put(ie, pval);
callToMethod.put(ie, srcmpag.getMethod());
virtualCallsToReceivers.put(ie, base);
} else if (e.kind() == Kind.PRIVILEGED) {
// Flow from first parameter of doPrivileged() invocation
// to this of target, and from return of target to the
// return of doPrivileged()
InvokeExpr ie = e.srcStmt().getInvokeExpr();
Node parm = srcmpag.nodeFactory().getNode(ie.getArg(0));
parm = srcmpag.parameterize(parm, e.srcCtxt());
parm = parm.getReplacement();
Node thiz = tgtmpag.nodeFactory().caseThis();
thiz = tgtmpag.parameterize(thiz, e.tgtCtxt());
thiz = thiz.getReplacement();
addEdge(parm, thiz);
pval = addInterproceduralAssignment(parm, thiz, e);
callAssigns.put(ie, pval);
callToMethod.put(ie, srcmpag.getMethod());
if (e.srcUnit() instanceof AssignStmt) {
AssignStmt as = (AssignStmt) e.srcUnit();
Node ret = tgtmpag.nodeFactory().caseRet();
ret = tgtmpag.parameterize(ret, e.tgtCtxt());
ret = ret.getReplacement();
Node lhs = srcmpag.nodeFactory().getNode(as.getLeftOp());
lhs = srcmpag.parameterize(lhs, e.srcCtxt());
lhs = lhs.getReplacement();
addEdge(ret, lhs);
pval = addInterproceduralAssignment(ret, lhs, e);
callAssigns.put(ie, pval);
callToMethod.put(ie, srcmpag.getMethod());
}
} else if (e.kind() == Kind.FINALIZE) {
Node srcThis = srcmpag.nodeFactory().caseThis();
srcThis = srcmpag.parameterize(srcThis, e.srcCtxt());
srcThis = srcThis.getReplacement();
Node tgtThis = tgtmpag.nodeFactory().caseThis();
tgtThis = tgtmpag.parameterize(tgtThis, e.tgtCtxt());
tgtThis = tgtThis.getReplacement();
addEdge(srcThis, tgtThis);
pval = addInterproceduralAssignment(srcThis, tgtThis, e);
} else if (e.kind() == Kind.NEWINSTANCE) {
Stmt s = (Stmt) e.srcUnit();
InstanceInvokeExpr iie = (InstanceInvokeExpr) s.getInvokeExpr();
Node cls = srcmpag.nodeFactory().getNode(iie.getBase());
cls = srcmpag.parameterize(cls, e.srcCtxt());
cls = cls.getReplacement();
Node newObject = nodeFactory.caseNewInstance((VarNode) cls);
Node initThis = tgtmpag.nodeFactory().caseThis();
initThis = tgtmpag.parameterize(initThis, e.tgtCtxt());
initThis = initThis.getReplacement();
addEdge(newObject, initThis);
if (s instanceof AssignStmt) {
AssignStmt as = (AssignStmt) s;
Node asLHS = srcmpag.nodeFactory().getNode(as.getLeftOp());
asLHS = srcmpag.parameterize(asLHS, e.srcCtxt());
asLHS = asLHS.getReplacement();
addEdge(newObject, asLHS);
}
pval = addInterproceduralAssignment(newObject, initThis, e);
callAssigns.put(s.getInvokeExpr(), pval);
callToMethod.put(s.getInvokeExpr(), srcmpag.getMethod());
} else if (e.kind() == Kind.REFL_INVOKE) {
// Flow (1) from first parameter of invoke(..) invocation
// to this of target, (2) from the contents of the second (array)
// parameter
// to all parameters of the target, and (3) from return of target to
// the
// return of invoke(..)
// (1)
InvokeExpr ie = e.srcStmt().getInvokeExpr();
Value arg0 = ie.getArg(0);
// if "null" is passed in, omit the edge
if (arg0 != NullConstant.v()) {
Node parm0 = srcmpag.nodeFactory().getNode(arg0);
parm0 = srcmpag.parameterize(parm0, e.srcCtxt());
parm0 = parm0.getReplacement();
Node thiz = tgtmpag.nodeFactory().caseThis();
thiz = tgtmpag.parameterize(thiz, e.tgtCtxt());
thiz = thiz.getReplacement();
addEdge(parm0, thiz);
pval = addInterproceduralAssignment(parm0, thiz, e);
callAssigns.put(ie, pval);
callToMethod.put(ie, srcmpag.getMethod());
}
// (2)
Value arg1 = ie.getArg(1);
SootMethod tgt = e.getTgt().method();
// edge
if (arg1 != NullConstant.v() && tgt.getParameterCount() > 0) {
Node parm1 = srcmpag.nodeFactory().getNode(arg1);
parm1 = srcmpag.parameterize(parm1, e.srcCtxt());
parm1 = parm1.getReplacement();
FieldRefNode parm1contents = makeFieldRefNode((VarNode) parm1, ArrayElement.v());
for (int i = 0; i < tgt.getParameterCount(); i++) {
// if no reference type, create no edge
if (!(tgt.getParameterType(i) instanceof RefLikeType))
continue;
Node tgtParmI = tgtmpag.nodeFactory().caseParm(i);
tgtParmI = tgtmpag.parameterize(tgtParmI, e.tgtCtxt());
tgtParmI = tgtParmI.getReplacement();
addEdge(parm1contents, tgtParmI);
pval = addInterproceduralAssignment(parm1contents, tgtParmI, e);
callAssigns.put(ie, pval);
}
}
// the return type of the callee is actually a reference type
if (e.srcUnit() instanceof AssignStmt && (tgt.getReturnType() instanceof RefLikeType)) {
AssignStmt as = (AssignStmt) e.srcUnit();
Node ret = tgtmpag.nodeFactory().caseRet();
ret = tgtmpag.parameterize(ret, e.tgtCtxt());
ret = ret.getReplacement();
Node lhs = srcmpag.nodeFactory().getNode(as.getLeftOp());
lhs = srcmpag.parameterize(lhs, e.srcCtxt());
lhs = lhs.getReplacement();
addEdge(ret, lhs);
pval = addInterproceduralAssignment(ret, lhs, e);
callAssigns.put(ie, pval);
}
} else if (e.kind() == Kind.REFL_CLASS_NEWINSTANCE || e.kind() == Kind.REFL_CONSTR_NEWINSTANCE) {
// (1) create a fresh node for the new object
// (2) create edge from this object to "this" of the constructor
// (3) if this is a call to Constructor.newInstance and not
// Class.newInstance,
// create edges passing the contents of the arguments array of the
// call
// to all possible parameters of the target
// (4) if we are inside an assign statement,
// assign the fresh object from (1) to the LHS of the assign
// statement
Stmt s = (Stmt) e.srcUnit();
InstanceInvokeExpr iie = (InstanceInvokeExpr) s.getInvokeExpr();
// (1)
Node cls = srcmpag.nodeFactory().getNode(iie.getBase());
cls = srcmpag.parameterize(cls, e.srcCtxt());
cls = cls.getReplacement();
if (cls instanceof ContextVarNode)
cls = findLocalVarNode(((VarNode) cls).getVariable());
VarNode newObject = makeGlobalVarNode(cls, RefType.v("java.lang.Object"));
SootClass tgtClass = e.getTgt().method().getDeclaringClass();
RefType tgtType = tgtClass.getType();
AllocNode site = makeAllocNode(new Pair<Node, SootClass>(cls, tgtClass), tgtType, null);
addEdge(site, newObject);
// (2)
Node initThis = tgtmpag.nodeFactory().caseThis();
initThis = tgtmpag.parameterize(initThis, e.tgtCtxt());
initThis = initThis.getReplacement();
addEdge(newObject, initThis);
addInterproceduralAssignment(newObject, initThis, e);
// (3)
if (e.kind() == Kind.REFL_CONSTR_NEWINSTANCE) {
Value arg = iie.getArg(0);
SootMethod tgt = e.getTgt().method();
// edge
if (arg != NullConstant.v() && tgt.getParameterCount() > 0) {
Node parm0 = srcmpag.nodeFactory().getNode(arg);
parm0 = srcmpag.parameterize(parm0, e.srcCtxt());
parm0 = parm0.getReplacement();
FieldRefNode parm1contents = makeFieldRefNode((VarNode) parm0, ArrayElement.v());
for (int i = 0; i < tgt.getParameterCount(); i++) {
// if no reference type, create no edge
if (!(tgt.getParameterType(i) instanceof RefLikeType))
continue;
Node tgtParmI = tgtmpag.nodeFactory().caseParm(i);
tgtParmI = tgtmpag.parameterize(tgtParmI, e.tgtCtxt());
tgtParmI = tgtParmI.getReplacement();
addEdge(parm1contents, tgtParmI);
pval = addInterproceduralAssignment(parm1contents, tgtParmI, e);
callAssigns.put(iie, pval);
}
}
}
// (4)
if (s instanceof AssignStmt) {
AssignStmt as = (AssignStmt) s;
Node asLHS = srcmpag.nodeFactory().getNode(as.getLeftOp());
asLHS = srcmpag.parameterize(asLHS, e.srcCtxt());
asLHS = asLHS.getReplacement();
addEdge(newObject, asLHS);
}
pval = addInterproceduralAssignment(newObject, initThis, e);
callAssigns.put(s.getInvokeExpr(), pval);
callToMethod.put(s.getInvokeExpr(), srcmpag.getMethod());
} else {
throw new RuntimeException("Unhandled edge " + e);
}
}
use of soot.SootMethod in project soot by Sable.
the class MethodCallFinder method inInvokeStmt.
/*
* some ASTConstuct{ ASTConstruct{ Some bodies Some Bodies Statement
* SequenceNode New Stmt seq node with some stmts some stmts ---------->
* Body of method to inline the invoke stmt New Stmt seq node with other
* stmts some other stmts Some other bodies Some other bodies End
* ASTConstruct End ASTConstruct
*/
/*
* Notice that since this class is only invoked for clinit methods this
* invoke statement is some invocation that occured within the clinit method
*/
public void inInvokeStmt(InvokeStmt s) {
InvokeExpr invokeExpr = s.getInvokeExpr();
SootMethod maybeInline = invokeExpr.getMethod();
// check whether we want to inline
ASTMethodNode toInlineASTMethod = cleaner.inline(maybeInline);
if (toInlineASTMethod == null) {
// not to inline
return;
} else {
// yes we want to inline
// we know that the method to be inlined has no declarations.
List<Object> subBodies = toInlineASTMethod.get_SubBodies();
if (subBodies.size() != 1) {
throw new RuntimeException("Found ASTMEthod node with more than one subBodies");
}
List body = (List) subBodies.get(0);
ASTParentNodeFinder finder = new ASTParentNodeFinder();
underAnalysis.apply(finder);
List<ASTStatementSequenceNode> newChangedBodyPart = createChangedBodyPart(s, body, finder);
boolean replaced = replaceSubBody(s, newChangedBodyPart, finder);
if (replaced) {
// so the invoke stmt has been replaced with the body of the
// method invoked
/*
* if the inlined method contained an assignment to a static
* field we want to replace that with a throw stmt
*/
StaticDefinitionFinder defFinder = new StaticDefinitionFinder(maybeInline);
toInlineASTMethod.apply(defFinder);
if (defFinder.anyFinalFieldDefined()) {
// create throw stmt to be added to inlined method
// create a SootMethodRef
SootClass runtime = Scene.v().loadClassAndSupport("java.lang.RuntimeException");
if (runtime.declaresMethod("void <init>(java.lang.String)")) {
SootMethod sootMethod = runtime.getMethod("void <init>(java.lang.String)");
SootMethodRef methodRef = sootMethod.makeRef();
RefType myRefType = RefType.v(runtime);
StringConstant tempString = StringConstant.v("This method used to have a definition of a final variable. " + "Dava inlined the definition into the static initializer");
List list = new ArrayList();
list.add(tempString);
GNewInvokeExpr newInvokeExpr = new GNewInvokeExpr(myRefType, methodRef, list);
GThrowStmt throwStmt = new GThrowStmt(newInvokeExpr);
AugmentedStmt augStmt = new AugmentedStmt(throwStmt);
List<AugmentedStmt> sequence = new ArrayList<AugmentedStmt>();
sequence.add(augStmt);
ASTStatementSequenceNode seqNode = new ASTStatementSequenceNode(sequence);
List<Object> subBody = new ArrayList<Object>();
subBody.add(seqNode);
toInlineASTMethod.replaceBody(subBody);
}
}
}
}
}
use of soot.SootMethod in project soot by Sable.
the class ConstantFieldValueFinder method computeFieldToValuesAssignedList.
/*
* Go through all the methods in the application and make a mapping of className+methodName ---> values assigned
* There can obviously be more than one value assigned to each field
*/
private void computeFieldToValuesAssignedList() {
// go through all the classes
Iterator classIt = appClasses.iterator();
while (classIt.hasNext()) {
SootClass s = (SootClass) classIt.next();
debug("\ncomputeMethodSummaries", "Processing class " + s.getName());
// go though all the methods
Iterator methodIt = s.methodIterator();
while (methodIt.hasNext()) {
SootMethod m = (SootMethod) methodIt.next();
DavaBody body = null;
if (m.hasActiveBody()) {
/*
* Added to try to fix the no active body found exception
*/
body = (DavaBody) m.getActiveBody();
} else {
continue;
}
ASTNode AST = (ASTNode) body.getUnits().getFirst();
// find all definitions in the program
AllDefinitionsFinder defFinder = new AllDefinitionsFinder();
AST.apply(defFinder);
Iterator<DefinitionStmt> allDefIt = defFinder.getAllDefs().iterator();
// go through each definition
while (allDefIt.hasNext()) {
DefinitionStmt stmt = allDefIt.next();
// debug("DefinitionStmt")
Value left = stmt.getLeftOp();
/*
* Only care if we have fieldRef on the left
*/
if (!(left instanceof FieldRef)) {
continue;
}
// we know definition is to a field
debug("computeMethodSummaries method: " + m.getName(), "Field ref is: " + left);
// Information we want to store is class of field and name of field and the right op
FieldRef ref = (FieldRef) left;
SootField field = ref.getField();
/*
* Only care about fields with primtype
*/
if (!(field.getType() instanceof PrimType))
continue;
String fieldName = field.getName();
String declaringClass = field.getDeclaringClass().getName();
debug("\tField Name: " + fieldName);
debug("\tField DeclaringClass: " + declaringClass);
// get the valueList for this class+field combo
String combined = declaringClass + combiner + fieldName;
Object temp = fieldToValues.get(combined);
ArrayList valueList;
if (temp == null) {
// no value of this field was yet assigned
valueList = new ArrayList();
fieldToValues.put(combined, valueList);
} else {
valueList = (ArrayList) temp;
}
valueList.add(stmt.getRightOp());
}
// going through all the definitions
}
// going through methods of class s
}
// going through classes
}
use of soot.SootMethod in project soot by Sable.
the class InterProceduralAnalyses method applyInterProceduralAnalyses.
/*
* Method is invoked by postProcessDava in PackManager
* if the transformations flag is true
*
* All interproceduralAnalyses should be applied in here
*/
public static void applyInterProceduralAnalyses() {
Chain classes = Scene.v().getApplicationClasses();
if (DEBUG)
System.out.println("\n\nInvoking redundantFielduseEliminator");
ConstantFieldValueFinder finder = new ConstantFieldValueFinder(classes);
HashMap<String, Object> constantValueFields = finder.getFieldsWithConstantValues();
if (DEBUG)
finder.printConstantValueFields();
/*
* The code above this gathers interprocedural information
* the code below this USES the interprocedural results
*/
Iterator it = classes.iterator();
while (it.hasNext()) {
// go though all the methods
SootClass s = (SootClass) it.next();
Iterator methodIt = s.methodIterator();
while (methodIt.hasNext()) {
SootMethod m = (SootMethod) methodIt.next();
/*
* Adding try block to handle RuntimeException no active body found
*/
DavaBody body = null;
if (m.hasActiveBody()) {
body = (DavaBody) m.getActiveBody();
} else {
continue;
}
ASTNode AST = (ASTNode) body.getUnits().getFirst();
if (!(AST instanceof ASTMethodNode))
continue;
Map options = PhaseOptions.v().getPhaseOptions("db.deobfuscate");
boolean deobfuscate = PhaseOptions.getBoolean(options, "enabled");
// System.out.println("force is "+force);
if (deobfuscate) {
if (DEBUG)
System.out.println("\nSTART CP Class:" + s.getName() + " Method: " + m.getName());
CPApplication CPApp = new CPApplication((ASTMethodNode) AST, constantValueFields, finder.getClassNameFieldNameToSootFieldMapping());
AST.apply(CPApp);
if (DEBUG)
System.out.println("DONE CP for " + m.getName());
}
// expression simplification
// SimplifyExpressions.DEBUG=true;
AST.apply(new SimplifyExpressions());
// SimplifyConditions.DEBUG=true;
AST.apply(new SimplifyConditions());
// condition elimination
// EliminateConditions.DEBUG=true;
AST.apply(new EliminateConditions((ASTMethodNode) AST));
// the above should ALWAYS be followed by an unreachable code eliminator
AST.apply(new UnreachableCodeEliminator(AST));
// local variable cleanup
AST.apply(new LocalVariableCleaner(AST));
// VERY EXPENSIVE STAGE of redoing all analyses!!!!
if (deobfuscate) {
if (DEBUG)
System.out.println("reinvoking analyzeAST");
UselessLabelFinder.DEBUG = false;
body.analyzeAST();
}
// renaming should be applied as the last stage
options = PhaseOptions.v().getPhaseOptions("db.renamer");
boolean renamer = PhaseOptions.getBoolean(options, "enabled");
// System.out.println("renaming is"+renamer);
if (renamer) {
applyRenamerAnalyses(AST, body);
}
// remove returns from void methods
VoidReturnRemover.cleanClass(s);
}
}
}
use of soot.SootMethod in project soot by Sable.
the class LockAllocationBodyTransformer method getLockFor.
public static Value getLockFor(EquivalentValue lockEqVal) {
Value lock = lockEqVal.getValue();
if (lock instanceof InstanceFieldRef)
return lock;
if (// it would be better to lock the array
lock instanceof ArrayRef)
// ref for each value of the index!
return ((ArrayRef) lock).getBase();
if (lock instanceof Local)
return lock;
if (lock instanceof StaticFieldRef || lock instanceof NewStaticLock) {
if (lockEqValToLock.containsKey(lockEqVal))
return lockEqValToLock.get(lockEqVal);
SootClass lockClass = null;
if (lock instanceof StaticFieldRef) {
StaticFieldRef sfrLock = (StaticFieldRef) lock;
lockClass = sfrLock.getField().getDeclaringClass();
} else if (lock instanceof NewStaticLock) {
DeadlockAvoidanceEdge dae = (DeadlockAvoidanceEdge) lock;
lockClass = dae.getLockClass();
}
SootMethod clinitMethod = null;
JimpleBody clinitBody = null;
Stmt firstStmt = null;
boolean addingNewClinit = !lockClass.declaresMethod("void <clinit>()");
if (addingNewClinit) {
clinitMethod = Scene.v().makeSootMethod("<clinit>", new ArrayList(), VoidType.v(), Modifier.PUBLIC | Modifier.STATIC);
clinitBody = Jimple.v().newBody(clinitMethod);
clinitMethod.setActiveBody(clinitBody);
lockClass.addMethod(clinitMethod);
} else {
clinitMethod = lockClass.getMethod("void <clinit>()");
clinitBody = (JimpleBody) clinitMethod.getActiveBody();
firstStmt = clinitBody.getFirstNonIdentityStmt();
}
PatchingChain<Unit> clinitUnits = clinitBody.getUnits();
Local lockLocal = Jimple.v().newLocal("objectLockLocal" + lockNumber, RefType.v("java.lang.Object"));
// lockNumber is increased below
// TODO: add name conflict
clinitBody.getLocals().add(lockLocal);
// avoidance code
// assign new object to lock obj
Stmt newStmt = Jimple.v().newAssignStmt(lockLocal, Jimple.v().newNewExpr(RefType.v("java.lang.Object")));
if (addingNewClinit)
clinitUnits.add(newStmt);
else
clinitUnits.insertBeforeNoRedirect(newStmt, firstStmt);
// initialize new object
SootClass objectClass = Scene.v().loadClassAndSupport("java.lang.Object");
RefType type = RefType.v(objectClass);
SootMethod initMethod = objectClass.getMethod("void <init>()");
Stmt initStmt = Jimple.v().newInvokeStmt(Jimple.v().newSpecialInvokeExpr(lockLocal, initMethod.makeRef(), Collections.EMPTY_LIST));
if (addingNewClinit)
clinitUnits.add(initStmt);
else
clinitUnits.insertBeforeNoRedirect(initStmt, firstStmt);
// copy new object to global static lock object (for use by other
// fns)
SootField actualLockObject = Scene.v().makeSootField("objectLockGlobal" + lockNumber, RefType.v("java.lang.Object"), Modifier.STATIC | Modifier.PUBLIC);
lockNumber++;
lockClass.addField(actualLockObject);
StaticFieldRef actualLockSfr = Jimple.v().newStaticFieldRef(actualLockObject.makeRef());
Stmt assignStmt = Jimple.v().newAssignStmt(actualLockSfr, lockLocal);
if (addingNewClinit)
clinitUnits.add(assignStmt);
else
clinitUnits.insertBeforeNoRedirect(assignStmt, firstStmt);
if (addingNewClinit)
clinitUnits.add(Jimple.v().newReturnVoidStmt());
lockEqValToLock.put(lockEqVal, actualLockSfr);
return actualLockSfr;
}
throw new RuntimeException("Unknown type of lock (" + lock + "): expected FieldRef, ArrayRef, or Local");
}
Aggregations