Commit 868e0706 authored by Skylot's avatar Skylot

core: fix source line number parsing and saving

parent 324f544b
...@@ -10,6 +10,7 @@ import java.util.Collections; ...@@ -10,6 +10,7 @@ import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.Map; import java.util.Map;
import java.util.TreeMap;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
...@@ -172,11 +173,11 @@ public class CodeWriter { ...@@ -172,11 +173,11 @@ public class CodeWriter {
return attachAnnotation(obj, new CodePosition(line, offset + 1)); return attachAnnotation(obj, new CodePosition(line, offset + 1));
} }
private void attachSourceLine(int decompiledLine, int sourceLine) { private Object attachAnnotation(Object obj, CodePosition pos) {
if (lineMap.isEmpty()) { if (annotations.isEmpty()) {
lineMap = new HashMap<Integer, Integer>(); annotations = new HashMap<CodePosition, Object>();
} }
lineMap.put(decompiledLine, sourceLine); return annotations.put(pos, obj);
} }
public Map<CodePosition, Object> getAnnotations() { public Map<CodePosition, Object> getAnnotations() {
...@@ -184,18 +185,21 @@ public class CodeWriter { ...@@ -184,18 +185,21 @@ public class CodeWriter {
} }
public void attachSourceLine(int sourceLine) { public void attachSourceLine(int sourceLine) {
if (sourceLine == 0) {
return;
}
attachSourceLine(line, sourceLine); attachSourceLine(line, sourceLine);
} }
public Map<Integer, Integer> getLineMapping() { private void attachSourceLine(int decompiledLine, int sourceLine) {
return lineMap; if (lineMap.isEmpty()) {
lineMap = new TreeMap<Integer, Integer>();
} }
lineMap.put(decompiledLine, sourceLine);
private Object attachAnnotation(Object obj, CodePosition pos) {
if (annotations.isEmpty()) {
annotations = new HashMap<CodePosition, Object>();
} }
return annotations.put(pos, obj);
public Map<Integer, Integer> getLineMapping() {
return lineMap;
} }
public void finish() { public void finish() {
......
...@@ -86,6 +86,7 @@ public class MethodGen { ...@@ -86,6 +86,7 @@ public class MethodGen {
ai = ai.remove(AccessFlags.ACC_PUBLIC); ai = ai.remove(AccessFlags.ACC_PUBLIC);
} }
code.startLine(ai.makeString()); code.startLine(ai.makeString());
code.attachSourceLine(mth.getSourceLine());
if (classGen.addGenericMap(code, mth.getGenericMap())) { if (classGen.addGenericMap(code, mth.getGenericMap())) {
code.add(' '); code.add(' ');
......
...@@ -108,6 +108,7 @@ public class RegionGen extends InsnGen { ...@@ -108,6 +108,7 @@ public class RegionGen extends InsnGen {
if (newLine) { if (newLine) {
code.startLine(); code.startLine();
} }
code.attachSourceLine(region.getSourceLine());
code.add("if ("); code.add("if (");
new ConditionGen(this).add(code, region.getCondition()); new ConditionGen(this).add(code, region.getCondition());
code.add(") {"); code.add(") {");
......
...@@ -49,6 +49,7 @@ public class ConstructorInsn extends InsnNode { ...@@ -49,6 +49,7 @@ public class ConstructorInsn extends InsnNode {
addArg(invoke.getArg(i)); addArg(invoke.getArg(i));
} }
offset = invoke.getOffset(); offset = invoke.getOffset();
setSourceLine(invoke.getSourceLine());
} }
public MethodInfo getCallMth() { public MethodInfo getCallMth() {
......
...@@ -75,6 +75,7 @@ public class DebugInfoParser { ...@@ -75,6 +75,7 @@ public class DebugInfoParser {
// process '0' instruction // process '0' instruction
addrChange(-1, 1, line); addrChange(-1, 1, line);
setLine(addr, line);
int c = section.readByte() & 0xFF; int c = section.readByte() & 0xFF;
while (c != DBG_END_SEQUENCE) { while (c != DBG_END_SEQUENCE) {
...@@ -82,6 +83,7 @@ public class DebugInfoParser { ...@@ -82,6 +83,7 @@ public class DebugInfoParser {
case DBG_ADVANCE_PC: { case DBG_ADVANCE_PC: {
int addrInc = section.readUleb128(); int addrInc = section.readUleb128();
addr = addrChange(addr, addrInc, line); addr = addrChange(addr, addrInc, line);
setLine(addr, line);
break; break;
} }
case DBG_ADVANCE_LINE: { case DBG_ADVANCE_LINE: {
...@@ -143,9 +145,10 @@ public class DebugInfoParser { ...@@ -143,9 +145,10 @@ public class DebugInfoParser {
default: { default: {
if (c >= DBG_FIRST_SPECIAL) { if (c >= DBG_FIRST_SPECIAL) {
int adjustedOpcode = c - DBG_FIRST_SPECIAL; int adjustedOpcode = c - DBG_FIRST_SPECIAL;
line += DBG_LINE_BASE + (adjustedOpcode % DBG_LINE_RANGE);
int addrInc = adjustedOpcode / DBG_LINE_RANGE; int addrInc = adjustedOpcode / DBG_LINE_RANGE;
addr = addrChange(addr, addrInc, line); addr = addrChange(addr, addrInc, line);
line += DBG_LINE_BASE + (adjustedOpcode % DBG_LINE_RANGE);
setLine(addr, line);
} else { } else {
throw new DecodeException("Unknown debug insn code: " + c); throw new DecodeException("Unknown debug insn code: " + c);
} }
...@@ -161,6 +164,7 @@ public class DebugInfoParser { ...@@ -161,6 +164,7 @@ public class DebugInfoParser {
setVar(var); setVar(var);
} }
} }
setSourceLines(addr, insnByOffset.length, line);
} }
private int addrChange(int addr, int addrInc, int line) { private int addrChange(int addr, int addrInc, int line) {
...@@ -170,7 +174,6 @@ public class DebugInfoParser { ...@@ -170,7 +174,6 @@ public class DebugInfoParser {
if (insn == null) { if (insn == null) {
continue; continue;
} }
insn.setSourceLine(line);
for (InsnArg arg : insn.getArguments()) { for (InsnArg arg : insn.getArguments()) {
if (arg.isRegister()) { if (arg.isRegister()) {
activeRegisters[((RegisterArg) arg).getRegNum()] = arg; activeRegisters[((RegisterArg) arg).getRegNum()] = arg;
...@@ -181,9 +184,23 @@ public class DebugInfoParser { ...@@ -181,9 +184,23 @@ public class DebugInfoParser {
activeRegisters[res.getRegNum()] = res; activeRegisters[res.getRegNum()] = res;
} }
} }
setSourceLines(addr, newAddr, line);
return newAddr; return newAddr;
} }
private void setSourceLines(int start, int end, int line) {
for (int offset = start + 1; offset < end; offset++) {
setLine(offset, line);
}
}
private void setLine(int offset, int line) {
InsnNode insn = insnByOffset[offset];
if (insn != null) {
insn.setSourceLine(line);
}
}
private void startVar(LocalVar var, int addr, int line) { private void startVar(LocalVar var, int addr, int line) {
int regNum = var.getRegNum(); int regNum = var.getRegNum();
LocalVar prev = locals[regNum]; LocalVar prev = locals[regNum];
......
...@@ -78,6 +78,13 @@ public final class IfRegion extends AbstractRegion { ...@@ -78,6 +78,13 @@ public final class IfRegion extends AbstractRegion {
elseRegion = tmp; elseRegion = tmp;
} }
public int getSourceLine() {
if (header.getInstructions().isEmpty()) {
return 0;
}
return header.getInstructions().get(0).getSourceLine();
}
@Override @Override
public List<IContainer> getSubBlocks() { public List<IContainer> getSubBlocks() {
if (ternRegion != null) { if (ternRegion != null) {
......
...@@ -488,6 +488,7 @@ public class BlockMakerVisitor extends AbstractVisitor { ...@@ -488,6 +488,7 @@ public class BlockMakerVisitor extends AbstractVisitor {
} }
insn.copyAttributesFrom(returnInsn); insn.copyAttributesFrom(returnInsn);
insn.setOffset(returnInsn.getOffset()); insn.setOffset(returnInsn.getOffset());
insn.setSourceLine(returnInsn.getSourceLine());
return insn; return insn;
} }
......
...@@ -48,6 +48,7 @@ public class TernaryMod { ...@@ -48,6 +48,7 @@ public class TernaryMod {
RegisterArg resArg = t.getResult().getSVar().getUsedInPhi().getResult(); RegisterArg resArg = t.getResult().getSVar().getUsedInPhi().getResult();
TernaryInsn ternInsn = new TernaryInsn(ifRegion.getCondition(), TernaryInsn ternInsn = new TernaryInsn(ifRegion.getCondition(),
resArg, InsnArg.wrapArg(t), InsnArg.wrapArg(e)); resArg, InsnArg.wrapArg(t), InsnArg.wrapArg(e));
ternInsn.setSourceLine(t.getSourceLine());
TernaryRegion tern = new TernaryRegion(ifRegion, header); TernaryRegion tern = new TernaryRegion(ifRegion, header);
// TODO: add api for replace regions // TODO: add api for replace regions
ifRegion.setTernRegion(tern); ifRegion.setTernRegion(tern);
...@@ -69,6 +70,7 @@ public class TernaryMod { ...@@ -69,6 +70,7 @@ public class TernaryMod {
eb.remove(AFlag.RETURN); eb.remove(AFlag.RETURN);
TernaryInsn ternInsn = new TernaryInsn(ifRegion.getCondition(), null, t.getArg(0), e.getArg(0)); TernaryInsn ternInsn = new TernaryInsn(ifRegion.getCondition(), null, t.getArg(0), e.getArg(0));
ternInsn.setSourceLine(t.getSourceLine());
InsnNode retInsn = new InsnNode(InsnType.RETURN, 1); InsnNode retInsn = new InsnNode(InsnType.RETURN, 1);
retInsn.addArg(InsnArg.wrapArg(ternInsn)); retInsn.addArg(InsnArg.wrapArg(ternInsn));
......
package jadx.tests.internal.debuginfo;
import jadx.api.InternalJadxTest;
import jadx.core.codegen.CodeWriter;
import jadx.core.dex.nodes.ClassNode;
import java.lang.ref.WeakReference;
import java.util.Map;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class TestLineNumbers2 extends InternalJadxTest {
public static class TestCls {
private WeakReference<TestCls> f;
public TestCls(TestCls s) {
}
TestCls test(TestCls s) {
TestCls store = f != null ? f.get() : null;
if (store == null) {
store = new TestCls(s);
f = new WeakReference<TestCls>(store);
}
return store;
}
public Object test2() {
return new Object();
}
}
@Test
public void test() {
ClassNode cls = getClassNode(TestCls.class);
CodeWriter codeWriter = cls.getCode();
String code = codeWriter.toString();
System.out.println(code);
Map<Integer, Integer> lineMapping = codeWriter.getLineMapping();
assertEquals("{8=18, 11=22, 13=23, 14=24, 15=28, 17=25, 18=26, 19=28, 22=31, 23=32}",
lineMapping.toString());
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment