Commit f2aa4cd1 authored by Skylot's avatar Skylot

core: make better variables naming

parent b940b99e
...@@ -9,18 +9,16 @@ subprojects { ...@@ -9,18 +9,16 @@ subprojects {
apply plugin: 'jacoco' apply plugin: 'jacoco'
apply plugin: 'coveralls' apply plugin: 'coveralls'
sourceCompatibility = 1.6
targetCompatibility = 1.6
version = jadxVersion version = jadxVersion
gradle.projectsEvaluated { tasks.withType(JavaCompile) {
tasks.withType(Compile) { sourceCompatibility = JavaVersion.VERSION_1_6
targetCompatibility = JavaVersion.VERSION_1_6
if (!"$it".contains(':jadx-samples:')) { if (!"$it".contains(':jadx-samples:')) {
options.compilerArgs << '-Xlint' << '-Xlint:unchecked' << '-Xlint:deprecation' options.compilerArgs << '-Xlint' << '-Xlint:unchecked' << '-Xlint:deprecation'
} }
} }
}
jar { jar {
version = jadxVersion version = jadxVersion
......
...@@ -6,6 +6,7 @@ import jadx.core.dex.visitors.BlockMakerVisitor; ...@@ -6,6 +6,7 @@ import jadx.core.dex.visitors.BlockMakerVisitor;
import jadx.core.dex.visitors.ClassModifier; import jadx.core.dex.visitors.ClassModifier;
import jadx.core.dex.visitors.CodeShrinker; import jadx.core.dex.visitors.CodeShrinker;
import jadx.core.dex.visitors.ConstInlinerVisitor; import jadx.core.dex.visitors.ConstInlinerVisitor;
import jadx.core.dex.visitors.DebugInfoVisitor;
import jadx.core.dex.visitors.DotGraphVisitor; import jadx.core.dex.visitors.DotGraphVisitor;
import jadx.core.dex.visitors.EnumVisitor; import jadx.core.dex.visitors.EnumVisitor;
import jadx.core.dex.visitors.FallbackModeVisitor; import jadx.core.dex.visitors.FallbackModeVisitor;
...@@ -54,6 +55,7 @@ public class Jadx { ...@@ -54,6 +55,7 @@ public class Jadx {
} else { } else {
passes.add(new BlockMakerVisitor()); passes.add(new BlockMakerVisitor());
passes.add(new SSATransform()); passes.add(new SSATransform());
passes.add(new DebugInfoVisitor());
passes.add(new TypeInference()); passes.add(new TypeInference());
passes.add(new ConstInlinerVisitor()); passes.add(new ConstInlinerVisitor());
......
...@@ -88,7 +88,7 @@ public class InsnGen { ...@@ -88,7 +88,7 @@ public class InsnGen {
public void addArg(CodeWriter code, InsnArg arg, boolean wrap) throws CodegenException { public void addArg(CodeWriter code, InsnArg arg, boolean wrap) throws CodegenException {
if (arg.isRegister()) { if (arg.isRegister()) {
code.add(mgen.makeArgName((RegisterArg) arg)); code.add(mgen.getNameGen().useArg((RegisterArg) arg));
} else if (arg.isLiteral()) { } else if (arg.isLiteral()) {
code.add(lit((LiteralArg) arg)); code.add(lit((LiteralArg) arg));
} else if (arg.isInsnWrap()) { } else if (arg.isInsnWrap()) {
...@@ -120,7 +120,7 @@ public class InsnGen { ...@@ -120,7 +120,7 @@ public class InsnGen {
public void declareVar(CodeWriter code, RegisterArg arg) { public void declareVar(CodeWriter code, RegisterArg arg) {
useType(code, arg.getType()); useType(code, arg.getType());
code.add(' '); code.add(' ');
code.add(mgen.assignArg(arg)); code.add(mgen.getNameGen().assignArg(arg));
} }
private static String lit(LiteralArg arg) { private static String lit(LiteralArg arg) {
......
package jadx.core.codegen; package jadx.core.codegen;
import jadx.core.Consts;
import jadx.core.dex.attributes.AFlag; import jadx.core.dex.attributes.AFlag;
import jadx.core.dex.attributes.AType; import jadx.core.dex.attributes.AType;
import jadx.core.dex.attributes.annotations.MethodParameters; import jadx.core.dex.attributes.annotations.MethodParameters;
import jadx.core.dex.attributes.nodes.JadxErrorAttr; import jadx.core.dex.attributes.nodes.JadxErrorAttr;
import jadx.core.dex.info.AccessInfo; import jadx.core.dex.info.AccessInfo;
import jadx.core.dex.instructions.args.ArgType; 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.RegisterArg;
import jadx.core.dex.nodes.InsnNode; import jadx.core.dex.nodes.InsnNode;
import jadx.core.dex.nodes.MethodNode; import jadx.core.dex.nodes.MethodNode;
...@@ -21,10 +19,8 @@ import jadx.core.utils.Utils; ...@@ -21,10 +19,8 @@ import jadx.core.utils.Utils;
import jadx.core.utils.exceptions.CodegenException; import jadx.core.utils.exceptions.CodegenException;
import jadx.core.utils.exceptions.DecodeException; import jadx.core.utils.exceptions.DecodeException;
import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Set;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
...@@ -36,27 +32,24 @@ public class MethodGen { ...@@ -36,27 +32,24 @@ public class MethodGen {
private final MethodNode mth; private final MethodNode mth;
private final ClassGen classGen; private final ClassGen classGen;
private final boolean fallback;
private final AnnotationGen annotationGen; private final AnnotationGen annotationGen;
private final NameGen nameGen;
private final Set<String> varNames = new HashSet<String>();
public MethodGen(ClassGen classGen, MethodNode mth) { public MethodGen(ClassGen classGen, MethodNode mth) {
this.mth = mth; this.mth = mth;
this.classGen = classGen; this.classGen = classGen;
this.fallback = classGen.isFallbackMode();
this.annotationGen = classGen.getAnnotationGen(); this.annotationGen = classGen.getAnnotationGen();
this.nameGen = new NameGen(classGen.isFallbackMode());
List<RegisterArg> args = mth.getArguments(true);
for (RegisterArg arg : args) {
varNames.add(makeArgName(arg));
}
} }
public ClassGen getClassGen() { public ClassGen getClassGen() {
return classGen; return classGen;
} }
public NameGen getNameGen() {
return nameGen;
}
public MethodNode getMethodNode() { public MethodNode getMethodNode() {
return mth; return mth;
} }
...@@ -124,9 +117,7 @@ public class MethodGen { ...@@ -124,9 +117,7 @@ public class MethodGen {
} }
private void addMethodArguments(CodeWriter argsCode, List<RegisterArg> args) { private void addMethodArguments(CodeWriter argsCode, List<RegisterArg> args) {
MethodParameters paramsAnnotation = MethodParameters paramsAnnotation = mth.get(AType.ANNOTATION_MTH_PARAMETERS);
mth.get(AType.ANNOTATION_MTH_PARAMETERS);
int i = 0; int i = 0;
for (Iterator<RegisterArg> it = args.iterator(); it.hasNext(); ) { for (Iterator<RegisterArg> it = args.iterator(); it.hasNext(); ) {
RegisterArg arg = it.next(); RegisterArg arg = it.next();
...@@ -150,7 +141,7 @@ public class MethodGen { ...@@ -150,7 +141,7 @@ public class MethodGen {
classGen.useType(argsCode, arg.getType()); classGen.useType(argsCode, arg.getType());
} }
argsCode.add(' '); argsCode.add(' ');
argsCode.add(makeArgName(arg)); argsCode.add(nameGen.assignArg(arg));
i++; i++;
if (it.hasNext()) { if (it.hasNext()) {
...@@ -159,74 +150,6 @@ public class MethodGen { ...@@ -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 { public void addInstructions(CodeWriter code) throws CodegenException {
if (mth.contains(AType.JADX_ERROR)) { if (mth.contains(AType.JADX_ERROR)) {
code.startLine("throw new UnsupportedOperationException(\"Method not decompiled: "); code.startLine("throw new UnsupportedOperationException(\"Method not decompiled: ");
...@@ -283,20 +206,23 @@ public class MethodGen { ...@@ -283,20 +206,23 @@ public class MethodGen {
return; return;
} }
} }
List<InsnNode> insns = mth.getInstructions(); InsnNode[] insnArr = mth.getInstructions();
if (insns == null) { if (insnArr == null) {
code.startLine("// Can't load method instructions."); code.startLine("// Can't load method instructions.");
return; return;
} }
if (mth.getThisArg() != null) { 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<InsnNode> insns, boolean addLabels) { public static void addFallbackInsns(CodeWriter code, MethodNode mth, InsnNode[] insnArr, boolean addLabels) {
InsnGen insnGen = new InsnGen(getFallbackMethodGen(mth), true); InsnGen insnGen = new InsnGen(getFallbackMethodGen(mth), true);
for (InsnNode insn : insns) { for (InsnNode insn : insnArr) {
if (insn == null) {
continue;
}
if (addLabels) { if (addLabels) {
if (insn.contains(AType.JUMP) if (insn.contains(AType.JUMP)
|| insn.contains(AType.EXC_HANDLER)) { || insn.contains(AType.EXC_HANDLER)) {
......
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<String> varNames = new HashSet<String>();
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());
}
}
...@@ -277,7 +277,7 @@ public class RegionGen extends InsnGen { ...@@ -277,7 +277,7 @@ public class RegionGen extends InsnGen {
useClass(code, handler.getCatchType()); useClass(code, handler.getCatchType());
} }
code.add(' '); code.add(' ');
code.add(mgen.assignNamedArg(handler.getArg())); code.add(mgen.getNameGen().assignNamedArg(handler.getArg()));
code.add(") {"); code.add(") {");
makeRegionIndent(code, region); makeRegionIndent(code, region);
} }
......
...@@ -26,7 +26,7 @@ public abstract class InsnArg extends Typed { ...@@ -26,7 +26,7 @@ public abstract class InsnArg extends Typed {
return reg(InsnUtils.getArg(insn, argNum), type); 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); return new MthParameterArg(regNum, type);
} }
...@@ -113,7 +113,7 @@ public abstract class InsnArg extends Typed { ...@@ -113,7 +113,7 @@ public abstract class InsnArg extends Typed {
} }
public boolean isThis() { public boolean isThis() {
// must be implemented in RegisterArg // must be implemented in RegisterArg and MthParameterArg
return false; return false;
} }
} }
...@@ -2,6 +2,8 @@ package jadx.core.dex.instructions.args; ...@@ -2,6 +2,8 @@ package jadx.core.dex.instructions.args;
public class MthParameterArg extends RegisterArg { public class MthParameterArg extends RegisterArg {
private boolean isThis = false;
public MthParameterArg(int rn, ArgType type) { public MthParameterArg(int rn, ArgType type) {
super(rn, type); super(rn, type);
} }
...@@ -14,4 +16,29 @@ public class MthParameterArg extends RegisterArg { ...@@ -14,4 +16,29 @@ public class MthParameterArg extends RegisterArg {
@Override @Override
public void setType(ArgType type) { 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);
}
} }
...@@ -11,7 +11,6 @@ import jadx.core.dex.nodes.DexNode; ...@@ -11,7 +11,6 @@ import jadx.core.dex.nodes.DexNode;
import jadx.core.dex.nodes.FieldNode; import jadx.core.dex.nodes.FieldNode;
import jadx.core.dex.nodes.InsnNode; import jadx.core.dex.nodes.InsnNode;
import jadx.core.dex.nodes.parser.FieldValueAttr; import jadx.core.dex.nodes.parser.FieldValueAttr;
import jadx.core.utils.exceptions.JadxRuntimeException;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
...@@ -21,7 +20,6 @@ public class RegisterArg extends InsnArg implements Named { ...@@ -21,7 +20,6 @@ public class RegisterArg extends InsnArg implements Named {
protected final int regNum; protected final int regNum;
protected SSAVar sVar; protected SSAVar sVar;
protected String name;
public RegisterArg(int rn) { public RegisterArg(int rn) {
this.regNum = rn; this.regNum = rn;
...@@ -49,32 +47,41 @@ public class RegisterArg extends InsnArg implements Named { ...@@ -49,32 +47,41 @@ public class RegisterArg extends InsnArg implements Named {
this.sVar = sVar; this.sVar = sVar;
} }
@Override public String getName() {
public void setType(ArgType type) { if (sVar == null) {
if (sVar != null) { return null;
sVar.setType(type);
} else {
throw new JadxRuntimeException("SSA variable equals null");
} }
return sVar.getName();
} }
public void forceType(ArgType type) { public void setName(String name) {
this.type = type; if (sVar != null) {
sVar.setName(name);
} }
public String getName() {
return name;
} }
public boolean isNameEquals(InsnArg arg) { public boolean isNameEquals(InsnArg arg) {
if (name == null || !(arg instanceof Named)) { String n = getName();
if (n == null || !(arg instanceof Named)) {
return false; return false;
} }
return name.equals(((Named) arg).getName()); return n.equals(((Named) arg).getName());
} }
public void setName(String newName) { @Override
this.name = newName; public void setType(ArgType type) {
if (sVar != null) {
sVar.setType(type);
}
}
public void mergeDebugInfo(ArgType type, String name) {
setType(type);
setName(name);
}
public void forceType(ArgType type) {
this.type = type;
} }
/** /**
...@@ -113,17 +120,15 @@ public class RegisterArg extends InsnArg implements Named { ...@@ -113,17 +120,15 @@ public class RegisterArg extends InsnArg implements Named {
@Override @Override
public boolean isThis() { public boolean isThis() {
if ("this".equals(name)) { if ("this".equals(getName())) {
return true; return true;
} }
// maybe it was moved from 'this' register // maybe it was moved from 'this' register
InsnNode ai = getAssignInsn(); InsnNode ai = getAssignInsn();
if (ai != null && ai.getType() == InsnType.MOVE) { if (ai != null && ai.getType() == InsnType.MOVE) {
InsnArg arg = ai.getArg(0); InsnArg arg = ai.getArg(0);
if (arg != this if (arg != this) {
&& arg.isRegister() return arg.isThis();
&& "this".equals(((RegisterArg) arg).getName())) {
return true;
} }
} }
return false; return false;
...@@ -196,8 +201,8 @@ public class RegisterArg extends InsnArg implements Named { ...@@ -196,8 +201,8 @@ public class RegisterArg extends InsnArg implements Named {
if (sVar != null) { if (sVar != null) {
sb.append("_").append(sVar.getVersion()); sb.append("_").append(sVar.getVersion());
} }
if (name != null) { if (getName() != null) {
sb.append(" '").append(name).append("'"); sb.append(" '").append(getName()).append("'");
} }
sb.append(" "); sb.append(" ");
sb.append(type); sb.append(type);
......
...@@ -9,6 +9,7 @@ public class SSAVar { ...@@ -9,6 +9,7 @@ public class SSAVar {
private final int regNum; private final int regNum;
private final int version; private final int version;
private VarName varName;
private RegisterArg assign; private RegisterArg assign;
private final List<RegisterArg> useList = new ArrayList<RegisterArg>(2); private final List<RegisterArg> useList = new ArrayList<RegisterArg>(2);
...@@ -22,7 +23,6 @@ public class SSAVar { ...@@ -22,7 +23,6 @@ public class SSAVar {
this.assign = assign; this.assign = assign;
if (assign != null) { if (assign != null) {
mergeName(assign);
assign.setSVar(this); assign.setSVar(this);
} }
} }
...@@ -52,7 +52,6 @@ public class SSAVar { ...@@ -52,7 +52,6 @@ public class SSAVar {
} }
public void use(RegisterArg arg) { public void use(RegisterArg arg) {
mergeName(arg);
if (arg.getSVar() != null) { if (arg.getSVar() != null) {
arg.getSVar().removeUse(arg); arg.getSVar().removeUse(arg);
} }
...@@ -103,35 +102,27 @@ public class SSAVar { ...@@ -103,35 +102,27 @@ public class SSAVar {
} }
public void setName(String name) { public void setName(String name) {
if (assign != null) { if (name != null) {
assign.setName(name); if (varName == null) {
varName = new VarName();
} }
for (int i = 0, useListSize = useList.size(); i < useListSize; i++) { varName.setName(name);
useList.get(i).setName(name);
} }
} }
public void setVariableName(String name) { public String getName() {
setName(name); if (varName == null) {
if (isUsedInPhi()) { return null;
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);
}
}
}
} }
return varName.getName();
} }
public void mergeName(RegisterArg arg) { public VarName getVarName() {
if (arg.getName() != null) { return varName;
setName(arg.getName());
} }
public void setVarName(VarName varName) {
this.varName = varName;
} }
@Override @Override
......
...@@ -28,12 +28,4 @@ public abstract class Typed { ...@@ -28,12 +28,4 @@ public abstract class Typed {
public boolean merge(InsnArg arg) { public boolean merge(InsnArg arg) {
return merge(arg.getType()); 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());
}
}
} }
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;
}
}
...@@ -15,9 +15,9 @@ import jadx.core.dex.instructions.InsnDecoder; ...@@ -15,9 +15,9 @@ import jadx.core.dex.instructions.InsnDecoder;
import jadx.core.dex.instructions.SwitchNode; import jadx.core.dex.instructions.SwitchNode;
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;
import jadx.core.dex.instructions.args.MthParameterArg;
import jadx.core.dex.instructions.args.RegisterArg; import jadx.core.dex.instructions.args.RegisterArg;
import jadx.core.dex.instructions.args.SSAVar; 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.nodes.parser.SignatureParser;
import jadx.core.dex.regions.Region; import jadx.core.dex.regions.Region;
import jadx.core.dex.trycatch.ExcHandlerAttr; import jadx.core.dex.trycatch.ExcHandlerAttr;
...@@ -51,7 +51,8 @@ public class MethodNode extends LineAttrNode implements ILoadable { ...@@ -51,7 +51,8 @@ public class MethodNode extends LineAttrNode implements ILoadable {
private final Method methodData; private final Method methodData;
private int regsCount; private int regsCount;
private List<InsnNode> instructions; private InsnNode[] instructions;
private int debugInfoOffset;
private boolean noCode; private boolean noCode;
private ArgType retType; private ArgType retType;
...@@ -92,30 +93,12 @@ public class MethodNode extends LineAttrNode implements ILoadable { ...@@ -92,30 +93,12 @@ public class MethodNode extends LineAttrNode implements ILoadable {
InsnDecoder decoder = new InsnDecoder(this); InsnDecoder decoder = new InsnDecoder(this);
decoder.decodeInsns(mthCode); decoder.decodeInsns(mthCode);
InsnNode[] insnByOffset = decoder.process(); instructions = decoder.process();
instructions = new ArrayList<InsnNode>();
for (InsnNode insn : insnByOffset) {
if (insn != null) {
instructions.add(insn);
}
}
((ArrayList<InsnNode>) instructions).trimToSize();
initTryCatches(mthCode, insnByOffset); initTryCatches(mthCode);
initJumps(insnByOffset); initJumps();
int debugInfoOffset = mthCode.getDebugInfoOffset(); this.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) { } catch (Exception e) {
if (!noCode) { if (!noCode) {
noCode = true; noCode = true;
...@@ -139,9 +122,7 @@ public class MethodNode extends LineAttrNode implements ILoadable { ...@@ -139,9 +122,7 @@ public class MethodNode extends LineAttrNode implements ILoadable {
if (noCode) { if (noCode) {
return; return;
} }
if (instructions != null) { instructions = null;
instructions.clear();
}
blocks = null; blocks = null;
exitBlocks = null; exitBlocks = null;
exceptionHandlers.clear(); exceptionHandlers.clear();
...@@ -199,8 +180,9 @@ public class MethodNode extends LineAttrNode implements ILoadable { ...@@ -199,8 +180,9 @@ public class MethodNode extends LineAttrNode implements ILoadable {
if (accFlags.isStatic()) { if (accFlags.isStatic()) {
thisArg = null; thisArg = null;
} else { } else {
thisArg = InsnArg.parameterReg(pos - 1, parentClass.getClassInfo().getType()); MthParameterArg arg = InsnArg.parameterReg(pos - 1, parentClass.getClassInfo().getType());
thisArg.setName("this"); arg.markAsThis();
thisArg = arg;
} }
if (args.isEmpty()) { if (args.isEmpty()) {
argsList = Collections.emptyList(); argsList = Collections.emptyList();
...@@ -241,7 +223,8 @@ public class MethodNode extends LineAttrNode implements ILoadable { ...@@ -241,7 +223,8 @@ public class MethodNode extends LineAttrNode implements ILoadable {
return genericMap; return genericMap;
} }
private void initTryCatches(Code mthCode, InsnNode[] insnByOffset) { private void initTryCatches(Code mthCode) {
InsnNode[] insnByOffset = instructions;
CatchHandler[] catchBlocks = mthCode.getCatchHandlers(); CatchHandler[] catchBlocks = mthCode.getCatchHandlers();
Try[] tries = mthCode.getTries(); Try[] tries = mthCode.getTries();
...@@ -311,9 +294,13 @@ public class MethodNode extends LineAttrNode implements ILoadable { ...@@ -311,9 +294,13 @@ public class MethodNode extends LineAttrNode implements ILoadable {
} }
} }
private void initJumps(InsnNode[] insnByOffset) { private void initJumps() {
for (InsnNode insn : getInstructions()) { InsnNode[] insnByOffset = instructions;
int offset = insn.getOffset(); for (int offset = 0; offset < insnByOffset.length; offset++) {
InsnNode insn = insnByOffset[offset];
if (insn == null) {
continue;
}
switch (insn.getType()) { switch (insn.getType()) {
case SWITCH: { case SWITCH: {
SwitchNode sw = (SwitchNode) insn; SwitchNode sw = (SwitchNode) insn;
...@@ -367,20 +354,20 @@ public class MethodNode extends LineAttrNode implements ILoadable { ...@@ -367,20 +354,20 @@ public class MethodNode extends LineAttrNode implements ILoadable {
return noCode; return noCode;
} }
public List<InsnNode> getInstructions() { public InsnNode[] getInstructions() {
return instructions; return instructions;
} }
public void unloadInsnArr() {
this.instructions = null;
}
public void initBasicBlocks() { public void initBasicBlocks() {
blocks = new ArrayList<BlockNode>(); blocks = new ArrayList<BlockNode>();
exitBlocks = new ArrayList<BlockNode>(1); exitBlocks = new ArrayList<BlockNode>(1);
} }
public void finishBasicBlocks() { public void finishBasicBlocks() {
// after filling basic blocks we don't need instructions list anymore
instructions.clear();
instructions = null;
((ArrayList<BlockNode>) blocks).trimToSize(); ((ArrayList<BlockNode>) blocks).trimToSize();
((ArrayList<BlockNode>) exitBlocks).trimToSize(); ((ArrayList<BlockNode>) exitBlocks).trimToSize();
...@@ -479,6 +466,10 @@ public class MethodNode extends LineAttrNode implements ILoadable { ...@@ -479,6 +466,10 @@ public class MethodNode extends LineAttrNode implements ILoadable {
return regsCount; return regsCount;
} }
public int getDebugInfoOffset() {
return debugInfoOffset;
}
public SSAVar makeNewSVar(int regNum, int[] versions, RegisterArg arg) { public SSAVar makeNewSVar(int regNum, int[] versions, RegisterArg arg) {
SSAVar var = new SSAVar(regNum, versions[regNum], arg); SSAVar var = new SSAVar(regNum, versions[regNum], arg);
versions[regNum]++; versions[regNum]++;
......
...@@ -226,19 +226,18 @@ public class DebugInfoParser { ...@@ -226,19 +226,18 @@ public class DebugInfoParser {
} }
private static void fillLocals(InsnNode insn, LocalVar var) { 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()) { for (InsnArg arg : insn.getArguments()) {
merge(arg, var); merge(arg, var);
} }
} }
private static void merge(InsnArg arg, LocalVar var) { private static void merge(InsnArg arg, LocalVar var) {
if (arg != null if (arg != null && arg.isRegister()) {
&& arg.isRegister() RegisterArg reg = (RegisterArg) arg;
&& var.getRegNum() == ((RegisterArg) arg).getRegNum()) { if (var.getRegNum() == reg.getRegNum()) {
arg.mergeDebugInfo(var); reg.mergeDebugInfo(var.getType(), var.getName());
}
} }
} }
} }
...@@ -8,17 +8,19 @@ import jadx.core.utils.InsnUtils; ...@@ -8,17 +8,19 @@ import jadx.core.utils.InsnUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
final class LocalVar extends RegisterArg { final class LocalVar {
private static final Logger LOG = LoggerFactory.getLogger(LocalVar.class); 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 startAddr;
private int endAddr; private int endAddr;
public LocalVar(DexNode dex, int rn, int nameId, int typeId, int signId) { 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)); String name = (nameId == DexNode.NO_INDEX ? null : dex.getString(nameId));
ArgType type = (typeId == DexNode.NO_INDEX ? null : dex.getType(typeId)); ArgType type = (typeId == DexNode.NO_INDEX ? null : dex.getType(typeId));
String sign = (signId == DexNode.NO_INDEX ? null : dex.getString(signId)); String sign = (signId == DexNode.NO_INDEX ? null : dex.getString(signId));
...@@ -27,7 +29,7 @@ final class LocalVar extends RegisterArg { ...@@ -27,7 +29,7 @@ final class LocalVar extends RegisterArg {
} }
public LocalVar(RegisterArg arg) { public LocalVar(RegisterArg arg) {
super(arg.getRegNum(), arg.getType()); this.regNum = arg.getRegNum();
init(arg.getName(), arg.getType(), null); init(arg.getName(), arg.getType(), null);
} }
...@@ -42,8 +44,8 @@ final class LocalVar extends RegisterArg { ...@@ -42,8 +44,8 @@ final class LocalVar extends RegisterArg {
LOG.error("Can't parse signature for local variable: " + sign, e); LOG.error("Can't parse signature for local variable: " + sign, e);
} }
} }
setName(name); this.name = name;
forceType(type); this.type = type;
} }
private boolean checkSignature(ArgType type, String sign, ArgType gType) { private boolean checkSignature(ArgType type, String sign, ArgType gType) {
...@@ -72,6 +74,18 @@ final class LocalVar extends RegisterArg { ...@@ -72,6 +74,18 @@ final class LocalVar extends RegisterArg {
this.endAddr = addr; this.endAddr = addr;
} }
public int getRegNum() {
return regNum;
}
public String getName() {
return name;
}
public ArgType getType() {
return type;
}
public boolean isEnd() { public boolean isEnd() {
return isEnd; return isEnd;
} }
......
...@@ -60,6 +60,9 @@ public class BlockMakerVisitor extends AbstractVisitor { ...@@ -60,6 +60,9 @@ public class BlockMakerVisitor extends AbstractVisitor {
// split into blocks // split into blocks
for (InsnNode insn : mth.getInstructions()) { for (InsnNode insn : mth.getInstructions()) {
if (insn == null) {
continue;
}
boolean startNew = false; boolean startNew = false;
if (prevInsn != null) { if (prevInsn != null) {
InsnType type = prevInsn.getType(); InsnType type = prevInsn.getType();
...@@ -443,10 +446,18 @@ public class BlockMakerVisitor extends AbstractVisitor { ...@@ -443,10 +446,18 @@ public class BlockMakerVisitor extends AbstractVisitor {
if (returnInsn.getArgsCount() != 0 && !isReturnArgAssignInPred(preds, returnInsn)) { if (returnInsn.getArgsCount() != 0 && !isReturnArgAssignInPred(preds, returnInsn)) {
return false; return false;
} }
boolean first = true;
for (BlockNode pred : preds) { for (BlockNode pred : preds) {
BlockNode newRetBlock = startNewBlock(mth, exitBlock.getStartOffset()); BlockNode newRetBlock = startNewBlock(mth, exitBlock.getStartOffset());
newRetBlock.add(AFlag.SYNTHETIC); 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); removeConnection(pred, exitBlock);
connect(pred, newRetBlock); connect(pred, newRetBlock);
} }
......
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();
}
}
...@@ -211,7 +211,9 @@ public class DotGraphVisitor extends AbstractVisitor { ...@@ -211,7 +211,9 @@ public class DotGraphVisitor extends AbstractVisitor {
return str.toString(); return str.toString();
} else { } else {
CodeWriter code = new CodeWriter(); CodeWriter code = new CodeWriter();
MethodGen.addFallbackInsns(code, mth, block.getInstructions(), false); List<InsnNode> instructions = block.getInstructions();
MethodGen.addFallbackInsns(code, mth,
instructions.toArray(new InsnNode[instructions.size()]), false);
String str = escape(code.newLine().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());
......
...@@ -14,6 +14,9 @@ public class FallbackModeVisitor extends AbstractVisitor { ...@@ -14,6 +14,9 @@ public class FallbackModeVisitor extends AbstractVisitor {
return; return;
} }
for (InsnNode insn : mth.getInstructions()) { for (InsnNode insn : mth.getInstructions()) {
if (insn == null) {
continue;
}
// remove 'exception catch' for instruction which don't throw any exceptions // remove 'exception catch' for instruction which don't throw any exceptions
CatchAttr catchAttr = insn.get(AType.CATCH_BLOCK); CatchAttr catchAttr = insn.get(AType.CATCH_BLOCK);
if (catchAttr != null) { if (catchAttr != null) {
......
...@@ -5,6 +5,7 @@ import jadx.core.dex.attributes.AType; ...@@ -5,6 +5,7 @@ import jadx.core.dex.attributes.AType;
import jadx.core.dex.attributes.nodes.DeclareVariablesAttr; import jadx.core.dex.attributes.nodes.DeclareVariablesAttr;
import jadx.core.dex.instructions.args.ArgType; import jadx.core.dex.instructions.args.ArgType;
import jadx.core.dex.instructions.args.RegisterArg; 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.IBlock;
import jadx.core.dex.nodes.IContainer; import jadx.core.dex.nodes.IContainer;
import jadx.core.dex.nodes.IRegion; import jadx.core.dex.nodes.IRegion;
...@@ -66,6 +67,7 @@ public class ProcessVariables extends AbstractVisitor { ...@@ -66,6 +67,7 @@ public class ProcessVariables extends AbstractVisitor {
private static class Usage { private static class Usage {
private RegisterArg arg; private RegisterArg arg;
private VarName varName;
private IRegion argRegion; private IRegion argRegion;
private final Set<IRegion> usage = new HashSet<IRegion>(2); private final Set<IRegion> usage = new HashSet<IRegion>(2);
private final Set<IRegion> assigns = new HashSet<IRegion>(2); private final Set<IRegion> assigns = new HashSet<IRegion>(2);
...@@ -78,6 +80,14 @@ public class ProcessVariables extends AbstractVisitor { ...@@ -78,6 +80,14 @@ public class ProcessVariables extends AbstractVisitor {
return arg; return arg;
} }
public VarName getVarName() {
return varName;
}
public void setVarName(VarName varName) {
this.varName = varName;
}
public void setArgRegion(IRegion argRegion) { public void setArgRegion(IRegion argRegion) {
this.argRegion = argRegion; this.argRegion = argRegion;
} }
...@@ -102,7 +112,14 @@ public class ProcessVariables extends AbstractVisitor { ...@@ -102,7 +112,14 @@ public class ProcessVariables extends AbstractVisitor {
@Override @Override
public void visit(MethodNode mth) throws JadxException { public void visit(MethodNode mth) throws JadxException {
if (mth.isNoCode()) {
return;
}
final Map<Variable, Usage> usageMap = new LinkedHashMap<Variable, Usage>(); final Map<Variable, Usage> usageMap = new LinkedHashMap<Variable, Usage>();
for (RegisterArg arg : mth.getArguments(true)) {
addToUsageMap(arg, usageMap);
}
// collect all variables usage // collect all variables usage
IRegionVisitor collect = new TracedRegionVisitor() { IRegionVisitor collect = new TracedRegionVisitor() {
...@@ -210,6 +227,17 @@ public class ProcessVariables extends AbstractVisitor { ...@@ -210,6 +227,17 @@ public class ProcessVariables extends AbstractVisitor {
usage = new Usage(); usage = new Usage();
usageMap.put(varId, 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; return usage;
} }
......
...@@ -3,7 +3,6 @@ package jadx.core.dex.visitors.ssa; ...@@ -3,7 +3,6 @@ package jadx.core.dex.visitors.ssa;
import jadx.core.dex.attributes.AType; import jadx.core.dex.attributes.AType;
import jadx.core.dex.attributes.nodes.PhiListAttr; import jadx.core.dex.attributes.nodes.PhiListAttr;
import jadx.core.dex.instructions.PhiInsn; import jadx.core.dex.instructions.PhiInsn;
import jadx.core.dex.instructions.args.SSAVar;
import jadx.core.dex.nodes.BlockNode; import jadx.core.dex.nodes.BlockNode;
import jadx.core.dex.nodes.InsnNode; import jadx.core.dex.nodes.InsnNode;
import jadx.core.dex.nodes.MethodNode; import jadx.core.dex.nodes.MethodNode;
...@@ -19,56 +18,9 @@ public class EliminatePhiNodes extends AbstractVisitor { ...@@ -19,56 +18,9 @@ public class EliminatePhiNodes extends AbstractVisitor {
if (mth.isNoCode()) { if (mth.isNoCode()) {
return; return;
} }
enumerateSVars(mth);
removePhiInstructions(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<SSAVar> vars = mth.getSVars();
// int varsSize = vars.size();
// Deque<SSAVar> workList = new LinkedList<SSAVar>();
// 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) { private static void removePhiInstructions(MethodNode mth) {
for (BlockNode block : mth.getBasicBlocks()) { for (BlockNode block : mth.getBasicBlocks()) {
PhiListAttr phiList = block.get(AType.PHI_LIST); PhiListAttr phiList = block.get(AType.PHI_LIST);
......
...@@ -32,7 +32,7 @@ public class SSATransform extends AbstractVisitor { ...@@ -32,7 +32,7 @@ public class SSATransform extends AbstractVisitor {
process(mth); process(mth);
} }
public void process(MethodNode mth) { private void process(MethodNode mth) {
LiveVarAnalysis la = new LiveVarAnalysis(mth); LiveVarAnalysis la = new LiveVarAnalysis(mth);
la.runAnalysis(); la.runAnalysis();
for (int i = 0; i < mth.getRegsCount(); i++) { for (int i = 0; i < mth.getRegsCount(); i++) {
......
...@@ -82,7 +82,7 @@ public class TypeInference extends AbstractVisitor { ...@@ -82,7 +82,7 @@ public class TypeInference extends AbstractVisitor {
for (int i = 0; i < phi.getArgsCount(); i++) { for (int i = 0; i < phi.getArgsCount(); i++) {
RegisterArg arg = phi.getArg(i); RegisterArg arg = phi.getArg(i);
arg.setType(type); arg.setType(type);
arg.getSVar().mergeName(phi.getResult()); arg.getSVar().setName(phi.getResult().getName());
} }
} }
......
...@@ -31,8 +31,8 @@ public class TestInline2 extends InternalJadxTest { ...@@ -31,8 +31,8 @@ public class TestInline2 extends InternalJadxTest {
System.out.println(code); System.out.println(code);
assertThat(code, containsString("i < a.length")); assertThat(code, containsString("i < a.length"));
assertThat(code, containsString("long i_2 =")); assertThat(code, containsString("long i2 ="));
assertThat(code, containsString("+ i_2")); assertThat(code, containsString("+ i2"));
assertThat(code, containsString("i_2--;")); assertThat(code, containsString("i2--;"));
} }
} }
...@@ -36,8 +36,9 @@ public abstract class AbstractTest { ...@@ -36,8 +36,9 @@ public abstract class AbstractTest {
public static void assertEquals(Object a1, Object a2) { public static void assertEquals(Object a1, Object a2) {
if (a1 == null) { if (a1 == null) {
if (a2 != null) if (a2 != null) {
throw new AssertionError(a1 + " != " + a2); throw new AssertionError(a1 + " != " + a2);
}
} else if (!a1.equals(a2)) { } else if (!a1.equals(a2)) {
throw new AssertionError(a1 + " != " + a2); throw new AssertionError(a1 + " != " + a2);
} }
......
...@@ -50,7 +50,7 @@ public class TestAnnotations extends AbstractTest { ...@@ -50,7 +50,7 @@ public class TestAnnotations extends AbstractTest {
@MyAnnotation(name = "b", @MyAnnotation(name = "b",
num = 7, num = 7,
cls = Exception.class, cls = Exception.class,
doubles = { 0.0, 1.1 }, doubles = {0.0, 1.1},
value = 9.87f, value = 9.87f,
simple = @SimpleAnnotation(false)) simple = @SimpleAnnotation(false))
public static Object test(String[] a) { public static Object test(String[] a) {
......
...@@ -22,11 +22,12 @@ public class TestCF extends AbstractTest { ...@@ -22,11 +22,12 @@ public class TestCF extends AbstractTest {
public int test1b(int a) { public int test1b(int a) {
if (a > 0) { if (a > 0) {
if (a < 5) if (a < 5) {
a++; a++;
else } else {
a -= 2; a -= 2;
} }
}
a *= 2; a *= 2;
return a + 3; return a + 3;
...@@ -134,16 +135,17 @@ public class TestCF extends AbstractTest { ...@@ -134,16 +135,17 @@ public class TestCF extends AbstractTest {
public int testIfElse(String str) { public int testIfElse(String str) {
int r; int r;
if (str.equals("a")) if (str.equals("a")) {
r = 1; r = 1;
else if (str.equals("b")) } else if (str.equals("b")) {
r = 2; r = 2;
else if (str.equals("3")) } else if (str.equals("3")) {
r = 3; r = 3;
else if (str.equals("$")) } else if (str.equals("$")) {
r = 4; r = 4;
else } else {
r = -1; r = -1;
}
r = r * 10; r = r * 10;
return Math.abs(r); return Math.abs(r);
......
...@@ -5,7 +5,7 @@ public class TestCF2 extends AbstractTest { ...@@ -5,7 +5,7 @@ public class TestCF2 extends AbstractTest {
private boolean ready = false; private boolean ready = false;
public int simple_loops() throws InterruptedException { 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; int b = 0;
for (int i = 0; i < a.length; i++) { for (int i = 0; i < a.length; i++) {
b += a[i]; b += a[i];
...@@ -21,8 +21,9 @@ public class TestCF2 extends AbstractTest { ...@@ -21,8 +21,9 @@ public class TestCF2 extends AbstractTest {
*/ */
public void run() throws InterruptedException { public void run() throws InterruptedException {
while (true) { while (true) {
if (!ready) if (!ready) {
ready_mutex.wait(); ready_mutex.wait();
}
ready = false; ready = false;
func(); func();
} }
...@@ -88,8 +89,9 @@ public class TestCF2 extends AbstractTest { ...@@ -88,8 +89,9 @@ public class TestCF2 extends AbstractTest {
public void do_while_return2(boolean k) throws InterruptedException { public void do_while_return2(boolean k) throws InterruptedException {
int i = 3; int i = 3;
do { do {
if (k) if (k) {
return; return;
}
i++; i++;
} while (i < 5); } while (i < 5);
} }
......
...@@ -3,8 +3,9 @@ package jadx.samples; ...@@ -3,8 +3,9 @@ package jadx.samples;
public class TestDeadCode extends AbstractTest { public class TestDeadCode extends AbstractTest {
private void test1(int i) { private void test1(int i) {
if (i == 0) if (i == 0) {
return; return;
}
return; return;
} }
......
...@@ -77,7 +77,7 @@ public class TestGenerics extends AbstractTest { ...@@ -77,7 +77,7 @@ public class TestGenerics extends AbstractTest {
public static boolean use() { public static boolean use() {
Pair<Integer, String> p1 = new OrderedPair<Integer, String>(1, "str1"); Pair<Integer, String> p1 = new OrderedPair<Integer, String>(1, "str1");
Pair<Integer, String> p2 = new OrderedPair<Integer, String>(2, "str2"); Pair<Integer, String> p2 = new OrderedPair<Integer, String>(2, "str2");
boolean same = Util.<Integer, String> compare(p1, p2); boolean same = Util.<Integer, String>compare(p1, p2);
return same; return same;
} }
...@@ -107,9 +107,11 @@ public class TestGenerics extends AbstractTest { ...@@ -107,9 +107,11 @@ public class TestGenerics extends AbstractTest {
public static <T extends Comparable<T>> int countGreaterThan(T[] anArray, T elem) { public static <T extends Comparable<T>> int countGreaterThan(T[] anArray, T elem) {
int count = 0; int count = 0;
for (T e : anArray) for (T e : anArray) {
if (e.compareTo(elem) > 0) if (e.compareTo(elem) > 0) {
++count; ++count;
}
}
return count; return count;
} }
...@@ -117,8 +119,9 @@ public class TestGenerics extends AbstractTest { ...@@ -117,8 +119,9 @@ public class TestGenerics extends AbstractTest {
} }
public static void printList(List<?> list) { public static void printList(List<?> list) {
for (Object elem : list) for (Object elem : list) {
System.out.print(elem + " "); System.out.print(elem + " ");
}
System.out.println(); System.out.println();
} }
......
...@@ -56,6 +56,7 @@ public class TestInner extends AbstractTest { ...@@ -56,6 +56,7 @@ public class TestInner extends AbstractTest {
{ {
count += 5; count += 5;
} }
@Override @Override
public void run() { public void run() {
count += 6; count += 6;
...@@ -68,6 +69,7 @@ public class TestInner extends AbstractTest { ...@@ -68,6 +69,7 @@ public class TestInner extends AbstractTest {
{ {
count += 7; count += 7;
} }
@Override @Override
public String toString() { public String toString() {
count += 8; count += 8;
......
...@@ -73,7 +73,7 @@ public class TestInner2 extends AbstractTest { ...@@ -73,7 +73,7 @@ public class TestInner2 extends AbstractTest {
Method[] mths = TestInner2.class.getDeclaredMethods(); Method[] mths = TestInner2.class.getDeclaredMethods();
for (Method mth : mths) { for (Method mth : mths) {
if(mth.getName().startsWith("access$")) { if (mth.getName().startsWith("access$")) {
int modifiers = mth.getModifiers(); int modifiers = mth.getModifiers();
assertTrue((modifiers & SYNTHETIC) != 0, "Synthetic methods must be removed"); assertTrue((modifiers & SYNTHETIC) != 0, "Synthetic methods must be removed");
} }
......
...@@ -14,11 +14,12 @@ public class TestInvoke extends AbstractTest { ...@@ -14,11 +14,12 @@ public class TestInvoke extends AbstractTest {
} }
private void parse(String[] args) { private void parse(String[] args) {
if (args.length > 0) if (args.length > 0) {
f = Integer.parseInt(args[0]); f = Integer.parseInt(args[0]);
else } else {
f = 20; f = 20;
} }
}
public int getF() { public int getF() {
return f; return f;
...@@ -37,18 +38,26 @@ public class TestInvoke extends AbstractTest { ...@@ -37,18 +38,26 @@ public class TestInvoke extends AbstractTest {
return s; return s;
} }
private String testSameArgTypes(String s1, String s2) {
if (s1.equals(s2)) {
return null;
}
return s1;
}
@Override @Override
public boolean testRun() throws Exception { public boolean testRun() throws Exception {
TestInvoke inv = new TestInvoke(); TestInvoke inv = new TestInvoke();
inv.parse(new String[] { "12", "35" }); inv.parse(new String[]{"12", "35"});
assertTrue(inv.getF() == 12); assertTrue(inv.getF() == 12);
inv.parse(new String[0]); inv.parse(new String[0]);
assertTrue(inv.getF() == 20); assertTrue(inv.getF() == 20);
assertTrue(inv.testVarArgs("a", "2", "III")); 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; return true;
} }
......
...@@ -43,10 +43,11 @@ public class TestSwitch extends AbstractTest { ...@@ -43,10 +43,11 @@ public class TestSwitch extends AbstractTest {
int k = i; int k = i;
switch (k) { switch (k) {
case 1: case 1:
if (j == 0) if (j == 0) {
return 0; return 0;
else } else {
return -1; return -1;
}
case 2: case 2:
return 1; return 1;
} }
...@@ -69,8 +70,9 @@ public class TestSwitch extends AbstractTest { ...@@ -69,8 +70,9 @@ public class TestSwitch extends AbstractTest {
int k = i; int k = i;
switch (k) { switch (k) {
case 1: case 1:
if (b == 0) if (b == 0) {
return 3; return 3;
}
case 2: case 2:
b++; b++;
......
...@@ -5,14 +5,16 @@ import java.io.IOException; ...@@ -5,14 +5,16 @@ import java.io.IOException;
public class TestTryCatch extends AbstractTest { public class TestTryCatch extends AbstractTest {
private static boolean exc(Object obj) throws Exception { private static boolean exc(Object obj) throws Exception {
if (obj == null) if (obj == null) {
throw new Exception("test"); throw new Exception("test");
}
return (obj instanceof Object); return (obj instanceof Object);
} }
private static boolean exc2(Object obj) throws IOException { private static boolean exc2(Object obj) throws IOException {
if (obj == null) if (obj == null) {
throw new IOException(); throw new IOException();
}
return true; return true;
} }
...@@ -41,12 +43,13 @@ public class TestTryCatch extends AbstractTest { ...@@ -41,12 +43,13 @@ public class TestTryCatch extends AbstractTest {
try { try {
return exc(obj); return exc(obj);
} catch (Exception e) { } catch (Exception e) {
if (obj != null) if (obj != null) {
return true; return true;
else } else {
return false; return false;
} }
} }
}
private static boolean test3(Object obj) { private static boolean test3(Object obj) {
boolean res = false; boolean res = false;
...@@ -78,8 +81,9 @@ public class TestTryCatch extends AbstractTest { ...@@ -78,8 +81,9 @@ public class TestTryCatch extends AbstractTest {
try { try {
res = "" + exc(obj); res = "" + exc(obj);
boolean f = exc2("a"); boolean f = exc2("a");
if (!f) if (!f) {
res = "f == false"; res = "f == false";
}
} catch (Exception e) { } catch (Exception e) {
res = "exc"; res = "exc";
} }
...@@ -95,11 +99,12 @@ public class TestTryCatch extends AbstractTest { ...@@ -95,11 +99,12 @@ public class TestTryCatch extends AbstractTest {
} catch (IOException e) { } catch (IOException e) {
res = true; res = true;
} catch (Throwable e) { } catch (Throwable e) {
if (obj == null) if (obj == null) {
obj = new Object(); obj = new Object();
} }
} }
} }
}
private static boolean test7() { private static boolean test7() {
boolean res = false; boolean res = false;
...@@ -112,11 +117,12 @@ public class TestTryCatch extends AbstractTest { ...@@ -112,11 +117,12 @@ public class TestTryCatch extends AbstractTest {
res = true; res = true;
obj = new Object(); obj = new Object();
} catch (Throwable e) { } catch (Throwable e) {
if (obj == null) if (obj == null) {
res = false; res = false;
} }
} }
} }
}
private boolean test8(Object obj) { private boolean test8(Object obj) {
this.mDiscovering = false; this.mDiscovering = false;
...@@ -137,16 +143,18 @@ public class TestTryCatch extends AbstractTest { ...@@ -137,16 +143,18 @@ public class TestTryCatch extends AbstractTest {
} catch (Exception e) { } catch (Exception e) {
e.toString(); e.toString();
} finally { } finally {
if (!mDiscovering) if (!mDiscovering) {
mDiscovering = true; mDiscovering = true;
} }
}
return mDiscovering; return mDiscovering;
} }
private static boolean testSynchronize(Object obj) throws InterruptedException { private static boolean testSynchronize(Object obj) throws InterruptedException {
synchronized (obj) { synchronized (obj) {
if (obj instanceof String) if (obj instanceof String) {
return false; return false;
}
obj.wait(5); obj.wait(5);
} }
return true; return true;
...@@ -171,8 +179,9 @@ public class TestTryCatch extends AbstractTest { ...@@ -171,8 +179,9 @@ public class TestTryCatch extends AbstractTest {
public int catchInLoop(int i, int j) { public int catchInLoop(int i, int j) {
while (true) { while (true) {
try { try {
while (i < j) while (i < j) {
i = j++ / i; i = j++ / i;
}
} catch (RuntimeException e) { } catch (RuntimeException e) {
i = 10; i = 10;
continue; continue;
......
rootProject.name = 'jadx'
include 'jadx-core', 'jadx-samples', 'jadx-cli', 'jadx-gui' include 'jadx-core', 'jadx-samples', 'jadx-cli', 'jadx-gui'
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