Commit 25b2c8fe authored by Skylot's avatar Skylot

core: store line info, add fields and methods to api, refactoring

parent 36da79fe
...@@ -65,7 +65,7 @@ public final class Decompiler { ...@@ -65,7 +65,7 @@ public final class Decompiler {
for (ClassNode classNode : root.getClasses()) { for (ClassNode classNode : root.getClasses()) {
classes.add(new JavaClass(this, classNode)); classes.add(new JavaClass(this, classNode));
} }
return classes; return Collections.unmodifiableList(classes);
} }
public List<JavaPackage> getPackages() { public List<JavaPackage> getPackages() {
...@@ -85,7 +85,7 @@ public final class Decompiler { ...@@ -85,7 +85,7 @@ public final class Decompiler {
packages.add(new JavaPackage(entry.getKey(), entry.getValue())); packages.add(new JavaPackage(entry.getKey(), entry.getValue()));
} }
Collections.sort(packages); Collections.sort(packages);
return packages; return Collections.unmodifiableList(packages);
} }
public void saveAll() throws InterruptedException { public void saveAll() throws InterruptedException {
......
package jadx.api; package jadx.api;
import jadx.core.codegen.CodeWriter; import jadx.core.codegen.CodeWriter;
import jadx.core.dex.attributes.AttributeFlag;
import jadx.core.dex.info.AccessInfo;
import jadx.core.dex.nodes.ClassNode; import jadx.core.dex.nodes.ClassNode;
import jadx.core.dex.nodes.FieldNode;
import jadx.core.dex.nodes.MethodNode;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public final class JavaClass { public final class JavaClass {
private final Decompiler decompiler; private final Decompiler decompiler;
private final ClassNode cls; private final ClassNode cls;
private final List<JavaClass> innerClasses;
private final List<JavaField> fields;
private final List<JavaMethod> methods;
JavaClass(Decompiler decompiler, ClassNode classNode) { JavaClass(Decompiler decompiler, ClassNode classNode) {
this.decompiler = decompiler; this.decompiler = decompiler;
this.cls = classNode; this.cls = classNode;
int inClsCount = cls.getInnerClasses().size();
if (inClsCount == 0) {
this.innerClasses = Collections.emptyList();
} else {
List<JavaClass> list = new ArrayList<JavaClass>(inClsCount);
for (ClassNode inner : cls.getInnerClasses()) {
list.add(new JavaClass(decompiler, inner));
}
this.innerClasses = Collections.unmodifiableList(list);
}
int fieldsCount = cls.getFields().size();
if (fieldsCount == 0) {
this.fields = Collections.emptyList();
} else {
List<JavaField> flds = new ArrayList<JavaField>(fieldsCount);
for (FieldNode f : cls.getFields()) {
flds.add(new JavaField(f));
}
this.fields = Collections.unmodifiableList(flds);
}
int methodsCount = cls.getMethods().size();
if (methodsCount == 0) {
this.methods = Collections.emptyList();
} else {
List<JavaMethod> mths = new ArrayList<JavaMethod>(methodsCount);
for (MethodNode m : cls.getMethods()) {
if (!m.getAttributes().contains(AttributeFlag.DONT_GENERATE)) {
mths.add(new JavaMethod(m));
}
}
this.methods = Collections.unmodifiableList(mths);
}
} }
public String getCode() { public String getCode() {
CodeWriter code = cls.getCode(); CodeWriter code = cls.getCode();
if(code == null) { if (code == null) {
decompiler.processClass(cls); decompiler.processClass(cls);
code = cls.getCode(); code = cls.getCode();
} }
...@@ -34,8 +80,28 @@ public final class JavaClass { ...@@ -34,8 +80,28 @@ public final class JavaClass {
return cls.getPackage(); return cls.getPackage();
} }
public AccessInfo getAccessInfo() {
return cls.getAccessFlags();
}
public List<JavaClass> getInnerClasses() {
return innerClasses;
}
public List<JavaField> getFields() {
return fields;
}
public List<JavaMethod> getMethods() {
return methods;
}
@Override @Override
public String toString() { public String toString() {
return getFullName(); return getFullName();
} }
public int getDecompiledLine() {
return cls.getDecompiledLine();
}
} }
package jadx.api;
import jadx.core.dex.info.AccessInfo;
import jadx.core.dex.nodes.FieldNode;
public class JavaField {
private final FieldNode field;
public JavaField(FieldNode f) {
this.field = f;
}
public String getName() {
return field.getName();
}
public AccessInfo getAccessFlags() {
return field.getAccessFlags();
}
public int getDecompiledLine() {
return field.getDecompiledLine();
}
}
package jadx.api;
import jadx.core.dex.info.AccessInfo;
import jadx.core.dex.info.MethodInfo;
import jadx.core.dex.nodes.MethodNode;
public class JavaMethod {
private final MethodNode mth;
public JavaMethod(MethodNode m) {
this.mth = m;
}
public String getName() {
MethodInfo mi = mth.getMethodInfo();
if (mi.isConstructor()) {
return mth.getParentClass().getShortName();
} else if (mi.isClassInit()) {
return "static";
}
return mi.getName();
}
public AccessInfo getAccessFlags() {
return mth.getAccessFlags();
}
public int getDecompiledLine() {
return mth.getDecompiledLine();
}
}
...@@ -59,7 +59,7 @@ public class ClassGen { ...@@ -59,7 +59,7 @@ public class ClassGen {
if (!"".equals(cls.getPackage())) { if (!"".equals(cls.getPackage())) {
clsCode.add("package ").add(cls.getPackage()).add(';'); clsCode.add("package ").add(cls.getPackage()).add(';');
clsCode.endl(); clsCode.newLine();
} }
if (imports.size() != 0) { if (imports.size() != 0) {
...@@ -71,7 +71,7 @@ public class ClassGen { ...@@ -71,7 +71,7 @@ public class ClassGen {
for (String imp : sortImports) { for (String imp : sortImports) {
clsCode.startLine("import ").add(imp).add(';'); clsCode.startLine("import ").add(imp).add(';');
} }
clsCode.endl(); clsCode.newLine();
sortImports.clear(); sortImports.clear();
imports.clear(); imports.clear();
...@@ -90,7 +90,7 @@ public class ClassGen { ...@@ -90,7 +90,7 @@ public class ClassGen {
makeClassDeclaration(code); makeClassDeclaration(code);
makeClassBody(code); makeClassBody(code);
code.endl(); code.newLine();
} }
public void makeClassDeclaration(CodeWriter clsCode) { public void makeClassDeclaration(CodeWriter clsCode) {
...@@ -139,6 +139,8 @@ public class ClassGen { ...@@ -139,6 +139,8 @@ public class ClassGen {
if (!cls.getInterfaces().isEmpty()) if (!cls.getInterfaces().isEmpty())
clsCode.add(' '); clsCode.add(' ');
} }
clsCode.attachAnnotation(cls);
} }
public boolean makeGenericMap(CodeWriter code, Map<ArgType, List<ArgType>> gmap) { public boolean makeGenericMap(CodeWriter code, Map<ArgType, List<ArgType>> gmap) {
...@@ -178,13 +180,13 @@ public class ClassGen { ...@@ -178,13 +180,13 @@ public class ClassGen {
CodeWriter fieldsCode = makeFields(clsCode, cls, cls.getFields()); CodeWriter fieldsCode = makeFields(clsCode, cls, cls.getFields());
clsCode.add(fieldsCode); clsCode.add(fieldsCode);
if (fieldsCode.notEmpty() && mthsCode.notEmpty()) if (fieldsCode.notEmpty() && mthsCode.notEmpty())
clsCode.endl(); clsCode.newLine();
// insert inner classes code // insert inner classes code
if (cls.getInnerClasses().size() != 0) { if (cls.getInnerClasses().size() != 0) {
clsCode.add(makeInnerClasses(cls, clsCode.getIndent())); clsCode.add(makeInnerClasses(cls, clsCode.getIndent()));
if (mthsCode.notEmpty()) if (mthsCode.notEmpty())
clsCode.endl(); clsCode.newLine();
} }
clsCode.add(mthsCode); clsCode.add(mthsCode);
clsCode.startLine('}'); clsCode.startLine('}');
...@@ -239,7 +241,7 @@ public class ClassGen { ...@@ -239,7 +241,7 @@ public class ClassGen {
} }
if (it.hasNext()) if (it.hasNext())
code.endl(); code.newLine();
} }
return code; return code;
} }
...@@ -278,7 +280,7 @@ public class ClassGen { ...@@ -278,7 +280,7 @@ public class ClassGen {
code.startLine(); code.startLine();
code.add(';'); code.add(';');
code.endl(); code.newLine();
} }
for (FieldNode f : fields) { for (FieldNode f : fields) {
...@@ -297,6 +299,7 @@ public class ClassGen { ...@@ -297,6 +299,7 @@ public class ClassGen {
} }
} }
code.add(';'); code.add(';');
code.attachAnnotation(f);
} }
return code; return code;
} }
......
...@@ -21,14 +21,8 @@ public class CodeGen extends AbstractVisitor { ...@@ -21,14 +21,8 @@ public class CodeGen extends AbstractVisitor {
public boolean visit(ClassNode cls) throws CodegenException { public boolean visit(ClassNode cls) throws CodegenException {
ClassGen clsGen = new ClassGen(cls, null, isFallbackMode()); ClassGen clsGen = new ClassGen(cls, null, isFallbackMode());
CodeWriter clsCode = clsGen.makeClass(); CodeWriter clsCode = clsGen.makeClass();
clsCode.finish();
cls.setCode(clsCode); cls.setCode(clsCode);
// String fileName = cls.getClassInfo().getFullPath() + ".java";
// if (isFallbackMode())
// fileName += ".jadx";
// clsCode.save(dir, fileName);
return false; return false;
} }
......
package jadx.core.codegen; package jadx.core.codegen;
import jadx.core.dex.attributes.LineAttrNode;
import jadx.core.utils.exceptions.JadxRuntimeException; import jadx.core.utils.exceptions.JadxRuntimeException;
import java.io.File; import java.io.File;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
...@@ -19,6 +23,9 @@ public class CodeWriter { ...@@ -19,6 +23,9 @@ public class CodeWriter {
private String indentStr; private String indentStr;
private int indent; private int indent;
private int line = 1;
private Map<Object, Integer> annotations = Collections.emptyMap();
public CodeWriter() { public CodeWriter() {
this.indent = 0; this.indent = 0;
this.indentStr = ""; this.indentStr = "";
...@@ -29,32 +36,32 @@ public class CodeWriter { ...@@ -29,32 +36,32 @@ public class CodeWriter {
updateIndent(); updateIndent();
} }
public CodeWriter startLine(String str) { public CodeWriter startLine() {
buf.append(NL); addLine();
buf.append(indentStr); buf.append(indentStr);
buf.append(str);
return this; return this;
} }
public CodeWriter startLine(char c) { public CodeWriter startLine(char c) {
buf.append(NL); addLine();
buf.append(indentStr); buf.append(indentStr);
buf.append(c); buf.append(c);
return this; return this;
} }
public CodeWriter startLine(int ind, String str) { public CodeWriter startLine(String str) {
buf.append(NL); addLine();
buf.append(indentStr); buf.append(indentStr);
for (int i = 0; i < ind; i++)
buf.append(INDENT);
buf.append(str); buf.append(str);
return this; return this;
} }
public CodeWriter startLine() { public CodeWriter startLine(int ind, String str) {
buf.append(NL); addLine();
buf.append(indentStr); buf.append(indentStr);
for (int i = 0; i < ind; i++)
buf.append(INDENT);
buf.append(str);
return this; return this;
} }
...@@ -68,17 +75,47 @@ public class CodeWriter { ...@@ -68,17 +75,47 @@ public class CodeWriter {
return this; return this;
} }
public CodeWriter add(CodeWriter mthsCode) { public CodeWriter add(CodeWriter code) {
buf.append(mthsCode.toString()); line--;
for (Map.Entry<Object, Integer> entry : code.annotations.entrySet()) {
attachAnnotation(entry.getKey(), line + entry.getValue());
}
line += code.line;
buf.append(code.toString());
return this; return this;
} }
public CodeWriter endl() { public CodeWriter newLine() {
addLine();
return this;
}
private void addLine() {
buf.append(NL); buf.append(NL);
line++;
}
public int getLine() {
return line;
}
public Object attachAnnotation(Object obj) {
return attachAnnotation(obj, line);
}
public Object attachAnnotation(Object obj, int line) {
if (annotations.isEmpty()) {
annotations = new HashMap<Object, Integer>();
}
return annotations.put(obj, line);
}
public CodeWriter indent() {
buf.append(indentStr);
return this; return this;
} }
private static final String[] INDENT_CACHE = new String[] { private static final String[] INDENT_CACHE = new String[]{
"", "",
INDENT, INDENT,
INDENT + INDENT, INDENT + INDENT,
...@@ -126,6 +163,18 @@ public class CodeWriter { ...@@ -126,6 +163,18 @@ public class CodeWriter {
updateIndent(); updateIndent();
} }
public void finish() {
buf.trimToSize();
for (Map.Entry<Object, Integer> entry : annotations.entrySet()) {
Object v = entry.getKey();
if(v instanceof LineAttrNode) {
LineAttrNode l = (LineAttrNode) v;
l.setDecompiledLine(entry.getValue());
}
}
annotations.clear();
}
private static String removeFirstEmptyLine(String str) { private static String removeFirstEmptyLine(String str) {
if (str.startsWith(NL)) { if (str.startsWith(NL)) {
return str.substring(NL.length()); return str.substring(NL.length());
......
...@@ -152,13 +152,16 @@ public class InsnGen { ...@@ -152,13 +152,16 @@ public class InsnGen {
} else { } else {
CodeWriter body = new CodeWriter(code.getIndent()); CodeWriter body = new CodeWriter(code.getIndent());
makeInsnBody(body, insn, state); makeInsnBody(body, insn, state);
if (state.contains(InsnGenState.SKIP)) if (state.contains(InsnGenState.SKIP)) {
return false; return false;
}
if (insn.getResult() != null && !state.contains(InsnGenState.NO_RESULT))
code.startLine(assignVar(insn)).add(" = ");
else
code.startLine(); code.startLine();
if (insn.getSourceLine() != 0) {
code.attachAnnotation(insn.getSourceLine());
}
if (insn.getResult() != null && !state.contains(InsnGenState.NO_RESULT))
code.add(assignVar(insn)).add(" = ");
code.add(body); code.add(body);
......
...@@ -108,6 +108,7 @@ public class MethodGen { ...@@ -108,6 +108,7 @@ public class MethodGen {
annotationGen.addThrows(mth, code); annotationGen.addThrows(mth, code);
} }
code.attachAnnotation(mth);
} }
public CodeWriter makeArguments(List<RegisterArg> args) { public CodeWriter makeArguments(List<RegisterArg> args) {
...@@ -225,7 +226,7 @@ public class MethodGen { ...@@ -225,7 +226,7 @@ public class MethodGen {
code.startLine("// jadx: method processing error"); code.startLine("// jadx: method processing error");
Throwable cause = err.getCause(); Throwable cause = err.getCause();
if (cause != null) { if (cause != null) {
code.endl(); code.newLine();
code.add("/*"); code.add("/*");
code.startLine("Error: ").add(Utils.getStackTrace(cause)); code.startLine("Error: ").add(Utils.getStackTrace(cause));
code.add("*/"); code.add("*/");
......
...@@ -165,14 +165,14 @@ public class RegionGen extends InsnGen { ...@@ -165,14 +165,14 @@ public class RegionGen extends InsnGen {
case AND: case AND:
case OR: case OR:
String mode = condition.getMode() == IfCondition.MODE.AND ? " && " : " || "; String mode = condition.getMode() == IfCondition.MODE.AND ? " && " : " || ";
CodeWriter cw = new CodeWriter(); StringBuilder sb = new StringBuilder();
for (IfCondition arg : condition.getArgs()) { for (IfCondition arg : condition.getArgs()) {
if (cw.notEmpty()) { if (sb.length() != 0) {
cw.add(mode); sb.append(mode);
} }
cw.add('(').add(makeCondition(arg)).add(')'); sb.append('(').append(makeCondition(arg)).append(')');
} }
return cw.toString(); return sb.toString();
default: default:
return "??" + condition.toString(); return "??" + condition.toString();
} }
......
package jadx.core.dex.attributes;
public abstract class LineAttrNode extends AttrNode {
private int sourceLine;
private int decompiledLine;
public int getSourceLine() {
return sourceLine;
}
public void setSourceLine(int sourceLine) {
this.sourceLine = sourceLine;
}
public int getDecompiledLine() {
return decompiledLine;
}
public void setDecompiledLine(int decompiledLine) {
this.decompiledLine = decompiledLine;
}
}
...@@ -97,6 +97,10 @@ public class AccessInfo { ...@@ -97,6 +97,10 @@ public class AccessInfo {
return accFlags; return accFlags;
} }
public AFType getType() {
return type;
}
public String makeString() { public String makeString() {
StringBuilder code = new StringBuilder(); StringBuilder code = new StringBuilder();
if (isPublic()) if (isPublic())
......
...@@ -40,6 +40,26 @@ public class FieldInfo { ...@@ -40,6 +40,26 @@ public class FieldInfo {
} }
@Override @Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
FieldInfo fieldInfo = (FieldInfo) o;
if (!name.equals(fieldInfo.name)) return false;
if (!type.equals(fieldInfo.type)) return false;
if (!declClass.equals(fieldInfo.declClass)) return false;
return true;
}
@Override
public int hashCode() {
int result = name.hashCode();
result = 31 * result + type.hashCode();
result = 31 * result + declClass.hashCode();
return result;
}
@Override
public String toString() { public String toString() {
return declClass + "." + name + " " + type; return declClass + "." + name + " " + type;
} }
......
...@@ -2,8 +2,8 @@ package jadx.core.dex.nodes; ...@@ -2,8 +2,8 @@ package jadx.core.dex.nodes;
import jadx.core.Consts; import jadx.core.Consts;
import jadx.core.codegen.CodeWriter; import jadx.core.codegen.CodeWriter;
import jadx.core.dex.attributes.AttrNode;
import jadx.core.dex.attributes.AttributeType; import jadx.core.dex.attributes.AttributeType;
import jadx.core.dex.attributes.LineAttrNode;
import jadx.core.dex.attributes.SourceFileAttr; import jadx.core.dex.attributes.SourceFileAttr;
import jadx.core.dex.attributes.annotations.Annotation; import jadx.core.dex.attributes.annotations.Annotation;
import jadx.core.dex.info.AccessInfo; import jadx.core.dex.info.AccessInfo;
...@@ -32,7 +32,7 @@ import com.android.dx.io.ClassData.Field; ...@@ -32,7 +32,7 @@ import com.android.dx.io.ClassData.Field;
import com.android.dx.io.ClassData.Method; import com.android.dx.io.ClassData.Method;
import com.android.dx.io.ClassDef; import com.android.dx.io.ClassDef;
public class ClassNode extends AttrNode implements ILoadable { public class ClassNode extends LineAttrNode implements ILoadable {
private static final Logger LOG = LoggerFactory.getLogger(ClassNode.class); private static final Logger LOG = LoggerFactory.getLogger(ClassNode.class);
private final DexNode dex; private final DexNode dex;
......
package jadx.core.dex.nodes; package jadx.core.dex.nodes;
import jadx.core.dex.attributes.AttrNode; import jadx.core.dex.attributes.LineAttrNode;
import jadx.core.dex.info.AccessInfo; import jadx.core.dex.info.AccessInfo;
import jadx.core.dex.info.AccessInfo.AFType; import jadx.core.dex.info.AccessInfo.AFType;
import jadx.core.dex.info.FieldInfo; import jadx.core.dex.info.FieldInfo;
...@@ -8,7 +8,7 @@ import jadx.core.dex.instructions.args.ArgType; ...@@ -8,7 +8,7 @@ import jadx.core.dex.instructions.args.ArgType;
import com.android.dx.io.ClassData.Field; import com.android.dx.io.ClassData.Field;
public class FieldNode extends AttrNode { public class FieldNode extends LineAttrNode {
private final FieldInfo fieldInfo; private final FieldInfo fieldInfo;
private final AccessInfo accFlags; private final AccessInfo accFlags;
...@@ -42,6 +42,19 @@ public class FieldNode extends AttrNode { ...@@ -42,6 +42,19 @@ public class FieldNode extends AttrNode {
} }
@Override @Override
public int hashCode() {
return fieldInfo.hashCode();
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
FieldNode other = (FieldNode) obj;
return fieldInfo.equals(other.fieldInfo);
}
@Override
public String toString() { public String toString() {
return fieldInfo.getDeclClass() + "." + fieldInfo.getName() + " " + type; return fieldInfo.getDeclClass() + "." + fieldInfo.getName() + " " + type;
} }
......
package jadx.core.dex.nodes; package jadx.core.dex.nodes;
import jadx.core.dex.attributes.AttrNode; import jadx.core.dex.attributes.LineAttrNode;
import jadx.core.dex.instructions.InsnType; import jadx.core.dex.instructions.InsnType;
import jadx.core.dex.instructions.args.ArgType; import jadx.core.dex.instructions.args.ArgType;
import jadx.core.dex.instructions.args.InsnArg; import jadx.core.dex.instructions.args.InsnArg;
...@@ -15,7 +15,7 @@ import java.util.List; ...@@ -15,7 +15,7 @@ import java.util.List;
import com.android.dx.io.instructions.DecodedInstruction; import com.android.dx.io.instructions.DecodedInstruction;
public class InsnNode extends AttrNode { public class InsnNode extends LineAttrNode {
protected final InsnType insnType; protected final InsnType insnType;
......
package jadx.core.dex.nodes; package jadx.core.dex.nodes;
import jadx.core.Consts; import jadx.core.Consts;
import jadx.core.dex.attributes.AttrNode;
import jadx.core.dex.attributes.AttributeFlag; import jadx.core.dex.attributes.AttributeFlag;
import jadx.core.dex.attributes.JumpAttribute; import jadx.core.dex.attributes.JumpAttribute;
import jadx.core.dex.attributes.LineAttrNode;
import jadx.core.dex.attributes.LoopAttr; import jadx.core.dex.attributes.LoopAttr;
import jadx.core.dex.attributes.annotations.Annotation; import jadx.core.dex.attributes.annotations.Annotation;
import jadx.core.dex.info.AccessInfo; import jadx.core.dex.info.AccessInfo;
...@@ -40,7 +40,7 @@ import com.android.dx.io.Code; ...@@ -40,7 +40,7 @@ import com.android.dx.io.Code;
import com.android.dx.io.Code.CatchHandler; import com.android.dx.io.Code.CatchHandler;
import com.android.dx.io.Code.Try; import com.android.dx.io.Code.Try;
public class MethodNode extends AttrNode implements ILoadable { public class MethodNode extends LineAttrNode implements ILoadable {
private static final Logger LOG = LoggerFactory.getLogger(MethodNode.class); private static final Logger LOG = LoggerFactory.getLogger(MethodNode.class);
private final MethodInfo mthInfo; private final MethodInfo mthInfo;
...@@ -101,8 +101,17 @@ public class MethodNode extends AttrNode implements ILoadable { ...@@ -101,8 +101,17 @@ public class MethodNode extends AttrNode implements ILoadable {
initTryCatches(mthCode, insnByOffset); initTryCatches(mthCode, insnByOffset);
initJumps(insnByOffset); initJumps(insnByOffset);
if (mthCode.getDebugInfoOffset() > 0) { int debugInfoOffset = mthCode.getDebugInfoOffset();
(new DebugInfoParser(this, mthCode.getDebugInfoOffset(), insnByOffset)).process(); if (debugInfoOffset > 0) {
DebugInfoParser debugInfoParser = new DebugInfoParser(this, debugInfoOffset, insnByOffset);
debugInfoParser.process();
if (instructions.size() != 0) {
int line = instructions.get(0).getSourceLine();
if (line != 0) {
this.setSourceLine(line - 1);
}
}
} }
} catch (Exception e) { } catch (Exception e) {
throw new DecodeException(this, "Load method exception", e); throw new DecodeException(this, "Load method exception", e);
...@@ -414,7 +423,7 @@ public class MethodNode extends AttrNode implements ILoadable { ...@@ -414,7 +423,7 @@ public class MethodNode extends AttrNode implements ILoadable {
} }
public void registerLoop(LoopAttr loop) { public void registerLoop(LoopAttr loop) {
if(loops.isEmpty()) { if (loops.isEmpty()) {
loops = new ArrayList<LoopAttr>(5); loops = new ArrayList<LoopAttr>(5);
} }
loops.add(loop); loops.add(loop);
...@@ -422,7 +431,7 @@ public class MethodNode extends AttrNode implements ILoadable { ...@@ -422,7 +431,7 @@ public class MethodNode extends AttrNode implements ILoadable {
public LoopAttr getLoopForBlock(BlockNode block) { public LoopAttr getLoopForBlock(BlockNode block) {
for (LoopAttr loop : loops) { for (LoopAttr loop : loops) {
if(loop.getLoopBlocks().contains(block)) if (loop.getLoopBlocks().contains(block))
return loop; return loop;
} }
return null; return null;
...@@ -478,6 +487,19 @@ public class MethodNode extends AttrNode implements ILoadable { ...@@ -478,6 +487,19 @@ public class MethodNode extends AttrNode implements ILoadable {
} }
@Override @Override
public int hashCode() {
return mthInfo.hashCode();
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
MethodNode other = (MethodNode) obj;
return mthInfo.equals(other.mthInfo);
}
@Override
public String toString() { public String toString() {
return retType return retType
+ " " + parentClass.getFullName() + "." + mthInfo.getName() + " " + parentClass.getFullName() + "." + mthInfo.getName()
......
...@@ -49,9 +49,8 @@ public class DebugInfoParser { ...@@ -49,9 +49,8 @@ public class DebugInfoParser {
public void process() throws DecodeException { public void process() throws DecodeException {
int addr = 0; int addr = 0;
int line; int line = section.readUleb128();
line = section.readUleb128();
int param_size = section.readUleb128(); // exclude 'this' int param_size = section.readUleb128(); // exclude 'this'
List<RegisterArg> mthArgs = mth.getArguments(false); List<RegisterArg> mthArgs = mth.getArguments(false);
assert param_size == mthArgs.size(); assert param_size == mthArgs.size();
...@@ -70,14 +69,14 @@ public class DebugInfoParser { ...@@ -70,14 +69,14 @@ public class DebugInfoParser {
activeRegisters[rn] = arg; activeRegisters[rn] = arg;
} }
addrChange(-1, 1); // process '0' instruction addrChange(-1, 1, line); // process '0' instruction
int c = section.readByte() & 0xFF; int c = section.readByte() & 0xFF;
while (c != DBG_END_SEQUENCE) { while (c != DBG_END_SEQUENCE) {
switch (c) { switch (c) {
case DBG_ADVANCE_PC: { case DBG_ADVANCE_PC: {
int addrInc = section.readUleb128(); int addrInc = section.readUleb128();
addr = addrChange(addr, addrInc); addr = addrChange(addr, addrInc, line);
break; break;
} }
case DBG_ADVANCE_LINE: { case DBG_ADVANCE_LINE: {
...@@ -141,14 +140,13 @@ public class DebugInfoParser { ...@@ -141,14 +140,13 @@ public class DebugInfoParser {
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);
int addrInc = (adjusted_opcode / DBG_LINE_RANGE); int addrInc = (adjusted_opcode / DBG_LINE_RANGE);
addr = addrChange(addr, addrInc); addr = addrChange(addr, addrInc, line);
} else { } else {
throw new DecodeException("Unknown debug insn code: " + c); throw new DecodeException("Unknown debug insn code: " + c);
} }
break; break;
} }
} }
c = section.readByte() & 0xFF; c = section.readByte() & 0xFF;
} }
...@@ -160,13 +158,14 @@ public class DebugInfoParser { ...@@ -160,13 +158,14 @@ public class DebugInfoParser {
} }
} }
private int addrChange(int addr, int addrInc) { private int addrChange(int addr, int addrInc, int line) {
int newAddr = addr + addrInc; int newAddr = addr + addrInc;
for (int i = addr + 1; i <= newAddr; i++) { for (int i = addr + 1; i <= newAddr; i++) {
InsnNode insn = insnByOffset[i]; InsnNode insn = insnByOffset[i];
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[arg.getRegNum()] = arg; activeRegisters[arg.getRegNum()] = arg;
......
...@@ -168,7 +168,7 @@ public class DotGraphVisitor extends AbstractVisitor { ...@@ -168,7 +168,7 @@ public class DotGraphVisitor extends AbstractVisitor {
} else { } else {
CodeWriter code = new CodeWriter(0); CodeWriter code = new CodeWriter(0);
MethodGen.makeFallbackInsns(code, mth, block.getInstructions(), false); MethodGen.makeFallbackInsns(code, mth, block.getInstructions(), false);
String str = escape(code.endl().toString()); String str = escape(code.newLine().toString());
if (str.startsWith(NL)) if (str.startsWith(NL))
str = str.substring(NL.length()); str = str.substring(NL.length());
return str; return str;
......
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