use of jadx.core.dex.instructions.IndexInsnNode in project jadx by skylot.
the class ClassModifier method removeFieldUsageFromConstructor.
private static boolean removeFieldUsageFromConstructor(MethodNode mth, FieldNode field, ClassNode fieldsCls) {
if (mth.isNoCode() || !mth.getAccessFlags().isConstructor()) {
return false;
}
List<RegisterArg> args = mth.getArguments(false);
if (args.isEmpty() || mth.contains(AFlag.SKIP_FIRST_ARG)) {
return false;
}
RegisterArg arg = args.get(0);
if (!arg.getType().equals(fieldsCls.getClassInfo().getType())) {
return false;
}
BlockNode block = mth.getBasicBlocks().get(0);
List<InsnNode> instructions = block.getInstructions();
if (instructions.isEmpty()) {
return false;
}
InsnNode insn = instructions.get(0);
if (insn.getType() != InsnType.IPUT) {
return false;
}
IndexInsnNode putInsn = (IndexInsnNode) insn;
FieldInfo fieldInfo = (FieldInfo) putInsn.getIndex();
if (!fieldInfo.equals(field.getFieldInfo()) || !putInsn.getArg(0).equals(arg)) {
return false;
}
mth.removeFirstArgument();
InstructionRemover.remove(mth, block, insn);
// other arg usage -> wrap with IGET insn
if (arg.getSVar().getUseCount() != 0) {
InsnNode iget = new IndexInsnNode(InsnType.IGET, fieldInfo, 1);
iget.addArg(insn.getArg(1));
for (InsnArg insnArg : arg.getSVar().getUseList()) {
insnArg.wrapInstruction(iget);
}
}
return true;
}
use of jadx.core.dex.instructions.IndexInsnNode in project jadx by skylot.
the class ConstInlineVisitor method replaceConst.
private static boolean replaceConst(MethodNode mth, InsnNode constInsn, long literal) {
SSAVar sVar = constInsn.getResult().getSVar();
List<RegisterArg> use = new ArrayList<RegisterArg>(sVar.getUseList());
int replaceCount = 0;
for (RegisterArg arg : use) {
InsnNode useInsn = arg.getParentInsn();
if (useInsn == null || useInsn.getType() == InsnType.PHI || useInsn.getType() == InsnType.MERGE) {
continue;
}
LiteralArg litArg;
ArgType argType = arg.getType();
if (argType.isObject() && literal != 0) {
argType = ArgType.NARROW_NUMBERS;
}
if (use.size() == 1 || arg.isTypeImmutable()) {
// arg used only in one place
litArg = InsnArg.lit(literal, argType);
} else if (useInsn.getType() == InsnType.MOVE && !useInsn.getResult().getType().isTypeKnown()) {
// save type for 'move' instructions (hard to find type in chains of 'move')
litArg = InsnArg.lit(literal, argType);
} else {
// in most cases type not equal arg.getType()
// just set unknown type and run type fixer
litArg = InsnArg.lit(literal, ArgType.UNKNOWN);
}
if (useInsn.replaceArg(arg, litArg)) {
fixTypes(mth, useInsn, litArg);
replaceCount++;
if (useInsn.getType() == InsnType.RETURN) {
useInsn.setSourceLine(constInsn.getSourceLine());
}
FieldNode f = null;
ArgType litArgType = litArg.getType();
if (litArgType.isTypeKnown()) {
f = mth.getParentClass().getConstFieldByLiteralArg(litArg);
} else if (litArgType.contains(PrimitiveType.INT)) {
f = mth.getParentClass().getConstField((int) literal, false);
}
if (f != null) {
litArg.wrapInstruction(new IndexInsnNode(InsnType.SGET, f.getFieldInfo(), 0));
}
}
}
return replaceCount == use.size();
}
use of jadx.core.dex.instructions.IndexInsnNode in project jadx by skylot.
the class SimplifyVisitor method processCast.
private static InsnNode processCast(MethodNode mth, InsnNode insn) {
InsnArg castArg = insn.getArg(0);
ArgType argType = castArg.getType();
// Don't removes CHECK_CAST for wrapped INVOKE if invoked method returns different type
if (castArg.isInsnWrap()) {
InsnNode wrapInsn = ((InsnWrapArg) castArg).getWrapInsn();
if (wrapInsn.getType() == InsnType.INVOKE) {
argType = ((InvokeNode) wrapInsn).getCallMth().getReturnType();
}
}
ArgType castToType = (ArgType) ((IndexInsnNode) insn).getIndex();
if (ArgType.isCastNeeded(mth.dex(), argType, castToType)) {
return null;
}
InsnNode insnNode = new InsnNode(InsnType.MOVE, 1);
insnNode.setOffset(insn.getOffset());
insnNode.setResult(insn.getResult());
insnNode.addArg(castArg);
return insnNode;
}
use of jadx.core.dex.instructions.IndexInsnNode in project jadx by skylot.
the class SimplifyVisitor method convertFieldArith.
/**
* Convert field arith operation to arith instruction
* (IPUT = ARITH (IGET, lit) -> ARITH (fieldArg <op>= lit))
*/
private static InsnNode convertFieldArith(MethodNode mth, InsnNode insn) {
InsnArg arg = insn.getArg(0);
if (!arg.isInsnWrap()) {
return null;
}
InsnNode wrap = ((InsnWrapArg) arg).getWrapInsn();
InsnType wrapType = wrap.getType();
if (wrapType != InsnType.ARITH && wrapType != InsnType.STR_CONCAT || !wrap.getArg(0).isInsnWrap()) {
return null;
}
InsnNode get = ((InsnWrapArg) wrap.getArg(0)).getWrapInsn();
InsnType getType = get.getType();
if (getType != InsnType.IGET && getType != InsnType.SGET) {
return null;
}
FieldInfo field = (FieldInfo) ((IndexInsnNode) insn).getIndex();
FieldInfo innerField = (FieldInfo) ((IndexInsnNode) get).getIndex();
if (!field.equals(innerField)) {
return null;
}
try {
InsnArg reg = null;
if (getType == InsnType.IGET) {
reg = get.getArg(0);
InsnArg putReg = insn.getArg(1);
if (!reg.equals(putReg)) {
return null;
}
}
FieldArg fArg = new FieldArg(field, reg);
if (reg != null) {
fArg.setType(get.getArg(0).getType());
}
if (wrapType == InsnType.ARITH) {
ArithNode ar = (ArithNode) wrap;
return new ArithNode(ar.getOp(), fArg, ar.getArg(1));
} else {
int argsCount = wrap.getArgsCount();
InsnNode concat = new InsnNode(InsnType.STR_CONCAT, argsCount - 1);
for (int i = 1; i < argsCount; i++) {
concat.addArg(wrap.getArg(i));
}
return new ArithNode(ArithOp.ADD, fArg, InsnArg.wrapArg(concat));
}
} catch (Exception e) {
LOG.debug("Can't convert field arith insn: {}, mth: {}", insn, mth, e);
}
return null;
}
Aggregations