mirror of
https://github.com/skylot/jadx.git
synced 2024-11-26 22:20:50 +00:00
core: store line info, add fields and methods to api, refactoring
This commit is contained in:
parent
36da79feb8
commit
25b2c8fe5b
@ -65,7 +65,7 @@ public final class Decompiler {
|
||||
for (ClassNode classNode : root.getClasses()) {
|
||||
classes.add(new JavaClass(this, classNode));
|
||||
}
|
||||
return classes;
|
||||
return Collections.unmodifiableList(classes);
|
||||
}
|
||||
|
||||
public List<JavaPackage> getPackages() {
|
||||
@ -85,7 +85,7 @@ public final class Decompiler {
|
||||
packages.add(new JavaPackage(entry.getKey(), entry.getValue()));
|
||||
}
|
||||
Collections.sort(packages);
|
||||
return packages;
|
||||
return Collections.unmodifiableList(packages);
|
||||
}
|
||||
|
||||
public void saveAll() throws InterruptedException {
|
||||
|
@ -1,21 +1,67 @@
|
||||
package jadx.api;
|
||||
|
||||
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.FieldNode;
|
||||
import jadx.core.dex.nodes.MethodNode;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public final class JavaClass {
|
||||
|
||||
private final Decompiler decompiler;
|
||||
private final ClassNode cls;
|
||||
private final List<JavaClass> innerClasses;
|
||||
private final List<JavaField> fields;
|
||||
private final List<JavaMethod> methods;
|
||||
|
||||
JavaClass(Decompiler decompiler, ClassNode classNode) {
|
||||
this.decompiler = decompiler;
|
||||
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() {
|
||||
CodeWriter code = cls.getCode();
|
||||
if(code == null) {
|
||||
if (code == null) {
|
||||
decompiler.processClass(cls);
|
||||
code = cls.getCode();
|
||||
}
|
||||
@ -34,8 +80,28 @@ public final class JavaClass {
|
||||
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
|
||||
public String toString() {
|
||||
return getFullName();
|
||||
}
|
||||
|
||||
public int getDecompiledLine() {
|
||||
return cls.getDecompiledLine();
|
||||
}
|
||||
}
|
||||
|
25
jadx-core/src/main/java/jadx/api/JavaField.java
Normal file
25
jadx-core/src/main/java/jadx/api/JavaField.java
Normal file
@ -0,0 +1,25 @@
|
||||
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();
|
||||
}
|
||||
}
|
31
jadx-core/src/main/java/jadx/api/JavaMethod.java
Normal file
31
jadx-core/src/main/java/jadx/api/JavaMethod.java
Normal file
@ -0,0 +1,31 @@
|
||||
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 {
|
||||
|
||||
if (!"".equals(cls.getPackage())) {
|
||||
clsCode.add("package ").add(cls.getPackage()).add(';');
|
||||
clsCode.endl();
|
||||
clsCode.newLine();
|
||||
}
|
||||
|
||||
if (imports.size() != 0) {
|
||||
@ -71,7 +71,7 @@ public class ClassGen {
|
||||
for (String imp : sortImports) {
|
||||
clsCode.startLine("import ").add(imp).add(';');
|
||||
}
|
||||
clsCode.endl();
|
||||
clsCode.newLine();
|
||||
|
||||
sortImports.clear();
|
||||
imports.clear();
|
||||
@ -90,7 +90,7 @@ public class ClassGen {
|
||||
|
||||
makeClassDeclaration(code);
|
||||
makeClassBody(code);
|
||||
code.endl();
|
||||
code.newLine();
|
||||
}
|
||||
|
||||
public void makeClassDeclaration(CodeWriter clsCode) {
|
||||
@ -139,6 +139,8 @@ public class ClassGen {
|
||||
if (!cls.getInterfaces().isEmpty())
|
||||
clsCode.add(' ');
|
||||
}
|
||||
|
||||
clsCode.attachAnnotation(cls);
|
||||
}
|
||||
|
||||
public boolean makeGenericMap(CodeWriter code, Map<ArgType, List<ArgType>> gmap) {
|
||||
@ -178,13 +180,13 @@ public class ClassGen {
|
||||
CodeWriter fieldsCode = makeFields(clsCode, cls, cls.getFields());
|
||||
clsCode.add(fieldsCode);
|
||||
if (fieldsCode.notEmpty() && mthsCode.notEmpty())
|
||||
clsCode.endl();
|
||||
clsCode.newLine();
|
||||
|
||||
// insert inner classes code
|
||||
if (cls.getInnerClasses().size() != 0) {
|
||||
clsCode.add(makeInnerClasses(cls, clsCode.getIndent()));
|
||||
if (mthsCode.notEmpty())
|
||||
clsCode.endl();
|
||||
clsCode.newLine();
|
||||
}
|
||||
clsCode.add(mthsCode);
|
||||
clsCode.startLine('}');
|
||||
@ -239,7 +241,7 @@ public class ClassGen {
|
||||
}
|
||||
|
||||
if (it.hasNext())
|
||||
code.endl();
|
||||
code.newLine();
|
||||
}
|
||||
return code;
|
||||
}
|
||||
@ -278,7 +280,7 @@ public class ClassGen {
|
||||
code.startLine();
|
||||
|
||||
code.add(';');
|
||||
code.endl();
|
||||
code.newLine();
|
||||
}
|
||||
|
||||
for (FieldNode f : fields) {
|
||||
@ -297,6 +299,7 @@ public class ClassGen {
|
||||
}
|
||||
}
|
||||
code.add(';');
|
||||
code.attachAnnotation(f);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
@ -21,14 +21,8 @@ public class CodeGen extends AbstractVisitor {
|
||||
public boolean visit(ClassNode cls) throws CodegenException {
|
||||
ClassGen clsGen = new ClassGen(cls, null, isFallbackMode());
|
||||
CodeWriter clsCode = clsGen.makeClass();
|
||||
|
||||
clsCode.finish();
|
||||
cls.setCode(clsCode);
|
||||
|
||||
// String fileName = cls.getClassInfo().getFullPath() + ".java";
|
||||
// if (isFallbackMode())
|
||||
// fileName += ".jadx";
|
||||
// clsCode.save(dir, fileName);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1,9 +1,13 @@
|
||||
package jadx.core.codegen;
|
||||
|
||||
import jadx.core.dex.attributes.LineAttrNode;
|
||||
import jadx.core.utils.exceptions.JadxRuntimeException;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@ -19,6 +23,9 @@ public class CodeWriter {
|
||||
private String indentStr;
|
||||
private int indent;
|
||||
|
||||
private int line = 1;
|
||||
private Map<Object, Integer> annotations = Collections.emptyMap();
|
||||
|
||||
public CodeWriter() {
|
||||
this.indent = 0;
|
||||
this.indentStr = "";
|
||||
@ -29,32 +36,32 @@ public class CodeWriter {
|
||||
updateIndent();
|
||||
}
|
||||
|
||||
public CodeWriter startLine(String str) {
|
||||
buf.append(NL);
|
||||
public CodeWriter startLine() {
|
||||
addLine();
|
||||
buf.append(indentStr);
|
||||
buf.append(str);
|
||||
return this;
|
||||
}
|
||||
|
||||
public CodeWriter startLine(char c) {
|
||||
buf.append(NL);
|
||||
addLine();
|
||||
buf.append(indentStr);
|
||||
buf.append(c);
|
||||
return this;
|
||||
}
|
||||
|
||||
public CodeWriter startLine(int ind, String str) {
|
||||
buf.append(NL);
|
||||
public CodeWriter startLine(String str) {
|
||||
addLine();
|
||||
buf.append(indentStr);
|
||||
for (int i = 0; i < ind; i++)
|
||||
buf.append(INDENT);
|
||||
buf.append(str);
|
||||
return this;
|
||||
}
|
||||
|
||||
public CodeWriter startLine() {
|
||||
buf.append(NL);
|
||||
public CodeWriter startLine(int ind, String str) {
|
||||
addLine();
|
||||
buf.append(indentStr);
|
||||
for (int i = 0; i < ind; i++)
|
||||
buf.append(INDENT);
|
||||
buf.append(str);
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -68,17 +75,47 @@ public class CodeWriter {
|
||||
return this;
|
||||
}
|
||||
|
||||
public CodeWriter add(CodeWriter mthsCode) {
|
||||
buf.append(mthsCode.toString());
|
||||
public CodeWriter add(CodeWriter code) {
|
||||
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;
|
||||
}
|
||||
|
||||
public CodeWriter endl() {
|
||||
public CodeWriter newLine() {
|
||||
addLine();
|
||||
return this;
|
||||
}
|
||||
|
||||
private void addLine() {
|
||||
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;
|
||||
}
|
||||
|
||||
private static final String[] INDENT_CACHE = new String[] {
|
||||
private static final String[] INDENT_CACHE = new String[]{
|
||||
"",
|
||||
INDENT,
|
||||
INDENT + INDENT,
|
||||
@ -126,6 +163,18 @@ public class CodeWriter {
|
||||
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) {
|
||||
if (str.startsWith(NL)) {
|
||||
return str.substring(NL.length());
|
||||
|
@ -152,13 +152,16 @@ public class InsnGen {
|
||||
} else {
|
||||
CodeWriter body = new CodeWriter(code.getIndent());
|
||||
makeInsnBody(body, insn, state);
|
||||
if (state.contains(InsnGenState.SKIP))
|
||||
if (state.contains(InsnGenState.SKIP)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
code.startLine();
|
||||
if (insn.getSourceLine() != 0) {
|
||||
code.attachAnnotation(insn.getSourceLine());
|
||||
}
|
||||
if (insn.getResult() != null && !state.contains(InsnGenState.NO_RESULT))
|
||||
code.startLine(assignVar(insn)).add(" = ");
|
||||
else
|
||||
code.startLine();
|
||||
code.add(assignVar(insn)).add(" = ");
|
||||
|
||||
code.add(body);
|
||||
|
||||
|
@ -108,6 +108,7 @@ public class MethodGen {
|
||||
|
||||
annotationGen.addThrows(mth, code);
|
||||
}
|
||||
code.attachAnnotation(mth);
|
||||
}
|
||||
|
||||
public CodeWriter makeArguments(List<RegisterArg> args) {
|
||||
@ -225,7 +226,7 @@ public class MethodGen {
|
||||
code.startLine("// jadx: method processing error");
|
||||
Throwable cause = err.getCause();
|
||||
if (cause != null) {
|
||||
code.endl();
|
||||
code.newLine();
|
||||
code.add("/*");
|
||||
code.startLine("Error: ").add(Utils.getStackTrace(cause));
|
||||
code.add("*/");
|
||||
|
@ -165,14 +165,14 @@ public class RegionGen extends InsnGen {
|
||||
case AND:
|
||||
case OR:
|
||||
String mode = condition.getMode() == IfCondition.MODE.AND ? " && " : " || ";
|
||||
CodeWriter cw = new CodeWriter();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (IfCondition arg : condition.getArgs()) {
|
||||
if (cw.notEmpty()) {
|
||||
cw.add(mode);
|
||||
if (sb.length() != 0) {
|
||||
sb.append(mode);
|
||||
}
|
||||
cw.add('(').add(makeCondition(arg)).add(')');
|
||||
sb.append('(').append(makeCondition(arg)).append(')');
|
||||
}
|
||||
return cw.toString();
|
||||
return sb.toString();
|
||||
default:
|
||||
return "??" + condition.toString();
|
||||
}
|
||||
|
@ -0,0 +1,24 @@
|
||||
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 {
|
||||
return accFlags;
|
||||
}
|
||||
|
||||
public AFType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public String makeString() {
|
||||
StringBuilder code = new StringBuilder();
|
||||
if (isPublic())
|
||||
|
@ -39,6 +39,26 @@ public class FieldInfo {
|
||||
return declClass;
|
||||
}
|
||||
|
||||
@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() {
|
||||
return declClass + "." + name + " " + type;
|
||||
|
@ -2,8 +2,8 @@ package jadx.core.dex.nodes;
|
||||
|
||||
import jadx.core.Consts;
|
||||
import jadx.core.codegen.CodeWriter;
|
||||
import jadx.core.dex.attributes.AttrNode;
|
||||
import jadx.core.dex.attributes.AttributeType;
|
||||
import jadx.core.dex.attributes.LineAttrNode;
|
||||
import jadx.core.dex.attributes.SourceFileAttr;
|
||||
import jadx.core.dex.attributes.annotations.Annotation;
|
||||
import jadx.core.dex.info.AccessInfo;
|
||||
@ -32,7 +32,7 @@ import com.android.dx.io.ClassData.Field;
|
||||
import com.android.dx.io.ClassData.Method;
|
||||
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 final DexNode dex;
|
||||
|
@ -1,6 +1,6 @@
|
||||
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.AFType;
|
||||
import jadx.core.dex.info.FieldInfo;
|
||||
@ -8,7 +8,7 @@ import jadx.core.dex.instructions.args.ArgType;
|
||||
|
||||
import com.android.dx.io.ClassData.Field;
|
||||
|
||||
public class FieldNode extends AttrNode {
|
||||
public class FieldNode extends LineAttrNode {
|
||||
|
||||
private final FieldInfo fieldInfo;
|
||||
private final AccessInfo accFlags;
|
||||
@ -41,6 +41,19 @@ public class FieldNode extends AttrNode {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@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() {
|
||||
return fieldInfo.getDeclClass() + "." + fieldInfo.getName() + " " + type;
|
||||
|
@ -1,6 +1,6 @@
|
||||
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.args.ArgType;
|
||||
import jadx.core.dex.instructions.args.InsnArg;
|
||||
@ -15,7 +15,7 @@ import java.util.List;
|
||||
|
||||
import com.android.dx.io.instructions.DecodedInstruction;
|
||||
|
||||
public class InsnNode extends AttrNode {
|
||||
public class InsnNode extends LineAttrNode {
|
||||
|
||||
protected final InsnType insnType;
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
package jadx.core.dex.nodes;
|
||||
|
||||
import jadx.core.Consts;
|
||||
import jadx.core.dex.attributes.AttrNode;
|
||||
import jadx.core.dex.attributes.AttributeFlag;
|
||||
import jadx.core.dex.attributes.JumpAttribute;
|
||||
import jadx.core.dex.attributes.LineAttrNode;
|
||||
import jadx.core.dex.attributes.LoopAttr;
|
||||
import jadx.core.dex.attributes.annotations.Annotation;
|
||||
import jadx.core.dex.info.AccessInfo;
|
||||
@ -40,7 +40,7 @@ import com.android.dx.io.Code;
|
||||
import com.android.dx.io.Code.CatchHandler;
|
||||
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 final MethodInfo mthInfo;
|
||||
@ -101,8 +101,17 @@ public class MethodNode extends AttrNode implements ILoadable {
|
||||
initTryCatches(mthCode, insnByOffset);
|
||||
initJumps(insnByOffset);
|
||||
|
||||
if (mthCode.getDebugInfoOffset() > 0) {
|
||||
(new DebugInfoParser(this, mthCode.getDebugInfoOffset(), insnByOffset)).process();
|
||||
int debugInfoOffset = mthCode.getDebugInfoOffset();
|
||||
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) {
|
||||
throw new DecodeException(this, "Load method exception", e);
|
||||
@ -414,7 +423,7 @@ public class MethodNode extends AttrNode implements ILoadable {
|
||||
}
|
||||
|
||||
public void registerLoop(LoopAttr loop) {
|
||||
if(loops.isEmpty()) {
|
||||
if (loops.isEmpty()) {
|
||||
loops = new ArrayList<LoopAttr>(5);
|
||||
}
|
||||
loops.add(loop);
|
||||
@ -422,7 +431,7 @@ public class MethodNode extends AttrNode implements ILoadable {
|
||||
|
||||
public LoopAttr getLoopForBlock(BlockNode block) {
|
||||
for (LoopAttr loop : loops) {
|
||||
if(loop.getLoopBlocks().contains(block))
|
||||
if (loop.getLoopBlocks().contains(block))
|
||||
return loop;
|
||||
}
|
||||
return null;
|
||||
@ -477,6 +486,19 @@ public class MethodNode extends AttrNode implements ILoadable {
|
||||
return mthInfo;
|
||||
}
|
||||
|
||||
@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() {
|
||||
return retType
|
||||
|
@ -49,9 +49,8 @@ public class DebugInfoParser {
|
||||
|
||||
public void process() throws DecodeException {
|
||||
int addr = 0;
|
||||
int line;
|
||||
int line = section.readUleb128();
|
||||
|
||||
line = section.readUleb128();
|
||||
int param_size = section.readUleb128(); // exclude 'this'
|
||||
List<RegisterArg> mthArgs = mth.getArguments(false);
|
||||
assert param_size == mthArgs.size();
|
||||
@ -70,14 +69,14 @@ public class DebugInfoParser {
|
||||
activeRegisters[rn] = arg;
|
||||
}
|
||||
|
||||
addrChange(-1, 1); // process '0' instruction
|
||||
addrChange(-1, 1, line); // process '0' instruction
|
||||
|
||||
int c = section.readByte() & 0xFF;
|
||||
while (c != DBG_END_SEQUENCE) {
|
||||
switch (c) {
|
||||
case DBG_ADVANCE_PC: {
|
||||
int addrInc = section.readUleb128();
|
||||
addr = addrChange(addr, addrInc);
|
||||
addr = addrChange(addr, addrInc, line);
|
||||
break;
|
||||
}
|
||||
case DBG_ADVANCE_LINE: {
|
||||
@ -141,14 +140,13 @@ public class DebugInfoParser {
|
||||
int adjusted_opcode = c - DBG_FIRST_SPECIAL;
|
||||
line += DBG_LINE_BASE + (adjusted_opcode % DBG_LINE_RANGE);
|
||||
int addrInc = (adjusted_opcode / DBG_LINE_RANGE);
|
||||
addr = addrChange(addr, addrInc);
|
||||
addr = addrChange(addr, addrInc, line);
|
||||
} else {
|
||||
throw new DecodeException("Unknown debug insn code: " + c);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
c = section.readByte() & 0xFF;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
for (int i = addr + 1; i <= newAddr; i++) {
|
||||
InsnNode insn = insnByOffset[i];
|
||||
if (insn == null)
|
||||
continue;
|
||||
|
||||
insn.setSourceLine(line);
|
||||
for (InsnArg arg : insn.getArguments())
|
||||
if (arg.isRegister()) {
|
||||
activeRegisters[arg.getRegNum()] = arg;
|
||||
|
@ -168,7 +168,7 @@ public class DotGraphVisitor extends AbstractVisitor {
|
||||
} else {
|
||||
CodeWriter code = new CodeWriter(0);
|
||||
MethodGen.makeFallbackInsns(code, mth, block.getInstructions(), false);
|
||||
String str = escape(code.endl().toString());
|
||||
String str = escape(code.newLine().toString());
|
||||
if (str.startsWith(NL))
|
||||
str = str.substring(NL.length());
|
||||
return str;
|
||||
|
Loading…
Reference in New Issue
Block a user