package cute.concolic.symbolicexecution; import cute.concolic.CuteException; import cute.concolic.input.InputMap; import cute.concolic.logging.BranchCoverageLog; import cute.concolic.pathconstraint.PathConstraint; import cute.concolic.pathconstraint.PointerConstraint; import cute.concolic.symbolicstate.*; import java.io.PrintWriter; import java.util.Stack; /** * Author: Koushik Sen <ksen@cs.uiuc.edu> */ public class ComputationStack { private State state; private PathConstraint path; private BranchHistory history; private BranchCoverageLog coverage; private InputMap input; private Stack stack; private Stack stackValue; private Stack stackSymbolic; ComputationStackElem[] biops; int ibiops; String op; private long addr; private boolean ready = false; private String fname; private Expression returnExpression; public ComputationStack(State state, PathConstraint path, BranchHistory history, BranchCoverageLog coverage,InputMap input) { this.state = state; this.path = path; this.history = history; this.coverage = coverage; this.input = input; stack = new Stack(); stackSymbolic = new Stack(); stackValue = new Stack(); biops = new ComputationStackElem[2]; for (int i = 0; i < biops.length; i++) { biops[i] = new ComputationStackElem(); } ibiops = -1; op = null; } public void push(long adr){ Expression e = state.getState(adr); stack.push(e); stackSymbolic.push(new Long(adr)); //((Expression)stack.peek()).printExpression(); } public void setReturn(long adr){ returnExpression = state.getState(adr); } public void setReturnExpression(Expression returnExpression) { this.returnExpression = returnExpression; } public void pushValue(Object val) { stackValue.push(val); if(stackSymbolic.size()==stackValue.size()){ int sz = stackSymbolic.size(); int szby2 = sz / 2; Object o; // reverse the stack for(int i=0;i<szby2;i++){ o = stackSymbolic.elementAt(i); stackSymbolic.setElementAt(stackSymbolic.elementAt(sz-i-1),i); stackSymbolic.setElementAt(o,sz-i-1); } boolean isSymbolic = false; for(int i=0;i<sz;i++){ Expression e = state.getState(((Long)stackSymbolic.elementAt(i)).longValue(), System.identityHashCode(stackValue.elementAt(i))); if(e!=null) { isSymbolic = true; } stackSymbolic.setElementAt(e,i); } if(isSymbolic){ FunctionExpression.handleFunction(fname,stackSymbolic,stackValue,this,input); } } } public void loadAddress(long adr){ addr = adr; ready = true; } public void loadValue(double val){ ibiops++; if(ready){ biops[ibiops].address = addr; } else { biops[ibiops].address = 0; } biops[ibiops].value = val; ready = false; } public void loadValueLong(long val){ ibiops++; if(ready){ biops[ibiops].address = addr; } else { biops[ibiops].address = 0; } biops[ibiops].valueLong = val; ready = false; } public void popAll(){ stack.clear(); stackSymbolic.clear(); stackValue.clear(); fname = null; returnExpression = null; ibiops = -1; op = null; } public void applyOp(String op){ this.op = op.trim(); } public void funBegin(String fname){ state.pushLocals(); this.fname = fname; } public void funEnd(){ state.popLocals(); } public void pop(long addr){ if(stack.isEmpty()){ state.setState(addr,null); } else { state.setState(addr,(Expression)stack.pop()); } //state.print(); } public void storeReturn(long addr){ state.setState(addr,returnExpression); } public void store(long addr){ if(ibiops==-1){ state.setState(addr,null); } else if(ibiops==0){ if(op==null){ state.setState(addr, state.getState(biops[0].address)); } else if(op.equals("-")){ state.setState(addr, ((ArithmeticExpression)state.getState(biops[0].address)).negate()); } else { throw new CuteException("Unknown unary op "+op); } } else if(ibiops==1){ ArithmeticExpression first = (ArithmeticExpression)state.getState(biops[0].address); ArithmeticExpression second = (ArithmeticExpression)state.getState(biops[1].address); if(first!=null && second!=null){ if(op.equals("+")){ state.setState(addr,first.add(second)); } else if(op.equals("-")){ state.setState(addr,first.subtract(second)); } else if(op.equals("cmpl")){ state.setState(addr,first.subtract(second)); } else if(op.equals("cmpg")){ state.setState(addr,second.subtract(first)); } else if(op.equals("cmp")){ state.setState(addr,first.subtract(second)); } else if(op.equals("*")){ second.printExpression(new PrintWriter(System.out)); state.setState(addr,second.multiply(biops[0].value)); } else { throw new CuteException("Unknown binary exception "+op); } } else if(first==null && second!=null){ if(op.equals("+")){ state.setState(addr,second.add(biops[0].value)); } else if(op.equals("-")){ state.setState(addr,second.subtractFrom(biops[0].value)); } else if(op.equals("cmpl")){ state.setState(addr,second.subtractFrom(biops[0].value)); } else if(op.equals("cmpg")){ state.setState(addr,second.subtract(biops[0].value)); } else if(op.equals("cmp")){ state.setState(addr,second.subtractFrom(biops[0].value)); } else if(op.equals("*")){ state.setState(addr,second.multiply(biops[0].value)); } else { throw new CuteException("Unknown binary exception "+op); } } else if(first!=null && second==null){ if(op.equals("+")){ state.setState(addr,first.add(biops[1].value)); } else if(op.equals("-")){ state.setState(addr,first.subtract(biops[1].value)); } else if(op.equals("cmpl")){ state.setState(addr,first.subtract(biops[1].value)); } else if(op.equals("cmpg")){ state.setState(addr,first.subtractFrom(biops[1].value)); } else if(op.equals("cmp")){ state.setState(addr,first.subtract(biops[1].value)); } else if(op.equals("*")){ state.setState(addr,first.multiply(biops[1].value)); } else { throw new CuteException("Unknown binary exception "+op); } } else { state.setState(addr,null); } } else { throw new CuteException("Unknown number of ops"); } ibiops = -1; op = null; } public void branch(boolean pos,String fname,int bid,int bCount){ boolean added = false; /*System.out.println("Branching "+bid); state.print(); System.out.println("pos = " + pos); */ boolean isOtherBranchTaken = false; if(fname!=null) isOtherBranchTaken = coverage.branchTaken(fname,bid,bCount,pos); if(ibiops==1 && (op.equals("==") || op.equals("!="))){ Expression first = (Expression)state.getState(biops[0].address); Expression second = (Expression)state.getState(biops[1].address); if(first!=null && second==null && first instanceof PointerExpression && biops[1].valueLong==0){ path.add(new PointerConstraint(0,((PointerExpression)first).getP(), (op.equals("==") && pos) || (op.equals("!=") && !pos)),isOtherBranchTaken); added = true; } if(first==null && second!=null && second instanceof PointerExpression && biops[0].valueLong==0){ path.add(new PointerConstraint(0,((PointerExpression)second).getP(), (op.equals("==") && pos) || (op.equals("!=") && !pos)),isOtherBranchTaken); added = true; } if(first!=null && second!=null && first instanceof PointerExpression && second instanceof PointerExpression){ path.add(new PointerConstraint(((PointerExpression)first).getP(),((PointerExpression)second).getP(), (op.equals("==") && pos) || (op.equals("!=") && !pos)),isOtherBranchTaken); added = true; } } if(ibiops==1){ Expression first = (Expression)state.getState(biops[0].address); Expression second = (Expression)state.getState(biops[1].address); ArithmeticExpression ret = null; if(first!=null && second==null && first instanceof ArithmeticExpression){ ret = ((ArithmeticExpression)first).subtract(biops[1].value); } if(first==null && second!=null && second instanceof ArithmeticExpression){ ret = ((ArithmeticExpression)second).subtractFrom(biops[0].value); } if(first!=null && second!=null && first instanceof ArithmeticExpression && second instanceof ArithmeticExpression){ ret = ((ArithmeticExpression)first).subtract((ArithmeticExpression)second); } if(ret!=null){ added = true; if(op.equals("<")){ if(pos) ret.setL(); else ret.setGE(); } if(op.equals(">")){ if(pos) ret.setG(); else ret.setLE(); } if(op.equals(">=")){ if(pos) ret.setGE(); else ret.setL(); } if(op.equals("<=")){ if(pos) ret.setLE(); else ret.setG(); } if(op.equals("==")){ if(pos) ret.setEQ(); else ret.setNE(); } if(op.equals("!=")){ if(pos) ret.setNE(); else ret.setEQ(); } path.add(ret,isOtherBranchTaken); } } if(!added){ path.add(null,isOtherBranchTaken); } op=null; ibiops = -1; history.compareAndSet(pos,path.size()); } }