From f2aa4cd10ba50dc8e1554a503a5b3254b86268a3 Mon Sep 17 00:00:00 2001 From: Skylot Date: Thu, 5 Jun 2014 18:39:06 +0400 Subject: [PATCH] core: make better variables naming --- build.gradle | 14 +- jadx-core/src/main/java/jadx/core/Jadx.java | 2 + .../main/java/jadx/core/codegen/InsnGen.java | 4 +- .../java/jadx/core/codegen/MethodGen.java | 108 +++----------- .../main/java/jadx/core/codegen/NameGen.java | 134 ++++++++++++++++++ .../java/jadx/core/codegen/RegionGen.java | 2 +- .../core/dex/instructions/args/InsnArg.java | 4 +- .../instructions/args/MthParameterArg.java | 27 ++++ .../dex/instructions/args/RegisterArg.java | 57 ++++---- .../core/dex/instructions/args/SSAVar.java | 43 +++--- .../core/dex/instructions/args/Typed.java | 8 -- .../core/dex/instructions/args/VarName.java | 18 +++ .../java/jadx/core/dex/nodes/MethodNode.java | 67 ++++----- .../dex/nodes/parser/DebugInfoParser.java | 13 +- .../jadx/core/dex/nodes/parser/LocalVar.java | 28 +++- .../core/dex/visitors/BlockMakerVisitor.java | 13 +- .../core/dex/visitors/DebugInfoVisitor.java | 43 ++++++ .../core/dex/visitors/DotGraphVisitor.java | 4 +- .../dex/visitors/FallbackModeVisitor.java | 3 + .../visitors/regions/ProcessVariables.java | 28 ++++ .../dex/visitors/ssa/EliminatePhiNodes.java | 48 ------- .../core/dex/visitors/ssa/SSATransform.java | 2 +- .../visitors/typeinference/TypeInference.java | 2 +- .../tests/internal/inline/TestInline2.java | 6 +- .../main/java/jadx/samples/AbstractTest.java | 3 +- .../java/jadx/samples/TestAnnotations.java | 2 +- .../src/main/java/jadx/samples/TestCF.java | 16 ++- .../src/main/java/jadx/samples/TestCF2.java | 8 +- .../main/java/jadx/samples/TestDeadCode.java | 3 +- .../main/java/jadx/samples/TestGenerics.java | 11 +- .../src/main/java/jadx/samples/TestInner.java | 2 + .../main/java/jadx/samples/TestInner2.java | 2 +- .../main/java/jadx/samples/TestInvoke.java | 17 ++- .../main/java/jadx/samples/TestSwitch.java | 8 +- .../main/java/jadx/samples/TestTryCatch.java | 29 ++-- .../java/jadx/samples/TestTypeResolver2.java | 2 +- settings.gradle | 2 + 37 files changed, 476 insertions(+), 307 deletions(-) create mode 100644 jadx-core/src/main/java/jadx/core/codegen/NameGen.java create mode 100644 jadx-core/src/main/java/jadx/core/dex/instructions/args/VarName.java create mode 100644 jadx-core/src/main/java/jadx/core/dex/visitors/DebugInfoVisitor.java diff --git a/build.gradle b/build.gradle index a44473c87..d044f8090 100644 --- a/build.gradle +++ b/build.gradle @@ -9,16 +9,14 @@ subprojects { apply plugin: 'jacoco' apply plugin: 'coveralls' - sourceCompatibility = 1.6 - targetCompatibility = 1.6 - version = jadxVersion - gradle.projectsEvaluated { - tasks.withType(Compile) { - if (!"$it".contains(':jadx-samples:')) { - options.compilerArgs << '-Xlint' << '-Xlint:unchecked' << '-Xlint:deprecation' - } + tasks.withType(JavaCompile) { + sourceCompatibility = JavaVersion.VERSION_1_6 + targetCompatibility = JavaVersion.VERSION_1_6 + + if (!"$it".contains(':jadx-samples:')) { + options.compilerArgs << '-Xlint' << '-Xlint:unchecked' << '-Xlint:deprecation' } } diff --git a/jadx-core/src/main/java/jadx/core/Jadx.java b/jadx-core/src/main/java/jadx/core/Jadx.java index 8a3717d1a..b896d6136 100644 --- a/jadx-core/src/main/java/jadx/core/Jadx.java +++ b/jadx-core/src/main/java/jadx/core/Jadx.java @@ -6,6 +6,7 @@ import jadx.core.dex.visitors.BlockMakerVisitor; import jadx.core.dex.visitors.ClassModifier; import jadx.core.dex.visitors.CodeShrinker; import jadx.core.dex.visitors.ConstInlinerVisitor; +import jadx.core.dex.visitors.DebugInfoVisitor; import jadx.core.dex.visitors.DotGraphVisitor; import jadx.core.dex.visitors.EnumVisitor; import jadx.core.dex.visitors.FallbackModeVisitor; @@ -54,6 +55,7 @@ public class Jadx { } else { passes.add(new BlockMakerVisitor()); passes.add(new SSATransform()); + passes.add(new DebugInfoVisitor()); passes.add(new TypeInference()); passes.add(new ConstInlinerVisitor()); diff --git a/jadx-core/src/main/java/jadx/core/codegen/InsnGen.java b/jadx-core/src/main/java/jadx/core/codegen/InsnGen.java index ed2510c88..87e991cd6 100644 --- a/jadx-core/src/main/java/jadx/core/codegen/InsnGen.java +++ b/jadx-core/src/main/java/jadx/core/codegen/InsnGen.java @@ -88,7 +88,7 @@ public class InsnGen { public void addArg(CodeWriter code, InsnArg arg, boolean wrap) throws CodegenException { if (arg.isRegister()) { - code.add(mgen.makeArgName((RegisterArg) arg)); + code.add(mgen.getNameGen().useArg((RegisterArg) arg)); } else if (arg.isLiteral()) { code.add(lit((LiteralArg) arg)); } else if (arg.isInsnWrap()) { @@ -120,7 +120,7 @@ public class InsnGen { public void declareVar(CodeWriter code, RegisterArg arg) { useType(code, arg.getType()); code.add(' '); - code.add(mgen.assignArg(arg)); + code.add(mgen.getNameGen().assignArg(arg)); } private static String lit(LiteralArg arg) { diff --git a/jadx-core/src/main/java/jadx/core/codegen/MethodGen.java b/jadx-core/src/main/java/jadx/core/codegen/MethodGen.java index 7d5684dfd..db103706b 100644 --- a/jadx-core/src/main/java/jadx/core/codegen/MethodGen.java +++ b/jadx-core/src/main/java/jadx/core/codegen/MethodGen.java @@ -1,13 +1,11 @@ package jadx.core.codegen; -import jadx.core.Consts; import jadx.core.dex.attributes.AFlag; import jadx.core.dex.attributes.AType; import jadx.core.dex.attributes.annotations.MethodParameters; import jadx.core.dex.attributes.nodes.JadxErrorAttr; import jadx.core.dex.info.AccessInfo; import jadx.core.dex.instructions.args.ArgType; -import jadx.core.dex.instructions.args.NamedArg; import jadx.core.dex.instructions.args.RegisterArg; import jadx.core.dex.nodes.InsnNode; import jadx.core.dex.nodes.MethodNode; @@ -21,10 +19,8 @@ import jadx.core.utils.Utils; import jadx.core.utils.exceptions.CodegenException; import jadx.core.utils.exceptions.DecodeException; -import java.util.HashSet; import java.util.Iterator; import java.util.List; -import java.util.Set; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -36,27 +32,24 @@ public class MethodGen { private final MethodNode mth; private final ClassGen classGen; - private final boolean fallback; private final AnnotationGen annotationGen; - - private final Set varNames = new HashSet(); + private final NameGen nameGen; public MethodGen(ClassGen classGen, MethodNode mth) { this.mth = mth; this.classGen = classGen; - this.fallback = classGen.isFallbackMode(); this.annotationGen = classGen.getAnnotationGen(); - - List args = mth.getArguments(true); - for (RegisterArg arg : args) { - varNames.add(makeArgName(arg)); - } + this.nameGen = new NameGen(classGen.isFallbackMode()); } public ClassGen getClassGen() { return classGen; } + public NameGen getNameGen() { + return nameGen; + } + public MethodNode getMethodNode() { return mth; } @@ -124,9 +117,7 @@ public class MethodGen { } private void addMethodArguments(CodeWriter argsCode, List args) { - MethodParameters paramsAnnotation = - mth.get(AType.ANNOTATION_MTH_PARAMETERS); - + MethodParameters paramsAnnotation = mth.get(AType.ANNOTATION_MTH_PARAMETERS); int i = 0; for (Iterator it = args.iterator(); it.hasNext(); ) { RegisterArg arg = it.next(); @@ -150,7 +141,7 @@ public class MethodGen { classGen.useType(argsCode, arg.getType()); } argsCode.add(' '); - argsCode.add(makeArgName(arg)); + argsCode.add(nameGen.assignArg(arg)); i++; if (it.hasNext()) { @@ -159,74 +150,6 @@ public class MethodGen { } } - /** - * Make variable name for register, - * Name contains register number and - * variable type or name (if debug info available) - */ - public String makeArgName(RegisterArg arg) { - String name = arg.getName(); - String base = "r" + arg.getRegNum(); - if (fallback) { - if (name != null) { - return base + "_" + name; - } - return base; - } else { - if (name != null) { - if (Consts.DEBUG) { - return base + "_" + name; - } - return name; - } else { - ArgType type = arg.getType(); - if (type.isPrimitive()) { - return base + type.getPrimitiveType().getShortName().toLowerCase(); - } else { - // TODO: prettify variable name - return base + "_" + Utils.escape(type.toString()); - } - } - } - } - - /** - * Put variable declaration and return variable name (used for assignments) - * - * @param arg register variable - * @return variable name - */ - public String assignArg(RegisterArg arg) { - String name = makeArgName(arg); - if (varNames.add(name) || fallback) { - return name; - } - name = getUniqVarName(name); - arg.getSVar().setVariableName(name); - return name; - } - - public String assignNamedArg(NamedArg arg) { - String name = arg.getName(); - if (varNames.add(name) || fallback) { - return name; - } - name = getUniqVarName(name); - arg.setName(name); - return name; - } - - private String getUniqVarName(String name) { - String r; - int i = 2; - do { - r = name + "_" + i; - i++; - } while (varNames.contains(r)); - varNames.add(r); - return r; - } - public void addInstructions(CodeWriter code) throws CodegenException { if (mth.contains(AType.JADX_ERROR)) { code.startLine("throw new UnsupportedOperationException(\"Method not decompiled: "); @@ -283,20 +206,23 @@ public class MethodGen { return; } } - List insns = mth.getInstructions(); - if (insns == null) { + InsnNode[] insnArr = mth.getInstructions(); + if (insnArr == null) { code.startLine("// Can't load method instructions."); return; } if (mth.getThisArg() != null) { - code.startLine(getFallbackMethodGen(mth).makeArgName(mth.getThisArg())).add(" = this;"); + code.startLine(getFallbackMethodGen(mth).nameGen.useArg(mth.getThisArg())).add(" = this;"); } - addFallbackInsns(code, mth, insns, true); + addFallbackInsns(code, mth, insnArr, true); } - public static void addFallbackInsns(CodeWriter code, MethodNode mth, List insns, boolean addLabels) { + public static void addFallbackInsns(CodeWriter code, MethodNode mth, InsnNode[] insnArr, boolean addLabels) { InsnGen insnGen = new InsnGen(getFallbackMethodGen(mth), true); - for (InsnNode insn : insns) { + for (InsnNode insn : insnArr) { + if (insn == null) { + continue; + } if (addLabels) { if (insn.contains(AType.JUMP) || insn.contains(AType.EXC_HANDLER)) { diff --git a/jadx-core/src/main/java/jadx/core/codegen/NameGen.java b/jadx-core/src/main/java/jadx/core/codegen/NameGen.java new file mode 100644 index 000000000..eb60acc44 --- /dev/null +++ b/jadx-core/src/main/java/jadx/core/codegen/NameGen.java @@ -0,0 +1,134 @@ +package jadx.core.codegen; + +import jadx.core.Consts; +import jadx.core.deobf.NameMapper; +import jadx.core.dex.info.ClassInfo; +import jadx.core.dex.instructions.args.ArgType; +import jadx.core.dex.instructions.args.NamedArg; +import jadx.core.dex.instructions.args.RegisterArg; +import jadx.core.dex.instructions.args.SSAVar; +import jadx.core.utils.Utils; + +import java.util.HashSet; +import java.util.Set; + +public class NameGen { + + private final Set varNames = new HashSet(); + private final boolean fallback; + + public NameGen(boolean fallback) { + this.fallback = fallback; + } + + public String assignArg(RegisterArg arg) { + String name = makeArgName(arg); + if (fallback) { + return name; + } + name = getUniqueVarName(name); + SSAVar sVar = arg.getSVar(); + if (sVar != null) { + sVar.setName(name); + } + return name; + } + + public String assignNamedArg(NamedArg arg) { + String name = arg.getName(); + if (fallback) { + return name; + } + name = getUniqueVarName(name); + arg.setName(name); + return name; + } + + public String useArg(RegisterArg arg) { + String name = makeArgName(arg); + varNames.add(name); + return name; + } + + private String getUniqueVarName(String name) { + String r = name; + int i = 2; + while (varNames.contains(r)) { + r = name + i; + i++; + } + varNames.add(r); + return r; + } + + private String makeArgName(RegisterArg arg) { + String name = arg.getName(); + if (fallback) { + String base = "r" + arg.getRegNum(); + if (name != null) { + return base + "_" + name; + } + return base; + } + String varName; + if (name != null) { + if (name.equals("this")) { + return name; + } + varName = name; + } else { + varName = makeNameForType(arg.getType()); + } + if (NameMapper.isReserved(varName)) { + return varName + "R"; + } + return varName; + } + + private static String makeNameForType(ArgType type) { + if (type.isPrimitive()) { + return makeNameForPrimitive(type); + } else if (type.isArray()) { + return makeNameForType(type.getArrayRootElement()) + "Arr"; + } else { + return makeNameForObject(type); + } + } + + private static String makeNameForPrimitive(ArgType type) { + return type.getPrimitiveType().getShortName().toLowerCase(); + } + + private static String makeNameForObject(ArgType type) { + if (type.isObject()) { + String obj = type.getObject(); + if (obj.startsWith("java.lang.")) { + if (obj.equals(Consts.CLASS_STRING)) { + return "str"; + } + if (obj.equals(Consts.CLASS_OBJECT)) { + return "obj"; + } + if (obj.equals(Consts.CLASS_CLASS)) { + return "cls"; + } + if (obj.equals(Consts.CLASS_THROWABLE)) { + return "th"; + } + } + ClassInfo clsInfo = ClassInfo.fromType(type); + String shortName = clsInfo.getShortName(); + if (shortName.toUpperCase().equals(shortName)) { + // all characters are upper case + return shortName.toLowerCase(); + } + if (!shortName.isEmpty()) { + String v1 = Character.toLowerCase(shortName.charAt(0)) + shortName.substring(1); + if (!v1.equals(shortName)) { + return v1; + } + } + } + return Utils.escape(type.toString()); + } +} diff --git a/jadx-core/src/main/java/jadx/core/codegen/RegionGen.java b/jadx-core/src/main/java/jadx/core/codegen/RegionGen.java index dfa361abf..dca77cc76 100644 --- a/jadx-core/src/main/java/jadx/core/codegen/RegionGen.java +++ b/jadx-core/src/main/java/jadx/core/codegen/RegionGen.java @@ -277,7 +277,7 @@ public class RegionGen extends InsnGen { useClass(code, handler.getCatchType()); } code.add(' '); - code.add(mgen.assignNamedArg(handler.getArg())); + code.add(mgen.getNameGen().assignNamedArg(handler.getArg())); code.add(") {"); makeRegionIndent(code, region); } diff --git a/jadx-core/src/main/java/jadx/core/dex/instructions/args/InsnArg.java b/jadx-core/src/main/java/jadx/core/dex/instructions/args/InsnArg.java index cbd1505be..a0eb2880d 100644 --- a/jadx-core/src/main/java/jadx/core/dex/instructions/args/InsnArg.java +++ b/jadx-core/src/main/java/jadx/core/dex/instructions/args/InsnArg.java @@ -26,7 +26,7 @@ public abstract class InsnArg extends Typed { return reg(InsnUtils.getArg(insn, argNum), type); } - public static RegisterArg parameterReg(int regNum, ArgType type) { + public static MthParameterArg parameterReg(int regNum, ArgType type) { return new MthParameterArg(regNum, type); } @@ -113,7 +113,7 @@ public abstract class InsnArg extends Typed { } public boolean isThis() { - // must be implemented in RegisterArg + // must be implemented in RegisterArg and MthParameterArg return false; } } diff --git a/jadx-core/src/main/java/jadx/core/dex/instructions/args/MthParameterArg.java b/jadx-core/src/main/java/jadx/core/dex/instructions/args/MthParameterArg.java index 210ab8597..a6e9a4fb1 100644 --- a/jadx-core/src/main/java/jadx/core/dex/instructions/args/MthParameterArg.java +++ b/jadx-core/src/main/java/jadx/core/dex/instructions/args/MthParameterArg.java @@ -2,6 +2,8 @@ package jadx.core.dex.instructions.args; public class MthParameterArg extends RegisterArg { + private boolean isThis = false; + public MthParameterArg(int rn, ArgType type) { super(rn, type); } @@ -14,4 +16,29 @@ public class MthParameterArg extends RegisterArg { @Override public void setType(ArgType type) { } + + public void markAsThis() { + this.isThis = true; + } + + @Override + public boolean isThis() { + return isThis; + } + + @Override + public String getName() { + if (isThis) { + return "this"; + } + return super.getName(); + } + + @Override + void setSVar(SSAVar sVar) { + if (isThis) { + sVar.setName("this"); + } + super.setSVar(sVar); + } } diff --git a/jadx-core/src/main/java/jadx/core/dex/instructions/args/RegisterArg.java b/jadx-core/src/main/java/jadx/core/dex/instructions/args/RegisterArg.java index 25ac1082b..0ec8dffc6 100644 --- a/jadx-core/src/main/java/jadx/core/dex/instructions/args/RegisterArg.java +++ b/jadx-core/src/main/java/jadx/core/dex/instructions/args/RegisterArg.java @@ -11,7 +11,6 @@ import jadx.core.dex.nodes.DexNode; import jadx.core.dex.nodes.FieldNode; import jadx.core.dex.nodes.InsnNode; import jadx.core.dex.nodes.parser.FieldValueAttr; -import jadx.core.utils.exceptions.JadxRuntimeException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -21,7 +20,6 @@ public class RegisterArg extends InsnArg implements Named { protected final int regNum; protected SSAVar sVar; - protected String name; public RegisterArg(int rn) { this.regNum = rn; @@ -49,34 +47,43 @@ public class RegisterArg extends InsnArg implements Named { this.sVar = sVar; } + public String getName() { + if (sVar == null) { + return null; + } + return sVar.getName(); + } + + public void setName(String name) { + if (sVar != null) { + sVar.setName(name); + } + } + + public boolean isNameEquals(InsnArg arg) { + String n = getName(); + if (n == null || !(arg instanceof Named)) { + return false; + } + return n.equals(((Named) arg).getName()); + } + @Override public void setType(ArgType type) { if (sVar != null) { sVar.setType(type); - } else { - throw new JadxRuntimeException("SSA variable equals null"); } } + public void mergeDebugInfo(ArgType type, String name) { + setType(type); + setName(name); + } + public void forceType(ArgType type) { this.type = type; } - public String getName() { - return name; - } - - public boolean isNameEquals(InsnArg arg) { - if (name == null || !(arg instanceof Named)) { - return false; - } - return name.equals(((Named) arg).getName()); - } - - public void setName(String newName) { - this.name = newName; - } - /** * Return constant value from register assign or null if not constant * @@ -113,17 +120,15 @@ public class RegisterArg extends InsnArg implements Named { @Override public boolean isThis() { - if ("this".equals(name)) { + if ("this".equals(getName())) { return true; } // maybe it was moved from 'this' register InsnNode ai = getAssignInsn(); if (ai != null && ai.getType() == InsnType.MOVE) { InsnArg arg = ai.getArg(0); - if (arg != this - && arg.isRegister() - && "this".equals(((RegisterArg) arg).getName())) { - return true; + if (arg != this) { + return arg.isThis(); } } return false; @@ -196,8 +201,8 @@ public class RegisterArg extends InsnArg implements Named { if (sVar != null) { sb.append("_").append(sVar.getVersion()); } - if (name != null) { - sb.append(" '").append(name).append("'"); + if (getName() != null) { + sb.append(" '").append(getName()).append("'"); } sb.append(" "); sb.append(type); diff --git a/jadx-core/src/main/java/jadx/core/dex/instructions/args/SSAVar.java b/jadx-core/src/main/java/jadx/core/dex/instructions/args/SSAVar.java index 8dba96ead..10b23c6e8 100644 --- a/jadx-core/src/main/java/jadx/core/dex/instructions/args/SSAVar.java +++ b/jadx-core/src/main/java/jadx/core/dex/instructions/args/SSAVar.java @@ -9,6 +9,7 @@ public class SSAVar { private final int regNum; private final int version; + private VarName varName; private RegisterArg assign; private final List useList = new ArrayList(2); @@ -22,7 +23,6 @@ public class SSAVar { this.assign = assign; if (assign != null) { - mergeName(assign); assign.setSVar(this); } } @@ -52,7 +52,6 @@ public class SSAVar { } public void use(RegisterArg arg) { - mergeName(arg); if (arg.getSVar() != null) { arg.getSVar().removeUse(arg); } @@ -103,35 +102,27 @@ public class SSAVar { } public void setName(String name) { - if (assign != null) { - assign.setName(name); - } - for (int i = 0, useListSize = useList.size(); i < useListSize; i++) { - useList.get(i).setName(name); - } - } - - public void setVariableName(String name) { - setName(name); - if (isUsedInPhi()) { - PhiInsn phi = getUsedInPhi(); - phi.getResult().getSVar().setVariableName(name); - for (InsnArg arg : phi.getArguments()) { - if (arg.isRegister()) { - RegisterArg reg = (RegisterArg) arg; - SSAVar sVar = reg.getSVar(); - if (sVar != this && !name.equals(reg.getName())) { - sVar.setVariableName(name); - } - } + if (name != null) { + if (varName == null) { + varName = new VarName(); } + varName.setName(name); } } - public void mergeName(RegisterArg arg) { - if (arg.getName() != null) { - setName(arg.getName()); + public String getName() { + if (varName == null) { + return null; } + return varName.getName(); + } + + public VarName getVarName() { + return varName; + } + + public void setVarName(VarName varName) { + this.varName = varName; } @Override diff --git a/jadx-core/src/main/java/jadx/core/dex/instructions/args/Typed.java b/jadx-core/src/main/java/jadx/core/dex/instructions/args/Typed.java index 67f9dfe4e..f3557a3ec 100644 --- a/jadx-core/src/main/java/jadx/core/dex/instructions/args/Typed.java +++ b/jadx-core/src/main/java/jadx/core/dex/instructions/args/Typed.java @@ -28,12 +28,4 @@ public abstract class Typed { public boolean merge(InsnArg arg) { return merge(arg.getType()); } - - public void mergeDebugInfo(RegisterArg arg) { - this.type = arg.getType(); - if (this instanceof Named) { - Named n = (Named) this; - n.setName(arg.getName()); - } - } } diff --git a/jadx-core/src/main/java/jadx/core/dex/instructions/args/VarName.java b/jadx-core/src/main/java/jadx/core/dex/instructions/args/VarName.java new file mode 100644 index 000000000..33ba9f42a --- /dev/null +++ b/jadx-core/src/main/java/jadx/core/dex/instructions/args/VarName.java @@ -0,0 +1,18 @@ +package jadx.core.dex.instructions.args; + +public class VarName { + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @Override + public String toString() { + return name; + } +} diff --git a/jadx-core/src/main/java/jadx/core/dex/nodes/MethodNode.java b/jadx-core/src/main/java/jadx/core/dex/nodes/MethodNode.java index 1df98a1a0..bc576be10 100644 --- a/jadx-core/src/main/java/jadx/core/dex/nodes/MethodNode.java +++ b/jadx-core/src/main/java/jadx/core/dex/nodes/MethodNode.java @@ -15,9 +15,9 @@ import jadx.core.dex.instructions.InsnDecoder; import jadx.core.dex.instructions.SwitchNode; import jadx.core.dex.instructions.args.ArgType; import jadx.core.dex.instructions.args.InsnArg; +import jadx.core.dex.instructions.args.MthParameterArg; import jadx.core.dex.instructions.args.RegisterArg; import jadx.core.dex.instructions.args.SSAVar; -import jadx.core.dex.nodes.parser.DebugInfoParser; import jadx.core.dex.nodes.parser.SignatureParser; import jadx.core.dex.regions.Region; import jadx.core.dex.trycatch.ExcHandlerAttr; @@ -51,7 +51,8 @@ public class MethodNode extends LineAttrNode implements ILoadable { private final Method methodData; private int regsCount; - private List instructions; + private InsnNode[] instructions; + private int debugInfoOffset; private boolean noCode; private ArgType retType; @@ -92,30 +93,12 @@ public class MethodNode extends LineAttrNode implements ILoadable { InsnDecoder decoder = new InsnDecoder(this); decoder.decodeInsns(mthCode); - InsnNode[] insnByOffset = decoder.process(); - instructions = new ArrayList(); - for (InsnNode insn : insnByOffset) { - if (insn != null) { - instructions.add(insn); - } - } - ((ArrayList) instructions).trimToSize(); + instructions = decoder.process(); - initTryCatches(mthCode, insnByOffset); - initJumps(insnByOffset); + initTryCatches(mthCode); + initJumps(); - 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); - } - } - } + this.debugInfoOffset = mthCode.getDebugInfoOffset(); } catch (Exception e) { if (!noCode) { noCode = true; @@ -139,9 +122,7 @@ public class MethodNode extends LineAttrNode implements ILoadable { if (noCode) { return; } - if (instructions != null) { - instructions.clear(); - } + instructions = null; blocks = null; exitBlocks = null; exceptionHandlers.clear(); @@ -199,8 +180,9 @@ public class MethodNode extends LineAttrNode implements ILoadable { if (accFlags.isStatic()) { thisArg = null; } else { - thisArg = InsnArg.parameterReg(pos - 1, parentClass.getClassInfo().getType()); - thisArg.setName("this"); + MthParameterArg arg = InsnArg.parameterReg(pos - 1, parentClass.getClassInfo().getType()); + arg.markAsThis(); + thisArg = arg; } if (args.isEmpty()) { argsList = Collections.emptyList(); @@ -241,7 +223,8 @@ public class MethodNode extends LineAttrNode implements ILoadable { return genericMap; } - private void initTryCatches(Code mthCode, InsnNode[] insnByOffset) { + private void initTryCatches(Code mthCode) { + InsnNode[] insnByOffset = instructions; CatchHandler[] catchBlocks = mthCode.getCatchHandlers(); Try[] tries = mthCode.getTries(); @@ -311,9 +294,13 @@ public class MethodNode extends LineAttrNode implements ILoadable { } } - private void initJumps(InsnNode[] insnByOffset) { - for (InsnNode insn : getInstructions()) { - int offset = insn.getOffset(); + private void initJumps() { + InsnNode[] insnByOffset = instructions; + for (int offset = 0; offset < insnByOffset.length; offset++) { + InsnNode insn = insnByOffset[offset]; + if (insn == null) { + continue; + } switch (insn.getType()) { case SWITCH: { SwitchNode sw = (SwitchNode) insn; @@ -367,20 +354,20 @@ public class MethodNode extends LineAttrNode implements ILoadable { return noCode; } - public List getInstructions() { + public InsnNode[] getInstructions() { return instructions; } + public void unloadInsnArr() { + this.instructions = null; + } + public void initBasicBlocks() { blocks = new ArrayList(); exitBlocks = new ArrayList(1); } public void finishBasicBlocks() { - // after filling basic blocks we don't need instructions list anymore - instructions.clear(); - instructions = null; - ((ArrayList) blocks).trimToSize(); ((ArrayList) exitBlocks).trimToSize(); @@ -479,6 +466,10 @@ public class MethodNode extends LineAttrNode implements ILoadable { return regsCount; } + public int getDebugInfoOffset() { + return debugInfoOffset; + } + public SSAVar makeNewSVar(int regNum, int[] versions, RegisterArg arg) { SSAVar var = new SSAVar(regNum, versions[regNum], arg); versions[regNum]++; diff --git a/jadx-core/src/main/java/jadx/core/dex/nodes/parser/DebugInfoParser.java b/jadx-core/src/main/java/jadx/core/dex/nodes/parser/DebugInfoParser.java index 9af30501f..22a382a12 100644 --- a/jadx-core/src/main/java/jadx/core/dex/nodes/parser/DebugInfoParser.java +++ b/jadx-core/src/main/java/jadx/core/dex/nodes/parser/DebugInfoParser.java @@ -226,19 +226,18 @@ public class DebugInfoParser { } private static void fillLocals(InsnNode insn, LocalVar var) { - if (insn.getResult() != null) { - merge(insn.getResult(), var); - } + merge(insn.getResult(), var); for (InsnArg arg : insn.getArguments()) { merge(arg, var); } } private static void merge(InsnArg arg, LocalVar var) { - if (arg != null - && arg.isRegister() - && var.getRegNum() == ((RegisterArg) arg).getRegNum()) { - arg.mergeDebugInfo(var); + if (arg != null && arg.isRegister()) { + RegisterArg reg = (RegisterArg) arg; + if (var.getRegNum() == reg.getRegNum()) { + reg.mergeDebugInfo(var.getType(), var.getName()); + } } } } diff --git a/jadx-core/src/main/java/jadx/core/dex/nodes/parser/LocalVar.java b/jadx-core/src/main/java/jadx/core/dex/nodes/parser/LocalVar.java index 4c1ffc081..d42625a8a 100644 --- a/jadx-core/src/main/java/jadx/core/dex/nodes/parser/LocalVar.java +++ b/jadx-core/src/main/java/jadx/core/dex/nodes/parser/LocalVar.java @@ -8,17 +8,19 @@ import jadx.core.utils.InsnUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -final class LocalVar extends RegisterArg { - +final class LocalVar { private static final Logger LOG = LoggerFactory.getLogger(LocalVar.class); - private boolean isEnd; + private int regNum; + private String name; + private ArgType type; + private boolean isEnd; private int startAddr; private int endAddr; public LocalVar(DexNode dex, int rn, int nameId, int typeId, int signId) { - super(rn, ArgType.UNKNOWN); + this.regNum = rn; String name = (nameId == DexNode.NO_INDEX ? null : dex.getString(nameId)); ArgType type = (typeId == DexNode.NO_INDEX ? null : dex.getType(typeId)); String sign = (signId == DexNode.NO_INDEX ? null : dex.getString(signId)); @@ -27,7 +29,7 @@ final class LocalVar extends RegisterArg { } public LocalVar(RegisterArg arg) { - super(arg.getRegNum(), arg.getType()); + this.regNum = arg.getRegNum(); init(arg.getName(), arg.getType(), null); } @@ -42,8 +44,8 @@ final class LocalVar extends RegisterArg { LOG.error("Can't parse signature for local variable: " + sign, e); } } - setName(name); - forceType(type); + this.name = name; + this.type = type; } private boolean checkSignature(ArgType type, String sign, ArgType gType) { @@ -72,6 +74,18 @@ final class LocalVar extends RegisterArg { this.endAddr = addr; } + public int getRegNum() { + return regNum; + } + + public String getName() { + return name; + } + + public ArgType getType() { + return type; + } + public boolean isEnd() { return isEnd; } diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/BlockMakerVisitor.java b/jadx-core/src/main/java/jadx/core/dex/visitors/BlockMakerVisitor.java index ba44be1da..0f93695f9 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/BlockMakerVisitor.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/BlockMakerVisitor.java @@ -60,6 +60,9 @@ public class BlockMakerVisitor extends AbstractVisitor { // split into blocks for (InsnNode insn : mth.getInstructions()) { + if (insn == null) { + continue; + } boolean startNew = false; if (prevInsn != null) { InsnType type = prevInsn.getType(); @@ -443,10 +446,18 @@ public class BlockMakerVisitor extends AbstractVisitor { if (returnInsn.getArgsCount() != 0 && !isReturnArgAssignInPred(preds, returnInsn)) { return false; } + boolean first = true; for (BlockNode pred : preds) { BlockNode newRetBlock = startNewBlock(mth, exitBlock.getStartOffset()); newRetBlock.add(AFlag.SYNTHETIC); - newRetBlock.getInstructions().add(duplicateReturnInsn(returnInsn)); + InsnNode newRetInsn; + if (first) { + newRetInsn = returnInsn; + first = false; + } else { + newRetInsn = duplicateReturnInsn(returnInsn); + } + newRetBlock.getInstructions().add(newRetInsn); removeConnection(pred, exitBlock); connect(pred, newRetBlock); } diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/DebugInfoVisitor.java b/jadx-core/src/main/java/jadx/core/dex/visitors/DebugInfoVisitor.java new file mode 100644 index 000000000..70670155c --- /dev/null +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/DebugInfoVisitor.java @@ -0,0 +1,43 @@ +package jadx.core.dex.visitors; + +import jadx.core.dex.instructions.args.ArgType; +import jadx.core.dex.instructions.args.RegisterArg; +import jadx.core.dex.nodes.BlockNode; +import jadx.core.dex.nodes.InsnNode; +import jadx.core.dex.nodes.MethodNode; +import jadx.core.dex.nodes.parser.DebugInfoParser; +import jadx.core.utils.exceptions.JadxException; + +public class DebugInfoVisitor extends AbstractVisitor { + @Override + public void visit(MethodNode mth) throws JadxException { + int debugOffset = mth.getDebugInfoOffset(); + if (debugOffset > 0) { + InsnNode[] insnArr = mth.getInstructions(); + DebugInfoParser debugInfoParser = new DebugInfoParser(mth, debugOffset, insnArr); + debugInfoParser.process(); + + if (insnArr.length != 0) { + int line = insnArr[0].getSourceLine(); + if (line != 0) { + mth.setSourceLine(line - 1); + } + } + if (!mth.getReturnType().equals(ArgType.VOID) + && mth.getExitBlocks().size() > 1) { + // fix debug for splitter 'return' instructions + for (BlockNode exit : mth.getExitBlocks()) { + InsnNode ret = exit.getInstructions().get(0); + InsnNode oldRet = insnArr[ret.getOffset()]; + if (oldRet != ret) { + RegisterArg oldArg = (RegisterArg) oldRet.getArg(0); + RegisterArg newArg = (RegisterArg) ret.getArg(0); + newArg.mergeDebugInfo(oldArg.getType(), oldArg.getName()); + ret.setSourceLine(oldRet.getSourceLine()); + } + } + } + } + mth.unloadInsnArr(); + } +} diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/DotGraphVisitor.java b/jadx-core/src/main/java/jadx/core/dex/visitors/DotGraphVisitor.java index 0671f6227..d46336f4a 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/DotGraphVisitor.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/DotGraphVisitor.java @@ -211,7 +211,9 @@ public class DotGraphVisitor extends AbstractVisitor { return str.toString(); } else { CodeWriter code = new CodeWriter(); - MethodGen.addFallbackInsns(code, mth, block.getInstructions(), false); + List instructions = block.getInstructions(); + MethodGen.addFallbackInsns(code, mth, + instructions.toArray(new InsnNode[instructions.size()]), false); String str = escape(code.newLine().toString()); if (str.startsWith(NL)) { str = str.substring(NL.length()); diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/FallbackModeVisitor.java b/jadx-core/src/main/java/jadx/core/dex/visitors/FallbackModeVisitor.java index fbd8dcde4..63c177726 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/FallbackModeVisitor.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/FallbackModeVisitor.java @@ -14,6 +14,9 @@ public class FallbackModeVisitor extends AbstractVisitor { return; } for (InsnNode insn : mth.getInstructions()) { + if (insn == null) { + continue; + } // remove 'exception catch' for instruction which don't throw any exceptions CatchAttr catchAttr = insn.get(AType.CATCH_BLOCK); if (catchAttr != null) { diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/regions/ProcessVariables.java b/jadx-core/src/main/java/jadx/core/dex/visitors/regions/ProcessVariables.java index ae8c9f6f7..508f48f4c 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/regions/ProcessVariables.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/regions/ProcessVariables.java @@ -5,6 +5,7 @@ import jadx.core.dex.attributes.AType; import jadx.core.dex.attributes.nodes.DeclareVariablesAttr; import jadx.core.dex.instructions.args.ArgType; import jadx.core.dex.instructions.args.RegisterArg; +import jadx.core.dex.instructions.args.VarName; import jadx.core.dex.nodes.IBlock; import jadx.core.dex.nodes.IContainer; import jadx.core.dex.nodes.IRegion; @@ -66,6 +67,7 @@ public class ProcessVariables extends AbstractVisitor { private static class Usage { private RegisterArg arg; + private VarName varName; private IRegion argRegion; private final Set usage = new HashSet(2); private final Set assigns = new HashSet(2); @@ -78,6 +80,14 @@ public class ProcessVariables extends AbstractVisitor { return arg; } + public VarName getVarName() { + return varName; + } + + public void setVarName(VarName varName) { + this.varName = varName; + } + public void setArgRegion(IRegion argRegion) { this.argRegion = argRegion; } @@ -102,7 +112,14 @@ public class ProcessVariables extends AbstractVisitor { @Override public void visit(MethodNode mth) throws JadxException { + if (mth.isNoCode()) { + return; + } + final Map usageMap = new LinkedHashMap(); + for (RegisterArg arg : mth.getArguments(true)) { + addToUsageMap(arg, usageMap); + } // collect all variables usage IRegionVisitor collect = new TracedRegionVisitor() { @@ -210,6 +227,17 @@ public class ProcessVariables extends AbstractVisitor { usage = new Usage(); usageMap.put(varId, usage); } + // merge variables names + if (usage.getVarName() == null) { + VarName argVN = arg.getSVar().getVarName(); + if (argVN == null) { + argVN = new VarName(); + arg.getSVar().setVarName(argVN); + } + usage.setVarName(argVN); + } else { + arg.getSVar().setVarName(usage.getVarName()); + } return usage; } diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/ssa/EliminatePhiNodes.java b/jadx-core/src/main/java/jadx/core/dex/visitors/ssa/EliminatePhiNodes.java index 6737b745e..18304f72b 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/ssa/EliminatePhiNodes.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/ssa/EliminatePhiNodes.java @@ -3,7 +3,6 @@ package jadx.core.dex.visitors.ssa; import jadx.core.dex.attributes.AType; import jadx.core.dex.attributes.nodes.PhiListAttr; import jadx.core.dex.instructions.PhiInsn; -import jadx.core.dex.instructions.args.SSAVar; import jadx.core.dex.nodes.BlockNode; import jadx.core.dex.nodes.InsnNode; import jadx.core.dex.nodes.MethodNode; @@ -19,56 +18,9 @@ public class EliminatePhiNodes extends AbstractVisitor { if (mth.isNoCode()) { return; } - enumerateSVars(mth); removePhiInstructions(mth); } - public static void enumerateSVars(MethodNode mth) { - for (SSAVar sVar : mth.getSVars()) { - if (sVar.isUsedInPhi()) { - sVar.mergeName(sVar.getUsedInPhi().getResult()); - } - } - } - -// public static void enumerateSVars(MethodNode mth) { -// List vars = mth.getSVars(); -// int varsSize = vars.size(); -// Deque workList = new LinkedList(); -// for (int i = 0; i < varsSize; i++) { -// SSAVar ssaVar = vars.get(i); -// ssaVar.setVarId(i); -// if (ssaVar.isUsedInPhi()) { -// workList.add(ssaVar); -// } -// } -// -// int k = 0; -// while (!workList.isEmpty()) { -// SSAVar var = workList.pop(); -// RegisterArg assignVar = var.getUsedInPhi().getResult(); -// // set same name and variable ID -// var.mergeName(assignVar); -// SSAVar assignSVar = assignVar.getSVar(); -// int varId = assignSVar.getVarId(); -// var.setVarId(varId); -// -// if (assignSVar.isUsedInPhi()) { -// PhiInsn assignPhi = assignSVar.getUsedInPhi(); -// SSAVar asVar = assignPhi.getResult().getSVar(); -// if (asVar.getVarId() != varId) { -// asVar.setVarId(varId); -// for (int i = 0; i < assignPhi.getArgsCount(); i++) { -// workList.push(assignPhi.getArg(i).getSVar()); -// } -// } -// } -// if (k++ > 1000) { -// throw new JadxRuntimeException("Can't calculate variable id"); -// } -// } -// } - private static void removePhiInstructions(MethodNode mth) { for (BlockNode block : mth.getBasicBlocks()) { PhiListAttr phiList = block.get(AType.PHI_LIST); diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/ssa/SSATransform.java b/jadx-core/src/main/java/jadx/core/dex/visitors/ssa/SSATransform.java index 63816a93e..8789f0dae 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/ssa/SSATransform.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/ssa/SSATransform.java @@ -32,7 +32,7 @@ public class SSATransform extends AbstractVisitor { process(mth); } - public void process(MethodNode mth) { + private void process(MethodNode mth) { LiveVarAnalysis la = new LiveVarAnalysis(mth); la.runAnalysis(); for (int i = 0; i < mth.getRegsCount(); i++) { diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/typeinference/TypeInference.java b/jadx-core/src/main/java/jadx/core/dex/visitors/typeinference/TypeInference.java index d36271812..42fc00f9f 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/typeinference/TypeInference.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/typeinference/TypeInference.java @@ -82,7 +82,7 @@ public class TypeInference extends AbstractVisitor { for (int i = 0; i < phi.getArgsCount(); i++) { RegisterArg arg = phi.getArg(i); arg.setType(type); - arg.getSVar().mergeName(phi.getResult()); + arg.getSVar().setName(phi.getResult().getName()); } } diff --git a/jadx-core/src/test/java/jadx/tests/internal/inline/TestInline2.java b/jadx-core/src/test/java/jadx/tests/internal/inline/TestInline2.java index d2a9a93b4..91bce49bb 100644 --- a/jadx-core/src/test/java/jadx/tests/internal/inline/TestInline2.java +++ b/jadx-core/src/test/java/jadx/tests/internal/inline/TestInline2.java @@ -31,8 +31,8 @@ public class TestInline2 extends InternalJadxTest { System.out.println(code); assertThat(code, containsString("i < a.length")); - assertThat(code, containsString("long i_2 =")); - assertThat(code, containsString("+ i_2")); - assertThat(code, containsString("i_2--;")); + assertThat(code, containsString("long i2 =")); + assertThat(code, containsString("+ i2")); + assertThat(code, containsString("i2--;")); } } diff --git a/jadx-samples/src/main/java/jadx/samples/AbstractTest.java b/jadx-samples/src/main/java/jadx/samples/AbstractTest.java index 61dede9f6..00a790e41 100644 --- a/jadx-samples/src/main/java/jadx/samples/AbstractTest.java +++ b/jadx-samples/src/main/java/jadx/samples/AbstractTest.java @@ -36,8 +36,9 @@ public abstract class AbstractTest { public static void assertEquals(Object a1, Object a2) { if (a1 == null) { - if (a2 != null) + if (a2 != null) { throw new AssertionError(a1 + " != " + a2); + } } else if (!a1.equals(a2)) { throw new AssertionError(a1 + " != " + a2); } diff --git a/jadx-samples/src/main/java/jadx/samples/TestAnnotations.java b/jadx-samples/src/main/java/jadx/samples/TestAnnotations.java index 4c720258e..70bae924e 100644 --- a/jadx-samples/src/main/java/jadx/samples/TestAnnotations.java +++ b/jadx-samples/src/main/java/jadx/samples/TestAnnotations.java @@ -50,7 +50,7 @@ public class TestAnnotations extends AbstractTest { @MyAnnotation(name = "b", num = 7, cls = Exception.class, - doubles = { 0.0, 1.1 }, + doubles = {0.0, 1.1}, value = 9.87f, simple = @SimpleAnnotation(false)) public static Object test(String[] a) { diff --git a/jadx-samples/src/main/java/jadx/samples/TestCF.java b/jadx-samples/src/main/java/jadx/samples/TestCF.java index b8ece2e69..96a1e4585 100644 --- a/jadx-samples/src/main/java/jadx/samples/TestCF.java +++ b/jadx-samples/src/main/java/jadx/samples/TestCF.java @@ -22,10 +22,11 @@ public class TestCF extends AbstractTest { public int test1b(int a) { if (a > 0) { - if (a < 5) + if (a < 5) { a++; - else + } else { a -= 2; + } } a *= 2; return a + 3; @@ -134,16 +135,17 @@ public class TestCF extends AbstractTest { public int testIfElse(String str) { int r; - if (str.equals("a")) + if (str.equals("a")) { r = 1; - else if (str.equals("b")) + } else if (str.equals("b")) { r = 2; - else if (str.equals("3")) + } else if (str.equals("3")) { r = 3; - else if (str.equals("$")) + } else if (str.equals("$")) { r = 4; - else + } else { r = -1; + } r = r * 10; return Math.abs(r); diff --git a/jadx-samples/src/main/java/jadx/samples/TestCF2.java b/jadx-samples/src/main/java/jadx/samples/TestCF2.java index b90cbd09d..f09ce28da 100644 --- a/jadx-samples/src/main/java/jadx/samples/TestCF2.java +++ b/jadx-samples/src/main/java/jadx/samples/TestCF2.java @@ -5,7 +5,7 @@ public class TestCF2 extends AbstractTest { private boolean ready = false; public int simple_loops() throws InterruptedException { - int[] a = new int[] { 1, 2, 4, 6, 8 }; + int[] a = new int[]{1, 2, 4, 6, 8}; int b = 0; for (int i = 0; i < a.length; i++) { b += a[i]; @@ -21,8 +21,9 @@ public class TestCF2 extends AbstractTest { */ public void run() throws InterruptedException { while (true) { - if (!ready) + if (!ready) { ready_mutex.wait(); + } ready = false; func(); } @@ -88,8 +89,9 @@ public class TestCF2 extends AbstractTest { public void do_while_return2(boolean k) throws InterruptedException { int i = 3; do { - if (k) + if (k) { return; + } i++; } while (i < 5); } diff --git a/jadx-samples/src/main/java/jadx/samples/TestDeadCode.java b/jadx-samples/src/main/java/jadx/samples/TestDeadCode.java index 94b2328d3..76e9f5d15 100644 --- a/jadx-samples/src/main/java/jadx/samples/TestDeadCode.java +++ b/jadx-samples/src/main/java/jadx/samples/TestDeadCode.java @@ -3,8 +3,9 @@ package jadx.samples; public class TestDeadCode extends AbstractTest { private void test1(int i) { - if (i == 0) + if (i == 0) { return; + } return; } diff --git a/jadx-samples/src/main/java/jadx/samples/TestGenerics.java b/jadx-samples/src/main/java/jadx/samples/TestGenerics.java index bb3eccbd1..3b984e586 100644 --- a/jadx-samples/src/main/java/jadx/samples/TestGenerics.java +++ b/jadx-samples/src/main/java/jadx/samples/TestGenerics.java @@ -77,7 +77,7 @@ public class TestGenerics extends AbstractTest { public static boolean use() { Pair p1 = new OrderedPair(1, "str1"); Pair p2 = new OrderedPair(2, "str2"); - boolean same = Util. compare(p1, p2); + boolean same = Util.compare(p1, p2); return same; } @@ -107,9 +107,11 @@ public class TestGenerics extends AbstractTest { public static > int countGreaterThan(T[] anArray, T elem) { int count = 0; - for (T e : anArray) - if (e.compareTo(elem) > 0) + for (T e : anArray) { + if (e.compareTo(elem) > 0) { ++count; + } + } return count; } @@ -117,8 +119,9 @@ public class TestGenerics extends AbstractTest { } public static void printList(List list) { - for (Object elem : list) + for (Object elem : list) { System.out.print(elem + " "); + } System.out.println(); } diff --git a/jadx-samples/src/main/java/jadx/samples/TestInner.java b/jadx-samples/src/main/java/jadx/samples/TestInner.java index d1343358e..f96907ca7 100644 --- a/jadx-samples/src/main/java/jadx/samples/TestInner.java +++ b/jadx-samples/src/main/java/jadx/samples/TestInner.java @@ -56,6 +56,7 @@ public class TestInner extends AbstractTest { { count += 5; } + @Override public void run() { count += 6; @@ -68,6 +69,7 @@ public class TestInner extends AbstractTest { { count += 7; } + @Override public String toString() { count += 8; diff --git a/jadx-samples/src/main/java/jadx/samples/TestInner2.java b/jadx-samples/src/main/java/jadx/samples/TestInner2.java index bba7a9fdf..6523dad49 100644 --- a/jadx-samples/src/main/java/jadx/samples/TestInner2.java +++ b/jadx-samples/src/main/java/jadx/samples/TestInner2.java @@ -73,7 +73,7 @@ public class TestInner2 extends AbstractTest { Method[] mths = TestInner2.class.getDeclaredMethods(); for (Method mth : mths) { - if(mth.getName().startsWith("access$")) { + if (mth.getName().startsWith("access$")) { int modifiers = mth.getModifiers(); assertTrue((modifiers & SYNTHETIC) != 0, "Synthetic methods must be removed"); } diff --git a/jadx-samples/src/main/java/jadx/samples/TestInvoke.java b/jadx-samples/src/main/java/jadx/samples/TestInvoke.java index f6abf674b..b1279c950 100644 --- a/jadx-samples/src/main/java/jadx/samples/TestInvoke.java +++ b/jadx-samples/src/main/java/jadx/samples/TestInvoke.java @@ -14,10 +14,11 @@ public class TestInvoke extends AbstractTest { } private void parse(String[] args) { - if (args.length > 0) + if (args.length > 0) { f = Integer.parseInt(args[0]); - else + } else { f = 20; + } } public int getF() { @@ -37,18 +38,26 @@ public class TestInvoke extends AbstractTest { return s; } + private String testSameArgTypes(String s1, String s2) { + if (s1.equals(s2)) { + return null; + } + return s1; + } + @Override public boolean testRun() throws Exception { TestInvoke inv = new TestInvoke(); - inv.parse(new String[] { "12", "35" }); + inv.parse(new String[]{"12", "35"}); assertTrue(inv.getF() == 12); inv.parse(new String[0]); assertTrue(inv.getF() == 20); assertTrue(inv.testVarArgs("a", "2", "III")); - assertTrue(inv.testVarArgs2("a".toCharArray(), new char[] { '1', '2' }).equals("a12")); + assertTrue(inv.testVarArgs2("a".toCharArray(), new char[]{'1', '2'}).equals("a12")); + assertEquals(testSameArgTypes("a", "b"), "a"); return true; } diff --git a/jadx-samples/src/main/java/jadx/samples/TestSwitch.java b/jadx-samples/src/main/java/jadx/samples/TestSwitch.java index 2d4d9356c..71d7a8704 100644 --- a/jadx-samples/src/main/java/jadx/samples/TestSwitch.java +++ b/jadx-samples/src/main/java/jadx/samples/TestSwitch.java @@ -43,10 +43,11 @@ public class TestSwitch extends AbstractTest { int k = i; switch (k) { case 1: - if (j == 0) + if (j == 0) { return 0; - else + } else { return -1; + } case 2: return 1; } @@ -69,8 +70,9 @@ public class TestSwitch extends AbstractTest { int k = i; switch (k) { case 1: - if (b == 0) + if (b == 0) { return 3; + } case 2: b++; diff --git a/jadx-samples/src/main/java/jadx/samples/TestTryCatch.java b/jadx-samples/src/main/java/jadx/samples/TestTryCatch.java index e3ef44758..48a749ceb 100644 --- a/jadx-samples/src/main/java/jadx/samples/TestTryCatch.java +++ b/jadx-samples/src/main/java/jadx/samples/TestTryCatch.java @@ -5,14 +5,16 @@ import java.io.IOException; public class TestTryCatch extends AbstractTest { private static boolean exc(Object obj) throws Exception { - if (obj == null) + if (obj == null) { throw new Exception("test"); + } return (obj instanceof Object); } private static boolean exc2(Object obj) throws IOException { - if (obj == null) + if (obj == null) { throw new IOException(); + } return true; } @@ -41,10 +43,11 @@ public class TestTryCatch extends AbstractTest { try { return exc(obj); } catch (Exception e) { - if (obj != null) + if (obj != null) { return true; - else + } else { return false; + } } } @@ -78,8 +81,9 @@ public class TestTryCatch extends AbstractTest { try { res = "" + exc(obj); boolean f = exc2("a"); - if (!f) + if (!f) { res = "f == false"; + } } catch (Exception e) { res = "exc"; } @@ -95,8 +99,9 @@ public class TestTryCatch extends AbstractTest { } catch (IOException e) { res = true; } catch (Throwable e) { - if (obj == null) + if (obj == null) { obj = new Object(); + } } } } @@ -112,8 +117,9 @@ public class TestTryCatch extends AbstractTest { res = true; obj = new Object(); } catch (Throwable e) { - if (obj == null) + if (obj == null) { res = false; + } } } } @@ -137,16 +143,18 @@ public class TestTryCatch extends AbstractTest { } catch (Exception e) { e.toString(); } finally { - if (!mDiscovering) + if (!mDiscovering) { mDiscovering = true; + } } return mDiscovering; } private static boolean testSynchronize(Object obj) throws InterruptedException { synchronized (obj) { - if (obj instanceof String) + if (obj instanceof String) { return false; + } obj.wait(5); } return true; @@ -171,8 +179,9 @@ public class TestTryCatch extends AbstractTest { public int catchInLoop(int i, int j) { while (true) { try { - while (i < j) + while (i < j) { i = j++ / i; + } } catch (RuntimeException e) { i = 10; continue; diff --git a/jadx-samples/src/main/java/jadx/samples/TestTypeResolver2.java b/jadx-samples/src/main/java/jadx/samples/TestTypeResolver2.java index c3a3652e3..2ad938b2d 100644 --- a/jadx-samples/src/main/java/jadx/samples/TestTypeResolver2.java +++ b/jadx-samples/src/main/java/jadx/samples/TestTypeResolver2.java @@ -7,7 +7,7 @@ package jadx.samples; */ public class TestTypeResolver2 extends AbstractTest { - private static String result = ""; + private static String result = ""; public void testOverloadedMethods() { Object s1 = "The"; diff --git a/settings.gradle b/settings.gradle index 934b2e28c..3115b7a0f 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1 +1,3 @@ +rootProject.name = 'jadx' + include 'jadx-core', 'jadx-samples', 'jadx-cli', 'jadx-gui'