Package jadx.core.dex.trycatch

Source Code of jadx.core.dex.trycatch.TryCatchBlock

package jadx.core.dex.trycatch;

import jadx.core.dex.attributes.AType;
import jadx.core.dex.info.ClassInfo;
import jadx.core.dex.nodes.BlockNode;
import jadx.core.dex.nodes.IBlock;
import jadx.core.dex.nodes.IContainer;
import jadx.core.dex.nodes.InsnContainer;
import jadx.core.dex.nodes.InsnNode;
import jadx.core.dex.nodes.MethodNode;
import jadx.core.utils.InstructionRemover;
import jadx.core.utils.Utils;

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

public class TryCatchBlock {

  private final List<ExceptionHandler> handlers;
  private IContainer finalRegion;

  // references for fast remove/modify
  private final List<InsnNode> insns;
  private final CatchAttr attr;

  public TryCatchBlock() {
    handlers = new LinkedList<ExceptionHandler>();
    insns = new ArrayList<InsnNode>();
    attr = new CatchAttr(this);
  }

  public Iterable<ExceptionHandler> getHandlers() {
    return handlers;
  }

  public int getHandlersCount() {
    return handlers.size();
  }

  public boolean containsAllHandlers(TryCatchBlock tb) {
    return handlers.containsAll(tb.handlers);
  }

  public ExceptionHandler addHandler(MethodNode mth, int addr, ClassInfo type) {
    ExceptionHandler handler = new ExceptionHandler(addr, type);
    handler = mth.addExceptionHandler(handler);
    handlers.add(handler);
    handler.setTryBlock(this);
    return handler;
  }

  public void removeHandler(MethodNode mth, ExceptionHandler handler) {
    for (Iterator<ExceptionHandler> it = handlers.iterator(); it.hasNext(); ) {
      ExceptionHandler h = it.next();
      if (h == handler) {
        it.remove();
        break;
      }
    }
    if (handlers.isEmpty()) {
      removeWholeBlock(mth);
    }
  }

  private void removeWholeBlock(MethodNode mth) {
    if (finalRegion != null) {
      // search catch attr
      for (BlockNode block : mth.getBasicBlocks()) {
        CatchAttr cb = block.get(AType.CATCH_BLOCK);
        if (cb == attr) {
          for (ExceptionHandler eh : mth.getExceptionHandlers()) {
            if (eh.getBlocks().contains(block)) {
              TryCatchBlock tb = eh.getTryBlock();
              tb.setFinalRegionFromInsns(mth, ((IBlock) finalRegion).getInstructions());
            }
          }
        }
      }
    } else {
      // self destruction
      for (InsnNode insn : insns) {
        insn.removeAttr(attr);
      }
      insns.clear();
      for (BlockNode block : mth.getBasicBlocks()) {
        block.removeAttr(attr);
      }
    }
  }

  public void addInsn(InsnNode insn) {
    insns.add(insn);
    insn.addAttr(attr);
  }

  public void removeInsn(InsnNode insn) {
    insns.remove(insn);
    insn.remove(AType.CATCH_BLOCK);
  }

  public Iterable<InsnNode> getInsns() {
    return insns;
  }

  public CatchAttr getCatchAttr() {
    return attr;
  }

  public IContainer getFinalRegion() {
    return finalRegion;
  }

  public void setFinalRegion(IContainer finalRegion) {
    this.finalRegion = finalRegion;
  }

  public void setFinalRegionFromInsns(MethodNode mth, List<InsnNode> insns) {
    List<InsnNode> finalBlockInsns = new ArrayList<InsnNode>(insns);
    setFinalRegion(new InsnContainer(finalBlockInsns));

    InstructionRemover.unbindInsnList(mth, finalBlockInsns);

    // remove these instructions from other handlers
    for (ExceptionHandler h : getHandlers()) {
      for (BlockNode ehb : h.getBlocks()) {
        ehb.getInstructions().removeAll(finalBlockInsns);
      }
    }
    // remove from blocks with this catch
    for (BlockNode b : mth.getBasicBlocks()) {
      CatchAttr ca = b.get(AType.CATCH_BLOCK);
      if (attr == ca) {
        b.getInstructions().removeAll(finalBlockInsns);
      }
    }
  }

  public void merge(MethodNode mth, TryCatchBlock tryBlock) {
    for (InsnNode insn : tryBlock.getInsns()) {
      this.addInsn(insn);
    }
    this.handlers.addAll(tryBlock.handlers);
    for (ExceptionHandler eh : handlers) {
      eh.setTryBlock(this);
    }
    // clear
    tryBlock.handlers.clear();
    tryBlock.removeWholeBlock(mth);
  }

  @Override
  public int hashCode() {
    return handlers.hashCode();
  }

  @Override
  public boolean equals(Object obj) {
    if (this == obj) {
      return true;
    }
    if (obj == null || getClass() != obj.getClass()) {
      return false;
    }
    TryCatchBlock other = (TryCatchBlock) obj;
    return handlers.equals(other.handlers);
  }

  @Override
  public String toString() {
    return "Catch:{ " + Utils.listToString(handlers) + " }";
  }
}
TOP

Related Classes of jadx.core.dex.trycatch.TryCatchBlock

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.