use of soot.dava.internal.AST.ASTStatementSequenceNode 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.ASTStatementSequenceNode in project soot by Sable.
the class MethodCallFinder method createChangedBodyPart.
/*
* Given an invoke stmt this method finds the parent of this stmt which
* should always be a StatementSequenceNode Then the sequence is broken into
* three parts. The first part contains stmts till above the invoke stmt.
* The second part contains the body argument which is the body of the
* inlined method and the third part are the stmts below the invoke stmt
*/
public List<ASTStatementSequenceNode> createChangedBodyPart(InvokeStmt s, List body, ASTParentNodeFinder finder) {
// get parent node of invoke stmt
Object parent = finder.getParentOf(s);
if (parent == null) {
throw new RuntimeException("MethodCall FInder: parent of invoke stmt not found");
}
ASTNode parentNode = (ASTNode) parent;
if (!(parentNode instanceof ASTStatementSequenceNode)) {
throw new RuntimeException("MethodCall FInder: parent node not a stmt seq node");
}
ASTStatementSequenceNode orignal = (ASTStatementSequenceNode) parentNode;
// copying the stmts till above the inoke stmt into one stmt sequence
// node
List<AugmentedStmt> newInitialNode = new ArrayList<AugmentedStmt>();
Iterator<AugmentedStmt> it = orignal.getStatements().iterator();
while (it.hasNext()) {
AugmentedStmt as = it.next();
Stmt tempStmt = as.get_Stmt();
if (tempStmt != s) {
newInitialNode.add(as);
} else {
// stmt we break
break;
}
}
// copy remaining stmts into the AFTER stmt sequence node
List<AugmentedStmt> newSecondNode = new ArrayList<AugmentedStmt>();
while (it.hasNext()) {
newSecondNode.add(it.next());
}
List<ASTStatementSequenceNode> toReturn = new ArrayList<ASTStatementSequenceNode>();
if (newInitialNode.size() != 0)
toReturn.add(new ASTStatementSequenceNode(newInitialNode));
// add inline methods body
toReturn.addAll(body);
if (newSecondNode.size() != 0)
toReturn.add(new ASTStatementSequenceNode(newSecondNode));
return toReturn;
}
use of soot.dava.internal.AST.ASTStatementSequenceNode in project soot by Sable.
the class EliminateConditions method change.
public boolean change(Boolean returned, ASTNode temp) {
if (bodyContainingNode != null && returned != null && temp != null) {
int index = bodyContainingNode.indexOf(temp);
if (DEBUG)
System.out.println("in change");
if (temp instanceof ASTIfNode) {
bodyContainingNode.remove(temp);
if (returned.booleanValue()) {
// if statement and value was true put the body of if into
// the code
// if its a labeled stmt we need a labeled block instead
// notice that its okkay to put a labeled block since other
// transformations might remove it
String label = ((ASTLabeledNode) temp).get_Label().toString();
if (label != null) {
ASTLabeledBlockNode labeledNode = new ASTLabeledBlockNode(((ASTLabeledNode) temp).get_Label(), (List<Object>) temp.get_SubBodies().get(0));
bodyContainingNode.add(index, labeledNode);
} else {
bodyContainingNode.addAll(index, (List) temp.get_SubBodies().get(0));
}
}
if (DEBUG)
System.out.println("Removed if" + temp);
return true;
} else if (temp instanceof ASTIfElseNode) {
bodyContainingNode.remove(temp);
if (returned.booleanValue()) {
// true so the if branch's body has to be added
// if its a labeled stmt we need a labeled block instead
// notice that its okkay to put a labeled block since other
// transformations might remove it
String label = ((ASTLabeledNode) temp).get_Label().toString();
if (label != null) {
ASTLabeledBlockNode labeledNode = new ASTLabeledBlockNode(((ASTLabeledNode) temp).get_Label(), (List<Object>) temp.get_SubBodies().get(0));
bodyContainingNode.add(index, labeledNode);
} else {
bodyContainingNode.addAll(index, (List) temp.get_SubBodies().get(0));
}
} else {
// if its a labeled stmt we need a labeled block instead
// notice that its okkay to put a labeled block since other
// transformations might remove it
String label = ((ASTLabeledNode) temp).get_Label().toString();
if (label != null) {
ASTLabeledBlockNode labeledNode = new ASTLabeledBlockNode(((ASTLabeledNode) temp).get_Label(), (List<Object>) temp.get_SubBodies().get(1));
bodyContainingNode.add(index, labeledNode);
} else {
bodyContainingNode.addAll(index, (List) temp.get_SubBodies().get(1));
}
}
return true;
} else if (temp instanceof ASTWhileNode && returned.booleanValue() == false) {
// notice we only remove if ASTWhileNode has false condition
bodyContainingNode.remove(temp);
return true;
} else if (temp instanceof ASTDoWhileNode && returned.booleanValue() == false) {
// System.out.println("in try dowhile false");
// remove the loop copy the body out since it gets executed once
bodyContainingNode.remove(temp);
bodyContainingNode.addAll(index, (List) temp.get_SubBodies().get(0));
return true;
} else if (temp instanceof ASTForLoopNode && returned.booleanValue() == false) {
bodyContainingNode.remove(temp);
ASTStatementSequenceNode newNode = new ASTStatementSequenceNode(((ASTForLoopNode) temp).getInit());
bodyContainingNode.add(index, newNode);
return true;
}
}
return false;
}
use of soot.dava.internal.AST.ASTStatementSequenceNode 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.ASTStatementSequenceNode in project soot by Sable.
the class SuperFirstStmtHandler method finalizePreInitMethod.
// method should return false if the PreInit body(ASTBody that is) is empty
// meaning there is no need to create it all
private boolean finalizePreInitMethod() {
// set davaBody...totally redundant but have to do as this is checked by
// toString of ASTMethodNode
newASTPreInitMethod.setDavaBody(newPreInitDavaBody);
// newPreInitDavaBody is the active body
newPreInitDavaBody.getUnits().clear();
newPreInitDavaBody.getUnits().addLast(newASTPreInitMethod);
// check whether there is something in side the ASTBody
// if its empty (maybe there were only declarations and that got removed
// then no point in creating the preInit method
List<Object> subBodies = newASTPreInitMethod.get_SubBodies();
if (subBodies.size() != 1)
return false;
List body = (List) subBodies.get(0);
// body is NOT allowed to contain one declaration node with whatever in
// it
// after that it is NOT allowed all ASTStatement nodes with empty bodies
Iterator it = body.iterator();
// indicating that method is empty
boolean empty = true;
while (it.hasNext()) {
ASTNode tempNode = (ASTNode) it.next();
if (!(tempNode instanceof ASTStatementSequenceNode)) {
// found some node other than stmtseq...body not empty return
// true
empty = false;
break;
}
List<AugmentedStmt> stmts = ((ASTStatementSequenceNode) tempNode).getStatements();
// all declaration stmts are allowed
for (AugmentedStmt as : stmts) {
Stmt s = as.get_Stmt();
if (!(s instanceof DVariableDeclarationStmt)) {
empty = false;
break;
}
}
if (!empty)
break;
}
if (empty) {
// should not be creating the method
return false;
}
// about to return true enter all DavaSuperHandler stmts to make it part
// of the preinit method
createDavaStoreStmts();
return true;
}
Aggregations