mirror of
https://github.com/skylot/jadx.git
synced 2024-11-23 04:39:46 +00:00
Fix debug info parsing, save generics types for variables
This commit is contained in:
parent
a617a77d1f
commit
d662b2c50c
@ -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) {
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user