use of jadx.core.dex.trycatch.TryCatchBlock in project jadx by skylot.
the class ProcessTryCatchRegions method checkAndWrap.
private static boolean checkAndWrap(MethodNode mth, Map<BlockNode, TryCatchBlock> tryBlocksMap, IRegion region) {
// search dominator blocks in this region (don't need to go deeper)
for (Map.Entry<BlockNode, TryCatchBlock> entry : tryBlocksMap.entrySet()) {
BlockNode dominator = entry.getKey();
if (region.getSubBlocks().contains(dominator)) {
TryCatchBlock tb = tryBlocksMap.get(dominator);
if (!wrapBlocks(region, tb, dominator)) {
ErrorsCounter.methodError(mth, "Can't wrap try/catch for " + region);
}
tryBlocksMap.remove(dominator);
return true;
}
}
return false;
}
use of jadx.core.dex.trycatch.TryCatchBlock in project jadx by skylot.
the class ProcessTryCatchRegions method searchTryCatchDominators.
private static void searchTryCatchDominators(MethodNode mth, Map<BlockNode, TryCatchBlock> tryBlocksMap) {
Set<TryCatchBlock> tryBlocks = new HashSet<TryCatchBlock>();
// collect all try/catch blocks
for (BlockNode block : mth.getBasicBlocks()) {
CatchAttr c = block.get(AType.CATCH_BLOCK);
if (c != null) {
tryBlocks.add(c.getTryBlock());
}
}
// for each try block search nearest dominator block
for (TryCatchBlock tb : tryBlocks) {
if (tb.getHandlersCount() == 0) {
LOG.warn("No exception handlers in catch block, method: {}", mth);
continue;
}
BitSet bs = new BitSet(mth.getBasicBlocks().size());
for (ExceptionHandler excHandler : tb.getHandlers()) {
SplitterBlockAttr splitter = excHandler.getHandlerBlock().get(AType.SPLITTER_BLOCK);
if (splitter != null) {
BlockNode block = splitter.getBlock();
bs.set(block.getId());
}
}
List<BlockNode> domBlocks = BlockUtils.bitSetToBlocks(mth, bs);
BlockNode domBlock;
if (domBlocks.size() != 1) {
domBlock = BlockUtils.getTopBlock(domBlocks);
if (domBlock == null) {
throw new JadxRuntimeException("Exception block dominator not found, method:" + mth + ". bs: " + domBlocks);
}
} else {
domBlock = domBlocks.get(0);
}
TryCatchBlock prevTB = tryBlocksMap.put(domBlock, tb);
if (prevTB != null) {
ErrorsCounter.methodError(mth, "Failed to process nested try/catch");
}
}
}
use of jadx.core.dex.trycatch.TryCatchBlock in project jadx by skylot.
the class BlockFinallyExtract method extractFinally.
/**
* Search and remove common code from 'catch' and 'handlers'.
*/
private static boolean extractFinally(MethodNode mth, ExceptionHandler handler) {
int count = handler.getBlocks().size();
BitSet bs = new BitSet(count);
List<BlockNode> blocks = new ArrayList<BlockNode>(count);
for (BlockNode block : handler.getBlocks()) {
List<InsnNode> insns = block.getInstructions();
if (!insns.isEmpty()) {
if (insns.get(0).getType() != InsnType.MOVE_EXCEPTION) {
blocks.add(block);
}
bs.set(block.getId());
}
}
if (blocks.isEmpty()) {
// nothing to do
return false;
}
List<BlocksRemoveInfo> removes = new LinkedList<BlocksRemoveInfo>();
Set<BlockNode> splitters = new HashSet<BlockNode>();
// remove 'finally' from handlers
TryCatchBlock tryBlock = handler.getTryBlock();
if (tryBlock.getHandlersCount() > 1) {
for (ExceptionHandler otherHandler : tryBlock.getHandlers()) {
if (otherHandler == handler) {
continue;
}
for (BlockNode hb : otherHandler.getBlocks()) {
BlocksRemoveInfo removeInfo = removeInsns(mth, hb, blocks, bs);
if (removeInfo != null) {
removes.add(removeInfo);
break;
}
}
}
if (removes.size() != tryBlock.getHandlersCount() - 1) {
return false;
}
}
for (ExceptionHandler otherHandler : tryBlock.getHandlers()) {
SplitterBlockAttr splitterAttr = otherHandler.getHandlerBlock().get(AType.SPLITTER_BLOCK);
if (splitterAttr != null) {
BlockNode splBlock = splitterAttr.getBlock();
if (!splBlock.getCleanSuccessors().isEmpty()) {
splitters.add(splBlock);
}
}
}
// remove 'finally' from 'try' blocks (dominated by splitter block)
boolean removed = false;
for (BlockNode splitter : splitters) {
BlockNode start = splitter.getCleanSuccessors().get(0);
List<BlockNode> list = BlockUtils.collectBlocksDominatedBy(splitter, start);
for (BlockNode block : list) {
if (bs.get(block.getId())) {
continue;
}
BlocksRemoveInfo removeInfo = removeInsns(mth, block, blocks, bs);
if (removeInfo != null) {
removes.add(removeInfo);
removed = true;
break;
}
}
}
if (!removed) {
return false;
}
// 'finally' extract confirmed, run remove steps
LiveVarAnalysis laBefore = null;
boolean runReMap = isReMapNeeded(removes);
if (runReMap) {
laBefore = new LiveVarAnalysis(mth);
laBefore.runAnalysis();
}
for (BlocksRemoveInfo removeInfo : removes) {
if (!applyRemove(mth, removeInfo)) {
return false;
}
}
LiveVarAnalysis laAfter = null;
// remove 'move-exception' instruction
BlockNode handlerBlock = handler.getHandlerBlock();
InsnNode me = BlockUtils.getLastInsn(handlerBlock);
if (me != null && me.getType() == InsnType.MOVE_EXCEPTION) {
boolean replaced = false;
List<InsnNode> insnsList = handlerBlock.getInstructions();
if (!handlerBlock.getCleanSuccessors().isEmpty()) {
laAfter = new LiveVarAnalysis(mth);
laAfter.runAnalysis();
RegisterArg resArg = me.getResult();
BlockNode succ = handlerBlock.getCleanSuccessors().get(0);
if (laAfter.isLive(succ, resArg.getRegNum())) {
// kill variable
InsnNode kill = new InsnNode(InsnType.NOP, 0);
kill.setResult(resArg);
kill.add(AFlag.REMOVE);
insnsList.set(insnsList.size() - 1, kill);
replaced = true;
}
}
if (!replaced) {
insnsList.remove(insnsList.size() - 1);
handlerBlock.add(AFlag.SKIP);
}
}
// generate 'move' instruction for mapped register pairs
if (runReMap) {
if (laAfter == null) {
laAfter = new LiveVarAnalysis(mth);
laAfter.runAnalysis();
}
performVariablesReMap(mth, removes, laBefore, laAfter);
}
handler.setFinally(true);
return true;
}
use of jadx.core.dex.trycatch.TryCatchBlock in project jadx by skylot.
the class RegionMaker method processHandlersOutBlocks.
/**
* Search handlers successor blocks not included in any region.
*/
protected IRegion processHandlersOutBlocks(MethodNode mth, Set<TryCatchBlock> tcs) {
Set<IBlock> allRegionBlocks = new HashSet<IBlock>();
RegionUtils.getAllRegionBlocks(mth.getRegion(), allRegionBlocks);
Set<IBlock> succBlocks = new HashSet<IBlock>();
for (TryCatchBlock tc : tcs) {
for (ExceptionHandler handler : tc.getHandlers()) {
IContainer region = handler.getHandlerRegion();
if (region != null) {
IBlock lastBlock = RegionUtils.getLastBlock(region);
if (lastBlock instanceof BlockNode) {
succBlocks.addAll(((BlockNode) lastBlock).getSuccessors());
}
RegionUtils.getAllRegionBlocks(region, allRegionBlocks);
}
}
}
succBlocks.removeAll(allRegionBlocks);
if (succBlocks.isEmpty()) {
return null;
}
Region excOutRegion = new Region(mth.getRegion());
for (IBlock block : succBlocks) {
if (block instanceof BlockNode) {
excOutRegion.add(makeRegion((BlockNode) block, new RegionStack(mth)));
}
}
return excOutRegion;
}
use of jadx.core.dex.trycatch.TryCatchBlock in project jadx by skylot.
the class MethodNode method initTryCatches.
private void initTryCatches(Code mthCode) {
InsnNode[] insnByOffset = instructions;
CatchHandler[] catchBlocks = mthCode.getCatchHandlers();
Try[] tries = mthCode.getTries();
if (catchBlocks.length == 0 && tries.length == 0) {
return;
}
int hc = 0;
Set<Integer> addrs = new HashSet<Integer>();
List<TryCatchBlock> catches = new ArrayList<TryCatchBlock>(catchBlocks.length);
for (CatchHandler handler : catchBlocks) {
TryCatchBlock tcBlock = new TryCatchBlock();
catches.add(tcBlock);
for (int i = 0; i < handler.getAddresses().length; i++) {
int addr = handler.getAddresses()[i];
ClassInfo type = ClassInfo.fromDex(parentClass.dex(), handler.getTypeIndexes()[i]);
tcBlock.addHandler(this, addr, type);
addrs.add(addr);
hc++;
}
int addr = handler.getCatchAllAddress();
if (addr >= 0) {
tcBlock.addHandler(this, addr, null);
addrs.add(addr);
hc++;
}
}
if (hc > 0 && hc != addrs.size()) {
// each handler must be only in one try/catch block
for (TryCatchBlock ct1 : catches) {
for (TryCatchBlock ct2 : catches) {
if (ct1 != ct2 && ct2.containsAllHandlers(ct1)) {
for (ExceptionHandler h : ct1.getHandlers()) {
ct2.removeHandler(this, h);
h.setTryBlock(ct1);
}
}
}
}
}
// attach EXC_HANDLER attributes to instructions
addrs.clear();
for (TryCatchBlock ct : catches) {
for (ExceptionHandler eh : ct.getHandlers()) {
int addr = eh.getHandleOffset();
ExcHandlerAttr ehAttr = new ExcHandlerAttr(ct, eh);
insnByOffset[addr].addAttr(ehAttr);
}
}
// attach TRY_ENTER, TRY_LEAVE attributes to instructions
for (Try aTry : tries) {
int catchNum = aTry.getCatchHandlerIndex();
TryCatchBlock catchBlock = catches.get(catchNum);
int offset = aTry.getStartAddress();
int end = offset + aTry.getInstructionCount() - 1;
InsnNode insn = insnByOffset[offset];
insn.add(AFlag.TRY_ENTER);
while (offset <= end && offset >= 0) {
insn = insnByOffset[offset];
catchBlock.addInsn(insn);
offset = InsnDecoder.getNextInsnOffset(insnByOffset, offset);
}
if (insnByOffset[end] != null) {
insnByOffset[end].add(AFlag.TRY_LEAVE);
} else {
insn.add(AFlag.TRY_LEAVE);
}
}
}
Aggregations