use of soot.dava.internal.AST.ASTMethodNode 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.dava.internal.AST.ASTMethodNode 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.dava.internal.AST.ASTMethodNode in project soot by Sable.
the class SuperFirstStmtHandler method addDefsToLiveVariables.
/*
* newASTPreInitMethod at time of invocation just contains body X find all
* defs for this body
*/
private List<Local> addDefsToLiveVariables() {
// get all defs within x
AllDefinitionsFinder finder = new AllDefinitionsFinder();
newASTPreInitMethod.apply(finder);
List<DefinitionStmt> allDefs = finder.getAllDefs();
List<Local> uniqueLocals = new ArrayList<Local>();
List<DefinitionStmt> uniqueLocalDefs = new ArrayList<DefinitionStmt>();
// remove any defs for fields, and any which are done multiple times
Iterator<DefinitionStmt> it = allDefs.iterator();
while (it.hasNext()) {
DefinitionStmt s = it.next();
Value left = s.getLeftOp();
if (left instanceof Local) {
if (uniqueLocals.contains(left)) {
// a def for this local already encountered
int index = uniqueLocals.indexOf(left);
uniqueLocals.remove(index);
uniqueLocalDefs.remove(index);
} else {
// no def for this local yet
uniqueLocals.add((Local) left);
uniqueLocalDefs.add(s);
}
}
}
// at this point unique locals contains all locals defined and
// uniqueLocaldef list has a list of the corresponding definitions
// Now remove those unique locals and localdefs whose stmtseq node does
// not have the ASTMEthodNode as a parent
// This is a conservative step!!
ASTParentNodeFinder parentFinder = new ASTParentNodeFinder();
newASTPreInitMethod.apply(parentFinder);
List<DefinitionStmt> toRemoveDefs = new ArrayList<DefinitionStmt>();
it = uniqueLocalDefs.iterator();
while (it.hasNext()) {
DefinitionStmt s = it.next();
Object parent = parentFinder.getParentOf(s);
if (parent == null || (!(parent instanceof ASTStatementSequenceNode))) {
// shouldnt happen but if it does add this s to toRemove list
toRemoveDefs.add(s);
}
// parent is an ASTStatementsequence node. check that its parent is
// the ASTMethodNode
Object grandParent = parentFinder.getParentOf(parent);
if (grandParent == null || (!(grandParent instanceof ASTMethodNode))) {
// can happen if obfuscators are really smart. add s to toRemove
// list
toRemoveDefs.add(s);
}
}
// remove any defs and corresponding locals if present in the
// toRemoveDefs list
it = toRemoveDefs.iterator();
while (it.hasNext()) {
DefinitionStmt s = it.next();
int index = uniqueLocalDefs.indexOf(s);
uniqueLocals.remove(index);
uniqueLocalDefs.remove(index);
}
// the uniqueLocalDefs contains all those definitions to unique locals
// which are not deeply nested in the X body
// find all the uses of these definitions in the original method body
toRemoveDefs = new ArrayList<DefinitionStmt>();
ASTUsesAndDefs uDdU = new ASTUsesAndDefs(originalASTMethod);
originalASTMethod.apply(uDdU);
it = uniqueLocalDefs.iterator();
while (it.hasNext()) {
DefinitionStmt s = it.next();
Object temp = uDdU.getDUChain(s);
if (temp == null) {
// couldnt find uses
toRemoveDefs.add(s);
continue;
}
ArrayList uses = (ArrayList) temp;
// check if uses is non-empty
if (uses.size() == 0) {
toRemoveDefs.add(s);
}
// check for all the non zero uses
Iterator useIt = uses.iterator();
boolean onlyInConstructorUnit = true;
while (useIt.hasNext()) {
// a use is either a statement or a node(condition, synch,
// switch , for etc)
Object tempUse = useIt.next();
if (tempUse != originalConstructorUnit) {
onlyInConstructorUnit = false;
}
}
if (onlyInConstructorUnit) {
// mark it to be removed
toRemoveDefs.add(s);
}
}
// remove any defs and corresponding locals if present in the
// toRemoveDefs list
it = toRemoveDefs.iterator();
while (it.hasNext()) {
DefinitionStmt s = it.next();
int index = uniqueLocalDefs.indexOf(s);
uniqueLocals.remove(index);
uniqueLocalDefs.remove(index);
}
// the remaining uniquelocals are the ones which are needed for body Y
return uniqueLocals;
}
use of soot.dava.internal.AST.ASTMethodNode in project soot by Sable.
the class DavaStaticBlockCleaner method inline.
/*
* Method called with a sootMethod to decide whether this method should be inlined or not
* returns null if it shouldnt be inlined
*
* A method can be inlined if it belongs to the same class and also if its static....(why???)
*/
public ASTMethodNode inline(SootMethod maybeInline) {
if (sootClass != null) {
// 1, method should belong to the same class as the clinit method
if (sootClass.declaresMethod(maybeInline.getSubSignature())) {
if (Modifier.isStatic(maybeInline.getModifiers())) {
// retireve the active body
if (!maybeInline.hasActiveBody())
throw new RuntimeException("method " + maybeInline.getName() + " has no active body!");
Body bod = maybeInline.getActiveBody();
Chain units = ((DavaBody) bod).getUnits();
if (units.size() != 1) {
throw new RuntimeException("DavaBody AST doesn't have single root.");
}
ASTNode ASTtemp = (ASTNode) units.getFirst();
if (!(ASTtemp instanceof ASTMethodNode))
throw new RuntimeException("Starting node of DavaBody AST is not an ASTMethodNode");
// restricting to methods which do not have any variables declared
ASTMethodNode toReturn = (ASTMethodNode) ASTtemp;
ASTStatementSequenceNode declarations = toReturn.getDeclarations();
if (declarations.getStatements().size() == 0) {
// System.out.println("No declarations in the method. we can inline this method");
return toReturn;
}
}
}
}
// meaning dont inline
return null;
}
use of soot.dava.internal.AST.ASTMethodNode in project soot by Sable.
the class RemoveEmptyBodyDefaultConstructor method checkAndRemoveDefault.
public static void checkAndRemoveDefault(SootClass s) {
debug("\n\nRemoveEmptyBodyDefaultConstructor----" + s.getName());
List methods = s.getMethods();
Iterator it = methods.iterator();
List<SootMethod> constructors = new ArrayList<SootMethod>();
while (it.hasNext()) {
SootMethod method = (SootMethod) it.next();
debug("method name is" + method.getName());
if (method.getName().indexOf("<init>") > -1) {
// constructor add to constructor list
constructors.add(method);
}
}
if (constructors.size() != 1) {
// cant do anything since there are more than one constructors
debug("class has more than one constructors cant do anything");
return;
}
// only one constructor check its default (no arguments)
SootMethod constructor = constructors.get(0);
if (constructor.getParameterCount() != 0) {
// can only deal with default constructors
debug("constructor is not the default constructor");
return;
}
debug("Check that the body is empty....and call to super contains no arguments and delete");
if (!constructor.hasActiveBody()) {
debug("No active body found for the default constructor");
return;
}
Body body = constructor.getActiveBody();
Chain units = ((DavaBody) body).getUnits();
if (units.size() != 1) {
debug(" DavaBody AST does not have single root");
return;
}
ASTNode AST = (ASTNode) units.getFirst();
if (!(AST instanceof ASTMethodNode))
throw new RuntimeException("Starting node of DavaBody AST is not an ASTMethodNode");
ASTMethodNode methodNode = (ASTMethodNode) AST;
debug("got methodnode check body is empty and super has nothing in it");
List<Object> subBodies = methodNode.get_SubBodies();
if (subBodies.size() != 1) {
debug("Method node does not have one subBody!!!");
return;
}
List methodBody = (List) subBodies.get(0);
if (methodBody.size() != 0) {
debug("Method body size is greater than 1 so cant do nothing");
return;
}
debug("Method body is empty...check super call is empty");
if (((DavaBody) body).get_ConstructorExpr().getArgCount() != 0) {
debug("call to super not empty");
return;
}
debug("REMOVE METHOD");
s.removeMethod(constructor);
}
Aggregations