Commit d662b2c5 authored by Skylot's avatar Skylot

Fix debug info parsing, save generics types for variables

parent a617a77d
...@@ -80,7 +80,6 @@ public class InsnGen { ...@@ -80,7 +80,6 @@ public class InsnGen {
} }
public String assignVar(InsnNode insn) { public String assignVar(InsnNode insn) {
// return mgen.assignArg(arg);
try { try {
RegisterArg arg = insn.getResult(); RegisterArg arg = insn.getResult();
if (insn.getAttributes().contains(AttributeType.DECLARE_VARIABLE)) { if (insn.getAttributes().contains(AttributeType.DECLARE_VARIABLE)) {
...@@ -95,7 +94,11 @@ public class InsnGen { ...@@ -95,7 +94,11 @@ public class InsnGen {
} }
public String declareVar(RegisterArg arg) throws CodegenException { public String declareVar(RegisterArg arg) throws CodegenException {
return TypeGen.translate(mgen.getClassGen(), arg.getType()) + " " + arg(arg); String type = TypeGen.translate(mgen.getClassGen(), arg.getType());
String generic = arg.getType().getGeneric();
if (generic != null)
type += " /* " + generic + " */";
return type + " " + arg(arg);
} }
private String lit(LiteralArg arg) { private String lit(LiteralArg arg) {
......
...@@ -9,6 +9,9 @@ public class LocalVarInfo extends RegisterArg { ...@@ -9,6 +9,9 @@ public class LocalVarInfo extends RegisterArg {
private boolean isEnd; private boolean isEnd;
private int startAddr;
private int endAddr;
public LocalVarInfo(DexNode dex, int rn, int nameId, int typeId, int signId) { public LocalVarInfo(DexNode dex, int rn, int nameId, int typeId, int signId) {
super(rn); super(rn);
String name = (nameId == DexNode.NO_INDEX ? null : dex.getString(nameId)); String name = (nameId == DexNode.NO_INDEX ? null : dex.getString(nameId));
...@@ -24,6 +27,9 @@ public class LocalVarInfo extends RegisterArg { ...@@ -24,6 +27,9 @@ public class LocalVarInfo extends RegisterArg {
} }
private void init(String name, ArgType type, String sign) { private void init(String name, ArgType type, String sign) {
if (sign != null) {
type.setGeneric(sign);
}
TypedVar tv = new TypedVar(type); TypedVar tv = new TypedVar(type);
tv.setName(name); tv.setName(name);
setTypedVar(tv); setTypedVar(tv);
...@@ -31,13 +37,28 @@ public class LocalVarInfo extends RegisterArg { ...@@ -31,13 +37,28 @@ public class LocalVarInfo extends RegisterArg {
public void start(int addr, int line) { public void start(int addr, int line) {
this.isEnd = false; this.isEnd = false;
this.startAddr = addr;
} }
public void end(int addr, int line) { public void end(int addr, int line) {
this.isEnd = true; this.isEnd = true;
this.endAddr = addr;
} }
public boolean isEnd() { public boolean isEnd() {
return isEnd; return isEnd;
} }
public int getStartAddr() {
return startAddr;
}
public int getEndAddr() {
return endAddr;
}
@Override
public String toString() {
return super.toString() + " " + (isEnd ? "end" : "active");
}
} }
...@@ -42,6 +42,8 @@ public final class ArgType { ...@@ -42,6 +42,8 @@ public final class ArgType {
private final int hash; private final int hash;
private String generic; // TODO extract generic info from signature
private ArgType(PrimitiveType type, String object, ArgType arrayElement) { private ArgType(PrimitiveType type, String object, ArgType arrayElement) {
this.type = type; this.type = type;
this.object = (object == null ? null : Utils.cleanObjectName(object)); this.object = (object == null ? null : Utils.cleanObjectName(object));
...@@ -96,6 +98,14 @@ public final class ArgType { ...@@ -96,6 +98,14 @@ public final class ArgType {
return type == PrimitiveType.OBJECT; return type == PrimitiveType.OBJECT;
} }
public String getGeneric() {
return generic;
}
public void setGeneric(String generic) {
this.generic = generic;
}
public ArgType getArrayElement() { public ArgType getArrayElement() {
return arrayElement; return arrayElement;
} }
......
...@@ -95,7 +95,7 @@ public class MethodNode extends AttrNode implements ILoadable { ...@@ -95,7 +95,7 @@ public class MethodNode extends AttrNode implements ILoadable {
initJumps(insnByOffset); initJumps(insnByOffset);
if (mthCode.getDebugInfoOffset() > 0) { if (mthCode.getDebugInfoOffset() > 0) {
DebugInfoParser debugInfo = new DebugInfoParser(this, dex.openSection(mthCode.getDebugInfoOffset())); DebugInfoParser debugInfo = new DebugInfoParser(this, mthCode.getDebugInfoOffset());
debugInfo.process(insnByOffset); debugInfo.process(insnByOffset);
} }
} catch (Exception e) { } catch (Exception e) {
......
...@@ -33,10 +33,10 @@ public class DebugInfoParser { ...@@ -33,10 +33,10 @@ public class DebugInfoParser {
private final Section section; private final Section section;
private final DexNode dex; private final DexNode dex;
public DebugInfoParser(MethodNode mth, Section section) { public DebugInfoParser(MethodNode mth, int debugOffset) {
this.mth = mth; this.mth = mth;
this.section = section;
this.dex = mth.dex(); this.dex = mth.dex();
this.section = dex.openSection(debugOffset);
} }
public void process(InsnNode[] insnByOffset) throws DecodeException { public void process(InsnNode[] insnByOffset) throws DecodeException {
...@@ -77,8 +77,9 @@ public class DebugInfoParser { ...@@ -77,8 +77,9 @@ public class DebugInfoParser {
int regNum = section.readUleb128(); int regNum = section.readUleb128();
int nameId = section.readUleb128() - 1; int nameId = section.readUleb128() - 1;
int type = section.readUleb128() - 1; int type = section.readUleb128() - 1;
locals[regNum] = new LocalVarInfo(dex, regNum, nameId, type, DexNode.NO_INDEX); LocalVarInfo var = new LocalVarInfo(dex, regNum, nameId, type, DexNode.NO_INDEX);
locals[regNum].start(addr, line); var.start(addr, line);
locals[regNum] = var;
break; break;
} }
case DBG_START_LOCAL_EXTENDED: { case DBG_START_LOCAL_EXTENDED: {
...@@ -86,20 +87,25 @@ public class DebugInfoParser { ...@@ -86,20 +87,25 @@ public class DebugInfoParser {
int nameId = section.readUleb128() - 1; int nameId = section.readUleb128() - 1;
int type = section.readUleb128() - 1; int type = section.readUleb128() - 1;
int sign = section.readUleb128() - 1; int sign = section.readUleb128() - 1;
locals[regNum] = new LocalVarInfo(dex, regNum, nameId, type, sign); LocalVarInfo var = new LocalVarInfo(dex, regNum, nameId, type, sign);
locals[regNum].start(addr, line); var.start(addr, line);
locals[regNum] = var;
break; break;
} }
case DBG_RESTART_LOCAL: { case DBG_RESTART_LOCAL: {
int regNum = section.readUleb128(); int regNum = section.readUleb128();
if (locals[regNum] != null) LocalVarInfo var = locals[regNum];
locals[regNum].start(addr, line); if (var != null)
var.start(addr, line);
break; break;
} }
case DBG_END_LOCAL: { case DBG_END_LOCAL: {
int regNum = section.readUleb128(); int regNum = section.readUleb128();
if (locals[regNum] != null) LocalVarInfo var = locals[regNum];
locals[regNum].end(addr, line); if (var != null) {
var.end(addr, line);
setVar(var, insnByOffset);
}
break; break;
} }
...@@ -115,12 +121,9 @@ public class DebugInfoParser { ...@@ -115,12 +121,9 @@ public class DebugInfoParser {
default: default:
if (c >= DBG_FIRST_SPECIAL) { if (c >= DBG_FIRST_SPECIAL) {
int adjusted_opcode = c - DBG_FIRST_SPECIAL; int adjusted_opcode = c - DBG_FIRST_SPECIAL;
line += DBG_LINE_BASE + (adjusted_opcode % DBG_LINE_RANGE); line += DBG_LINE_BASE + (adjusted_opcode % DBG_LINE_RANGE);
addr += (adjusted_opcode / DBG_LINE_RANGE); addr += (adjusted_opcode / DBG_LINE_RANGE);
fillLocals(insnByOffset[addr], locals);
} else { } else {
throw new DecodeException("Unknown debug insn code: " + c); throw new DecodeException("Unknown debug insn code: " + c);
} }
...@@ -129,29 +132,41 @@ public class DebugInfoParser { ...@@ -129,29 +132,41 @@ public class DebugInfoParser {
c = section.readByte() & 0xFF; c = section.readByte() & 0xFF;
} }
for (LocalVarInfo var : locals) {
if (var != null && !var.isEnd()) {
var.end(addr, line);
setVar(var, insnByOffset);
}
} }
}
private void setVar(LocalVarInfo var, InsnNode[] insnByOffset) {
int start = var.getStartAddr();
int end = var.getEndAddr();
private void fillLocals(InsnNode insn, LocalVarInfo[] locals) { for (int i = start; i <= end; i++) {
InsnNode insn = insnByOffset[i];
fillLocals(insn, var);
}
}
private void fillLocals(InsnNode insn, LocalVarInfo var) {
if (insn == null) if (insn == null)
return; return;
if (insn.getResult() != null) if (insn.getResult() != null)
merge(insn.getResult(), locals); merge(insn.getResult(), var);
for (InsnArg arg : insn.getArguments()) for (InsnArg arg : insn.getArguments())
merge(arg, locals); merge(arg, var);
} }
private void merge(InsnArg arg, LocalVarInfo[] locals) { private void merge(InsnArg arg, LocalVarInfo var) {
if (arg.isRegister()) { if (arg.isRegister()) {
int rn = ((RegisterArg) arg).getRegNum(); int rn = ((RegisterArg) arg).getRegNum();
for (LocalVarInfo var : locals) {
if (var != null && !var.isEnd()) {
if (var.getRegNum() == rn) if (var.getRegNum() == rn)
arg.replace(var); arg.setTypedVar(var.getTypedVar());
}
}
} }
} }
} }
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