@Nonnull public Opcode getAndCheckDeodexedOpcode(@Nonnull String fieldType, @Nonnull Opcode odexedOpcode) { FieldOpcode fieldOpcode = opcodeMap[isGet(odexedOpcode)?GET:PUT] [isStatic(odexedOpcode)?STATIC:INSTANCE] [getTypeIndex(fieldType.charAt(0))]; if (!isCompatible(odexedOpcode, fieldOpcode.type)) { throw new AnalysisException(String.format("Incorrect field type \"%s\" for %s", fieldType, odexedOpcode.name)); } return fieldOpcode.normalOpcode; }
@Override public OdexedFieldInstructionMapper get() { return new OdexedFieldInstructionMapper(isArt()); } });
public OdexedFieldInstructionMapper(boolean isArt) { FieldOpcode[] opcodes; if (isArt) { opcodes = artFieldOpcodes; } else { opcodes = dalvikFieldOpcodes; } for (FieldOpcode fieldOpcode: opcodes) { opcodeMap[isGet(fieldOpcode.normalOpcode)?GET:PUT] [isStatic(fieldOpcode.normalOpcode)?STATIC:INSTANCE] [getTypeIndex(fieldOpcode.type)] = fieldOpcode; if (fieldOpcode.quickOpcode != null) { opcodeValueTypeMap.put(fieldOpcode.quickOpcode, getValueType(fieldOpcode.type)); } if (fieldOpcode.volatileOpcode != null) { opcodeValueTypeMap.put(fieldOpcode.volatileOpcode, getValueType(fieldOpcode.type)); } } }
private boolean analyzePutGetVolatile(@Nonnull AnalyzedInstruction analyzedInstruction, boolean analyzeResult) { FieldReference field = (FieldReference)((ReferenceInstruction)analyzedInstruction.instruction).getReference(); String fieldType = field.getType(); Opcode originalOpcode = analyzedInstruction.instruction.getOpcode(); Opcode opcode = classPath.getFieldInstructionMapper().getAndCheckDeodexedOpcode( fieldType, originalOpcode); Instruction deodexedInstruction; if (originalOpcode.isStaticFieldAccessor()) { OneRegisterInstruction instruction = (OneRegisterInstruction)analyzedInstruction.instruction; deodexedInstruction = new ImmutableInstruction21c(opcode, instruction.getRegisterA(), field); } else { TwoRegisterInstruction instruction = (TwoRegisterInstruction)analyzedInstruction.instruction; deodexedInstruction = new ImmutableInstruction22c(opcode, instruction.getRegisterA(), instruction.getRegisterB(), field); } analyzedInstruction.setDeodexedInstruction(deodexedInstruction); if (analyzeResult) { analyzeInstruction(analyzedInstruction); } return true; }
@Nonnull static Opcode getAndCheckDeodexedOpcodeForOdexedOpcode(@Nonnull String fieldType, @Nonnull Opcode odexedOpcode,MethodAnalyzer ma) { int opcodeType = odexedOpcode.setsRegister()?0:1; int opcodeSubType = getOpcodeSubtype(odexedOpcode); int typeIndex = getTypeIndex(fieldType.charAt(0)); Opcode correctOdexedOpcode, deodexedOpcode; correctOdexedOpcode = opcodeMap[opcodeType][opcodeSubType][0][typeIndex]; deodexedOpcode = opcodeMap[opcodeType][opcodeSubType][1][typeIndex]; if (correctOdexedOpcode != odexedOpcode) { throw new AnalysisException(String.format("Incorrect field type \"%s\" for %s", fieldType, odexedOpcode.name)); } return deodexedOpcode; } }
private boolean isCompatible(Opcode opcode, char type) { Integer valueType = opcodeValueTypeMap.get(opcode); if (valueType == null) { throw new RuntimeException("Unexpected opcode: " + opcode.name); } return valueType == getValueType(type); } }
private boolean analyzePutGetVolatile(@Nonnull AnalyzedInstruction analyzedInstruction, boolean analyzeResult) { FieldReference field = (FieldReference)((ReferenceInstruction)analyzedInstruction.instruction).getReference(); String fieldType = field.getType(); Opcode originalOpcode = analyzedInstruction.instruction.getOpcode(); Opcode opcode = OdexedFieldInstructionMapper.getAndCheckDeodexedOpcodeForOdexedOpcode(fieldType, originalOpcode,this); Instruction deodexedInstruction; if (originalOpcode.isOdexedStaticVolatile()) { OneRegisterInstruction instruction = (OneRegisterInstruction)analyzedInstruction.instruction; deodexedInstruction = new ImmutableInstruction21c(opcode, instruction.getRegisterA(), field); } else { TwoRegisterInstruction instruction = (TwoRegisterInstruction)analyzedInstruction.instruction; deodexedInstruction = new ImmutableInstruction22c(opcode, instruction.getRegisterA(), instruction.getRegisterB(), field); } analyzedInstruction.setDeodexedInstruction(deodexedInstruction); if (analyzeResult) { analyzeInstruction(analyzedInstruction); } return true; }
Opcode opcode = classPath.getFieldInstructionMapper().getAndCheckDeodexedOpcode( fieldType, instruction.getOpcode());
private boolean isCompatible(Opcode opcode, char type) { Integer valueType = opcodeValueTypeMap.get(opcode); if (valueType == null) { throw new RuntimeException("Unexpected opcode: " + opcode.name); } return valueType == getValueType(type); } }
Opcode opcode = OdexedFieldInstructionMapper.getAndCheckDeodexedOpcodeForOdexedOpcode(fieldType, instruction.getOpcode(),this);
@Nonnull public Opcode getAndCheckDeodexedOpcode(@Nonnull String fieldType, @Nonnull Opcode odexedOpcode) { FieldOpcode fieldOpcode = opcodeMap[isGet(odexedOpcode)?GET:PUT] [isStatic(odexedOpcode)?STATIC:INSTANCE] [getTypeIndex(fieldType.charAt(0))]; if (!isCompatible(odexedOpcode, fieldOpcode.type)) { throw new AnalysisException(String.format("Incorrect field type \"%s\" for %s", fieldType, odexedOpcode.name)); } return fieldOpcode.normalOpcode; }
public OdexedFieldInstructionMapper(boolean isArt) { FieldOpcode[] opcodes; if (isArt) { opcodes = artFieldOpcodes; } else { opcodes = dalvikFieldOpcodes; } for (FieldOpcode fieldOpcode: opcodes) { opcodeMap[isGet(fieldOpcode.normalOpcode)?GET:PUT] [isStatic(fieldOpcode.normalOpcode)?STATIC:INSTANCE] [getTypeIndex(fieldOpcode.type)] = fieldOpcode; if (fieldOpcode.quickOpcode != null) { opcodeValueTypeMap.put(fieldOpcode.quickOpcode, getValueType(fieldOpcode.type)); } if (fieldOpcode.volatileOpcode != null) { opcodeValueTypeMap.put(fieldOpcode.volatileOpcode, getValueType(fieldOpcode.type)); } } }
Instruction decompileInstanceFieldAccess(Instruction instruction) { final int fieldIndex = nextInfo().getIndex(); final DexBackedFieldReference fieldRef = (DexBackedFieldReference) DexBackedReference.makeReference(mDex, ReferenceType.FIELD, fieldIndex); final Opcode newOpcode = sInstrMapper.getAndCheckDeodexedOpcode( fieldRef.getType(), instruction.getOpcode()); final Instruction22cs instr = (Instruction22cs) instruction; return new ImmutableInstruction22c(newOpcode, instr.getRegisterA(), instr.getRegisterB(), fieldRef); }
@Override public OdexedFieldInstructionMapper get() { return new OdexedFieldInstructionMapper(isArt()); } });
private boolean analyzePutGetVolatile(@Nonnull AnalyzedInstruction analyzedInstruction, boolean analyzeResult) { FieldReference field = (FieldReference)((ReferenceInstruction)analyzedInstruction.instruction).getReference(); String fieldType = field.getType(); Opcode originalOpcode = analyzedInstruction.instruction.getOpcode(); Opcode opcode = classPath.getFieldInstructionMapper().getAndCheckDeodexedOpcode( fieldType, originalOpcode); Instruction deodexedInstruction; if (originalOpcode.isStaticFieldAccessor()) { OneRegisterInstruction instruction = (OneRegisterInstruction)analyzedInstruction.instruction; deodexedInstruction = new ImmutableInstruction21c(opcode, instruction.getRegisterA(), field); } else { TwoRegisterInstruction instruction = (TwoRegisterInstruction)analyzedInstruction.instruction; deodexedInstruction = new ImmutableInstruction22c(opcode, instruction.getRegisterA(), instruction.getRegisterB(), field); } analyzedInstruction.setDeodexedInstruction(deodexedInstruction); if (analyzeResult) { analyzeInstruction(analyzedInstruction); } return true; }
Opcode opcode = classPath.getFieldInstructionMapper().getAndCheckDeodexedOpcode( fieldType, instruction.getOpcode());