// // Copyright (C) 2013 United States Government as represented by the // Administrator of the National Aeronautics and Space Administration // (NASA). All Rights Reserved. // // This software is distributed under the NASA Open Source Agreement // (NOSA), version 1.3. The NOSA has been approved by the Open Source // Initiative. See the file NOSA-1.3-JPF at the top of the distribution // directory tree for the complete NOSA document. // // THE SUBJECT SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY OF ANY // KIND, EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT // LIMITED TO, ANY WARRANTY THAT THE SUBJECT SOFTWARE WILL CONFORM TO // SPECIFICATIONS, ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR // A PARTICULAR PURPOSE, OR FREEDOM FROM INFRINGEMENT, ANY WARRANTY THAT // THE SUBJECT SOFTWARE WILL BE ERROR FREE, OR ANY WARRANTY THAT // DOCUMENTATION, IF PROVIDED, WILL CONFORM TO THE SUBJECT SOFTWARE. // package gov.nasa.jpf.listener; import gov.nasa.jpf.Config; import gov.nasa.jpf.JPF; import gov.nasa.jpf.jvm.bytecode.DIRECTCALLRETURN; import gov.nasa.jpf.jvm.bytecode.EXECUTENATIVE; import gov.nasa.jpf.jvm.bytecode.FieldInstruction; import gov.nasa.jpf.jvm.bytecode.InvokeInstruction; import gov.nasa.jpf.jvm.bytecode.LockInstruction; import gov.nasa.jpf.search.Search; import gov.nasa.jpf.vm.ChoiceGenerator; import gov.nasa.jpf.vm.Instruction; import gov.nasa.jpf.vm.MethodInfo; import gov.nasa.jpf.vm.MultiProcessChoiceGenerator; import gov.nasa.jpf.vm.ThreadInfo; import gov.nasa.jpf.vm.VM; /** * This is a Graphviz dot-file generator similar to SimpleDot. It is useful in * the case of Multiprocess applications. It distinguishes local choices from global * choices. * * @author Nastaran Shafiei <nastaran.shafiei@gmail.com> */ public class DistributedSimpleDot extends SimpleDot { static final String MP_START_NODE_ATTRS = "shape=octagon,fillcolor=green"; static final String MP_NODE_ATTRS = "shape=octagon,fillcolor=azure2"; protected String mpNodeAttrs; protected String mpStartNodeAttrs; protected Instruction insn; public DistributedSimpleDot (Config config, JPF jpf) { super(config, jpf); mpNodeAttrs = config.getString("dot.mp_node_attr", MP_NODE_ATTRS); startNodeAttrs = config.getString("dot.mp_start_node_attr", MP_START_NODE_ATTRS); } @Override public void instructionExecuted(VM vm, ThreadInfo currentThread, Instruction nextInstruction, Instruction executedInstruction) { insn = executedInstruction; } @Override public void stateAdvanced(Search search){ int id = search.getStateId(); long edgeId = ((long)lastId << 32) | id; String prcId = "P"+Integer.toString(search.getVM().getCurrentApplicationContext().getId()); if (id <0 || seenEdges.contains(edgeId)){ return; // skip the root state and property violations (reported separately) } String lastInst = getNextCG(); String choice = prcId+"."+getLastChoice(); if (search.isErrorState()) { String eid = "e" + search.getNumberOfErrors(); printTransition(getStateId(lastId), eid, choice, getError(search)); printErrorState(eid); lastErrorId = eid; } else if (search.isNewState()) { if (search.isEndState()) { printTransition(getStateId(lastId), getStateId(id), choice, lastInst); printEndState(getStateId(id)); } else { printTransition(getStateId(lastId), getStateId(id), choice, lastInst); printMultiProcessState(getStateId(id)); } } else { // already visited state printTransition(getStateId(lastId), getStateId(id), choice, lastInst); } seenEdges.add(edgeId); lastId = id; } protected String getNextCG(){ if (insn instanceof EXECUTENATIVE) { return getNativeExecCG((EXECUTENATIVE)insn); } else if (insn instanceof FieldInstruction) { // shared object field access return getFieldAccessCG((FieldInstruction)insn); } else if (insn instanceof LockInstruction){ // monitor_enter return getLockCG((LockInstruction)insn); } else if (insn instanceof InvokeInstruction){ // sync method invoke return getInvokeCG((InvokeInstruction)insn); } else if(insn instanceof DIRECTCALLRETURN && vm.getCurrentThread().getNextPC()==null) { return "return"; } return insn.getMnemonic(); // our generic fallback } protected void printMultiProcessState(String stateId){ if(vm.getNextChoiceGenerator() instanceof MultiProcessChoiceGenerator) { pw.print(stateId); pw.print(" ["); pw.print(mpNodeAttrs); pw.print(']'); pw.println(" // multiprc state"); } } protected String getNativeExecCG (EXECUTENATIVE insn){ MethodInfo mi = insn.getExecutedMethod(); String s = mi.getName(); if (s.equals("start")) { s = lastTi.getName() + ".start"; } else if (s.equals("wait")) { s = lastTi.getName() + ".wait"; } return s; } protected String getLastChoice() { ChoiceGenerator<?> cg = vm.getChoiceGenerator(); Object choice = cg.getNextChoice(); if (choice instanceof ThreadInfo){ return ((ThreadInfo) choice).getName(); } else { return choice.toString(); } } }