// // Copyright (C) 2006 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.vm; import java.io.FileInputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.util.BitSet; import java.util.List; import cmu.conditional.Conditional; import cmu.conditional.One; import de.fosd.typechef.featureexpr.FeatureExpr; import de.fosd.typechef.featureexpr.FeatureExprFactory; import gov.nasa.jpf.Config; import gov.nasa.jpf.JPF; import gov.nasa.jpf.JPFException; import gov.nasa.jpf.annotation.MJI; import gov.nasa.jpf.util.IntTable; import gov.nasa.jpf.util.JPFLogger; import gov.nasa.jpf.util.ObjectConverter; import gov.nasa.jpf.util.ObjectList; import gov.nasa.jpf.util.RunListener; import gov.nasa.jpf.util.RunRegistry; import gov.nasa.jpf.util.json.CGCall; import gov.nasa.jpf.util.json.JSONLexer; import gov.nasa.jpf.util.json.JSONObject; import gov.nasa.jpf.util.json.JSONParser; import gov.nasa.jpf.vm.choice.DoubleChoiceFromList; import gov.nasa.jpf.vm.choice.FloatChoiceFromList; import gov.nasa.jpf.vm.choice.IntChoiceFromSet; import gov.nasa.jpf.vm.choice.IntIntervalGenerator; import gov.nasa.jpf.vm.choice.LongChoiceFromList; /** * native peer class for programmatic JPF interface (that can be used inside * of apps to verify - if you are aware of the danger that comes with it) * * this peer is a bit different in that it only uses static fields and methods because * its use is supposed to be JPF global (without classloader namespaces) */ @SuppressWarnings({"deprecation", "unchecked"}) public class JPF_gov_nasa_jpf_vm_Verify extends NativePeer { static final int MAX_COUNTERS = 10; static boolean isInitialized; // those are used to store search global int values (e.g. from TestJPF derived classes) static int[] counter; static IntTable<String> map; static boolean supportIgnorePath; static boolean breakSingleChoice; static boolean enableAtomic; static Config config; // we need to keep this around for CG creation // our const ChoiceGenerator ctor argtypes static Class<?>[] cgArgTypes = { Config.class, String.class }; // this is our cache for ChoiceGenerator ctor parameters static Object[] cgArgs = { null, null }; static BitSet[] bitSets; static int nextBitSet; public static boolean init (Config conf) { if (!isInitialized){ supportIgnorePath = conf.getBoolean("vm.verify.ignore_path"); breakSingleChoice = conf.getBoolean("cg.break_single_choice"); enableAtomic = conf.getBoolean("cg.enable_atomic", true); counter = null; map = null; config = conf; Verify.setPeerClass( JPF_gov_nasa_jpf_vm_Verify.class); RunRegistry.getDefaultRegistry().addListener( new RunListener() { public void reset (RunRegistry reg){ isInitialized = false; } }); } return true; } private static boolean reset = false; @MJI public static void resetInstructionCounter____V(MJIEnv env, int clsObjRef, FeatureExpr ctx) { System.out.println("resetInstructionCounter"); if (reset) { System.out.println("counter already reset"); } else { env.getVM().resetInstructionCounter(); reset = true; } } public static final int NO_VALUE = -1; @MJI public static int getValue__Ljava_lang_String_2__I (MJIEnv env, int clsObjRef, int keyRef, FeatureExpr ctx) { if (map == null) { return NO_VALUE; } else { String key = env.getStringObject(ctx, keyRef); IntTable.Entry<String> e = map.get(key); if (e != null) { return e.val; } else { return NO_VALUE; } } } @MJI public static void putValue__Ljava_lang_String_2I__V (MJIEnv env, int clsObjRef, int keyRef, int val, FeatureExpr ctx) { if (map == null) { map = new IntTable<String>(); } String key = env.getStringObject(ctx, keyRef); map.put(key, val); } @MJI public static int getCounter__I__I (MJIEnv env, int clsObjRef, int counterId, FeatureExpr ctx) { if ((counter == null) || (counterId < 0) || (counterId >= counter.length)) { return 0; } return counter[counterId]; } private static void ensureCounterCapacity (int counterId){ if (counter == null) { counter = new int[(counterId >= MAX_COUNTERS) ? counterId+1 : MAX_COUNTERS]; } else if (counterId >= counter.length) { int[] newCounter = new int[counterId+1]; System.arraycopy(counter, 0, newCounter, 0, counter.length); counter = newCounter; } } @MJI public static void resetCounter__I__V (MJIEnv env, int clsObjRef, int counterId, FeatureExpr ctx) { if ((counter == null) || (counterId < 0) || (counterId >= counter.length)) { return; } counter[counterId] = 0; } @MJI public static void setCounter__II__V (MJIEnv env, int clsObjRef, int counterId, int val, FeatureExpr ctx) { if (counterId < 0){ return; } ensureCounterCapacity(counterId); counter[counterId] = val; } @MJI public static int incrementCounter__I__I (MJIEnv env, int clsObjRef, int counterId, FeatureExpr ctx) { if (counterId < 0) { return 0; } ensureCounterCapacity(counterId); return ++counter[counterId]; } private static void checkBitSetId(int id) { if (bitSets == null) { bitSets = new BitSet[id + 1]; } else if (id >= bitSets.length) { BitSet[] newBitSets = new BitSet[id + 1]; System.arraycopy(bitSets, 0, newBitSets, 0, bitSets.length); bitSets = newBitSets; } if (bitSets[id] == null) { bitSets[id] = new BitSet(); } } @MJI public static void setBitInBitSet__IIZ__V(MJIEnv env, int clsObjRef, int id, int bitNum, boolean value, FeatureExpr ctx) { checkBitSetId(id); bitSets[id].set(bitNum, value); } @MJI public static boolean getBitInBitSet__II__Z(MJIEnv env, int clsObjRef, int id, int bitNum, FeatureExpr ctx) { checkBitSetId(id); return bitSets[id].get(bitNum); } @MJI public static long currentTimeMillis____J (MJIEnv env, int clsObjRef, FeatureExpr ctx) { return System.currentTimeMillis(); } @MJI public static String getType (int objRef, MJIEnv env, FeatureExpr ctx) { return Types.getTypeName(env.getElementInfo(objRef).getType()); } @MJI public static void addComment__Ljava_lang_String_2__V (MJIEnv env, int clsObjRef, int stringRef, FeatureExpr ctx) { SystemState ss = env.getSystemState(); String cmt = env.getStringObject(ctx, stringRef); ss.getTrail().setAnnotation(cmt); } /** deprectated, just use assert */ @MJI public static void assertTrue__Z__V (MJIEnv env, int clsObjRef, boolean b, FeatureExpr ctx) { if (!b) { env.throwException(ctx, "java.lang.AssertionError", "assertTrue failed"); } } // those are evil - use with extreme care @MJI public static void beginAtomic____V (MJIEnv env, int clsObjRef, FeatureExpr ctx) { if (enableAtomic){ ThreadInfo tiAtomic = env.getThreadInfo(); if (!tiAtomic.isFirstStepInsn()){ SystemState ss = env.getSystemState(); ChoiceGenerator<?> cg = ss.getSchedulerFactory().createBeginAtomicCG(tiAtomic); if (ss.setNextChoiceGenerator(cg)) { env.repeatInvocation(); return; } } env.getSystemState().incAtomic(); } } @MJI public static void endAtomic____V (MJIEnv env, int clsObjRef, FeatureExpr ctx) { if (enableAtomic){ ThreadInfo tiAtomic = env.getThreadInfo(); if (!tiAtomic.isFirstStepInsn()){ env.getSystemState().decAtomic(); SystemState ss = env.getSystemState(); ChoiceGenerator<?> cg = ss.getSchedulerFactory().createEndAtomicCG(tiAtomic); if (ss.setNextChoiceGenerator(cg)) { env.repeatInvocation(); } } } } @MJI public static void busyWait__J__V (MJIEnv env, int clsObjRef, long duration, FeatureExpr ctx) { // nothing required here (we systematically explore scheduling // sequences anyway), but we need to intercept the call } @MJI public static void ignoreIf__Z__V (MJIEnv env, int clsObjRef, boolean cond, FeatureExpr ctx) { if (supportIgnorePath) { env.getSystemState().setIgnored(cond); } } @MJI public static void interesting__Z__V (MJIEnv env, int clsObjRef, boolean cond, FeatureExpr ctx) { env.getSystemState().setInteresting(cond); } @MJI public static void breakTransition__Ljava_lang_String_2__V (MJIEnv env, int clsObjRef, int reasonRef, FeatureExpr ctx){ ThreadInfo ti = env.getThreadInfo(); String reason = env.getStringObject(ctx, reasonRef); ti.breakTransition(reason); } @MJI public static boolean isCalledFromClass__Ljava_lang_String_2__Z (MJIEnv env, int clsObjRef, int clsNameRef, FeatureExpr ctx) { String refClassName = env.getStringObject(ctx, clsNameRef); ThreadInfo ti = env.getThreadInfo(); StackFrame caller = ti.getLastInvokedStackFrame(); if (caller != null){ ClassInfo ci = caller.getClassInfo(); return ci.isInstanceOf(refClassName); } return false; } static <T extends ChoiceGenerator<?>> T createChoiceGenerator (Class<T> cgClass, SystemState ss, String id) { T gen = null; cgArgs[0] = config; cgArgs[1] = id; // good thing we are not multithreaded (other fields are const) String key = id + ".class"; gen = config.getEssentialInstance(key, cgClass, cgArgTypes, cgArgs); return gen; } static <T> T registerChoiceGenerator (MJIEnv env, SystemState ss, ThreadInfo ti, ChoiceGenerator<T> cg, T dummyVal){ int n = cg.getTotalNumberOfChoices(); if (n == 0) { // we need a CG ss.setIgnored(true); ti.breakTransition( cg.getId()); } else if (n == 1 && !breakSingleChoice) { // no choice -> no CG optimization cg.advance(); return cg.getNextChoice(); } else { if (ss.setNextChoiceGenerator(cg)){ env.repeatInvocation(); } } return dummyVal; } static <T,C extends ChoiceGenerator<T>> T getNextChoice (SystemState ss, String id, Class<C> cgClass, Class<T> choiceClass){ ChoiceGenerator<?> cg = ss.getCurrentChoiceGenerator(id, cgClass); assert (cg != null) : "no ChoiceGenerator of type " + cgClass.getName(); return ((ChoiceGenerator<T>)cg).getNextChoice(); } @MJI public static boolean getBoolean____Z (MJIEnv env, int clsObjRef, FeatureExpr ctx) { ThreadInfo ti = env.getThreadInfo(); SystemState ss = env.getSystemState(); ChoiceGenerator<?> cg; if (!ti.isFirstStepInsn()) { // first time around cg = new BooleanChoiceGenerator(config, "verifyGetBoolean"); if (ss.setNextChoiceGenerator(cg)){ env.repeatInvocation(); } return true; // not used if we repeat } else { // this is what really returns results return getNextChoice(ss,"verifyGetBoolean", BooleanChoiceGenerator.class,Boolean.class); } } @MJI public static boolean getBoolean__Z__Z (MJIEnv env, int clsObjRef, boolean falseFirst, FeatureExpr ctx) { ThreadInfo ti = env.getThreadInfo(); SystemState ss = env.getSystemState(); ChoiceGenerator<?> cg; if (!ti.isFirstStepInsn()) { // first time around cg = new BooleanChoiceGenerator( "verifyGetBoolean(Z)", falseFirst ); if (ss.setNextChoiceGenerator(cg)){ env.repeatInvocation(); } return true; // not used if we repeat } else { // this is what really returns results return getNextChoice(ss,"verifyGetBoolean(Z)", BooleanChoiceGenerator.class, Boolean.class); } } @MJI public static int getInt__II__I (MJIEnv env, int clsObjRef, Conditional<Integer> min, Conditional<Integer> max, FeatureExpr ctx) { ThreadInfo ti = env.getThreadInfo(); SystemState ss = env.getSystemState(); if (!ti.isFirstStepInsn()) { // first time around if (min.getValue() > max.getValue()){ Conditional<Integer> t = max; max = min; min = t; } IntChoiceGenerator cg = new IntIntervalGenerator( "verifyGetInt(II)", min.getValue(),max.getValue()); return registerChoiceGenerator(env,ss,ti,cg,0); } else { return getNextChoice(ss, "verifyGetInt(II)", IntChoiceGenerator.class, Integer.class); } } static int getIntFromList (MJIEnv env, int[] values){ ThreadInfo ti = env.getThreadInfo(); SystemState ss = env.getSystemState(); if (!ti.isFirstStepInsn()) { // first time around ChoiceGenerator<Integer> cg = new IntChoiceFromSet( "verifyGetIntSet([I)", values); return registerChoiceGenerator(env,ss,ti,cg,0); } else { return getNextChoice(ss, "verifyGetIntSet([I)", IntChoiceGenerator.class, Integer.class); } } @MJI public static int getIntFromList___3I__I (MJIEnv env, int clsObjRef, int valArrayRef, FeatureExpr ctx){ int[] values = env.getIntArrayObject(ctx, valArrayRef); return getIntFromList( env, values); } @MJI public static int getInt__Ljava_lang_String_2__I (MJIEnv env, int clsObjRef, int idRef, FeatureExpr ctx) { ThreadInfo ti = env.getThreadInfo(); SystemState ss = env.getSystemState(); if (!ti.isFirstStepInsn()) { // first time around String id = env.getStringObject(ctx, idRef); IntChoiceGenerator cg = createChoiceGenerator( IntChoiceGenerator.class, ss, id); return registerChoiceGenerator(env,ss,ti,cg, 0); } else { String id = env.getStringObject(ctx, idRef); return getNextChoice(ss, id, IntChoiceGenerator.class,Integer.class); } } static long getLongFromList (MJIEnv env, long[] values){ ThreadInfo ti = env.getThreadInfo(); SystemState ss = env.getSystemState(); if (!ti.isFirstStepInsn()) { // first time around ChoiceGenerator<Long> cg = new LongChoiceFromList( "verifyLongList([J)", values); return registerChoiceGenerator(env,ss,ti,cg,0L); } else { return getNextChoice(ss, "verifyLongList([J)", LongChoiceGenerator.class, Long.class); } } @MJI public static long getLongFromList___3J__J (MJIEnv env, int clsObjRef, int valArrayRef, FeatureExpr ctx){ Conditional<Long>[] values = env.getLongArrayObject(valArrayRef); long [] a = new long[values.length]; for (int i = 0; i < values.length; i++) { a[i] = values[i].getValue(); } return getLongFromList( env, a); } @MJI public static int getObject__Ljava_lang_String_2__Ljava_lang_Object_2 (MJIEnv env, int clsObjRef, int idRef, FeatureExpr ctx) { ThreadInfo ti = env.getThreadInfo(); SystemState ss = env.getSystemState(); if (!ti.isFirstStepInsn()) { // first time around String id = env.getStringObject(ctx, idRef); ReferenceChoiceGenerator cg = createChoiceGenerator( ReferenceChoiceGenerator.class, ss, id); return registerChoiceGenerator(env,ss,ti,cg, 0); } else { String id = env.getStringObject(ctx, idRef); return getNextChoice(ss, id, ReferenceChoiceGenerator.class,Integer.class); } } @MJI public static double getDouble__Ljava_lang_String_2__D (MJIEnv env, int clsObjRef, int idRef, FeatureExpr ctx) { ThreadInfo ti = env.getThreadInfo(); SystemState ss = env.getSystemState(); if (!ti.isFirstStepInsn()) { // first time around String id = env.getStringObject(ctx, idRef); DoubleChoiceGenerator cg = createChoiceGenerator( DoubleChoiceGenerator.class, ss, id); return registerChoiceGenerator(env,ss,ti,cg, 0.0); } else { String id = env.getStringObject(ctx, idRef); return getNextChoice(ss, id, DoubleChoiceGenerator.class,Double.class); } } @MJI public static double getDoubleFromList (MJIEnv env, double[] values, FeatureExpr ctx){ ThreadInfo ti = env.getThreadInfo(); SystemState ss = env.getSystemState(); if (!ti.isFirstStepInsn()) { // first time around ChoiceGenerator<Double> cg = new DoubleChoiceFromList("verifyDoubleList([D)", values); return registerChoiceGenerator(env,ss,ti,cg, 0.0); } else { return getNextChoice(ss, "verifyDoubleList([D)", DoubleChoiceFromList.class,Double.class); } } @MJI public static double getDoubleFromList___3D__D (MJIEnv env, int clsObjRef, Conditional<Integer> valArrayRef, FeatureExpr ctx){ Conditional<Double>[] values = env.getDoubleArrayObject(valArrayRef.getValue()); double [] a = new double[values.length]; for (int i = 0; i < values.length; i++) { a[i] = values[i].getValue(); } return getDoubleFromList( env, a, ctx); } @MJI public static float getFloatFromList (MJIEnv env, float[] values, FeatureExpr ctx){ ThreadInfo ti = env.getThreadInfo(); SystemState ss = env.getSystemState(); if (!ti.isFirstStepInsn()) { // first time around ChoiceGenerator<Float> cg = new FloatChoiceFromList("verifyFloatList([F)", values); return registerChoiceGenerator(env,ss,ti,cg, 0.0f); } else { return getNextChoice(ss, "verifyFloatList([F)", FloatChoiceFromList.class, Float.class); } } @MJI public static float getFloatFromList___3F__F (MJIEnv env, int clsObjRef, int valArrayRef, FeatureExpr ctx){ Conditional<Float>[] condValues = env.getFloatArrayObject(valArrayRef); float[] values = new float[condValues.length]; for (int i = 0; i < condValues.length; i++) { values[i] = condValues[i].getValue(); } return getFloatFromList( env, values, ctx); } @MJI public static void print__Ljava_lang_String_2I__V (MJIEnv env, int clsRef, int sRef, int val, FeatureExpr ctx){ String s = env.getStringObject(ctx, sRef); System.out.println(s + " : " + val); } @MJI public static void print__Ljava_lang_String_2Z__V (MJIEnv env, int clsRef, int sRef, boolean val, FeatureExpr ctx){ String s = env.getStringObject(ctx, sRef); System.out.println(s + " : " + val); } @MJI public static void print___3Ljava_lang_String_2__V (MJIEnv env, int clsRef, int argsRef, FeatureExpr ctx){ int n = env.getArrayLength(ctx, argsRef); for (int i=0; i<n; i++){ int aref = env.getReferenceArrayElement(argsRef, i).getValue(); String s = env.getStringObject(ctx, aref); System.out.print(s); } } @MJI public static void print__Ljava_lang_String_2__V (MJIEnv env, int clsRef, int sRef, FeatureExpr ctx){ String s = env.getStringObject(ctx, sRef); System.out.print(s); } @MJI public static void println__Ljava_lang_String_2__V (MJIEnv env, int clsRef, int sRef, FeatureExpr ctx){ String s = env.getStringObject(ctx, sRef); System.out.println(s); } @MJI public static void println____V (MJIEnv env, int clsRef, FeatureExpr ctx){ System.out.println(); } //--- various attribute test methods private static int getAttribute (MJIEnv env, Object a, FeatureExpr ctx){ if (a != null) { if (a instanceof Integer) { return ((Integer) a).intValue(); } else { env.throwException(ctx, "java.lang.RuntimeException", "element attribute not an Integer: " + a); } } return 0; } private static int getAttributeList (MJIEnv env, Object a, FeatureExpr ctx){ if (a != null) { int l = ObjectList.size(a); int[] attrs = new int[l]; int i = 0; for (Integer v : ObjectList.typedIterator(a, Integer.class)) { attrs[i++] = v; } if (i != l) { env.throwException(ctx, "java.lang.RuntimeException", "found non-Integer attributes"); return 0; } return env.newIntArray(ctx, attrs); } else { return MJIEnv.NULL; } } @MJI public static void setObjectAttribute__Ljava_lang_Object_2I__V (MJIEnv env, int clsRef, int oRef, int attr, FeatureExpr ctx){ if (oRef != MJIEnv.NULL){ ElementInfo ei = env.getElementInfo(oRef); ei.setObjectAttr(Integer.valueOf(attr)); } } @MJI public static int getObjectAttribute__Ljava_lang_Object_2__I (MJIEnv env, int clsRef, int oRef, FeatureExpr ctx){ if (oRef != MJIEnv.NULL){ ElementInfo ei = env.getElementInfo(oRef); return getAttribute( env, ei.getObjectAttr(), ctx); } return 0; } @MJI public static void addObjectAttribute__Ljava_lang_Object_2I__V (MJIEnv env, int clsRef, int oRef, int attr, FeatureExpr ctx){ if (oRef != MJIEnv.NULL){ ElementInfo ei = env.getElementInfo(oRef); ei.addObjectAttr(Integer.valueOf(attr)); } } @MJI public static int getObjectAttributes__Ljava_lang_Object_2___3I (MJIEnv env, int clsRef, int oRef, FeatureExpr ctx){ if (oRef != MJIEnv.NULL){ ElementInfo ei = env.getElementInfo(oRef); return getAttributeList( env, ei.getObjectAttr(), ctx); } return MJIEnv.NULL; } @MJI public static void setFieldAttribute__Ljava_lang_Object_2Ljava_lang_String_2I__V (MJIEnv env, int clsRef, int oRef, int fnRef, int attr, FeatureExpr ctx){ if (oRef != MJIEnv.NULL){ ElementInfo ei = env.getElementInfo(oRef); if (ei != null){ String fname = env.getStringObject(ctx, fnRef); FieldInfo fi = ei.getFieldInfo(fname); if (fi != null) { ei.setFieldAttr(fi, Integer.valueOf(attr)); } else { env.throwException(ctx, "java.lang.NoSuchFieldException", ei.getClassInfo().getName() + '.' + fname); } } else { env.throwException(ctx, "java.lang.RuntimeException", "illegal reference value: " + oRef); } } } @MJI public static int getFieldAttribute__Ljava_lang_Object_2Ljava_lang_String_2__I (MJIEnv env, int clsRef, int oRef, int fnRef, FeatureExpr ctx){ if (oRef != MJIEnv.NULL){ ElementInfo ei = env.getElementInfo(oRef); if (ei != null){ String fname = env.getStringObject(ctx, fnRef); FieldInfo fi = ei.getFieldInfo(fname); if (fi != null) { return getAttribute( env, ei.getFieldAttr(fi), ctx); } else { env.throwException(ctx, "java.lang.NoSuchFieldException", ei.toString() + '.' + fname); } } else { env.throwException(ctx, "java.lang.RuntimeException", "illegal reference value: " + oRef); } } return 0; } @MJI public static void addFieldAttribute__Ljava_lang_Object_2Ljava_lang_String_2I__V (MJIEnv env, int clsRef, int oRef, int fnRef, int attr, FeatureExpr ctx){ if (oRef != MJIEnv.NULL){ ElementInfo ei = env.getElementInfo(oRef); if (ei != null){ String fname = env.getStringObject(ctx, fnRef); FieldInfo fi = ei.getFieldInfo(fname); if (fi != null) { ei.addFieldAttr(fi, Integer.valueOf(attr)); } else { env.throwException(ctx, "java.lang.NoSuchFieldException", ei.getClassInfo().getName() + '.' + fname); } } else { env.throwException(ctx, "java.lang.RuntimeException", "illegal reference value: " + oRef); } } } @MJI public static int getFieldAttributes__Ljava_lang_Object_2Ljava_lang_String_2___3I (MJIEnv env, int clsRef, int oRef, int fnRef, FeatureExpr ctx){ if (oRef != MJIEnv.NULL){ ElementInfo ei = env.getElementInfo(oRef); if (ei != null){ String fname = env.getStringObject(ctx, fnRef); FieldInfo fi = ei.getFieldInfo(fname); if (fi != null) { return getAttributeList( env, ei.getFieldAttr(fi), ctx); } else { env.throwException(ctx, "java.lang.NoSuchFieldException", ei.toString() + '.' + fname); } } else { env.throwException(ctx, "java.lang.RuntimeException", "illegal reference value: " + oRef); } } return MJIEnv.NULL; } @MJI public static void setLocalAttribute__Ljava_lang_String_2I__V (MJIEnv env, int clsRef, int varRef, int attr, FeatureExpr ctx) { String slotName = env.getStringObject(ctx, varRef); StackFrame frame = env.getModifiableCallerStackFrame(); // we are executing in a NativeStackFrame if (!frame.getMethodInfo().isStatic() && slotName.equals("this")) { frame.setLocalAttr(0, Integer.valueOf(attr)); // only for instance methods of course } else { int slotIdx = frame.getLocalVariableSlotIndex(slotName); if (slotIdx >= 0) { frame.setLocalAttr(slotIdx, Integer.valueOf(attr)); } else { env.throwException(ctx, "java.lang.RuntimeException", "local variable not found: " + slotName); } } } @MJI public static int getLocalAttribute__Ljava_lang_String_2__I (MJIEnv env, int clsRef, int varRef, FeatureExpr ctx) { String slotName = env.getStringObject(ctx, varRef); StackFrame frame = env.getCallerStackFrame(); int slotIdx = frame.getLocalVariableSlotIndex(slotName); if (slotIdx >= 0) { return getAttribute( env, frame.getLocalAttr(slotIdx), ctx); } else { env.throwException(ctx, "java.lang.RuntimeException", "local variable not found: " + slotName); return 0; } } @MJI public static void addLocalAttribute__Ljava_lang_String_2I__V (MJIEnv env, int clsRef, int varRef, int attr, FeatureExpr ctx) { String slotName = env.getStringObject(ctx, varRef); StackFrame frame = env.getModifiableCallerStackFrame(); // we are executing in a NativeStackFrame if (!frame.getMethodInfo().isStatic() && slotName.equals("this")) { frame.addLocalAttr(0, Integer.valueOf(attr)); // only for instance methods of course } else { int slotIdx = frame.getLocalVariableSlotIndex(slotName); if (slotIdx >= 0) { frame.addLocalAttr(slotIdx, Integer.valueOf(attr)); } else { env.throwException(ctx, "java.lang.RuntimeException", "local variable not found: " + slotName); } } } @MJI public static int getLocalAttributes__Ljava_lang_String_2___3I (MJIEnv env, int clsRef, int varRef, FeatureExpr ctx) { String slotName = env.getStringObject(ctx, varRef); StackFrame frame = env.getCallerStackFrame(); int slotIdx = frame.getLocalVariableSlotIndex(slotName); if (slotIdx >= 0) { return getAttributeList( env, frame.getLocalAttr(slotIdx), ctx); } else { env.throwException(ctx, "java.lang.RuntimeException", "local variable not found: " + slotName); } return MJIEnv.NULL; } @MJI public static void setElementAttribute__Ljava_lang_Object_2II__V (MJIEnv env, int clsRef, int oRef, int idx, int attr, FeatureExpr ctx){ if (oRef != MJIEnv.NULL){ ElementInfo ei = env.getElementInfo(oRef); if (ei != null){ if (ei.isArray()) { if (idx < ei.arrayLength().getValue()) { ei.setElementAttr(idx, Integer.valueOf(attr)); } else { env.throwException(ctx, "java.lang.ArrayIndexOutOfBoundsException", Integer.toString(idx)); } } else { env.throwException(ctx, "java.lang.RuntimeException", "not an array: " + ei); } } else { env.throwException(ctx, "java.lang.RuntimeException", "illegal reference value: " + oRef); } } } @MJI public static int getElementAttribute__Ljava_lang_Object_2I__I (MJIEnv env, int clsRef, int oRef, int idx, FeatureExpr ctx){ if (oRef != MJIEnv.NULL){ ElementInfo ei = env.getElementInfo(oRef); if (ei != null) { if (ei.isArray()) { if (idx < ei.arrayLength().getValue()) { return getAttribute( env, ei.getElementAttr( idx), ctx); } else { env.throwException(ctx, "java.lang.ArrayIndexOutOfBoundsException", Integer.toString(idx)); } } else { env.throwException(ctx, "java.lang.RuntimeException", "not an array: " + ei); } } else { env.throwException(ctx, "java.lang.RuntimeException", "illegal reference value: " + oRef); } } return 0; } @MJI public static void addElementAttribute__Ljava_lang_Object_2II__V (MJIEnv env, int clsRef, int oRef, int idx, int attr, FeatureExpr ctx){ if (oRef != MJIEnv.NULL){ ElementInfo ei = env.getElementInfo(oRef); if (ei != null){ if (ei.isArray()) { if (idx < ei.arrayLength().getValue()) { ei.addElementAttr(idx, Integer.valueOf(attr)); } else { env.throwException(ctx, "java.lang.ArrayIndexOutOfBoundsException", Integer.toString(idx)); } } else { env.throwException(ctx, "java.lang.RuntimeException", "not an array: " + ei); } } else { env.throwException(ctx, "java.lang.RuntimeException", "illegal reference value: " + oRef); } } } @MJI public static int getElementAttributes__Ljava_lang_Object_2I___3I (MJIEnv env, int clsRef, int oRef, int idx, FeatureExpr ctx){ if (oRef != MJIEnv.NULL){ ElementInfo ei = env.getElementInfo(oRef); if (ei != null) { if (ei.isArray()) { if (idx < ei.arrayLength().getValue()) { return getAttributeList( env, ei.getElementAttr( idx), ctx); } else { env.throwException(ctx, "java.lang.ArrayIndexOutOfBoundsException", Integer.toString(idx)); } } else { env.throwException(ctx, "java.lang.RuntimeException", "not an array: " + ei); } } else { env.throwException(ctx, "java.lang.RuntimeException", "illegal reference value: " + oRef); } } return MJIEnv.NULL; } /** * deprecated, use getBoolean() */ @MJI public static boolean randomBool (MJIEnv env, int clsObjRef, FeatureExpr ctx) { //SystemState ss = env.getSystemState(); //return (ss.random(2) != 0); return getBoolean____Z(env, clsObjRef, ctx); } /** * deprecated, use getInt */ @MJI public static int random__I__I (MJIEnv env, int clsObjRef, Conditional<Integer> x, FeatureExpr ctx) { return getInt__II__I( env, clsObjRef, One.valueOf(0), x, ctx); } static void boring__Z__V (MJIEnv env, int clsObjRef, boolean b, FeatureExpr ctx) { env.getSystemState().setBoring(b); } @MJI public static boolean isRunningInJPF____Z(MJIEnv env, int clsObjRe, FeatureExpr ctxf) { return true; } @MJI public static boolean vmIsMatchingStates____Z(MJIEnv env, int clsObjRef, FeatureExpr ctx) { return env.getVM().getStateSet() != null; } @MJI public static void storeTrace__Ljava_lang_String_2Ljava_lang_String_2__V (MJIEnv env, int clsObjRef, int filenameRef, int commentRef, FeatureExpr ctx) { String fileName = env.getStringObject(ctx, filenameRef); String comment = env.getStringObject(ctx, commentRef); env.getVM().storeTrace(fileName, comment, config.getBoolean("trace.verbose", false)); } @MJI public static void terminateSearch____V (MJIEnv env, int clsObjRef, FeatureExpr ctx) { JPF jpf = env.getVM().getJPF(); jpf.getSearch().terminate(); } @MJI public static boolean isTraceReplay____Z (MJIEnv env, int clsObjRef, FeatureExpr ctx) { return env.getVM().isTraceReplay(); } @MJI public static boolean isShared__Ljava_lang_Object_2__Z (MJIEnv env, int clsObjRef, int objRef, FeatureExpr ctx){ if (objRef != MJIEnv.NULL){ ElementInfo ei = env.getElementInfo(objRef); if (ei != null){ return ei.isShared(); } } return false; } @MJI public static void setShared__Ljava_lang_Object_2Z__V (MJIEnv env, int clsObjRef, int objRef, boolean isShared, FeatureExpr ctx) { if (objRef != MJIEnv.NULL){ ElementInfo ei = env.getElementInfo(objRef); if (ei != null){ if (ei.getClassInfo() == ClassLoaderInfo.getCurrentSystemClassLoader().getClassClassInfo()) { // it's a class object, set static fields shared ei = env.getStaticElementInfo(objRef); } if (ei.isShared() != isShared) { ei = ei.getModifiableInstance(); ei.setShared( isShared); } } } } @MJI public static void freezeSharedness__Ljava_lang_Object_2Z__V (MJIEnv env, int clsObjRef, int objRef, boolean freeze, FeatureExpr ctx) { if (objRef != MJIEnv.NULL){ ElementInfo ei = env.getElementInfo(objRef); if (ei != null) { if (ei.getClassInfo() == ClassLoaderInfo.getCurrentSystemClassLoader().getClassClassInfo()) { // it's a class object, freeze sharedness of static fields ei = env.getStaticElementInfo(objRef); } if (ei.isSharednessFrozen() != freeze) { ei = ei.getModifiableInstance(); ei.freezeSharedness(freeze); } } } } @MJI public static void setProperties___3Ljava_lang_String_2__V (MJIEnv env, int clsObjRef, int argRef, FeatureExpr ctx) { if (argRef != MJIEnv.NULL) { // Config conf = env.getConfig(); int n = env.getArrayLength(ctx, argRef); for (int i=0; i<n; i++) { int pRef = env.getReferenceArrayElement(argRef, i).getValue(); if (pRef != MJIEnv.NULL) { String p = env.getStringObject(ctx, pRef); config.parse(p); } } } } @MJI public static int getProperty__Ljava_lang_String_2__Ljava_lang_String_2 (MJIEnv env, int clsObjRef, int keyRef, FeatureExpr ctx) { if (keyRef != MJIEnv.NULL){ // Config conf = env.getConfig(); String key = env.getStringObject(ctx, keyRef); String val = config.getString(key); if (val != null){ return env.newString(FeatureExprFactory.True(), val); } else { return MJIEnv.NULL; } } else { return MJIEnv.NULL; } } @MJI public static void printPathOutput__ZLjava_lang_String_2__V (MJIEnv env, int clsObjRef, boolean cond, int msgRef, FeatureExpr ctx){ if (cond){ printPathOutput__Ljava_lang_String_2__V(env,clsObjRef,msgRef, ctx); } } @MJI public static void printPathOutput__Ljava_lang_String_2__V (MJIEnv env, int clsObjRef, int msgRef, FeatureExpr ctx){ VM vm = env.getVM(); System.out.println(); if (msgRef != MJIEnv.NULL){ String msg = env.getStringObject(ctx, msgRef); System.out.println("~~~~~~~~~~~~~~~~~~~~~~~ begin program output at: " + msg); } else { System.out.println("~~~~~~~~~~~~~~~~~~~~~~~ begin path output"); } for (Transition t : vm.getPath()) { String s = t.getOutput(); if (s != null) { System.out.print(s); } } // we might be in the middle of a transition that isn't stored yet in the path String s = vm.getPendingOutput(); if (s != null) { System.out.print(s); } System.out.println("~~~~~~~~~~~~~~~~~~~~~~~ end path output"); } // the JSON object initialization @MJI public static int createFromJSON__Ljava_lang_Class_2Ljava_lang_String_2__Ljava_lang_Object_2( MJIEnv env, int clsObjRef, int newObjClsRef, int jsonStringRef, FeatureExpr ctx) { ThreadInfo ti = env.getThreadInfo(); SystemState ss = env.getSystemState(); String jsonString = env.getStringObject(ctx, jsonStringRef); JSONLexer lexer = new JSONLexer(jsonString); JSONParser parser = new JSONParser(lexer); JSONObject jsonObject = parser.parse(); if (jsonObject != null) { ClassInfo ci = env.getReferredClassInfo( ctx, newObjClsRef); // check if we need any class init (and hence reexecution) before creating any CGs if (jsonObject.requiresClinitExecution(ci,ti)){ env.repeatInvocation(); return MJIEnv.NULL; } if (!ti.isFirstStepInsn()) { // Top half - get and register CGs we need to set to fill object from JSON List<ChoiceGenerator<?>> cgList = CGCall.createCGList(jsonObject); if (cgList.isEmpty()){ return jsonObject.fillObject(ctx, env, ci, null, ""); } else { for (ChoiceGenerator<?> cg : cgList) { ss.setNextChoiceGenerator(cg); } env.repeatInvocation(); return MJIEnv.NULL; } } else { // Bottom half - fill object with JSON and current values of CGs ChoiceGenerator<?>[] cgs = ss.getChoiceGenerators(); return jsonObject.fillObject(ctx, env, ci, cgs, ""); } } else { return MJIEnv.NULL; } } @SuppressWarnings("resource") @MJI public static int readObjectFromFile__Ljava_lang_Class_2Ljava_lang_String_2__Ljava_lang_Object_2( MJIEnv env, int clsObjRef, int newObjClsRef, int fileNameRef, FeatureExpr ctx) { // int typeNameRef = env.getReferenceField(ctx, newObjClsRef, "name").getValue(); // String typeName = env.getStringObject(ctx, typeNameRef); String fileName = env.getStringObject(ctx, fileNameRef); try { FileInputStream fis = new FileInputStream(fileName); ObjectInputStream ois = new ObjectInputStream(fis); Object javaObject = ois.readObject(); // String readObjectTypeName = javaObject.getClass().getCanonicalName(); int readObjRef = ObjectConverter.JPFObjectFromJavaObject(ctx, env, javaObject); return readObjRef; } catch (ClinitRequired clix){ env.repeatInvocation(); return MJIEnv.NULL; } catch (IOException iox){ throw new JPFException("failure reading object from file: " + fileName, iox); } catch (ClassNotFoundException cnfx){ throw new JPFException("failure reading object from file: " + fileName, cnfx); } } //--- those need to be kept in sync with the model side public static final int SEVERE = 1; public static final int WARNING = 2; public static final int INFO = 3; public static final int FINE = 4; public static final int FINER = 5; public static final int FINEST = 6; private static void log (JPFLogger logger, int logLevel, String msg){ switch (logLevel){ case SEVERE: logger.severe( msg); break; case WARNING: logger.warning( msg); break; case INFO: logger.info( msg); break; case FINE: logger.fine( msg); break; case FINER: logger.finer( msg); break; case FINEST: logger.finest( msg); break; default: throw new JPFException("unknown log level " + logLevel + " for logger " + logger.getName()); } } @MJI public static void log__Ljava_lang_String_2ILjava_lang_String_2__V (MJIEnv env, int clsObjRef, int loggerIdRef, int logLevel, int msgRef, FeatureExpr ctx){ String loggerId = env.getStringObject(ctx, loggerIdRef); String msg = env.getStringObject(ctx, msgRef); JPFLogger logger = JPF.getLogger(loggerId); log( logger, logLevel, msg); } @MJI public static void log__Ljava_lang_String_2ILjava_lang_String_2Ljava_lang_String_2__V (MJIEnv env, int clsObjRef, int loggerIdRef, int logLevel, int arg1Ref, int arg2Ref, FeatureExpr ctx){ String loggerId = env.getStringObject(ctx, loggerIdRef); String msg = env.getStringObject(ctx, arg1Ref) + env.getStringObject(ctx, arg2Ref); JPFLogger logger = JPF.getLogger(loggerId); log( logger, logLevel, msg); } @MJI public static void log__Ljava_lang_String_2ILjava_lang_String_2_3Ljava_lang_Object_2__V (MJIEnv env, int clsObjRef, int loggerIdRef, int logLevel, int fmtRef, int argsRef, FeatureExpr ctx){ String loggerId = env.getStringObject(ctx, loggerIdRef); String fmt = env.getStringObject(ctx, fmtRef); JPFLogger logger = JPF.getLogger(loggerId); Conditional<Integer>[] argRefs = env.getReferenceArrayObject( argsRef); Object[] args = new Object[argRefs.length]; for (int i=0; i<args.length; i++){ ElementInfo eiArg = env.getElementInfo(argRefs[i].getValue()); if (eiArg.isStringObject()){ args[i] = env.getStringObject(ctx, argRefs[i].getValue()); } else if (eiArg.isBoxObject()){ args[i] = eiArg.asBoxObject(); } else { args[i] = eiArg.toString(); } } String msg = String.format(fmt, args); log( logger, logLevel, msg); } }