private int getMoveResultRegister(DecodedInstruction[] insnArr, int offset) { int nextOffset = getNextInsnOffset(insnArr, offset); if (nextOffset >= 0) { DecodedInstruction next = insnArr[nextOffset]; int opc = next.getOpcode(); if (opc == Opcodes.MOVE_RESULT || opc == Opcodes.MOVE_RESULT_WIDE || opc == Opcodes.MOVE_RESULT_OBJECT) { return next.getA(); } } return -1; }
/** * Helper method that encodes any of the register-list formats. */ private static void encodeRegisterList(DecodedInstruction insn, CodeOutput out) { out.write(codeUnit(insn.getOpcode(), makeByte(insn.getE(), insn.getRegisterCount())), insn.getIndexUnit(), codeUnit(insn.getA(), insn.getB(), insn.getC(), insn.getD())); }
/** * Helper method that encodes any of the three-unit register-range formats. */ private static void encodeRegisterRange(DecodedInstruction insn, CodeOutput out) { out.write(codeUnit(insn.getOpcode(), insn.getRegisterCount()), insn.getIndexUnit(), insn.getAUnit()); }
private InsnNode decodeSwitch(DecodedInstruction insn, int offset, boolean packed) { int payloadOffset = insn.getTarget(); DecodedInstruction payload = insnArr[payloadOffset]; Object[] keys; int[] targets; if (packed) { PackedSwitchPayloadDecodedInstruction ps = (PackedSwitchPayloadDecodedInstruction) payload; targets = ps.getTargets(); keys = new Object[targets.length]; int k = ps.getFirstKey(); for (int i = 0; i < keys.length; i++) { keys[i] = k++; } } else { SparseSwitchPayloadDecodedInstruction ss = (SparseSwitchPayloadDecodedInstruction) payload; targets = ss.getTargets(); keys = new Object[targets.length]; for (int i = 0; i < keys.length; i++) { keys[i] = ss.getKeys()[i]; } } // convert from relative to absolute offsets for (int i = 0; i < targets.length; i++) { targets[i] = targets[i] - payloadOffset + offset; } int nextOffset = getNextInsnOffset(insnArr, offset); return new SwitchNode(InsnArg.reg(insn, 0, ArgType.NARROW), keys, targets, nextOffset); }
public void test(Code mthCode) throws DecodeException { short[] encodedInstructions = mthCode.getInstructions(); int size = encodedInstructions.length; DecodedInstruction[] decoded = new DecodedInstruction[size]; ShortArrayCodeInput in = new ShortArrayCodeInput(encodedInstructions); try { while (in.hasMore()) { decoded[in.cursor()] = DecodedInstruction.decode(in); } } catch (EOFException e) { throw new DecodeException(method, "", e); } insnArr = decoded; } }
public void decodeInsns(Code mthCode) throws DecodeException { short[] encodedInstructions = mthCode.getInstructions(); int size = encodedInstructions.length; DecodedInstruction[] decoded = new DecodedInstruction[size]; ShortArrayCodeInput in = new ShortArrayCodeInput(encodedInstructions); try { while (in.hasMore()) { decoded[in.cursor()] = decodeRawInsn(in); } } catch (Exception e) { throw new DecodeException(method, e.getMessage(), e); } insnArr = decoded; }
public FillArrayNode(int resReg, FillArrayDataPayloadDecodedInstruction payload) { super(InsnType.FILL_ARRAY, 0); ArgType elType; switch (payload.getElementWidthUnit()) { case 1: elType = ArgType.unknown(PrimitiveType.BOOLEAN, PrimitiveType.BYTE); break; case 2: elType = ArgType.unknown(PrimitiveType.SHORT, PrimitiveType.CHAR); break; case 4: elType = ArgType.unknown(PrimitiveType.INT, PrimitiveType.FLOAT); break; case 8: elType = ArgType.unknown(PrimitiveType.LONG, PrimitiveType.DOUBLE); break; default: throw new JadxRuntimeException("Unknown array element width: " + payload.getElementWidthUnit()); } setResult(InsnArg.reg(resReg, ArgType.array(elType))); this.data = payload.getData(); this.size = payload.getSize(); this.elemType = elType; }
private InsnNode filledNewArray(DecodedInstruction insn, int offset, boolean isRange) { int resReg = getMoveResultRegister(insnArr, offset); ArgType arrType = dex.getType(insn.getIndex()); ArgType elType = arrType.getArrayElement(); boolean typeImmutable = elType.isPrimitive(); int regsCount = insn.getRegisterCount(); InsnArg[] regs = new InsnArg[regsCount]; if (isRange) { int r = insn.getA(); for (int i = 0; i < regsCount; i++) { regs[i] = InsnArg.reg(r, elType, typeImmutable); r++; } } else { for (int i = 0; i < regsCount; i++) { int regNum = InsnUtils.getArg(insn, i); regs[i] = InsnArg.reg(regNum, elType, typeImmutable); } } InsnNode node = new FilledNewArrayNode(elType, regs.length); node.setResult(resReg == -1 ? null : InsnArg.reg(resReg, arrType)); for (InsnArg arg : regs) { node.addArg(arg); } return node; }
@NotNull private InsnNode decode(DecodedInstruction insn, int offset) throws DecodeException { switch (insn.getOpcode()) { case Opcodes.NOP: case Opcodes.PACKED_SWITCH_PAYLOAD: InsnNode constStrInsn = new ConstStringNode(dex.getString(insn.getIndex())); constStrInsn.setResult(InsnArg.reg(insn, 0, ArgType.STRING)); return constStrInsn; InsnNode constClsInsn = new ConstClassNode(dex.getType(insn.getIndex())); constClsInsn.setResult(InsnArg.reg(insn, 0, ArgType.CLASS)); return constClsInsn; case Opcodes.GOTO_16: case Opcodes.GOTO_32: return new GotoNode(insn.getTarget()); InsnNode instInsn = new IndexInsnNode(InsnType.INSTANCE_OF, dex.getType(insn.getIndex()), 1); instInsn.setResult(InsnArg.reg(insn, 0, ArgType.BOOLEAN)); instInsn.addArg(InsnArg.reg(insn, 1, ArgType.UNKNOWN_OBJECT)); ArgType castType = dex.getType(insn.getIndex()); InsnNode checkCastInsn = new IndexInsnNode(InsnType.CHECK_CAST, castType, 1); checkCastInsn.setResult(InsnArg.reg(insn, 0, castType)); case Opcodes.IGET_WIDE: case Opcodes.IGET_OBJECT: FieldInfo igetFld = FieldInfo.fromDex(dex, insn.getIndex()); InsnNode igetInsn = new IndexInsnNode(InsnType.IGET, igetFld, 1);
public IfNode(DecodedInstruction insn, IfOp op) { this(op, insn.getTarget(), InsnArg.reg(insn, 0, ARG_TYPE), insn.getRegisterCount() == 1 ? InsnArg.lit(0, ARG_TYPE) : InsnArg.reg(insn, 1, ARG_TYPE)); }
private DecodedInstruction decodeRawInsn(ShortArrayCodeInput in) throws EOFException { int opcodeUnit = in.read(); int opcode = Opcodes.extractOpcodeFromUnit(opcodeUnit); OpcodeInfo.Info opcodeInfo; try { opcodeInfo = OpcodeInfo.get(opcode); } catch (IllegalArgumentException e) { LOG.warn("Ignore decode error: '{}', replace with NOP instruction", e.getMessage()); opcodeInfo = OpcodeInfo.NOP; } return opcodeInfo.getFormat().decode(opcodeUnit, in); }
public static LiteralArg lit(DecodedInstruction insn, ArgType type) { return lit(insn.getLiteral(), type); }
private InsnNode invoke(DecodedInstruction insn, int offset, InvokeType type, boolean isRange) { int resReg = getMoveResultRegister(insnArr, offset); MethodInfo mth = MethodInfo.fromDex(dex, insn.getIndex()); return new InvokeNode(mth, insn, type, isRange, resReg); }
public ArithNode(DecodedInstruction insn, ArithOp op, ArgType type, boolean literal) { super(InsnType.ARITH, 2); this.op = op; setResult(InsnArg.reg(insn, 0, type)); int rc = insn.getRegisterCount(); if (literal) { if (rc == 1) { // self addReg(insn, 0, type); addLit(insn, type); } else if (rc == 2) { // normal addReg(insn, 1, type); addLit(insn, type); } } else { if (rc == 2) { // self addReg(insn, 0, type); addReg(insn, 1, type); } else if (rc == 3) { // normal addReg(insn, 1, type); addReg(insn, 2, type); } } }
public InvokeNode(MethodInfo mth, DecodedInstruction insn, InvokeType type, boolean isRange, int resReg) { super(InsnType.INVOKE, mth.getArgsCount() + (type != InvokeType.STATIC ? 1 : 0)); this.mth = mth; this.type = type; if (resReg >= 0) { setResult(InsnArg.reg(resReg, mth.getReturnType())); } int k = isRange ? insn.getA() : 0; if (type != InvokeType.STATIC) { int r = isRange ? k : InsnUtils.getArg(insn, k); addReg(r, mth.getDeclClass().getType()); k++; } for (ArgType arg : mth.getArgumentsTypes()) { addReg(isRange ? k : InsnUtils.getArg(insn, k), arg); k += arg.getRegCount(); } }
/** * Helper method that encodes any of the register-list formats. */ private static void encodeRegisterList(DecodedInstruction insn, CodeOutput out) { out.write(codeUnit(insn.getOpcode(), makeByte(insn.getE(), insn.getRegisterCount())), insn.getIndexUnit(), codeUnit(insn.getA(), insn.getB(), insn.getC(), insn.getD())); }
/** * Helper method that encodes any of the three-unit register-range formats. */ private static void encodeRegisterRange(DecodedInstruction insn, CodeOutput out) { out.write(codeUnit(insn.getOpcode(), insn.getRegisterCount()), insn.getIndexUnit(), insn.getAUnit()); }
/** * Helper method that encodes any of the three-unit register-range formats. */ private static void encodeRegisterRange(DecodedInstruction insn, CodeOutput out) { out.write(codeUnit(insn.getOpcode(), insn.getRegisterCount()), insn.getIndexUnit(), insn.getAUnit()); }