diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/DebugInfoVisitor.java b/jadx-core/src/main/java/jadx/core/dex/visitors/DebugInfoVisitor.java index 5bf1f0519..69375ff84 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/DebugInfoVisitor.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/DebugInfoVisitor.java @@ -1,5 +1,8 @@ package jadx.core.dex.visitors; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import jadx.core.dex.instructions.args.ArgType; import jadx.core.dex.instructions.args.RegisterArg; import jadx.core.dex.nodes.BlockNode; @@ -7,40 +10,50 @@ import jadx.core.dex.nodes.InsnNode; import jadx.core.dex.nodes.MethodNode; import jadx.core.dex.nodes.parser.DebugInfoParser; import jadx.core.utils.BlockUtils; +import jadx.core.utils.ErrorsCounter; +import jadx.core.utils.exceptions.DecodeException; import jadx.core.utils.exceptions.JadxException; public class DebugInfoVisitor extends AbstractVisitor { + + private static final Logger LOG = LoggerFactory.getLogger(DebugInfoVisitor.class); + @Override public void visit(MethodNode mth) throws JadxException { - int debugOffset = mth.getDebugInfoOffset(); - if (debugOffset > 0) { - InsnNode[] insnArr = mth.getInstructions(); - DebugInfoParser debugInfoParser = new DebugInfoParser(mth, debugOffset, insnArr); - debugInfoParser.process(); - - // set method source line from first instruction - if (insnArr.length != 0) { - for (InsnNode insn : insnArr) { - if (insn != null) { - int line = insn.getSourceLine(); - if (line != 0) { - mth.setSourceLine(line - 1); - } - break; - } - } + try { + int debugOffset = mth.getDebugInfoOffset(); + if (debugOffset > 0) { + processDebugInfo(mth, debugOffset); } - if (!mth.getReturnType().equals(ArgType.VOID)) { - // fix debug info for splitter 'return' instructions - for (BlockNode exit : mth.getExitBlocks()) { - InsnNode ret = BlockUtils.getLastInsn(exit); - if (ret == null) { - continue; - } - InsnNode oldRet = insnArr[ret.getOffset()]; - if (oldRet == ret) { - continue; - } + } catch (Exception e) { + LOG.error("Error in debug info parser: " + ErrorsCounter.formatErrorMsg(mth, e.getMessage()), e); + } finally { + mth.unloadInsnArr(); + } + } + + private void processDebugInfo(MethodNode mth, int debugOffset) throws DecodeException { + InsnNode[] insnArr = mth.getInstructions(); + DebugInfoParser debugInfoParser = new DebugInfoParser(mth, debugOffset, insnArr); + debugInfoParser.process(); + + if (insnArr.length != 0) { + setMethodSourceLine(mth, insnArr); + } + if (!mth.getReturnType().equals(ArgType.VOID)) { + setLineForReturn(mth, insnArr); + } + } + + /** + * Fix debug info for splitter 'return' instructions + */ + private void setLineForReturn(MethodNode mth, InsnNode[] insnArr) { + for (BlockNode exit : mth.getExitBlocks()) { + InsnNode ret = BlockUtils.getLastInsn(exit); + if (ret != null) { + InsnNode oldRet = insnArr[ret.getOffset()]; + if (oldRet != ret) { RegisterArg oldArg = (RegisterArg) oldRet.getArg(0); RegisterArg newArg = (RegisterArg) ret.getArg(0); newArg.mergeDebugInfo(oldArg.getType(), oldArg.getName()); @@ -48,6 +61,20 @@ public class DebugInfoVisitor extends AbstractVisitor { } } } - mth.unloadInsnArr(); + } + + /** + * Set method source line from first instruction + */ + private void setMethodSourceLine(MethodNode mth, InsnNode[] insnArr) { + for (InsnNode insn : insnArr) { + if (insn != null) { + int line = insn.getSourceLine(); + if (line != 0) { + mth.setSourceLine(line - 1); + } + return; + } + } } }