package fr.inria.diversify.transformation.query; import fr.inria.diversify.diversification.InputProgram; import fr.inria.diversify.coverage.ICoverageReport; import fr.inria.diversify.transformation.Transformation; import fr.inria.diversify.transformation.bytecode.BytecodeAdd; import fr.inria.diversify.transformation.bytecode.BytecodeDelete; import fr.inria.diversify.transformation.bytecode.BytecodeReplace; import javassist.CtClass; import javassist.CtMethod; import javassist.NotFoundException; import javassist.bytecode.BadBytecode; import javassist.bytecode.CodeAttribute; import javassist.bytecode.CodeIterator; import javassist.bytecode.MethodInfo; import java.util.ArrayList; import java.util.Random; import java.util.List; /** * User: Simon * Date: 07/11/13 * Time: 13:07 */ public class ByteCodeTransformationQuery extends TransformationQuery { protected List<CtMethod> methods; protected ICoverageReport coverageReport; public ByteCodeTransformationQuery(InputProgram inputProgram) throws NotFoundException { super(inputProgram); this.coverageReport = inputProgram.getCoverageReport(); methods = inputProgram.getJavassistMethods(); } @Override public Transformation query() { try { Random r = new Random(); int i = r.nextInt(3); if (i == 0) { return replace(); } if (i == 1) { return add(); } if (i == 2) { return delete(); } return null; } catch (Exception e) { throw new RuntimeException(e); } } public BytecodeDelete delete() throws Exception { CtMethod method = randomConcreteMethod(); int opCodeIndex = randomOpCode(method); while(coverageReport.opCodeCoverage(method,opCodeIndex) == 0x00) { method = randomConcreteMethod(); opCodeIndex = randomOpCode(method); } return new BytecodeDelete(method,opCodeIndex, methods); } public BytecodeAdd add() throws Exception { CtMethod method = randomConcreteMethod(); int opCodeIndex = randomOpCode(method); while(coverageReport.opCodeCoverage(method,opCodeIndex) == 0x00) { method = randomConcreteMethod(); opCodeIndex = randomOpCode(method); } return new BytecodeAdd(method,opCodeIndex, randomOpCodeInClass(method.getDeclaringClass()), methods); } public BytecodeReplace replace() throws Exception { CtMethod method = randomConcreteMethod(); int opCodeIndex = randomOpCode(method); while(coverageReport.opCodeCoverage(method,opCodeIndex) == 0x00) { method = randomConcreteMethod(); opCodeIndex = randomOpCode(method); } return new BytecodeReplace(method,opCodeIndex, randomOpCodeInClass(method.getDeclaringClass()), methods); } protected CtMethod randomConcreteMethod() { Random r = new Random(); CtMethod mth = methods.get(r.nextInt(methods.size())); while (mth.getDeclaringClass().isFrozen()) mth = methods.get(r.nextInt(methods.size())); return mth; } protected int randomOpCode(CtMethod method) throws BadBytecode { MethodInfo minfo = method.getMethodInfo(); CodeAttribute ca = minfo.getCodeAttribute(); List<Integer> opCodeIndexList = opCodeIndexList(ca); Random r = new Random(); return r.nextInt(opCodeIndexList.size()); } protected byte[] randomOpCodeInClass(CtClass cl) throws BadBytecode { Random r = new Random(); CtMethod[] methods = cl.getDeclaredMethods(); CtMethod method = methods[r.nextInt(methods.length)]; while (method.isEmpty()) method = methods[r.nextInt(methods.length)]; MethodInfo minfo = method.getMethodInfo(); CodeAttribute ca = minfo.getCodeAttribute(); List<Integer> opCodeIndexList = opCodeIndexList(ca); int opCodeIndex = r.nextInt(opCodeIndexList.size()); return byteCodeAt(ca,opCodeIndexList,opCodeIndex); } protected byte[] byteCodeAt(CodeAttribute ca, List<Integer> opCodeIndexList, int index) { int borne; int byteCodeIndex = opCodeIndexList.get(index); if(index + 1 == opCodeIndexList.size()) borne = ca.getCodeLength(); else borne = opCodeIndexList.get(index+1); CodeIterator iter = ca.iterator(); byte[] bytecode = new byte[borne - byteCodeIndex]; for(int i = 0; i < borne - byteCodeIndex; i++) { bytecode[i] = (byte) iter.byteAt(i); } return bytecode; } protected List<Integer> opCodeIndexList(CodeAttribute ca) throws BadBytecode { List<Integer> list = new ArrayList<Integer>(); CodeIterator i = ca.iterator(); while (i.hasNext()) { list.add(i.next()); } return list; } }