use of jadx.core.dex.instructions.args.LiteralArg in project jadx by skylot.
the class LoopRegionVisitor method checkArrayForEach.
private static LoopType checkArrayForEach(MethodNode mth, InsnNode initInsn, InsnNode incrInsn, IfCondition condition) {
if (!(incrInsn instanceof ArithNode)) {
return null;
}
ArithNode arithNode = (ArithNode) incrInsn;
if (arithNode.getOp() != ArithOp.ADD) {
return null;
}
InsnArg lit = incrInsn.getArg(1);
if (!lit.isLiteral() || ((LiteralArg) lit).getLiteral() != 1) {
return null;
}
if (initInsn.getType() != InsnType.CONST || !initInsn.getArg(0).isLiteral() || ((LiteralArg) initInsn.getArg(0)).getLiteral() != 0) {
return null;
}
InsnArg condArg = incrInsn.getArg(0);
if (!condArg.isRegister()) {
return null;
}
SSAVar sVar = ((RegisterArg) condArg).getSVar();
List<RegisterArg> args = sVar.getUseList();
if (args.size() != 3 || args.get(2) != condArg) {
return null;
}
condArg = args.get(0);
RegisterArg arrIndex = args.get(1);
InsnNode arrGetInsn = arrIndex.getParentInsn();
if (arrGetInsn == null || arrGetInsn.getType() != InsnType.AGET) {
return null;
}
if (!condition.isCompare()) {
return null;
}
Compare compare = condition.getCompare();
if (compare.getOp() != IfOp.LT || compare.getA() != condArg) {
return null;
}
InsnNode len;
InsnArg bCondArg = compare.getB();
if (bCondArg.isInsnWrap()) {
len = ((InsnWrapArg) bCondArg).getWrapInsn();
} else if (bCondArg.isRegister()) {
len = ((RegisterArg) bCondArg).getAssignInsn();
} else {
return null;
}
if (len == null || len.getType() != InsnType.ARRAY_LENGTH) {
return null;
}
InsnArg arrayArg = len.getArg(0);
if (!arrayArg.equals(arrGetInsn.getArg(0))) {
return null;
}
RegisterArg iterVar = arrGetInsn.getResult();
if (iterVar == null) {
return null;
}
// array for each loop confirmed
len.add(AFlag.SKIP);
arrGetInsn.add(AFlag.SKIP);
InstructionRemover.unbindInsn(mth, len);
// inline array variable
CodeShrinker.shrinkMethod(mth);
if (arrGetInsn.contains(AFlag.WRAPPED)) {
InsnArg wrapArg = BlockUtils.searchWrappedInsnParent(mth, arrGetInsn);
if (wrapArg != null && wrapArg.getParentInsn() != null) {
wrapArg.getParentInsn().replaceArg(wrapArg, iterVar);
} else {
LOG.debug(" checkArrayForEach: Wrapped insn not found: {}, mth: {}", arrGetInsn, mth);
}
}
return new ForEachLoop(iterVar, len.getArg(0));
}
use of jadx.core.dex.instructions.args.LiteralArg in project jadx by skylot.
the class SimplifyVisitor method simplifyArith.
private static InsnNode simplifyArith(InsnNode insn) {
ArithNode arith = (ArithNode) insn;
if (arith.getArgsCount() != 2) {
return null;
}
InsnArg litArg = null;
InsnArg secondArg = arith.getArg(1);
if (secondArg.isInsnWrap()) {
InsnNode wr = ((InsnWrapArg) secondArg).getWrapInsn();
if (wr.getType() == InsnType.CONST) {
litArg = wr.getArg(0);
}
} else if (secondArg.isLiteral()) {
litArg = secondArg;
}
if (litArg != null) {
long lit = ((LiteralArg) litArg).getLiteral();
// fix 'c + (-1)' => 'c - (1)'
if (arith.getOp() == ArithOp.ADD && lit < 0) {
return new ArithNode(ArithOp.SUB, arith.getResult(), insn.getArg(0), InsnArg.lit(-lit, litArg.getType()));
}
}
return null;
}
use of jadx.core.dex.instructions.args.LiteralArg in project jadx by skylot.
the class ModVisitor method replaceStep.
private static void replaceStep(MethodNode mth, InstructionRemover remover) {
ClassNode parentClass = mth.getParentClass();
for (BlockNode block : mth.getBasicBlocks()) {
remover.setBlock(block);
int size = block.getInstructions().size();
for (int i = 0; i < size; i++) {
InsnNode insn = block.getInstructions().get(i);
switch(insn.getType()) {
case INVOKE:
processInvoke(mth, block, i, remover);
break;
case CONST:
case CONST_STR:
case CONST_CLASS:
{
FieldNode f;
if (insn.getType() == InsnType.CONST_STR) {
String s = ((ConstStringNode) insn).getString();
f = parentClass.getConstField(s);
} else if (insn.getType() == InsnType.CONST_CLASS) {
ArgType t = ((ConstClassNode) insn).getClsType();
f = parentClass.getConstField(t);
} else {
f = parentClass.getConstFieldByLiteralArg((LiteralArg) insn.getArg(0));
}
if (f != null) {
InsnNode inode = new IndexInsnNode(InsnType.SGET, f.getFieldInfo(), 0);
inode.setResult(insn.getResult());
replaceInsn(block, i, inode);
}
break;
}
case SWITCH:
SwitchNode sn = (SwitchNode) insn;
for (int k = 0; k < sn.getCasesCount(); k++) {
FieldNode f = parentClass.getConstField(sn.getKeys()[k]);
if (f != null) {
sn.getKeys()[k] = f;
}
}
break;
case NEW_ARRAY:
// create array in 'fill-array' instruction
int next = i + 1;
if (next < size) {
InsnNode ni = block.getInstructions().get(next);
if (ni.getType() == InsnType.FILL_ARRAY) {
ni.getResult().merge(mth.dex(), insn.getResult());
ArgType arrType = ((NewArrayNode) insn).getArrayType();
((FillArrayNode) ni).mergeElementType(mth.dex(), arrType.getArrayElement());
remover.add(insn);
}
}
break;
case FILL_ARRAY:
InsnNode filledArr = makeFilledArrayInsn(mth, (FillArrayNode) insn);
replaceInsn(block, i, filledArr);
break;
case MOVE_EXCEPTION:
processMoveException(mth, block, insn, remover);
break;
case ARITH:
ArithNode arithNode = (ArithNode) insn;
if (arithNode.getArgsCount() == 2) {
InsnArg litArg = arithNode.getArg(1);
if (litArg.isLiteral()) {
FieldNode f = parentClass.getConstFieldByLiteralArg((LiteralArg) litArg);
if (f != null) {
InsnNode fGet = new IndexInsnNode(InsnType.SGET, f.getFieldInfo(), 0);
insn.replaceArg(litArg, InsnArg.wrapArg(fGet));
}
}
}
break;
default:
break;
}
}
remover.perform();
}
}
use of jadx.core.dex.instructions.args.LiteralArg in project jadx by skylot.
the class ConstInlineVisitor method checkInsn.
private static boolean checkInsn(MethodNode mth, InsnNode insn) {
if (insn.getType() != InsnType.CONST || insn.contains(AFlag.DONT_INLINE)) {
return false;
}
InsnArg arg = insn.getArg(0);
if (!arg.isLiteral()) {
return false;
}
long lit = ((LiteralArg) arg).getLiteral();
SSAVar sVar = insn.getResult().getSVar();
if (lit == 0 && checkObjectInline(sVar)) {
if (sVar.getUseCount() == 1) {
InsnNode assignInsn = insn.getResult().getAssignInsn();
if (assignInsn != null) {
assignInsn.add(AFlag.DONT_INLINE);
}
}
return false;
}
ArgType resType = insn.getResult().getType();
// make sure arg has correct type
if (!arg.getType().isTypeKnown()) {
arg.merge(mth.dex(), resType);
}
return replaceConst(mth, insn, lit);
}
use of jadx.core.dex.instructions.args.LiteralArg in project jadx by skylot.
the class PostTypeInference method process.
public static boolean process(MethodNode mth, InsnNode insn) {
DexNode dex = mth.dex();
switch(insn.getType()) {
case CONST:
RegisterArg res = insn.getResult();
LiteralArg litArg = (LiteralArg) insn.getArg(0);
if (res.getType().isObject()) {
long lit = litArg.getLiteral();
if (lit != 0) {
// incorrect literal value for object
ArgType type = lit == 1 ? ArgType.BOOLEAN : ArgType.INT;
// can't merge with object -> force it
litArg.setType(type);
res.getSVar().setType(type);
return true;
}
}
return litArg.merge(dex, res);
case MOVE:
{
boolean change = false;
if (insn.getResult().merge(dex, insn.getArg(0))) {
change = true;
}
if (insn.getArg(0).merge(dex, insn.getResult())) {
change = true;
}
return change;
}
case AGET:
return fixArrayTypes(dex, insn.getArg(0), insn.getResult());
case APUT:
return fixArrayTypes(dex, insn.getArg(0), insn.getArg(2));
case IF:
{
boolean change = false;
if (insn.getArg(1).merge(dex, insn.getArg(0))) {
change = true;
}
if (insn.getArg(0).merge(dex, insn.getArg(1))) {
change = true;
}
return change;
}
// check argument types for overloaded methods
case INVOKE:
{
boolean change = false;
InvokeNode inv = (InvokeNode) insn;
MethodInfo callMth = inv.getCallMth();
MethodNode node = mth.dex().resolveMethod(callMth);
if (node != null && node.isArgsOverload()) {
List<ArgType> args = callMth.getArgumentsTypes();
int j = inv.getArgsCount() - 1;
for (int i = args.size() - 1; i >= 0; i--) {
ArgType argType = args.get(i);
InsnArg insnArg = inv.getArg(j--);
if (insnArg.isRegister() && !argType.equals(insnArg.getType())) {
insnArg.setType(argType);
change = true;
}
}
}
return change;
}
case CHECK_CAST:
{
ArgType castType = (ArgType) ((IndexInsnNode) insn).getIndex();
RegisterArg result = insn.getResult();
ArgType resultType = result.getType();
// don't override generic types of same base class
boolean skip = castType.isObject() && resultType.isObject() && castType.getObject().equals(resultType.getObject());
if (!skip) {
// workaround for compiler bug (see TestDuplicateCast)
result.getSVar().setType(castType);
}
return true;
}
case PHI:
case MERGE:
{
ArgType type = insn.getResult().getType();
if (!type.isTypeKnown()) {
for (InsnArg arg : insn.getArguments()) {
if (arg.getType().isTypeKnown()) {
type = arg.getType();
break;
}
}
}
boolean changed = false;
if (updateType(insn.getResult(), type)) {
changed = true;
}
for (int i = 0; i < insn.getArgsCount(); i++) {
RegisterArg arg = (RegisterArg) insn.getArg(i);
if (updateType(arg, type)) {
changed = true;
}
}
return changed;
}
default:
break;
}
return false;
}
Aggregations