MethodAnalyzer.java revision 1c56c7e7507dc24ae1ed2f693c793d94df814c76
1d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.compackage org.jf.dexlib.Code.Analysis; 2d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 3fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.comimport org.jf.dexlib.*; 4fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.comimport org.jf.dexlib.Code.*; 5472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.comimport org.jf.dexlib.Code.Format.ArrayDataPseudoInstruction; 6472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.comimport org.jf.dexlib.Code.Format.Format; 7fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.comimport org.jf.dexlib.Util.*; 8d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 9fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.comimport java.util.*; 10d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 11d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.compublic class MethodAnalyzer { 12d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com private final ClassDataItem.EncodedMethod encodedMethod; 13d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 14fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com private SparseArray<AnalyzedInstruction> instructions; 15fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 16fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com private boolean analyzed = false; 17d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 18c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com private BitSet verifiedInstructions; 19c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com 20c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com private ValidationException validationException = null; 21300ad56aa3c343a84017ae7a2267dc516b5b6202JesusFreke@JesusFreke.com 22d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com //This is a dummy instruction that occurs immediately before the first real instruction. We can initialize the 23d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com //register types for this instruction to the parameter types, in order to have them propagate to all of its 24d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com //successors, e.g. the first real instruction, the first instructions in any exception handlers covering the first 25d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com //instruction, etc. 26d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com private AnalyzedInstruction startOfMethod; 27d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 28d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com public MethodAnalyzer(ClassDataItem.EncodedMethod encodedMethod) { 29d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com if (encodedMethod == null) { 30d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com throw new IllegalArgumentException("encodedMethod cannot be null"); 31d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com } 32fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (encodedMethod.codeItem == null || encodedMethod.codeItem.getInstructions().length == 0) { 33d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com throw new IllegalArgumentException("The method has no code"); 34d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com } 35d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com this.encodedMethod = encodedMethod; 36fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 37fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //override AnalyzedInstruction and provide custom implementations of some of the methods, so that we don't 38fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //have to handle the case this special case of instruction being null, in the main class 39fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com startOfMethod = new AnalyzedInstruction(null, -1, encodedMethod.codeItem.getRegisterCount()) { 40fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com public boolean setsRegister() { 41fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return false; 42fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 43fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 44fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com @Override 45fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com public boolean setsWideRegister() { 46fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return false; 47fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 48fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 49fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com @Override 50fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com public boolean setsRegister(int registerNumber) { 51fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return false; 52fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 53fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 54fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com @Override 55fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com public int getDestinationRegister() { 56fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com assert false; 57fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return -1; 58fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com }; 59fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com }; 60300ad56aa3c343a84017ae7a2267dc516b5b6202JesusFreke@JesusFreke.com 617e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com buildInstructionList(); 627e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com 63c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com verifiedInstructions = new BitSet(instructions.size()); 64d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com } 65d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 66d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com public AnalyzedInstruction[] analyze() { 67fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com assert encodedMethod != null; 68fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com assert encodedMethod.codeItem != null; 69fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 70fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (analyzed) { 71fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return makeInstructionArray(); 72fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 73fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 74fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com CodeItem codeItem = encodedMethod.codeItem; 75fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com MethodIdItem methodIdItem = encodedMethod.method; 76fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 77fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com int totalRegisters = codeItem.getRegisterCount(); 78fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com int parameterRegisters = methodIdItem.getPrototype().getParameterRegisterCount(); 79fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 80fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //if this isn't a static method, determine which register is the "this" register and set the type to the 81fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //current class 82fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if ((encodedMethod.accessFlags & AccessFlags.STATIC.getValue()) == 0) { 83fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com int thisRegister = totalRegisters - parameterRegisters - 1; 84fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 85fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //if this is a constructor, then set the "this" register to an uninitialized reference of the current class 86fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if ((encodedMethod.accessFlags & AccessFlags.CONSTRUCTOR.getValue()) != 0) { 87fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //TODO: it would probably make more sense to validate this somewhere else, and just put an assert here. Also, need to do a similar check for static constructor 887e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com if (!encodedMethod.method.getMethodName().getStringValue().equals("<init>")) { 89fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com throw new ValidationException("The constructor flag can only be used with an <init> method."); 90fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 91fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 92fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com setRegisterTypeAndPropagateChanges(startOfMethod, thisRegister, 93c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com RegisterType.getRegisterType(RegisterType.Category.UninitThis, 94fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com ClassPath.getClassDef(methodIdItem.getContainingClass()))); 95fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } else { 967e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com if (encodedMethod.method.getMethodName().getStringValue().equals("<init>")) { 97fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com throw new ValidationException("An <init> method must have the \"constructor\" access flag"); 98fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 99fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 100fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com setRegisterTypeAndPropagateChanges(startOfMethod, thisRegister, 101fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType.getRegisterType(RegisterType.Category.Reference, 102fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com ClassPath.getClassDef(methodIdItem.getContainingClass()))); 103fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 104fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 105fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 106fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com TypeListItem parameters = methodIdItem.getPrototype().getParameters(); 107fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (parameters != null) { 108fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType[] parameterTypes = getParameterTypes(parameters, parameterRegisters); 109fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com for (int i=0; i<parameterTypes.length; i++) { 110fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType registerType = parameterTypes[i]; 111fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com int registerNum = (totalRegisters - parameterRegisters) + i; 112fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com setRegisterTypeAndPropagateChanges(startOfMethod, registerNum, registerType); 113fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 114fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 115fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 116c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com BitSet instructionsToAnalyze = new BitSet(verifiedInstructions.size()); 117300ad56aa3c343a84017ae7a2267dc516b5b6202JesusFreke@JesusFreke.com 118300ad56aa3c343a84017ae7a2267dc516b5b6202JesusFreke@JesusFreke.com //make sure all of the "first instructions" are marked for processing 119300ad56aa3c343a84017ae7a2267dc516b5b6202JesusFreke@JesusFreke.com for (AnalyzedInstruction successor: startOfMethod.successors) { 120c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com instructionsToAnalyze.set(successor.instructionIndex); 121300ad56aa3c343a84017ae7a2267dc516b5b6202JesusFreke@JesusFreke.com } 122300ad56aa3c343a84017ae7a2267dc516b5b6202JesusFreke@JesusFreke.com 123c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com while (!instructionsToAnalyze.isEmpty()) { 124c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com for(int i=instructionsToAnalyze.nextSetBit(0); i>=0; i=instructionsToAnalyze.nextSetBit(i+1)) { 125c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com instructionsToAnalyze.clear(i); 126c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com if (verifiedInstructions.get(i)) { 127c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com continue; 128c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com } 129c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com AnalyzedInstruction instructionToVerify = instructions.valueAt(i); 130c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com try { 131c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com analyzeInstruction(instructionToVerify); 132c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com } catch (ValidationException ex) { 133c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com this.validationException = ex; 134c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com int codeAddress = getInstructionAddress(instructionToVerify); 135c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com ex.setCodeAddress(codeAddress); 136c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com ex.addContext(String.format("opcode: %s", instructionToVerify.instruction.opcode.name)); 137c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com ex.addContext(String.format("CodeAddress: %d", codeAddress)); 138c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com ex.addContext(String.format("Method: %s", encodedMethod.method.getMethodString())); 139c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com break; 140c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com } 141c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com 142c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com verifiedInstructions.set(instructionToVerify.getInstructionIndex()); 143c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com 144c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com for (AnalyzedInstruction successor: instructionToVerify.successors) { 145c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com instructionsToAnalyze.set(successor.getInstructionIndex()); 146c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com } 147c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com } 148c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com if (validationException != null) { 149c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com break; 150300ad56aa3c343a84017ae7a2267dc516b5b6202JesusFreke@JesusFreke.com } 151300ad56aa3c343a84017ae7a2267dc516b5b6202JesusFreke@JesusFreke.com } 152300ad56aa3c343a84017ae7a2267dc516b5b6202JesusFreke@JesusFreke.com 153fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com analyzed = true; 154fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return makeInstructionArray(); 155fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 156fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 157fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com private int getThisRegister() { 158fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com assert (encodedMethod.accessFlags & AccessFlags.STATIC.getValue()) == 0; 159fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 160fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com CodeItem codeItem = encodedMethod.codeItem; 161fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com assert codeItem != null; 162fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 163fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com MethodIdItem methodIdItem = encodedMethod.method; 164fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com assert methodIdItem != null; 165fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 166fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com int totalRegisters = codeItem.getRegisterCount(); 167fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (totalRegisters == 0) { 168fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com throw new ValidationException("A non-static method must have at least 1 register"); 169fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 170fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 171fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com int parameterRegisters = methodIdItem.getPrototype().getParameterRegisterCount(); 172fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 173fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return totalRegisters - parameterRegisters - 1; 174fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 175fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 176fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com private boolean isInstanceConstructor() { 177fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return (encodedMethod.accessFlags & AccessFlags.STATIC.getValue()) == 0 && 178fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com (encodedMethod.accessFlags & AccessFlags.CONSTRUCTOR.getValue()) != 0; 179fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 180fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 181fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com private boolean isStaticConstructor() { 182fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return (encodedMethod.accessFlags & AccessFlags.STATIC.getValue()) != 0 && 183fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com (encodedMethod.accessFlags & AccessFlags.CONSTRUCTOR.getValue()) != 0; 184fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 185fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1861c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com public AnalyzedInstruction getStartOfMethod() { 1871c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com return startOfMethod; 1881c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com } 1891c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com 190fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com public AnalyzedInstruction[] makeInstructionArray() { 191fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com AnalyzedInstruction[] instructionArray = new AnalyzedInstruction[instructions.size()]; 192fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com for (int i=0; i<instructions.size(); i++) { 193fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com instructionArray[i] = instructions.valueAt(i); 194fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 195fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return instructionArray; 196fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 197fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 198c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com public ValidationException getValidationException() { 199c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com return validationException; 200c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com } 201c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com 202fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com private static RegisterType[] getParameterTypes(TypeListItem typeListItem, int parameterRegisterCount) { 203fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com assert typeListItem != null; 204fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com assert parameterRegisterCount == typeListItem.getRegisterCount(); 205fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 206fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType[] registerTypes = new RegisterType[parameterRegisterCount]; 207fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 208fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com int registerNum = 0; 209fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com for (TypeIdItem type: typeListItem.getTypes()) { 210fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (type.getRegisterCount() == 2) { 211fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com registerTypes[registerNum++] = RegisterType.getWideRegisterTypeForTypeIdItem(type, true); 212fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com registerTypes[registerNum++] = RegisterType.getWideRegisterTypeForTypeIdItem(type, false); 213fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } else { 214c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com registerTypes[registerNum++] = RegisterType.getRegisterTypeForTypeIdItem(type); 215fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 216fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 217fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 218fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return registerTypes; 219fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 220fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 2211c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com public int getInstructionAddress(AnalyzedInstruction instruction) { 222fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return instructions.keyAt(instruction.instructionIndex); 223fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 224fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 225fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com private void setDestinationRegisterTypeAndPropagateChanges(AnalyzedInstruction analyzedInstruction, 226fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType registerType) { 227fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com setRegisterTypeAndPropagateChanges(analyzedInstruction, analyzedInstruction.getDestinationRegister(), 228fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com registerType); 229fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 230fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 23185e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com private void setRegisterTypeAndPropagateChanges(AnalyzedInstruction analyzedInstruction, int registerNumber, 232fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType registerType) { 233fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 234fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com BitSet changedInstructions = new BitSet(instructions.size()); 235fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 23685e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com boolean changed = analyzedInstruction.setPostRegisterType(registerNumber, registerType); 237fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 2387e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com if (!changed) { 239fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return; 240fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 241fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 24285e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com propagateRegisterToSuccessors(analyzedInstruction, registerNumber, changedInstructions); 243fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 244fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //using a for loop inside the while loop optimizes for the common case of the successors of an instruction 245fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //occurring after the instruction. Any successors that occur prior to the instruction will be picked up on 246fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //the next iteration of the while loop. 247fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //this could also be done recursively, but in large methods it would likely cause very deep recursion, 248fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //which would requires the user to specify a larger stack size. This isn't really a problem, but it is 249fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //slightly annoying. 250fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com while (!changedInstructions.isEmpty()) { 251fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com for (int instructionIndex=changedInstructions.nextSetBit(0); 252fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com instructionIndex>=0; 2537e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com instructionIndex=changedInstructions.nextSetBit(instructionIndex+1)) { 254fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 255fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com changedInstructions.clear(instructionIndex); 256fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 257fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com propagateRegisterToSuccessors(instructions.valueAt(instructionIndex), registerNumber, 258fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com changedInstructions); 259fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 260fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 26185e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com 26285e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com if (registerType.category == RegisterType.Category.LongLo) { 26385e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com checkWidePair(registerNumber, analyzedInstruction); 26485e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com setRegisterTypeAndPropagateChanges(analyzedInstruction, registerNumber+1, 26585e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com RegisterType.getRegisterType(RegisterType.Category.LongHi, null)); 26685e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com } else if (registerType.category == RegisterType.Category.DoubleLo) { 26785e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com checkWidePair(registerNumber, analyzedInstruction); 26885e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com setRegisterTypeAndPropagateChanges(analyzedInstruction, registerNumber+1, 26985e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com RegisterType.getRegisterType(RegisterType.Category.DoubleHi, null)); 27085e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com } 271d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com } 272d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 273fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com private void propagateRegisterToSuccessors(AnalyzedInstruction instruction, int registerNumber, 274fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com BitSet changedInstructions) { 275fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com for (AnalyzedInstruction successor: instruction.successors) { 276fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (!successor.setsRegister(registerNumber)) { 277fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType registerType = successor.getMergedRegisterTypeFromPredecessors(registerNumber); 278fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 2797e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com //TODO: GROT? 2807e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com /*if (registerType.category == RegisterType.Category.UninitRef && instruction.isInvokeInit()) { 28189e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com continue; 2827e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com }*/ 28389e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com 284fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (successor.setPostRegisterType(registerNumber, registerType)) { 285fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com changedInstructions.set(successor.instructionIndex); 286c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com verifiedInstructions.clear(successor.instructionIndex); 287fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 288fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 289fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 290fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 291fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 292fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 293fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 294d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com private void buildInstructionList() { 295d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com assert encodedMethod != null; 296d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com assert encodedMethod.codeItem != null; 297fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com int registerCount = encodedMethod.codeItem.getRegisterCount(); 298d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 299d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com Instruction[] insns = encodedMethod.codeItem.getInstructions(); 300d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 301fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com instructions = new SparseArray<AnalyzedInstruction>(insns.length); 302d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 303d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com //first, create all the instructions and populate the instructionAddresses array 304d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com int currentCodeAddress = 0; 305d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com for (int i=0; i<insns.length; i++) { 306fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com instructions.append(currentCodeAddress, new AnalyzedInstruction(insns[i], i, registerCount)); 307fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com assert instructions.indexOfKey(currentCodeAddress) == i; 308d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com currentCodeAddress += insns[i].getSize(currentCodeAddress); 309d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com } 310d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 311d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com //next, populate the exceptionHandlers array. The array item for each instruction that can throw an exception 312d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com //and is covered by a try block should be set to a list of the first instructions of each exception handler 313d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com //for the try block covering the instruction 314d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com CodeItem.TryItem[] tries = encodedMethod.codeItem.getTries(); 315d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com int triesIndex = 0; 316d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com CodeItem.TryItem currentTry = null; 317fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com AnalyzedInstruction[] currentExceptionHandlers = null; 318fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com AnalyzedInstruction[][] exceptionHandlers = new AnalyzedInstruction[insns.length][]; 319d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 3207e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com if (tries != null) { 3217e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com for (int i=0; i<instructions.size(); i++) { 3227e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com AnalyzedInstruction instruction = instructions.valueAt(i); 3237e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com Opcode instructionOpcode = instruction.instruction.opcode; 324c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com currentCodeAddress = getInstructionAddress(instruction); 325d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 3267e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com //check if we have gone past the end of the current try 3277e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com if (currentTry != null) { 3287e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com if (currentTry.getStartCodeAddress() + currentTry.getTryLength() <= currentCodeAddress) { 3297e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com currentTry = null; 3307e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com triesIndex++; 3317e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com } 332d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com } 333d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 3347e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com //check if the next try is applicable yet 3357e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com if (currentTry == null && triesIndex < tries.length) { 3367e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com CodeItem.TryItem tryItem = tries[triesIndex]; 3377e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com if (tryItem.getStartCodeAddress() <= currentCodeAddress) { 3387e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com assert(tryItem.getStartCodeAddress() + tryItem.getTryLength() > currentCodeAddress); 339d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 3407e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com currentTry = tryItem; 341d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 3427e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com currentExceptionHandlers = buildExceptionHandlerArray(tryItem); 3437e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com } 344d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com } 345d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 3467e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com //if we're inside a try block, and the instruction can throw an exception, then add the exception handlers 3477e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com //for the current instruction 3487e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com if (currentTry != null && instructionOpcode.canThrow()) { 3497e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com exceptionHandlers[i] = currentExceptionHandlers; 3507e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com } 351d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com } 352d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com } 353d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 354d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com //finally, populate the successors and predecessors for each instruction 355fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com assert instructions.size() > 0; 356fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com addPredecessorSuccessor(startOfMethod, instructions.valueAt(0), exceptionHandlers); 357fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com startOfMethod.addSuccessor(instructions.valueAt(0)); 358fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 359fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com for (int i=0; i<instructions.size(); i++) { 360fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com AnalyzedInstruction instruction = instructions.valueAt(i); 361d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com Opcode instructionOpcode = instruction.instruction.opcode; 362fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com int instructionCodeAddress = getInstructionAddress(instruction); 363d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 364d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com if (instruction.instruction.opcode.canContinue()) { 365c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com if (instruction.instruction.opcode != Opcode.NOP || 366c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com !instruction.instruction.getFormat().variableSizeFormat) { 367c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com 368c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com if (i == instructions.size() - 1) { 369c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com throw new ValidationException("Execution can continue past the last instruction"); 370c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com } 371c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com 372c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com AnalyzedInstruction nextInstruction = instructions.valueAt(i+1); 373c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com addPredecessorSuccessor(instruction, nextInstruction, exceptionHandlers); 374d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com } 375d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com } 376d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 3777e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com if (instruction.instruction instanceof OffsetInstruction) { 3787e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com OffsetInstruction offsetInstruction = (OffsetInstruction)instruction.instruction; 379d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 380d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com if (instructionOpcode == Opcode.PACKED_SWITCH || instructionOpcode == Opcode.SPARSE_SWITCH) { 381d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com MultiOffsetInstruction switchDataInstruction = 382fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com (MultiOffsetInstruction)instructions.get(instructionCodeAddress + 383d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com offsetInstruction.getTargetAddressOffset()).instruction; 384d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com for (int targetAddressOffset: switchDataInstruction.getTargets()) { 385fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com AnalyzedInstruction targetInstruction = instructions.get(instructionCodeAddress + 386d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com targetAddressOffset); 387d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 388fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com addPredecessorSuccessor(instruction, targetInstruction, exceptionHandlers); 389d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com } 390d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com } else { 391d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com int targetAddressOffset = offsetInstruction.getTargetAddressOffset(); 392fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com AnalyzedInstruction targetInstruction = instructions.get(instructionCodeAddress + 393fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com targetAddressOffset); 394fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com addPredecessorSuccessor(instruction, targetInstruction, exceptionHandlers); 395d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com } 396d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com } 397d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com } 398d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com } 399d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 400d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com private void addPredecessorSuccessor(AnalyzedInstruction predecessor, AnalyzedInstruction successor, 401fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com AnalyzedInstruction[][] exceptionHandlers) { 402fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com addPredecessorSuccessor(predecessor, successor, exceptionHandlers, false); 403fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 404fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 405fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com private void addPredecessorSuccessor(AnalyzedInstruction predecessor, AnalyzedInstruction successor, 406fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com AnalyzedInstruction[][] exceptionHandlers, boolean allowMoveException) { 407fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 408fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (!allowMoveException && successor.instruction.opcode == Opcode.MOVE_EXCEPTION) { 409fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com throw new ValidationException("Execution can pass from the " + predecessor.instruction.opcode.name + 410fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com " instruction at code address 0x" + Integer.toHexString(getInstructionAddress(predecessor)) + 411fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com " to the move-exception instruction at address 0x" + 412fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com Integer.toHexString(getInstructionAddress(successor))); 413fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 414d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 415d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com if (!predecessor.addSuccessor(successor)) { 416d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com //if predecessor already had successor as a successor, then there's nothing else to do 417d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com return; 418d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com } 419d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 420d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com successor.addPredecessor(predecessor); 421d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 422fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //TODO: need to handle the case of monitor-exit as a special case - the exception is thrown *after* the instruction executes 423d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com //if the successor can throw an instruction, then we need to add the exception handlers as additional 424d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com //successors to the predecessor (and then apply this same logic recursively if needed) 425fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com AnalyzedInstruction[] exceptionHandlersForSuccessor = exceptionHandlers[successor.instructionIndex]; 426d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com if (exceptionHandlersForSuccessor != null) { 427d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com //the item for this instruction in exceptionHandlersForSuccessor should only be set if this instruction 428d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com //can throw an exception 429c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com assert successor.instruction.opcode.canThrow(); 430d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 431fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com for (AnalyzedInstruction exceptionHandler: exceptionHandlersForSuccessor) { 432fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com addPredecessorSuccessor(predecessor, exceptionHandler, exceptionHandlers, true); 433d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com } 434d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com } 435d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com } 436d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 437fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com private AnalyzedInstruction[] buildExceptionHandlerArray(CodeItem.TryItem tryItem) { 438d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com int exceptionHandlerCount = tryItem.encodedCatchHandler.handlers.length; 439d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com int catchAllHandler = tryItem.encodedCatchHandler.getCatchAllHandlerAddress(); 440d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com if (catchAllHandler != -1) { 441d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com exceptionHandlerCount++; 442d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com } 443d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 444fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com AnalyzedInstruction[] exceptionHandlers = new AnalyzedInstruction[exceptionHandlerCount]; 445d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com for (int i=0; i<tryItem.encodedCatchHandler.handlers.length; i++) { 446fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com exceptionHandlers[i] = instructions.get(tryItem.encodedCatchHandler.handlers[i].getHandlerAddress()); 447d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com } 448d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 449d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com if (catchAllHandler != -1) { 450fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com exceptionHandlers[exceptionHandlers.length - 1] = instructions.get(catchAllHandler); 451d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com } 452d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 453d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com return exceptionHandlers; 454d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com } 455d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 456ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com private void analyzeInstruction(AnalyzedInstruction analyzedInstruction) { 457fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com Instruction instruction = analyzedInstruction.instruction; 458fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 459fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com switch (instruction.opcode) { 460fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case NOP: 461ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 462fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case MOVE: 463fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case MOVE_FROM16: 464fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case MOVE_16: 465ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handleMove(analyzedInstruction, Primitive32BitCategories); 466ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 467fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case MOVE_WIDE: 468fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case MOVE_WIDE_FROM16: 469fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case MOVE_WIDE_16: 47085e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com handleMove(analyzedInstruction, WideLowCategories); 471ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 472fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case MOVE_OBJECT: 473fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case MOVE_OBJECT_FROM16: 474fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case MOVE_OBJECT_16: 4757e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com handleMove(analyzedInstruction, ReferenceOrUninitCategories); 476ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 477fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case MOVE_RESULT: 478ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handleMoveResult(analyzedInstruction, Primitive32BitCategories); 479ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 480fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case MOVE_RESULT_WIDE: 481ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handleMoveResult(analyzedInstruction, WideLowCategories); 482ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 483fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case MOVE_RESULT_OBJECT: 484ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handleMoveResult(analyzedInstruction, ReferenceCategories); 485ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 486fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case MOVE_EXCEPTION: 487ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handleMoveException(analyzedInstruction); 488ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 489fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case RETURN_VOID: 490ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handleReturnVoid(analyzedInstruction); 491ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 492fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case RETURN: 49385e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com handleReturn(analyzedInstruction, Primitive32BitCategories); 494ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 495fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case RETURN_WIDE: 49685e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com handleReturn(analyzedInstruction, WideLowCategories); 497ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 498fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case RETURN_OBJECT: 49985e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com handleReturn(analyzedInstruction, ReferenceCategories); 500ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 501fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case CONST_4: 502fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case CONST_16: 503fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case CONST: 504ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handleConst(analyzedInstruction); 505ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 506fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case CONST_HIGH16: 507ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handleConstHigh16(analyzedInstruction); 508ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 509fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case CONST_WIDE_16: 510fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case CONST_WIDE_32: 511fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case CONST_WIDE: 512fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case CONST_WIDE_HIGH16: 513ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handleWideConst(analyzedInstruction); 514ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 515fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case CONST_STRING: 516fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case CONST_STRING_JUMBO: 517ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handleConstString(analyzedInstruction); 518ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 519fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case CONST_CLASS: 520ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handleConstClass(analyzedInstruction); 521ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 522fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case MONITOR_ENTER: 523fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case MONITOR_EXIT: 524ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handleMonitor(analyzedInstruction); 525ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 526fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case CHECK_CAST: 527ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handleCheckCast(analyzedInstruction); 528ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 529fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case INSTANCE_OF: 530ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handleInstanceOf(analyzedInstruction); 531ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 532fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case ARRAY_LENGTH: 533ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handleArrayLength(analyzedInstruction); 534ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 535fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case NEW_INSTANCE: 536ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handleNewInstance(analyzedInstruction); 537ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 538fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case NEW_ARRAY: 539ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handleNewArray(analyzedInstruction); 540ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 5419e5dd85d837501e84e18617fc136c8203ab1f183JesusFreke@JesusFreke.com case FILLED_NEW_ARRAY: 542ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handleFilledNewArray(analyzedInstruction); 543ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 544ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com case FILLED_NEW_ARRAY_RANGE: 545ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handleFilledNewArrayRange(analyzedInstruction); 546ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 547472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com case FILL_ARRAY_DATA: 548ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handleFillArrayData(analyzedInstruction); 549ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 550ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com case THROW: 551ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handleThrow(analyzedInstruction); 552ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 553898edda7cea48c02687bb71804a98cfd6e260b89JesusFreke@JesusFreke.com case GOTO: 554898edda7cea48c02687bb71804a98cfd6e260b89JesusFreke@JesusFreke.com case GOTO_16: 555898edda7cea48c02687bb71804a98cfd6e260b89JesusFreke@JesusFreke.com case GOTO_32: 556898edda7cea48c02687bb71804a98cfd6e260b89JesusFreke@JesusFreke.com //nothing to do 557ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 558cda44f70cfebfae4875cd77455a171075aebac4dJesusFreke@JesusFreke.com case PACKED_SWITCH: 559ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handleSwitch(analyzedInstruction, Format.PackedSwitchData); 560ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 561cda44f70cfebfae4875cd77455a171075aebac4dJesusFreke@JesusFreke.com case SPARSE_SWITCH: 562ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handleSwitch(analyzedInstruction, Format.SparseSwitchData); 563ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 564f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com case CMPL_FLOAT: 565f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com case CMPG_FLOAT: 56685e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com handleFloatWideCmp(analyzedInstruction, Primitive32BitCategories); 567ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 568f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com case CMPL_DOUBLE: 569f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com case CMPG_DOUBLE: 570f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com case CMP_LONG: 57185e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com handleFloatWideCmp(analyzedInstruction, WideLowCategories); 572ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 573aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com case IF_EQ: 574aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com case IF_NE: 575ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handleIfEqNe(analyzedInstruction); 576ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 577150acd9db94f9886f6fc32e89acc15a1a5c1466fJesusFreke@JesusFreke.com case IF_LT: 578150acd9db94f9886f6fc32e89acc15a1a5c1466fJesusFreke@JesusFreke.com case IF_GE: 579150acd9db94f9886f6fc32e89acc15a1a5c1466fJesusFreke@JesusFreke.com case IF_GT: 580150acd9db94f9886f6fc32e89acc15a1a5c1466fJesusFreke@JesusFreke.com case IF_LE: 581ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handleIf(analyzedInstruction); 582ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 583cb00252b6aed86cd3e7c426015cea83fcdbaa806JesusFreke@JesusFreke.com case IF_EQZ: 584cb00252b6aed86cd3e7c426015cea83fcdbaa806JesusFreke@JesusFreke.com case IF_NEZ: 585ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handleIfEqzNez(analyzedInstruction); 586ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 58716a709ba046343bfefc15a6cdb0be38282126223JesusFreke@JesusFreke.com case IF_LTZ: 58816a709ba046343bfefc15a6cdb0be38282126223JesusFreke@JesusFreke.com case IF_GEZ: 58916a709ba046343bfefc15a6cdb0be38282126223JesusFreke@JesusFreke.com case IF_GTZ: 59016a709ba046343bfefc15a6cdb0be38282126223JesusFreke@JesusFreke.com case IF_LEZ: 591ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handleIfz(analyzedInstruction); 592ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 593b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com case AGET: 594ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handle32BitPrimitiveAget(analyzedInstruction, RegisterType.Category.Integer); 595ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 596b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com case AGET_BOOLEAN: 597ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handle32BitPrimitiveAget(analyzedInstruction, RegisterType.Category.Boolean); 598ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 599b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com case AGET_BYTE: 600ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handle32BitPrimitiveAget(analyzedInstruction, RegisterType.Category.Byte); 601ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 602b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com case AGET_CHAR: 603ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handle32BitPrimitiveAget(analyzedInstruction, RegisterType.Category.Char); 604ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 605b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com case AGET_SHORT: 606ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handle32BitPrimitiveAget(analyzedInstruction, RegisterType.Category.Short); 607ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 608c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com case AGET_WIDE: 609ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handleAgetWide(analyzedInstruction); 610ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 611461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com case AGET_OBJECT: 612ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handleAgetObject(analyzedInstruction); 613ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 614c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com case APUT: 615ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handle32BitPrimitiveAput(analyzedInstruction, RegisterType.Category.Integer); 616ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 617c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com case APUT_BOOLEAN: 618ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handle32BitPrimitiveAput(analyzedInstruction, RegisterType.Category.Boolean); 619ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 620c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com case APUT_BYTE: 621ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handle32BitPrimitiveAput(analyzedInstruction, RegisterType.Category.Byte); 622ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 623c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com case APUT_CHAR: 624ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handle32BitPrimitiveAput(analyzedInstruction, RegisterType.Category.Char); 625ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 626c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com case APUT_SHORT: 627ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handle32BitPrimitiveAput(analyzedInstruction, RegisterType.Category.Short); 628ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 62955d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com case APUT_WIDE: 630ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handleAputWide(analyzedInstruction); 631ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 632898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com case APUT_OBJECT: 633ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handleAputObject(analyzedInstruction); 634ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 6354f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com case IGET: 636ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handle32BitPrimitiveIget(analyzedInstruction, RegisterType.Category.Integer); 637ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 6384f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com case IGET_BOOLEAN: 639ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handle32BitPrimitiveIget(analyzedInstruction, RegisterType.Category.Boolean); 640ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 6414f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com case IGET_BYTE: 642ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handle32BitPrimitiveIget(analyzedInstruction, RegisterType.Category.Byte); 643ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 6444f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com case IGET_CHAR: 645ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handle32BitPrimitiveIget(analyzedInstruction, RegisterType.Category.Char); 646ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 6474f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com case IGET_SHORT: 648ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handle32BitPrimitiveIget(analyzedInstruction, RegisterType.Category.Short); 649ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 6509d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com case IGET_WIDE: 651ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handleIgetWide(analyzedInstruction); 652ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 6537a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com case IGET_OBJECT: 654ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handleIgetObject(analyzedInstruction); 655ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 6569971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com case IPUT: 657ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handle32BitPrimitiveIput(analyzedInstruction, RegisterType.Category.Integer); 658ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 6599971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com case IPUT_BOOLEAN: 660ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handle32BitPrimitiveIput(analyzedInstruction, RegisterType.Category.Boolean); 661ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 6629971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com case IPUT_BYTE: 663ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handle32BitPrimitiveIput(analyzedInstruction, RegisterType.Category.Byte); 664ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 6659971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com case IPUT_CHAR: 666ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handle32BitPrimitiveIput(analyzedInstruction, RegisterType.Category.Char); 667ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 6689971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com case IPUT_SHORT: 669ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handle32BitPrimitiveIput(analyzedInstruction, RegisterType.Category.Short); 670ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 67192616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com case IPUT_WIDE: 672ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handleIputWide(analyzedInstruction); 673ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 67450ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com case IPUT_OBJECT: 675ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handleIputObject(analyzedInstruction); 676ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 677052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com case SGET: 678ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handle32BitPrimitiveSget(analyzedInstruction, RegisterType.Category.Integer); 679ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 680052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com case SGET_BOOLEAN: 681ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handle32BitPrimitiveSget(analyzedInstruction, RegisterType.Category.Boolean); 682ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 683052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com case SGET_BYTE: 684ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handle32BitPrimitiveSget(analyzedInstruction, RegisterType.Category.Byte); 685ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 686052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com case SGET_CHAR: 687ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handle32BitPrimitiveSget(analyzedInstruction, RegisterType.Category.Char); 688ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 689052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com case SGET_SHORT: 690ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handle32BitPrimitiveSget(analyzedInstruction, RegisterType.Category.Short); 691ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 6922f233fefd9d73af8fab4037a6f874b161b98b259JesusFreke@JesusFreke.com case SGET_WIDE: 693ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handleSgetWide(analyzedInstruction); 694ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 6952d6d6eb22c86c79344b85ffe46fdd4268566bd0fJesusFreke@JesusFreke.com case SGET_OBJECT: 696ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handleSgetObject(analyzedInstruction); 697ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 6989d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com case SPUT: 699ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handle32BitPrimitiveSput(analyzedInstruction, RegisterType.Category.Integer); 700ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 7019d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com case SPUT_BOOLEAN: 702ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handle32BitPrimitiveSput(analyzedInstruction, RegisterType.Category.Boolean); 703ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 7049d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com case SPUT_BYTE: 705ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handle32BitPrimitiveSput(analyzedInstruction, RegisterType.Category.Byte); 706ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 7079d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com case SPUT_CHAR: 708ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handle32BitPrimitiveSput(analyzedInstruction, RegisterType.Category.Char); 709ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 7109d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com case SPUT_SHORT: 711ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handle32BitPrimitiveSput(analyzedInstruction, RegisterType.Category.Short); 712ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 713f08a9e1c2c130a5ed5923999fec0283f91b48a09JesusFreke@JesusFreke.com case SPUT_WIDE: 714ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handleSputWide(analyzedInstruction); 715ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 71651cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com case SPUT_OBJECT: 717ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handleSputObject(analyzedInstruction); 718ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 71989e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com case INVOKE_VIRTUAL: 720ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handleInvoke(analyzedInstruction, INVOKE_VIRTUAL); 721ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 72289e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com case INVOKE_SUPER: 723ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handleInvoke(analyzedInstruction, INVOKE_SUPER); 724ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 72589e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com case INVOKE_DIRECT: 726ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handleInvoke(analyzedInstruction, INVOKE_DIRECT); 727ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 72889e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com case INVOKE_STATIC: 729ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handleInvoke(analyzedInstruction, INVOKE_STATIC); 730ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 73189e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com case INVOKE_INTERFACE: 732ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handleInvoke(analyzedInstruction, INVOKE_INTERFACE); 733ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 73489e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com case INVOKE_VIRTUAL_RANGE: 735ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handleInvokeRange(analyzedInstruction, INVOKE_VIRTUAL); 736ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 73789e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com case INVOKE_SUPER_RANGE: 738ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handleInvokeRange(analyzedInstruction, INVOKE_SUPER); 739ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 74089e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com case INVOKE_DIRECT_RANGE: 741ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handleInvokeRange(analyzedInstruction, INVOKE_DIRECT); 742ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 74389e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com case INVOKE_STATIC_RANGE: 744ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handleInvokeRange(analyzedInstruction, INVOKE_STATIC); 745ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 74689e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com case INVOKE_INTERFACE_RANGE: 747ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handleInvokeRange(analyzedInstruction, INVOKE_INTERFACE); 748ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 7491483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com case NEG_INT: 7501483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com case NOT_INT: 7511483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com handleUnaryOp(analyzedInstruction, Primitive32BitCategories, RegisterType.Category.Integer); 7521483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com return; 7531483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com case NEG_LONG: 7541483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com case NOT_LONG: 7551483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com handleUnaryOp(analyzedInstruction, WideLowCategories, RegisterType.Category.LongLo); 7561483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com return; 7571483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com case NEG_FLOAT: 7581483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com handleUnaryOp(analyzedInstruction, Primitive32BitCategories, RegisterType.Category.Float); 7591483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com return; 7601483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com case NEG_DOUBLE: 7611483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com handleUnaryOp(analyzedInstruction, WideLowCategories, RegisterType.Category.DoubleLo); 7621483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com return; 7631483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com case INT_TO_LONG: 7641483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com handleUnaryOp(analyzedInstruction, Primitive32BitCategories, RegisterType.Category.LongLo); 7651483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com return; 7661483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com case INT_TO_FLOAT: 7671483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com handleUnaryOp(analyzedInstruction, Primitive32BitCategories, RegisterType.Category.Float); 7681483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com return; 7691483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com case INT_TO_DOUBLE: 7701483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com handleUnaryOp(analyzedInstruction, Primitive32BitCategories, RegisterType.Category.DoubleLo); 7711483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com return; 7721483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com case LONG_TO_INT: 7731483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com case DOUBLE_TO_INT: 7741483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com handleUnaryOp(analyzedInstruction, WideLowCategories, RegisterType.Category.Integer); 7751483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com return; 7761483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com case LONG_TO_FLOAT: 7771483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com case DOUBLE_TO_FLOAT: 7781483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com handleUnaryOp(analyzedInstruction, WideLowCategories, RegisterType.Category.Float); 7791483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com return; 7801483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com case LONG_TO_DOUBLE: 7811483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com handleUnaryOp(analyzedInstruction, WideLowCategories, RegisterType.Category.DoubleLo); 7821483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com return; 7831483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com case FLOAT_TO_INT: 7841483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com handleUnaryOp(analyzedInstruction, Primitive32BitCategories, RegisterType.Category.Integer); 7851483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com return; 7861483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com case FLOAT_TO_LONG: 7871483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com handleUnaryOp(analyzedInstruction, Primitive32BitCategories, RegisterType.Category.LongLo); 7881483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com return; 7891483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com case FLOAT_TO_DOUBLE: 7901483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com handleUnaryOp(analyzedInstruction, Primitive32BitCategories, RegisterType.Category.DoubleLo); 7911483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com return; 7921483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com case DOUBLE_TO_LONG: 7931483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com handleUnaryOp(analyzedInstruction, WideLowCategories, RegisterType.Category.LongLo); 7941483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com return; 7951483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com case INT_TO_BYTE: 7961483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com handleUnaryOp(analyzedInstruction, Primitive32BitCategories, RegisterType.Category.Byte); 7971483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com return; 7981483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com case INT_TO_CHAR: 7991483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com handleUnaryOp(analyzedInstruction, Primitive32BitCategories, RegisterType.Category.Char); 8001483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com return; 8011483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com case INT_TO_SHORT: 8021483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com handleUnaryOp(analyzedInstruction, Primitive32BitCategories, RegisterType.Category.Short); 8031483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com return; 804195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com case ADD_INT: 805195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com case SUB_INT: 806195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com case MUL_INT: 807195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com case DIV_INT: 808195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com case REM_INT: 809195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com case SHL_INT: 810195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com case SHR_INT: 811195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com case USHR_INT: 812195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com handleBinaryOp(analyzedInstruction, Primitive32BitCategories, Primitive32BitCategories, 813195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com RegisterType.Category.Integer, false); 814195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com return; 815195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com case AND_INT: 816195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com case OR_INT: 817195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com case XOR_INT: 818195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com handleBinaryOp(analyzedInstruction, Primitive32BitCategories, Primitive32BitCategories, 819195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com RegisterType.Category.Integer, true); 820c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com return; 821195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com case ADD_LONG: 822195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com case SUB_LONG: 823195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com case MUL_LONG: 824195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com case DIV_LONG: 825195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com case REM_LONG: 826195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com case AND_LONG: 827195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com case OR_LONG: 828195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com case XOR_LONG: 829195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com handleBinaryOp(analyzedInstruction, WideLowCategories, WideLowCategories, RegisterType.Category.LongLo, 830195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com false); 831195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com return; 832195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com case SHL_LONG: 833195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com case SHR_LONG: 834195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com case USHR_LONG: 835195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com handleBinaryOp(analyzedInstruction, WideLowCategories, Primitive32BitCategories, 836195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com RegisterType.Category.LongLo, false); 837195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com return; 838195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com case ADD_FLOAT: 839195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com case SUB_FLOAT: 840195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com case MUL_FLOAT: 841195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com case DIV_FLOAT: 842195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com case REM_FLOAT: 843195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com handleBinaryOp(analyzedInstruction, Primitive32BitCategories, Primitive32BitCategories, 844195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com RegisterType.Category.Float, false); 845195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com return; 846195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com case ADD_DOUBLE: 847195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com case SUB_DOUBLE: 848195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com case MUL_DOUBLE: 849195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com case DIV_DOUBLE: 850195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com case REM_DOUBLE: 851195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com handleBinaryOp(analyzedInstruction, WideLowCategories, WideLowCategories, 852195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com RegisterType.Category.DoubleLo, false); 853195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com return; 854122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com case ADD_INT_2ADDR: 855122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com case SUB_INT_2ADDR: 856122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com case MUL_INT_2ADDR: 857122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com case DIV_INT_2ADDR: 858122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com case REM_INT_2ADDR: 859122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com case SHL_INT_2ADDR: 860122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com case SHR_INT_2ADDR: 861122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com case USHR_INT_2ADDR: 862122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com handleBinary2AddrOp(analyzedInstruction, Primitive32BitCategories, Primitive32BitCategories, 863122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com RegisterType.Category.Integer, false); 864122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com return; 865122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com case AND_INT_2ADDR: 866122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com case OR_INT_2ADDR: 867122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com case XOR_INT_2ADDR: 868122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com handleBinary2AddrOp(analyzedInstruction, Primitive32BitCategories, Primitive32BitCategories, 869122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com RegisterType.Category.Integer, true); 870122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com return; 871122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com case ADD_LONG_2ADDR: 872122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com case SUB_LONG_2ADDR: 873122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com case MUL_LONG_2ADDR: 874122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com case DIV_LONG_2ADDR: 875122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com case REM_LONG_2ADDR: 876122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com case AND_LONG_2ADDR: 877122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com case OR_LONG_2ADDR: 878122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com case XOR_LONG_2ADDR: 879122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com handleBinary2AddrOp(analyzedInstruction, WideLowCategories, WideLowCategories, 880122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com RegisterType.Category.LongLo, false); 881122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com return; 882122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com case SHL_LONG_2ADDR: 883122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com case SHR_LONG_2ADDR: 884122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com case USHR_LONG_2ADDR: 885122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com handleBinary2AddrOp(analyzedInstruction, WideLowCategories, Primitive32BitCategories, 886122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com RegisterType.Category.LongLo, false); 887122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com return; 888122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com case ADD_FLOAT_2ADDR: 889122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com case SUB_FLOAT_2ADDR: 890122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com case MUL_FLOAT_2ADDR: 891122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com case DIV_FLOAT_2ADDR: 892122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com case REM_FLOAT_2ADDR: 893122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com handleBinary2AddrOp(analyzedInstruction, Primitive32BitCategories, Primitive32BitCategories, 894122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com RegisterType.Category.Float, false); 895122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com return; 896122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com case ADD_DOUBLE_2ADDR: 897122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com case SUB_DOUBLE_2ADDR: 898122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com case MUL_DOUBLE_2ADDR: 899122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com case DIV_DOUBLE_2ADDR: 900122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com case REM_DOUBLE_2ADDR: 901122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com handleBinary2AddrOp(analyzedInstruction, WideLowCategories, WideLowCategories, 902122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com RegisterType.Category.DoubleLo, false); 903122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com return; 904caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com case ADD_INT_LIT16: 905caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com case RSUB_INT: 906caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com case MUL_INT_LIT16: 907caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com case DIV_INT_LIT16: 908caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com case REM_INT_LIT16: 909caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com handleLiteralBinaryOp(analyzedInstruction, Primitive32BitCategories, RegisterType.Category.Integer, 910caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com false); 911caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com return; 912caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com case AND_INT_LIT16: 913caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com case OR_INT_LIT16: 914caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com case XOR_INT_LIT16: 915caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com handleLiteralBinaryOp(analyzedInstruction, Primitive32BitCategories, RegisterType.Category.Integer, 916caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com true); 917caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com return; 918caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com case ADD_INT_LIT8: 919caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com case RSUB_INT_LIT8: 920caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com case MUL_INT_LIT8: 921caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com case DIV_INT_LIT8: 922caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com case REM_INT_LIT8: 923caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com case SHL_INT_LIT8: 924caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com handleLiteralBinaryOp(analyzedInstruction, Primitive32BitCategories, RegisterType.Category.Integer, 925caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com false); 926caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com return; 927caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com case AND_INT_LIT8: 928caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com case OR_INT_LIT8: 929caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com case XOR_INT_LIT8: 930caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com handleLiteralBinaryOp(analyzedInstruction, Primitive32BitCategories, RegisterType.Category.Integer, 931caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com true); 932caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com return; 933caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com case SHR_INT_LIT8: 934caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com handleLiteralBinaryOp(analyzedInstruction, Primitive32BitCategories, 935caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com getDestTypeForLiteralShiftRight(analyzedInstruction, true), false); 936caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com return; 937caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com case USHR_INT_LIT8: 938caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com handleLiteralBinaryOp(analyzedInstruction, Primitive32BitCategories, 939caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com getDestTypeForLiteralShiftRight(analyzedInstruction, false), false); 940caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com return; 941caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com default: 942caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com assert false; 943fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 944fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 945fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 946fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com private static final EnumSet<RegisterType.Category> Primitive32BitCategories = EnumSet.of( 947fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType.Category.Null, 9487e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com RegisterType.Category.One, 949fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType.Category.Boolean, 950fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType.Category.Byte, 9517e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com RegisterType.Category.PosByte, 952fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType.Category.Short, 9537e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com RegisterType.Category.PosShort, 954fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType.Category.Char, 955fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType.Category.Integer, 956fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType.Category.Float); 957fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 958fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com private static final EnumSet<RegisterType.Category> WideLowCategories = EnumSet.of( 959fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType.Category.LongLo, 960fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType.Category.DoubleLo); 961fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 962fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com private static final EnumSet<RegisterType.Category> WideHighCategories = EnumSet.of( 963fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType.Category.LongHi, 964fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType.Category.DoubleHi); 965fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 966fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com private static final EnumSet<RegisterType.Category> ReferenceCategories = EnumSet.of( 967fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType.Category.Null, 968fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType.Category.Reference); 969fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 970c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com private static final EnumSet<RegisterType.Category> ReferenceOrUninitThisCategories = EnumSet.of( 971c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com RegisterType.Category.Null, 972c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com RegisterType.Category.UninitThis, 973c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com RegisterType.Category.Reference); 974c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com 9757e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com private static final EnumSet<RegisterType.Category> ReferenceOrUninitCategories = EnumSet.of( 9767e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com RegisterType.Category.Null, 9777e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com RegisterType.Category.UninitRef, 978c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com RegisterType.Category.UninitThis, 9797e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com RegisterType.Category.Reference); 9807e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com 98185e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com private static final EnumSet<RegisterType.Category> ReferenceAndPrimitive32BitCategories = EnumSet.of( 98285e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com RegisterType.Category.Null, 9837e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com RegisterType.Category.One, 98485e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com RegisterType.Category.Boolean, 98585e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com RegisterType.Category.Byte, 9867e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com RegisterType.Category.PosByte, 98785e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com RegisterType.Category.Short, 9887e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com RegisterType.Category.PosShort, 98985e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com RegisterType.Category.Char, 99085e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com RegisterType.Category.Integer, 99185e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com RegisterType.Category.Float, 99285e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com RegisterType.Category.Reference); 993fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 994195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com private static final EnumSet<RegisterType.Category> BooleanCategories = EnumSet.of( 995195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com RegisterType.Category.Null, 996195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com RegisterType.Category.One, 997195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com RegisterType.Category.Boolean); 998fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 99985e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com private void handleMove(AnalyzedInstruction analyzedInstruction, EnumSet validCategories) { 1000fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com TwoRegisterInstruction instruction = (TwoRegisterInstruction)analyzedInstruction.instruction; 1001fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 100285e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com RegisterType sourceRegisterType = getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterB(), 100385e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com validCategories); 1004fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1005fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, sourceRegisterType); 1006fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 1007fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1008ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com private void handleMoveResult(AnalyzedInstruction analyzedInstruction, 1009fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com EnumSet<RegisterType.Category> allowedCategories) { 1010fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1011fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //TODO: handle the case when the previous instruction is an odexed instruction 1012fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1013fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (analyzedInstruction.instructionIndex == 0) { 1014fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com throw new ValidationException(analyzedInstruction.instruction.opcode.name + " cannot be the first " + 1015fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com "instruction in a method. It must occur after an invoke-*/fill-new-array instruction"); 1016fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 1017fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1018fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com AnalyzedInstruction previousInstruction = instructions.valueAt(analyzedInstruction.instructionIndex-1); 1019fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1020fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (!previousInstruction.instruction.opcode.setsResult()) { 1021fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com throw new ValidationException(analyzedInstruction.instruction.opcode.name + " must occur after an " + 1022fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com "invoke-*/fill-new-array instruction"); 1023fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 1024fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1025fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //TODO: does dalvik allow a move-result after an invoke with a void return type? 102685e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com RegisterType resultRegisterType; 1027fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1028fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com InstructionWithReference invokeInstruction = (InstructionWithReference)previousInstruction.instruction; 1029fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com Item item = invokeInstruction.getReferencedItem(); 1030fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1031fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (item instanceof MethodIdItem) { 103285e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com resultRegisterType = RegisterType.getRegisterTypeForTypeIdItem( 1033fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com ((MethodIdItem)item).getPrototype().getReturnType()); 1034fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } else { 1035fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com assert item instanceof TypeIdItem; 103685e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com resultRegisterType = RegisterType.getRegisterTypeForTypeIdItem((TypeIdItem)item); 103785e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com } 103885e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com 103985e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com if (!allowedCategories.contains(resultRegisterType.category)) { 104085e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com throw new ValidationException(String.format("Wrong move-result* instruction for return value %s", 104185e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com resultRegisterType.toString())); 1042fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 1043fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 104485e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, resultRegisterType); 1045fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 1046fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1047ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com private void handleMoveException(AnalyzedInstruction analyzedInstruction) { 1048fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com CodeItem.TryItem[] tries = encodedMethod.codeItem.getTries(); 1049fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com int instructionAddress = getInstructionAddress(analyzedInstruction); 1050fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1051fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (tries == null) { 1052fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com throw new ValidationException("move-exception must be the first instruction in an exception handler block"); 1053fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 1054fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1055fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType exceptionType = null; 1056fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1057fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com for (CodeItem.TryItem tryItem: encodedMethod.codeItem.getTries()) { 1058fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (tryItem.encodedCatchHandler.getCatchAllHandlerAddress() == instructionAddress) { 1059fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com exceptionType = RegisterType.getRegisterType(RegisterType.Category.Reference, 1060fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com ClassPath.getClassDef("Ljava/lang/Throwable;")); 1061fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com break; 1062fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 1063fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com for (CodeItem.EncodedTypeAddrPair handler: tryItem.encodedCatchHandler.handlers) { 1064fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (handler.getHandlerAddress() == instructionAddress) { 1065fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com exceptionType = RegisterType.getRegisterTypeForTypeIdItem(handler.exceptionType) 1066fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com .merge(exceptionType); 1067fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 1068fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 1069fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 1070fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 107185e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com if (exceptionType == null) { 107285e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com throw new ValidationException("move-exception must be the first instruction in an exception handler block"); 107385e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com } 107485e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com 1075fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //TODO: check if the type is a throwable. Should we throw a ValidationException or print a warning? (does dalvik validate that it's a throwable? It doesn't in CodeVerify.c, but it might check in DexSwapVerify.c) 107685e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com if (exceptionType.category != RegisterType.Category.Reference) { 107785e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com throw new ValidationException(String.format("Exception type %s is not a reference type", 107885e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com exceptionType.toString())); 107985e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com } 108085e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com 1081fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, exceptionType); 1082fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 1083fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1084c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com //TODO: GROT 1085c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com /*private void checkConstructorReturn(AnalyzedInstruction analyzedInstruction) { 1086fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com assert this.isInstanceConstructor(); 1087fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1088fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //if we're in an instance constructor (an <init> method), then the superclass <init> must have been called. 1089fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //When execution enters the method, the "this" register is set as an uninitialized reference to the containing 1090fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //class. Once the superclass' <init> is called, the "this" register is upgraded to a full-blown reference type, 1091fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //so we need to ensure that the "this" register isn't an uninitialized reference 1092fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1093fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com int thisRegister = getThisRegister(); 1094fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType thisRegisterType = analyzedInstruction.postRegisterMap[thisRegister]; 1095fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1096fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (thisRegisterType.category == RegisterType.Category.UninitRef) { 1097fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com throw new ValidationException("Returning from constructor without calling the superclass' <init>"); 1098fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 10997e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com //TODO: GROT 11007e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com //assert thisRegisterType.category == RegisterType.Category.Reference; 11017e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com //assert thisRegisterType.type == ClassPath.getClassDef(encodedMethod.method.getContainingClass()); 1102c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com }*/ 1103fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1104ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com private void handleReturnVoid(AnalyzedInstruction analyzedInstruction) { 1105c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com /*if (this.isInstanceConstructor()) { 1106ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com checkConstructorReturn(analyzedInstruction); 1107c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com }*/ 1108fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1109fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com TypeIdItem returnType = encodedMethod.method.getPrototype().getReturnType(); 1110fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (returnType.getTypeDescriptor().charAt(0) != 'V') { 1111fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //TODO: could add which return-* variation should be used instead 1112fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com throw new ValidationException("Cannot use return-void with a non-void return type (" + 1113fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com returnType.getTypeDescriptor() + ")"); 1114fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 1115fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 1116fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 111785e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com private void handleReturn(AnalyzedInstruction analyzedInstruction, EnumSet validCategories) { 1118c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com /*if (this.isInstanceConstructor()) { 1119ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com checkConstructorReturn(analyzedInstruction); 1120c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com }*/ 1121fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1122fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com SingleRegisterInstruction instruction = (SingleRegisterInstruction)analyzedInstruction.instruction; 112385e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com int returnRegister = instruction.getRegisterA(); 112485e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com RegisterType returnRegisterType = getAndCheckSourceRegister(analyzedInstruction, returnRegister, 112585e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com validCategories); 1126fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1127fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com TypeIdItem returnType = encodedMethod.method.getPrototype().getReturnType(); 1128fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (returnType.getTypeDescriptor().charAt(0) == 'V') { 1129fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com throw new ValidationException("Cannot use return with a void return type. Use return-void instead"); 1130fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 1131fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 113285e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com RegisterType methodReturnRegisterType = RegisterType.getRegisterTypeForTypeIdItem(returnType); 1133fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 113485e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com if (!validCategories.contains(methodReturnRegisterType.category)) { 1135fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //TODO: could add which return-* variation should be used instead 113685e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use %s with return type %s", 113785e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com analyzedInstruction.instruction.opcode.name, returnType.getTypeDescriptor())); 1138fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 1139fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 114085e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com if (validCategories == ReferenceCategories) { 114185e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com if (methodReturnRegisterType.type.isInterface()) { 1142c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com if (returnRegisterType.category != RegisterType.Category.Null && 1143c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com !returnRegisterType.type.implementsInterface(methodReturnRegisterType.type)) { 114485e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com //TODO: how to handle warnings? 114585e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com } 114685e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com } else { 1147c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com if (returnRegisterType.category == RegisterType.Category.Reference && 1148c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com !returnRegisterType.type.extendsClass(methodReturnRegisterType.type)) { 1149c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com 115085e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com throw new ValidationException(String.format("The return value in register v%d (%s) is not " + 115185e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com "compatible with the method's return type %s", returnRegister, 115285e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com returnRegisterType.type.getClassType(), methodReturnRegisterType.type.getClassType())); 115385e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com } 1154fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 1155fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 1156fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 1157fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1158ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com private void handleConst(AnalyzedInstruction analyzedInstruction) { 1159fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com LiteralInstruction instruction = (LiteralInstruction)analyzedInstruction.instruction; 1160fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1161fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType newDestinationRegisterType = RegisterType.getRegisterTypeForLiteral(instruction.getLiteral()); 1162fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1163fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //we assume that the literal value is a valid value for the given instruction type, because it's impossible 1164fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //to store an invalid literal with the instruction. so we don't need to check the type of the literal 1165fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, newDestinationRegisterType); 1166fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 1167fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1168ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com private void handleConstHigh16(AnalyzedInstruction analyzedInstruction) { 1169fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com LiteralInstruction instruction = (LiteralInstruction)analyzedInstruction.instruction; 1170fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1171fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //TODO: test this 1172fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com long literalValue = instruction.getLiteral() << 16; 1173fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType newDestinationRegisterType = RegisterType.getRegisterTypeForLiteral(literalValue); 1174fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1175fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //we assume that the literal value is a valid value for the given instruction type, because it's impossible 1176fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //to store an invalid literal with the instruction. so we don't need to check the type of the literal 1177fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, newDestinationRegisterType); 1178fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 1179fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1180ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com private void handleWideConst(AnalyzedInstruction analyzedInstruction) { 118185e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, 1182fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType.getRegisterType(RegisterType.Category.LongLo, null)); 1183fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 1184fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1185ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com private void handleConstString(AnalyzedInstruction analyzedInstruction) { 1186fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com ClassPath.ClassDef stringClassDef = ClassPath.getClassDef("Ljava/lang/String;"); 1187fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType stringType = RegisterType.getRegisterType(RegisterType.Category.Reference, stringClassDef); 1188fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, stringType); 1189fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 1190fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1191ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com private void handleConstClass(AnalyzedInstruction analyzedInstruction) { 1192fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com ClassPath.ClassDef classClassDef = ClassPath.getClassDef("Ljava/lang/Class;"); 1193fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType classType = RegisterType.getRegisterType(RegisterType.Category.Reference, classClassDef); 1194fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1195fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com InstructionWithReference instruction = (InstructionWithReference)analyzedInstruction.instruction; 1196fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com Item item = instruction.getReferencedItem(); 1197fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com assert item.getItemType() == ItemType.TYPE_TYPE_ID_ITEM; 1198fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1199fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //TODO: need to check class access 1200c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com //make sure the referenced class is resolvable 1201c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com ClassPath.getClassDef((TypeIdItem)item); 1202c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com 1203c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, classType); 1204fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 1205fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1206ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com private void handleMonitor(AnalyzedInstruction analyzedInstruction) { 120785e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com SingleRegisterInstruction instruction = (SingleRegisterInstruction)analyzedInstruction.instruction; 120885e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterA(), ReferenceCategories); 1209fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 1210fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1211ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com private void handleCheckCast(AnalyzedInstruction analyzedInstruction) { 1212fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com { 1213fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //ensure the "source" register is a reference type 1214fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com SingleRegisterInstruction instruction = (SingleRegisterInstruction)analyzedInstruction.instruction; 1215fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 121685e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com RegisterType registerType = getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterA(), 121785e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com ReferenceCategories); 1218fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 1219fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1220fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com { 1221fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //resolve and verify the class that we're casting to 1222fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com InstructionWithReference instruction = (InstructionWithReference)analyzedInstruction.instruction; 1223fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1224fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com Item item = instruction.getReferencedItem(); 1225fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com assert item.getItemType() == ItemType.TYPE_TYPE_ID_ITEM; 1226fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1227fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //TODO: need to check class access 122885e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com RegisterType castRegisterType = RegisterType.getRegisterTypeForTypeIdItem((TypeIdItem)item); 122985e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com if (castRegisterType.category != RegisterType.Category.Reference) { 1230fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //TODO: verify that dalvik allows a non-reference type.. 1231fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //TODO: print a warning, but don't re-throw the exception. dalvik allows a non-reference type during validation (but throws an exception at runtime) 1232fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 1233fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 123485e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, castRegisterType); 1235fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 1236fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 1237fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1238ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com private void handleInstanceOf(AnalyzedInstruction analyzedInstruction) { 1239fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com { 1240fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //ensure the register that is being checks is a reference type 124185e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com TwoRegisterInstruction instruction = (TwoRegisterInstruction)analyzedInstruction.instruction; 1242fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 124385e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterB(), ReferenceCategories); 1244fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 1245fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1246fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com { 1247fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //resolve and verify the class that we're checking against 1248fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com InstructionWithReference instruction = (InstructionWithReference)analyzedInstruction.instruction; 1249fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1250fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com Item item = instruction.getReferencedItem(); 1251fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com assert item.getItemType() == ItemType.TYPE_TYPE_ID_ITEM; 1252fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType registerType = RegisterType.getRegisterTypeForTypeIdItem((TypeIdItem)item); 125385e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com if (registerType.category != RegisterType.Category.Reference) { 125485e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use instance-of with a non-reference type %s", 125585e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com registerType.toString())); 125685e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com } 1257fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1258fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //TODO: is it valid to use an array type? 1259fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1260fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //TODO: could probably do an even more sophisticated check, where we check the possible register types against the specified type. In some cases, we could determine that it always fails, and print a warning to that effect. 1261fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, 1262fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType.getRegisterType(RegisterType.Category.Boolean, null)); 1263fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 1264fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 1265fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1266ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com private void handleArrayLength(AnalyzedInstruction analyzedInstruction) { 126785e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com TwoRegisterInstruction instruction = (TwoRegisterInstruction)analyzedInstruction.instruction; 1268fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1269fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com int arrayRegisterNumber = instruction.getRegisterB(); 127085e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com RegisterType arrayRegisterType = getAndCheckSourceRegister(analyzedInstruction, arrayRegisterNumber, 127185e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com ReferenceCategories); 1272fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1273fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (arrayRegisterType.type != null) { 1274fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (arrayRegisterType.type.getClassType().charAt(0) != '[') { 127585e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use array-length with non-array type %s", 127685e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com arrayRegisterType.type.getClassType())); 1277d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com } 1278c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com assert arrayRegisterType.type instanceof ClassPath.ArrayClassDef; 1279d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com } 1280d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 1281fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, 1282fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType.getRegisterType(RegisterType.Category.Integer, null)); 1283fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 1284fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1285ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com private void handleNewInstance(AnalyzedInstruction analyzedInstruction) { 1286fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com InstructionWithReference instruction = (InstructionWithReference)analyzedInstruction.instruction; 1287fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1288a0314c265e76426e3e05e615cc713cf36c78cb85JesusFreke@JesusFreke.com int register = ((SingleRegisterInstruction)analyzedInstruction.instruction).getRegisterA(); 1289a0314c265e76426e3e05e615cc713cf36c78cb85JesusFreke@JesusFreke.com RegisterType destRegisterType = analyzedInstruction.postRegisterMap[register]; 1290a0314c265e76426e3e05e615cc713cf36c78cb85JesusFreke@JesusFreke.com if (destRegisterType.category != RegisterType.Category.Unknown) { 1291a0314c265e76426e3e05e615cc713cf36c78cb85JesusFreke@JesusFreke.com assert destRegisterType.category == RegisterType.Category.UninitRef; 1292a0314c265e76426e3e05e615cc713cf36c78cb85JesusFreke@JesusFreke.com 1293a0314c265e76426e3e05e615cc713cf36c78cb85JesusFreke@JesusFreke.com //the "post-instruction" destination register will only be set if we've gone over 1294a0314c265e76426e3e05e615cc713cf36c78cb85JesusFreke@JesusFreke.com //this instruction at least once before. If this is the case, then we need to check 1295a0314c265e76426e3e05e615cc713cf36c78cb85JesusFreke@JesusFreke.com //all the other registers, and make sure that none of them contain the same 1296a0314c265e76426e3e05e615cc713cf36c78cb85JesusFreke@JesusFreke.com //uninitialized reference that is in the destination register. 1297a0314c265e76426e3e05e615cc713cf36c78cb85JesusFreke@JesusFreke.com 1298a0314c265e76426e3e05e615cc713cf36c78cb85JesusFreke@JesusFreke.com for (int i=0; i<analyzedInstruction.postRegisterMap.length; i++) { 1299a0314c265e76426e3e05e615cc713cf36c78cb85JesusFreke@JesusFreke.com if (i==register) { 1300a0314c265e76426e3e05e615cc713cf36c78cb85JesusFreke@JesusFreke.com continue; 1301a0314c265e76426e3e05e615cc713cf36c78cb85JesusFreke@JesusFreke.com } 1302a0314c265e76426e3e05e615cc713cf36c78cb85JesusFreke@JesusFreke.com 1303a0314c265e76426e3e05e615cc713cf36c78cb85JesusFreke@JesusFreke.com if (analyzedInstruction.getPreInstructionRegisterType(i) == destRegisterType) { 1304a0314c265e76426e3e05e615cc713cf36c78cb85JesusFreke@JesusFreke.com throw new ValidationException(String.format("Register v%d contains an uninitialized reference " + 1305a0314c265e76426e3e05e615cc713cf36c78cb85JesusFreke@JesusFreke.com "that was created by this new-instance instruction.", i)); 1306a0314c265e76426e3e05e615cc713cf36c78cb85JesusFreke@JesusFreke.com } 1307a0314c265e76426e3e05e615cc713cf36c78cb85JesusFreke@JesusFreke.com } 1308c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com 1309c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com return; 1310a0314c265e76426e3e05e615cc713cf36c78cb85JesusFreke@JesusFreke.com } 1311a0314c265e76426e3e05e615cc713cf36c78cb85JesusFreke@JesusFreke.com 1312fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com Item item = instruction.getReferencedItem(); 1313fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com assert item.getItemType() == ItemType.TYPE_TYPE_ID_ITEM; 1314fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1315fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //TODO: need to check class access 1316fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType classType = RegisterType.getRegisterTypeForTypeIdItem((TypeIdItem)item); 131785e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com if (classType.category != RegisterType.Category.Reference) { 131885e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use new-instance with a non-reference type %s", 131985e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com classType.toString())); 132085e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com } 132185e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com 1322fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (((TypeIdItem)item).getTypeDescriptor().charAt(0) == '[') { 1323fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com throw new ValidationException("Cannot use array type \"" + ((TypeIdItem)item).getTypeDescriptor() + 1324fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com "\" with new-instance. Use new-array instead."); 1325d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com } 1326d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 1327fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, 1328a0314c265e76426e3e05e615cc713cf36c78cb85JesusFreke@JesusFreke.com RegisterType.getUnitializedReference(classType.type)); 1329fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 1330fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1331ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com private void handleNewArray(AnalyzedInstruction analyzedInstruction) { 1332fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com { 1333fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com TwoRegisterInstruction instruction = (TwoRegisterInstruction)analyzedInstruction.instruction; 133485e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterB(), Primitive32BitCategories); 1335fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 1336fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1337fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com InstructionWithReference instruction = (InstructionWithReference)analyzedInstruction.instruction; 1338fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1339fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com Item item = instruction.getReferencedItem(); 1340fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com assert item.getItemType() == ItemType.TYPE_TYPE_ID_ITEM; 1341fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1342fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType arrayType = RegisterType.getRegisterTypeForTypeIdItem((TypeIdItem)item); 1343fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com assert arrayType.type instanceof ClassPath.ArrayClassDef; 1344d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 134585e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com if (arrayType.category != RegisterType.Category.Reference) { 134685e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use new-array with a non-reference type %s", 134785e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com arrayType.toString())); 134885e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com } 1349fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (arrayType.type.getClassType().charAt(0) != '[') { 1350fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com throw new ValidationException("Cannot use non-array type \"" + arrayType.type.getClassType() + 1351fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com "\" with new-array. Use new-instance instead."); 1352fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 1353fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1354fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, arrayType); 1355fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 1356fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1357ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com private static interface RegisterIterator { 1358ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com int getRegister(); 1359ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com boolean moveNext(); 136006d1aacf61792afcdb273cf458e1e3daead0cf85JesusFreke@JesusFreke.com int getCount(); 13616192896f88638177ab6a5e64535f834f4a08b726JesusFreke@JesusFreke.com boolean pastEnd(); 1362ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com } 1363ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com 1364b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com private static class Format35cRegisterIterator implements RegisterIterator { 1365b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com private final int registerCount; 1366b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com private final int[] registers; 1367b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com private int currentRegister = 0; 1368b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com 1369b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com public Format35cRegisterIterator(FiveRegisterInstruction instruction) { 1370b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com registerCount = instruction.getRegCount(); 1371b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com registers = new int[]{instruction.getRegisterD(), instruction.getRegisterE(), 1372b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com instruction.getRegisterF(), instruction.getRegisterG(), 1373b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com instruction.getRegisterA()}; 1374b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com } 1375b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com 1376b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com public int getRegister() { 1377b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com return registers[currentRegister]; 1378b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com } 1379b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com 1380b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com public boolean moveNext() { 1381b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com currentRegister++; 1382c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com return !pastEnd(); 1383b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com } 1384b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com 1385b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com public int getCount() { 1386b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com return registerCount; 1387b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com } 1388b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com 1389b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com public boolean pastEnd() { 1390b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com return currentRegister >= registerCount; 1391b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com } 1392b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com } 1393b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com 1394b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com private static class Format3rcRegisterIterator implements RegisterIterator { 1395b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com private final int startRegister; 1396b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com private final int registerCount; 1397b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com private int currentRegister = 0; 1398b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com 1399b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com public Format3rcRegisterIterator(RegisterRangeInstruction instruction) { 1400b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com startRegister = instruction.getStartRegister(); 1401b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com registerCount = instruction.getRegCount(); 1402b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com } 1403b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com 1404b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com public int getRegister() { 1405b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com return startRegister + currentRegister; 1406b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com } 1407b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com 1408b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com public boolean moveNext() { 1409b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com currentRegister++; 1410c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com return !pastEnd(); 1411b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com } 1412b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com 1413b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com public int getCount() { 1414b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com return registerCount; 1415b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com } 1416b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com 1417b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com public boolean pastEnd() { 1418b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com return currentRegister >= registerCount; 1419b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com } 1420b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com } 1421b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com 1422ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com private void handleFilledNewArrayCommon(AnalyzedInstruction analyzedInstruction, 1423ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com RegisterIterator registerIterator) { 1424ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com InstructionWithReference instruction = (InstructionWithReference)analyzedInstruction.instruction; 1425ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com 14269e5dd85d837501e84e18617fc136c8203ab1f183JesusFreke@JesusFreke.com RegisterType arrayType; 14279e5dd85d837501e84e18617fc136c8203ab1f183JesusFreke@JesusFreke.com RegisterType arrayImmediateElementType; 14289e5dd85d837501e84e18617fc136c8203ab1f183JesusFreke@JesusFreke.com 1429ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com Item item = instruction.getReferencedItem(); 1430ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com assert item.getItemType() == ItemType.TYPE_TYPE_ID_ITEM; 14319e5dd85d837501e84e18617fc136c8203ab1f183JesusFreke@JesusFreke.com 1432ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com ClassPath.ClassDef classDef = ClassPath.getClassDef((TypeIdItem)item); 14339e5dd85d837501e84e18617fc136c8203ab1f183JesusFreke@JesusFreke.com 1434ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com if (classDef.getClassType().charAt(0) != '[') { 1435ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com throw new ValidationException("Cannot use non-array type \"" + classDef.getClassType() + 1436ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com "\" with new-array. Use new-instance instead."); 14379e5dd85d837501e84e18617fc136c8203ab1f183JesusFreke@JesusFreke.com } 14389e5dd85d837501e84e18617fc136c8203ab1f183JesusFreke@JesusFreke.com 1439ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com ClassPath.ArrayClassDef arrayClassDef = (ClassPath.ArrayClassDef)classDef; 1440ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com arrayType = RegisterType.getRegisterType(RegisterType.Category.Reference, classDef); 1441ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com arrayImmediateElementType = RegisterType.getRegisterTypeForType( 1442ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com arrayClassDef.getImmediateElementClass().getClassType()); 1443ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com String baseElementType = arrayClassDef.getBaseElementClass().getClassType(); 1444ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com if (baseElementType.charAt(0) == 'J' || baseElementType.charAt(0) == 'D') { 1445ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com throw new ValidationException("Cannot use filled-new-array to create an array of wide values " + 1446ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com "(long or double)"); 1447ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com } 14489e5dd85d837501e84e18617fc136c8203ab1f183JesusFreke@JesusFreke.com 1449ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com do { 1450ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com int register = registerIterator.getRegister(); 14519e5dd85d837501e84e18617fc136c8203ab1f183JesusFreke@JesusFreke.com RegisterType elementType = analyzedInstruction.getPreInstructionRegisterType(register); 14529e5dd85d837501e84e18617fc136c8203ab1f183JesusFreke@JesusFreke.com assert elementType != null; 14539e5dd85d837501e84e18617fc136c8203ab1f183JesusFreke@JesusFreke.com 14549e5dd85d837501e84e18617fc136c8203ab1f183JesusFreke@JesusFreke.com if (!elementType.canBeAssignedTo(arrayImmediateElementType)) { 14559e5dd85d837501e84e18617fc136c8203ab1f183JesusFreke@JesusFreke.com throw new ValidationException("Register v" + Integer.toString(register) + " is of type " + 14569e5dd85d837501e84e18617fc136c8203ab1f183JesusFreke@JesusFreke.com elementType.toString() + " and is incompatible with the array type " + 14579e5dd85d837501e84e18617fc136c8203ab1f183JesusFreke@JesusFreke.com arrayType.type.getClassType()); 14589e5dd85d837501e84e18617fc136c8203ab1f183JesusFreke@JesusFreke.com } 1459ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com } while (registerIterator.moveNext()); 14609e5dd85d837501e84e18617fc136c8203ab1f183JesusFreke@JesusFreke.com } 14619e5dd85d837501e84e18617fc136c8203ab1f183JesusFreke@JesusFreke.com 1462ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com private void handleFilledNewArray(AnalyzedInstruction analyzedInstruction) { 1463ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com FiveRegisterInstruction instruction = (FiveRegisterInstruction)analyzedInstruction.instruction; 1464ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handleFilledNewArrayCommon(analyzedInstruction, new Format35cRegisterIterator(instruction)); 1465ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com } 1466ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com 1467ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com private void handleFilledNewArrayRange(AnalyzedInstruction analyzedInstruction) { 1468b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com RegisterRangeInstruction instruction = (RegisterRangeInstruction)analyzedInstruction.instruction; 1469ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com 1470ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com //instruction.getStartRegister() and instruction.getRegCount() both return an int value, but are actually 1471ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com //unsigned 16 bit values, so we don't have to worry about overflowing an int when adding them together 1472ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com if (instruction.getStartRegister() + instruction.getRegCount() >= 1<<16) { 1473ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com throw new ValidationException(String.format("Invalid register range {v%d .. v%d}. The ending register " + 1474472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com "is larger than the largest allowed register of v65535.", 1475ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com instruction.getStartRegister(), 1476ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com instruction.getStartRegister() + instruction.getRegCount() - 1)); 1477ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com } 1478ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com 1479ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handleFilledNewArrayCommon(analyzedInstruction, new Format3rcRegisterIterator(instruction)); 1480ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com } 1481ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com 1482ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com private void handleFillArrayData(AnalyzedInstruction analyzedInstruction) { 1483472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com SingleRegisterInstruction instruction = (SingleRegisterInstruction)analyzedInstruction.instruction; 1484472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com 1485472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com int register = instruction.getRegisterA(); 1486472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com RegisterType registerType = analyzedInstruction.getPreInstructionRegisterType(register); 1487472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com assert registerType != null; 1488472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com 1489ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com if (registerType.category == RegisterType.Category.Null) { 1490ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 1491472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com } 1492472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com 1493472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com if (registerType.category != RegisterType.Category.Reference) { 1494472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use fill-array-data with non-array register v%d of " + 1495472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com "type %s", register, registerType.toString())); 1496472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com } 1497472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com 1498472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com assert registerType.type instanceof ClassPath.ArrayClassDef; 1499472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com ClassPath.ArrayClassDef arrayClassDef = (ClassPath.ArrayClassDef)registerType.type; 1500472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com 1501472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com if (arrayClassDef.getArrayDimensions() != 1) { 1502472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use fill-array-data with array type %s. It can only " + 1503472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com "be used with a one-dimensional array of primitives.", arrayClassDef.getClassType())); 1504472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com } 1505472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com 1506472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com int elementWidth; 1507472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com switch (arrayClassDef.getBaseElementClass().getClassType().charAt(0)) { 1508472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com case 'Z': 1509472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com case 'B': 1510472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com elementWidth = 1; 1511472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com break; 1512472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com case 'C': 1513472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com case 'S': 1514472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com elementWidth = 2; 1515472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com break; 1516472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com case 'I': 1517472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com case 'F': 1518472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com elementWidth = 4; 1519472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com break; 1520472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com case 'J': 1521472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com case 'D': 1522472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com elementWidth = 8; 1523472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com break; 1524472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com default: 1525472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use fill-array-data with array type %s. It can " + 1526472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com "only be used with a one-dimensional array of primitives.", arrayClassDef.getClassType())); 1527472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com } 1528472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com 1529472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com 1530b7e78115277e30c71e6e991da3f31c5a1403c634JesusFreke@JesusFreke.com int arrayDataAddressOffset = ((OffsetInstruction)analyzedInstruction.instruction).getTargetAddressOffset(); 1531b7e78115277e30c71e6e991da3f31c5a1403c634JesusFreke@JesusFreke.com int arrayDataCodeAddress = getInstructionAddress(analyzedInstruction) + arrayDataAddressOffset; 1532b7e78115277e30c71e6e991da3f31c5a1403c634JesusFreke@JesusFreke.com AnalyzedInstruction arrayDataInstruction = this.instructions.get(arrayDataCodeAddress); 1533472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com if (arrayDataInstruction == null || arrayDataInstruction.instruction.getFormat() != Format.ArrayData) { 1534472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com throw new ValidationException(String.format("Could not find an array data structure at code address 0x%x", 1535b7e78115277e30c71e6e991da3f31c5a1403c634JesusFreke@JesusFreke.com arrayDataCodeAddress)); 1536472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com } 1537472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com 1538472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com ArrayDataPseudoInstruction arrayDataPseudoInstruction = 1539472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com (ArrayDataPseudoInstruction)arrayDataInstruction.instruction; 1540472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com 1541472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com if (elementWidth != arrayDataPseudoInstruction.getElementWidth()) { 1542472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com throw new ValidationException(String.format("The array data at code address 0x%x does not have the " + 1543472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com "correct element width for array type %s. Expecting element width %d, got element width %d.", 1544b7e78115277e30c71e6e991da3f31c5a1403c634JesusFreke@JesusFreke.com arrayDataCodeAddress, arrayClassDef.getClassType(), elementWidth, 1545472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com arrayDataPseudoInstruction.getElementWidth())); 1546472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com } 1547472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com } 1548472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com 1549ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com private void handleThrow(AnalyzedInstruction analyzedInstruction) { 1550ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com int register = ((SingleRegisterInstruction)analyzedInstruction.instruction).getRegisterA(); 1551ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com 1552ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com RegisterType registerType = analyzedInstruction.getPreInstructionRegisterType(register); 1553ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com assert registerType != null; 1554ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com 1555ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com if (registerType.category == RegisterType.Category.Null) { 1556ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com return; 1557ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com } 1558ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com 1559ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com if (registerType.category != RegisterType.Category.Reference) { 1560ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use throw with non-reference type %s in register v%d", 1561ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com registerType.toString(), register)); 1562ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com } 1563ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com 1564ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com assert registerType.type != null; 1565ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com 1566ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com if (!registerType.type.extendsClass(ClassPath.getClassDef("Ljava/lang/Throwable;"))) { 1567ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use throw with non-throwable type %s in register v%d", 1568ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com registerType.type.getClassType(), register)); 1569ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com } 1570ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com } 1571ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com 1572ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com private void handleSwitch(AnalyzedInstruction analyzedInstruction, Format expectedSwitchDataFormat) { 1573cda44f70cfebfae4875cd77455a171075aebac4dJesusFreke@JesusFreke.com int register = ((SingleRegisterInstruction)analyzedInstruction.instruction).getRegisterA(); 1574cda44f70cfebfae4875cd77455a171075aebac4dJesusFreke@JesusFreke.com int switchCodeAddressOffset = ((OffsetInstruction)analyzedInstruction.instruction).getTargetAddressOffset(); 1575cda44f70cfebfae4875cd77455a171075aebac4dJesusFreke@JesusFreke.com 157685e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com getAndCheckSourceRegister(analyzedInstruction, register, Primitive32BitCategories); 1577cda44f70cfebfae4875cd77455a171075aebac4dJesusFreke@JesusFreke.com 1578cda44f70cfebfae4875cd77455a171075aebac4dJesusFreke@JesusFreke.com int switchDataCodeAddress = this.getInstructionAddress(analyzedInstruction) + switchCodeAddressOffset; 1579cda44f70cfebfae4875cd77455a171075aebac4dJesusFreke@JesusFreke.com AnalyzedInstruction switchDataAnalyzedInstruction = instructions.get(switchDataCodeAddress); 1580cda44f70cfebfae4875cd77455a171075aebac4dJesusFreke@JesusFreke.com 1581cda44f70cfebfae4875cd77455a171075aebac4dJesusFreke@JesusFreke.com if (switchDataAnalyzedInstruction == null || 1582cda44f70cfebfae4875cd77455a171075aebac4dJesusFreke@JesusFreke.com switchDataAnalyzedInstruction.instruction.getFormat() != expectedSwitchDataFormat) { 1583cda44f70cfebfae4875cd77455a171075aebac4dJesusFreke@JesusFreke.com throw new ValidationException(String.format("There is no %s structure at code address 0x%x", 1584cda44f70cfebfae4875cd77455a171075aebac4dJesusFreke@JesusFreke.com expectedSwitchDataFormat.name(), switchDataCodeAddress)); 1585cda44f70cfebfae4875cd77455a171075aebac4dJesusFreke@JesusFreke.com } 1586cda44f70cfebfae4875cd77455a171075aebac4dJesusFreke@JesusFreke.com } 1587cda44f70cfebfae4875cd77455a171075aebac4dJesusFreke@JesusFreke.com 158885e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com private void handleFloatWideCmp(AnalyzedInstruction analyzedInstruction, EnumSet validCategories) { 1589f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com ThreeRegisterInstruction instruction = (ThreeRegisterInstruction)analyzedInstruction.instruction; 1590f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com 159185e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterB(), validCategories); 159285e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterC(), validCategories); 1593f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com 1594f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, 1595f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com RegisterType.getRegisterType(RegisterType.Category.Byte, null)); 1596f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com } 1597f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com 1598ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com private void handleIfEqNe(AnalyzedInstruction analyzedInstruction) { 1599aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com TwoRegisterInstruction instruction = (TwoRegisterInstruction)analyzedInstruction.instruction; 1600aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com 1601aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com RegisterType registerType1 = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterA()); 1602aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com assert registerType1 != null; 1603aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com 1604aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com RegisterType registerType2 = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterB()); 1605aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com assert registerType2 != null; 1606aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com 1607aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com if (!( 1608aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com (ReferenceCategories.contains(registerType1.category) && 1609aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com ReferenceCategories.contains(registerType2.category)) 1610aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com || 1611aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com (Primitive32BitCategories.contains(registerType1.category) && 1612aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com Primitive32BitCategories.contains(registerType2.category)) 1613aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com )) { 1614aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com 1615aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com throw new ValidationException(String.format("%s cannot be used on registers of dissimilar types %s and " + 1616aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com "%s. They must both be a reference type or a primitive 32 bit type.", 1617aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com analyzedInstruction.instruction.opcode.name, registerType1.toString(), registerType2.toString())); 1618aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com } 1619aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com } 1620aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com 1621ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com private void handleIf(AnalyzedInstruction analyzedInstruction) { 1622150acd9db94f9886f6fc32e89acc15a1a5c1466fJesusFreke@JesusFreke.com TwoRegisterInstruction instruction = (TwoRegisterInstruction)analyzedInstruction.instruction; 1623150acd9db94f9886f6fc32e89acc15a1a5c1466fJesusFreke@JesusFreke.com 162485e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterA(), Primitive32BitCategories); 162585e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterB(), Primitive32BitCategories); 1626150acd9db94f9886f6fc32e89acc15a1a5c1466fJesusFreke@JesusFreke.com } 1627150acd9db94f9886f6fc32e89acc15a1a5c1466fJesusFreke@JesusFreke.com 1628ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com private void handleIfEqzNez(AnalyzedInstruction analyzedInstruction) { 1629cb00252b6aed86cd3e7c426015cea83fcdbaa806JesusFreke@JesusFreke.com SingleRegisterInstruction instruction = (SingleRegisterInstruction)analyzedInstruction.instruction; 1630cb00252b6aed86cd3e7c426015cea83fcdbaa806JesusFreke@JesusFreke.com 163185e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterA(), 163285e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com ReferenceAndPrimitive32BitCategories); 1633cb00252b6aed86cd3e7c426015cea83fcdbaa806JesusFreke@JesusFreke.com } 1634cb00252b6aed86cd3e7c426015cea83fcdbaa806JesusFreke@JesusFreke.com 1635ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com private void handleIfz(AnalyzedInstruction analyzedInstruction) { 163616a709ba046343bfefc15a6cdb0be38282126223JesusFreke@JesusFreke.com SingleRegisterInstruction instruction = (SingleRegisterInstruction)analyzedInstruction.instruction; 163716a709ba046343bfefc15a6cdb0be38282126223JesusFreke@JesusFreke.com 163885e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterA(), Primitive32BitCategories); 163916a709ba046343bfefc15a6cdb0be38282126223JesusFreke@JesusFreke.com } 164016a709ba046343bfefc15a6cdb0be38282126223JesusFreke@JesusFreke.com 1641ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com private void handle32BitPrimitiveAget(AnalyzedInstruction analyzedInstruction, 1642b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com RegisterType.Category instructionCategory) { 1643b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com ThreeRegisterInstruction instruction = (ThreeRegisterInstruction)analyzedInstruction.instruction; 1644b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com 164585e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterC(), Primitive32BitCategories); 1646b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com 1647b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com RegisterType arrayRegisterType = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterB()); 1648b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com assert arrayRegisterType != null; 1649b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com 1650b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com if (arrayRegisterType.category != RegisterType.Category.Null) { 1651b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com if (arrayRegisterType.category != RegisterType.Category.Reference) { 1652b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use %s with non-array type %s", 1653b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com analyzedInstruction.instruction.opcode.name, arrayRegisterType.category.toString())); 1654b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com } 1655b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com 1656b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com assert arrayRegisterType.type != null; 1657b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com if (arrayRegisterType.type.getClassType().charAt(0) != '[') { 1658b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use %s with non-array type %s", 1659b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com analyzedInstruction.instruction.opcode.name, arrayRegisterType.type.getClassType())); 1660b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com } 1661b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com 1662b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com assert arrayRegisterType.type instanceof ClassPath.ArrayClassDef; 1663b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com ClassPath.ArrayClassDef arrayClassDef = (ClassPath.ArrayClassDef)arrayRegisterType.type; 1664b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com 1665b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com if (arrayClassDef.getArrayDimensions() != 1) { 1666b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use %s with multi-dimensional array type %s", 1667b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com analyzedInstruction.instruction.opcode.name, arrayRegisterType.type.getClassType())); 1668b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com } 1669b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com 1670b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com RegisterType arrayBaseType = 1671b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com RegisterType.getRegisterTypeForType(arrayClassDef.getBaseElementClass().getClassType()); 1672c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com if (!checkArrayFieldAssignment(arrayBaseType.category, instructionCategory)) { 1673b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use %s with array type %s. Incorrect array type " + 1674b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com "for the instruction.", analyzedInstruction.instruction.opcode.name, 1675b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com arrayRegisterType.type.getClassType())); 1676b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com } 1677b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com } 1678b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com 1679b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, 1680b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com RegisterType.getRegisterType(instructionCategory, null)); 1681b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com } 1682b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com 1683ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com private void handleAgetWide(AnalyzedInstruction analyzedInstruction) { 1684c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com ThreeRegisterInstruction instruction = (ThreeRegisterInstruction)analyzedInstruction.instruction; 1685c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com 168685e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterC(), Primitive32BitCategories); 1687c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com 1688c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com RegisterType arrayRegisterType = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterB()); 1689c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com assert arrayRegisterType != null; 1690c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com 1691c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com if (arrayRegisterType.category != RegisterType.Category.Null) { 1692c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com if (arrayRegisterType.category != RegisterType.Category.Reference) { 1693c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use aget-wide with non-array type %s", 1694c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com arrayRegisterType.category.toString())); 1695c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com } 1696c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com 1697c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com assert arrayRegisterType.type != null; 1698c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com if (arrayRegisterType.type.getClassType().charAt(0) != '[') { 1699c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use aget-wide with non-array type %s", 1700c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com arrayRegisterType.type.getClassType())); 1701c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com } 1702c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com 1703c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com assert arrayRegisterType.type instanceof ClassPath.ArrayClassDef; 1704c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com ClassPath.ArrayClassDef arrayClassDef = (ClassPath.ArrayClassDef)arrayRegisterType.type; 1705c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com 1706c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com if (arrayClassDef.getArrayDimensions() != 1) { 1707c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use aget-wide with multi-dimensional array type %s", 1708c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com arrayRegisterType.type.getClassType())); 1709c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com } 1710c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com 1711c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com char arrayBaseType = arrayClassDef.getBaseElementClass().getClassType().charAt(0); 1712c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com if (arrayBaseType == 'J') { 171385e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, 1714c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com RegisterType.getRegisterType(RegisterType.Category.LongLo, null)); 1715c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com } else if (arrayBaseType == 'D') { 171685e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, 1717c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com RegisterType.getRegisterType(RegisterType.Category.DoubleLo, null)); 1718c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com } else { 1719c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use aget-wide with array type %s. Incorrect " + 1720c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com "array type for the instruction.", arrayRegisterType.type.getClassType())); 1721c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com } 1722c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com } else { 172385e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, 1724c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com RegisterType.getRegisterType(RegisterType.Category.LongLo, null)); 1725c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com } 1726c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com } 1727c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com 1728ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com private void handleAgetObject(AnalyzedInstruction analyzedInstruction) { 1729461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com ThreeRegisterInstruction instruction = (ThreeRegisterInstruction)analyzedInstruction.instruction; 1730461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com 173185e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterC(), Primitive32BitCategories); 1732461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com 1733461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com RegisterType arrayRegisterType = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterB()); 1734461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com assert arrayRegisterType != null; 1735461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com 1736461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com if (arrayRegisterType.category != RegisterType.Category.Null) { 1737461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com if (arrayRegisterType.category != RegisterType.Category.Reference) { 1738461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use aget-object with non-array type %s", 1739461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com arrayRegisterType.category.toString())); 1740461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com } 1741461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com 1742461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com assert arrayRegisterType.type != null; 1743461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com if (arrayRegisterType.type.getClassType().charAt(0) != '[') { 1744461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use aget-object with non-array type %s", 1745461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com arrayRegisterType.type.getClassType())); 1746461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com } 1747461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com 1748461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com assert arrayRegisterType.type instanceof ClassPath.ArrayClassDef; 1749461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com ClassPath.ArrayClassDef arrayClassDef = (ClassPath.ArrayClassDef)arrayRegisterType.type; 1750461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com 1751461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com ClassPath.ClassDef elementClassDef = arrayClassDef.getImmediateElementClass(); 1752461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com char elementTypePrefix = elementClassDef.getClassType().charAt(0); 1753461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com if (elementTypePrefix != 'L' && elementTypePrefix != '[') { 1754461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use aget-object with array type %s. Incorrect " + 1755461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com "array type for the instruction.", arrayRegisterType.type.getClassType())); 1756461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com } 1757461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com 1758461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, 1759461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com RegisterType.getRegisterType(RegisterType.Category.Reference, elementClassDef)); 1760461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com } else { 1761461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, 1762461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com RegisterType.getRegisterType(RegisterType.Category.Null, null)); 1763461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com } 1764461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com } 1765461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com 1766ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com private void handle32BitPrimitiveAput(AnalyzedInstruction analyzedInstruction, 1767c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com RegisterType.Category instructionCategory) { 1768c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com ThreeRegisterInstruction instruction = (ThreeRegisterInstruction)analyzedInstruction.instruction; 1769c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com 177085e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterC(), Primitive32BitCategories); 1771c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com 1772c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com RegisterType sourceRegisterType = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterA()); 1773c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com assert sourceRegisterType != null; 1774c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com RegisterType instructionRegisterType = RegisterType.getRegisterType(instructionCategory, null); 1775c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com if (!sourceRegisterType.canBeAssignedTo(instructionRegisterType)) { 1776c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use %s with source register type %s.", 1777c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com analyzedInstruction.instruction.opcode.name, sourceRegisterType.toString())); 1778c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com } 1779c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com 1780c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com 1781c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com RegisterType arrayRegisterType = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterB()); 1782c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com assert arrayRegisterType != null; 1783c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com 1784c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com if (arrayRegisterType.category != RegisterType.Category.Null) { 1785c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com if (arrayRegisterType.category != RegisterType.Category.Reference) { 1786c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use %s with non-array type %s", 1787c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com analyzedInstruction.instruction.opcode.name, arrayRegisterType.category.toString())); 1788c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com } 1789c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com 1790c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com assert arrayRegisterType.type != null; 1791c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com if (arrayRegisterType.type.getClassType().charAt(0) != '[') { 1792c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use %s with non-array type %s", 1793c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com analyzedInstruction.instruction.opcode.name, arrayRegisterType.type.getClassType())); 1794c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com } 1795c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com 1796c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com assert arrayRegisterType.type instanceof ClassPath.ArrayClassDef; 1797c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com ClassPath.ArrayClassDef arrayClassDef = (ClassPath.ArrayClassDef)arrayRegisterType.type; 1798c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com 1799c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com if (arrayClassDef.getArrayDimensions() != 1) { 1800c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use %s with multi-dimensional array type %s", 1801c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com analyzedInstruction.instruction.opcode.name, arrayRegisterType.type.getClassType())); 1802c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com } 1803c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com 1804c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com RegisterType arrayBaseType = 1805c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com RegisterType.getRegisterTypeForType(arrayClassDef.getBaseElementClass().getClassType()); 1806c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com if (!checkArrayFieldAssignment(arrayBaseType.category, instructionCategory)) { 1807c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use %s with array type %s. Incorrect array type " + 1808c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com "for the instruction.", analyzedInstruction.instruction.opcode.name, 1809c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com arrayRegisterType.type.getClassType())); 181055d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com } 181155d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com } 181255d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com } 181355d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com 1814ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com private void handleAputWide(AnalyzedInstruction analyzedInstruction) { 181555d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com ThreeRegisterInstruction instruction = (ThreeRegisterInstruction)analyzedInstruction.instruction; 181655d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com 181785e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterC(), Primitive32BitCategories); 181885e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterA(), WideLowCategories); 181955d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com 182055d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com RegisterType arrayRegisterType = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterB()); 182155d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com assert arrayRegisterType != null; 182255d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com 182355d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com if (arrayRegisterType.category != RegisterType.Category.Null) { 182455d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com if (arrayRegisterType.category != RegisterType.Category.Reference) { 182555d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use aput-wide with non-array type %s", 182655d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com arrayRegisterType.category.toString())); 182755d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com } 182855d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com 182955d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com assert arrayRegisterType.type != null; 183055d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com if (arrayRegisterType.type.getClassType().charAt(0) != '[') { 183155d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use aput-wide with non-array type %s", 183255d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com arrayRegisterType.type.getClassType())); 183355d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com } 183455d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com 183555d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com assert arrayRegisterType.type instanceof ClassPath.ArrayClassDef; 183655d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com ClassPath.ArrayClassDef arrayClassDef = (ClassPath.ArrayClassDef)arrayRegisterType.type; 183755d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com 183855d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com if (arrayClassDef.getArrayDimensions() != 1) { 183955d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use aput-wide with multi-dimensional array type %s", 184055d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com arrayRegisterType.type.getClassType())); 184155d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com } 184255d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com 184355d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com char arrayBaseType = arrayClassDef.getBaseElementClass().getClassType().charAt(0); 184455d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com if (arrayBaseType != 'J' && arrayBaseType != 'D') { 184555d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use aput-wide with array type %s. Incorrect " + 184655d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com "array type for the instruction.", arrayRegisterType.type.getClassType())); 1847898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com } 1848898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com } 1849898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com } 1850898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com 1851ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com private void handleAputObject(AnalyzedInstruction analyzedInstruction) { 1852898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com ThreeRegisterInstruction instruction = (ThreeRegisterInstruction)analyzedInstruction.instruction; 1853898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com 185485e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterC(), Primitive32BitCategories); 1855898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com 1856898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com RegisterType sourceRegisterType = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterA()); 1857898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com assert sourceRegisterType != null; 1858ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com 18596d11e9062dfaa27c7fa8719d9d9b4f58b0d5cfa0JesusFreke@JesusFreke.com //TODO: ensure sourceRegisterType is a Reference type? 1860898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com 1861898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com RegisterType arrayRegisterType = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterB()); 1862898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com assert arrayRegisterType != null; 1863898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com 1864898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com if (arrayRegisterType.category != RegisterType.Category.Null) { 1865898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com //don't check the source type against the array type, just make sure it is an array of reference types 1866898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com 1867898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com if (arrayRegisterType.category != RegisterType.Category.Reference) { 1868898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use aget-object with non-array type %s", 1869898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com arrayRegisterType.category.toString())); 1870898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com } 1871898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com 1872898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com assert arrayRegisterType.type != null; 1873898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com if (arrayRegisterType.type.getClassType().charAt(0) != '[') { 1874898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use aget-object with non-array type %s", 1875898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com arrayRegisterType.type.getClassType())); 1876898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com } 1877898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com 1878898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com assert arrayRegisterType.type instanceof ClassPath.ArrayClassDef; 1879898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com ClassPath.ArrayClassDef arrayClassDef = (ClassPath.ArrayClassDef)arrayRegisterType.type; 1880898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com 1881898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com ClassPath.ClassDef elementClassDef = arrayClassDef.getImmediateElementClass(); 1882898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com char elementTypePrefix = elementClassDef.getClassType().charAt(0); 1883898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com if (elementTypePrefix != 'L' && elementTypePrefix != '[') { 1884898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use aget-object with array type %s. Incorrect " + 1885898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com "array type for the instruction.", arrayRegisterType.type.getClassType())); 1886c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com } 1887c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com } 1888c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com } 1889c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com 1890ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com private void handle32BitPrimitiveIget(AnalyzedInstruction analyzedInstruction, 18914f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com RegisterType.Category instructionCategory) { 18924f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com TwoRegisterInstruction instruction = (TwoRegisterInstruction)analyzedInstruction.instruction; 18934f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com 189485e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com RegisterType objectRegisterType = getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterB(), 1895c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com ReferenceOrUninitThisCategories); 18964f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com 18974f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com //TODO: check access 18984f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com Item referencedItem = ((InstructionWithReference)analyzedInstruction.instruction).getReferencedItem(); 18994f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com assert referencedItem instanceof FieldIdItem; 19004f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com FieldIdItem field = (FieldIdItem)referencedItem; 19014f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com 19024f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com if (objectRegisterType.category != RegisterType.Category.Null && 19034f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com !objectRegisterType.type.extendsClass(ClassPath.getClassDef(field.getContainingClass()))) { 19044f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot access field %s through type %s", 19054f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com field.getFieldString(), objectRegisterType.type.getClassType())); 19064f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com } 19074f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com 19084f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com RegisterType fieldType = RegisterType.getRegisterTypeForTypeIdItem(field.getFieldType()); 19094f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com 19104f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com if (!checkArrayFieldAssignment(fieldType.category, instructionCategory)) { 19114f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use %s with field %s. Incorrect field type " + 19124f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com "for the instruction.", analyzedInstruction.instruction.opcode.name, 19134f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com field.getFieldString())); 19144f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com } 19154f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com 19164f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, 19174f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com RegisterType.getRegisterType(instructionCategory, null)); 19184f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com } 19194f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com 1920ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com private void handleIgetWide(AnalyzedInstruction analyzedInstruction) { 19219d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com TwoRegisterInstruction instruction = (TwoRegisterInstruction)analyzedInstruction.instruction; 19229d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com 192385e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com RegisterType objectRegisterType = getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterB(), 1924c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com ReferenceOrUninitThisCategories); 19259d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com 19269d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com //TODO: check access 19279d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com Item referencedItem = ((InstructionWithReference)analyzedInstruction.instruction).getReferencedItem(); 19289d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com assert referencedItem instanceof FieldIdItem; 19299d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com FieldIdItem field = (FieldIdItem)referencedItem; 19309d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com 19319d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com if (objectRegisterType.category != RegisterType.Category.Null && 19329d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com !objectRegisterType.type.extendsClass(ClassPath.getClassDef(field.getContainingClass()))) { 19339d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot access field %s through type %s", 19349d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com field.getFieldString(), objectRegisterType.type.getClassType())); 19359d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com } 19369d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com 19379d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com RegisterType fieldType = RegisterType.getRegisterTypeForTypeIdItem(field.getFieldType()); 19389d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com 193985e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com if (!WideLowCategories.contains(fieldType.category)) { 19409d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use %s with field %s. Incorrect field type " + 194185e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com "for the instruction.", analyzedInstruction.instruction.opcode.name, 194285e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com field.getFieldString())); 19439d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com } 19449d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com 194585e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, fieldType); 19467a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com } 19477a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com 1948ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com private void handleIgetObject(AnalyzedInstruction analyzedInstruction) { 19497a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com TwoRegisterInstruction instruction = (TwoRegisterInstruction)analyzedInstruction.instruction; 19507a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com 195185e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com RegisterType objectRegisterType = getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterB(), 1952c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com ReferenceOrUninitThisCategories); 19537a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com 19547a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com //TODO: check access 19557a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com Item referencedItem = ((InstructionWithReference)analyzedInstruction.instruction).getReferencedItem(); 19567a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com assert referencedItem instanceof FieldIdItem; 19577a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com FieldIdItem field = (FieldIdItem)referencedItem; 19587a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com 19597a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com if (objectRegisterType.category != RegisterType.Category.Null && 19607a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com !objectRegisterType.type.extendsClass(ClassPath.getClassDef(field.getContainingClass()))) { 19617a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot access field %s through type %s", 19627a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com field.getFieldString(), objectRegisterType.type.getClassType())); 19637a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com } 19647a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com 19657a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com RegisterType fieldType = RegisterType.getRegisterTypeForTypeIdItem(field.getFieldType()); 19667a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com 19677a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com if (fieldType.category != RegisterType.Category.Reference) { 19687a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use %s with field %s. Incorrect field type " + 19697a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com "for the instruction.", analyzedInstruction.instruction.opcode.name, 19707a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com field.getFieldString())); 19717a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com } 19727a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com 19737a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, fieldType); 19749d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com } 19759d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com 1976ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com private void handle32BitPrimitiveIput(AnalyzedInstruction analyzedInstruction, 19779971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com RegisterType.Category instructionCategory) { 19789971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com TwoRegisterInstruction instruction = (TwoRegisterInstruction)analyzedInstruction.instruction; 19799971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com 198085e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com RegisterType objectRegisterType = getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterB(), 1981c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com ReferenceOrUninitThisCategories); 19829971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com 19839971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com RegisterType sourceRegisterType = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterA()); 19849971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com assert sourceRegisterType != null; 19859971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com 19869971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com //per CodeVerify.c in dalvik: 19879971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com //java generates synthetic functions that write byte values into boolean fields 19889971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com if (sourceRegisterType.category == RegisterType.Category.Byte && 19899971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com instructionCategory == RegisterType.Category.Boolean) { 19909971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com 19919971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com sourceRegisterType = RegisterType.getRegisterType(RegisterType.Category.Boolean, null); 19929971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com } 19939971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com 19949971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com RegisterType instructionRegisterType = RegisterType.getRegisterType(instructionCategory, null); 19959971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com if (!sourceRegisterType.canBeAssignedTo(instructionRegisterType)) { 19969971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use %s with source register type %s.", 19979971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com analyzedInstruction.instruction.opcode.name, sourceRegisterType.toString())); 19989971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com } 19999971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com 20009971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com 20019971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com //TODO: check access 20029971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com Item referencedItem = ((InstructionWithReference)analyzedInstruction.instruction).getReferencedItem(); 20039971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com assert referencedItem instanceof FieldIdItem; 20049971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com FieldIdItem field = (FieldIdItem)referencedItem; 20059971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com 20069971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com if (objectRegisterType.category != RegisterType.Category.Null && 20079971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com !objectRegisterType.type.extendsClass(ClassPath.getClassDef(field.getContainingClass()))) { 20089971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot access field %s through type %s", 20099971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com field.getFieldString(), objectRegisterType.type.getClassType())); 20109971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com } 20119971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com 20129971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com RegisterType fieldType = RegisterType.getRegisterTypeForTypeIdItem(field.getFieldType()); 20139971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com 20149971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com if (!checkArrayFieldAssignment(fieldType.category, instructionCategory)) { 20159971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use %s with field %s. Incorrect field type " + 20169971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com "for the instruction.", analyzedInstruction.instruction.opcode.name, 20179971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com field.getFieldString())); 20189971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com } 20199971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com } 20209971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com 2021ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com private void handleIputWide(AnalyzedInstruction analyzedInstruction) { 202292616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com TwoRegisterInstruction instruction = (TwoRegisterInstruction)analyzedInstruction.instruction; 202392616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com 202485e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com RegisterType objectRegisterType = getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterB(), 2025c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com ReferenceOrUninitThisCategories); 202692616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com 202785e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterA(), WideLowCategories); 202892616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com 202992616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com //TODO: check access 203092616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com Item referencedItem = ((InstructionWithReference)analyzedInstruction.instruction).getReferencedItem(); 203192616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com assert referencedItem instanceof FieldIdItem; 203292616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com FieldIdItem field = (FieldIdItem)referencedItem; 203392616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com 203492616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com if (objectRegisterType.category != RegisterType.Category.Null && 203592616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com !objectRegisterType.type.extendsClass(ClassPath.getClassDef(field.getContainingClass()))) { 203692616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot access field %s through type %s", 203792616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com field.getFieldString(), objectRegisterType.type.getClassType())); 203892616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com } 203992616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com 204092616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com RegisterType fieldType = RegisterType.getRegisterTypeForTypeIdItem(field.getFieldType()); 204192616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com 204292616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com if (!WideLowCategories.contains(fieldType.category)) { 204392616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use %s with field %s. Incorrect field type " + 204492616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com "for the instruction.", analyzedInstruction.instruction.opcode.name, 204592616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com field.getFieldString())); 204692616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com } 204792616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com } 204892616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com 2049ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com private void handleIputObject(AnalyzedInstruction analyzedInstruction) { 205050ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com TwoRegisterInstruction instruction = (TwoRegisterInstruction)analyzedInstruction.instruction; 205150ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com 205285e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com RegisterType objectRegisterType = getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterB(), 2053c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com ReferenceOrUninitThisCategories); 205450ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com 2055c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com RegisterType sourceRegisterType = getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterA(), 205685e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com ReferenceCategories); 205750ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com 205850ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com //TODO: check access 205950ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com Item referencedItem = ((InstructionWithReference)analyzedInstruction.instruction).getReferencedItem(); 206050ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com assert referencedItem instanceof FieldIdItem; 206150ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com FieldIdItem field = (FieldIdItem)referencedItem; 206250ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com 206350ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com if (objectRegisterType.category != RegisterType.Category.Null && 206450ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com !objectRegisterType.type.extendsClass(ClassPath.getClassDef(field.getContainingClass()))) { 206550ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot access field %s through type %s", 206650ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com field.getFieldString(), objectRegisterType.type.getClassType())); 206750ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com } 206850ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com 206950ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com RegisterType fieldType = RegisterType.getRegisterTypeForTypeIdItem(field.getFieldType()); 207050ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com 207150ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com if (fieldType.category != RegisterType.Category.Reference) { 207250ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use %s with field %s. Incorrect field type " + 207350ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com "for the instruction.", analyzedInstruction.instruction.opcode.name, 207450ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com field.getFieldString())); 207550ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com } 207650ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com 207750ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com if (sourceRegisterType.category != RegisterType.Category.Null && 207850ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com !fieldType.type.isInterface() && 207950ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com !sourceRegisterType.type.extendsClass(fieldType.type)) { 208050ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com 208150ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot store a value of type %s into a field of type %s", 208250ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com sourceRegisterType.type.getClassType(), fieldType.type.getClassType())); 208350ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com } 208450ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com } 208550ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com 2086ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com private void handle32BitPrimitiveSget(AnalyzedInstruction analyzedInstruction, 2087052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com RegisterType.Category instructionCategory) { 2088052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com //TODO: check access 2089052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com Item referencedItem = ((InstructionWithReference)analyzedInstruction.instruction).getReferencedItem(); 2090052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com assert referencedItem instanceof FieldIdItem; 2091052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com FieldIdItem field = (FieldIdItem)referencedItem; 2092052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com 2093052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com RegisterType fieldType = RegisterType.getRegisterTypeForTypeIdItem(field.getFieldType()); 2094052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com 2095052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com if (!checkArrayFieldAssignment(fieldType.category, instructionCategory)) { 2096052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use %s with field %s. Incorrect field type " + 2097052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com "for the instruction.", analyzedInstruction.instruction.opcode.name, 2098052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com field.getFieldString())); 2099052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com } 2100052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com 2101052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, 2102052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com RegisterType.getRegisterType(instructionCategory, null)); 2103052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com } 2104052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com 2105ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com private void handleSgetWide(AnalyzedInstruction analyzedInstruction) { 21062f233fefd9d73af8fab4037a6f874b161b98b259JesusFreke@JesusFreke.com //TODO: check access 21072f233fefd9d73af8fab4037a6f874b161b98b259JesusFreke@JesusFreke.com Item referencedItem = ((InstructionWithReference)analyzedInstruction.instruction).getReferencedItem(); 21082f233fefd9d73af8fab4037a6f874b161b98b259JesusFreke@JesusFreke.com assert referencedItem instanceof FieldIdItem; 21092f233fefd9d73af8fab4037a6f874b161b98b259JesusFreke@JesusFreke.com FieldIdItem field = (FieldIdItem)referencedItem; 21102f233fefd9d73af8fab4037a6f874b161b98b259JesusFreke@JesusFreke.com 21112f233fefd9d73af8fab4037a6f874b161b98b259JesusFreke@JesusFreke.com RegisterType fieldType = RegisterType.getRegisterTypeForTypeIdItem(field.getFieldType()); 21122f233fefd9d73af8fab4037a6f874b161b98b259JesusFreke@JesusFreke.com 21132f233fefd9d73af8fab4037a6f874b161b98b259JesusFreke@JesusFreke.com 21142f233fefd9d73af8fab4037a6f874b161b98b259JesusFreke@JesusFreke.com if (fieldType.category != RegisterType.Category.LongLo && 21152f233fefd9d73af8fab4037a6f874b161b98b259JesusFreke@JesusFreke.com fieldType.category != RegisterType.Category.DoubleLo) { 21162f233fefd9d73af8fab4037a6f874b161b98b259JesusFreke@JesusFreke.com 21172f233fefd9d73af8fab4037a6f874b161b98b259JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use %s with field %s. Incorrect field type " + 21182f233fefd9d73af8fab4037a6f874b161b98b259JesusFreke@JesusFreke.com "for the instruction.", analyzedInstruction.instruction.opcode.name, 21192f233fefd9d73af8fab4037a6f874b161b98b259JesusFreke@JesusFreke.com field.getFieldString())); 21202f233fefd9d73af8fab4037a6f874b161b98b259JesusFreke@JesusFreke.com } 21212f233fefd9d73af8fab4037a6f874b161b98b259JesusFreke@JesusFreke.com 212285e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, fieldType); 21232d6d6eb22c86c79344b85ffe46fdd4268566bd0fJesusFreke@JesusFreke.com } 21242d6d6eb22c86c79344b85ffe46fdd4268566bd0fJesusFreke@JesusFreke.com 2125ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com private void handleSgetObject(AnalyzedInstruction analyzedInstruction) { 21262d6d6eb22c86c79344b85ffe46fdd4268566bd0fJesusFreke@JesusFreke.com //TODO: check access 21272d6d6eb22c86c79344b85ffe46fdd4268566bd0fJesusFreke@JesusFreke.com Item referencedItem = ((InstructionWithReference)analyzedInstruction.instruction).getReferencedItem(); 21282d6d6eb22c86c79344b85ffe46fdd4268566bd0fJesusFreke@JesusFreke.com assert referencedItem instanceof FieldIdItem; 21292d6d6eb22c86c79344b85ffe46fdd4268566bd0fJesusFreke@JesusFreke.com FieldIdItem field = (FieldIdItem)referencedItem; 21302d6d6eb22c86c79344b85ffe46fdd4268566bd0fJesusFreke@JesusFreke.com 21312d6d6eb22c86c79344b85ffe46fdd4268566bd0fJesusFreke@JesusFreke.com RegisterType fieldType = RegisterType.getRegisterTypeForTypeIdItem(field.getFieldType()); 21322d6d6eb22c86c79344b85ffe46fdd4268566bd0fJesusFreke@JesusFreke.com 21332d6d6eb22c86c79344b85ffe46fdd4268566bd0fJesusFreke@JesusFreke.com if (fieldType.category != RegisterType.Category.Reference) { 21342d6d6eb22c86c79344b85ffe46fdd4268566bd0fJesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use %s with field %s. Incorrect field type " + 21352d6d6eb22c86c79344b85ffe46fdd4268566bd0fJesusFreke@JesusFreke.com "for the instruction.", analyzedInstruction.instruction.opcode.name, 21362d6d6eb22c86c79344b85ffe46fdd4268566bd0fJesusFreke@JesusFreke.com field.getFieldString())); 21372d6d6eb22c86c79344b85ffe46fdd4268566bd0fJesusFreke@JesusFreke.com } 21382d6d6eb22c86c79344b85ffe46fdd4268566bd0fJesusFreke@JesusFreke.com 21392d6d6eb22c86c79344b85ffe46fdd4268566bd0fJesusFreke@JesusFreke.com setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, fieldType); 21402f233fefd9d73af8fab4037a6f874b161b98b259JesusFreke@JesusFreke.com } 21412f233fefd9d73af8fab4037a6f874b161b98b259JesusFreke@JesusFreke.com 2142ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com private void handle32BitPrimitiveSput(AnalyzedInstruction analyzedInstruction, 21439d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com RegisterType.Category instructionCategory) { 21449d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com SingleRegisterInstruction instruction = (SingleRegisterInstruction)analyzedInstruction.instruction; 21459d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com 21469d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com RegisterType sourceRegisterType = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterA()); 21479d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com assert sourceRegisterType != null; 21489d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com 21499d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com //per CodeVerify.c in dalvik: 21509d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com //java generates synthetic functions that write byte values into boolean fields 21519d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com if (sourceRegisterType.category == RegisterType.Category.Byte && 21529d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com instructionCategory == RegisterType.Category.Boolean) { 21539d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com 21549d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com sourceRegisterType = RegisterType.getRegisterType(RegisterType.Category.Boolean, null); 21559d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com } 21569d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com 21579d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com RegisterType instructionRegisterType = RegisterType.getRegisterType(instructionCategory, null); 21589d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com if (!sourceRegisterType.canBeAssignedTo(instructionRegisterType)) { 21599d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use %s with source register type %s.", 21609d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com analyzedInstruction.instruction.opcode.name, sourceRegisterType.toString())); 21619d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com } 21629d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com 21639d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com //TODO: check access 21649d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com Item referencedItem = ((InstructionWithReference)analyzedInstruction.instruction).getReferencedItem(); 21659d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com assert referencedItem instanceof FieldIdItem; 21669d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com FieldIdItem field = (FieldIdItem)referencedItem; 21679d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com 21689d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com RegisterType fieldType = RegisterType.getRegisterTypeForTypeIdItem(field.getFieldType()); 21699d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com 21709d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com if (!checkArrayFieldAssignment(fieldType.category, instructionCategory)) { 21719d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use %s with field %s. Incorrect field type " + 21729d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com "for the instruction.", analyzedInstruction.instruction.opcode.name, 21739d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com field.getFieldString())); 21749d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com } 21759d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com } 21769d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com 2177ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com private void handleSputWide(AnalyzedInstruction analyzedInstruction) { 2178f08a9e1c2c130a5ed5923999fec0283f91b48a09JesusFreke@JesusFreke.com SingleRegisterInstruction instruction = (SingleRegisterInstruction)analyzedInstruction.instruction; 2179f08a9e1c2c130a5ed5923999fec0283f91b48a09JesusFreke@JesusFreke.com 2180f08a9e1c2c130a5ed5923999fec0283f91b48a09JesusFreke@JesusFreke.com 218185e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterA(), WideLowCategories); 2182f08a9e1c2c130a5ed5923999fec0283f91b48a09JesusFreke@JesusFreke.com 2183f08a9e1c2c130a5ed5923999fec0283f91b48a09JesusFreke@JesusFreke.com //TODO: check access 2184f08a9e1c2c130a5ed5923999fec0283f91b48a09JesusFreke@JesusFreke.com Item referencedItem = ((InstructionWithReference)analyzedInstruction.instruction).getReferencedItem(); 2185f08a9e1c2c130a5ed5923999fec0283f91b48a09JesusFreke@JesusFreke.com assert referencedItem instanceof FieldIdItem; 2186f08a9e1c2c130a5ed5923999fec0283f91b48a09JesusFreke@JesusFreke.com FieldIdItem field = (FieldIdItem)referencedItem; 2187f08a9e1c2c130a5ed5923999fec0283f91b48a09JesusFreke@JesusFreke.com 2188f08a9e1c2c130a5ed5923999fec0283f91b48a09JesusFreke@JesusFreke.com RegisterType fieldType = RegisterType.getRegisterTypeForTypeIdItem(field.getFieldType()); 2189f08a9e1c2c130a5ed5923999fec0283f91b48a09JesusFreke@JesusFreke.com 2190f08a9e1c2c130a5ed5923999fec0283f91b48a09JesusFreke@JesusFreke.com if (!WideLowCategories.contains(fieldType.category)) { 2191f08a9e1c2c130a5ed5923999fec0283f91b48a09JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use %s with field %s. Incorrect field type " + 2192f08a9e1c2c130a5ed5923999fec0283f91b48a09JesusFreke@JesusFreke.com "for the instruction.", analyzedInstruction.instruction.opcode.name, 2193f08a9e1c2c130a5ed5923999fec0283f91b48a09JesusFreke@JesusFreke.com field.getFieldString())); 2194f08a9e1c2c130a5ed5923999fec0283f91b48a09JesusFreke@JesusFreke.com } 2195f08a9e1c2c130a5ed5923999fec0283f91b48a09JesusFreke@JesusFreke.com } 2196f08a9e1c2c130a5ed5923999fec0283f91b48a09JesusFreke@JesusFreke.com 2197ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com private void handleSputObject(AnalyzedInstruction analyzedInstruction) { 219851cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com SingleRegisterInstruction instruction = (SingleRegisterInstruction)analyzedInstruction.instruction; 219951cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com 220085e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com RegisterType sourceRegisterType = getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterA(), 220185e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com ReferenceCategories); 220251cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com 220351cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com //TODO: check access 220451cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com Item referencedItem = ((InstructionWithReference)analyzedInstruction.instruction).getReferencedItem(); 220551cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com assert referencedItem instanceof FieldIdItem; 220651cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com FieldIdItem field = (FieldIdItem)referencedItem; 220751cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com 220851cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com RegisterType fieldType = RegisterType.getRegisterTypeForTypeIdItem(field.getFieldType()); 220951cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com 221051cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com if (fieldType.category != RegisterType.Category.Reference) { 221151cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use %s with field %s. Incorrect field type " + 221251cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com "for the instruction.", analyzedInstruction.instruction.opcode.name, 221351cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com field.getFieldString())); 221451cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com } 221551cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com 221651cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com if (sourceRegisterType.category != RegisterType.Category.Null && 221751cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com !fieldType.type.isInterface() && 221851cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com !sourceRegisterType.type.extendsClass(fieldType.type)) { 221951cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com 222051cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot store a value of type %s into a field of type %s", 222151cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com sourceRegisterType.type.getClassType(), fieldType.type.getClassType())); 222251cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com } 222351cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com } 222451cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com 2225ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com private void handleInvoke(AnalyzedInstruction analyzedInstruction, int invokeType) { 222689e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com FiveRegisterInstruction instruction = (FiveRegisterInstruction)analyzedInstruction.instruction; 2227ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handleInvokeCommon(analyzedInstruction, false, invokeType, new Format35cRegisterIterator(instruction)); 222889e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com } 222989e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com 2230ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com private void handleInvokeRange(AnalyzedInstruction analyzedInstruction, int invokeType) { 223189e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com RegisterRangeInstruction instruction = (RegisterRangeInstruction)analyzedInstruction.instruction; 2232ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com handleInvokeCommon(analyzedInstruction, true, invokeType, new Format3rcRegisterIterator(instruction)); 223389e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com } 223489e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com 223589e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com private static final int INVOKE_VIRTUAL = 0x01; 223689e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com private static final int INVOKE_SUPER = 0x02; 223789e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com private static final int INVOKE_DIRECT = 0x04; 223889e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com private static final int INVOKE_INTERFACE = 0x08; 223989e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com private static final int INVOKE_STATIC = 0x10; 224089e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com 2241ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com private void handleInvokeCommon(AnalyzedInstruction analyzedInstruction, boolean isRange, int invokeType, 224289e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com RegisterIterator registers) { 224389e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com InstructionWithReference instruction = (InstructionWithReference)analyzedInstruction.instruction; 224489e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com 224589e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com //TODO: check access 224689e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com //TODO: allow uninitialized reference if this in an <init> method 224789e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com 224889e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com Item item = instruction.getReferencedItem(); 224989e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com assert item.getItemType() == ItemType.TYPE_METHOD_ID_ITEM; 225089e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com MethodIdItem methodIdItem = (MethodIdItem)item; 225189e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com 225289e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com TypeIdItem methodClass = methodIdItem.getContainingClass(); 225389e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com boolean isInit = false; 225489e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com 225589e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com if (methodIdItem.getMethodName().getStringValue().charAt(0) == '<') { 225689e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com if ((invokeType & INVOKE_DIRECT) != 0) { 225789e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com isInit = true; 225889e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com } else { 225989e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot call constructor %s with %s", 226089e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com methodIdItem.getMethodString(), analyzedInstruction.instruction.opcode.name)); 226189e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com } 226289e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com } 226389e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com 226489e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com ClassPath.ClassDef methodClassDef = ClassPath.getClassDef(methodClass); 226589e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com if ((invokeType & INVOKE_INTERFACE) != 0) { 226689e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com if (!methodClassDef.isInterface()) { 226789e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot call method %s with %s. %s is not an interface " + 226889e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com "class.", methodIdItem.getMethodString(), analyzedInstruction.instruction.opcode.name, 226989e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com methodClassDef.getClassType())); 227089e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com } 227189e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com } else { 227289e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com if (methodClassDef.isInterface()) { 227389e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot call method %s with %s. %s is an interface class." + 227489e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com " Use invoke-interface or invoke-interface/range instead.", methodIdItem.getMethodString(), 227589e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com analyzedInstruction.instruction.opcode.name, methodClassDef.getClassType())); 227689e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com } 227789e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com } 227889e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com 227989e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com if ((invokeType & INVOKE_SUPER) != 0) { 2280c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com ClassPath.ClassDef currentMethodClassDef = ClassPath.getClassDef(encodedMethod.method.getContainingClass()); 2281c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com if (currentMethodClassDef.getSuperclass() == null) { 228289e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot call method %s with %s. %s has no superclass", 228389e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com methodIdItem.getMethodString(), analyzedInstruction.instruction.opcode.name, 228489e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com methodClassDef.getSuperclass().getClassType())); 228589e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com } 228689e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com 2287c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com if (!currentMethodClassDef.getSuperclass().extendsClass(methodClassDef)) { 2288c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot call method %s with %s. %s is not an ancestor " + 2289c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com "of the current class %s", methodIdItem.getMethodString(), 2290c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com analyzedInstruction.instruction.opcode.name, methodClass.getTypeDescriptor(), 2291c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com encodedMethod.method.getContainingClass().getTypeDescriptor())); 2292c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com } 2293c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com 2294c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com if (!currentMethodClassDef.getSuperclass().hasVirtualMethod(methodIdItem.getVirtualMethodString())) { 229589e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot call method %s with %s. The superclass %s has" + 229689e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com "no such method", methodIdItem.getMethodString(), 229789e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com analyzedInstruction.instruction.opcode.name, methodClassDef.getSuperclass().getClassType())); 229889e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com } 229989e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com } 230089e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com 230189e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com assert isRange || registers.getCount() <= 5; 230289e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com 230389e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com TypeListItem typeListItem = methodIdItem.getPrototype().getParameters(); 230489e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com int methodParameterRegisterCount; 230589e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com if (typeListItem == null) { 230689e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com methodParameterRegisterCount = 0; 230789e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com } else { 230889e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com methodParameterRegisterCount = typeListItem.getRegisterCount(); 230989e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com } 231089e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com 231189e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com if ((invokeType & INVOKE_STATIC) == 0) { 231289e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com methodParameterRegisterCount++; 231389e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com } 231489e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com 231589e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com if (methodParameterRegisterCount != registers.getCount()) { 231689e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com throw new ValidationException(String.format("The number of registers does not match the number of " + 231789e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com "parameters for method %s. Expecting %d registers, got %d.", methodIdItem.getMethodString(), 231889e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com methodParameterRegisterCount + 1, registers.getCount())); 231989e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com } 232089e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com 232189e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com RegisterType objectRegisterType = null; 232289e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com int objectRegister = 0; 232389e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com if ((invokeType & INVOKE_STATIC) == 0) { 232489e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com objectRegister = registers.getRegister(); 232589e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com registers.moveNext(); 232689e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com 232789e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com objectRegisterType = analyzedInstruction.getPreInstructionRegisterType(objectRegister); 232889e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com assert objectRegisterType != null; 2329c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com if (objectRegisterType.category == RegisterType.Category.UninitRef || 2330c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com objectRegisterType.category == RegisterType.Category.UninitThis) { 2331c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com 233289e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com if (!isInit) { 233389e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot invoke non-<init> method %s on uninitialized " + 233489e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com "reference type %s", methodIdItem.getMethodString(), 233589e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com objectRegisterType.type.getClassType())); 233689e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com } 233789e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com } else if (objectRegisterType.category == RegisterType.Category.Reference) { 233889e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com if (isInit) { 233989e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot invoke %s on initialized reference type %s", 234089e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com methodIdItem.getMethodString(), objectRegisterType.type.getClassType())); 234189e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com } 234289e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com } else if (objectRegisterType.category == RegisterType.Category.Null) { 234389e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com if (isInit) { 234489e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot invoke %s on a null reference", 234589e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com methodIdItem.getMethodString())); 234689e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com } 234789e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com } 234889e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com else { 234989e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot invoke %s on non-reference type %s", 235089e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com methodIdItem.getMethodString(), objectRegisterType.toString())); 235189e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com } 235289e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com 235389e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com if (isInit) { 23547e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com if (objectRegisterType.type.getSuperclass() == methodClassDef) { 23557e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com if (!encodedMethod.method.getMethodName().getStringValue().equals("<init>")) { 235689e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot call %s on type %s. The object type must " + 235789e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com "match the method type exactly", methodIdItem.getMethodString(), 235889e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com objectRegisterType.type.getClassType())); 235989e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com } 236089e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com } 236189e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com } 236289e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com 2363c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com if ((invokeType & INVOKE_INTERFACE) == 0 && objectRegisterType.category != RegisterType.Category.Null && 2364c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com !objectRegisterType.type.extendsClass(methodClassDef)) { 236589e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com 236689e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot call method %s on an object of type %s, which " + 236789e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com "does not extend %s.", methodIdItem.getMethodString(), objectRegisterType.type.getClassType(), 236889e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com methodClassDef.getClassType())); 236989e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com } 237089e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com } 237189e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com 23727e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com if (typeListItem != null) { 23737e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com List<TypeIdItem> parameterTypes = typeListItem.getTypes(); 23747e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com int parameterTypeIndex = 0; 23757e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com while (!registers.pastEnd()) { 23767e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com assert parameterTypeIndex < parameterTypes.size(); 23777e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com RegisterType parameterType = 23787e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com RegisterType.getRegisterTypeForTypeIdItem(parameterTypes.get(parameterTypeIndex)); 237989e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com 23807e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com int register = registers.getRegister(); 238189e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com 23827e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com RegisterType parameterRegisterType; 23837e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com if (WideLowCategories.contains(parameterType.category)) { 23847e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com parameterRegisterType = getAndCheckSourceRegister(analyzedInstruction, register, WideLowCategories); 238589e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com 23867e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com if (!registers.moveNext()) { 23877e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com throw new ValidationException(String.format("No 2nd register specified for wide register pair v%d", 23887e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com parameterTypeIndex+1)); 23897e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com } 23907e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com int nextRegister = registers.getRegister(); 239189e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com 23927e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com if (nextRegister != register + 1) { 23937e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com throw new ValidationException(String.format("Invalid wide register pair (v%d, v%d). Registers " + 23947e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com "must be consecutive.", register, nextRegister)); 23957e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com } 23967e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com } else { 23977e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com parameterRegisterType = analyzedInstruction.getPreInstructionRegisterType(register); 239889e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com } 239989e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com 24007e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com assert parameterRegisterType != null; 240189e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com 24027e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com if (!parameterRegisterType.canBeAssignedTo(parameterType)) { 24037e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com throw new ValidationException( 24047e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com String.format("Invalid register type %s for parameter %d %s.", 24057e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com parameterRegisterType.toString(), parameterTypeIndex+1, 24067e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com parameterType.toString())); 24077e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com } 240889e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com 24097e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com parameterTypeIndex++; 24107e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com registers.moveNext(); 24117e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com } 241289e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com } 241389e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com 241489e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com 241589e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com //TODO: need to ensure the "this" register is initialized, in a constructor method 241689e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com if (isInit) { 241789e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com setRegisterTypeAndPropagateChanges(analyzedInstruction, objectRegister, 241889e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com RegisterType.getRegisterType(RegisterType.Category.Reference, objectRegisterType.type)); 241989e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com 242089e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com for (int i=0; i<analyzedInstruction.postRegisterMap.length; i++) { 242189e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com RegisterType postInstructionRegisterType = analyzedInstruction.postRegisterMap[i]; 242289e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com if (postInstructionRegisterType.category == RegisterType.Category.Unknown) { 242389e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com RegisterType preInstructionRegisterType = 242489e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com analyzedInstruction.getMergedRegisterTypeFromPredecessors(i); 242589e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com 2426c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com if (preInstructionRegisterType.category == RegisterType.Category.UninitRef || 2427c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com preInstructionRegisterType.category == RegisterType.Category.UninitThis) { 2428c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com 242989e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com RegisterType registerType = null; 243089e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com if (preInstructionRegisterType == objectRegisterType) { 243189e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com registerType = analyzedInstruction.postRegisterMap[objectRegister]; 243289e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com } else { 243389e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com registerType = preInstructionRegisterType; 243489e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com } 243589e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com 243689e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com setRegisterTypeAndPropagateChanges(analyzedInstruction, i, registerType); 243789e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com } 243889e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com } 243989e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com } 244089e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com } 244189e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com } 244289e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com 24431483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com private void handleUnaryOp(AnalyzedInstruction analyzedInstruction, EnumSet validSourceCategories, 24441483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com RegisterType.Category destRegisterCategory) { 24451483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com TwoRegisterInstruction instruction = (TwoRegisterInstruction)analyzedInstruction.instruction; 24461483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com 24471483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterB(), validSourceCategories); 244889e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com 24491483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, 24501483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com RegisterType.getRegisterType(destRegisterCategory, null)); 24511483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com } 245289e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com 2453195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com private void handleBinaryOp(AnalyzedInstruction analyzedInstruction, EnumSet validSource1Categories, 2454195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com EnumSet validSource2Categories, RegisterType.Category destRegisterCategory, 2455195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com boolean checkForBoolean) { 2456195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com ThreeRegisterInstruction instruction = (ThreeRegisterInstruction)analyzedInstruction.instruction; 2457195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com 2458195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com RegisterType source1RegisterType = getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterB(), 2459195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com validSource1Categories); 2460195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com RegisterType source2RegisterType = getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterC(), 2461195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com validSource2Categories); 2462195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com 2463195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com if (checkForBoolean) { 2464195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com if (BooleanCategories.contains(source1RegisterType.category) && 2465195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com BooleanCategories.contains(source2RegisterType.category)) { 2466195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com 2467195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com destRegisterCategory = RegisterType.Category.Boolean; 2468195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com } 2469195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com } 2470195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com 2471195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, 2472195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com RegisterType.getRegisterType(destRegisterCategory, null)); 2473195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com } 2474195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com 2475122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com private void handleBinary2AddrOp(AnalyzedInstruction analyzedInstruction, EnumSet validSource1Categories, 2476122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com EnumSet validSource2Categories, RegisterType.Category destRegisterCategory, 2477122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com boolean checkForBoolean) { 2478122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com TwoRegisterInstruction instruction = (TwoRegisterInstruction)analyzedInstruction.instruction; 2479122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com 2480122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com RegisterType source1RegisterType = getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterA(), 2481122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com validSource1Categories); 2482122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com RegisterType source2RegisterType = getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterB(), 2483122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com validSource2Categories); 2484122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com 2485122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com if (checkForBoolean) { 2486122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com if (BooleanCategories.contains(source1RegisterType.category) && 2487122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com BooleanCategories.contains(source2RegisterType.category)) { 2488122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com 2489122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com destRegisterCategory = RegisterType.Category.Boolean; 2490122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com } 2491122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com } 2492122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com 2493122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, 2494122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com RegisterType.getRegisterType(destRegisterCategory, null)); 2495122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com } 2496122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com 2497caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com private void handleLiteralBinaryOp(AnalyzedInstruction analyzedInstruction, EnumSet validSourceCategories, 2498caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com RegisterType.Category destRegisterCategory, boolean checkForBoolean) { 2499caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com TwoRegisterInstruction instruction = (TwoRegisterInstruction)analyzedInstruction.instruction; 2500caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com 2501caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com RegisterType sourceRegisterType = getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterB(), 2502caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com validSourceCategories); 2503caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com 2504caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com if (checkForBoolean) { 2505caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com if (BooleanCategories.contains(sourceRegisterType.category)) { 2506caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com long literal = ((LiteralInstruction)analyzedInstruction.instruction).getLiteral(); 2507caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com if (literal == 0 || literal == 1) { 2508caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com destRegisterCategory = RegisterType.Category.Boolean; 2509caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com } 2510caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com } 2511caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com } 2512caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com 2513caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, 2514caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com RegisterType.getRegisterType(destRegisterCategory, null)); 2515caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com } 2516caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com 2517caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com private RegisterType.Category getDestTypeForLiteralShiftRight(AnalyzedInstruction analyzedInstruction, 2518caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com boolean signedShift) { 2519caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com TwoRegisterInstruction instruction = (TwoRegisterInstruction)analyzedInstruction.instruction; 2520caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com 2521caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com RegisterType sourceRegisterType = getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterB(), 2522caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com Primitive32BitCategories); 2523caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com long literalShift = ((LiteralInstruction)analyzedInstruction.instruction).getLiteral(); 2524caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com 2525caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com if (literalShift == 0) { 2526caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com return sourceRegisterType.category; 2527caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com } 2528caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com 2529caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com RegisterType.Category destRegisterCategory; 2530caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com if (!signedShift) { 2531caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com destRegisterCategory = RegisterType.Category.Integer; 2532caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com } else { 2533caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com destRegisterCategory = sourceRegisterType.category; 2534caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com } 2535caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com 2536caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com if (literalShift >= 32) { 2537caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com //TODO: add warning 2538caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com return destRegisterCategory; 2539caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com } 2540caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com 2541caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com switch (sourceRegisterType.category) { 2542caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com case Integer: 2543caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com case Float: 2544caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com if (!signedShift) { 2545caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com if (literalShift > 24) { 2546caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com return RegisterType.Category.PosByte; 2547caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com } 2548caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com if (literalShift >= 16) { 2549caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com return RegisterType.Category.Char; 2550caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com } 2551caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com } else { 2552caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com if (literalShift >= 24) { 2553caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com return RegisterType.Category.Byte; 2554caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com } 2555caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com if (literalShift >= 16) { 2556caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com return RegisterType.Category.Short; 2557caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com } 2558caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com } 2559caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com break; 2560caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com case Short: 2561caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com if (signedShift && literalShift >= 8) { 2562caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com return RegisterType.Category.Byte; 2563caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com } 2564caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com break; 2565caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com case PosShort: 2566caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com if (literalShift >= 8) { 2567caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com return RegisterType.Category.PosByte; 2568caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com } 2569caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com break; 2570caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com case Char: 2571caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com if (literalShift > 8) { 2572caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com return RegisterType.Category.PosByte; 2573caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com } 2574caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com break; 2575caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com case Byte: 2576caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com break; 2577caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com case PosByte: 2578caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com return RegisterType.Category.PosByte; 2579caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com case Null: 2580caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com case One: 2581caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com case Boolean: 2582caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com return RegisterType.Category.Null; 2583caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com default: 2584caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com assert false; 2585caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com } 2586caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com 2587caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com return destRegisterCategory; 2588caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com } 2589caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com 2590b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com private static boolean checkArrayFieldAssignment(RegisterType.Category arrayFieldCategory, 2591b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com RegisterType.Category instructionCategory) { 2592b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com if (arrayFieldCategory == instructionCategory) { 2593b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com return true; 2594b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com } 2595b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com 2596b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com if ((arrayFieldCategory == RegisterType.Category.Integer && 2597b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com instructionCategory == RegisterType.Category.Float) || 2598b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com (arrayFieldCategory == RegisterType.Category.Float && 2599b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com instructionCategory == RegisterType.Category.Integer)) { 2600b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com return true; 2601b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com } 2602b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com return false; 2603b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com } 2604b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com 260585e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com private static RegisterType getAndCheckSourceRegister(AnalyzedInstruction analyzedInstruction, int registerNumber, 260685e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com EnumSet validCategories) { 260785e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com assert registerNumber >= 0 && registerNumber < analyzedInstruction.postRegisterMap.length; 2608fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 260985e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com RegisterType registerType = analyzedInstruction.getPreInstructionRegisterType(registerNumber); 261085e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com assert registerType != null; 2611fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 261285e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com checkRegister(registerType, registerNumber, validCategories); 2613fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 261485e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com if (validCategories == WideLowCategories) { 261585e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com checkRegister(registerType, registerNumber, WideLowCategories); 261685e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com checkWidePair(registerNumber, analyzedInstruction); 2617fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 261885e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com RegisterType secondRegisterType = analyzedInstruction.getPreInstructionRegisterType(registerNumber + 1); 261985e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com assert secondRegisterType != null; 262085e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com checkRegister(secondRegisterType, registerNumber+1, WideHighCategories); 2621fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 2622fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 262385e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com return registerType; 262485e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com } 2625fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 262685e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com private static void checkRegister(RegisterType registerType, int registerNumber, EnumSet validCategories) { 262785e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com if (!validCategories.contains(registerType.category)) { 262885e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com //TODO: add expected categories to error message 262985e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com throw new ValidationException(String.format("Invalid register type for register v%d. Expecting one of: " + 263085e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com "but got %s", registerNumber, registerType.toString())); 2631fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 263285e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com } 2633d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 263485e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com private static void checkWidePair(int registerNumber, AnalyzedInstruction analyzedInstruction) { 263585e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com if (registerNumber + 1 >= analyzedInstruction.postRegisterMap.length) { 263685e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com throw new ValidationException(String.format("v%d is the last register and not a valid wide register " + 263785e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com "pair.", registerNumber)); 263885e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com } 2639d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com } 2640d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com} 2641