use of soot.dava.toolkits.base.AST.traversals.ASTParentNodeFinder 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.toolkits.base.AST.traversals.ASTParentNodeFinder in project soot by Sable.
the class IfElseSplitter method outASTIfElseNode.
public void outASTIfElseNode(ASTIfElseNode node) {
// if some pattern has already matched cant do another one in this go
if (transform)
return;
List<Object> subBodies = node.get_SubBodies();
if (subBodies.size() != 2)
throw new DecompilationException("IfelseNode without two subBodies. report to developer");
List<Object> ifBody = (List<Object>) subBodies.get(0);
List<Object> elseBody = (List<Object>) subBodies.get(1);
boolean patternMatched = tryBodyPattern(ifBody, node.get_Label(), elseBody);
List<Object> newIfBody = null;
List<Object> outerScopeBody = null;
boolean negateIfCondition = false;
if (patternMatched) {
if (DEBUG)
System.out.println("First pattern matched");
newIfBody = ifBody;
outerScopeBody = elseBody;
negateIfCondition = false;
} else {
patternMatched = tryBodyPattern(elseBody, node.get_Label(), ifBody);
if (patternMatched) {
if (DEBUG)
System.out.println("Second pattern matched");
newIfBody = elseBody;
outerScopeBody = ifBody;
negateIfCondition = true;
}
}
// if at this point newIfBody and outerScopeBody are non null we got ourselves a transformation :)
if (newIfBody != null && outerScopeBody != null) {
ASTCondition cond = node.get_Condition();
if (negateIfCondition)
cond.flip();
ASTIfNode newNode = new ASTIfNode(node.get_Label(), cond, newIfBody);
if (DEBUG) {
System.out.println("New IF Node is: " + newNode.toString());
System.out.println("Outer scope body list is:\n");
for (int i = 0; i < outerScopeBody.size(); i++) System.out.println("\n\n " + outerScopeBody.get(i).toString());
}
ASTParentNodeFinder finder = new ASTParentNodeFinder();
methodNode.apply(finder);
Object returned = finder.getParentOf(node);
if (returned == null) {
// coundnt find parent so cant do anything
return;
}
/*
* Setting globals since everything is ready for transformation
* BECAUSE we cant modify the parent here we are going to do some
* bad coding style
* store the information needed for this into globals
* set a flag
* and the outASTMethod checks for this
*/
parent = (ASTNode) returned;
toReplace = node;
toInsert = newNode;
bodyAfterInsert = outerScopeBody;
transform = true;
}
}
use of soot.dava.toolkits.base.AST.traversals.ASTParentNodeFinder 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.toolkits.base.AST.traversals.ASTParentNodeFinder in project soot by Sable.
the class SuperFirstStmtHandler method inASTStatementSequenceNode.
/*
* looking for an init stmt
*/
public void inASTStatementSequenceNode(ASTStatementSequenceNode node) {
for (AugmentedStmt as : node.getStatements()) {
Unit u = as.get_Stmt();
if (u == originalConstructorUnit) {
// System.out.println("Found the constructorUnit"+u);
// ONE: make sure the parent of the super() call is an
// ASTMethodNode
ASTParentNodeFinder parentFinder = new ASTParentNodeFinder();
originalASTMethod.apply(parentFinder);
Object tempParent = parentFinder.getParentOf(node);
if (tempParent != originalASTMethod) {
// System.out.println("ASTMethod node is not the parent of
// constructorUnit");
// notice since we cant remove one call of super there is no
// point
// in trying to remove any other calls to super
removeInit();
return;
}
// only gets here if the call to super is not nested within some
// other construct
/**
*******************************************************
*/
/**
**************** CREATING PREINIT METHOD **************
*/
/**
*******************************************************
*/
// CREATE UNIQUE METHOD
// new method is initalized in
createSootPreInitMethod();
// newSootPreInitMethod
// Create ASTMethodNode for this SootMethod
// the field
createNewASTPreInitMethod(node);
if (newASTPreInitMethod == null) {
// could not create ASTMethodNode for some reason or the
// other
// just silently return
// System.out.println(">>>>>>>>>>>>>>>>Couldnt not create
// ASTMethodNode for the new PreInitMethod");
removeInit();
return;
}
if (!finalizePreInitMethod()) {
// shouldnt be creating PreInit
// System.out.println(">>>>>>>>>>>>>>SHOULDNT BE CREATING
// PREINIT");
removeInit();
return;
}
/**
*******************************************************
*/
/**
************ CREATING NEW CONSTRUCTOR *****************
*/
/**
*******************************************************
*/
// create SootMethod for the constructor
createNewConstructor();
createNewASTConstructor(node);
if (!createCallToSuper()) {
// could not create call to super
// still safe to simply exit
// System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>Could not
// create call to super...SuperFirstStmtHandler");
removeInit();
return;
}
finalizeConstructor();
/**
*******************************************************
*/
if (changeOriginalAST()) {
// System.out.println("Done Done Done");
debug("SuperFirstStmtHandler....inASTStatementSeuqneNode", "Added PreInit");
G.v().SootMethodAddedByDava = true;
G.v().SootMethodsAdded.add(newSootPreInitMethod);
G.v().SootMethodsAdded.add(newConstructor);
/**
*******************************************************
*/
/**
**************** CREATING INNER CLASS *****************
*/
/**
*******************************************************
*/
// notice that inner class is created by DavaPrinter in the
// printTo method
// all we do is set a Global to true and later on when the
// SootClass is being
// output the inner class will be output also
G.v().SootClassNeedsDavaSuperHandlerClass.add(originalSootClass);
// System.out.println("\n\nSet SootMethodAddedByDava to
// true\n\n");
}
}
}
}
use of soot.dava.toolkits.base.AST.traversals.ASTParentNodeFinder in project soot by Sable.
the class UselessAbruptStmtRemover method caseASTStatementSequenceNode.
public void caseASTStatementSequenceNode(ASTStatementSequenceNode node) {
Iterator<AugmentedStmt> it = node.getStatements().iterator();
AugmentedStmt remove = null;
ASTLabeledNode target = null;
while (it.hasNext()) {
AugmentedStmt as = it.next();
Stmt s = as.get_Stmt();
// we only care about break and continue stmts
if (!(s instanceof DAbruptStmt)) {
continue;
}
DAbruptStmt abrupt = (DAbruptStmt) s;
String label = abrupt.getLabel().toString();
if (label == null) {
// analysis with implicit abrupt flow but not needed currently
continue;
}
if (it.hasNext()) {
// afterwards...that is for sure dead code
throw new DecompilationException("Dead code detected. Report to developer");
}
// get the target node
Object temp = mapper.getTarget(label);
if (temp == null) {
continue;
// throw new DecompilationException("Could not find target for abrupt stmt"+abrupt.toString());
}
target = (ASTLabeledNode) temp;
// will need to find parents of ancestors see if we need to initialize the finder
if (finder == null) {
finder = new ASTParentNodeFinder();
methodNode.apply(finder);
}
if (DEBUG)
System.out.println("Starting useless check for abrupt stmt: " + abrupt);
// start condition is that ancestor is the stmt seq node
ASTNode ancestor = node;
while (ancestor != target) {
Object tempParent = finder.getParentOf(ancestor);
if (tempParent == null)
throw new DecompilationException("Parent found was null!!. Report to Developer");
ASTNode ancestorsParent = (ASTNode) tempParent;
if (DEBUG)
System.out.println("\tCurrent ancestorsParent has type" + ancestorsParent.getClass());
// ancestor should be last child of ancestorsParent
if (!checkChildLastInParent(ancestor, ancestorsParent)) {
if (DEBUG)
System.out.println("\t\tCurrent ancestorParent has more children after this ancestor");
// return from the method since this is the last stmt and we cant do anything
return;
}
// ancestorsParent should not be a loop of any kind OR A SWITCH
if (ancestorsParent instanceof ASTWhileNode || ancestorsParent instanceof ASTDoWhileNode || ancestorsParent instanceof ASTUnconditionalLoopNode || ancestorsParent instanceof ASTForLoopNode || ancestorsParent instanceof ASTSwitchNode) {
if (DEBUG)
System.out.println("\t\tAncestorsParent is a loop shouldnt remove abrupt stmt");
return;
}
ancestor = ancestorsParent;
}
if (DEBUG)
System.out.println("\tGot to target without returning means we can remove stmt");
remove = as;
}
if (remove != null) {
List<AugmentedStmt> stmts = node.getStatements();
stmts.remove(remove);
if (DEBUG)
System.out.println("\tRemoved abrupt stmt");
if (target != null) {
if (DEBUG)
System.out.println("Invoking findAndKill on the target");
UselessLabelFinder.v().findAndKill(target);
}
// TODO what if we just emptied a stmt seq block??
// not doing this for the moment
// set modified flag make finder null
G.v().ASTTransformations_modified = true;
finder = null;
}
}
Aggregations