diff --git a/jadx-core/src/main/java/jadx/core/dex/trycatch/SplitterBlockAttr.java b/jadx-core/src/main/java/jadx/core/dex/trycatch/SplitterBlockAttr.java index f7b952e04..561091c64 100644 --- a/jadx-core/src/main/java/jadx/core/dex/trycatch/SplitterBlockAttr.java +++ b/jadx-core/src/main/java/jadx/core/dex/trycatch/SplitterBlockAttr.java @@ -23,6 +23,6 @@ public class SplitterBlockAttr implements IAttribute { @Override public String toString() { - return "Splitter: " + block; + return "Splitter:" + block; } } diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/blocksmaker/BlockFinish.java b/jadx-core/src/main/java/jadx/core/dex/visitors/blocksmaker/BlockFinish.java index 96db02e95..dd7d47bf6 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/blocksmaker/BlockFinish.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/blocksmaker/BlockFinish.java @@ -26,7 +26,7 @@ public class BlockFinish extends AbstractVisitor { for (BlockNode block : mth.getBasicBlocks()) { block.updateCleanSuccessors(); - fixSplitterBlock(block); + fixSplitterBlock(mth, block); } mth.finishBasicBlocks(); @@ -36,7 +36,7 @@ public class BlockFinish extends AbstractVisitor { * For evey exception handler must be only one splitter block, * select correct one and remove others if necessary. */ - private static void fixSplitterBlock(BlockNode block) { + private static void fixSplitterBlock(MethodNode mth, BlockNode block) { ExcHandlerAttr excHandlerAttr = block.get(AType.EXC_HANDLER); if (excHandlerAttr == null) { return; @@ -58,7 +58,7 @@ public class BlockFinish extends AbstractVisitor { } BlockNode topSplitter = BlockUtils.getTopBlock(splitters.keySet()); if (topSplitter == null) { - LOG.warn("Unknown top splitter block from list: {}", splitters); + mth.addWarn("Unknown top exception splitter block from list: " + splitters); return; } for (Map.Entry entry : splitters.entrySet()) { diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/regions/CheckRegions.java b/jadx-core/src/main/java/jadx/core/dex/visitors/regions/CheckRegions.java index 106eeee7a..49389ea7b 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/regions/CheckRegions.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/regions/CheckRegions.java @@ -60,7 +60,7 @@ public class CheckRegions extends AbstractVisitor { && !block.getInstructions().isEmpty() && !block.contains(AFlag.SKIP)) { String blockCode = getBlockInsnStr(mth, block); - mth.addWarn("Missing block: " + block + ", code:" + CodeWriter.NL + blockCode); + mth.addWarn("Missing block: " + block + ", code skipped:" + CodeWriter.NL + blockCode); } } } diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/regions/ProcessTryCatchRegions.java b/jadx-core/src/main/java/jadx/core/dex/visitors/regions/ProcessTryCatchRegions.java index 33d544cc3..bb2d543e8 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/regions/ProcessTryCatchRegions.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/regions/ProcessTryCatchRegions.java @@ -27,7 +27,6 @@ import jadx.core.dex.trycatch.TryCatchBlock; import jadx.core.utils.BlockUtils; import jadx.core.utils.ErrorsCounter; import jadx.core.utils.RegionUtils; -import jadx.core.utils.exceptions.JadxRuntimeException; /** * Extract blocks to separate try/catch region @@ -67,34 +66,39 @@ public class ProcessTryCatchRegions extends AbstractRegionVisitor { // 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); + mth.addWarn("No exception handlers in catch block: " + tb); continue; } - BitSet bs = new BitSet(mth.getBasicBlocks().size()); - for (ExceptionHandler excHandler : tb.getHandlers()) { - BlockNode handlerBlock = excHandler.getHandlerBlock(); - if (handlerBlock != null) { - SplitterBlockAttr splitter = handlerBlock.get(AType.SPLITTER_BLOCK); - if (splitter != null) { - BlockNode block = splitter.getBlock(); - bs.set(block.getId()); - } + processTryCatchBlock(mth, tb, tryBlocksMap); + } + } + + private static void processTryCatchBlock(MethodNode mth, TryCatchBlock tb, Map tryBlocksMap) { + BitSet bs = new BitSet(mth.getBasicBlocks().size()); + for (ExceptionHandler excHandler : tb.getHandlers()) { + BlockNode handlerBlock = excHandler.getHandlerBlock(); + if (handlerBlock != null) { + SplitterBlockAttr splitter = handlerBlock.get(AType.SPLITTER_BLOCK); + if (splitter != null) { + BlockNode block = splitter.getBlock(); + bs.set(block.getId()); } } - List 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 + ", dom blocks: " + domBlocks); - } - } else { - domBlock = domBlocks.get(0); - } - TryCatchBlock prevTB = tryBlocksMap.put(domBlock, tb); - if (prevTB != null) { - ErrorsCounter.methodWarn(mth, "Failed to process nested try/catch"); + } + List domBlocks = BlockUtils.bitSetToBlocks(mth, bs); + BlockNode domBlock; + if (domBlocks.size() != 1) { + domBlock = BlockUtils.getTopBlock(domBlocks); + if (domBlock == null) { + mth.addWarn("Exception block dominator not found, dom blocks: " + domBlocks); + return; } + } else { + domBlock = domBlocks.get(0); + } + TryCatchBlock prevTB = tryBlocksMap.put(domBlock, tb); + if (prevTB != null) { + mth.addWarn("Failed to process nested try/catch"); } } @@ -105,7 +109,7 @@ public class ProcessTryCatchRegions extends AbstractRegionVisitor { if (region.getSubBlocks().contains(dominator)) { TryCatchBlock tb = tryBlocksMap.get(dominator); if (!wrapBlocks(region, tb, dominator)) { - ErrorsCounter.methodWarn(mth, "Can't wrap try/catch for " + region); + ErrorsCounter.methodWarn(mth, "Can't wrap try/catch for region: " + region); } tryBlocksMap.remove(dominator); return true; diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/regions/RegionMaker.java b/jadx-core/src/main/java/jadx/core/dex/visitors/regions/RegionMaker.java index 80860bf5a..c5aa7498a 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/regions/RegionMaker.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/regions/RegionMaker.java @@ -929,7 +929,7 @@ public class RegionMaker { } } for (ExceptionHandler handler : tc.getHandlers()) { - processExcHandler(handler, exits); + processExcHandler(mth, handler, exits); } } return processHandlersOutBlocks(mth, tcs); @@ -968,12 +968,12 @@ public class RegionMaker { return excOutRegion; } - private void processExcHandler(ExceptionHandler handler, Set exits) { + private void processExcHandler(MethodNode mth, ExceptionHandler handler, Set exits) { BlockNode start = handler.getHandlerBlock(); if (start == null) { return; } - RegionStack stack = new RegionStack(mth); + RegionStack stack = new RegionStack(this.mth); BlockNode dom; if (handler.isFinally()) { SplitterBlockAttr splitterAttr = start.get(AType.SPLITTER_BLOCK); @@ -986,11 +986,11 @@ public class RegionMaker { stack.addExits(exits); } BitSet domFrontier = dom.getDomFrontier(); - List handlerExits = BlockUtils.bitSetToBlocks(mth, domFrontier); - boolean inLoop = mth.getLoopForBlock(start) != null; + List handlerExits = BlockUtils.bitSetToBlocks(this.mth, domFrontier); + boolean inLoop = this.mth.getLoopForBlock(start) != null; for (BlockNode exit : handlerExits) { if ((!inLoop || BlockUtils.isPathExists(start, exit)) - && RegionUtils.isRegionContainsBlock(mth.getRegion(), exit)) { + && RegionUtils.isRegionContainsBlock(this.mth.getRegion(), exit)) { stack.addExit(exit); } } @@ -998,7 +998,7 @@ public class RegionMaker { ExcHandlerAttr excHandlerAttr = start.get(AType.EXC_HANDLER); if (excHandlerAttr == null) { - LOG.warn("Missing exception handler attribute for start block"); + mth.addWarn("Missing exception handler attribute for start block: " + start); } else { handler.getHandlerRegion().addAttr(excHandlerAttr); } diff --git a/jadx-core/src/test/java/jadx/tests/external/BaseExternalTest.java b/jadx-core/src/test/java/jadx/tests/external/BaseExternalTest.java index 90ac8de9e..58b29cc5d 100644 --- a/jadx-core/src/test/java/jadx/tests/external/BaseExternalTest.java +++ b/jadx-core/src/test/java/jadx/tests/external/BaseExternalTest.java @@ -127,23 +127,36 @@ public abstract class BaseExternalTest extends IntegrationTest { String[] lines = code.split(CodeWriter.NL); for (MethodNode mth : classNode.getMethods()) { if (mthPattern.matcher(mth.getName()).matches()) { - int decompiledLine = mth.getDecompiledLine(); + int decompiledLine = mth.getDecompiledLine() - 1; StringBuilder mthCode = new StringBuilder(); + int startLine = getCommentLinesCount(lines, decompiledLine); int brackets = 0; - for (int i = decompiledLine - 1; i > 0 && i < lines.length; i++) { + for (int i = startLine; i > 0 && i < lines.length; i++) { String line = lines[i]; mthCode.append(line).append(CodeWriter.NL); - brackets += StringUtils.countMatches(line, '{'); - brackets -= StringUtils.countMatches(line, '}'); - if (brackets <= 0) { - break; + if (i >= decompiledLine) { + brackets += StringUtils.countMatches(line, '{'); + brackets -= StringUtils.countMatches(line, '}'); + if (brackets <= 0) { + break; + } } } - LOG.info("\n{}", mthCode); + LOG.info("Print method: {}\n{}", mth.getMethodInfo().getShortId(), mthCode); } } } + protected int getCommentLinesCount(String[] lines, int line) { + for (int i = line - 1; i > 0 && i < lines.length; i--) { + String str = lines[i]; + if (str.isEmpty() || str.equals(CodeWriter.NL)) { + return i + 1; + } + } + return 0; + } + private void printErrorReport(JadxDecompiler jadx) { jadx.printErrorsReport(); assertThat(jadx.getErrorsCount(), is(0));