private HeapItem get(Field field, Object instance, String className, int accessFlags, ExecutionContext context, VirtualMachine vm, Op op) { if (vm.getConfiguration().isSafe(className)) { return getSafeField(field, instance, context, op, vm.getExceptionFactory()); } else { boolean isStatic = Modifier.isStatic(accessFlags); if (!isStatic) { // Instance field lookup isn't supported yet. String internalName = ClassNameUtils.toInternal(field.getType()); return HeapItem.newUnknown(internalName); } return getVirtualField(field, vm, context); } }
@Override public Op create(MethodLocation location, TIntObjectMap<MethodLocation> addressToLocation, VirtualMachine vm) { MethodLocation child = Utils.getNextLocation(location, addressToLocation); Instruction12x instr = (Instruction12x) location.getInstruction(); int destRegister = instr.getRegisterA(); int arrayRegister = instr.getRegisterB(); return new ArrayLengthOp(location, child, destRegister, arrayRegister, vm.getExceptionFactory()); }
@Before public void setUp() { vm = mock(VirtualMachine.class); mState = mock(MethodState.class); node = mock(ExecutionNode.class); location = mock(MethodLocation.class); when(location.getCodeAddress()).thenReturn(ADDRESS); ExceptionFactory exceptionFactory = mock(ExceptionFactory.class); when(vm.getExceptionFactory()).thenReturn(exceptionFactory); addressToLocation = new TIntObjectHashMap<MethodLocation>(); addressToLocation.put(ADDRESS, location); opFactory = new BinaryMathOpFactory(); }
@Before public void setUp() throws ClassNotFoundException { vm = mock(VirtualMachine.class); classManager = mock(ClassManager.class); when(vm.getClassManager()).thenReturn(classManager); classLoader = mock(SmaliClassLoader.class); when(vm.getClassLoader()).thenReturn(classLoader); configuration = mock(Configuration.class); when(vm.getConfiguration()).thenReturn(configuration); mState = mock(MethodState.class); context = mock(ExecutionContext.class); when(context.getMethodState()).thenReturn(mState); method = new java_lang_Class_forName(); op = mock(Op.class); exceptionFactory = mock(ExceptionFactory.class); when(vm.getExceptionFactory()).thenReturn(exceptionFactory); }
@Override public Op create(MethodLocation location, TIntObjectMap<MethodLocation> addressToLocation, VirtualMachine vm) { MethodLocation child = Utils.getNextLocation(location, addressToLocation); Instruction23x instr = (Instruction23x) location.getInstruction(); int valueRegister = instr.getRegisterA(); int arrayRegister = instr.getRegisterB(); int indexRegister = instr.getRegisterC(); return new AGetOp(location, child, valueRegister, arrayRegister, indexRegister, vm.getExceptionFactory()); }
@Override public Op create(MethodLocation location, TIntObjectMap<MethodLocation> addressToLocation, VirtualMachine vm) { MethodLocation child = Utils.getNextLocation(location, addressToLocation); Instruction23x instr = (Instruction23x) location.getInstruction(); int putRegister = instr.getRegisterA(); int arrayRegister = instr.getRegisterB(); int indexRegister = instr.getRegisterC(); return new APutOp(location, child, putRegister, arrayRegister, indexRegister, vm.getClassManager(), vm.getExceptionFactory()); }
@Override public Op create(MethodLocation location, TIntObjectMap<MethodLocation> addressToLocation, VirtualMachine vm) { MethodLocation child = Utils.getNextLocation(location, addressToLocation); Instruction21c instr = (Instruction21c) location.getInstruction(); int targetRegister = instr.getRegisterA(); TypeReference reference = (TypeReference) instr.getReference(); VirtualType referenceType = vm.getClassManager().getVirtualType(reference); return new CheckCastOp(location, child, targetRegister, referenceType, vm.getClassManager(), vm.getExceptionFactory()); }
@Override public void execute(VirtualMachine vm, Op op, ExecutionContext context) { MethodState mState = context.getMethodState(); HeapItem fieldItem = mState.peekParameter(0); HeapItem instanceItem = mState.peekParameter(1); Field field = (Field) fieldItem.getValue(); int accessFlags = field.getModifiers(); String fieldClassName = ClassNameUtils.toInternal(field.getDeclaringClass()); if (!field.isAccessible()) { VirtualType callingClass = context.getCallerContext().getMethod().getDefiningClass(); ClassManager classManager = vm.getClassManager(); VirtualClass fieldClass = classManager.getVirtualClass(fieldClassName); boolean hasAccess = checkAccess(callingClass, fieldClass, accessFlags, op, vm.getExceptionFactory()); if (!hasAccess) { return; } } Object instance = instanceItem.getValue(); HeapItem getItem = get(field, instance, fieldClassName, accessFlags, context, vm, op); mState.assignReturnRegister(getItem); }
Throwable exception = vm.getExceptionFactory().build(op, ClassNotFoundException.class, binaryClassName); setException(exception);
@Override public ConstOp create(MethodLocation location, TIntObjectMap<MethodLocation> addressToLocation, VirtualMachine vm) { MethodLocation child = Utils.getNextLocation(location, addressToLocation); BuilderInstruction instruction = (BuilderInstruction) location.getInstruction(); int destRegister = ((OneRegisterInstruction) instruction).getRegisterA(); ConstantType constantType; Object literal; String opName = instruction.getOpcode().name; if (opName.matches("const-string(?:/jumbo)?")) { ReferenceInstruction instr = (ReferenceInstruction) location.getInstruction(); literal = ((StringReference) instr.getReference()).getString(); constantType = ConstantType.STRING; } else if (opName.endsWith("-class")) { // Don't lookup the class here. Defer to actual execution to handle any possible exceptions. ReferenceInstruction instr = (ReferenceInstruction) location.getInstruction(); Reference classRef = instr.getReference(); literal = ReferenceUtil.getReferenceString(classRef); constantType = ConstantType.CLASS; } else if (opName.contains("-wide")) { WideLiteralInstruction instr = (WideLiteralInstruction) location.getInstruction(); literal = instr.getWideLiteral(); constantType = ConstantType.WIDE; } else { NarrowLiteralInstruction instr = (NarrowLiteralInstruction) location.getInstruction(); literal = instr.getNarrowLiteral(); constantType = ConstantType.NARROW; } return new ConstOp(location, child, destRegister, constantType, literal, vm.getClassLoader(), vm.getExceptionFactory()); }
@Override public BinaryMathOp create(MethodLocation location, TIntObjectMap<MethodLocation> addressToLocation, VirtualMachine vm) { MethodLocation child = Utils.getNextLocation(location, addressToLocation); BuilderInstruction instruction = (BuilderInstruction) location.getInstruction(); TwoRegisterInstruction instr = (TwoRegisterInstruction) location.getInstruction(); int destRegister = instr.getRegisterA(); int arg1Register = instr.getRegisterB(); ExceptionFactory exceptionFactory = vm.getExceptionFactory(); if (instruction instanceof Instruction23x) { // add-int vAA, vBB, vCC int arg2Register = ((Instruction23x) instruction).getRegisterC(); return new BinaryMathOp(location, child, destRegister, arg1Register, arg2Register, false, exceptionFactory); } else if (instruction instanceof Instruction12x) { // add-int/2addr vAA, vBB arg1Register = instr.getRegisterA(); int arg2Register = ((Instruction12x) instruction).getRegisterB(); return new BinaryMathOp(location, child, destRegister, arg1Register, arg2Register, false, exceptionFactory); } else if (instruction instanceof NarrowLiteralInstruction) { // Instruction22b - add-int/lit8 vAA, vBB, #CC // Instruction22s - add-int/lit16 vAA, vBB, #CCCC int arg2Literal = ((NarrowLiteralInstruction) instruction).getNarrowLiteral(); return new BinaryMathOp(location, child, destRegister, arg1Register, arg2Literal, true, exceptionFactory); } else { return null; } }