AbstractStaticInvokeExpr(SootMethodRef methodRef, List args) { super.methodRef = methodRef; super.argBoxes = new ArrayList(); for (int i = 0; i < args.size(); i++) this.argBoxes.add(Jimple.v().newImmediateBox((Value) args.get(i))); }
private boolean removeBeginNode() { List heads = getHeads(); if (heads.size() != 1) { // System.out.println("heads: "+heads); // System.out.println("Error: the size of heads is not equal to 1!"); return false; // System.exit(1); } else { JPegStmt head = (JPegStmt) heads.get(0); // System.out.println("test head: "+head); if (!head.getName().equals("begin")) { System.err.println("Error: the head is not begin node!"); System.exit(1); } // remove begin node from heads list heads.remove(0); // set the preds list of the succs of head to a new list and put succs of head into heads Iterator succOfHeadIt = getSuccsOf(head).iterator(); while (succOfHeadIt.hasNext()) { JPegStmt succOfHead = (JPegStmt) succOfHeadIt.next(); unitToPreds.put(succOfHead, new ArrayList()); // put succs of head into heads heads.add(succOfHead); } // remove begin node from inlinee Peg if (!mainPegChain.remove(head)) { System.err.println("fail to remove begin node in from mainPegChain!"); System.exit(1); } if (!allNodes.contains(head)) { System.err.println("fail to find begin node in FlowSet allNodes!"); System.exit(1); } else { allNodes.remove(head); } // remove begin node from unitToSuccs if (unitToSuccs.containsKey(head)) { unitToSuccs.remove(head); } } return true; }
private boolean checkStmt(ASTNode onlyNode, ASTIfElseNode node) { if (!(onlyNode instanceof ASTStatementSequenceNode)) { // only interested in StmtSeq nodes return false; } ASTStatementSequenceNode stmtNode = (ASTStatementSequenceNode) onlyNode; List<Object> statements = stmtNode.getStatements(); if (statements.size() != 1) { // need one stmt only return false; } AugmentedStmt as = (AugmentedStmt) statements.get(0); Stmt stmt = as.get_Stmt(); if (!(stmt instanceof DAbruptStmt)) { // interested in abrupt stmts only return false; } DAbruptStmt abStmt = (DAbruptStmt) stmt; if (!(abStmt.is_Break() || abStmt.is_Continue())) { // interested in breaks and continues only return false; } // make sure that the break is not that of the if // unliekly but good to check SETNodeLabel ifLabel = ((ASTLabeledNode) node).get_Label(); if (ifLabel != null) { if (ifLabel.toString() != null) { if (abStmt.is_Break()) { String breakLabel = abStmt.getLabel().toString(); if (breakLabel != null) { if (breakLabel.compareTo(ifLabel.toString()) == 0) { // is a break of this label return false; } } } } } return true; }
public boolean isIfElseBreakingPossiblePatternOne(ASTIfElseNode node) { List<Object> ifBody = node.getIfBody(); if (ifBody.size() != 1) { // we are only interested if size is one return false; } ASTNode onlyNode = (ASTNode) ifBody.get(0); boolean check = checkStmt(onlyNode, node); if (!check) { return false; } // breaking is possible // break and store newIfNode = new ASTIfNode(((ASTLabeledNode) node).get_Label(), node.get_Condition(), ifBody); remainingBody = node.getElseBody(); return true; }
/** * Create a method conveniently. The method is added to the class "TestClass". Parameters can be * given as an (positional) array of local variables (the "identity statements", required by Soot * to map parameters to local variables, are inserted automatically) */ public SootMethod makeMethod( int modifier, String name, List<Local> params, soot.Type retType, List<Unit> bodyStmts) { SootMethod m = new SootMethod( name, params.stream().map(Local::getType).collect(toList()), retType, modifier); this.testClass.addMethod(m); Body body = Jimple.v().newBody(m); m.setActiveBody(body); // set the statements for the body.. first the identity statements, then the bodyStmts if (!m.isStatic()) { body.getLocals().add(localThis); body.getUnits() .add(Jimple.v().newIdentityStmt(localThis, Jimple.v().newThisRef(testClass.getType()))); } IntStream.range(0, params.size()) .forEach( pos -> { Local l = params.get(pos); ParameterRef pr = Jimple.v().newParameterRef(l.getType(), pos); body.getUnits().add(Jimple.v().newIdentityStmt(l, pr)); }); body.getUnits().addAll(bodyStmts); // set the locals for the body Set<Local> locals = Stream.concat( params.stream(), body.getUseAndDefBoxes() .stream() .filter(b -> b.getValue() instanceof Local) .map(b -> (Local) b.getValue())) .collect(toSet()); locals.removeAll(body.getLocals()); body.getLocals().addAll(locals); return m; }
public boolean isIfElseBreakingPossiblePatternTwo(ASTIfElseNode node) { List<Object> elseBody = node.getElseBody(); if (elseBody.size() != 1) { // we are only interested if size is one return false; } ASTNode onlyNode = (ASTNode) elseBody.get(0); boolean check = checkStmt(onlyNode, node); if (!check) { return false; } // breaking is possible ASTCondition cond = node.get_Condition(); // flip cond.flip(); newIfNode = new ASTIfNode(((ASTLabeledNode) node).get_Label(), cond, elseBody); remainingBody = node.getIfBody(); return true; }
public void outAFullMethodBody(AFullMethodBody node) { Object catchClause = null; JimpleBody jBody = Jimple.v().newBody(); if (node.getCatchClause() != null) { int size = node.getCatchClause().size(); for (int i = 0; i < size; i++) jBody.getTraps().addFirst((Trap) mProductions.removeLast()); } if (node.getStatement() != null) { int size = node.getStatement().size(); Unit lastStmt = null; for (int i = 0; i < size; i++) { Object o = mProductions.removeLast(); if (o instanceof Unit) { jBody.getUnits().addFirst(o); lastStmt = (Unit) o; } else if (o instanceof String) { if (lastStmt == null) throw new RuntimeException("impossible"); mLabelToStmtMap.put(o, lastStmt); } else throw new RuntimeException("impossible"); } } if (node.getDeclaration() != null) { int size = node.getDeclaration().size(); for (int i = 0; i < size; i++) { List localList = (List) mProductions.removeLast(); int listSize = localList.size(); for (int j = listSize - 1; j >= 0; j--) jBody.getLocals().addFirst(localList.get(j)); } } Iterator it = mLabelToPatchList.keySet().iterator(); while (it.hasNext()) { String label = (String) it.next(); Unit target = (Unit) mLabelToStmtMap.get(label); Iterator patchIt = ((List) mLabelToPatchList.get(label)).iterator(); while (patchIt.hasNext()) { UnitBox box = (UnitBox) patchIt.next(); box.setUnit(target); } } /* Iterator it = mLabelToStmtMap.keySet().iterator(); while(it.hasNext()) { String label = (String) it.next(); Unit target = (Unit) mLabelToStmtMap.get(label); List l = (List) mLabelToPatchList.get(label); if(l != null) { Iterator patchIt = l.iterator(); while(patchIt.hasNext()) { UnitBox box = (UnitBox) patchIt.next(); box.setUnit(target); } } } */ mProductions.addLast(jBody); }
public JInterfaceInvokeExpr(Value base, SootMethodRef methodRef, List args) { super(Jimple.v().newLocalBox(base), methodRef, new ArrayList(args.size())); for (int i = 0; i < args.size(); i++) this.argBoxes.add(Jimple.v().newImmediateBox((Value) args.get(i))); }
// This method adds the monitorenter/exit statements into whichever pegChain contains the // corresponding node statement protected void addMonitorStmt() { // System.out.println("====entering addMonitorStmt"); if (synch.size() > 0) { // System.out.println("synch: "+synch); Iterator<List> it = synch.iterator(); while (it.hasNext()) { List list = it.next(); JPegStmt node = (JPegStmt) list.get(0); JPegStmt enter = (JPegStmt) list.get(1); JPegStmt exit = (JPegStmt) list.get(2); // System.out.println("monitor node: "+node); // System.out.println("monitor enter: "+enter); // System.out.println("monitor exit: "+exit); // add for test // System.out.println("allNodes contains node: "+allNodes.contains(node)); // end add for test { if (!mainPegChain.contains(node)) { boolean find = false; // System.out.println("main chain does not contain node"); Set maps = startToThread.entrySet(); // System.out.println("size of startToThread: "+startToThread.size()); for (Iterator iter = maps.iterator(); iter.hasNext(); ) { Map.Entry entry = (Map.Entry) iter.next(); Object startNode = entry.getKey(); Iterator runIt = ((List) entry.getValue()).iterator(); while (runIt.hasNext()) { Chain chain = (Chain) runIt.next(); // testPegChain(chain); if (chain.contains(node)) { find = true; // System.out.println("---find it---"); chain.add(enter); chain.add(exit); break; } } } if (find == false) { System.err.println("fail to find stmt: " + node + " in chains!"); System.exit(1); } // this.toString(); } else { mainPegChain.add(enter); mainPegChain.add(exit); } } allNodes.add(enter); allNodes.add(exit); insertBefore(node, enter); insertAfter(node, exit); } } // add for test /* { // System.out.println("===main peg chain==="); //testPegChain(mainPegChain); //System.out.println("===end main peg chain==="); Set maps = startToThread.entrySet(); for(Iterator iter=maps.iterator(); iter.hasNext();){ Map.Entry entry = (Map.Entry)iter.next(); Object startNode = entry.getKey(); Iterator runIt = ((List)entry.getValue()).iterator(); while (runIt.hasNext()){ Chain chain=(Chain)runIt.next(); testPegChain(chain); } } } */ // System.out.println(this.toString()); // end add for test }
private static boolean internalAggregate( StmtBody body, Map<ValueBox, Zone> boxToZone, boolean onlyStackVars) { LocalUses localUses; LocalDefs localDefs; ExceptionalUnitGraph graph; boolean hadAggregation = false; Chain<Unit> units = body.getUnits(); graph = new ExceptionalUnitGraph(body); localDefs = new SmartLocalDefs(graph, new SimpleLiveLocals(graph)); localUses = new SimpleLocalUses(graph, localDefs); List<Unit> unitList = new PseudoTopologicalOrderer<Unit>().newList(graph, false); for (Unit u : unitList) { if (!(u instanceof AssignStmt)) continue; AssignStmt s = (AssignStmt) u; Value lhs = s.getLeftOp(); if (!(lhs instanceof Local)) continue; Local lhsLocal = (Local) lhs; if (onlyStackVars && !lhsLocal.getName().startsWith("$")) continue; List<UnitValueBoxPair> lu = localUses.getUsesOf(s); if (lu.size() != 1) continue; UnitValueBoxPair usepair = lu.get(0); Unit use = usepair.unit; ValueBox useBox = usepair.valueBox; List<Unit> ld = localDefs.getDefsOfAt(lhsLocal, use); if (ld.size() != 1) continue; // Check to make sure aggregation pair in the same zone if (boxToZone.get(s.getRightOpBox()) != boxToZone.get(usepair.valueBox)) { continue; } /* we need to check the path between def and use */ /* to see if there are any intervening re-defs of RHS */ /* in fact, we should check that this path is unique. */ /* if the RHS uses only locals, then we know what to do; if RHS has a method invocation f(a, b, c) or field access, we must ban field writes, other method calls and (as usual) writes to a, b, c. */ boolean cantAggr = false; boolean propagatingInvokeExpr = false; boolean propagatingFieldRef = false; boolean propagatingArrayRef = false; ArrayList<FieldRef> fieldRefList = new ArrayList<FieldRef>(); LinkedList<Value> localsUsed = new LinkedList<Value>(); for (ValueBox vb : s.getUseBoxes()) { Value v = vb.getValue(); if (v instanceof Local) localsUsed.add(v); else if (v instanceof InvokeExpr) propagatingInvokeExpr = true; else if (v instanceof ArrayRef) propagatingArrayRef = true; else if (v instanceof FieldRef) { propagatingFieldRef = true; fieldRefList.add((FieldRef) v); } } // look for a path from s to use in graph. // only look in an extended basic block, though. List<Unit> path = graph.getExtendedBasicBlockPathBetween(s, use); if (path == null) continue; Iterator<Unit> pathIt = path.iterator(); // skip s. if (pathIt.hasNext()) pathIt.next(); while (pathIt.hasNext() && !cantAggr) { Stmt between = (Stmt) (pathIt.next()); if (between != use) { // Check for killing definitions for (ValueBox vb : between.getDefBoxes()) { Value v = vb.getValue(); if (localsUsed.contains(v)) { cantAggr = true; break; } if (propagatingInvokeExpr || propagatingFieldRef || propagatingArrayRef) { if (v instanceof FieldRef) { if (propagatingInvokeExpr) { cantAggr = true; break; } else if (propagatingFieldRef) { // Can't aggregate a field access if passing a definition of a field // with the same name, because they might be aliased for (FieldRef fieldRef : fieldRefList) { if (((FieldRef) v).getField() == fieldRef.getField()) { cantAggr = true; break; } } } } else if (v instanceof ArrayRef) { if (propagatingInvokeExpr) { // Cannot aggregate an invoke expr past an array write cantAggr = true; break; } else if (propagatingArrayRef) { // cannot aggregate an array read past a write // this is somewhat conservative // (if types differ they may not be aliased) cantAggr = true; break; } } } } // Make sure not propagating past a {enter,exit}Monitor if (propagatingInvokeExpr && between instanceof MonitorStmt) cantAggr = true; } // Check for intervening side effects due to method calls if (propagatingInvokeExpr || propagatingFieldRef || propagatingArrayRef) { for (final ValueBox box : between.getUseBoxes()) { if (between == use && box == useBox) { // Reached use point, stop looking for // side effects break; } Value v = box.getValue(); if (v instanceof InvokeExpr || (propagatingInvokeExpr && (v instanceof FieldRef || v instanceof ArrayRef))) { cantAggr = true; break; } } } } // we give up: can't aggregate. if (cantAggr) { continue; } /* assuming that the d-u chains are correct, */ /* we need not check the actual contents of ld */ Value aggregatee = s.getRightOp(); if (usepair.valueBox.canContainValue(aggregatee)) { boolean wasSimpleCopy = isSimpleCopy(usepair.unit); usepair.valueBox.setValue(aggregatee); units.remove(s); hadAggregation = true; // clean up the tags. If s was not a simple copy, the new statement should get // the tags of s. // OK, this fix was wrong. The condition should not be // "If s was not a simple copy", but rather "If usepair.unit // was a simple copy". This way, when there's a load of a constant // followed by an invoke, the invoke gets the tags. if (wasSimpleCopy) { // usepair.unit.removeAllTags(); usepair.unit.addAllTagsOf(s); } } else { /* if(Options.v().verbose()) { G.v().out.println("[debug] failed aggregation"); G.v().out.println("[debug] tried to put "+aggregatee+ " into "+usepair.stmt + ": in particular, "+usepair.valueBox); G.v().out.println("[debug] aggregatee instanceof Expr: " +(aggregatee instanceof Expr)); }*/ } } return hadAggregation; }
/* We know this method is called when there is a loop node which has a body consisting entirely of one ASTIfElseNode */ public static List getNewNode(ASTNode loopNode, ASTIfElseNode ifElseNode) { // make sure that elsebody has only a stmtseq node List elseBody = ((ASTIfElseNode) ifElseNode).getElseBody(); if (elseBody.size() != 1) { // this is more than one we need one stmtSeq Node return null; } ASTNode tempNode = (ASTNode) elseBody.get(0); if (!(tempNode instanceof ASTStatementSequenceNode)) { // not a stmtSeq return null; } List statements = ((ASTStatementSequenceNode) tempNode).getStatements(); Iterator stmtIt = statements.iterator(); while (stmtIt.hasNext()) { AugmentedStmt as = (AugmentedStmt) stmtIt.next(); Stmt stmt = as.get_Stmt(); if (stmt instanceof DAbruptStmt) { // this is a abrupt stmt DAbruptStmt abStmt = (DAbruptStmt) stmt; if (!(abStmt.is_Break())) { // we need a break return null; } else { if (stmtIt.hasNext()) { // a break should be the last stmt return null; } SETNodeLabel label = abStmt.getLabel(); String labelBroken = label.toString(); String loopLabel = ((ASTLabeledNode) loopNode).get_Label().toString(); if (labelBroken != null && loopLabel != null) { // stmt breaks some label if (labelBroken.compareTo(loopLabel) == 0) { // we have found a break breaking this label // make sure that if the orignal was an ASTWhileNode then there was // ONLY a break statement if (loopNode instanceof ASTWhileNode) { if (statements.size() != 1) { // more than 1 statement return null; } } // pattern matched ASTWhileNode newWhileNode = makeWhileNode(ifElseNode, loopNode); if (newWhileNode == null) { return null; } List toReturn = new ArrayList(); toReturn.add(newWhileNode); // Add the statementSequenceNode AFTER the whileNode except for the laststmt if (statements.size() != 1) { // size 1 means that the only stmt is a break stmt Iterator tempIt = statements.iterator(); List newStmts = new ArrayList(); while (tempIt.hasNext()) { Object tempStmt = tempIt.next(); if (tempIt.hasNext()) { newStmts.add(tempStmt); } } toReturn.add(new ASTStatementSequenceNode(newStmts)); } return toReturn; } // labels matched } // non null labels } // end of break stmt } // stmt is an abrupt stmt else if (stmt instanceof ReturnStmt || stmt instanceof ReturnVoidStmt) { if (!(loopNode instanceof ASTUnconditionalLoopNode)) { // this pattern is only possible for while(true) return null; } if (stmtIt.hasNext()) { // returns should come in the end return null; } // pattern matched ASTWhileNode newWhileNode = makeWhileNode(ifElseNode, loopNode); if (newWhileNode == null) { return null; } List toReturn = new ArrayList(); toReturn.add(newWhileNode); // Add the statementSequenceNode AFTER the whileNode Iterator tempIt = statements.iterator(); List newStmts = new ArrayList(); while (tempIt.hasNext()) { Object tempStmt = tempIt.next(); newStmts.add(tempStmt); } toReturn.add(new ASTStatementSequenceNode(newStmts)); return toReturn; } // if stmt was a return stmt } // going through the stmts return null; } // end of method