From 8da0ba82e431bc2cb58588a62cc2cec88f4e2f5c Mon Sep 17 00:00:00 2001 From: Skylot Date: Sun, 16 Jun 2013 17:04:26 +0400 Subject: [PATCH] Save source file name, move constant strings --- src/main/java/jadx/Consts.java | 6 +++++ src/main/java/jadx/codegen/AnnotationGen.java | 6 ++--- src/main/java/jadx/codegen/ClassGen.java | 14 +++++++++++ src/main/java/jadx/codegen/CodeWriter.java | 11 +++++---- .../jadx/dex/attributes/AttributeType.java | 13 +++++----- .../jadx/dex/attributes/AttributesList.java | 2 +- .../jadx/dex/attributes/BlockRegState.java | 2 +- .../jadx/dex/attributes/SourceFileAttr.java | 24 +++++++++++++++++++ src/main/java/jadx/dex/info/ClassInfo.java | 6 ++--- src/main/java/jadx/dex/nodes/ClassNode.java | 12 +++++++++- .../dex/nodes/parser/DebugInfoParser.java | 14 +++++++---- 11 files changed, 84 insertions(+), 26 deletions(-) create mode 100644 src/main/java/jadx/dex/attributes/SourceFileAttr.java diff --git a/src/main/java/jadx/Consts.java b/src/main/java/jadx/Consts.java index c119e0db..acf8ea0a 100644 --- a/src/main/java/jadx/Consts.java +++ b/src/main/java/jadx/Consts.java @@ -15,5 +15,11 @@ public class Consts { public static final String CLASS_STRING_BUILDER = "java.lang.StringBuilder"; + public static final String DALVIK_ANNOTATION_PKG = "dalvik.annotation."; public static final String DALVIK_SIGNATURE = "dalvik.annotation.Signature"; + public static final String DALVIK_INNER_CLASS = "dalvik.annotation.InnerClass"; + public static final String DALVIK_THROWS = "dalvik.annotation.Throws"; + public static final String DALVIK_ANNOTATION_DEFAULT = "dalvik.annotation.AnnotationDefault"; + + public static final String DEFAULT_PACKAGE_NAME = "defpackage"; } diff --git a/src/main/java/jadx/codegen/AnnotationGen.java b/src/main/java/jadx/codegen/AnnotationGen.java index fb998e4d..fcb0597a 100644 --- a/src/main/java/jadx/codegen/AnnotationGen.java +++ b/src/main/java/jadx/codegen/AnnotationGen.java @@ -59,7 +59,7 @@ public class AnnotationGen { for (Annotation a : aList.getAll()) { String aCls = a.getAnnotationClass(); - if (aCls.startsWith("dalvik.annotation.")) { + if (aCls.startsWith(Consts.DALVIK_ANNOTATION_PKG)) { // skip if (Consts.DEBUG) { code.startLine("// " + a); @@ -97,7 +97,7 @@ public class AnnotationGen { @SuppressWarnings("unchecked") public void addThrows(MethodNode mth, CodeWriter code) { - Annotation an = mth.getAttributes().getAnnotation("dalvik.annotation.Throws"); + Annotation an = mth.getAttributes().getAnnotation(Consts.DALVIK_THROWS); if (an != null) { Object exs = an.getDefaultValue(); code.add(" throws "); @@ -111,7 +111,7 @@ public class AnnotationGen { } public Object getAnnotationDefaultValue(String name) { - Annotation an = cls.getAttributes().getAnnotation("dalvik.annotation.AnnotationDefault"); + Annotation an = cls.getAttributes().getAnnotation(Consts.DALVIK_ANNOTATION_DEFAULT); if (an != null) { Annotation defAnnotation = (Annotation) an.getDefaultValue(); return defAnnotation.getValues().get(name); diff --git a/src/main/java/jadx/codegen/ClassGen.java b/src/main/java/jadx/codegen/ClassGen.java index 1507ed7d..5d69861e 100644 --- a/src/main/java/jadx/codegen/ClassGen.java +++ b/src/main/java/jadx/codegen/ClassGen.java @@ -1,10 +1,13 @@ package jadx.codegen; import jadx.Consts; +import jadx.dex.attributes.AttrNode; import jadx.dex.attributes.AttributeFlag; import jadx.dex.attributes.AttributeType; import jadx.dex.attributes.EnumClassAttr; import jadx.dex.attributes.EnumClassAttr.EnumField; +import jadx.dex.attributes.IAttribute; +import jadx.dex.attributes.SourceFileAttr; import jadx.dex.info.AccessInfo; import jadx.dex.info.ClassInfo; import jadx.dex.instructions.args.ArgType; @@ -169,6 +172,8 @@ public class ClassGen { public void makeClassBody(CodeWriter clsCode) throws CodegenException { clsCode.add('{'); + insertSourceFileInfo(clsCode, cls); + CodeWriter mthsCode = makeMethods(clsCode, cls.getMethods()); CodeWriter fieldsCode = makeFields(clsCode, cls, cls.getFields()); clsCode.add(fieldsCode); @@ -224,6 +229,7 @@ public class ClassGen { MethodGen mthGen = new MethodGen(this, mth); mthGen.addDefinition(code); code.add(" {"); + insertSourceFileInfo(code, mth); code.add(mthGen.makeInstructions(code.getIndent())); code.startLine('}'); } @@ -363,6 +369,14 @@ public class ClassGen { return false; } + private void insertSourceFileInfo(CodeWriter code, AttrNode node) { + IAttribute sourceFileAttr = node.getAttributes().get(AttributeType.SOURCE_FILE); + if(sourceFileAttr != null) { + code.startLine(1, "// compiled from: "); + code.add(((SourceFileAttr)sourceFileAttr).getFileName()); + } + } + public Set getImports() { return imports; } diff --git a/src/main/java/jadx/codegen/CodeWriter.java b/src/main/java/jadx/codegen/CodeWriter.java index b1abab90..319b1dfa 100644 --- a/src/main/java/jadx/codegen/CodeWriter.java +++ b/src/main/java/jadx/codegen/CodeWriter.java @@ -78,7 +78,7 @@ public class CodeWriter { return this; } - private static final String[] indentCache = new String[] { + private static final String[] INDENT_CACHE = new String[] { "", INDENT, INDENT + INDENT, @@ -88,11 +88,12 @@ public class CodeWriter { }; private void updateIndent() { - if (indent < 6) { - this.indentStr = indentCache[indent]; + int curIndent = indent; + if (curIndent < 6) { + this.indentStr = INDENT_CACHE[curIndent]; } else { - StringBuilder s = new StringBuilder(indent * INDENT.length()); - for (int i = 0; i < indent; i++) { + StringBuilder s = new StringBuilder(curIndent * INDENT.length()); + for (int i = 0; i < curIndent; i++) { s.append(INDENT); } this.indentStr = s.toString(); diff --git a/src/main/java/jadx/dex/attributes/AttributeType.java b/src/main/java/jadx/dex/attributes/AttributeType.java index 33e19a78..4717e4c3 100644 --- a/src/main/java/jadx/dex/attributes/AttributeType.java +++ b/src/main/java/jadx/dex/attributes/AttributeType.java @@ -1,33 +1,32 @@ package jadx.dex.attributes; public enum AttributeType { - // TODO? add attribute target (insn, block, method, field, class) - // instructions + /* Multi attributes */ + JUMP(false), - // blocks LOOP(false), CATCH_BLOCK(false), + /* Uniq attributes */ + EXC_HANDLER(true), SPLITTER_BLOCK(true), FORCE_RETURN(true), - // fields FIELD_VALUE(true), - // methods JADX_ERROR(true), METHOD_INLINE(true), - // classes ENUM_CLASS(true), - // any ANNOTATION_LIST(true), ANNOTATION_MTH_PARAMETERS(true), + SOURCE_FILE(true), + DECLARE_VARIABLE(true); private static final int notUniqCount; diff --git a/src/main/java/jadx/dex/attributes/AttributesList.java b/src/main/java/jadx/dex/attributes/AttributesList.java index 0cf0d942..825ff0c7 100644 --- a/src/main/java/jadx/dex/attributes/AttributesList.java +++ b/src/main/java/jadx/dex/attributes/AttributesList.java @@ -20,7 +20,7 @@ import java.util.Set; * 2. attribute - class instance associated for attribute type, * only one attached to node for unique attributes, multiple for others */ -public class AttributesList { +public final class AttributesList { private final Set flags; private final Map uniqAttr; diff --git a/src/main/java/jadx/dex/attributes/BlockRegState.java b/src/main/java/jadx/dex/attributes/BlockRegState.java index 61c14713..35729c56 100644 --- a/src/main/java/jadx/dex/attributes/BlockRegState.java +++ b/src/main/java/jadx/dex/attributes/BlockRegState.java @@ -4,7 +4,7 @@ import jadx.dex.instructions.args.RegisterArg; import jadx.dex.instructions.args.TypedVar; import jadx.dex.nodes.MethodNode; -public class BlockRegState { +public final class BlockRegState { private final RegisterArg[] regs; diff --git a/src/main/java/jadx/dex/attributes/SourceFileAttr.java b/src/main/java/jadx/dex/attributes/SourceFileAttr.java new file mode 100644 index 00000000..7fa05242 --- /dev/null +++ b/src/main/java/jadx/dex/attributes/SourceFileAttr.java @@ -0,0 +1,24 @@ +package jadx.dex.attributes; + +public class SourceFileAttr implements IAttribute { + + private final String fileName; + + public SourceFileAttr(String fileName) { + this.fileName = fileName; + } + + public String getFileName() { + return fileName; + } + + @Override + public AttributeType getType() { + return AttributeType.SOURCE_FILE; + } + + @Override + public String toString() { + return "SOURCE:" + fileName; + } +} diff --git a/src/main/java/jadx/dex/info/ClassInfo.java b/src/main/java/jadx/dex/info/ClassInfo.java index 91712c2d..9f9d08ba 100644 --- a/src/main/java/jadx/dex/info/ClassInfo.java +++ b/src/main/java/jadx/dex/info/ClassInfo.java @@ -1,5 +1,6 @@ package jadx.dex.info; +import jadx.Consts; import jadx.deobf.NameMapper; import jadx.dex.instructions.args.ArgType; import jadx.dex.nodes.DexNode; @@ -11,7 +12,6 @@ import java.util.WeakHashMap; public final class ClassInfo { private static final Map CLASSINFO_CACHE = new WeakHashMap(); - private static final String DEFAULT_PACKAGE_NAME = "defpackage"; public static ClassInfo fromDex(DexNode dex, int clsIndex) { if (clsIndex == DexNode.NO_INDEX) @@ -62,7 +62,7 @@ public final class ClassInfo { int dot = fullObjectName.lastIndexOf('.'); if (dot == -1) { // rename default package if it used from class with package (often for obfuscated apps), - pkg = DEFAULT_PACKAGE_NAME; + pkg = Consts.DEFAULT_PACKAGE_NAME; name = fullObjectName; } else { pkg = fullObjectName.substring(0, dot); @@ -110,7 +110,7 @@ public final class ClassInfo { } public boolean isPackageDefault() { - return pkg.isEmpty() || pkg.equals(DEFAULT_PACKAGE_NAME); + return pkg.isEmpty() || pkg.equals(Consts.DEFAULT_PACKAGE_NAME); } public String getNameWithoutPackage() { diff --git a/src/main/java/jadx/dex/nodes/ClassNode.java b/src/main/java/jadx/dex/nodes/ClassNode.java index d41f68f8..efe2c984 100644 --- a/src/main/java/jadx/dex/nodes/ClassNode.java +++ b/src/main/java/jadx/dex/nodes/ClassNode.java @@ -3,6 +3,7 @@ package jadx.dex.nodes; import jadx.Consts; import jadx.dex.attributes.AttrNode; import jadx.dex.attributes.AttributeType; +import jadx.dex.attributes.SourceFileAttr; import jadx.dex.attributes.annotations.Annotation; import jadx.dex.info.AccessInfo; import jadx.dex.info.AccessInfo.AFType; @@ -85,8 +86,17 @@ public class ClassNode extends AttrNode implements ILoadable { parseClassSignature(); setFieldsTypesFromSignature(); + int sfIdx = cls.getSourceFileIndex(); + if(sfIdx != DexNode.NO_INDEX) { + String fileName = dex.getString(sfIdx); + if(!this.getFullName().contains(fileName.replace(".java", ""))) { + this.getAttributes().add(new SourceFileAttr(fileName)); + LOG.info("TODO: move class {} to {} file", this, fileName); + } + } + int accFlagsValue; - Annotation a = getAttributes().getAnnotation("dalvik.annotation.InnerClass"); + Annotation a = getAttributes().getAnnotation(Consts.DALVIK_INNER_CLASS); if (a != null) accFlagsValue = (Integer) a.getValues().get("accessFlags"); else diff --git a/src/main/java/jadx/dex/nodes/parser/DebugInfoParser.java b/src/main/java/jadx/dex/nodes/parser/DebugInfoParser.java index 8a624724..152f8cf0 100644 --- a/src/main/java/jadx/dex/nodes/parser/DebugInfoParser.java +++ b/src/main/java/jadx/dex/nodes/parser/DebugInfoParser.java @@ -1,5 +1,6 @@ package jadx.dex.nodes.parser; +import jadx.dex.attributes.SourceFileAttr; import jadx.dex.info.LocalVarInfo; import jadx.dex.instructions.args.InsnArg; import jadx.dex.instructions.args.RegisterArg; @@ -50,7 +51,6 @@ public class DebugInfoParser { public void process() throws DecodeException { int addr = 0; int line; - // String source_file; line = section.readUleb128(); int param_size = section.readUleb128(); // exclude 'this' @@ -124,14 +124,18 @@ public class DebugInfoParser { } case DBG_SET_PROLOGUE_END: - break; case DBG_SET_EPILOGUE_BEGIN: + // do nothing break; - case DBG_SET_FILE: - section.readUleb128(); - // source_file = dex.getString(idx); + case DBG_SET_FILE: { + int idx = section.readUleb128() - 1; + if (idx != DexNode.NO_INDEX) { + String sourceFile = dex.getString(idx); + mth.getAttributes().add(new SourceFileAttr(sourceFile)); + } break; + } default: { if (c >= DBG_FIRST_SPECIAL) { -- GitLab