use of jadx.core.dex.instructions.args.RegisterArg 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.RegisterArg in project jadx by skylot.
the class LoopRegionVisitor method checkForIndexedLoop.
/**
* Check for indexed loop.
*/
private static boolean checkForIndexedLoop(MethodNode mth, LoopRegion loopRegion, IfCondition condition) {
InsnNode incrInsn = RegionUtils.getLastInsn(loopRegion);
if (incrInsn == null) {
return false;
}
RegisterArg incrArg = incrInsn.getResult();
if (incrArg == null || incrArg.getSVar() == null || !incrArg.getSVar().isUsedInPhi()) {
return false;
}
PhiInsn phiInsn = incrArg.getSVar().getUsedInPhi();
if (phiInsn == null || phiInsn.getArgsCount() != 2 || !phiInsn.getArg(1).equals(incrArg) || incrArg.getSVar().getUseCount() != 1) {
return false;
}
RegisterArg arg = phiInsn.getResult();
List<RegisterArg> condArgs = condition.getRegisterArgs();
if (!condArgs.contains(arg) || arg.getSVar().isUsedInPhi()) {
return false;
}
RegisterArg initArg = phiInsn.getArg(0);
InsnNode initInsn = initArg.getAssignInsn();
if (initInsn == null || initArg.getSVar().getUseCount() != 1) {
return false;
}
if (!usedOnlyInLoop(mth, loopRegion, arg)) {
return false;
}
// can't make loop if argument from increment instruction is assign in loop
List<RegisterArg> args = new LinkedList<RegisterArg>();
incrInsn.getRegisterArgs(args);
for (RegisterArg iArg : args) {
if (assignOnlyInLoop(mth, loopRegion, iArg)) {
return false;
}
}
// all checks passed
initInsn.add(AFlag.SKIP);
incrInsn.add(AFlag.SKIP);
LoopType arrForEach = checkArrayForEach(mth, initInsn, incrInsn, condition);
if (arrForEach != null) {
loopRegion.setType(arrForEach);
return true;
}
loopRegion.setType(new ForLoop(initInsn, incrInsn));
return true;
}
use of jadx.core.dex.instructions.args.RegisterArg in project jadx by skylot.
the class LoopRegionVisitor method checkIterableForEach.
private static boolean checkIterableForEach(MethodNode mth, LoopRegion loopRegion, IfCondition condition) {
List<RegisterArg> condArgs = condition.getRegisterArgs();
if (condArgs.size() != 1) {
return false;
}
RegisterArg iteratorArg = condArgs.get(0);
SSAVar sVar = iteratorArg.getSVar();
if (sVar == null || sVar.isUsedInPhi()) {
return false;
}
List<RegisterArg> useList = sVar.getUseList();
InsnNode assignInsn = iteratorArg.getAssignInsn();
if (useList.size() != 2 || assignInsn == null || !checkInvoke(assignInsn, null, "iterator()Ljava/util/Iterator;", 0)) {
return false;
}
InsnArg iterableArg = assignInsn.getArg(0);
InsnNode hasNextCall = useList.get(0).getParentInsn();
InsnNode nextCall = useList.get(1).getParentInsn();
if (hasNextCall == null || nextCall == null || !checkInvoke(hasNextCall, "java.util.Iterator", "hasNext()Z", 0) || !checkInvoke(nextCall, "java.util.Iterator", "next()Ljava/lang/Object;", 0)) {
return false;
}
List<InsnNode> toSkip = new LinkedList<InsnNode>();
RegisterArg iterVar = nextCall.getResult();
if (iterVar == null) {
return false;
}
if (nextCall.contains(AFlag.WRAPPED)) {
InsnArg wrapArg = BlockUtils.searchWrappedInsnParent(mth, nextCall);
if (wrapArg != null && wrapArg.getParentInsn() != null) {
InsnNode parentInsn = wrapArg.getParentInsn();
if (parentInsn.getType() != InsnType.CHECK_CAST) {
if (!fixIterableType(mth, iterableArg, iterVar)) {
return false;
}
parentInsn.replaceArg(wrapArg, iterVar);
} else {
iterVar = parentInsn.getResult();
if (iterVar == null || !fixIterableType(mth, iterableArg, iterVar)) {
return false;
}
InsnArg castArg = BlockUtils.searchWrappedInsnParent(mth, parentInsn);
if (castArg != null && castArg.getParentInsn() != null) {
castArg.getParentInsn().replaceArg(castArg, iterVar);
} else {
// cast not inlined
toSkip.add(parentInsn);
}
}
} else {
LOG.warn(" checkIterableForEach: Wrapped insn not found: {}, mth: {}", nextCall, mth);
return false;
}
} else {
toSkip.add(nextCall);
}
assignInsn.add(AFlag.SKIP);
for (InsnNode insnNode : toSkip) {
insnNode.add(AFlag.SKIP);
}
loopRegion.setType(new ForEachLoop(iterVar, iterableArg));
return true;
}
use of jadx.core.dex.instructions.args.RegisterArg in project jadx by skylot.
the class ProcessVariables method visit.
@Override
public void visit(MethodNode mth) throws JadxException {
if (mth.isNoCode()) {
return;
}
final Map<Variable, Usage> usageMap = new LinkedHashMap<Variable, Usage>();
for (RegisterArg arg : mth.getArguments(true)) {
addToUsageMap(arg, usageMap);
}
// collect all variables usage
IRegionVisitor collect = new CollectUsageRegionVisitor(usageMap);
DepthRegionTraversal.traverse(mth, collect);
// reduce assigns map
List<RegisterArg> mthArgs = mth.getArguments(true);
for (RegisterArg arg : mthArgs) {
usageMap.remove(new Variable(arg));
}
Iterator<Entry<Variable, Usage>> umIt = usageMap.entrySet().iterator();
while (umIt.hasNext()) {
Entry<Variable, Usage> entry = umIt.next();
Usage u = entry.getValue();
// if no assigns => remove
if (u.getAssigns().isEmpty()) {
umIt.remove();
continue;
}
// variable declared at 'catch' clause
InsnNode parentInsn = u.getArg().getParentInsn();
if (parentInsn == null || parentInsn.getType() == InsnType.MOVE_EXCEPTION) {
umIt.remove();
}
}
if (usageMap.isEmpty()) {
return;
}
Map<IContainer, Integer> regionsOrder = new HashMap<IContainer, Integer>();
calculateOrder(mth.getRegion(), regionsOrder, 0, true);
for (Iterator<Entry<Variable, Usage>> it = usageMap.entrySet().iterator(); it.hasNext(); ) {
Entry<Variable, Usage> entry = it.next();
Usage u = entry.getValue();
// check if variable can be declared at current assigns
for (IRegion assignRegion : u.getAssigns()) {
if (u.getArgRegion() == assignRegion && canDeclareInRegion(u, assignRegion, regionsOrder)) {
if (declareAtAssign(u)) {
it.remove();
break;
}
}
}
}
if (usageMap.isEmpty()) {
return;
}
// apply
for (Entry<Variable, Usage> entry : usageMap.entrySet()) {
Usage u = entry.getValue();
// find region which contain all usage regions
Set<IRegion> set = u.getUseRegions();
for (Iterator<IRegion> it = set.iterator(); it.hasNext(); ) {
IRegion r = it.next();
IRegion parent = r.getParent();
if (parent != null && set.contains(parent)) {
it.remove();
}
}
IRegion region = null;
if (!set.isEmpty()) {
region = set.iterator().next();
} else if (!u.getAssigns().isEmpty()) {
region = u.getAssigns().iterator().next();
}
if (region == null) {
continue;
}
IRegion parent = region;
boolean declared = false;
while (parent != null) {
if (canDeclareInRegion(u, region, regionsOrder)) {
declareVar(region, u.getArg());
declared = true;
break;
}
region = parent;
parent = region.getParent();
}
if (!declared) {
declareVar(mth.getRegion(), u.getArg());
}
}
}
use of jadx.core.dex.instructions.args.RegisterArg in project jadx by skylot.
the class ProcessVariables method declareAtAssign.
private static boolean declareAtAssign(Usage u) {
RegisterArg arg = u.getArg();
InsnNode parentInsn = arg.getParentInsn();
if (!arg.equals(parentInsn.getResult())) {
return false;
}
parentInsn.add(AFlag.DECLARE_VAR);
return true;
}
Aggregations