package org.jf.dexlib2.dexbacked.instruction;
import org.jf.dexlib2.Opcode;
import org.jf.dexlib2.dexbacked.DexBackedDexFile;
import org.jf.dexlib2.dexbacked.DexReader;
import org.jf.dexlib2.iface.instruction.Instruction;
import org.jf.util.ExceptionWithContext;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public abstract class DexBackedInstruction implements Instruction {
@Nonnull public final DexBackedDexFile dexFile;
@Nonnull public final Opcode opcode;
public final int instructionStart;
public DexBackedInstruction(@Nonnull DexBackedDexFile dexFile,
@Nonnull Opcode opcode,
int instructionStart) {
this.dexFile = dexFile;
this.opcode = opcode;
this.instructionStart = instructionStart;
}
@Nonnull public Opcode getOpcode() { return opcode; }
@Override public int getCodeUnits() { return opcode.format.size / 2; }
@Nonnull
public static Instruction readFrom(DexBackedDexFile dexFile, @Nonnull DexReader reader) {
int opcodeValue = reader.peekUbyte();
if (opcodeValue == 0) {
opcodeValue = reader.peekUshort();
}
Opcode opcode = dexFile.getOpcodes().getOpcodeByValue(opcodeValue);
Instruction instruction = buildInstruction(dexFile, opcode,
reader.getOffset() + reader.dexBuf.getBaseOffset() -
dexFile.getBuffer().getBaseOffset() - dexFile.getBaseDataOffset());
reader.moveRelative(instruction.getCodeUnits()*2);
return instruction;
}
private static DexBackedInstruction buildInstruction(@Nonnull DexBackedDexFile dexFile, @Nullable Opcode opcode,
int instructionStartOffset) {
if (opcode == null) {
return new DexBackedUnknownInstruction(dexFile, instructionStartOffset);
}
switch (opcode.format) {
case Format10t:
return new DexBackedInstruction10t(dexFile, opcode, instructionStartOffset);
case Format10x:
return new DexBackedInstruction10x(dexFile, opcode, instructionStartOffset);
case Format11n:
return new DexBackedInstruction11n(dexFile, opcode, instructionStartOffset);
case Format11x:
return new DexBackedInstruction11x(dexFile, opcode, instructionStartOffset);
case Format12x:
return new DexBackedInstruction12x(dexFile, opcode, instructionStartOffset);
case Format20bc:
return new DexBackedInstruction20bc(dexFile, opcode, instructionStartOffset);
case Format20t:
return new DexBackedInstruction20t(dexFile, opcode, instructionStartOffset);
case Format21c:
return new DexBackedInstruction21c(dexFile, opcode, instructionStartOffset);
case Format21ih:
return new DexBackedInstruction21ih(dexFile, opcode, instructionStartOffset);
case Format21lh:
return new DexBackedInstruction21lh(dexFile, opcode, instructionStartOffset);
case Format21s:
return new DexBackedInstruction21s(dexFile, opcode, instructionStartOffset);
case Format21t:
return new DexBackedInstruction21t(dexFile, opcode, instructionStartOffset);
case Format22b:
return new DexBackedInstruction22b(dexFile, opcode, instructionStartOffset);
case Format22c:
return new DexBackedInstruction22c(dexFile, opcode, instructionStartOffset);
case Format22cs:
return new DexBackedInstruction22cs(dexFile, opcode, instructionStartOffset);
case Format22s:
return new DexBackedInstruction22s(dexFile, opcode, instructionStartOffset);
case Format22t:
return new DexBackedInstruction22t(dexFile, opcode, instructionStartOffset);
case Format22x:
return new DexBackedInstruction22x(dexFile, opcode, instructionStartOffset);
case Format23x:
return new DexBackedInstruction23x(dexFile, opcode, instructionStartOffset);
case Format30t:
return new DexBackedInstruction30t(dexFile, opcode, instructionStartOffset);
case Format31c:
return new DexBackedInstruction31c(dexFile, opcode, instructionStartOffset);
case Format31i:
return new DexBackedInstruction31i(dexFile, opcode, instructionStartOffset);
case Format31t:
return new DexBackedInstruction31t(dexFile, opcode, instructionStartOffset);
case Format32x:
return new DexBackedInstruction32x(dexFile, opcode, instructionStartOffset);
case Format35c:
return new DexBackedInstruction35c(dexFile, opcode, instructionStartOffset);
case Format35ms:
return new DexBackedInstruction35ms(dexFile, opcode, instructionStartOffset);
case Format35mi:
return new DexBackedInstruction35mi(dexFile, opcode, instructionStartOffset);
case Format3rc:
return new DexBackedInstruction3rc(dexFile, opcode, instructionStartOffset);
case Format3rmi:
return new DexBackedInstruction3rmi(dexFile, opcode, instructionStartOffset);
case Format3rms:
return new DexBackedInstruction3rms(dexFile, opcode, instructionStartOffset);
case Format45cc:
return new DexBackedInstruction45cc(dexFile, opcode, instructionStartOffset);
case Format4rcc:
return new DexBackedInstruction4rcc(dexFile, opcode, instructionStartOffset);
case Format51l:
return new DexBackedInstruction51l(dexFile, opcode, instructionStartOffset);
case PackedSwitchPayload:
return new DexBackedPackedSwitchPayload(dexFile, instructionStartOffset);
case SparseSwitchPayload:
return new DexBackedSparseSwitchPayload(dexFile, instructionStartOffset);
case ArrayPayload:
return new DexBackedArrayPayload(dexFile, instructionStartOffset);
default:
throw new ExceptionWithContext("Unexpected opcode format: %s", opcode.format.toString());
}
}
}