Fix debug info parsing, save generics types for variables

This commit is contained in:
Skylot 2013-04-09 23:56:20 +04:00
parent a617a77d1f
commit d662b2c50c
5 changed files with 76 additions and 27 deletions

View File

@ -80,7 +80,6 @@ public class InsnGen {
}
public String assignVar(InsnNode insn) {
// return mgen.assignArg(arg);
try {
RegisterArg arg = insn.getResult();
if (insn.getAttributes().contains(AttributeType.DECLARE_VARIABLE)) {
@ -95,7 +94,11 @@ public class InsnGen {
}
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) {

View File

@ -9,6 +9,9 @@ public class LocalVarInfo extends RegisterArg {
private boolean isEnd;
private int startAddr;
private int endAddr;
public LocalVarInfo(DexNode dex, int rn, int nameId, int typeId, int signId) {
super(rn);
String name = (nameId == DexNode.NO_INDEX ? null : dex.getString(nameId));
@ -24,6 +27,9 @@ public class LocalVarInfo extends RegisterArg {
}
private void init(String name, ArgType type, String sign) {
if (sign != null) {
type.setGeneric(sign);
}
TypedVar tv = new TypedVar(type);
tv.setName(name);
setTypedVar(tv);
@ -31,13 +37,28 @@ public class LocalVarInfo extends RegisterArg {
public void start(int addr, int line) {
this.isEnd = false;
this.startAddr = addr;
}
public void end(int addr, int line) {
this.isEnd = true;
this.endAddr = addr;
}
public boolean isEnd() {
return isEnd;
}
public int getStartAddr() {
return startAddr;
}
public int getEndAddr() {
return endAddr;
}
@Override
public String toString() {
return super.toString() + " " + (isEnd ? "end" : "active");
}
}

View File

@ -42,6 +42,8 @@ public final class ArgType {
private final int hash;
private String generic; // TODO extract generic info from signature
private ArgType(PrimitiveType type, String object, ArgType arrayElement) {
this.type = type;
this.object = (object == null ? null : Utils.cleanObjectName(object));
@ -96,6 +98,14 @@ public final class ArgType {
return type == PrimitiveType.OBJECT;
}
public String getGeneric() {
return generic;
}
public void setGeneric(String generic) {
this.generic = generic;
}
public ArgType getArrayElement() {
return arrayElement;
}

View File

@ -95,7 +95,7 @@ public class MethodNode extends AttrNode implements ILoadable {
initJumps(insnByOffset);
if (mthCode.getDebugInfoOffset() > 0) {
DebugInfoParser debugInfo = new DebugInfoParser(this, dex.openSection(mthCode.getDebugInfoOffset()));
DebugInfoParser debugInfo = new DebugInfoParser(this, mthCode.getDebugInfoOffset());
debugInfo.process(insnByOffset);
}
} catch (Exception e) {

View File

@ -33,10 +33,10 @@ public class DebugInfoParser {
private final Section section;
private final DexNode dex;
public DebugInfoParser(MethodNode mth, Section section) {
public DebugInfoParser(MethodNode mth, int debugOffset) {
this.mth = mth;
this.section = section;
this.dex = mth.dex();
this.section = dex.openSection(debugOffset);
}
public void process(InsnNode[] insnByOffset) throws DecodeException {
@ -77,8 +77,9 @@ public class DebugInfoParser {
int regNum = section.readUleb128();
int nameId = section.readUleb128() - 1;
int type = section.readUleb128() - 1;
locals[regNum] = new LocalVarInfo(dex, regNum, nameId, type, DexNode.NO_INDEX);
locals[regNum].start(addr, line);
LocalVarInfo var = new LocalVarInfo(dex, regNum, nameId, type, DexNode.NO_INDEX);
var.start(addr, line);
locals[regNum] = var;
break;
}
case DBG_START_LOCAL_EXTENDED: {
@ -86,20 +87,25 @@ public class DebugInfoParser {
int nameId = section.readUleb128() - 1;
int type = section.readUleb128() - 1;
int sign = section.readUleb128() - 1;
locals[regNum] = new LocalVarInfo(dex, regNum, nameId, type, sign);
locals[regNum].start(addr, line);
LocalVarInfo var = new LocalVarInfo(dex, regNum, nameId, type, sign);
var.start(addr, line);
locals[regNum] = var;
break;
}
case DBG_RESTART_LOCAL: {
int regNum = section.readUleb128();
if (locals[regNum] != null)
locals[regNum].start(addr, line);
LocalVarInfo var = locals[regNum];
if (var != null)
var.start(addr, line);
break;
}
case DBG_END_LOCAL: {
int regNum = section.readUleb128();
if (locals[regNum] != null)
locals[regNum].end(addr, line);
LocalVarInfo var = locals[regNum];
if (var != null) {
var.end(addr, line);
setVar(var, insnByOffset);
}
break;
}
@ -115,12 +121,9 @@ public class DebugInfoParser {
default:
if (c >= DBG_FIRST_SPECIAL) {
int adjusted_opcode = c - DBG_FIRST_SPECIAL;
line += DBG_LINE_BASE + (adjusted_opcode % DBG_LINE_RANGE);
addr += (adjusted_opcode / DBG_LINE_RANGE);
fillLocals(insnByOffset[addr], locals);
} else {
throw new DecodeException("Unknown debug insn code: " + c);
}
@ -129,29 +132,41 @@ public class DebugInfoParser {
c = section.readByte() & 0xFF;
}
for (LocalVarInfo var : locals) {
if (var != null && !var.isEnd()) {
var.end(addr, line);
setVar(var, insnByOffset);
}
}
}
private void fillLocals(InsnNode insn, LocalVarInfo[] locals) {
private void setVar(LocalVarInfo var, InsnNode[] insnByOffset) {
int start = var.getStartAddr();
int end = var.getEndAddr();
for (int i = start; i <= end; i++) {
InsnNode insn = insnByOffset[i];
fillLocals(insn, var);
}
}
private void fillLocals(InsnNode insn, LocalVarInfo var) {
if (insn == null)
return;
if (insn.getResult() != null)
merge(insn.getResult(), locals);
merge(insn.getResult(), var);
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()) {
int rn = ((RegisterArg) arg).getRegNum();
for (LocalVarInfo var : locals) {
if (var != null && !var.isEnd()) {
if (var.getRegNum() == rn)
arg.replace(var);
}
}
if (var.getRegNum() == rn)
arg.setTypedVar(var.getTypedVar());
}
}
}