From d1e0762c12bb663071da844777d96ad04d4aea7e Mon Sep 17 00:00:00 2001 From: Anton Dyachenko Date: Fri, 12 Sep 2014 19:24:44 +0400 Subject: [PATCH] core: fix processing of debug info (markup of local variables) --- .../core/dex/instructions/args/SSAVar.java | 54 +++++++++++++++++++ .../java/jadx/core/dex/nodes/MethodNode.java | 7 +++ .../dex/nodes/parser/DebugInfoParser.java | 30 +++++++++-- .../jadx/core/dex/nodes/parser/LocalVar.java | 17 ++++-- .../core/dex/visitors/ssa/SSATransform.java | 1 + 5 files changed, 102 insertions(+), 7 deletions(-) diff --git a/jadx-core/src/main/java/jadx/core/dex/instructions/args/SSAVar.java b/jadx-core/src/main/java/jadx/core/dex/instructions/args/SSAVar.java index 10b23c6e..da5ad647 100644 --- a/jadx-core/src/main/java/jadx/core/dex/instructions/args/SSAVar.java +++ b/jadx-core/src/main/java/jadx/core/dex/instructions/args/SSAVar.java @@ -11,6 +11,9 @@ public class SSAVar { private final int version; private VarName varName; + private int startUseAddr; + private int endUseAddr; + private RegisterArg assign; private final List useList = new ArrayList(2); private PhiInsn usedInPhi; @@ -25,12 +28,63 @@ public class SSAVar { if (assign != null) { assign.setSVar(this); } + + startUseAddr = -1; + endUseAddr = -1; } public int getRegNum() { return regNum; } + public int getStartAddr() { + if (startUseAddr == -1) { + calcUsageAddrRange(); + } + return startUseAddr; + } + + public int getEndAddr() { + if (endUseAddr == -1) { + calcUsageAddrRange(); + } + + return endUseAddr; + } + + private void calcUsageAddrRange() { + int start = Integer.MAX_VALUE; + int end = Integer.MIN_VALUE; + + if (assign != null) { + if (assign.getParentInsn() != null) { + int insnAddr = assign.getParentInsn().getOffset(); + + if (insnAddr >= 0) { + start = Math.min(insnAddr, start); + end = Math.max(insnAddr, end); + } + } + } + + for (RegisterArg arg : useList) { + if (arg.getParentInsn() != null) { + int insnAddr = arg.getParentInsn().getOffset(); + + if (insnAddr >= 0) { + start = Math.min(insnAddr, start); + end = Math.max(insnAddr, end); + } + } + } + + if ((start != Integer.MAX_VALUE) + && (end != Integer.MIN_VALUE)) { + startUseAddr = start; + endUseAddr = end; + } + } + public int getVersion() { return version; } diff --git a/jadx-core/src/main/java/jadx/core/dex/nodes/MethodNode.java b/jadx-core/src/main/java/jadx/core/dex/nodes/MethodNode.java index b393422c..5cd1b469 100644 --- a/jadx-core/src/main/java/jadx/core/dex/nodes/MethodNode.java +++ b/jadx-core/src/main/java/jadx/core/dex/nodes/MethodNode.java @@ -52,6 +52,7 @@ public class MethodNode extends LineAttrNode implements ILoadable { private final Method methodData; private int regsCount; private InsnNode[] instructions; + private int codeSize; private int debugInfoOffset; private boolean noCode; @@ -82,6 +83,7 @@ public class MethodNode extends LineAttrNode implements ILoadable { try { if (noCode) { regsCount = 0; + codeSize = 0; initMethodTypes(); return; } @@ -94,6 +96,7 @@ public class MethodNode extends LineAttrNode implements ILoadable { InsnDecoder decoder = new InsnDecoder(this); decoder.decodeInsns(mthCode); instructions = decoder.process(); + codeSize = instructions.length; initTryCatches(mthCode); initJumps(); @@ -350,6 +353,10 @@ public class MethodNode extends LineAttrNode implements ILoadable { return noCode; } + public int getCodeSize() { + return codeSize; + } + public InsnNode[] getInstructions() { return instructions; } diff --git a/jadx-core/src/main/java/jadx/core/dex/nodes/parser/DebugInfoParser.java b/jadx-core/src/main/java/jadx/core/dex/nodes/parser/DebugInfoParser.java index 22a382a1..78d4c4f1 100644 --- a/jadx-core/src/main/java/jadx/core/dex/nodes/parser/DebugInfoParser.java +++ b/jadx-core/src/main/java/jadx/core/dex/nodes/parser/DebugInfoParser.java @@ -3,6 +3,7 @@ package jadx.core.dex.nodes.parser; import jadx.core.dex.attributes.nodes.SourceFileAttr; import jadx.core.dex.instructions.args.InsnArg; import jadx.core.dex.instructions.args.RegisterArg; +import jadx.core.dex.instructions.args.SSAVar; import jadx.core.dex.nodes.DexNode; import jadx.core.dex.nodes.InsnNode; import jadx.core.dex.nodes.MethodNode; @@ -112,8 +113,9 @@ public class DebugInfoParser { int regNum = section.readUleb128(); LocalVar var = locals[regNum]; if (var != null) { - var.end(addr, line); - setVar(var); + if (var.end(addr, line)) { + setVar(var); + } var.start(addr, line); } break; @@ -160,7 +162,7 @@ public class DebugInfoParser { for (LocalVar var : locals) { if (var != null && !var.isEnd()) { - var.end(addr, line); + var.end(mth.getCodeSize()-1, line); setVar(var); } } @@ -236,7 +238,27 @@ public class DebugInfoParser { if (arg != null && arg.isRegister()) { RegisterArg reg = (RegisterArg) arg; if (var.getRegNum() == reg.getRegNum()) { - reg.mergeDebugInfo(var.getType(), var.getName()); + SSAVar ssaVar = reg.getSVar(); + + boolean mergeRequired = false; + + if (ssaVar != null) { + int ssaEnd = ssaVar.getEndAddr(); + int ssaStart = ssaVar.getStartAddr(); + int localStart = var.getStartAddr(); + int localEnd = var.getEndAddr(); + + boolean isIntersected = !((localEnd < ssaStart) || (ssaEnd < localStart)); + if (isIntersected && (ssaEnd <= localEnd)) { + mergeRequired = true; + } + } else { + mergeRequired = true; + } + + if (mergeRequired) { + reg.mergeDebugInfo(var.getType(), var.getName()); + } } } } diff --git a/jadx-core/src/main/java/jadx/core/dex/nodes/parser/LocalVar.java b/jadx-core/src/main/java/jadx/core/dex/nodes/parser/LocalVar.java index d1d5f4c2..59068804 100644 --- a/jadx-core/src/main/java/jadx/core/dex/nodes/parser/LocalVar.java +++ b/jadx-core/src/main/java/jadx/core/dex/nodes/parser/LocalVar.java @@ -69,9 +69,20 @@ final class LocalVar { this.startAddr = addr; } - public void end(int addr, int line) { - this.isEnd = true; - this.endAddr = addr; + /** + * Sets end address of local variable + * @param addr address + * @param line source line + * @return true if local variable was active, else false + */ + public boolean end(int addr, int line) { + if (!isEnd) { + this.isEnd = true; + this.endAddr = addr; + return true; + } + + return false; } public int getRegNum() { diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/ssa/SSATransform.java b/jadx-core/src/main/java/jadx/core/dex/visitors/ssa/SSATransform.java index 945c1a06..7f3df70d 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/ssa/SSATransform.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/ssa/SSATransform.java @@ -80,6 +80,7 @@ public class SSATransform extends AbstractVisitor { } PhiInsn phiInsn = new PhiInsn(regNum, block.getPredecessors().size()); phiList.getList().add(phiInsn); + phiInsn.setOffset(block.getStartOffset()); block.getInstructions().add(0, phiInsn); } -- GitLab