MethodAnalyzer.java revision 300ad56aa3c343a84017ae7a2267dc516b5b6202
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 18300ad56aa3c343a84017ae7a2267dc516b5b6202JesusFreke@JesusFreke.com private BitSet instructionsToVerify; 19300ad56aa3c343a84017ae7a2267dc516b5b6202JesusFreke@JesusFreke.com 20d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com //This is a dummy instruction that occurs immediately before the first real instruction. We can initialize the 21d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com //register types for this instruction to the parameter types, in order to have them propagate to all of its 22d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com //successors, e.g. the first real instruction, the first instructions in any exception handlers covering the first 23d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com //instruction, etc. 24d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com private AnalyzedInstruction startOfMethod; 25d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 26d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com public MethodAnalyzer(ClassDataItem.EncodedMethod encodedMethod) { 27d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com if (encodedMethod == null) { 28d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com throw new IllegalArgumentException("encodedMethod cannot be null"); 29d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com } 30fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (encodedMethod.codeItem == null || encodedMethod.codeItem.getInstructions().length == 0) { 31d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com throw new IllegalArgumentException("The method has no code"); 32d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com } 33d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com this.encodedMethod = encodedMethod; 34d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com buildInstructionList(); 35fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 36fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //override AnalyzedInstruction and provide custom implementations of some of the methods, so that we don't 37fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //have to handle the case this special case of instruction being null, in the main class 38fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com startOfMethod = new AnalyzedInstruction(null, -1, encodedMethod.codeItem.getRegisterCount()) { 39fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com public boolean setsRegister() { 40fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return false; 41fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 42fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 43fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com @Override 44fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com public boolean setsWideRegister() { 45fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return false; 46fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 47fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 48fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com @Override 49fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com public boolean setsRegister(int registerNumber) { 50fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return false; 51fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 52fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 53fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com @Override 54fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com public int getDestinationRegister() { 55fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com assert false; 56fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return -1; 57fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com }; 58fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com }; 59300ad56aa3c343a84017ae7a2267dc516b5b6202JesusFreke@JesusFreke.com 60300ad56aa3c343a84017ae7a2267dc516b5b6202JesusFreke@JesusFreke.com instructionsToVerify = new BitSet(instructions.size()); 61d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com } 62d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 63d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com public AnalyzedInstruction[] analyze() { 64fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com assert encodedMethod != null; 65fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com assert encodedMethod.codeItem != null; 66fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 67fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (analyzed) { 68fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return makeInstructionArray(); 69fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 70fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 71fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com CodeItem codeItem = encodedMethod.codeItem; 72fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com MethodIdItem methodIdItem = encodedMethod.method; 73fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 74fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com int totalRegisters = codeItem.getRegisterCount(); 75fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com int parameterRegisters = methodIdItem.getPrototype().getParameterRegisterCount(); 76fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 77fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //if this isn't a static method, determine which register is the "this" register and set the type to the 78fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //current class 79fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if ((encodedMethod.accessFlags & AccessFlags.STATIC.getValue()) == 0) { 80fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com int thisRegister = totalRegisters - parameterRegisters - 1; 81fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 82fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //if this is a constructor, then set the "this" register to an uninitialized reference of the current class 83fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if ((encodedMethod.accessFlags & AccessFlags.CONSTRUCTOR.getValue()) != 0) { 84fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@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 85fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (!encodedMethod.method.getMethodName().equals("<init>")) { 86fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com throw new ValidationException("The constructor flag can only be used with an <init> method."); 87fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 88fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 89fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com setRegisterTypeAndPropagateChanges(startOfMethod, thisRegister, 90fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType.getRegisterType(RegisterType.Category.UninitRef, 91fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com ClassPath.getClassDef(methodIdItem.getContainingClass()))); 92fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } else { 93fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (encodedMethod.method.getMethodName().equals("<init>")) { 94fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com throw new ValidationException("An <init> method must have the \"constructor\" access flag"); 95fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 96fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 97fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com setRegisterTypeAndPropagateChanges(startOfMethod, thisRegister, 98fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType.getRegisterType(RegisterType.Category.Reference, 99fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com ClassPath.getClassDef(methodIdItem.getContainingClass()))); 100fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 101fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 102fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 103fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com TypeListItem parameters = methodIdItem.getPrototype().getParameters(); 104fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (parameters != null) { 105fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType[] parameterTypes = getParameterTypes(parameters, parameterRegisters); 106fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com for (int i=0; i<parameterTypes.length; i++) { 107fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType registerType = parameterTypes[i]; 108fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com int registerNum = (totalRegisters - parameterRegisters) + i; 109fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com setRegisterTypeAndPropagateChanges(startOfMethod, registerNum, registerType); 110fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 111fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 112fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 113300ad56aa3c343a84017ae7a2267dc516b5b6202JesusFreke@JesusFreke.com BitSet analyzedInstructions = new BitSet(instructionsToVerify.size()); 114300ad56aa3c343a84017ae7a2267dc516b5b6202JesusFreke@JesusFreke.com 115300ad56aa3c343a84017ae7a2267dc516b5b6202JesusFreke@JesusFreke.com //make sure all of the "first instructions" are marked for processing 116300ad56aa3c343a84017ae7a2267dc516b5b6202JesusFreke@JesusFreke.com for (AnalyzedInstruction successor: startOfMethod.successors) { 117300ad56aa3c343a84017ae7a2267dc516b5b6202JesusFreke@JesusFreke.com instructionsToVerify.set(successor.instructionIndex); 118300ad56aa3c343a84017ae7a2267dc516b5b6202JesusFreke@JesusFreke.com } 119300ad56aa3c343a84017ae7a2267dc516b5b6202JesusFreke@JesusFreke.com 120300ad56aa3c343a84017ae7a2267dc516b5b6202JesusFreke@JesusFreke.com while (!instructionsToVerify.isEmpty()) { 121300ad56aa3c343a84017ae7a2267dc516b5b6202JesusFreke@JesusFreke.com for(int i=instructionsToVerify.nextSetBit(0); i>=0; i=instructionsToVerify.nextSetBit(i+1)) { 122300ad56aa3c343a84017ae7a2267dc516b5b6202JesusFreke@JesusFreke.com analyzeInstruction(instructions.get(i)); 123300ad56aa3c343a84017ae7a2267dc516b5b6202JesusFreke@JesusFreke.com } 124300ad56aa3c343a84017ae7a2267dc516b5b6202JesusFreke@JesusFreke.com } 125300ad56aa3c343a84017ae7a2267dc516b5b6202JesusFreke@JesusFreke.com 126fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com analyzed = true; 127fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return makeInstructionArray(); 128fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 129fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 130fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com private int getThisRegister() { 131fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com assert (encodedMethod.accessFlags & AccessFlags.STATIC.getValue()) == 0; 132fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 133fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com CodeItem codeItem = encodedMethod.codeItem; 134fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com assert codeItem != null; 135fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 136fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com MethodIdItem methodIdItem = encodedMethod.method; 137fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com assert methodIdItem != null; 138fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 139fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com int totalRegisters = codeItem.getRegisterCount(); 140fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (totalRegisters == 0) { 141fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com throw new ValidationException("A non-static method must have at least 1 register"); 142fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 143fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 144fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com int parameterRegisters = methodIdItem.getPrototype().getParameterRegisterCount(); 145fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 146fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return totalRegisters - parameterRegisters - 1; 147fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 148fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 149fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com private boolean isInstanceConstructor() { 150fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return (encodedMethod.accessFlags & AccessFlags.STATIC.getValue()) == 0 && 151fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com (encodedMethod.accessFlags & AccessFlags.CONSTRUCTOR.getValue()) != 0; 152fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 153fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 154fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com private boolean isStaticConstructor() { 155fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return (encodedMethod.accessFlags & AccessFlags.STATIC.getValue()) != 0 && 156fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com (encodedMethod.accessFlags & AccessFlags.CONSTRUCTOR.getValue()) != 0; 157fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 158fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 159fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com public AnalyzedInstruction[] makeInstructionArray() { 160fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com AnalyzedInstruction[] instructionArray = new AnalyzedInstruction[instructions.size()]; 161fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com for (int i=0; i<instructions.size(); i++) { 162fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com instructionArray[i] = instructions.valueAt(i); 163fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 164fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return instructionArray; 165fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 166fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 167fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com private static RegisterType[] getParameterTypes(TypeListItem typeListItem, int parameterRegisterCount) { 168fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com assert typeListItem != null; 169fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com assert parameterRegisterCount == typeListItem.getRegisterCount(); 170fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 171fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType[] registerTypes = new RegisterType[parameterRegisterCount]; 172fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 173fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com int registerNum = 0; 174fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com for (TypeIdItem type: typeListItem.getTypes()) { 175fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (type.getRegisterCount() == 2) { 176fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com registerTypes[registerNum++] = RegisterType.getWideRegisterTypeForTypeIdItem(type, true); 177fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com registerTypes[registerNum++] = RegisterType.getWideRegisterTypeForTypeIdItem(type, false); 178fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } else { 179fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com registerTypes[registerNum] = RegisterType.getRegisterTypeForTypeIdItem(type); 180fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 181fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 182fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 183fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return registerTypes; 184fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 185fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 186fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com private int getInstructionAddress(AnalyzedInstruction instruction) { 187fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return instructions.keyAt(instruction.instructionIndex); 188fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 189fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 190fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com private void setWideDestinationRegisterTypeAndPropagateChanges(AnalyzedInstruction analyzedInstruction, 191fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType registerType) { 192fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com assert registerType.category == RegisterType.Category.LongLo || 193fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com registerType.category == RegisterType.Category.DoubleLo; 194fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 195fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com checkWideDestinationPair(analyzedInstruction); 196fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 197fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com setRegisterTypeAndPropagateChanges(analyzedInstruction, analyzedInstruction.getDestinationRegister(), 198fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com registerType); 199fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (registerType.category == RegisterType.Category.LongLo) { 200fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com setRegisterTypeAndPropagateChanges(analyzedInstruction, analyzedInstruction.getDestinationRegister() + 1, 201fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType.getRegisterType(RegisterType.Category.LongHi, null)); 202fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } else { 203fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com setRegisterTypeAndPropagateChanges(analyzedInstruction, analyzedInstruction.getDestinationRegister() + 1, 204fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType.getRegisterType(RegisterType.Category.DoubleHi, null)); 205fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 206fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 207fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 208fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com private void setDestinationRegisterTypeAndPropagateChanges(AnalyzedInstruction analyzedInstruction, 209fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType registerType) { 210fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com setRegisterTypeAndPropagateChanges(analyzedInstruction, analyzedInstruction.getDestinationRegister(), 211fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com registerType); 212fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 213fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 214fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com private void setRegisterTypeAndPropagateChanges(AnalyzedInstruction instruction, int registerNumber, 215fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType registerType) { 216fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 217fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com BitSet changedInstructions = new BitSet(instructions.size()); 218fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 219fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com boolean changed = instruction.setPostRegisterType(registerNumber, registerType); 220fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 221fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (!changed || instruction.setsRegister(registerNumber)) { 222fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return; 223fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 224fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 225fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com propagateRegisterToSuccessors(instruction, registerNumber, changedInstructions); 226fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 227fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //using a for loop inside the while loop optimizes for the common case of the successors of an instruction 228fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //occurring after the instruction. Any successors that occur prior to the instruction will be picked up on 229fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //the next iteration of the while loop. 230fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //this could also be done recursively, but in large methods it would likely cause very deep recursion, 231fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //which would requires the user to specify a larger stack size. This isn't really a problem, but it is 232fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //slightly annoying. 233fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com while (!changedInstructions.isEmpty()) { 234fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com for (int instructionIndex=changedInstructions.nextSetBit(0); 235fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com instructionIndex>=0; 236fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com instructionIndex=changedInstructions.nextSetBit(instructionIndex)) { 237fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 238fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com changedInstructions.clear(instructionIndex); 239fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 240fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com propagateRegisterToSuccessors(instructions.valueAt(instructionIndex), registerNumber, 241fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com changedInstructions); 242fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 243fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 244d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com } 245d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 246fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com private void propagateRegisterToSuccessors(AnalyzedInstruction instruction, int registerNumber, 247fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com BitSet changedInstructions) { 248fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com for (AnalyzedInstruction successor: instruction.successors) { 249fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (!successor.setsRegister(registerNumber)) { 250fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType registerType = successor.getMergedRegisterTypeFromPredecessors(registerNumber); 251fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 252fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (successor.setPostRegisterType(registerNumber, registerType)) { 253fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com changedInstructions.set(successor.instructionIndex); 254300ad56aa3c343a84017ae7a2267dc516b5b6202JesusFreke@JesusFreke.com instructionsToVerify.set(successor.instructionIndex); 255fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 256fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 257fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 258fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 259fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 260fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 261fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 262d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com private void buildInstructionList() { 263d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com assert encodedMethod != null; 264d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com assert encodedMethod.codeItem != null; 265fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com int registerCount = encodedMethod.codeItem.getRegisterCount(); 266d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 267fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com startOfMethod = new AnalyzedInstruction(null, -1, registerCount); 268d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 269d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com Instruction[] insns = encodedMethod.codeItem.getInstructions(); 270d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 271fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com instructions = new SparseArray<AnalyzedInstruction>(insns.length); 272d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 273d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com //first, create all the instructions and populate the instructionAddresses array 274d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com int currentCodeAddress = 0; 275d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com for (int i=0; i<insns.length; i++) { 276fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com instructions.append(currentCodeAddress, new AnalyzedInstruction(insns[i], i, registerCount)); 277fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com assert instructions.indexOfKey(currentCodeAddress) == i; 278d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com currentCodeAddress += insns[i].getSize(currentCodeAddress); 279d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com } 280d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 281d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com //next, populate the exceptionHandlers array. The array item for each instruction that can throw an exception 282d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com //and is covered by a try block should be set to a list of the first instructions of each exception handler 283d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com //for the try block covering the instruction 284d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com CodeItem.TryItem[] tries = encodedMethod.codeItem.getTries(); 285d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com int triesIndex = 0; 286d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com CodeItem.TryItem currentTry = null; 287fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com AnalyzedInstruction[] currentExceptionHandlers = null; 288fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com AnalyzedInstruction[][] exceptionHandlers = new AnalyzedInstruction[insns.length][]; 289d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 290fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com for (int i=0; i<instructions.size(); i++) { 291fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com AnalyzedInstruction instruction = instructions.valueAt(i); 292d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com Opcode instructionOpcode = instruction.instruction.opcode; 293d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 294d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com //check if we have gone past the end of the current try 295d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com if (currentTry != null) { 296d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com if (currentTry.getStartCodeAddress() + currentTry.getTryLength() <= currentCodeAddress) { 297d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com currentTry = null; 298d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com triesIndex++; 299d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com } 300d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com } 301d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 302d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com //check if the next try is applicable yet 303d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com if (currentTry == null && triesIndex < tries.length) { 304d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com CodeItem.TryItem tryItem = tries[triesIndex]; 305d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com if (tryItem.getStartCodeAddress() <= currentCodeAddress) { 306d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com assert(tryItem.getStartCodeAddress() + tryItem.getTryLength() > currentCodeAddress); 307d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 308d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com currentTry = tryItem; 309d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 310d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com currentExceptionHandlers = buildExceptionHandlerArray(tryItem); 311d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com } 312d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com } 313d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 314d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com //if we're inside a try block, and the instruction can throw an exception, then add the exception handlers 315d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com //for the current instruction 316d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com if (currentTry != null && instructionOpcode.canThrow()) { 317d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com exceptionHandlers[i] = currentExceptionHandlers; 318d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com } 319d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com } 320d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 321d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com //finally, populate the successors and predecessors for each instruction 322fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com assert instructions.size() > 0; 323fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com addPredecessorSuccessor(startOfMethod, instructions.valueAt(0), exceptionHandlers); 324fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com startOfMethod.addSuccessor(instructions.valueAt(0)); 325fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 326fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com for (int i=0; i<instructions.size(); i++) { 327fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com AnalyzedInstruction instruction = instructions.valueAt(i); 328d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com Opcode instructionOpcode = instruction.instruction.opcode; 329fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com int instructionCodeAddress = getInstructionAddress(instruction); 330d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 331d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com if (instruction.instruction.opcode.canContinue()) { 332fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (i == instructions.size() - 1) { 333d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com throw new ValidationException("Execution can continue past the last instruction"); 334d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com } 335fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com AnalyzedInstruction nextInstruction = instructions.valueAt(i+1); 336fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com addPredecessorSuccessor(instruction, nextInstruction, exceptionHandlers); 337d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com } 338d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 339d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com if (instruction instanceof OffsetInstruction) { 340d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com OffsetInstruction offsetInstruction = (OffsetInstruction)instruction; 341d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 342d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com if (instructionOpcode == Opcode.PACKED_SWITCH || instructionOpcode == Opcode.SPARSE_SWITCH) { 343d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com MultiOffsetInstruction switchDataInstruction = 344fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com (MultiOffsetInstruction)instructions.get(instructionCodeAddress + 345d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com offsetInstruction.getTargetAddressOffset()).instruction; 346d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com for (int targetAddressOffset: switchDataInstruction.getTargets()) { 347fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com AnalyzedInstruction targetInstruction = instructions.get(instructionCodeAddress + 348d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com targetAddressOffset); 349d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 350fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com addPredecessorSuccessor(instruction, targetInstruction, exceptionHandlers); 351d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com } 352d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com } else { 353d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com int targetAddressOffset = offsetInstruction.getTargetAddressOffset(); 354fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com AnalyzedInstruction targetInstruction = instructions.get(instructionCodeAddress + 355fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com targetAddressOffset); 356fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com addPredecessorSuccessor(instruction, targetInstruction, exceptionHandlers); 357d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com } 358d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com } 359d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com } 360d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com } 361d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 362d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com private void addPredecessorSuccessor(AnalyzedInstruction predecessor, AnalyzedInstruction successor, 363fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com AnalyzedInstruction[][] exceptionHandlers) { 364fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com addPredecessorSuccessor(predecessor, successor, exceptionHandlers, false); 365fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 366fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 367fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com private void addPredecessorSuccessor(AnalyzedInstruction predecessor, AnalyzedInstruction successor, 368fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com AnalyzedInstruction[][] exceptionHandlers, boolean allowMoveException) { 369fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 370fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (!allowMoveException && successor.instruction.opcode == Opcode.MOVE_EXCEPTION) { 371fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com throw new ValidationException("Execution can pass from the " + predecessor.instruction.opcode.name + 372fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com " instruction at code address 0x" + Integer.toHexString(getInstructionAddress(predecessor)) + 373fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com " to the move-exception instruction at address 0x" + 374fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com Integer.toHexString(getInstructionAddress(successor))); 375fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 376d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 377d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com if (!predecessor.addSuccessor(successor)) { 378d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com //if predecessor already had successor as a successor, then there's nothing else to do 379d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com return; 380d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com } 381d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 382d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com successor.addPredecessor(predecessor); 383d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 384fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //TODO: need to handle the case of monitor-exit as a special case - the exception is thrown *after* the instruction executes 385d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com //if the successor can throw an instruction, then we need to add the exception handlers as additional 386d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com //successors to the predecessor (and then apply this same logic recursively if needed) 387fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com AnalyzedInstruction[] exceptionHandlersForSuccessor = exceptionHandlers[successor.instructionIndex]; 388d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com if (exceptionHandlersForSuccessor != null) { 389d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com //the item for this instruction in exceptionHandlersForSuccessor should only be set if this instruction 390d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com //can throw an exception 391d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com assert predecessor.instruction.opcode.canThrow(); 392d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 393fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com for (AnalyzedInstruction exceptionHandler: exceptionHandlersForSuccessor) { 394fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com addPredecessorSuccessor(predecessor, exceptionHandler, exceptionHandlers, true); 395d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com } 396d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com } 397d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com } 398d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 399fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com private AnalyzedInstruction[] buildExceptionHandlerArray(CodeItem.TryItem tryItem) { 400d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com int exceptionHandlerCount = tryItem.encodedCatchHandler.handlers.length; 401d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com int catchAllHandler = tryItem.encodedCatchHandler.getCatchAllHandlerAddress(); 402d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com if (catchAllHandler != -1) { 403d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com exceptionHandlerCount++; 404d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com } 405d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 406fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com AnalyzedInstruction[] exceptionHandlers = new AnalyzedInstruction[exceptionHandlerCount]; 407d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com for (int i=0; i<tryItem.encodedCatchHandler.handlers.length; i++) { 408fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com exceptionHandlers[i] = instructions.get(tryItem.encodedCatchHandler.handlers[i].getHandlerAddress()); 409d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com } 410d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 411d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com if (catchAllHandler != -1) { 412fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com exceptionHandlers[exceptionHandlers.length - 1] = instructions.get(catchAllHandler); 413d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com } 414d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 415d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com return exceptionHandlers; 416d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com } 417d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 418300ad56aa3c343a84017ae7a2267dc516b5b6202JesusFreke@JesusFreke.com private boolean analyzeInstruction(AnalyzedInstruction analyzedInstruction) { 419fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com Instruction instruction = analyzedInstruction.instruction; 420fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 421fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com switch (instruction.opcode) { 422fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case NOP: 423fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return true; 424fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case MOVE: 425fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case MOVE_FROM16: 426fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case MOVE_16: 427fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return handleMove(analyzedInstruction, Primitive32BitCategories); 428fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case MOVE_WIDE: 429fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case MOVE_WIDE_FROM16: 430fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case MOVE_WIDE_16: 431fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return handleMoveWide(analyzedInstruction); 432fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case MOVE_OBJECT: 433fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case MOVE_OBJECT_FROM16: 434fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case MOVE_OBJECT_16: 435fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return handleMove(analyzedInstruction, ReferenceCategories); 436fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case MOVE_RESULT: 437fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return handleMoveResult(analyzedInstruction, Primitive32BitCategories); 438fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case MOVE_RESULT_WIDE: 439fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return handleMoveResult(analyzedInstruction, WideLowCategories); 440fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case MOVE_RESULT_OBJECT: 441fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return handleMoveResult(analyzedInstruction, ReferenceCategories); 442fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case MOVE_EXCEPTION: 443fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return handleMoveException(analyzedInstruction); 444fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case RETURN_VOID: 445fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return handleReturnVoid(analyzedInstruction); 446fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case RETURN: 447fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return handleReturn(analyzedInstruction); 448fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case RETURN_WIDE: 449fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return handleReturnWide(analyzedInstruction); 450fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case RETURN_OBJECT: 451fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return handleReturnObject(analyzedInstruction); 452fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case CONST_4: 453fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case CONST_16: 454fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case CONST: 455fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return handleConst(analyzedInstruction); 456fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case CONST_HIGH16: 457fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return handleConstHigh16(analyzedInstruction); 458fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case CONST_WIDE_16: 459fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case CONST_WIDE_32: 460fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case CONST_WIDE: 461fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case CONST_WIDE_HIGH16: 462fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return handleWideConst(analyzedInstruction); 463fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case CONST_STRING: 464fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case CONST_STRING_JUMBO: 465fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return handleConstString(analyzedInstruction); 466fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case CONST_CLASS: 467fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return handleConstClass(analyzedInstruction); 468fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case MONITOR_ENTER: 469fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case MONITOR_EXIT: 470fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return handleMonitor(analyzedInstruction); 471fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case CHECK_CAST: 472fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return handleCheckCast(analyzedInstruction); 473fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case INSTANCE_OF: 474fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return handleInstanceOf(analyzedInstruction); 475fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case ARRAY_LENGTH: 476fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return handleArrayLength(analyzedInstruction); 477fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case NEW_INSTANCE: 478fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return handleNewInstance(analyzedInstruction); 479fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com case NEW_ARRAY: 480fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return handleNewArray(analyzedInstruction); 4819e5dd85d837501e84e18617fc136c8203ab1f183JesusFreke@JesusFreke.com case FILLED_NEW_ARRAY: 4829e5dd85d837501e84e18617fc136c8203ab1f183JesusFreke@JesusFreke.com return handleFilledNewArray(analyzedInstruction); 483ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com case FILLED_NEW_ARRAY_RANGE: 484ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com return handleFilledNewArrayRange(analyzedInstruction); 485472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com case FILL_ARRAY_DATA: 486472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com return handleFillArrayData(analyzedInstruction); 487ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com case THROW: 488ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com return handleThrow(analyzedInstruction); 489898edda7cea48c02687bb71804a98cfd6e260b89JesusFreke@JesusFreke.com case GOTO: 490898edda7cea48c02687bb71804a98cfd6e260b89JesusFreke@JesusFreke.com case GOTO_16: 491898edda7cea48c02687bb71804a98cfd6e260b89JesusFreke@JesusFreke.com case GOTO_32: 492898edda7cea48c02687bb71804a98cfd6e260b89JesusFreke@JesusFreke.com //nothing to do 493898edda7cea48c02687bb71804a98cfd6e260b89JesusFreke@JesusFreke.com return true; 494cda44f70cfebfae4875cd77455a171075aebac4dJesusFreke@JesusFreke.com case PACKED_SWITCH: 495cda44f70cfebfae4875cd77455a171075aebac4dJesusFreke@JesusFreke.com return handleSwitch(analyzedInstruction, Format.PackedSwitchData); 496cda44f70cfebfae4875cd77455a171075aebac4dJesusFreke@JesusFreke.com case SPARSE_SWITCH: 497cda44f70cfebfae4875cd77455a171075aebac4dJesusFreke@JesusFreke.com return handleSwitch(analyzedInstruction, Format.SparseSwitchData); 498f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com case CMPL_FLOAT: 499f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com case CMPG_FLOAT: 500f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com return handleFloatCmp(analyzedInstruction); 501f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com case CMPL_DOUBLE: 502f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com case CMPG_DOUBLE: 503f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com case CMP_LONG: 504f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com return handleWideCmp(analyzedInstruction); 505aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com case IF_EQ: 506aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com case IF_NE: 507aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com return handleIfEqNe(analyzedInstruction); 508150acd9db94f9886f6fc32e89acc15a1a5c1466fJesusFreke@JesusFreke.com case IF_LT: 509150acd9db94f9886f6fc32e89acc15a1a5c1466fJesusFreke@JesusFreke.com case IF_GE: 510150acd9db94f9886f6fc32e89acc15a1a5c1466fJesusFreke@JesusFreke.com case IF_GT: 511150acd9db94f9886f6fc32e89acc15a1a5c1466fJesusFreke@JesusFreke.com case IF_LE: 512150acd9db94f9886f6fc32e89acc15a1a5c1466fJesusFreke@JesusFreke.com return handleIf(analyzedInstruction); 513cb00252b6aed86cd3e7c426015cea83fcdbaa806JesusFreke@JesusFreke.com case IF_EQZ: 514cb00252b6aed86cd3e7c426015cea83fcdbaa806JesusFreke@JesusFreke.com case IF_NEZ: 515cb00252b6aed86cd3e7c426015cea83fcdbaa806JesusFreke@JesusFreke.com return handleIfEqzNez(analyzedInstruction); 51616a709ba046343bfefc15a6cdb0be38282126223JesusFreke@JesusFreke.com case IF_LTZ: 51716a709ba046343bfefc15a6cdb0be38282126223JesusFreke@JesusFreke.com case IF_GEZ: 51816a709ba046343bfefc15a6cdb0be38282126223JesusFreke@JesusFreke.com case IF_GTZ: 51916a709ba046343bfefc15a6cdb0be38282126223JesusFreke@JesusFreke.com case IF_LEZ: 52016a709ba046343bfefc15a6cdb0be38282126223JesusFreke@JesusFreke.com return handleIfz(analyzedInstruction); 521b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com case AGET: 522b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com return handle32BitPrimitiveAget(analyzedInstruction, RegisterType.Category.Integer); 523b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com case AGET_BOOLEAN: 524b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com return handle32BitPrimitiveAget(analyzedInstruction, RegisterType.Category.Boolean); 525b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com case AGET_BYTE: 526b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com return handle32BitPrimitiveAget(analyzedInstruction, RegisterType.Category.Byte); 527b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com case AGET_CHAR: 528b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com return handle32BitPrimitiveAget(analyzedInstruction, RegisterType.Category.Char); 529b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com case AGET_SHORT: 530b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com return handle32BitPrimitiveAget(analyzedInstruction, RegisterType.Category.Short); 531c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com case AGET_WIDE: 532c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com return handleAgetWide(analyzedInstruction); 533461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com case AGET_OBJECT: 534461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com return handleAgetObject(analyzedInstruction); 535c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com case APUT: 536c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com return handle32BitPrimitiveAput(analyzedInstruction, RegisterType.Category.Integer); 537c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com case APUT_BOOLEAN: 538c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com return handle32BitPrimitiveAput(analyzedInstruction, RegisterType.Category.Boolean); 539c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com case APUT_BYTE: 540c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com return handle32BitPrimitiveAput(analyzedInstruction, RegisterType.Category.Byte); 541c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com case APUT_CHAR: 542c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com return handle32BitPrimitiveAput(analyzedInstruction, RegisterType.Category.Char); 543c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com case APUT_SHORT: 544c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com return handle32BitPrimitiveAput(analyzedInstruction, RegisterType.Category.Short); 54555d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com case APUT_WIDE: 54655d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com return handleAputWide(analyzedInstruction); 547898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com case APUT_OBJECT: 548898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com return handleAputObject(analyzedInstruction); 5494f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com case IGET: 5504f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com return handle32BitPrimitiveIget(analyzedInstruction, RegisterType.Category.Integer); 5514f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com case IGET_BOOLEAN: 5524f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com return handle32BitPrimitiveIget(analyzedInstruction, RegisterType.Category.Boolean); 5534f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com case IGET_BYTE: 5544f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com return handle32BitPrimitiveIget(analyzedInstruction, RegisterType.Category.Byte); 5554f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com case IGET_CHAR: 5564f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com return handle32BitPrimitiveIget(analyzedInstruction, RegisterType.Category.Char); 5574f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com case IGET_SHORT: 5584f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com return handle32BitPrimitiveIget(analyzedInstruction, RegisterType.Category.Short); 5599d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com case IGET_WIDE: 5609d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com return handleIgetWide(analyzedInstruction); 5617a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com case IGET_OBJECT: 5627a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com return handleIgetObject(analyzedInstruction); 5639971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com case IPUT: 5649971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com return handle32BitPrimitiveIput(analyzedInstruction, RegisterType.Category.Integer); 5659971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com case IPUT_BOOLEAN: 5669971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com return handle32BitPrimitiveIput(analyzedInstruction, RegisterType.Category.Boolean); 5679971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com case IPUT_BYTE: 5689971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com return handle32BitPrimitiveIput(analyzedInstruction, RegisterType.Category.Byte); 5699971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com case IPUT_CHAR: 5709971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com return handle32BitPrimitiveIput(analyzedInstruction, RegisterType.Category.Char); 5719971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com case IPUT_SHORT: 5729971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com return handle32BitPrimitiveIput(analyzedInstruction, RegisterType.Category.Short); 57392616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com case IPUT_WIDE: 57492616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com return handleIputWide(analyzedInstruction); 57550ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com case IPUT_OBJECT: 57650ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com return handleIputObject(analyzedInstruction); 577052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com case SGET: 578052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com return handle32BitPrimitiveSget(analyzedInstruction, RegisterType.Category.Integer); 579052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com case SGET_BOOLEAN: 580052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com return handle32BitPrimitiveSget(analyzedInstruction, RegisterType.Category.Boolean); 581052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com case SGET_BYTE: 582052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com return handle32BitPrimitiveSget(analyzedInstruction, RegisterType.Category.Byte); 583052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com case SGET_CHAR: 584052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com return handle32BitPrimitiveSget(analyzedInstruction, RegisterType.Category.Char); 585052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com case SGET_SHORT: 586052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com return handle32BitPrimitiveSget(analyzedInstruction, RegisterType.Category.Short); 5872f233fefd9d73af8fab4037a6f874b161b98b259JesusFreke@JesusFreke.com case SGET_WIDE: 5882f233fefd9d73af8fab4037a6f874b161b98b259JesusFreke@JesusFreke.com return handleSgetWide(analyzedInstruction); 5892d6d6eb22c86c79344b85ffe46fdd4268566bd0fJesusFreke@JesusFreke.com case SGET_OBJECT: 5902d6d6eb22c86c79344b85ffe46fdd4268566bd0fJesusFreke@JesusFreke.com return handleSgetObject(analyzedInstruction); 5919d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com case SPUT: 5929d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com return handle32BitPrimitiveSput(analyzedInstruction, RegisterType.Category.Integer); 5939d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com case SPUT_BOOLEAN: 5949d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com return handle32BitPrimitiveSput(analyzedInstruction, RegisterType.Category.Boolean); 5959d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com case SPUT_BYTE: 5969d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com return handle32BitPrimitiveSput(analyzedInstruction, RegisterType.Category.Byte); 5979d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com case SPUT_CHAR: 5989d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com return handle32BitPrimitiveSput(analyzedInstruction, RegisterType.Category.Char); 5999d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com case SPUT_SHORT: 6009d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com return handle32BitPrimitiveSput(analyzedInstruction, RegisterType.Category.Short); 601f08a9e1c2c130a5ed5923999fec0283f91b48a09JesusFreke@JesusFreke.com case SPUT_WIDE: 602f08a9e1c2c130a5ed5923999fec0283f91b48a09JesusFreke@JesusFreke.com return handleSputWide(analyzedInstruction); 60351cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com case SPUT_OBJECT: 60451cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com return handleSputObject(analyzedInstruction); 605fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 606b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com 607fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com assert false; 608fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return false; 609fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 610fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 611fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com private static final EnumSet<RegisterType.Category> Primitive32BitCategories = EnumSet.of( 612fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType.Category.Null, 613fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType.Category.Boolean, 614fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType.Category.Byte, 615fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType.Category.Short, 616fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType.Category.Char, 617fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType.Category.Integer, 618fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType.Category.Float); 619fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 620fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com private static final EnumSet<RegisterType.Category> WideLowCategories = EnumSet.of( 621fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType.Category.LongLo, 622fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType.Category.DoubleLo); 623fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 624fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com private static final EnumSet<RegisterType.Category> WideHighCategories = EnumSet.of( 625fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType.Category.LongHi, 626fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType.Category.DoubleHi); 627fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 628fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com private static final EnumSet<RegisterType.Category> ReferenceCategories = EnumSet.of( 629fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType.Category.Null, 630fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType.Category.Reference); 631fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 632fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com private boolean handleMove(AnalyzedInstruction analyzedInstruction, 633fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com EnumSet<RegisterType.Category> allowedCategories) { 634fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com TwoRegisterInstruction instruction = (TwoRegisterInstruction)analyzedInstruction.instruction; 635fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 636fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //get the "pre-instruction" register type for the source register 637fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType sourceRegisterType = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterB()); 638fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com assert sourceRegisterType != null; 639fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 640fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (sourceRegisterType.category == RegisterType.Category.Unknown) { 641fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //we don't know the source register type yet, so we can't verify it. Return false, and we'll come back later 642fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return false; 643fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 644d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 645fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com checkRegister(sourceRegisterType, allowedCategories); 646d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 647fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, sourceRegisterType); 648fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return true; 649fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 650fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 651fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com private boolean handleMoveWide(AnalyzedInstruction analyzedInstruction) { 652fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com TwoRegisterInstruction instruction = (TwoRegisterInstruction)analyzedInstruction.instruction; 653fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 654fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType sourceRegisterType = getAndCheckWideSourcePair(analyzedInstruction, 655fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com instruction.getRegisterB()); 656fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com assert sourceRegisterType != null; 657fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 658fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (sourceRegisterType.category == RegisterType.Category.Unknown) { 659fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //we don't know the source register type yet, so we can't verify it. Return false, and we'll come back later 660fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return false; 661fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 662fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 663fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com checkWideDestinationPair(analyzedInstruction); 664fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 665fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, sourceRegisterType); 666fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return true; 667fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 668fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 669fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com private boolean handleMoveResult(AnalyzedInstruction analyzedInstruction, 670fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com EnumSet<RegisterType.Category> allowedCategories) { 671fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 672fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //TODO: handle the case when the previous instruction is an odexed instruction 673fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 674fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (analyzedInstruction.instructionIndex == 0) { 675fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com throw new ValidationException(analyzedInstruction.instruction.opcode.name + " cannot be the first " + 676fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com "instruction in a method. It must occur after an invoke-*/fill-new-array instruction"); 677fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 678fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 679fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com AnalyzedInstruction previousInstruction = instructions.valueAt(analyzedInstruction.instructionIndex-1); 680fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 681fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (!previousInstruction.instruction.opcode.setsResult()) { 682fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com throw new ValidationException(analyzedInstruction.instruction.opcode.name + " must occur after an " + 683fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com "invoke-*/fill-new-array instruction"); 684fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 685fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 686fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (analyzedInstruction.instruction.opcode.setsWideRegister()) { 687fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com checkWideDestinationPair(analyzedInstruction); 688fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 689fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 690fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //TODO: does dalvik allow a move-result after an invoke with a void return type? 691fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType destinationRegisterType; 692fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 693fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com InstructionWithReference invokeInstruction = (InstructionWithReference)previousInstruction.instruction; 694fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com Item item = invokeInstruction.getReferencedItem(); 695fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 696fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (item instanceof MethodIdItem) { 697fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com destinationRegisterType = RegisterType.getRegisterTypeForTypeIdItem( 698fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com ((MethodIdItem)item).getPrototype().getReturnType()); 699fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } else { 700fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com assert item instanceof TypeIdItem; 701fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com destinationRegisterType = RegisterType.getRegisterTypeForTypeIdItem((TypeIdItem)item); 702fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 703fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 704fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com checkRegister(destinationRegisterType, allowedCategories); 705fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, destinationRegisterType); 706fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return true; 707fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 708fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 709fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com private boolean handleMoveException(AnalyzedInstruction analyzedInstruction) { 710fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com CodeItem.TryItem[] tries = encodedMethod.codeItem.getTries(); 711fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com int instructionAddress = getInstructionAddress(analyzedInstruction); 712fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 713fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (tries == null) { 714fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com throw new ValidationException("move-exception must be the first instruction in an exception handler block"); 715fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 716fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 717fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType exceptionType = null; 718fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 719fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com for (CodeItem.TryItem tryItem: encodedMethod.codeItem.getTries()) { 720fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (tryItem.encodedCatchHandler.getCatchAllHandlerAddress() == instructionAddress) { 721fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com exceptionType = RegisterType.getRegisterType(RegisterType.Category.Reference, 722fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com ClassPath.getClassDef("Ljava/lang/Throwable;")); 723fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com break; 724fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 725fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com for (CodeItem.EncodedTypeAddrPair handler: tryItem.encodedCatchHandler.handlers) { 726fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (handler.getHandlerAddress() == instructionAddress) { 727fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com exceptionType = RegisterType.getRegisterTypeForTypeIdItem(handler.exceptionType) 728fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com .merge(exceptionType); 729fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 730fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 731fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 732fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 733fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@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) 734fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com checkRegister(exceptionType, ReferenceCategories); 735fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, exceptionType); 736fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return true; 737fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 738fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 739fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com private boolean checkConstructorReturn(AnalyzedInstruction analyzedInstruction) { 740fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com assert this.isInstanceConstructor(); 741fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 742fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //if we're in an instance constructor (an <init> method), then the superclass <init> must have been called. 743fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //When execution enters the method, the "this" register is set as an uninitialized reference to the containing 744fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //class. Once the superclass' <init> is called, the "this" register is upgraded to a full-blown reference type, 745fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //so we need to ensure that the "this" register isn't an uninitialized reference 746fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 747fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com int thisRegister = getThisRegister(); 748fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType thisRegisterType = analyzedInstruction.postRegisterMap[thisRegister]; 749fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 750fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (thisRegisterType.category == RegisterType.Category.Unknown) { 751fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //we don't have enough information yet, so return false. We'll come back later 752fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return false; 753fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 754fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (thisRegisterType.category == RegisterType.Category.UninitRef) { 755fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com throw new ValidationException("Returning from constructor without calling the superclass' <init>"); 756fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 757fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com assert thisRegisterType.category == RegisterType.Category.Reference; 758fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com assert thisRegisterType.type == ClassPath.getClassDef(encodedMethod.method.getContainingClass()); 759fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return true; 760fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 761fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 762fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com private boolean handleReturnVoid(AnalyzedInstruction analyzedInstruction) { 763fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (this.isInstanceConstructor()) { 764fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (!checkConstructorReturn(analyzedInstruction)) { 765fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return false; 766fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 767fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 768fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 769fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com TypeIdItem returnType = encodedMethod.method.getPrototype().getReturnType(); 770fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (returnType.getTypeDescriptor().charAt(0) != 'V') { 771fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //TODO: could add which return-* variation should be used instead 772fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com throw new ValidationException("Cannot use return-void with a non-void return type (" + 773fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com returnType.getTypeDescriptor() + ")"); 774fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 775fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return true; 776fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 777fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 778fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com private boolean handleReturn(AnalyzedInstruction analyzedInstruction) { 779fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (this.isInstanceConstructor()) { 780fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (!checkConstructorReturn(analyzedInstruction)) { 781fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return false; 782fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 783fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 784fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 785fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com SingleRegisterInstruction instruction = (SingleRegisterInstruction)analyzedInstruction.instruction; 786fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType returnRegisterType = analyzedInstruction.postRegisterMap[instruction.getRegisterA()]; 787fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 788fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (returnRegisterType.category == RegisterType.Category.Unknown) { 789fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return false; 790fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 791fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 792fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com checkRegister(returnRegisterType, Primitive32BitCategories); 793fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 794fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com TypeIdItem returnType = encodedMethod.method.getPrototype().getReturnType(); 795fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (returnType.getTypeDescriptor().charAt(0) == 'V') { 796fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com throw new ValidationException("Cannot use return with a void return type. Use return-void instead"); 797fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 798fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 799fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType registerType = RegisterType.getRegisterTypeForTypeIdItem(returnType); 800fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 801fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (!Primitive32BitCategories.contains(registerType.category)) { 802fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //TODO: could add which return-* variation should be used instead 803fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com throw new ValidationException("Cannot use return with return type " + returnType.getTypeDescriptor()); 804fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 805fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 806fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 807fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return true; 808fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 809fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 810fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com private boolean handleReturnWide(AnalyzedInstruction analyzedInstruction) { 811fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (this.isInstanceConstructor()) { 812fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (!checkConstructorReturn(analyzedInstruction)) { 813fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return false; 814fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 815fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 816fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 817fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com SingleRegisterInstruction instruction = (SingleRegisterInstruction)analyzedInstruction.instruction; 818fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType returnType = getAndCheckWideSourcePair(analyzedInstruction, instruction.getRegisterA()); 819fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 820fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (returnType.category == RegisterType.Category.Unknown) { 821fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return false; 822fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 823fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 824fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 825fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com TypeIdItem returnTypeIdItem = encodedMethod.method.getPrototype().getReturnType(); 826fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (returnTypeIdItem.getTypeDescriptor().charAt(0) == 'V') { 827fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com throw new ValidationException("Cannot use return-wide with a void return type. Use return-void instead"); 828fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 829fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 830fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com returnType = RegisterType.getRegisterTypeForTypeIdItem(returnTypeIdItem); 831fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (!WideLowCategories.contains(returnType.category)) { 832fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //TODO: could add which return-* variation should be used instead 833fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com throw new ValidationException("Cannot use return-wide with return type " + 834fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com returnTypeIdItem.getTypeDescriptor()); 835fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 836fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 837fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return true; 838fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 839fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 840fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com private boolean handleReturnObject(AnalyzedInstruction analyzedInstruction) { 841fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (this.isInstanceConstructor()) { 842fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (!checkConstructorReturn(analyzedInstruction)) { 843fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return false; 844fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 845fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 846fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 847fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com SingleRegisterInstruction instruction = (SingleRegisterInstruction)analyzedInstruction.instruction; 848fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com int returnRegister = instruction.getRegisterA(); 849fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType returnRegisterType = analyzedInstruction.postRegisterMap[returnRegister]; 850fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 851fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (returnRegisterType.category == RegisterType.Category.Unknown) { 852fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return false; 853fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 854fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 855fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com checkRegister(returnRegisterType, ReferenceCategories); 856fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 857fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 858fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com TypeIdItem returnTypeIdItem = encodedMethod.method.getPrototype().getReturnType(); 859fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (returnTypeIdItem.getTypeDescriptor().charAt(0) == 'V') { 860fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com throw new ValidationException("Cannot use return with a void return type. Use return-void instead"); 861fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 862fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 863fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType returnType = RegisterType.getRegisterTypeForTypeIdItem(returnTypeIdItem); 864fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 865fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (!ReferenceCategories.contains(returnType.category)) { 866fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //TODO: could add which return-* variation should be used instead 867fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com throw new ValidationException("Cannot use " + analyzedInstruction + " with return type " + 868fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com returnTypeIdItem.getTypeDescriptor()); 869fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 870fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 871fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (returnType.type.isInterface()) { 872fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (!returnRegisterType.type.implementsInterface(returnType.type)) { 873fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //TODO: how to handle warnings? 874fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 875fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } else { 876fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (!returnRegisterType.type.extendsClass(returnType.type)) { 877fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com throw new ValidationException("The return value in register v" + Integer.toString(returnRegister) + 878fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com "(" + returnRegisterType.type.getClassType() + ") is not compatible with the method's return " + 879fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com "type (" + returnType.type.getClassType() + ")"); 880fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 881fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 882fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 883fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return true; 884fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 885fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 886fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com private boolean handleConst(AnalyzedInstruction analyzedInstruction) { 887fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com LiteralInstruction instruction = (LiteralInstruction)analyzedInstruction.instruction; 888fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 889fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType newDestinationRegisterType = RegisterType.getRegisterTypeForLiteral(instruction.getLiteral()); 890fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 891fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //we assume that the literal value is a valid value for the given instruction type, because it's impossible 892fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //to store an invalid literal with the instruction. so we don't need to check the type of the literal 893fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, newDestinationRegisterType); 894fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return true; 895fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 896fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 897fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com private boolean handleConstHigh16(AnalyzedInstruction analyzedInstruction) { 898fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com LiteralInstruction instruction = (LiteralInstruction)analyzedInstruction.instruction; 899fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 900fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //TODO: test this 901fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com long literalValue = instruction.getLiteral() << 16; 902fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType newDestinationRegisterType = RegisterType.getRegisterTypeForLiteral(literalValue); 903fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 904fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //we assume that the literal value is a valid value for the given instruction type, because it's impossible 905fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //to store an invalid literal with the instruction. so we don't need to check the type of the literal 906fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, newDestinationRegisterType); 907fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return true; 908fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 909fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 910fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com private boolean handleWideConst(AnalyzedInstruction analyzedInstruction) { 911fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com setWideDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, 912fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType.getRegisterType(RegisterType.Category.LongLo, null)); 913fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return true; 914fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 915fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 916fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com private boolean handleConstString(AnalyzedInstruction analyzedInstruction) { 917fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com ClassPath.ClassDef stringClassDef = ClassPath.getClassDef("Ljava/lang/String;"); 918fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType stringType = RegisterType.getRegisterType(RegisterType.Category.Reference, stringClassDef); 919fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, stringType); 920fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return true; 921fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 922fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 923fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com private boolean handleConstClass(AnalyzedInstruction analyzedInstruction) { 924fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com ClassPath.ClassDef classClassDef = ClassPath.getClassDef("Ljava/lang/Class;"); 925fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType classType = RegisterType.getRegisterType(RegisterType.Category.Reference, classClassDef); 926fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 927fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com InstructionWithReference instruction = (InstructionWithReference)analyzedInstruction.instruction; 928fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com Item item = instruction.getReferencedItem(); 929fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com assert item.getItemType() == ItemType.TYPE_TYPE_ID_ITEM; 930fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 931fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //make sure the referenced class is resolvable 932fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //TODO: need to check class access 933fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com ClassPath.ClassDef classDef = ClassPath.getClassDef((TypeIdItem)item); 934fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return false; 935fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 936fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 937fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com private boolean handleMonitor(AnalyzedInstruction analyzedInstruction) { 938fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com SingleRegisterInstruction instruction = (SingleRegisterInstruction)analyzedInstruction; 939fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 940fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType registerType = analyzedInstruction.postRegisterMap[instruction.getRegisterA()]; 941fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com assert registerType != null; 942fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (registerType.category == RegisterType.Category.Unknown) { 943fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return false; 944fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 945fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 946fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com checkRegister(registerType, ReferenceCategories); 947fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return true; 948fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 949fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 950fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com private boolean handleCheckCast(AnalyzedInstruction analyzedInstruction) { 951fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com { 952fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //ensure the "source" register is a reference type 953fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com SingleRegisterInstruction instruction = (SingleRegisterInstruction)analyzedInstruction.instruction; 954fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 955fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType registerType = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterA()); 956fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com assert registerType != null; 957fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (registerType.category == RegisterType.Category.Unknown) { 958fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return false; 959fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 960fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 961fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com checkRegister(registerType, ReferenceCategories); 962fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 963fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 964fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com { 965fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //resolve and verify the class that we're casting to 966fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com InstructionWithReference instruction = (InstructionWithReference)analyzedInstruction.instruction; 967fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 968fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com Item item = instruction.getReferencedItem(); 969fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com assert item.getItemType() == ItemType.TYPE_TYPE_ID_ITEM; 970fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 971fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //TODO: need to check class access 972fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType newDestinationRegisterType = RegisterType.getRegisterTypeForTypeIdItem((TypeIdItem)item); 973fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com try { 974fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com checkRegister(newDestinationRegisterType, ReferenceCategories); 975fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } catch (ValidationException ex) { 976fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //TODO: verify that dalvik allows a non-reference type.. 977fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@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) 978fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 979fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 980fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, newDestinationRegisterType); 981fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return true; 982fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 983fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 984fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 985fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com private boolean handleInstanceOf(AnalyzedInstruction analyzedInstruction) { 986fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com { 987fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //ensure the register that is being checks is a reference type 988fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com TwoRegisterInstruction instruction = (TwoRegisterInstruction)analyzedInstruction; 989fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 990fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType registerType = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterB()); 991fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com assert registerType != null; 992fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (registerType.category == RegisterType.Category.Unknown) { 993fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return false; 994fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 995fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 996fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com checkRegister(registerType, ReferenceCategories); 997fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 998fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 999fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com { 1000fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //resolve and verify the class that we're checking against 1001fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com InstructionWithReference instruction = (InstructionWithReference)analyzedInstruction.instruction; 1002fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1003fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com Item item = instruction.getReferencedItem(); 1004fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com assert item.getItemType() == ItemType.TYPE_TYPE_ID_ITEM; 1005fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType registerType = RegisterType.getRegisterTypeForTypeIdItem((TypeIdItem)item); 1006fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com checkRegister(registerType, ReferenceCategories); 1007fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1008fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //TODO: is it valid to use an array type? 1009fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1010fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@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. 1011fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, 1012fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType.getRegisterType(RegisterType.Category.Boolean, null)); 1013fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return true; 1014fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 1015fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 1016fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1017fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com private boolean handleArrayLength(AnalyzedInstruction analyzedInstruction) { 1018fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com TwoRegisterInstruction instruction = (TwoRegisterInstruction)analyzedInstruction; 1019fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1020fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com int arrayRegisterNumber = instruction.getRegisterB(); 1021fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType arrayRegisterType = analyzedInstruction.getPreInstructionRegisterType(arrayRegisterNumber); 1022fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com assert arrayRegisterType != null; 1023fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (arrayRegisterType.category == RegisterType.Category.Unknown) { 1024fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return false; 1025fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 1026fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1027fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com assert arrayRegisterType.type instanceof ClassPath.ArrayClassDef; 1028fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1029fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com checkRegister(arrayRegisterType, ReferenceCategories); 1030fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (arrayRegisterType.type != null) { 1031fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (arrayRegisterType.type.getClassType().charAt(0) != '[') { 1032fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com throw new ValidationException("Cannot use array-length with non-array type " + 1033fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com arrayRegisterType.type.getClassType()); 1034d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com } 1035d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com } 1036d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 1037fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, 1038fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType.getRegisterType(RegisterType.Category.Integer, null)); 1039fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return true; 1040fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 1041fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1042fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com private boolean handleNewInstance(AnalyzedInstruction analyzedInstruction) { 1043fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com InstructionWithReference instruction = (InstructionWithReference)analyzedInstruction.instruction; 1044fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1045a0314c265e76426e3e05e615cc713cf36c78cb85JesusFreke@JesusFreke.com int register = ((SingleRegisterInstruction)analyzedInstruction.instruction).getRegisterA(); 1046a0314c265e76426e3e05e615cc713cf36c78cb85JesusFreke@JesusFreke.com RegisterType destRegisterType = analyzedInstruction.postRegisterMap[register]; 1047a0314c265e76426e3e05e615cc713cf36c78cb85JesusFreke@JesusFreke.com if (destRegisterType.category != RegisterType.Category.Unknown) { 1048a0314c265e76426e3e05e615cc713cf36c78cb85JesusFreke@JesusFreke.com assert destRegisterType.category == RegisterType.Category.UninitRef; 1049a0314c265e76426e3e05e615cc713cf36c78cb85JesusFreke@JesusFreke.com 1050a0314c265e76426e3e05e615cc713cf36c78cb85JesusFreke@JesusFreke.com //the "post-instruction" destination register will only be set if we've gone over 1051a0314c265e76426e3e05e615cc713cf36c78cb85JesusFreke@JesusFreke.com //this instruction at least once before. If this is the case, then we need to check 1052a0314c265e76426e3e05e615cc713cf36c78cb85JesusFreke@JesusFreke.com //all the other registers, and make sure that none of them contain the same 1053a0314c265e76426e3e05e615cc713cf36c78cb85JesusFreke@JesusFreke.com //uninitialized reference that is in the destination register. 1054a0314c265e76426e3e05e615cc713cf36c78cb85JesusFreke@JesusFreke.com 1055a0314c265e76426e3e05e615cc713cf36c78cb85JesusFreke@JesusFreke.com for (int i=0; i<analyzedInstruction.postRegisterMap.length; i++) { 1056a0314c265e76426e3e05e615cc713cf36c78cb85JesusFreke@JesusFreke.com if (i==register) { 1057a0314c265e76426e3e05e615cc713cf36c78cb85JesusFreke@JesusFreke.com continue; 1058a0314c265e76426e3e05e615cc713cf36c78cb85JesusFreke@JesusFreke.com } 1059a0314c265e76426e3e05e615cc713cf36c78cb85JesusFreke@JesusFreke.com 1060a0314c265e76426e3e05e615cc713cf36c78cb85JesusFreke@JesusFreke.com if (analyzedInstruction.getPreInstructionRegisterType(i) == destRegisterType) { 1061a0314c265e76426e3e05e615cc713cf36c78cb85JesusFreke@JesusFreke.com throw new ValidationException(String.format("Register v%d contains an uninitialized reference " + 1062a0314c265e76426e3e05e615cc713cf36c78cb85JesusFreke@JesusFreke.com "that was created by this new-instance instruction.", i)); 1063a0314c265e76426e3e05e615cc713cf36c78cb85JesusFreke@JesusFreke.com } 1064a0314c265e76426e3e05e615cc713cf36c78cb85JesusFreke@JesusFreke.com } 1065a0314c265e76426e3e05e615cc713cf36c78cb85JesusFreke@JesusFreke.com } 1066a0314c265e76426e3e05e615cc713cf36c78cb85JesusFreke@JesusFreke.com 1067fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com Item item = instruction.getReferencedItem(); 1068fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com assert item.getItemType() == ItemType.TYPE_TYPE_ID_ITEM; 1069fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1070fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //TODO: need to check class access 1071fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType classType = RegisterType.getRegisterTypeForTypeIdItem((TypeIdItem)item); 1072fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com checkRegister(classType, ReferenceCategories); 1073fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (((TypeIdItem)item).getTypeDescriptor().charAt(0) == '[') { 1074fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com throw new ValidationException("Cannot use array type \"" + ((TypeIdItem)item).getTypeDescriptor() + 1075fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com "\" with new-instance. Use new-array instead."); 1076d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com } 1077d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 1078fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, 1079a0314c265e76426e3e05e615cc713cf36c78cb85JesusFreke@JesusFreke.com RegisterType.getUnitializedReference(classType.type)); 1080fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return true; 1081fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 1082fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1083fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com private boolean handleNewArray(AnalyzedInstruction analyzedInstruction) { 1084fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com { 1085fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com TwoRegisterInstruction instruction = (TwoRegisterInstruction)analyzedInstruction.instruction; 1086fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1087fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com int sizeRegister = instruction.getRegisterB(); 1088fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType registerType = analyzedInstruction.getPreInstructionRegisterType(sizeRegister); 1089fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com assert registerType != null; 1090fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1091fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (registerType.category == RegisterType.Category.Unknown) { 1092fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return false; 1093fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 1094fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1095fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com checkRegister(registerType, Primitive32BitCategories); 1096fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 1097fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1098fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com InstructionWithReference instruction = (InstructionWithReference)analyzedInstruction.instruction; 1099fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1100fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com Item item = instruction.getReferencedItem(); 1101fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com assert item.getItemType() == ItemType.TYPE_TYPE_ID_ITEM; 1102fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1103fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType arrayType = RegisterType.getRegisterTypeForTypeIdItem((TypeIdItem)item); 1104fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com assert arrayType.type instanceof ClassPath.ArrayClassDef; 1105d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 1106fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com checkRegister(arrayType, ReferenceCategories); 1107fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (arrayType.type.getClassType().charAt(0) != '[') { 1108fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com throw new ValidationException("Cannot use non-array type \"" + arrayType.type.getClassType() + 1109fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com "\" with new-array. Use new-instance instead."); 1110fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 1111fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1112fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, arrayType); 1113fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return true; 1114fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 1115fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 1116ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com private static interface RegisterIterator { 1117ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com int getRegister(); 1118ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com boolean moveNext(); 111906d1aacf61792afcdb273cf458e1e3daead0cf85JesusFreke@JesusFreke.com int getCount(); 11206192896f88638177ab6a5e64535f834f4a08b726JesusFreke@JesusFreke.com boolean pastEnd(); 1121ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com } 1122ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com 1123b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com private static class Format35cRegisterIterator implements RegisterIterator { 1124b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com private final int registerCount; 1125b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com private final int[] registers; 1126b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com private int currentRegister = 0; 1127b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com 1128b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com public Format35cRegisterIterator(FiveRegisterInstruction instruction) { 1129b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com registerCount = instruction.getRegCount(); 1130b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com registers = new int[]{instruction.getRegisterD(), instruction.getRegisterE(), 1131b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com instruction.getRegisterF(), instruction.getRegisterG(), 1132b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com instruction.getRegisterA()}; 1133b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com } 1134b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com 1135b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com public int getRegister() { 1136b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com return registers[currentRegister]; 1137b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com } 1138b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com 1139b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com public boolean moveNext() { 1140b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com currentRegister++; 1141b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com return pastEnd(); 1142b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com } 1143b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com 1144b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com public int getCount() { 1145b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com return registerCount; 1146b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com } 1147b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com 1148b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com public boolean pastEnd() { 1149b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com return currentRegister >= registerCount; 1150b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com } 1151b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com } 1152b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com 1153b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com private static class Format3rcRegisterIterator implements RegisterIterator { 1154b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com private final int startRegister; 1155b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com private final int registerCount; 1156b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com private int currentRegister = 0; 1157b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com 1158b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com public Format3rcRegisterIterator(RegisterRangeInstruction instruction) { 1159b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com startRegister = instruction.getStartRegister(); 1160b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com registerCount = instruction.getRegCount(); 1161b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com } 1162b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com 1163b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com public int getRegister() { 1164b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com return startRegister + currentRegister; 1165b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com } 1166b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com 1167b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com public boolean moveNext() { 1168b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com currentRegister++; 1169b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com return pastEnd(); 1170b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com } 1171b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com 1172b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com public int getCount() { 1173b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com return registerCount; 1174b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com } 1175b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com 1176b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com public boolean pastEnd() { 1177b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com return currentRegister >= registerCount; 1178b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com } 1179b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com } 1180b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com 1181ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com private boolean handleFilledNewArrayCommon(AnalyzedInstruction analyzedInstruction, 1182ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com RegisterIterator registerIterator) { 1183ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com InstructionWithReference instruction = (InstructionWithReference)analyzedInstruction.instruction; 1184ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com 11859e5dd85d837501e84e18617fc136c8203ab1f183JesusFreke@JesusFreke.com RegisterType arrayType; 11869e5dd85d837501e84e18617fc136c8203ab1f183JesusFreke@JesusFreke.com RegisterType arrayImmediateElementType; 11879e5dd85d837501e84e18617fc136c8203ab1f183JesusFreke@JesusFreke.com 1188ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com Item item = instruction.getReferencedItem(); 1189ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com assert item.getItemType() == ItemType.TYPE_TYPE_ID_ITEM; 11909e5dd85d837501e84e18617fc136c8203ab1f183JesusFreke@JesusFreke.com 1191ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com ClassPath.ClassDef classDef = ClassPath.getClassDef((TypeIdItem)item); 11929e5dd85d837501e84e18617fc136c8203ab1f183JesusFreke@JesusFreke.com 1193ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com if (classDef.getClassType().charAt(0) != '[') { 1194ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com throw new ValidationException("Cannot use non-array type \"" + classDef.getClassType() + 1195ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com "\" with new-array. Use new-instance instead."); 11969e5dd85d837501e84e18617fc136c8203ab1f183JesusFreke@JesusFreke.com } 11979e5dd85d837501e84e18617fc136c8203ab1f183JesusFreke@JesusFreke.com 1198ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com ClassPath.ArrayClassDef arrayClassDef = (ClassPath.ArrayClassDef)classDef; 1199ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com arrayType = RegisterType.getRegisterType(RegisterType.Category.Reference, classDef); 1200ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com arrayImmediateElementType = RegisterType.getRegisterTypeForType( 1201ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com arrayClassDef.getImmediateElementClass().getClassType()); 1202ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com String baseElementType = arrayClassDef.getBaseElementClass().getClassType(); 1203ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com if (baseElementType.charAt(0) == 'J' || baseElementType.charAt(0) == 'D') { 1204ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com throw new ValidationException("Cannot use filled-new-array to create an array of wide values " + 1205ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com "(long or double)"); 1206ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com } 12079e5dd85d837501e84e18617fc136c8203ab1f183JesusFreke@JesusFreke.com 1208ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com do { 1209ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com int register = registerIterator.getRegister(); 12109e5dd85d837501e84e18617fc136c8203ab1f183JesusFreke@JesusFreke.com RegisterType elementType = analyzedInstruction.getPreInstructionRegisterType(register); 12119e5dd85d837501e84e18617fc136c8203ab1f183JesusFreke@JesusFreke.com assert elementType != null; 12129e5dd85d837501e84e18617fc136c8203ab1f183JesusFreke@JesusFreke.com 12139e5dd85d837501e84e18617fc136c8203ab1f183JesusFreke@JesusFreke.com if (elementType.category == RegisterType.Category.Unknown) { 12149e5dd85d837501e84e18617fc136c8203ab1f183JesusFreke@JesusFreke.com return false; 12159e5dd85d837501e84e18617fc136c8203ab1f183JesusFreke@JesusFreke.com } 12169e5dd85d837501e84e18617fc136c8203ab1f183JesusFreke@JesusFreke.com 12179e5dd85d837501e84e18617fc136c8203ab1f183JesusFreke@JesusFreke.com if (!elementType.canBeAssignedTo(arrayImmediateElementType)) { 12189e5dd85d837501e84e18617fc136c8203ab1f183JesusFreke@JesusFreke.com throw new ValidationException("Register v" + Integer.toString(register) + " is of type " + 12199e5dd85d837501e84e18617fc136c8203ab1f183JesusFreke@JesusFreke.com elementType.toString() + " and is incompatible with the array type " + 12209e5dd85d837501e84e18617fc136c8203ab1f183JesusFreke@JesusFreke.com arrayType.type.getClassType()); 12219e5dd85d837501e84e18617fc136c8203ab1f183JesusFreke@JesusFreke.com } 1222ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com } while (registerIterator.moveNext()); 12239e5dd85d837501e84e18617fc136c8203ab1f183JesusFreke@JesusFreke.com 12249e5dd85d837501e84e18617fc136c8203ab1f183JesusFreke@JesusFreke.com setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, arrayType); 12259e5dd85d837501e84e18617fc136c8203ab1f183JesusFreke@JesusFreke.com return true; 12269e5dd85d837501e84e18617fc136c8203ab1f183JesusFreke@JesusFreke.com } 12279e5dd85d837501e84e18617fc136c8203ab1f183JesusFreke@JesusFreke.com 1228ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com private boolean handleFilledNewArray(AnalyzedInstruction analyzedInstruction) { 1229ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com FiveRegisterInstruction instruction = (FiveRegisterInstruction)analyzedInstruction.instruction; 1230b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com return handleFilledNewArrayCommon(analyzedInstruction, new Format35cRegisterIterator(instruction)); 1231ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com } 1232ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com 1233ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com private boolean handleFilledNewArrayRange(AnalyzedInstruction analyzedInstruction) { 1234b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com RegisterRangeInstruction instruction = (RegisterRangeInstruction)analyzedInstruction.instruction; 1235ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com 1236ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com //instruction.getStartRegister() and instruction.getRegCount() both return an int value, but are actually 1237ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com //unsigned 16 bit values, so we don't have to worry about overflowing an int when adding them together 1238ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com if (instruction.getStartRegister() + instruction.getRegCount() >= 1<<16) { 1239ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com throw new ValidationException(String.format("Invalid register range {v%d .. v%d}. The ending register " + 1240472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com "is larger than the largest allowed register of v65535.", 1241ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com instruction.getStartRegister(), 1242ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com instruction.getStartRegister() + instruction.getRegCount() - 1)); 1243ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com } 1244ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com 1245b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com return handleFilledNewArrayCommon(analyzedInstruction, new Format3rcRegisterIterator(instruction)); 1246ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com } 1247ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com 1248472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com private boolean handleFillArrayData(AnalyzedInstruction analyzedInstruction) { 1249472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com SingleRegisterInstruction instruction = (SingleRegisterInstruction)analyzedInstruction.instruction; 1250472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com 1251472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com int register = instruction.getRegisterA(); 1252472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com RegisterType registerType = analyzedInstruction.getPreInstructionRegisterType(register); 1253472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com assert registerType != null; 1254472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com 1255472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com if (registerType.category == RegisterType.Category.Unknown || 1256472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com registerType.category == RegisterType.Category.Null) { 1257472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com return false; 1258472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com } 1259472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com 1260472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com if (registerType.category != RegisterType.Category.Reference) { 1261472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use fill-array-data with non-array register v%d of " + 1262472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com "type %s", register, registerType.toString())); 1263472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com } 1264472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com 1265472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com assert registerType.type instanceof ClassPath.ArrayClassDef; 1266472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com ClassPath.ArrayClassDef arrayClassDef = (ClassPath.ArrayClassDef)registerType.type; 1267472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com 1268472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com if (arrayClassDef.getArrayDimensions() != 1) { 1269472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use fill-array-data with array type %s. It can only " + 1270472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com "be used with a one-dimensional array of primitives.", arrayClassDef.getClassType())); 1271472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com } 1272472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com 1273472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com int elementWidth; 1274472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com switch (arrayClassDef.getBaseElementClass().getClassType().charAt(0)) { 1275472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com case 'Z': 1276472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com case 'B': 1277472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com elementWidth = 1; 1278472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com break; 1279472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com case 'C': 1280472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com case 'S': 1281472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com elementWidth = 2; 1282472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com break; 1283472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com case 'I': 1284472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com case 'F': 1285472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com elementWidth = 4; 1286472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com break; 1287472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com case 'J': 1288472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com case 'D': 1289472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com elementWidth = 8; 1290472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com break; 1291472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com default: 1292472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use fill-array-data with array type %s. It can " + 1293472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com "only be used with a one-dimensional array of primitives.", arrayClassDef.getClassType())); 1294472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com } 1295472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com 1296472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com 1297b7e78115277e30c71e6e991da3f31c5a1403c634JesusFreke@JesusFreke.com int arrayDataAddressOffset = ((OffsetInstruction)analyzedInstruction.instruction).getTargetAddressOffset(); 1298b7e78115277e30c71e6e991da3f31c5a1403c634JesusFreke@JesusFreke.com int arrayDataCodeAddress = getInstructionAddress(analyzedInstruction) + arrayDataAddressOffset; 1299b7e78115277e30c71e6e991da3f31c5a1403c634JesusFreke@JesusFreke.com AnalyzedInstruction arrayDataInstruction = this.instructions.get(arrayDataCodeAddress); 1300472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com if (arrayDataInstruction == null || arrayDataInstruction.instruction.getFormat() != Format.ArrayData) { 1301472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com throw new ValidationException(String.format("Could not find an array data structure at code address 0x%x", 1302b7e78115277e30c71e6e991da3f31c5a1403c634JesusFreke@JesusFreke.com arrayDataCodeAddress)); 1303472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com } 1304472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com 1305472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com ArrayDataPseudoInstruction arrayDataPseudoInstruction = 1306472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com (ArrayDataPseudoInstruction)arrayDataInstruction.instruction; 1307472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com 1308472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com if (elementWidth != arrayDataPseudoInstruction.getElementWidth()) { 1309472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com throw new ValidationException(String.format("The array data at code address 0x%x does not have the " + 1310472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com "correct element width for array type %s. Expecting element width %d, got element width %d.", 1311b7e78115277e30c71e6e991da3f31c5a1403c634JesusFreke@JesusFreke.com arrayDataCodeAddress, arrayClassDef.getClassType(), elementWidth, 1312472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com arrayDataPseudoInstruction.getElementWidth())); 1313472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com } 1314472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com 1315472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com return true; 1316472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com } 1317472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com 1318ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com private boolean handleThrow(AnalyzedInstruction analyzedInstruction) { 1319ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com int register = ((SingleRegisterInstruction)analyzedInstruction.instruction).getRegisterA(); 1320ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com 1321ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com RegisterType registerType = analyzedInstruction.getPreInstructionRegisterType(register); 1322ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com assert registerType != null; 1323ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com 1324ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com if (registerType.category == RegisterType.Category.Unknown) { 1325ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com return false; 1326ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com } 1327ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com 1328ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com if (registerType.category == RegisterType.Category.Null) { 1329ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com return true; 1330ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com } 1331ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com 1332ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com if (registerType.category != RegisterType.Category.Reference) { 1333ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use throw with non-reference type %s in register v%d", 1334ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com registerType.toString(), register)); 1335ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com } 1336ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com 1337ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com assert registerType.type != null; 1338ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com 1339ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com if (!registerType.type.extendsClass(ClassPath.getClassDef("Ljava/lang/Throwable;"))) { 1340ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use throw with non-throwable type %s in register v%d", 1341ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com registerType.type.getClassType(), register)); 1342ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com } 1343ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com 1344ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com return true; 1345ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com } 1346ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com 1347cda44f70cfebfae4875cd77455a171075aebac4dJesusFreke@JesusFreke.com private boolean handleSwitch(AnalyzedInstruction analyzedInstruction, Format expectedSwitchDataFormat) { 1348cda44f70cfebfae4875cd77455a171075aebac4dJesusFreke@JesusFreke.com int register = ((SingleRegisterInstruction)analyzedInstruction.instruction).getRegisterA(); 1349cda44f70cfebfae4875cd77455a171075aebac4dJesusFreke@JesusFreke.com int switchCodeAddressOffset = ((OffsetInstruction)analyzedInstruction.instruction).getTargetAddressOffset(); 1350cda44f70cfebfae4875cd77455a171075aebac4dJesusFreke@JesusFreke.com 1351cda44f70cfebfae4875cd77455a171075aebac4dJesusFreke@JesusFreke.com RegisterType registerType = analyzedInstruction.getPreInstructionRegisterType(register); 1352cda44f70cfebfae4875cd77455a171075aebac4dJesusFreke@JesusFreke.com assert registerType != null; 1353cda44f70cfebfae4875cd77455a171075aebac4dJesusFreke@JesusFreke.com 1354cda44f70cfebfae4875cd77455a171075aebac4dJesusFreke@JesusFreke.com if (registerType.category == RegisterType.Category.Unknown) { 1355cda44f70cfebfae4875cd77455a171075aebac4dJesusFreke@JesusFreke.com return false; 1356cda44f70cfebfae4875cd77455a171075aebac4dJesusFreke@JesusFreke.com } 1357cda44f70cfebfae4875cd77455a171075aebac4dJesusFreke@JesusFreke.com 1358cda44f70cfebfae4875cd77455a171075aebac4dJesusFreke@JesusFreke.com checkRegister(registerType, Primitive32BitCategories); 1359cda44f70cfebfae4875cd77455a171075aebac4dJesusFreke@JesusFreke.com 1360cda44f70cfebfae4875cd77455a171075aebac4dJesusFreke@JesusFreke.com int switchDataCodeAddress = this.getInstructionAddress(analyzedInstruction) + switchCodeAddressOffset; 1361cda44f70cfebfae4875cd77455a171075aebac4dJesusFreke@JesusFreke.com AnalyzedInstruction switchDataAnalyzedInstruction = instructions.get(switchDataCodeAddress); 1362cda44f70cfebfae4875cd77455a171075aebac4dJesusFreke@JesusFreke.com 1363cda44f70cfebfae4875cd77455a171075aebac4dJesusFreke@JesusFreke.com if (switchDataAnalyzedInstruction == null || 1364cda44f70cfebfae4875cd77455a171075aebac4dJesusFreke@JesusFreke.com switchDataAnalyzedInstruction.instruction.getFormat() != expectedSwitchDataFormat) { 1365cda44f70cfebfae4875cd77455a171075aebac4dJesusFreke@JesusFreke.com throw new ValidationException(String.format("There is no %s structure at code address 0x%x", 1366cda44f70cfebfae4875cd77455a171075aebac4dJesusFreke@JesusFreke.com expectedSwitchDataFormat.name(), switchDataCodeAddress)); 1367cda44f70cfebfae4875cd77455a171075aebac4dJesusFreke@JesusFreke.com } 1368cda44f70cfebfae4875cd77455a171075aebac4dJesusFreke@JesusFreke.com 1369cda44f70cfebfae4875cd77455a171075aebac4dJesusFreke@JesusFreke.com return true; 1370cda44f70cfebfae4875cd77455a171075aebac4dJesusFreke@JesusFreke.com } 1371cda44f70cfebfae4875cd77455a171075aebac4dJesusFreke@JesusFreke.com 1372f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com private boolean handleFloatCmp(AnalyzedInstruction analyzedInstruction) { 1373f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com ThreeRegisterInstruction instruction = (ThreeRegisterInstruction)analyzedInstruction.instruction; 1374f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com 1375f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com RegisterType registerType = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterB()); 1376f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com assert registerType != null; 1377f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com 1378f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com if (registerType.category == RegisterType.Category.Unknown) { 1379f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com return false; 1380f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com } 1381f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com checkRegister(registerType, Primitive32BitCategories); 1382f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com 1383f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com registerType = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterC()); 1384f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com assert registerType != null; 1385f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com 1386f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com if (registerType.category == RegisterType.Category.Unknown) { 1387f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com return false; 1388f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com } 1389f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com checkRegister(registerType, Primitive32BitCategories); 1390f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com 1391f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, 1392f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com RegisterType.getRegisterType(RegisterType.Category.Byte, null)); 1393f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com return true; 1394f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com } 1395f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com 1396f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com private boolean handleWideCmp(AnalyzedInstruction analyzedInstruction) { 1397f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com ThreeRegisterInstruction instruction = (ThreeRegisterInstruction)analyzedInstruction.instruction; 1398f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com 1399f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com RegisterType registerType = getAndCheckWideSourcePair(analyzedInstruction, instruction.getRegisterB()); 1400f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com assert registerType != null; 1401f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com if (registerType.category == RegisterType.Category.Unknown) { 1402f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com return false; 1403f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com } 1404f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com 1405f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com registerType = getAndCheckWideSourcePair(analyzedInstruction, instruction.getRegisterC()); 1406f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com assert registerType != null; 1407f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com if (registerType.category == RegisterType.Category.Unknown) { 1408f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com return false; 1409f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com } 1410f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com 1411f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, 1412f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com RegisterType.getRegisterType(RegisterType.Category.Byte, null)); 1413f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com return true; 1414f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com } 1415f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com 1416aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com private boolean handleIfEqNe(AnalyzedInstruction analyzedInstruction) { 1417aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com TwoRegisterInstruction instruction = (TwoRegisterInstruction)analyzedInstruction.instruction; 1418aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com 1419aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com RegisterType registerType1 = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterA()); 1420aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com assert registerType1 != null; 1421aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com if (registerType1.category == RegisterType.Category.Unknown) { 1422aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com return false; 1423aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com } 1424aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com 1425aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com RegisterType registerType2 = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterB()); 1426aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com assert registerType2 != null; 1427aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com if (registerType2.category == RegisterType.Category.Unknown) { 1428aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com return false; 1429aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com } 1430aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com 1431aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com if (!( 1432aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com (ReferenceCategories.contains(registerType1.category) && 1433aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com ReferenceCategories.contains(registerType2.category)) 1434aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com || 1435aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com (Primitive32BitCategories.contains(registerType1.category) && 1436aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com Primitive32BitCategories.contains(registerType2.category)) 1437aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com )) { 1438aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com 1439aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com throw new ValidationException(String.format("%s cannot be used on registers of dissimilar types %s and " + 1440aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com "%s. They must both be a reference type or a primitive 32 bit type.", 1441aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com analyzedInstruction.instruction.opcode.name, registerType1.toString(), registerType2.toString())); 1442aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com } 1443aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com 1444aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com return true; 1445aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com } 1446aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com 1447150acd9db94f9886f6fc32e89acc15a1a5c1466fJesusFreke@JesusFreke.com private boolean handleIf(AnalyzedInstruction analyzedInstruction) { 1448150acd9db94f9886f6fc32e89acc15a1a5c1466fJesusFreke@JesusFreke.com TwoRegisterInstruction instruction = (TwoRegisterInstruction)analyzedInstruction.instruction; 1449150acd9db94f9886f6fc32e89acc15a1a5c1466fJesusFreke@JesusFreke.com 1450150acd9db94f9886f6fc32e89acc15a1a5c1466fJesusFreke@JesusFreke.com RegisterType registerType = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterA()); 1451150acd9db94f9886f6fc32e89acc15a1a5c1466fJesusFreke@JesusFreke.com assert registerType != null; 1452150acd9db94f9886f6fc32e89acc15a1a5c1466fJesusFreke@JesusFreke.com 1453150acd9db94f9886f6fc32e89acc15a1a5c1466fJesusFreke@JesusFreke.com if (registerType.category == RegisterType.Category.Unknown) { 1454150acd9db94f9886f6fc32e89acc15a1a5c1466fJesusFreke@JesusFreke.com return false; 1455150acd9db94f9886f6fc32e89acc15a1a5c1466fJesusFreke@JesusFreke.com } 1456150acd9db94f9886f6fc32e89acc15a1a5c1466fJesusFreke@JesusFreke.com checkRegister(registerType, Primitive32BitCategories); 1457150acd9db94f9886f6fc32e89acc15a1a5c1466fJesusFreke@JesusFreke.com 1458150acd9db94f9886f6fc32e89acc15a1a5c1466fJesusFreke@JesusFreke.com registerType = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterB()); 1459150acd9db94f9886f6fc32e89acc15a1a5c1466fJesusFreke@JesusFreke.com assert registerType != null; 1460150acd9db94f9886f6fc32e89acc15a1a5c1466fJesusFreke@JesusFreke.com 1461150acd9db94f9886f6fc32e89acc15a1a5c1466fJesusFreke@JesusFreke.com if (registerType.category == RegisterType.Category.Unknown) { 1462150acd9db94f9886f6fc32e89acc15a1a5c1466fJesusFreke@JesusFreke.com return false; 1463150acd9db94f9886f6fc32e89acc15a1a5c1466fJesusFreke@JesusFreke.com } 1464150acd9db94f9886f6fc32e89acc15a1a5c1466fJesusFreke@JesusFreke.com checkRegister(registerType, Primitive32BitCategories); 1465150acd9db94f9886f6fc32e89acc15a1a5c1466fJesusFreke@JesusFreke.com 1466150acd9db94f9886f6fc32e89acc15a1a5c1466fJesusFreke@JesusFreke.com return true; 1467150acd9db94f9886f6fc32e89acc15a1a5c1466fJesusFreke@JesusFreke.com } 1468150acd9db94f9886f6fc32e89acc15a1a5c1466fJesusFreke@JesusFreke.com 1469cb00252b6aed86cd3e7c426015cea83fcdbaa806JesusFreke@JesusFreke.com private boolean handleIfEqzNez(AnalyzedInstruction analyzedInstruction) { 1470cb00252b6aed86cd3e7c426015cea83fcdbaa806JesusFreke@JesusFreke.com SingleRegisterInstruction instruction = (SingleRegisterInstruction)analyzedInstruction.instruction; 1471cb00252b6aed86cd3e7c426015cea83fcdbaa806JesusFreke@JesusFreke.com 1472cb00252b6aed86cd3e7c426015cea83fcdbaa806JesusFreke@JesusFreke.com RegisterType registerType = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterA()); 1473cb00252b6aed86cd3e7c426015cea83fcdbaa806JesusFreke@JesusFreke.com assert registerType != null; 1474cb00252b6aed86cd3e7c426015cea83fcdbaa806JesusFreke@JesusFreke.com if (registerType.category == RegisterType.Category.Unknown) { 1475cb00252b6aed86cd3e7c426015cea83fcdbaa806JesusFreke@JesusFreke.com return false; 1476cb00252b6aed86cd3e7c426015cea83fcdbaa806JesusFreke@JesusFreke.com } 1477cb00252b6aed86cd3e7c426015cea83fcdbaa806JesusFreke@JesusFreke.com 1478cb00252b6aed86cd3e7c426015cea83fcdbaa806JesusFreke@JesusFreke.com if (!ReferenceCategories.contains(registerType.category) && 1479cb00252b6aed86cd3e7c426015cea83fcdbaa806JesusFreke@JesusFreke.com !Primitive32BitCategories.contains(registerType.category)) { 1480cb00252b6aed86cd3e7c426015cea83fcdbaa806JesusFreke@JesusFreke.com throw new ValidationException(String.format("%s cannot be used with register type %s. Expecting 32-bit " + 1481cb00252b6aed86cd3e7c426015cea83fcdbaa806JesusFreke@JesusFreke.com "primitive type or reference type.", analyzedInstruction.instruction.opcode)); 1482cb00252b6aed86cd3e7c426015cea83fcdbaa806JesusFreke@JesusFreke.com } 1483cb00252b6aed86cd3e7c426015cea83fcdbaa806JesusFreke@JesusFreke.com 1484cb00252b6aed86cd3e7c426015cea83fcdbaa806JesusFreke@JesusFreke.com return true; 1485cb00252b6aed86cd3e7c426015cea83fcdbaa806JesusFreke@JesusFreke.com } 1486cb00252b6aed86cd3e7c426015cea83fcdbaa806JesusFreke@JesusFreke.com 148716a709ba046343bfefc15a6cdb0be38282126223JesusFreke@JesusFreke.com private boolean handleIfz(AnalyzedInstruction analyzedInstruction) { 148816a709ba046343bfefc15a6cdb0be38282126223JesusFreke@JesusFreke.com SingleRegisterInstruction instruction = (SingleRegisterInstruction)analyzedInstruction.instruction; 148916a709ba046343bfefc15a6cdb0be38282126223JesusFreke@JesusFreke.com 149016a709ba046343bfefc15a6cdb0be38282126223JesusFreke@JesusFreke.com RegisterType registerType = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterA()); 149116a709ba046343bfefc15a6cdb0be38282126223JesusFreke@JesusFreke.com assert registerType != null; 149216a709ba046343bfefc15a6cdb0be38282126223JesusFreke@JesusFreke.com 149316a709ba046343bfefc15a6cdb0be38282126223JesusFreke@JesusFreke.com if (registerType.category == RegisterType.Category.Unknown) { 149416a709ba046343bfefc15a6cdb0be38282126223JesusFreke@JesusFreke.com return false; 149516a709ba046343bfefc15a6cdb0be38282126223JesusFreke@JesusFreke.com } 149616a709ba046343bfefc15a6cdb0be38282126223JesusFreke@JesusFreke.com checkRegister(registerType, Primitive32BitCategories); 149716a709ba046343bfefc15a6cdb0be38282126223JesusFreke@JesusFreke.com 149816a709ba046343bfefc15a6cdb0be38282126223JesusFreke@JesusFreke.com return true; 149916a709ba046343bfefc15a6cdb0be38282126223JesusFreke@JesusFreke.com } 150016a709ba046343bfefc15a6cdb0be38282126223JesusFreke@JesusFreke.com 1501b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com private boolean handle32BitPrimitiveAget(AnalyzedInstruction analyzedInstruction, 1502b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com RegisterType.Category instructionCategory) { 1503b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com ThreeRegisterInstruction instruction = (ThreeRegisterInstruction)analyzedInstruction.instruction; 1504b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com 1505b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com RegisterType indexRegisterType = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterC()); 1506b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com assert indexRegisterType != null; 1507b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com if (indexRegisterType.category == RegisterType.Category.Unknown) { 1508b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com return false; 1509b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com } 1510b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com checkRegister(indexRegisterType, Primitive32BitCategories); 1511b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com 1512b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com RegisterType arrayRegisterType = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterB()); 1513b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com assert arrayRegisterType != null; 1514b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com if (indexRegisterType.category == RegisterType.Category.Unknown) { 1515b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com return false; 1516b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com } 1517b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com 1518b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com if (arrayRegisterType.category != RegisterType.Category.Null) { 1519b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com if (arrayRegisterType.category != RegisterType.Category.Reference) { 1520b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use %s with non-array type %s", 1521b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com analyzedInstruction.instruction.opcode.name, arrayRegisterType.category.toString())); 1522b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com } 1523b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com 1524b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com assert arrayRegisterType.type != null; 1525b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com if (arrayRegisterType.type.getClassType().charAt(0) != '[') { 1526b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use %s with non-array type %s", 1527b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com analyzedInstruction.instruction.opcode.name, arrayRegisterType.type.getClassType())); 1528b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com } 1529b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com 1530b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com assert arrayRegisterType.type instanceof ClassPath.ArrayClassDef; 1531b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com ClassPath.ArrayClassDef arrayClassDef = (ClassPath.ArrayClassDef)arrayRegisterType.type; 1532b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com 1533b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com if (arrayClassDef.getArrayDimensions() != 1) { 1534b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use %s with multi-dimensional array type %s", 1535b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com analyzedInstruction.instruction.opcode.name, arrayRegisterType.type.getClassType())); 1536b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com } 1537b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com 1538b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com RegisterType arrayBaseType = 1539b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com RegisterType.getRegisterTypeForType(arrayClassDef.getBaseElementClass().getClassType()); 1540b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com if (checkArrayFieldAssignment(arrayBaseType.category, instructionCategory)) { 1541b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use %s with array type %s. Incorrect array type " + 1542b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com "for the instruction.", analyzedInstruction.instruction.opcode.name, 1543b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com arrayRegisterType.type.getClassType())); 1544b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com } 1545b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com } 1546b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com 1547b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, 1548b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com RegisterType.getRegisterType(instructionCategory, null)); 1549b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com 1550b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com return true; 1551b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com } 1552b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com 1553c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com private boolean handleAgetWide(AnalyzedInstruction analyzedInstruction) { 1554c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com ThreeRegisterInstruction instruction = (ThreeRegisterInstruction)analyzedInstruction.instruction; 1555c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com 1556c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com RegisterType indexRegisterType = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterC()); 1557c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com assert indexRegisterType != null; 1558c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com if (indexRegisterType.category == RegisterType.Category.Unknown) { 1559c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com return false; 1560c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com } 1561c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com checkRegister(indexRegisterType, Primitive32BitCategories); 1562c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com 1563c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com RegisterType arrayRegisterType = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterB()); 1564c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com assert arrayRegisterType != null; 1565c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com if (indexRegisterType.category == RegisterType.Category.Unknown) { 1566c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com return false; 1567c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com } 1568c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com 1569c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com if (arrayRegisterType.category != RegisterType.Category.Null) { 1570c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com if (arrayRegisterType.category != RegisterType.Category.Reference) { 1571c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use aget-wide with non-array type %s", 1572c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com arrayRegisterType.category.toString())); 1573c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com } 1574c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com 1575c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com assert arrayRegisterType.type != null; 1576c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com if (arrayRegisterType.type.getClassType().charAt(0) != '[') { 1577c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use aget-wide with non-array type %s", 1578c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com arrayRegisterType.type.getClassType())); 1579c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com } 1580c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com 1581c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com assert arrayRegisterType.type instanceof ClassPath.ArrayClassDef; 1582c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com ClassPath.ArrayClassDef arrayClassDef = (ClassPath.ArrayClassDef)arrayRegisterType.type; 1583c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com 1584c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com if (arrayClassDef.getArrayDimensions() != 1) { 1585c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use aget-wide with multi-dimensional array type %s", 1586c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com arrayRegisterType.type.getClassType())); 1587c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com } 1588c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com 1589c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com char arrayBaseType = arrayClassDef.getBaseElementClass().getClassType().charAt(0); 1590c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com if (arrayBaseType == 'J') { 1591c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com setWideDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, 1592c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com RegisterType.getRegisterType(RegisterType.Category.LongLo, null)); 1593c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com } else if (arrayBaseType == 'D') { 1594c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com setWideDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, 1595c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com RegisterType.getRegisterType(RegisterType.Category.DoubleLo, null)); 1596c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com } else { 1597c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use aget-wide with array type %s. Incorrect " + 1598c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com "array type for the instruction.", arrayRegisterType.type.getClassType())); 1599c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com } 1600c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com } else { 1601c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com setWideDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, 1602c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com RegisterType.getRegisterType(RegisterType.Category.LongLo, null)); 1603c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com } 1604c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com 1605c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com return true; 1606c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com } 1607c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com 1608461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com private boolean handleAgetObject(AnalyzedInstruction analyzedInstruction) { 1609461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com ThreeRegisterInstruction instruction = (ThreeRegisterInstruction)analyzedInstruction.instruction; 1610461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com 1611461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com RegisterType indexRegisterType = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterC()); 1612461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com assert indexRegisterType != null; 1613461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com if (indexRegisterType.category == RegisterType.Category.Unknown) { 1614461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com return false; 1615461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com } 1616461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com checkRegister(indexRegisterType, Primitive32BitCategories); 1617461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com 1618461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com RegisterType arrayRegisterType = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterB()); 1619461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com assert arrayRegisterType != null; 1620461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com if (indexRegisterType.category == RegisterType.Category.Unknown) { 1621461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com return false; 1622461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com } 1623461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com 1624461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com if (arrayRegisterType.category != RegisterType.Category.Null) { 1625461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com if (arrayRegisterType.category != RegisterType.Category.Reference) { 1626461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use aget-object with non-array type %s", 1627461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com arrayRegisterType.category.toString())); 1628461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com } 1629461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com 1630461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com assert arrayRegisterType.type != null; 1631461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com if (arrayRegisterType.type.getClassType().charAt(0) != '[') { 1632461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use aget-object with non-array type %s", 1633461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com arrayRegisterType.type.getClassType())); 1634461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com } 1635461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com 1636461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com assert arrayRegisterType.type instanceof ClassPath.ArrayClassDef; 1637461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com ClassPath.ArrayClassDef arrayClassDef = (ClassPath.ArrayClassDef)arrayRegisterType.type; 1638461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com 1639461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com ClassPath.ClassDef elementClassDef = arrayClassDef.getImmediateElementClass(); 1640461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com char elementTypePrefix = elementClassDef.getClassType().charAt(0); 1641461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com if (elementTypePrefix != 'L' && elementTypePrefix != '[') { 1642461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use aget-object with array type %s. Incorrect " + 1643461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com "array type for the instruction.", arrayRegisterType.type.getClassType())); 1644461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com } 1645461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com 1646461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, 1647461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com RegisterType.getRegisterType(RegisterType.Category.Reference, elementClassDef)); 1648461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com } else { 1649461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, 1650461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com RegisterType.getRegisterType(RegisterType.Category.Null, null)); 1651461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com } 1652461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com 1653461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com return true; 1654461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com } 1655461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com 1656c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com private boolean handle32BitPrimitiveAput(AnalyzedInstruction analyzedInstruction, 1657c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com RegisterType.Category instructionCategory) { 1658c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com ThreeRegisterInstruction instruction = (ThreeRegisterInstruction)analyzedInstruction.instruction; 1659c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com 1660c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com RegisterType indexRegisterType = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterC()); 1661c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com assert indexRegisterType != null; 1662c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com if (indexRegisterType.category == RegisterType.Category.Unknown) { 1663c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com return false; 1664c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com } 1665c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com checkRegister(indexRegisterType, Primitive32BitCategories); 1666c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com 1667c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com 1668c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com RegisterType sourceRegisterType = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterA()); 1669c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com assert sourceRegisterType != null; 1670c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com if (sourceRegisterType.category == RegisterType.Category.Unknown) { 1671c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com return false; 1672c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com } 1673c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com RegisterType instructionRegisterType = RegisterType.getRegisterType(instructionCategory, null); 1674c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com if (!sourceRegisterType.canBeAssignedTo(instructionRegisterType)) { 1675c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use %s with source register type %s.", 1676c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com analyzedInstruction.instruction.opcode.name, sourceRegisterType.toString())); 1677c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com } 1678c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com 1679c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com 1680c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com RegisterType arrayRegisterType = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterB()); 1681c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com assert arrayRegisterType != null; 1682c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com if (indexRegisterType.category == RegisterType.Category.Unknown) { 1683c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com return false; 1684c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com } 1685c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com 1686c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com if (arrayRegisterType.category != RegisterType.Category.Null) { 1687c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com if (arrayRegisterType.category != RegisterType.Category.Reference) { 1688c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use %s with non-array type %s", 1689c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com analyzedInstruction.instruction.opcode.name, arrayRegisterType.category.toString())); 1690c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com } 1691c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com 1692c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com assert arrayRegisterType.type != null; 1693c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com if (arrayRegisterType.type.getClassType().charAt(0) != '[') { 1694c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use %s with non-array type %s", 1695c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com analyzedInstruction.instruction.opcode.name, arrayRegisterType.type.getClassType())); 1696c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com } 1697c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com 1698c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com assert arrayRegisterType.type instanceof ClassPath.ArrayClassDef; 1699c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com ClassPath.ArrayClassDef arrayClassDef = (ClassPath.ArrayClassDef)arrayRegisterType.type; 1700c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com 1701c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com if (arrayClassDef.getArrayDimensions() != 1) { 1702c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use %s with multi-dimensional array type %s", 1703c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com analyzedInstruction.instruction.opcode.name, arrayRegisterType.type.getClassType())); 1704c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com } 1705c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com 1706c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com RegisterType arrayBaseType = 1707c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com RegisterType.getRegisterTypeForType(arrayClassDef.getBaseElementClass().getClassType()); 1708c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com if (checkArrayFieldAssignment(arrayBaseType.category, instructionCategory)) { 1709c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use %s with array type %s. Incorrect array type " + 1710c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com "for the instruction.", analyzedInstruction.instruction.opcode.name, 1711c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com arrayRegisterType.type.getClassType())); 171255d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com } 171355d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com } 171455d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com 171555d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com return true; 171655d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com } 171755d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com 171855d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com private boolean handleAputWide(AnalyzedInstruction analyzedInstruction) { 171955d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com ThreeRegisterInstruction instruction = (ThreeRegisterInstruction)analyzedInstruction.instruction; 172055d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com 172155d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com RegisterType indexRegisterType = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterC()); 172255d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com assert indexRegisterType != null; 172355d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com if (indexRegisterType.category == RegisterType.Category.Unknown) { 172455d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com return false; 172555d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com } 172655d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com checkRegister(indexRegisterType, Primitive32BitCategories); 172755d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com 172855d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com RegisterType sourceRegisterType = getAndCheckWideSourcePair(analyzedInstruction, instruction.getRegisterA()); 172955d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com if (sourceRegisterType.category == RegisterType.Category.Unknown) { 173055d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com return false; 173155d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com } 173255d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com 173355d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com RegisterType arrayRegisterType = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterB()); 173455d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com assert arrayRegisterType != null; 173555d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com if (indexRegisterType.category == RegisterType.Category.Unknown) { 173655d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com return false; 173755d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com } 173855d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com 173955d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com if (arrayRegisterType.category != RegisterType.Category.Null) { 174055d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com if (arrayRegisterType.category != RegisterType.Category.Reference) { 174155d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use aput-wide with non-array type %s", 174255d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com arrayRegisterType.category.toString())); 174355d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com } 174455d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com 174555d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com assert arrayRegisterType.type != null; 174655d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com if (arrayRegisterType.type.getClassType().charAt(0) != '[') { 174755d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use aput-wide with non-array type %s", 174855d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com arrayRegisterType.type.getClassType())); 174955d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com } 175055d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com 175155d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com assert arrayRegisterType.type instanceof ClassPath.ArrayClassDef; 175255d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com ClassPath.ArrayClassDef arrayClassDef = (ClassPath.ArrayClassDef)arrayRegisterType.type; 175355d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com 175455d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com if (arrayClassDef.getArrayDimensions() != 1) { 175555d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use aput-wide with multi-dimensional array type %s", 175655d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com arrayRegisterType.type.getClassType())); 175755d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com } 175855d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com 175955d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com char arrayBaseType = arrayClassDef.getBaseElementClass().getClassType().charAt(0); 176055d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com if (arrayBaseType != 'J' && arrayBaseType != 'D') { 176155d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use aput-wide with array type %s. Incorrect " + 176255d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com "array type for the instruction.", arrayRegisterType.type.getClassType())); 1763898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com } 1764898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com } 1765898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com 1766898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com return true; 1767898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com } 1768898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com 1769898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com private boolean handleAputObject(AnalyzedInstruction analyzedInstruction) { 1770898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com ThreeRegisterInstruction instruction = (ThreeRegisterInstruction)analyzedInstruction.instruction; 1771898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com 1772898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com RegisterType indexRegisterType = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterC()); 1773898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com assert indexRegisterType != null; 1774898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com if (indexRegisterType.category == RegisterType.Category.Unknown) { 1775898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com return false; 1776898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com } 1777898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com checkRegister(indexRegisterType, Primitive32BitCategories); 1778898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com 1779898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com RegisterType sourceRegisterType = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterA()); 1780898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com assert sourceRegisterType != null; 1781898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com if (sourceRegisterType.category == RegisterType.Category.Unknown) { 1782898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com return false; 1783898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com } 17846d11e9062dfaa27c7fa8719d9d9b4f58b0d5cfa0JesusFreke@JesusFreke.com //TODO: ensure sourceRegisterType is a Reference type? 1785898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com 1786898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com RegisterType arrayRegisterType = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterB()); 1787898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com assert arrayRegisterType != null; 1788898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com if (indexRegisterType.category == RegisterType.Category.Unknown) { 1789898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com return false; 1790898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com } 1791898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com 1792898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com if (arrayRegisterType.category != RegisterType.Category.Null) { 1793898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com //don't check the source type against the array type, just make sure it is an array of reference types 1794898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com 1795898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com if (arrayRegisterType.category != RegisterType.Category.Reference) { 1796898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use aget-object with non-array type %s", 1797898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com arrayRegisterType.category.toString())); 1798898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com } 1799898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com 1800898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com assert arrayRegisterType.type != null; 1801898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com if (arrayRegisterType.type.getClassType().charAt(0) != '[') { 1802898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use aget-object with non-array type %s", 1803898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com arrayRegisterType.type.getClassType())); 1804898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com } 1805898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com 1806898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com assert arrayRegisterType.type instanceof ClassPath.ArrayClassDef; 1807898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com ClassPath.ArrayClassDef arrayClassDef = (ClassPath.ArrayClassDef)arrayRegisterType.type; 1808898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com 1809898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com ClassPath.ClassDef elementClassDef = arrayClassDef.getImmediateElementClass(); 1810898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com char elementTypePrefix = elementClassDef.getClassType().charAt(0); 1811898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com if (elementTypePrefix != 'L' && elementTypePrefix != '[') { 1812898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use aget-object with array type %s. Incorrect " + 1813898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com "array type for the instruction.", arrayRegisterType.type.getClassType())); 1814c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com } 1815c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com } 1816c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com 1817c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com return true; 1818c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com } 1819c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com 18204f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com private boolean handle32BitPrimitiveIget(AnalyzedInstruction analyzedInstruction, 18214f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com RegisterType.Category instructionCategory) { 18224f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com TwoRegisterInstruction instruction = (TwoRegisterInstruction)analyzedInstruction.instruction; 18234f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com 18244f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com RegisterType objectRegisterType = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterB()); 18254f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com assert objectRegisterType != null; 18264f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com if (objectRegisterType.category == RegisterType.Category.Unknown) { 18274f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com return false; 18284f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com } 18294f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com checkRegister(objectRegisterType, ReferenceCategories); 18304f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com 18314f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com //TODO: check access 18324f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com //TODO: allow an uninitialized "this" reference, if the current method is an <init> method 18334f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com Item referencedItem = ((InstructionWithReference)analyzedInstruction.instruction).getReferencedItem(); 18344f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com assert referencedItem instanceof FieldIdItem; 18354f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com FieldIdItem field = (FieldIdItem)referencedItem; 18364f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com 18374f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com if (objectRegisterType.category != RegisterType.Category.Null && 18384f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com !objectRegisterType.type.extendsClass(ClassPath.getClassDef(field.getContainingClass()))) { 18394f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot access field %s through type %s", 18404f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com field.getFieldString(), objectRegisterType.type.getClassType())); 18414f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com } 18424f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com 18434f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com RegisterType fieldType = RegisterType.getRegisterTypeForTypeIdItem(field.getFieldType()); 18444f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com 18454f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com if (!checkArrayFieldAssignment(fieldType.category, instructionCategory)) { 18464f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use %s with field %s. Incorrect field type " + 18474f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com "for the instruction.", analyzedInstruction.instruction.opcode.name, 18484f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com field.getFieldString())); 18494f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com } 18504f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com 18514f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, 18524f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com RegisterType.getRegisterType(instructionCategory, null)); 18534f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com 18544f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com return true; 18554f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com } 18564f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com 18579d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com private boolean handleIgetWide(AnalyzedInstruction analyzedInstruction) { 18589d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com TwoRegisterInstruction instruction = (TwoRegisterInstruction)analyzedInstruction.instruction; 18599d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com 18609d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com RegisterType objectRegisterType = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterB()); 18619d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com assert objectRegisterType != null; 18629d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com if (objectRegisterType.category == RegisterType.Category.Unknown) { 18639d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com return false; 18649d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com } 18659d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com checkRegister(objectRegisterType, ReferenceCategories); 18669d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com 18679d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com getAndCheckWideSourcePair(analyzedInstruction, instruction.getRegisterB()); 18689d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com 18699d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com //TODO: check access 18709d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com //TODO: allow an uninitialized "this" reference, if the current method is an <init> method 18719d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com Item referencedItem = ((InstructionWithReference)analyzedInstruction.instruction).getReferencedItem(); 18729d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com assert referencedItem instanceof FieldIdItem; 18739d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com FieldIdItem field = (FieldIdItem)referencedItem; 18749d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com 18759d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com if (objectRegisterType.category != RegisterType.Category.Null && 18769d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com !objectRegisterType.type.extendsClass(ClassPath.getClassDef(field.getContainingClass()))) { 18779d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot access field %s through type %s", 18789d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com field.getFieldString(), objectRegisterType.type.getClassType())); 18799d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com } 18809d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com 18819d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com RegisterType fieldType = RegisterType.getRegisterTypeForTypeIdItem(field.getFieldType()); 18829d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com 18839d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com try { 18849d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com checkRegister(fieldType, WideLowCategories); 18859d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com } catch (ValidationException ex) { 18869d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use %s with field %s. Incorrect field type " + 18879d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com "for the instruction.", analyzedInstruction.instruction.opcode.name, 18889d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com field.getFieldString())); 18899d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com } 18909d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com 18919d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com setWideDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, fieldType); 18927a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com 18937a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com return true; 18947a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com } 18957a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com 18967a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com private boolean handleIgetObject(AnalyzedInstruction analyzedInstruction) { 18977a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com TwoRegisterInstruction instruction = (TwoRegisterInstruction)analyzedInstruction.instruction; 18987a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com 18997a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com RegisterType objectRegisterType = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterB()); 19007a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com assert objectRegisterType != null; 19017a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com if (objectRegisterType.category == RegisterType.Category.Unknown) { 19027a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com return false; 19037a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com } 19047a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com checkRegister(objectRegisterType, ReferenceCategories); 19057a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com 19067a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com //TODO: check access 19077a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com //TODO: allow an uninitialized "this" reference, if the current method is an <init> method 19087a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com Item referencedItem = ((InstructionWithReference)analyzedInstruction.instruction).getReferencedItem(); 19097a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com assert referencedItem instanceof FieldIdItem; 19107a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com FieldIdItem field = (FieldIdItem)referencedItem; 19117a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com 19127a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com if (objectRegisterType.category != RegisterType.Category.Null && 19137a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com !objectRegisterType.type.extendsClass(ClassPath.getClassDef(field.getContainingClass()))) { 19147a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot access field %s through type %s", 19157a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com field.getFieldString(), objectRegisterType.type.getClassType())); 19167a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com } 19177a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com 19187a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com RegisterType fieldType = RegisterType.getRegisterTypeForTypeIdItem(field.getFieldType()); 19197a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com 19207a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com if (fieldType.category != RegisterType.Category.Reference) { 19217a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use %s with field %s. Incorrect field type " + 19227a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com "for the instruction.", analyzedInstruction.instruction.opcode.name, 19237a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com field.getFieldString())); 19247a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com } 19257a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com 19267a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, fieldType); 19279d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com 19289d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com return true; 19299d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com } 19309d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com 19319971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com private boolean handle32BitPrimitiveIput(AnalyzedInstruction analyzedInstruction, 19329971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com RegisterType.Category instructionCategory) { 19339971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com TwoRegisterInstruction instruction = (TwoRegisterInstruction)analyzedInstruction.instruction; 19349971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com 19359971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com RegisterType objectRegisterType = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterB()); 19369971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com assert objectRegisterType != null; 19379971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com if (objectRegisterType.category == RegisterType.Category.Unknown) { 19389971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com return false; 19399971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com } 19409971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com checkRegister(objectRegisterType, ReferenceCategories); 19419971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com 19429971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com RegisterType sourceRegisterType = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterA()); 19439971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com assert sourceRegisterType != null; 19449971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com if (sourceRegisterType.category == RegisterType.Category.Unknown) { 19459971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com return false; 19469971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com } 19479971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com 19489971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com //per CodeVerify.c in dalvik: 19499971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com //java generates synthetic functions that write byte values into boolean fields 19509971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com if (sourceRegisterType.category == RegisterType.Category.Byte && 19519971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com instructionCategory == RegisterType.Category.Boolean) { 19529971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com 19539971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com sourceRegisterType = RegisterType.getRegisterType(RegisterType.Category.Boolean, null); 19549971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com } 19559971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com 19569971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com RegisterType instructionRegisterType = RegisterType.getRegisterType(instructionCategory, null); 19579971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com if (!sourceRegisterType.canBeAssignedTo(instructionRegisterType)) { 19589971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use %s with source register type %s.", 19599971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com analyzedInstruction.instruction.opcode.name, sourceRegisterType.toString())); 19609971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com } 19619971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com 19629971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com 19639971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com //TODO: check access 19649971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com //TODO: allow an uninitialized "this" reference, if the current method is an <init> method 19659971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com Item referencedItem = ((InstructionWithReference)analyzedInstruction.instruction).getReferencedItem(); 19669971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com assert referencedItem instanceof FieldIdItem; 19679971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com FieldIdItem field = (FieldIdItem)referencedItem; 19689971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com 19699971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com if (objectRegisterType.category != RegisterType.Category.Null && 19709971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com !objectRegisterType.type.extendsClass(ClassPath.getClassDef(field.getContainingClass()))) { 19719971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot access field %s through type %s", 19729971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com field.getFieldString(), objectRegisterType.type.getClassType())); 19739971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com } 19749971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com 19759971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com RegisterType fieldType = RegisterType.getRegisterTypeForTypeIdItem(field.getFieldType()); 19769971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com 19779971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com if (!checkArrayFieldAssignment(fieldType.category, instructionCategory)) { 19789971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use %s with field %s. Incorrect field type " + 19799971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com "for the instruction.", analyzedInstruction.instruction.opcode.name, 19809971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com field.getFieldString())); 19819971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com } 19829971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com 19839971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com return true; 19849971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com } 19859971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com 198692616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com private boolean handleIputWide(AnalyzedInstruction analyzedInstruction) { 198792616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com TwoRegisterInstruction instruction = (TwoRegisterInstruction)analyzedInstruction.instruction; 198892616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com 198992616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com RegisterType objectRegisterType = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterB()); 199092616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com assert objectRegisterType != null; 199192616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com if (objectRegisterType.category == RegisterType.Category.Unknown) { 199292616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com return false; 199392616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com } 199492616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com checkRegister(objectRegisterType, ReferenceCategories); 199592616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com 199692616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com RegisterType sourceRegisterType = getAndCheckWideSourcePair(analyzedInstruction, instruction.getRegisterA()); 199792616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com assert sourceRegisterType != null; 199892616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com if (sourceRegisterType.category == RegisterType.Category.Unknown) { 199992616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com return false; 200092616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com } 200192616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com 200292616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com //TODO: check access 200392616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com //TODO: allow an uninitialized "this" reference, if the current method is an <init> method 200492616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com Item referencedItem = ((InstructionWithReference)analyzedInstruction.instruction).getReferencedItem(); 200592616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com assert referencedItem instanceof FieldIdItem; 200692616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com FieldIdItem field = (FieldIdItem)referencedItem; 200792616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com 200892616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com if (objectRegisterType.category != RegisterType.Category.Null && 200992616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com !objectRegisterType.type.extendsClass(ClassPath.getClassDef(field.getContainingClass()))) { 201092616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot access field %s through type %s", 201192616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com field.getFieldString(), objectRegisterType.type.getClassType())); 201292616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com } 201392616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com 201492616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com RegisterType fieldType = RegisterType.getRegisterTypeForTypeIdItem(field.getFieldType()); 201592616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com 201692616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com if (!WideLowCategories.contains(fieldType.category)) { 201792616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use %s with field %s. Incorrect field type " + 201892616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com "for the instruction.", analyzedInstruction.instruction.opcode.name, 201992616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com field.getFieldString())); 202092616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com } 202192616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com 202292616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com return true; 202392616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com } 202492616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com 202550ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com private boolean handleIputObject(AnalyzedInstruction analyzedInstruction) { 202650ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com TwoRegisterInstruction instruction = (TwoRegisterInstruction)analyzedInstruction.instruction; 202750ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com 202850ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com RegisterType objectRegisterType = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterB()); 202950ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com assert objectRegisterType != null; 203050ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com if (objectRegisterType.category == RegisterType.Category.Unknown) { 203150ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com return false; 203250ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com } 203350ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com checkRegister(objectRegisterType, ReferenceCategories); 203450ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com 203550ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com RegisterType sourceRegisterType = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterA()); 203650ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com assert sourceRegisterType != null; 203750ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com if (sourceRegisterType.category == RegisterType.Category.Unknown) { 203850ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com return false; 203950ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com } 20406d11e9062dfaa27c7fa8719d9d9b4f58b0d5cfa0JesusFreke@JesusFreke.com checkRegister(sourceRegisterType, ReferenceCategories); 204150ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com 204250ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com //TODO: check access 204350ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com //TODO: allow an uninitialized "this" reference, if the current method is an <init> method 204450ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com Item referencedItem = ((InstructionWithReference)analyzedInstruction.instruction).getReferencedItem(); 204550ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com assert referencedItem instanceof FieldIdItem; 204650ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com FieldIdItem field = (FieldIdItem)referencedItem; 204750ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com 204850ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com if (objectRegisterType.category != RegisterType.Category.Null && 204950ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com !objectRegisterType.type.extendsClass(ClassPath.getClassDef(field.getContainingClass()))) { 205050ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot access field %s through type %s", 205150ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com field.getFieldString(), objectRegisterType.type.getClassType())); 205250ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com } 205350ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com 205450ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com RegisterType fieldType = RegisterType.getRegisterTypeForTypeIdItem(field.getFieldType()); 205550ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com 205650ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com if (fieldType.category != RegisterType.Category.Reference) { 205750ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use %s with field %s. Incorrect field type " + 205850ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com "for the instruction.", analyzedInstruction.instruction.opcode.name, 205950ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com field.getFieldString())); 206050ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com } 206150ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com 206250ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com if (sourceRegisterType.category != RegisterType.Category.Null && 206350ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com !fieldType.type.isInterface() && 206450ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com !sourceRegisterType.type.extendsClass(fieldType.type)) { 206550ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com 206650ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot store a value of type %s into a field of type %s", 206750ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com sourceRegisterType.type.getClassType(), fieldType.type.getClassType())); 206850ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com } 206950ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com 207050ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com return true; 207150ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com } 207250ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com 2073052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com private boolean handle32BitPrimitiveSget(AnalyzedInstruction analyzedInstruction, 2074052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com RegisterType.Category instructionCategory) { 2075052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com //TODO: check access 2076052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com Item referencedItem = ((InstructionWithReference)analyzedInstruction.instruction).getReferencedItem(); 2077052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com assert referencedItem instanceof FieldIdItem; 2078052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com FieldIdItem field = (FieldIdItem)referencedItem; 2079052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com 2080052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com RegisterType fieldType = RegisterType.getRegisterTypeForTypeIdItem(field.getFieldType()); 2081052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com 2082052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com if (!checkArrayFieldAssignment(fieldType.category, instructionCategory)) { 2083052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use %s with field %s. Incorrect field type " + 2084052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com "for the instruction.", analyzedInstruction.instruction.opcode.name, 2085052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com field.getFieldString())); 2086052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com } 2087052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com 2088052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, 2089052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com RegisterType.getRegisterType(instructionCategory, null)); 2090052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com 2091052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com return true; 2092052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com } 2093052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com 20942f233fefd9d73af8fab4037a6f874b161b98b259JesusFreke@JesusFreke.com private boolean handleSgetWide(AnalyzedInstruction analyzedInstruction) { 20952f233fefd9d73af8fab4037a6f874b161b98b259JesusFreke@JesusFreke.com //TODO: check access 20962f233fefd9d73af8fab4037a6f874b161b98b259JesusFreke@JesusFreke.com Item referencedItem = ((InstructionWithReference)analyzedInstruction.instruction).getReferencedItem(); 20972f233fefd9d73af8fab4037a6f874b161b98b259JesusFreke@JesusFreke.com assert referencedItem instanceof FieldIdItem; 20982f233fefd9d73af8fab4037a6f874b161b98b259JesusFreke@JesusFreke.com FieldIdItem field = (FieldIdItem)referencedItem; 20992f233fefd9d73af8fab4037a6f874b161b98b259JesusFreke@JesusFreke.com 21002f233fefd9d73af8fab4037a6f874b161b98b259JesusFreke@JesusFreke.com RegisterType fieldType = RegisterType.getRegisterTypeForTypeIdItem(field.getFieldType()); 21012f233fefd9d73af8fab4037a6f874b161b98b259JesusFreke@JesusFreke.com 21022f233fefd9d73af8fab4037a6f874b161b98b259JesusFreke@JesusFreke.com 21032f233fefd9d73af8fab4037a6f874b161b98b259JesusFreke@JesusFreke.com if (fieldType.category != RegisterType.Category.LongLo && 21042f233fefd9d73af8fab4037a6f874b161b98b259JesusFreke@JesusFreke.com fieldType.category != RegisterType.Category.DoubleLo) { 21052f233fefd9d73af8fab4037a6f874b161b98b259JesusFreke@JesusFreke.com 21062f233fefd9d73af8fab4037a6f874b161b98b259JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use %s with field %s. Incorrect field type " + 21072f233fefd9d73af8fab4037a6f874b161b98b259JesusFreke@JesusFreke.com "for the instruction.", analyzedInstruction.instruction.opcode.name, 21082f233fefd9d73af8fab4037a6f874b161b98b259JesusFreke@JesusFreke.com field.getFieldString())); 21092f233fefd9d73af8fab4037a6f874b161b98b259JesusFreke@JesusFreke.com } 21102f233fefd9d73af8fab4037a6f874b161b98b259JesusFreke@JesusFreke.com 21112f233fefd9d73af8fab4037a6f874b161b98b259JesusFreke@JesusFreke.com setWideDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, fieldType); 21122d6d6eb22c86c79344b85ffe46fdd4268566bd0fJesusFreke@JesusFreke.com 21132d6d6eb22c86c79344b85ffe46fdd4268566bd0fJesusFreke@JesusFreke.com return true; 21142d6d6eb22c86c79344b85ffe46fdd4268566bd0fJesusFreke@JesusFreke.com } 21152d6d6eb22c86c79344b85ffe46fdd4268566bd0fJesusFreke@JesusFreke.com 21162d6d6eb22c86c79344b85ffe46fdd4268566bd0fJesusFreke@JesusFreke.com private boolean handleSgetObject(AnalyzedInstruction analyzedInstruction) { 21172d6d6eb22c86c79344b85ffe46fdd4268566bd0fJesusFreke@JesusFreke.com //TODO: check access 21182d6d6eb22c86c79344b85ffe46fdd4268566bd0fJesusFreke@JesusFreke.com Item referencedItem = ((InstructionWithReference)analyzedInstruction.instruction).getReferencedItem(); 21192d6d6eb22c86c79344b85ffe46fdd4268566bd0fJesusFreke@JesusFreke.com assert referencedItem instanceof FieldIdItem; 21202d6d6eb22c86c79344b85ffe46fdd4268566bd0fJesusFreke@JesusFreke.com FieldIdItem field = (FieldIdItem)referencedItem; 21212d6d6eb22c86c79344b85ffe46fdd4268566bd0fJesusFreke@JesusFreke.com 21222d6d6eb22c86c79344b85ffe46fdd4268566bd0fJesusFreke@JesusFreke.com RegisterType fieldType = RegisterType.getRegisterTypeForTypeIdItem(field.getFieldType()); 21232d6d6eb22c86c79344b85ffe46fdd4268566bd0fJesusFreke@JesusFreke.com 21242d6d6eb22c86c79344b85ffe46fdd4268566bd0fJesusFreke@JesusFreke.com if (fieldType.category != RegisterType.Category.Reference) { 21252d6d6eb22c86c79344b85ffe46fdd4268566bd0fJesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use %s with field %s. Incorrect field type " + 21262d6d6eb22c86c79344b85ffe46fdd4268566bd0fJesusFreke@JesusFreke.com "for the instruction.", analyzedInstruction.instruction.opcode.name, 21272d6d6eb22c86c79344b85ffe46fdd4268566bd0fJesusFreke@JesusFreke.com field.getFieldString())); 21282d6d6eb22c86c79344b85ffe46fdd4268566bd0fJesusFreke@JesusFreke.com } 21292d6d6eb22c86c79344b85ffe46fdd4268566bd0fJesusFreke@JesusFreke.com 21302d6d6eb22c86c79344b85ffe46fdd4268566bd0fJesusFreke@JesusFreke.com setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, fieldType); 21312f233fefd9d73af8fab4037a6f874b161b98b259JesusFreke@JesusFreke.com 21322f233fefd9d73af8fab4037a6f874b161b98b259JesusFreke@JesusFreke.com return true; 21332f233fefd9d73af8fab4037a6f874b161b98b259JesusFreke@JesusFreke.com } 21342f233fefd9d73af8fab4037a6f874b161b98b259JesusFreke@JesusFreke.com 21359d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com private boolean handle32BitPrimitiveSput(AnalyzedInstruction analyzedInstruction, 21369d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com RegisterType.Category instructionCategory) { 21379d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com SingleRegisterInstruction instruction = (SingleRegisterInstruction)analyzedInstruction.instruction; 21389d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com 21399d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com RegisterType sourceRegisterType = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterA()); 21409d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com assert sourceRegisterType != null; 21419d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com if (sourceRegisterType.category == RegisterType.Category.Unknown) { 21429d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com return false; 21439d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com } 21449d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com 21459d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com //per CodeVerify.c in dalvik: 21469d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com //java generates synthetic functions that write byte values into boolean fields 21479d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com if (sourceRegisterType.category == RegisterType.Category.Byte && 21489d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com instructionCategory == RegisterType.Category.Boolean) { 21499d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com 21509d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com sourceRegisterType = RegisterType.getRegisterType(RegisterType.Category.Boolean, null); 21519d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com } 21529d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com 21539d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com RegisterType instructionRegisterType = RegisterType.getRegisterType(instructionCategory, null); 21549d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com if (!sourceRegisterType.canBeAssignedTo(instructionRegisterType)) { 21559d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use %s with source register type %s.", 21569d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com analyzedInstruction.instruction.opcode.name, sourceRegisterType.toString())); 21579d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com } 21589d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com 21599d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com //TODO: check access 21609d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com Item referencedItem = ((InstructionWithReference)analyzedInstruction.instruction).getReferencedItem(); 21619d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com assert referencedItem instanceof FieldIdItem; 21629d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com FieldIdItem field = (FieldIdItem)referencedItem; 21639d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com 21649d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com RegisterType fieldType = RegisterType.getRegisterTypeForTypeIdItem(field.getFieldType()); 21659d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com 21669d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com if (!checkArrayFieldAssignment(fieldType.category, instructionCategory)) { 21679d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use %s with field %s. Incorrect field type " + 21689d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com "for the instruction.", analyzedInstruction.instruction.opcode.name, 21699d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com field.getFieldString())); 21709d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com } 21719d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com 21729d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com return true; 21739d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com } 21749d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com 2175f08a9e1c2c130a5ed5923999fec0283f91b48a09JesusFreke@JesusFreke.com private boolean handleSputWide(AnalyzedInstruction analyzedInstruction) { 2176f08a9e1c2c130a5ed5923999fec0283f91b48a09JesusFreke@JesusFreke.com SingleRegisterInstruction instruction = (SingleRegisterInstruction)analyzedInstruction.instruction; 2177f08a9e1c2c130a5ed5923999fec0283f91b48a09JesusFreke@JesusFreke.com 2178f08a9e1c2c130a5ed5923999fec0283f91b48a09JesusFreke@JesusFreke.com 2179f08a9e1c2c130a5ed5923999fec0283f91b48a09JesusFreke@JesusFreke.com RegisterType sourceRegisterType = getAndCheckWideSourcePair(analyzedInstruction, instruction.getRegisterA()); 2180f08a9e1c2c130a5ed5923999fec0283f91b48a09JesusFreke@JesusFreke.com assert sourceRegisterType != null; 2181f08a9e1c2c130a5ed5923999fec0283f91b48a09JesusFreke@JesusFreke.com if (sourceRegisterType.category == RegisterType.Category.Unknown) { 2182f08a9e1c2c130a5ed5923999fec0283f91b48a09JesusFreke@JesusFreke.com return false; 2183f08a9e1c2c130a5ed5923999fec0283f91b48a09JesusFreke@JesusFreke.com } 2184f08a9e1c2c130a5ed5923999fec0283f91b48a09JesusFreke@JesusFreke.com 2185f08a9e1c2c130a5ed5923999fec0283f91b48a09JesusFreke@JesusFreke.com //TODO: check access 2186f08a9e1c2c130a5ed5923999fec0283f91b48a09JesusFreke@JesusFreke.com Item referencedItem = ((InstructionWithReference)analyzedInstruction.instruction).getReferencedItem(); 2187f08a9e1c2c130a5ed5923999fec0283f91b48a09JesusFreke@JesusFreke.com assert referencedItem instanceof FieldIdItem; 2188f08a9e1c2c130a5ed5923999fec0283f91b48a09JesusFreke@JesusFreke.com FieldIdItem field = (FieldIdItem)referencedItem; 2189f08a9e1c2c130a5ed5923999fec0283f91b48a09JesusFreke@JesusFreke.com 2190f08a9e1c2c130a5ed5923999fec0283f91b48a09JesusFreke@JesusFreke.com RegisterType fieldType = RegisterType.getRegisterTypeForTypeIdItem(field.getFieldType()); 2191f08a9e1c2c130a5ed5923999fec0283f91b48a09JesusFreke@JesusFreke.com 2192f08a9e1c2c130a5ed5923999fec0283f91b48a09JesusFreke@JesusFreke.com if (!WideLowCategories.contains(fieldType.category)) { 2193f08a9e1c2c130a5ed5923999fec0283f91b48a09JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use %s with field %s. Incorrect field type " + 2194f08a9e1c2c130a5ed5923999fec0283f91b48a09JesusFreke@JesusFreke.com "for the instruction.", analyzedInstruction.instruction.opcode.name, 2195f08a9e1c2c130a5ed5923999fec0283f91b48a09JesusFreke@JesusFreke.com field.getFieldString())); 2196f08a9e1c2c130a5ed5923999fec0283f91b48a09JesusFreke@JesusFreke.com } 2197f08a9e1c2c130a5ed5923999fec0283f91b48a09JesusFreke@JesusFreke.com 2198f08a9e1c2c130a5ed5923999fec0283f91b48a09JesusFreke@JesusFreke.com setWideDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, fieldType); 2199f08a9e1c2c130a5ed5923999fec0283f91b48a09JesusFreke@JesusFreke.com 2200f08a9e1c2c130a5ed5923999fec0283f91b48a09JesusFreke@JesusFreke.com return true; 2201f08a9e1c2c130a5ed5923999fec0283f91b48a09JesusFreke@JesusFreke.com } 2202f08a9e1c2c130a5ed5923999fec0283f91b48a09JesusFreke@JesusFreke.com 220351cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com private boolean handleSputObject(AnalyzedInstruction analyzedInstruction) { 220451cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com SingleRegisterInstruction instruction = (SingleRegisterInstruction)analyzedInstruction.instruction; 220551cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com 220651cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com RegisterType sourceRegisterType = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterA()); 220751cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com assert sourceRegisterType != null; 220851cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com if (sourceRegisterType.category == RegisterType.Category.Unknown) { 220951cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com return false; 221051cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com } 221151cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com checkRegister(sourceRegisterType, ReferenceCategories); 221251cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com 221351cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com //TODO: check access 221451cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com Item referencedItem = ((InstructionWithReference)analyzedInstruction.instruction).getReferencedItem(); 221551cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com assert referencedItem instanceof FieldIdItem; 221651cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com FieldIdItem field = (FieldIdItem)referencedItem; 221751cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com 221851cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com RegisterType fieldType = RegisterType.getRegisterTypeForTypeIdItem(field.getFieldType()); 221951cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com 222051cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com if (fieldType.category != RegisterType.Category.Reference) { 222151cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot use %s with field %s. Incorrect field type " + 222251cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com "for the instruction.", analyzedInstruction.instruction.opcode.name, 222351cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com field.getFieldString())); 222451cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com } 222551cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com 222651cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com if (sourceRegisterType.category != RegisterType.Category.Null && 222751cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com !fieldType.type.isInterface() && 222851cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com !sourceRegisterType.type.extendsClass(fieldType.type)) { 222951cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com 223051cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com throw new ValidationException(String.format("Cannot store a value of type %s into a field of type %s", 223151cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com sourceRegisterType.type.getClassType(), fieldType.type.getClassType())); 223251cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com } 223351cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com 223451cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com return true; 223551cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com } 223651cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com 2237b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com private static boolean checkArrayFieldAssignment(RegisterType.Category arrayFieldCategory, 2238b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com RegisterType.Category instructionCategory) { 2239b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com if (arrayFieldCategory == instructionCategory) { 2240b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com return true; 2241b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com } 2242b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com 2243b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com if ((arrayFieldCategory == RegisterType.Category.Integer && 2244b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com instructionCategory == RegisterType.Category.Float) || 2245b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com (arrayFieldCategory == RegisterType.Category.Float && 2246b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com instructionCategory == RegisterType.Category.Integer)) { 2247b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com return true; 2248b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com } 2249b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com return false; 2250b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com } 2251b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com 2252fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com private static void checkRegister(RegisterType registerType, EnumSet validCategories) { 2253fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (!validCategories.contains(registerType.category)) { 2254fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com //TODO: add expected categories to error message 2255fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com throw new ValidationException("Invalid register type. Expecting one of: " + " but got \"" + 2256fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com registerType.category + "\""); 2257fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 2258fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 2259fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 2260fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com private static void checkWideDestinationPair(AnalyzedInstruction analyzedInstruction) { 2261fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com int register = analyzedInstruction.getDestinationRegister(); 2262fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 2263fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (register == (analyzedInstruction.postRegisterMap.length - 1)) { 2264fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com throw new ValidationException("v" + register + " is the last register and not a valid wide register " + 2265fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com "pair."); 2266fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 2267fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 2268fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 2269fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com private static RegisterType getAndCheckWideSourcePair(AnalyzedInstruction analyzedInstruction, int firstRegister) { 2270fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com assert firstRegister >= 0 && firstRegister < analyzedInstruction.postRegisterMap.length; 2271fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 2272fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (firstRegister == analyzedInstruction.postRegisterMap.length - 1) { 2273fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com throw new ValidationException("v" + firstRegister + " is the last register and not a valid wide register " + 2274fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com "pair."); 2275fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 2276fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 2277fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType registerType = analyzedInstruction.getPreInstructionRegisterType(firstRegister); 2278fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com assert registerType != null; 2279fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (registerType.category == RegisterType.Category.Unknown) { 2280fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return registerType; 2281fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 2282fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com checkRegister(registerType, WideLowCategories); 2283fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 2284fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com RegisterType secondRegisterType = analyzedInstruction.getPreInstructionRegisterType(firstRegister + 1); 2285fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com assert secondRegisterType != null; 2286fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com checkRegister(secondRegisterType, WideHighCategories); 2287fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com 2288fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com if (( registerType.category == RegisterType.Category.LongLo && 2289fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com secondRegisterType.category == RegisterType.Category.DoubleHi) 2290fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com || ( registerType.category == RegisterType.Category.DoubleLo && 2291fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com secondRegisterType.category == RegisterType.Category.LongHi)) { 2292fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com assert false; 2293fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com throw new ValidationException("The first register in the wide register pair isn't the same type (long " + 2294fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com "vs. double) as the second register in the pair"); 2295fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com } 2296d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com 2297fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com return registerType; 2298d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com } 2299d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com} 2300