Package jadx.core.utils

Source Code of jadx.core.utils.InstructionRemover

package jadx.core.utils;

import jadx.core.dex.attributes.AFlag;
import jadx.core.dex.instructions.args.InsnArg;
import jadx.core.dex.instructions.args.InsnWrapArg;
import jadx.core.dex.instructions.args.RegisterArg;
import jadx.core.dex.instructions.args.SSAVar;
import jadx.core.dex.nodes.BlockNode;
import jadx.core.dex.nodes.InsnNode;
import jadx.core.dex.nodes.MethodNode;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* Helper class for correct instructions removing,
* can be used while iterating over instructions list
*/
public class InstructionRemover {

  private static final Logger LOG = LoggerFactory.getLogger(InstructionRemover.class);

  private final MethodNode mth;
  private final List<InsnNode> toRemove;
  private List<InsnNode> instrList;

  public InstructionRemover(MethodNode mth) {
    this(mth, null);
  }

  public InstructionRemover(MethodNode mth, BlockNode block) {
    this.mth = mth;
    this.toRemove = new ArrayList<InsnNode>();
    if (block != null) {
      this.instrList = block.getInstructions();
    }
  }

  public void setBlock(BlockNode block) {
    this.instrList = block.getInstructions();
  }

  public void add(InsnNode insn) {
    toRemove.add(insn);
  }

  public void perform() {
    if (toRemove.isEmpty()) {
      return;
    }
    removeAll(mth, instrList, toRemove);
    toRemove.clear();
  }

  public static void unbindInsnList(MethodNode mth, List<InsnNode> unbind) {
    for (InsnNode rem : unbind) {
      unbindInsn(mth, rem);
    }
  }

  public static void unbindInsn(MethodNode mth, InsnNode insn) {
    RegisterArg r = insn.getResult();
    if (r != null && r.getSVar() != null) {
      mth.removeSVar(r.getSVar());
    }
    for (InsnArg arg : insn.getArguments()) {
      unbindArgUsage(mth, arg);
    }
    insn.add(AFlag.INCONSISTENT_CODE);
  }

  public static void unbindArgUsage(MethodNode mth, InsnArg arg) {
    if (arg instanceof RegisterArg) {
      RegisterArg reg = (RegisterArg) arg;
      SSAVar sVar = reg.getSVar();
      if (sVar != null) {
        sVar.removeUse(reg);
      }
    } else if (arg instanceof InsnWrapArg) {
      InsnWrapArg wrap = (InsnWrapArg) arg;
      unbindInsn(mth, wrap.getWrapInsn());
    }
  }

  // Don't use 'instrList.removeAll(toRemove)' because it will remove instructions by content
  // and here can be several instructions with same content
  private static void removeAll(MethodNode mth, List<InsnNode> insns, List<InsnNode> toRemove) {
    for (InsnNode rem : toRemove) {
      unbindInsn(mth, rem);
      int insnsCount = insns.size();
      for (int i = 0; i < insnsCount; i++) {
        if (insns.get(i) == rem) {
          insns.remove(i);
          break;
        }
      }
    }
  }

  public static void remove(MethodNode mth, InsnNode insn) {
    BlockNode block = BlockUtils.getBlockByInsn(mth, insn);
    if (block != null) {
      remove(mth, block, insn);
    }
  }

  public static void remove(MethodNode mth, BlockNode block, InsnNode insn) {
    unbindInsn(mth, insn);
    // remove by pointer (don't use equals)
    Iterator<InsnNode> it = block.getInstructions().iterator();
    while (it.hasNext()) {
      InsnNode ir = it.next();
      if (ir == insn) {
        it.remove();
        return;
      }
    }
  }

  public static void removeAll(MethodNode mth, BlockNode block, List<InsnNode> insns) {
    removeAll(mth, block.getInstructions(), insns);
  }

  public static void remove(MethodNode mth, BlockNode block, int index) {
    List<InsnNode> instructions = block.getInstructions();
    unbindInsn(mth, instructions.get(index));
    instructions.remove(index);
  }

}
TOP

Related Classes of jadx.core.utils.InstructionRemover

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.