use of org.jf.dexlib2.analysis.AnalyzedInstruction in project smali by JesusFreke.
the class PreInstructionRegisterInfoMethodItem method writeFullMerge.
private void writeFullMerge(IndentingWriter writer, int registerNum) throws IOException {
registerFormatter.writeTo(writer, registerNum);
writer.write('=');
analyzedInstruction.getPreInstructionRegisterType(registerNum).writeTo(writer);
writer.write(":merge{");
boolean first = true;
for (AnalyzedInstruction predecessor : analyzedInstruction.getPredecessors()) {
RegisterType predecessorRegisterType = analyzedInstruction.getPredecessorRegisterType(predecessor, registerNum);
if (!first) {
writer.write(',');
}
if (predecessor.getInstructionIndex() == -1) {
//the fake "StartOfMethod" instruction
writer.write("Start:");
} else {
writer.write("0x");
writer.printUnsignedLongAsHex(methodAnalyzer.getInstructionAddress(predecessor));
writer.write(':');
}
predecessorRegisterType.writeTo(writer);
first = false;
}
writer.write('}');
}
use of org.jf.dexlib2.analysis.AnalyzedInstruction in project smali by JesusFreke.
the class MethodDefinition method addAnalyzedInstructionMethodItems.
private void addAnalyzedInstructionMethodItems(List<MethodItem> methodItems) {
MethodAnalyzer methodAnalyzer = new MethodAnalyzer(classDef.options.classPath, method, classDef.options.inlineResolver, classDef.options.normalizeVirtualMethods);
AnalysisException analysisException = methodAnalyzer.getAnalysisException();
if (analysisException != null) {
// TODO: need to keep track of whether any errors occurred, so we can exit with a non-zero result
methodItems.add(new CommentMethodItem(String.format("AnalysisException: %s", analysisException.getMessage()), analysisException.codeAddress, Integer.MIN_VALUE));
analysisException.printStackTrace(System.err);
}
List<AnalyzedInstruction> instructions = methodAnalyzer.getAnalyzedInstructions();
int currentCodeAddress = 0;
for (int i = 0; i < instructions.size(); i++) {
AnalyzedInstruction instruction = instructions.get(i);
MethodItem methodItem = InstructionMethodItemFactory.makeInstructionFormatMethodItem(this, currentCodeAddress, instruction.getInstruction());
methodItems.add(methodItem);
if (instruction.getInstruction().getOpcode().format == Format.UnresolvedOdexInstruction) {
methodItems.add(new CommentedOutMethodItem(InstructionMethodItemFactory.makeInstructionFormatMethodItem(this, currentCodeAddress, instruction.getOriginalInstruction())));
}
if (i != instructions.size() - 1) {
methodItems.add(new BlankMethodItem(currentCodeAddress));
}
if (classDef.options.codeOffsets) {
methodItems.add(new MethodItem(currentCodeAddress) {
@Override
public double getSortOrder() {
return -1000;
}
@Override
public boolean writeTo(IndentingWriter writer) throws IOException {
writer.write("#@");
writer.printUnsignedLongAsHex(codeAddress & 0xFFFFFFFFL);
return true;
}
});
}
if (classDef.options.registerInfo != 0 && !instruction.getInstruction().getOpcode().format.isPayloadFormat) {
methodItems.add(new PreInstructionRegisterInfoMethodItem(classDef.options.registerInfo, methodAnalyzer, registerFormatter, instruction, currentCodeAddress));
methodItems.add(new PostInstructionRegisterInfoMethodItem(registerFormatter, instruction, currentCodeAddress));
}
currentCodeAddress += instruction.getInstruction().getCodeUnits();
}
}
use of org.jf.dexlib2.analysis.AnalyzedInstruction in project smali by JesusFreke.
the class AnalyzedInstruction method getSetRegisters.
public List<Integer> getSetRegisters() {
List<Integer> setRegisters = Lists.newArrayList();
if (instruction.getOpcode().setsRegister()) {
setRegisters.add(getDestinationRegister());
}
if (instruction.getOpcode().setsWideRegister()) {
setRegisters.add(getDestinationRegister() + 1);
}
if (isInvokeInit()) {
//When constructing a new object, the register type will be an uninitialized reference after the new-instance
//instruction, but becomes an initialized reference once the <init> method is called. So even though invoke
//instructions don't normally change any registers, calling an <init> method will change the type of its
//object register. If the uninitialized reference has been copied to other registers, they will be initialized
//as well, so we need to check for that too
int destinationRegister;
if (instruction instanceof FiveRegisterInstruction) {
destinationRegister = ((FiveRegisterInstruction) instruction).getRegisterC();
assert ((FiveRegisterInstruction) instruction).getRegisterCount() > 0;
} else {
assert instruction instanceof RegisterRangeInstruction;
RegisterRangeInstruction rangeInstruction = (RegisterRangeInstruction) instruction;
assert rangeInstruction.getRegisterCount() > 0;
destinationRegister = rangeInstruction.getStartRegister();
}
RegisterType preInstructionDestRegisterType = getPreInstructionRegisterType(destinationRegister);
if (preInstructionDestRegisterType.category == RegisterType.UNINIT_REF || preInstructionDestRegisterType.category == RegisterType.UNINIT_THIS) {
setRegisters.add(destinationRegister);
RegisterType objectRegisterType = preRegisterMap[destinationRegister];
for (int i = 0; i < preRegisterMap.length; i++) {
if (i == destinationRegister) {
continue;
}
RegisterType preInstructionRegisterType = preRegisterMap[i];
if (preInstructionRegisterType.equals(objectRegisterType)) {
setRegisters.add(i);
} else if (preInstructionRegisterType.category == RegisterType.UNINIT_REF || preInstructionRegisterType.category == RegisterType.UNINIT_THIS) {
RegisterType postInstructionRegisterType = postRegisterMap[i];
if (postInstructionRegisterType.category == RegisterType.UNKNOWN) {
setRegisters.add(i);
}
}
}
} else if (preInstructionDestRegisterType.category == RegisterType.UNKNOWN) {
for (int i = 0; i < preRegisterMap.length; i++) {
RegisterType registerType = preRegisterMap[i];
if (registerType.category == RegisterType.UNINIT_REF || registerType.category == RegisterType.UNINIT_THIS) {
setRegisters.add(i);
}
}
}
}
// branch of the following if-eqz/if-nez
if (instructionIndex > 0 && methodAnalyzer.getClassPath().isArt() && getPredecessorCount() == 1 && (instruction.getOpcode() == Opcode.IF_EQZ || instruction.getOpcode() == Opcode.IF_NEZ)) {
AnalyzedInstruction prevInstruction = predecessors.first();
if (prevInstruction.instruction.getOpcode() == Opcode.INSTANCE_OF && MethodAnalyzer.canPropagateTypeAfterInstanceOf(prevInstruction, this, methodAnalyzer.getClassPath())) {
Instruction22c instanceOfInstruction = (Instruction22c) prevInstruction.instruction;
setRegisters.add(instanceOfInstruction.getRegisterB());
// TODO: do we need to do some sort of additional check that these multiple move-object predecessors actually refer to the same value?
if (instructionIndex > 1) {
int originalSourceRegister = -1;
RegisterType newType = null;
for (AnalyzedInstruction prevPrevAnalyzedInstruction : prevInstruction.predecessors) {
Opcode opcode = prevPrevAnalyzedInstruction.instruction.getOpcode();
if (opcode == Opcode.MOVE_OBJECT || opcode == Opcode.MOVE_OBJECT_16 || opcode == Opcode.MOVE_OBJECT_FROM16) {
TwoRegisterInstruction moveInstruction = ((TwoRegisterInstruction) prevPrevAnalyzedInstruction.instruction);
RegisterType originalType = prevPrevAnalyzedInstruction.getPostInstructionRegisterType(moveInstruction.getRegisterB());
if (moveInstruction.getRegisterA() != instanceOfInstruction.getRegisterB()) {
originalSourceRegister = -1;
break;
}
if (originalType.type == null) {
originalSourceRegister = -1;
break;
}
if (newType == null) {
newType = RegisterType.getRegisterType(methodAnalyzer.getClassPath(), (TypeReference) instanceOfInstruction.getReference());
}
if (MethodAnalyzer.isNotWideningConversion(originalType, newType)) {
if (originalSourceRegister != -1) {
if (originalSourceRegister != moveInstruction.getRegisterB()) {
originalSourceRegister = -1;
break;
}
} else {
originalSourceRegister = moveInstruction.getRegisterB();
}
}
} else {
originalSourceRegister = -1;
break;
}
}
if (originalSourceRegister != -1) {
setRegisters.add(originalSourceRegister);
}
}
}
}
return setRegisters;
}
use of org.jf.dexlib2.analysis.AnalyzedInstruction in project smali by JesusFreke.
the class CustomInlineMethodResolver method resolveExecuteInline.
@Override
@Nonnull
public Method resolveExecuteInline(@Nonnull AnalyzedInstruction analyzedInstruction) {
InlineIndexInstruction instruction = (InlineIndexInstruction) analyzedInstruction.instruction;
int methodIndex = instruction.getInlineIndex();
if (methodIndex < 0 || methodIndex >= inlineMethods.length) {
throw new RuntimeException("Invalid method index: " + methodIndex);
}
return inlineMethods[methodIndex];
}
use of org.jf.dexlib2.analysis.AnalyzedInstruction in project smali by JesusFreke.
the class MethodAnalyzer method analyzeNewInstance.
private void analyzeNewInstance(@Nonnull AnalyzedInstruction analyzedInstruction) {
ReferenceInstruction instruction = (ReferenceInstruction) analyzedInstruction.instruction;
int register = ((OneRegisterInstruction) analyzedInstruction.instruction).getRegisterA();
RegisterType destRegisterType = analyzedInstruction.getPostInstructionRegisterType(register);
if (destRegisterType.category != RegisterType.UNKNOWN) {
//successors and nothing else needs to be done.
assert destRegisterType.category == RegisterType.UNINIT_REF;
return;
}
TypeReference typeReference = (TypeReference) instruction.getReference();
RegisterType classType = RegisterType.getRegisterType(classPath, typeReference);
setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, RegisterType.getRegisterType(RegisterType.UNINIT_REF, classType.type));
}
Aggregations