use of org.jf.dexlib2.iface.instruction.RegisterRangeInstruction in project atlas by alibaba.
the class InstructionMethodItem method writeInvokeRangeRegisters.
protected void writeInvokeRangeRegisters(IndentingWriter writer) throws IOException {
RegisterRangeInstruction instruction = (RegisterRangeInstruction) this.instruction;
int regCount = instruction.getRegisterCount();
if (regCount == 0) {
writer.write("{}");
} else {
int startRegister = instruction.getStartRegister();
methodDef.registerFormatter.writeRegisterRange(writer, startRegister, startRegister + regCount - 1);
}
}
use of org.jf.dexlib2.iface.instruction.RegisterRangeInstruction in project atlas by alibaba.
the class PreInstructionRegisterInfoMethodItem method addArgsRegs.
private void addArgsRegs(BitSet registers) {
if (analyzedInstruction.getInstruction() instanceof RegisterRangeInstruction) {
RegisterRangeInstruction instruction = (RegisterRangeInstruction) analyzedInstruction.getInstruction();
registers.set(instruction.getStartRegister(), instruction.getStartRegister() + instruction.getRegisterCount());
} else if (analyzedInstruction.getInstruction() instanceof FiveRegisterInstruction) {
FiveRegisterInstruction instruction = (FiveRegisterInstruction) analyzedInstruction.getInstruction();
int regCount = instruction.getRegisterCount();
switch(regCount) {
case 5:
registers.set(instruction.getRegisterG());
//fall through
case 4:
registers.set(instruction.getRegisterF());
//fall through
case 3:
registers.set(instruction.getRegisterE());
//fall through
case 2:
registers.set(instruction.getRegisterD());
//fall through
case 1:
registers.set(instruction.getRegisterC());
}
} else if (analyzedInstruction.getInstruction() instanceof ThreeRegisterInstruction) {
ThreeRegisterInstruction instruction = (ThreeRegisterInstruction) analyzedInstruction.getInstruction();
registers.set(instruction.getRegisterA());
registers.set(instruction.getRegisterB());
registers.set(instruction.getRegisterC());
} else if (analyzedInstruction.getInstruction() instanceof TwoRegisterInstruction) {
TwoRegisterInstruction instruction = (TwoRegisterInstruction) analyzedInstruction.getInstruction();
registers.set(instruction.getRegisterA());
registers.set(instruction.getRegisterB());
} else if (analyzedInstruction.getInstruction() instanceof OneRegisterInstruction) {
OneRegisterInstruction instruction = (OneRegisterInstruction) analyzedInstruction.getInstruction();
registers.set(instruction.getRegisterA());
}
}
use of org.jf.dexlib2.iface.instruction.RegisterRangeInstruction 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.iface.instruction.RegisterRangeInstruction in project smali by JesusFreke.
the class AnalyzedInstruction method setsRegister.
/**
* Determines if this instruction sets the given register, or alters its type
*
* @param registerNumber The register to check
* @return true if this instruction sets the given register or alters its type
*/
public boolean setsRegister(int registerNumber) {
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) {
assert ((FiveRegisterInstruction) instruction).getRegisterCount() > 0;
destinationRegister = ((FiveRegisterInstruction) instruction).getRegisterC();
} else {
assert instruction instanceof RegisterRangeInstruction;
RegisterRangeInstruction rangeInstruction = (RegisterRangeInstruction) instruction;
assert rangeInstruction.getRegisterCount() > 0;
destinationRegister = rangeInstruction.getStartRegister();
}
RegisterType preInstructionDestRegisterType = getPreInstructionRegisterType(destinationRegister);
if (preInstructionDestRegisterType.category == RegisterType.UNKNOWN) {
// We never let an uninitialized reference propagate past an invoke-init if the object register type is
// unknown This is because the uninitialized reference may be an alias to the reference being
// initialized, but we can't know that until the object register's type is known
RegisterType preInstructionRegisterType = getPreInstructionRegisterType(registerNumber);
if (preInstructionRegisterType.category == RegisterType.UNINIT_REF || preInstructionRegisterType.category == RegisterType.UNINIT_THIS) {
return true;
}
}
if (preInstructionDestRegisterType.category != RegisterType.UNINIT_REF && preInstructionDestRegisterType.category != RegisterType.UNINIT_THIS) {
return false;
}
if (registerNumber == destinationRegister) {
return true;
}
//check if the uninit ref has been copied to another register
return preInstructionDestRegisterType.equals(getPreInstructionRegisterType(registerNumber));
}
// 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;
if (registerNumber == instanceOfInstruction.getRegisterB()) {
return true;
}
// 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 && registerNumber == originalSourceRegister) {
return true;
}
}
}
}
if (!instruction.getOpcode().setsRegister()) {
return false;
}
int destinationRegister = getDestinationRegister();
if (registerNumber == destinationRegister) {
return true;
}
if (instruction.getOpcode().setsWideRegister() && registerNumber == (destinationRegister + 1)) {
return true;
}
return false;
}
Aggregations