private static void checkItem(Opcode opcode, Item item, int regCount) { if (opcode == FILLED_NEW_ARRAY_RANGE) { //check data for filled-new-array/range opcode String type = ((TypeIdItem) item).getTypeDescriptor(); if (type.charAt(0) != '[') { throw new RuntimeException("The type must be an array type"); } if (type.charAt(1) == 'J' || type.charAt(1) == 'D') { throw new RuntimeException("The type cannot be an array of longs or doubles"); } } else if (opcode.value >= INVOKE_VIRTUAL_RANGE.value && opcode.value <= INVOKE_INTERFACE_RANGE.value || opcode == INVOKE_OBJECT_INIT_RANGE) { //check data for invoke-*/range opcodes MethodIdItem methodIdItem = (MethodIdItem) item; int parameterRegisterCount = methodIdItem.getPrototype().getParameterRegisterCount(); if (opcode != INVOKE_STATIC_RANGE) { parameterRegisterCount++; } if (parameterRegisterCount != regCount) { throw new RuntimeException("regCount does not match the number of arguments of the method"); } } }
private static void checkItem(Opcode opcode, Item item, int regCount) { if (opcode == FILLED_NEW_ARRAY_JUMBO) { //check data for filled-new-array/jumbo opcode String type = ((TypeIdItem) item).getTypeDescriptor(); if (type.charAt(0) != '[') { throw new RuntimeException("The type must be an array type"); } if (type.charAt(1) == 'J' || type.charAt(1) == 'D') { throw new RuntimeException("The type cannot be an array of longs or doubles"); } } else if (opcode.value >= INVOKE_VIRTUAL_JUMBO.value && opcode.value <= INVOKE_INTERFACE_JUMBO.value || opcode == INVOKE_OBJECT_INIT_JUMBO) { //check data for invoke-*/range opcodes MethodIdItem methodIdItem = (MethodIdItem) item; int parameterRegisterCount = methodIdItem.getPrototype().getParameterRegisterCount(); if (opcode != INVOKE_STATIC_JUMBO) { parameterRegisterCount++; } if (parameterRegisterCount != regCount) { throw new RuntimeException("regCount does not match the number of arguments of the method"); } } }
private static void checkItem(Opcode opcode, Item item, int regCount) { if (opcode == FILLED_NEW_ARRAY) { //check data for filled-new-array opcode String type = ((TypeIdItem) item).getTypeDescriptor(); if (type.charAt(0) != '[') { throw new RuntimeException("The type must be an array type"); } if (type.charAt(1) == 'J' || type.charAt(1) == 'D') { throw new RuntimeException("The type cannot be an array of longs or doubles"); } } else if (opcode.value >= INVOKE_VIRTUAL.value && opcode.value <= INVOKE_INTERFACE.value || opcode == INVOKE_DIRECT_EMPTY) { //check data for invoke-* opcodes MethodIdItem methodIdItem = (MethodIdItem) item; int parameterRegisterCount = methodIdItem.getPrototype().getParameterRegisterCount(); if (opcode != INVOKE_STATIC) { parameterRegisterCount++; } if (parameterRegisterCount != regCount) { throw new RuntimeException("regCount does not match the number of arguments of the method"); } } }
private void verifyReturnVoid(AnalyzedInstruction analyzedInstruction) { TypeIdItem returnType = encodedMethod.method.getPrototype().getReturnType(); if (returnType.getTypeDescriptor().charAt(0) != 'V') { //TODO: could add which return-* variation should be used instead throw new ValidationException("Cannot use return-void with a non-void return type (" + returnType.getTypeDescriptor() + ")"); } }
private int getThisRegister() { assert (encodedMethod.accessFlags & AccessFlags.STATIC.getValue()) == 0; CodeItem codeItem = encodedMethod.codeItem; assert codeItem != null; MethodIdItem methodIdItem = encodedMethod.method; assert methodIdItem != null; int totalRegisters = codeItem.getRegisterCount(); if (totalRegisters == 0) { throw new ValidationException("A non-static method must have at least 1 register"); } int parameterRegisters = methodIdItem.getPrototype().getParameterRegisterCount(); return totalRegisters - parameterRegisters - 1; }
validCategories); TypeIdItem returnType = encodedMethod.method.getPrototype().getReturnType(); if (returnType.getTypeDescriptor().charAt(0) == 'V') { throw new ValidationException("Cannot use return with a void return type. Use return-void instead");
private void verifyMoveResult(AnalyzedInstruction analyzedInstruction, EnumSet<RegisterType.Category> allowedCategories) { if (analyzedInstruction.instructionIndex == 0) { throw new ValidationException(analyzedInstruction.instruction.opcode.name + " cannot be the first " + "instruction in a method. It must occur after an invoke-*/fill-new-array instruction"); } AnalyzedInstruction previousInstruction = instructions.valueAt(analyzedInstruction.instructionIndex-1); if (!previousInstruction.instruction.opcode.setsResult()) { throw new ValidationException(analyzedInstruction.instruction.opcode.name + " must occur after an " + "invoke-*/fill-new-array instruction"); } //TODO: does dalvik allow a move-result after an invoke with a void return type? RegisterType resultRegisterType; InstructionWithReference invokeInstruction = (InstructionWithReference)previousInstruction.getInstruction(); Item item = invokeInstruction.getReferencedItem(); if (item instanceof MethodIdItem) { resultRegisterType = RegisterType.getRegisterTypeForTypeIdItem( ((MethodIdItem)item).getPrototype().getReturnType()); } else { assert item instanceof TypeIdItem; resultRegisterType = RegisterType.getRegisterTypeForTypeIdItem((TypeIdItem)item); } if (!allowedCategories.contains(resultRegisterType.category)) { throw new ValidationException(String.format("Wrong move-result* instruction for return value %s", resultRegisterType.toString())); } }
int parameterRegisters = methodIdItem.getPrototype().getParameterRegisterCount(); TypeListItem parameters = methodIdItem.getPrototype().getParameters(); if (parameters != null) { RegisterType[] parameterTypes = getParameterTypes(parameters, parameterRegisters);
private void analyzeMoveResult(AnalyzedInstruction analyzedInstruction) { AnalyzedInstruction previousInstruction = instructions.valueAt(analyzedInstruction.instructionIndex-1); if (!previousInstruction.instruction.opcode.setsResult()) { throw new ValidationException(analyzedInstruction.instruction.opcode.name + " must occur after an " + "invoke-*/fill-new-array instruction"); } RegisterType resultRegisterType; InstructionWithReference invokeInstruction = (InstructionWithReference)previousInstruction.instruction; Item item = invokeInstruction.getReferencedItem(); if (item.getItemType() == ItemType.TYPE_METHOD_ID_ITEM) { resultRegisterType = RegisterType.getRegisterTypeForTypeIdItem( ((MethodIdItem)item).getPrototype().getReturnType()); } else { assert item.getItemType() == ItemType.TYPE_TYPE_ID_ITEM; resultRegisterType = RegisterType.getRegisterTypeForTypeIdItem((TypeIdItem)item); } setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, resultRegisterType); }
TypeListItem typeListItem = methodIdItem.getPrototype().getParameters(); int methodParameterRegisterCount; if (typeListItem == null) {
private static void checkItem(Opcode opcode, Item item, int regCount) { if (opcode == FILLED_NEW_ARRAY) { //check data for filled-new-array opcode String type = ((TypeIdItem) item).getTypeDescriptor(); if (type.charAt(0) != '[') { throw new RuntimeException("The type must be an array type"); } if (type.charAt(1) == 'J' || type.charAt(1) == 'D') { throw new RuntimeException("The type cannot be an array of longs or doubles"); } } else if (opcode.value >= INVOKE_VIRTUAL.value && opcode.value <= INVOKE_INTERFACE.value || opcode == INVOKE_DIRECT_EMPTY) { //check data for invoke-* opcodes MethodIdItem methodIdItem = (MethodIdItem) item; int parameterRegisterCount = methodIdItem.getPrototype().getParameterRegisterCount(); if (opcode != INVOKE_STATIC) { parameterRegisterCount++; } if (parameterRegisterCount != regCount) { throw new RuntimeException("regCount does not match the number of arguments of the method"); } } }
private static void checkItem(Opcode opcode, Item item, int regCount) { if (opcode == FILLED_NEW_ARRAY_RANGE) { //check data for filled-new-array/range opcode String type = ((TypeIdItem) item).getTypeDescriptor(); if (type.charAt(0) != '[') { throw new RuntimeException("The type must be an array type"); } if (type.charAt(1) == 'J' || type.charAt(1) == 'D') { throw new RuntimeException("The type cannot be an array of longs or doubles"); } } else if (opcode.value >= INVOKE_VIRTUAL_RANGE.value && opcode.value <= INVOKE_INTERFACE_RANGE.value || opcode == INVOKE_OBJECT_INIT_RANGE) { //check data for invoke-*/range opcodes MethodIdItem methodIdItem = (MethodIdItem) item; int parameterRegisterCount = methodIdItem.getPrototype().getParameterRegisterCount(); if (opcode != INVOKE_STATIC_RANGE) { parameterRegisterCount++; } if (parameterRegisterCount != regCount) { throw new RuntimeException("regCount does not match the number of arguments of the method"); } } }
private int getThisRegister() { assert (encodedMethod.accessFlags & AccessFlags.STATIC.getValue()) == 0; CodeItem codeItem = encodedMethod.codeItem; assert codeItem != null; MethodIdItem methodIdItem = encodedMethod.method; assert methodIdItem != null; int totalRegisters = codeItem.getRegisterCount(); if (totalRegisters == 0) { throw new ValidationException("A non-static method must have at least 1 register"); } int parameterRegisters = methodIdItem.getPrototype().getParameterRegisterCount(); return totalRegisters - parameterRegisters - 1; }
int parameterRegisters = methodIdItem.getPrototype().getParameterRegisterCount(); TypeListItem parameters = methodIdItem.getPrototype().getParameters(); if (parameters != null) { RegisterType[] parameterTypes = getParameterTypes(parameters, parameterRegisters);