Commit e3606d1b authored by Skylot's avatar Skylot

reformat code (force braces)

parent ab593e3c
...@@ -26,11 +26,14 @@ public final class JavaPackage implements Comparable<JavaPackage> { ...@@ -26,11 +26,14 @@ public final class JavaPackage implements Comparable<JavaPackage> {
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (this == o) return true; if (this == o) {
if (o == null || getClass() != o.getClass()) return false; return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
JavaPackage that = (JavaPackage) o; JavaPackage that = (JavaPackage) o;
if (!name.equals(that.name)) return false; return name.equals(that.name);
return true;
} }
@Override @Override
......
...@@ -37,10 +37,12 @@ public class Jadx { ...@@ -37,10 +37,12 @@ public class Jadx {
private static final Logger LOG = LoggerFactory.getLogger(Jadx.class); private static final Logger LOG = LoggerFactory.getLogger(Jadx.class);
static { static {
if (Consts.DEBUG) if (Consts.DEBUG) {
LOG.info("debug enabled"); LOG.info("debug enabled");
if (Jadx.class.desiredAssertionStatus()) }
if (Jadx.class.desiredAssertionStatus()) {
LOG.info("assertions enabled"); LOG.info("assertions enabled");
}
} }
public static List<IDexTreeVisitor> getPassesList(IJadxArgs args, File outDir) { public static List<IDexTreeVisitor> getPassesList(IJadxArgs args, File outDir) {
...@@ -52,8 +54,9 @@ public class Jadx { ...@@ -52,8 +54,9 @@ public class Jadx {
passes.add(new TypeResolver()); passes.add(new TypeResolver());
if (args.isRawCFGOutput()) if (args.isRawCFGOutput()) {
passes.add(new DotGraphVisitor(outDir, false, true)); passes.add(new DotGraphVisitor(outDir, false, true));
}
passes.add(new ConstInlinerVisitor()); passes.add(new ConstInlinerVisitor());
passes.add(new FinishTypeResolver()); passes.add(new FinishTypeResolver());
...@@ -61,8 +64,9 @@ public class Jadx { ...@@ -61,8 +64,9 @@ public class Jadx {
passes.add(new ModVisitor()); passes.add(new ModVisitor());
passes.add(new EnumVisitor()); passes.add(new EnumVisitor());
if (args.isCFGOutput()) if (args.isCFGOutput()) {
passes.add(new DotGraphVisitor(outDir, false)); passes.add(new DotGraphVisitor(outDir, false));
}
passes.add(new RegionMakerVisitor()); passes.add(new RegionMakerVisitor());
passes.add(new PostRegionVisitor()); passes.add(new PostRegionVisitor());
...@@ -71,8 +75,10 @@ public class Jadx { ...@@ -71,8 +75,10 @@ public class Jadx {
passes.add(new SimplifyVisitor()); passes.add(new SimplifyVisitor());
passes.add(new ProcessVariables()); passes.add(new ProcessVariables());
passes.add(new CheckRegions()); passes.add(new CheckRegions());
if (args.isCFGOutput())
if (args.isCFGOutput()) {
passes.add(new DotGraphVisitor(outDir, true)); passes.add(new DotGraphVisitor(outDir, true));
}
passes.add(new MethodInlinerVisitor()); passes.add(new MethodInlinerVisitor());
passes.add(new ClassModifier()); passes.add(new ClassModifier());
...@@ -88,8 +94,9 @@ public class Jadx { ...@@ -88,8 +94,9 @@ public class Jadx {
while (resources.hasMoreElements()) { while (resources.hasMoreElements()) {
Manifest manifest = new Manifest(resources.nextElement().openStream()); Manifest manifest = new Manifest(resources.nextElement().openStream());
String ver = manifest.getMainAttributes().getValue("jadx-version"); String ver = manifest.getMainAttributes().getValue("jadx-version");
if (ver != null) if (ver != null) {
return ver; return ver;
}
} }
} catch (IOException e) { } catch (IOException e) {
LOG.error("Can't get manifest file", e); LOG.error("Can't get manifest file", e);
......
...@@ -82,8 +82,9 @@ public class ClspGraph { ...@@ -82,8 +82,9 @@ public class ClspGraph {
return name; return name;
} else { } else {
String r = searchCommonParent(anc, p); String r = searchCommonParent(anc, p);
if (r != null) if (r != null) {
return r; return r;
}
} }
} }
return null; return null;
......
...@@ -41,11 +41,14 @@ public class NClass { ...@@ -41,11 +41,14 @@ public class NClass {
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (this == o) return true; if (this == o) {
if (o == null || getClass() != o.getClass()) return false; return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
NClass nClass = (NClass) o; NClass nClass = (NClass) o;
if (!name.equals(nClass.name)) return false; return name.equals(nClass.name);
return true;
} }
@Override @Override
......
...@@ -43,9 +43,9 @@ public class AnnotationGen { ...@@ -43,9 +43,9 @@ public class AnnotationGen {
public void addForParameter(CodeWriter code, MethodParameters paramsAnnotations, int n) { public void addForParameter(CodeWriter code, MethodParameters paramsAnnotations, int n) {
AnnotationsList aList = paramsAnnotations.getParamList().get(n); AnnotationsList aList = paramsAnnotations.getParamList().get(n);
if (aList == null || aList.size() == 0) if (aList == null || aList.size() == 0) {
return; return;
}
for (Annotation a : aList.getAll()) { for (Annotation a : aList.getAll()) {
code.add(formatAnnotation(a)); code.add(formatAnnotation(a));
code.add(' '); code.add(' ');
...@@ -54,9 +54,9 @@ public class AnnotationGen { ...@@ -54,9 +54,9 @@ public class AnnotationGen {
private void add(IAttributeNode node, CodeWriter code) { private void add(IAttributeNode node, CodeWriter code) {
AnnotationsList aList = (AnnotationsList) node.getAttributes().get(AttributeType.ANNOTATION_LIST); AnnotationsList aList = (AnnotationsList) node.getAttributes().get(AttributeType.ANNOTATION_LIST);
if (aList == null || aList.size() == 0) if (aList == null || aList.size() == 0) {
return; return;
}
for (Annotation a : aList.getAll()) { for (Annotation a : aList.getAll()) {
String aCls = a.getAnnotationClass(); String aCls = a.getAnnotationClass();
if (aCls.startsWith(Consts.DALVIK_ANNOTATION_PKG)) { if (aCls.startsWith(Consts.DALVIK_ANNOTATION_PKG)) {
...@@ -86,8 +86,9 @@ public class AnnotationGen { ...@@ -86,8 +86,9 @@ public class AnnotationGen {
code.add(e.getKey()); code.add(e.getKey());
code.add(" = "); code.add(" = ");
code.add(encValueToString(e.getValue())); code.add(encValueToString(e.getValue()));
if (it.hasNext()) if (it.hasNext()) {
code.add(", "); code.add(", ");
}
} }
} }
code.add(')'); code.add(')');
...@@ -104,8 +105,9 @@ public class AnnotationGen { ...@@ -104,8 +105,9 @@ public class AnnotationGen {
for (Iterator<ArgType> it = ((List<ArgType>) exs).iterator(); it.hasNext(); ) { for (Iterator<ArgType> it = ((List<ArgType>) exs).iterator(); it.hasNext(); ) {
ArgType ex = it.next(); ArgType ex = it.next();
code.add(TypeGen.translate(classGen, ex)); code.add(TypeGen.translate(classGen, ex));
if (it.hasNext()) if (it.hasNext()) {
code.add(", "); code.add(", ");
}
} }
} }
} }
...@@ -122,31 +124,39 @@ public class AnnotationGen { ...@@ -122,31 +124,39 @@ public class AnnotationGen {
// TODO: refactor this boilerplate code // TODO: refactor this boilerplate code
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public String encValueToString(Object val) { public String encValueToString(Object val) {
if (val == null) if (val == null) {
return "null"; return "null";
}
if (val instanceof String) if (val instanceof String) {
return StringUtils.unescapeString((String) val); return StringUtils.unescapeString((String) val);
if (val instanceof Integer) }
if (val instanceof Integer) {
return TypeGen.formatInteger((Integer) val); return TypeGen.formatInteger((Integer) val);
if (val instanceof Character) }
if (val instanceof Character) {
return StringUtils.unescapeChar((Character) val); return StringUtils.unescapeChar((Character) val);
if (val instanceof Boolean) }
if (val instanceof Boolean) {
return Boolean.TRUE.equals(val) ? "true" : "false"; return Boolean.TRUE.equals(val) ? "true" : "false";
if (val instanceof Float) }
if (val instanceof Float) {
return TypeGen.formatFloat((Float) val); return TypeGen.formatFloat((Float) val);
if (val instanceof Double) }
if (val instanceof Double) {
return TypeGen.formatDouble((Double) val); return TypeGen.formatDouble((Double) val);
if (val instanceof Long) }
if (val instanceof Long) {
return TypeGen.formatLong((Long) val); return TypeGen.formatLong((Long) val);
if (val instanceof Short) }
if (val instanceof Short) {
return TypeGen.formatShort((Short) val); return TypeGen.formatShort((Short) val);
if (val instanceof Byte) }
if (val instanceof Byte) {
return TypeGen.formatByte((Byte) val); return TypeGen.formatByte((Byte) val);
}
if (val instanceof ArgType) if (val instanceof ArgType) {
return TypeGen.translate(classGen, (ArgType) val) + ".class"; return TypeGen.translate(classGen, (ArgType) val) + ".class";
}
if (val instanceof FieldInfo) { if (val instanceof FieldInfo) {
// must be a static field // must be a static field
FieldInfo field = (FieldInfo) val; FieldInfo field = (FieldInfo) val;
...@@ -158,7 +168,6 @@ public class AnnotationGen { ...@@ -158,7 +168,6 @@ public class AnnotationGen {
return classGen.useClass(field.getDeclClass()) + '.' + field.getName(); return classGen.useClass(field.getDeclClass()) + '.' + field.getName();
} }
} }
if (val instanceof List) { if (val instanceof List) {
StringBuilder str = new StringBuilder(); StringBuilder str = new StringBuilder();
str.append('{'); str.append('{');
...@@ -166,19 +175,17 @@ public class AnnotationGen { ...@@ -166,19 +175,17 @@ public class AnnotationGen {
for (Iterator<Object> it = list.iterator(); it.hasNext(); ) { for (Iterator<Object> it = list.iterator(); it.hasNext(); ) {
Object obj = it.next(); Object obj = it.next();
str.append(encValueToString(obj)); str.append(encValueToString(obj));
if (it.hasNext()) if (it.hasNext()) {
str.append(", "); str.append(", ");
}
} }
str.append('}'); str.append('}');
return str.toString(); return str.toString();
} }
if (val instanceof Annotation) { if (val instanceof Annotation) {
return formatAnnotation((Annotation) val).toString(); return formatAnnotation((Annotation) val).toString();
} }
// TODO: also can be method values // TODO: also can be method values
throw new JadxRuntimeException("Can't decode value: " + val + " (" + val.getClass() + ")"); throw new JadxRuntimeException("Can't decode value: " + val + " (" + val.getClass() + ")");
} }
} }
...@@ -90,12 +90,12 @@ public class ClassGen { ...@@ -90,12 +90,12 @@ public class ClassGen {
} }
public void addClassCode(CodeWriter code) throws CodegenException { public void addClassCode(CodeWriter code) throws CodegenException {
if (cls.getAttributes().contains(AttributeFlag.DONT_GENERATE)) if (cls.getAttributes().contains(AttributeFlag.DONT_GENERATE)) {
return; return;
}
if (cls.getAttributes().contains(AttributeFlag.INCONSISTENT_CODE)) if (cls.getAttributes().contains(AttributeFlag.INCONSISTENT_CODE)) {
code.startLine("// jadx: inconsistent code"); code.startLine("// jadx: inconsistent code");
}
makeClassDeclaration(code); makeClassDeclaration(code);
makeClassBody(code); makeClassBody(code);
code.newLine(); code.newLine();
...@@ -113,8 +113,9 @@ public class ClassGen { ...@@ -113,8 +113,9 @@ public class ClassGen {
insertSourceFileInfo(clsCode, cls); insertSourceFileInfo(clsCode, cls);
clsCode.startLine(af.makeString()); clsCode.startLine(af.makeString());
if (af.isInterface()) { if (af.isInterface()) {
if (af.isAnnotation()) if (af.isAnnotation()) {
clsCode.add('@'); clsCode.add('@');
}
clsCode.add("interface "); clsCode.add("interface ");
} else if (af.isEnum()) { } else if (af.isEnum()) {
clsCode.add("enum "); clsCode.add("enum ");
...@@ -134,28 +135,30 @@ public class ClassGen { ...@@ -134,28 +135,30 @@ public class ClassGen {
} }
if (cls.getInterfaces().size() > 0 && !af.isAnnotation()) { if (cls.getInterfaces().size() > 0 && !af.isAnnotation()) {
if (cls.getAccessFlags().isInterface()) if (cls.getAccessFlags().isInterface()) {
clsCode.add("extends "); clsCode.add("extends ");
else } else {
clsCode.add("implements "); clsCode.add("implements ");
}
for (Iterator<ClassInfo> it = cls.getInterfaces().iterator(); it.hasNext(); ) { for (Iterator<ClassInfo> it = cls.getInterfaces().iterator(); it.hasNext(); ) {
ClassInfo interf = it.next(); ClassInfo interf = it.next();
clsCode.add(useClass(interf)); clsCode.add(useClass(interf));
if (it.hasNext()) if (it.hasNext()) {
clsCode.add(", "); clsCode.add(", ");
}
} }
if (!cls.getInterfaces().isEmpty()) if (!cls.getInterfaces().isEmpty()) {
clsCode.add(' '); clsCode.add(' ');
}
} }
clsCode.attachAnnotation(cls); clsCode.attachAnnotation(cls);
} }
public boolean makeGenericMap(CodeWriter code, Map<ArgType, List<ArgType>> gmap) { public boolean makeGenericMap(CodeWriter code, Map<ArgType, List<ArgType>> gmap) {
if (gmap == null || gmap.isEmpty()) if (gmap == null || gmap.isEmpty()) {
return false; return false;
}
code.add('<'); code.add('<');
int i = 0; int i = 0;
for (Entry<ArgType, List<ArgType>> e : gmap.entrySet()) { for (Entry<ArgType, List<ArgType>> e : gmap.entrySet()) {
...@@ -186,14 +189,15 @@ public class ClassGen { ...@@ -186,14 +189,15 @@ public class ClassGen {
CodeWriter mthsCode = makeMethods(clsCode, cls.getMethods()); CodeWriter mthsCode = makeMethods(clsCode, cls.getMethods());
CodeWriter fieldsCode = makeFields(clsCode, cls, cls.getFields()); CodeWriter fieldsCode = makeFields(clsCode, cls, cls.getFields());
clsCode.add(fieldsCode); clsCode.add(fieldsCode);
if (fieldsCode.notEmpty() && mthsCode.notEmpty()) if (fieldsCode.notEmpty() && mthsCode.notEmpty()) {
clsCode.newLine(); clsCode.newLine();
}
// insert inner classes code // insert inner classes code
if (cls.getInnerClasses().size() != 0) { if (cls.getInnerClasses().size() != 0) {
clsCode.add(makeInnerClasses(cls, clsCode.getIndent())); clsCode.add(makeInnerClasses(cls, clsCode.getIndent()));
if (mthsCode.notEmpty()) if (mthsCode.notEmpty()) {
clsCode.newLine(); clsCode.newLine();
}
} }
clsCode.add(mthsCode); clsCode.add(mthsCode);
clsCode.startLine('}'); clsCode.startLine('}');
...@@ -202,12 +206,11 @@ public class ClassGen { ...@@ -202,12 +206,11 @@ public class ClassGen {
private CodeWriter makeInnerClasses(ClassNode cls, int indent) throws CodegenException { private CodeWriter makeInnerClasses(ClassNode cls, int indent) throws CodegenException {
CodeWriter innerClsCode = new CodeWriter(indent + 1); CodeWriter innerClsCode = new CodeWriter(indent + 1);
for (ClassNode inCls : cls.getInnerClasses()) { for (ClassNode inCls : cls.getInnerClasses()) {
if (inCls.isAnonymous()) if (!inCls.isAnonymous()) {
continue; ClassGen inClGen = new ClassGen(inCls, parentGen == null ? this : parentGen, fallback);
inClGen.addClassCode(innerClsCode);
ClassGen inClGen = new ClassGen(inCls, parentGen == null ? this : parentGen, fallback); imports.addAll(inClGen.getImports());
inClGen.addClassCode(innerClsCode); }
imports.addAll(inClGen.getImports());
} }
return innerClsCode; return innerClsCode;
} }
...@@ -276,26 +279,28 @@ public class ClassGen { ...@@ -276,26 +279,28 @@ public class ClassGen {
igen = new InsnGen(mthGen, enumFields.getStaticMethod(), false); igen = new InsnGen(mthGen, enumFields.getStaticMethod(), false);
} }
code.add(igen.arg(arg)); code.add(igen.arg(arg));
if (aIt.hasNext()) if (aIt.hasNext()) {
code.add(", "); code.add(", ");
}
} }
code.add(')'); code.add(')');
} }
if (f.getCls() != null) { if (f.getCls() != null) {
new ClassGen(f.getCls(), this, fallback).makeClassBody(code); new ClassGen(f.getCls(), this, fallback).makeClassBody(code);
} }
if (it.hasNext()) if (it.hasNext()) {
code.add(','); code.add(',');
}
} }
if (enumFields.getFields().isEmpty()) if (enumFields.getFields().isEmpty()) {
code.startLine(); code.startLine();
}
code.add(';'); code.add(';');
code.newLine(); code.newLine();
} }
for (FieldNode f : fields) { for (FieldNode f : fields) {
if(f.getAttributes().contains(AttributeFlag.DONT_GENERATE)) { if (f.getAttributes().contains(AttributeFlag.DONT_GENERATE)) {
continue; continue;
} }
annotationGen.addForField(code, f); annotationGen.addForField(code, f);
...@@ -338,10 +343,11 @@ public class ClassGen { ...@@ -338,10 +343,11 @@ public class ClassGen {
sb.append(", "); sb.append(", ");
} }
ArgType gt = generics[i]; ArgType gt = generics[i];
if (gt.isTypeKnown()) if (gt.isTypeKnown()) {
sb.append(TypeGen.translate(this, gt)); sb.append(TypeGen.translate(this, gt));
else } else {
sb.append('?'); sb.append('?');
}
} }
sb.append('>'); sb.append('>');
return sb.toString(); return sb.toString();
......
...@@ -59,8 +59,9 @@ public class CodeWriter { ...@@ -59,8 +59,9 @@ public class CodeWriter {
public CodeWriter startLine(int ind, String str) { public CodeWriter startLine(int ind, String str) {
addLine(); addLine();
buf.append(indentStr); buf.append(indentStr);
for (int i = 0; i < ind; i++) for (int i = 0; i < ind; i++) {
buf.append(INDENT); buf.append(INDENT);
}
buf.append(str); buf.append(str);
return this; return this;
} }
...@@ -209,10 +210,11 @@ public class CodeWriter { ...@@ -209,10 +210,11 @@ public class CodeWriter {
if (name.length() > MAX_FILENAME_LENGTH) { if (name.length() > MAX_FILENAME_LENGTH) {
int dotIndex = name.indexOf('.'); int dotIndex = name.indexOf('.');
int cutAt = MAX_FILENAME_LENGTH - name.length() + dotIndex - 1; int cutAt = MAX_FILENAME_LENGTH - name.length() + dotIndex - 1;
if (cutAt <= 0) if (cutAt <= 0) {
name = name.substring(0, MAX_FILENAME_LENGTH - 1); name = name.substring(0, MAX_FILENAME_LENGTH - 1);
else } else {
name = name.substring(0, cutAt) + name.substring(dotIndex); name = name.substring(0, cutAt) + name.substring(dotIndex);
}
file = new File(file.getParentFile(), name); file = new File(file.getParentFile(), name);
} }
...@@ -226,8 +228,9 @@ public class CodeWriter { ...@@ -226,8 +228,9 @@ public class CodeWriter {
} catch (Exception e) { } catch (Exception e) {
LOG.error("Save file error", e); LOG.error("Save file error", e);
} finally { } finally {
if (out != null) if (out != null) {
out.close(); out.close();
}
} }
} }
......
...@@ -127,9 +127,9 @@ public class MethodGen { ...@@ -127,9 +127,9 @@ public class MethodGen {
RegisterArg arg = it.next(); RegisterArg arg = it.next();
// add argument annotation // add argument annotation
if (paramsAnnotation != null) if (paramsAnnotation != null) {
annotationGen.addForParameter(argsCode, paramsAnnotation, i); annotationGen.addForParameter(argsCode, paramsAnnotation, i);
}
if (!it.hasNext() && mth.getAccessFlags().isVarArgs()) { if (!it.hasNext() && mth.getAccessFlags().isVarArgs()) {
// change last array argument to varargs // change last array argument to varargs
ArgType type = arg.getType(); ArgType type = arg.getType();
...@@ -148,8 +148,9 @@ public class MethodGen { ...@@ -148,8 +148,9 @@ public class MethodGen {
argsCode.add(makeArgName(arg)); argsCode.add(makeArgName(arg));
i++; i++;
if (it.hasNext()) if (it.hasNext()) {
argsCode.add(", "); argsCode.add(", ");
}
} }
return argsCode; return argsCode;
} }
...@@ -163,24 +164,27 @@ public class MethodGen { ...@@ -163,24 +164,27 @@ public class MethodGen {
String name = arg.getTypedVar().getName(); String name = arg.getTypedVar().getName();
String base = "r" + arg.getRegNum(); String base = "r" + arg.getRegNum();
if (fallback) { if (fallback) {
if (name != null) if (name != null) {
return base + "_" + name; return base + "_" + name;
else } else {
return base; return base;
}
} else { } else {
if (name != null) { if (name != null) {
if (name.equals("this")) if (name.equals("this")) {
return name; return name;
else if (Consts.DEBUG) } else if (Consts.DEBUG) {
return name + "_" + base; return name + "_" + base;
else } else {
return name; return name;
}
} else { } else {
ArgType type = arg.getType(); ArgType type = arg.getType();
if (type.isPrimitive()) if (type.isPrimitive()) {
return base + type.getPrimitiveType().getShortName().toLowerCase(); return base + type.getPrimitiveType().getShortName().toLowerCase();
else } else {
return base + "_" + Utils.escape(TypeGen.translate(classGen, arg.getType())); return base + "_" + Utils.escape(TypeGen.translate(classGen, arg.getType()));
}
} }
} }
} }
...@@ -193,9 +197,9 @@ public class MethodGen { ...@@ -193,9 +197,9 @@ public class MethodGen {
*/ */
public String assignArg(RegisterArg arg) { public String assignArg(RegisterArg arg) {
String name = makeArgName(arg); String name = makeArgName(arg);
if (varNames.add(name) || fallback) if (varNames.add(name) || fallback) {
return name; return name;
}
name = getUniqVarName(name); name = getUniqVarName(name);
arg.getTypedVar().setName(name); arg.getTypedVar().setName(name);
return name; return name;
...@@ -203,9 +207,9 @@ public class MethodGen { ...@@ -203,9 +207,9 @@ public class MethodGen {
public String assignNamedArg(NamedArg arg) { public String assignNamedArg(NamedArg arg) {
String name = arg.getName(); String name = arg.getName();
if (varNames.add(name) || fallback) if (varNames.add(name) || fallback) {
return name; return name;
}
name = getUniqVarName(name); name = getUniqVarName(name);
arg.setName(name); arg.setName(name);
return name; return name;
...@@ -298,8 +302,9 @@ public class MethodGen { ...@@ -298,8 +302,9 @@ public class MethodGen {
try { try {
if (insnGen.makeInsn(insn, code)) { if (insnGen.makeInsn(insn, code)) {
CatchAttr catchAttr = (CatchAttr) attrs.get(AttributeType.CATCH_BLOCK); CatchAttr catchAttr = (CatchAttr) attrs.get(AttributeType.CATCH_BLOCK);
if (catchAttr != null) if (catchAttr != null) {
code.add("\t //" + catchAttr); code.add("\t //" + catchAttr);
}
} }
} catch (CodegenException e) { } catch (CodegenException e) {
code.startLine("// error: " + insn); code.startLine("// error: " + insn);
......
...@@ -10,9 +10,9 @@ public class TypeGen { ...@@ -10,9 +10,9 @@ public class TypeGen {
public static String translate(ClassGen clsGen, ArgType type) { public static String translate(ClassGen clsGen, ArgType type) {
final PrimitiveType stype = type.getPrimitiveType(); final PrimitiveType stype = type.getPrimitiveType();
if (stype == null) if (stype == null) {
return type.toString(); return type.toString();
}
if (stype == PrimitiveType.OBJECT) { if (stype == PrimitiveType.OBJECT) {
return clsGen.useClass(type); return clsGen.useClass(type);
} }
...@@ -69,8 +69,9 @@ public class TypeGen { ...@@ -69,8 +69,9 @@ public class TypeGen {
case OBJECT: case OBJECT:
case ARRAY: case ARRAY:
if (lit != 0) if (lit != 0) {
throw new JadxRuntimeException("Wrong object literal: " + type + " = " + lit); throw new JadxRuntimeException("Wrong object literal: " + type + " = " + lit);
}
return "null"; return "null";
default: default:
...@@ -100,8 +101,9 @@ public class TypeGen { ...@@ -100,8 +101,9 @@ public class TypeGen {
public static String formatLong(long lit) { public static String formatLong(long lit) {
String l = Long.toString(lit); String l = Long.toString(lit);
if (lit == Long.MIN_VALUE || Math.abs(lit) >= Integer.MAX_VALUE) if (lit == Long.MIN_VALUE || Math.abs(lit) >= Integer.MAX_VALUE) {
l += "L"; l += "L";
}
return wrapNegNum(lit < 0, l); return wrapNegNum(lit < 0, l);
} }
...@@ -109,6 +111,6 @@ public class TypeGen { ...@@ -109,6 +111,6 @@ public class TypeGen {
// if (lz) // if (lz)
// return "(" + str + ")"; // return "(" + str + ")";
// else // else
return str; return str;
} }
} }
...@@ -6,8 +6,9 @@ public abstract class AttrNode implements IAttributeNode { ...@@ -6,8 +6,9 @@ public abstract class AttrNode implements IAttributeNode {
@Override @Override
public AttributesList getAttributes() { public AttributesList getAttributes() {
if (attributesList == null) if (attributesList == null) {
attributesList = new AttributesList(); attributesList = new AttributesList();
}
return attributesList; return attributesList;
} }
......
...@@ -38,8 +38,9 @@ public enum AttributeType { ...@@ -38,8 +38,9 @@ public enum AttributeType {
AttributeType[] vals = AttributeType.values(); AttributeType[] vals = AttributeType.values();
for (int i = 0; i < vals.length; i++) { for (int i = 0; i < vals.length; i++) {
AttributeType type = vals[i]; AttributeType type = vals[i];
if (type.notUniq()) if (type.notUniq()) {
last = i; last = i;
}
} }
NOT_UNIQ_COUNT = last + 1; NOT_UNIQ_COUNT = last + 1;
} }
......
...@@ -52,10 +52,11 @@ public final class AttributesList { ...@@ -52,10 +52,11 @@ public final class AttributesList {
// Attributes // Attributes
public void add(IAttribute attr) { public void add(IAttribute attr) {
if (attr.getType().isUniq()) if (attr.getType().isUniq()) {
uniqAttr.put(attr.getType(), attr); uniqAttr.put(attr.getType(), attr);
else } else {
addMultiAttribute(attr); addMultiAttribute(attr);
}
} }
private void addMultiAttribute(IAttribute attr) { private void addMultiAttribute(IAttribute attr) {
...@@ -70,15 +71,17 @@ public final class AttributesList { ...@@ -70,15 +71,17 @@ public final class AttributesList {
public void addAll(AttributesList otherList) { public void addAll(AttributesList otherList) {
flags.addAll(otherList.flags); flags.addAll(otherList.flags);
uniqAttr.putAll(otherList.uniqAttr); uniqAttr.putAll(otherList.uniqAttr);
for (IAttribute attr : otherList.attributes) for (IAttribute attr : otherList.attributes) {
addMultiAttribute(attr); addMultiAttribute(attr);
}
} }
public boolean contains(AttributeType type) { public boolean contains(AttributeType type) {
if (type.isUniq()) if (type.isUniq()) {
return uniqAttr.containsKey(type); return uniqAttr.containsKey(type);
else } else {
return getMultiCountInternal(type) != 0; return getMultiCountInternal(type) != 0;
}
} }
public IAttribute get(AttributeType type) { public IAttribute get(AttributeType type) {
...@@ -86,9 +89,11 @@ public final class AttributesList { ...@@ -86,9 +89,11 @@ public final class AttributesList {
return uniqAttr.get(type); return uniqAttr.get(type);
} else { } else {
if (getMultiCountInternal(type) != 0) { if (getMultiCountInternal(type) != 0) {
for (IAttribute attr : attributes) for (IAttribute attr : attributes) {
if (attr.getType() == type) if (attr.getType() == type) {
return attr; return attr;
}
}
} }
return null; return null;
} }
...@@ -104,9 +109,9 @@ public final class AttributesList { ...@@ -104,9 +109,9 @@ public final class AttributesList {
public Annotation getAnnotation(String cls) { public Annotation getAnnotation(String cls) {
AnnotationsList aList = (AnnotationsList) get(AttributeType.ANNOTATION_LIST); AnnotationsList aList = (AnnotationsList) get(AttributeType.ANNOTATION_LIST);
if (aList == null || aList.size() == 0) if (aList == null || aList.size() == 0) {
return null; return null;
}
return aList.get(cls); return aList.get(cls);
} }
...@@ -119,8 +124,9 @@ public final class AttributesList { ...@@ -119,8 +124,9 @@ public final class AttributesList {
} else { } else {
List<IAttribute> attrs = new ArrayList<IAttribute>(count); List<IAttribute> attrs = new ArrayList<IAttribute>(count);
for (IAttribute attr : attributes) { for (IAttribute attr : attributes) {
if (attr.getType() == type) if (attr.getType() == type) {
attrs.add(attr); attrs.add(attr);
}
} }
return attrs; return attrs;
} }
...@@ -132,8 +138,9 @@ public final class AttributesList { ...@@ -132,8 +138,9 @@ public final class AttributesList {
} else { } else {
for (Iterator<IAttribute> it = attributes.iterator(); it.hasNext(); ) { for (Iterator<IAttribute> it = attributes.iterator(); it.hasNext(); ) {
IAttribute attr = it.next(); IAttribute attr = it.next();
if (attr.getType() == type) if (attr.getType() == type) {
it.remove(); it.remove();
}
} }
attrCount[type.ordinal()] = 0; attrCount[type.ordinal()] = 0;
} }
...@@ -143,11 +150,13 @@ public final class AttributesList { ...@@ -143,11 +150,13 @@ public final class AttributesList {
AttributeType type = attr.getType(); AttributeType type = attr.getType();
if (type.isUniq()) { if (type.isUniq()) {
IAttribute a = uniqAttr.get(type); IAttribute a = uniqAttr.get(type);
if (a == attr) if (a == attr) {
uniqAttr.remove(type); uniqAttr.remove(type);
}
} else { } else {
if (getMultiCountInternal(type) == 0) if (getMultiCountInternal(type) == 0) {
return; return;
}
for (Iterator<IAttribute> it = attributes.iterator(); it.hasNext(); ) { for (Iterator<IAttribute> it = attributes.iterator(); it.hasNext(); ) {
IAttribute a = it.next(); IAttribute a = it.next();
...@@ -168,25 +177,28 @@ public final class AttributesList { ...@@ -168,25 +177,28 @@ public final class AttributesList {
public List<String> getAttributeStrings() { public List<String> getAttributeStrings() {
int size = flags.size() + uniqAttr.size() + attributes.size(); int size = flags.size() + uniqAttr.size() + attributes.size();
if (size == 0) if (size == 0) {
return Collections.emptyList(); return Collections.emptyList();
}
List<String> list = new ArrayList<String>(size); List<String> list = new ArrayList<String>(size);
for (AttributeFlag a : flags) for (AttributeFlag a : flags) {
list.add(a.toString()); list.add(a.toString());
for (IAttribute a : uniqAttr.values()) }
for (IAttribute a : uniqAttr.values()) {
list.add(a.toString()); list.add(a.toString());
for (IAttribute a : attributes) }
for (IAttribute a : attributes) {
list.add(a.toString()); list.add(a.toString());
}
return list; return list;
} }
@Override @Override
public String toString() { public String toString() {
List<String> list = getAttributeStrings(); List<String> list = getAttributeStrings();
if (list.isEmpty()) if (list.isEmpty()) {
return ""; return "";
}
return "A:{" + Utils.listToString(list) + "}"; return "A:{" + Utils.listToString(list) + "}";
} }
......
...@@ -45,8 +45,9 @@ public final class BlockRegState { ...@@ -45,8 +45,9 @@ public final class BlockRegState {
StringBuilder str = new StringBuilder(); StringBuilder str = new StringBuilder();
for (RegisterArg reg : regs) { for (RegisterArg reg : regs) {
if (reg.getTypedVar() != null) { if (reg.getTypedVar() != null) {
if (str.length() != 0) if (str.length() != 0) {
str.append(", "); str.append(", ");
}
str.append(reg.toString()); str.append(reg.toString());
} }
} }
......
...@@ -24,8 +24,9 @@ public class DeclareVariableAttr implements IAttribute { ...@@ -24,8 +24,9 @@ public class DeclareVariableAttr implements IAttribute {
public void addVar(RegisterArg arg) { public void addVar(RegisterArg arg) {
int i; int i;
if ((i = vars.indexOf(arg)) != -1) { if ((i = vars.indexOf(arg)) != -1) {
if (vars.get(i).getType().equals(arg.getType())) if (vars.get(i).getType().equals(arg.getType())) {
return; return;
}
} }
vars.add(arg); vars.add(arg);
} }
......
...@@ -18,10 +18,11 @@ public class EnumClassAttr implements IAttribute { ...@@ -18,10 +18,11 @@ public class EnumClassAttr implements IAttribute {
public EnumField(String name, int argsCount) { public EnumField(String name, int argsCount) {
this.name = name; this.name = name;
if (argsCount != 0) if (argsCount != 0) {
this.args = new ArrayList<InsnArg>(argsCount); this.args = new ArrayList<InsnArg>(argsCount);
else } else {
this.args = Collections.emptyList(); this.args = Collections.emptyList();
}
} }
public String getName() { public String getName() {
......
...@@ -41,9 +41,15 @@ public class JumpAttribute implements IAttribute { ...@@ -41,9 +41,15 @@ public class JumpAttribute implements IAttribute {
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (this == obj) return true; if (this == obj) {
if (obj == null) return false; return true;
if (getClass() != obj.getClass()) return false; }
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
JumpAttribute other = (JumpAttribute) obj; JumpAttribute other = (JumpAttribute) obj;
return dest == other.dest && src == other.src; return dest == other.dest && src == other.src;
} }
......
...@@ -45,9 +45,11 @@ public class LoopAttr implements IAttribute { ...@@ -45,9 +45,11 @@ public class LoopAttr implements IAttribute {
Set<BlockNode> inloop = getLoopBlocks(); Set<BlockNode> inloop = getLoopBlocks();
for (BlockNode block : inloop) { for (BlockNode block : inloop) {
// exit: successor node not from this loop, (don't change to getCleanSuccessors) // exit: successor node not from this loop, (don't change to getCleanSuccessors)
for (BlockNode s : block.getSuccessors()) for (BlockNode s : block.getSuccessors()) {
if (!inloop.contains(s) && !s.getAttributes().contains(AttributeType.EXC_HANDLER)) if (!inloop.contains(s) && !s.getAttributes().contains(AttributeType.EXC_HANDLER)) {
nodes.add(block); nodes.add(block);
}
}
} }
return nodes; return nodes;
} }
......
...@@ -24,10 +24,11 @@ public class AccessInfo { ...@@ -24,10 +24,11 @@ public class AccessInfo {
} }
public AccessInfo remove(int flag) { public AccessInfo remove(int flag) {
if (containsFlag(flag)) if (containsFlag(flag)) {
return new AccessInfo(accFlags - flag, type); return new AccessInfo(accFlags - flag, type);
else } else {
return this; return this;
}
} }
public AccessInfo getVisibility() { public AccessInfo getVisibility() {
...@@ -111,71 +112,73 @@ public class AccessInfo { ...@@ -111,71 +112,73 @@ public class AccessInfo {
public String makeString() { public String makeString() {
StringBuilder code = new StringBuilder(); StringBuilder code = new StringBuilder();
if (isPublic()) if (isPublic()) {
code.append("public "); code.append("public ");
}
if (isPrivate()) if (isPrivate()) {
code.append("private "); code.append("private ");
}
if (isProtected()) if (isProtected()) {
code.append("protected "); code.append("protected ");
}
if (isStatic()) if (isStatic()) {
code.append("static "); code.append("static ");
}
if (isFinal()) if (isFinal()) {
code.append("final "); code.append("final ");
}
if (isAbstract()) if (isAbstract()) {
code.append("abstract "); code.append("abstract ");
}
if (isNative()) if (isNative()) {
code.append("native "); code.append("native ");
}
switch (type) { switch (type) {
case METHOD: case METHOD:
if (isSynchronized()) if (isSynchronized()) {
code.append("synchronized "); code.append("synchronized ");
}
if (isBridge()) if (isBridge()) {
code.append("/* bridge */ "); code.append("/* bridge */ ");
}
if (Consts.DEBUG) { if (Consts.DEBUG) {
if (isVarArgs()) if (isVarArgs()) {
code.append("/* varargs */ "); code.append("/* varargs */ ");
}
} }
break; break;
case FIELD: case FIELD:
if (isVolatile()) if (isVolatile()) {
code.append("volatile "); code.append("volatile ");
}
if (isTransient()) if (isTransient()) {
code.append("transient "); code.append("transient ");
}
break; break;
case CLASS: case CLASS:
if ((accFlags & AccessFlags.ACC_STRICT) != 0) if ((accFlags & AccessFlags.ACC_STRICT) != 0) {
code.append("strict "); code.append("strict ");
}
if (Consts.DEBUG) { if (Consts.DEBUG) {
if ((accFlags & AccessFlags.ACC_SUPER) != 0) if ((accFlags & AccessFlags.ACC_SUPER) != 0) {
code.append("/* super */ "); code.append("/* super */ ");
}
if ((accFlags & AccessFlags.ACC_ENUM) != 0) if ((accFlags & AccessFlags.ACC_ENUM) != 0) {
code.append("/* enum */ "); code.append("/* enum */ ");
}
} }
break; break;
} }
if (isSynthetic()) {
if (isSynthetic())
code.append("/* synthetic */ "); code.append("/* synthetic */ ");
}
return code.toString(); return code.toString();
} }
public String rawString() { public String rawString() {
switch (type){ switch (type) {
case CLASS: case CLASS:
return AccessFlags.classString(accFlags); return AccessFlags.classString(accFlags);
case FIELD: case FIELD:
......
...@@ -14,13 +14,13 @@ public final class ClassInfo { ...@@ -14,13 +14,13 @@ public final class ClassInfo {
private static final Map<ArgType, ClassInfo> CLASSINFO_CACHE = new WeakHashMap<ArgType, ClassInfo>(); private static final Map<ArgType, ClassInfo> CLASSINFO_CACHE = new WeakHashMap<ArgType, ClassInfo>();
public static ClassInfo fromDex(DexNode dex, int clsIndex) { public static ClassInfo fromDex(DexNode dex, int clsIndex) {
if (clsIndex == DexNode.NO_INDEX) if (clsIndex == DexNode.NO_INDEX) {
return null; return null;
}
ArgType type = dex.getType(clsIndex); ArgType type = dex.getType(clsIndex);
if (type.isArray()) if (type.isArray()) {
type = ArgType.OBJECT; type = ArgType.OBJECT;
}
return fromType(type); return fromType(type);
} }
...@@ -153,7 +153,9 @@ public final class ClassInfo { ...@@ -153,7 +153,9 @@ public final class ClassInfo {
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (this == obj) return true; if (this == obj) {
return true;
}
if (obj instanceof ClassInfo) { if (obj instanceof ClassInfo) {
ClassInfo other = (ClassInfo) obj; ClassInfo other = (ClassInfo) obj;
return this.getFullName().equals(other.getFullName()); return this.getFullName().equals(other.getFullName());
......
...@@ -41,13 +41,22 @@ public class FieldInfo { ...@@ -41,13 +41,22 @@ public class FieldInfo {
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (this == o) return true; if (this == o) {
if (o == null || getClass() != o.getClass()) return false; return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
FieldInfo fieldInfo = (FieldInfo) o; FieldInfo fieldInfo = (FieldInfo) o;
if (!name.equals(fieldInfo.name)) return false; if (!name.equals(fieldInfo.name)) {
if (!type.equals(fieldInfo.type)) return false; return false;
if (!declClass.equals(fieldInfo.declClass)) return false; }
if (!type.equals(fieldInfo.type)) {
return false;
}
if (!declClass.equals(fieldInfo.declClass)) {
return false;
}
return true; return true;
} }
......
...@@ -98,13 +98,25 @@ public final class MethodInfo { ...@@ -98,13 +98,25 @@ public final class MethodInfo {
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (this == obj) return true; if (this == obj) {
if (obj == null) return false; return true;
if (getClass() != obj.getClass()) return false; }
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
MethodInfo other = (MethodInfo) obj; MethodInfo other = (MethodInfo) obj;
if (!shortId.equals(other.shortId)) return false; if (!shortId.equals(other.shortId)) {
if (!retType.equals(other.retType)) return false; return false;
if (!declClass.equals(other.declClass)) return false; }
if (!retType.equals(other.retType)) {
return false;
}
if (!declClass.equals(other.declClass)) {
return false;
}
return true; return true;
} }
......
...@@ -578,14 +578,16 @@ public class InsnDecoder { ...@@ -578,14 +578,16 @@ public class InsnDecoder {
targets = ps.getTargets(); targets = ps.getTargets();
keys = new Object[targets.length]; keys = new Object[targets.length];
int k = ps.getFirstKey(); int k = ps.getFirstKey();
for (int i = 0; i < keys.length; i++) for (int i = 0; i < keys.length; i++) {
keys[i] = k++; keys[i] = k++;
}
} else { } else {
SparseSwitchPayloadDecodedInstruction ss = (SparseSwitchPayloadDecodedInstruction) payload; SparseSwitchPayloadDecodedInstruction ss = (SparseSwitchPayloadDecodedInstruction) payload;
targets = ss.getTargets(); targets = ss.getTargets();
keys = new Object[targets.length]; keys = new Object[targets.length];
for (int i = 0; i < keys.length; i++) for (int i = 0; i < keys.length; i++) {
keys[i] = ss.getKeys()[i]; keys[i] = ss.getKeys()[i];
}
} }
// convert from relative to absolute offsets // convert from relative to absolute offsets
for (int i = 0; i < targets.length; i++) { for (int i = 0; i < targets.length; i++) {
...@@ -612,8 +614,9 @@ public class InsnDecoder { ...@@ -612,8 +614,9 @@ public class InsnDecoder {
r++; r++;
} }
} else { } else {
for (int i = 0; i < insn.getRegisterCount(); i++) for (int i = 0; i < insn.getRegisterCount(); i++) {
regs[i] = InsnArg.reg(insn, i, elType); regs[i] = InsnArg.reg(insn, i, elType);
}
} }
return insn(InsnType.FILLED_NEW_ARRAY, return insn(InsnType.FILLED_NEW_ARRAY,
resReg == -1 ? null : InsnArg.reg(resReg, arrType), resReg == -1 ? null : InsnArg.reg(resReg, arrType),
...@@ -689,8 +692,9 @@ public class InsnDecoder { ...@@ -689,8 +692,9 @@ public class InsnDecoder {
InsnNode node = new InsnNode(type, args == null ? 0 : args.length); InsnNode node = new InsnNode(type, args == null ? 0 : args.length);
node.setResult(res); node.setResult(res);
if (args != null) { if (args != null) {
for (InsnArg arg : args) for (InsnArg arg : args) {
node.addArg(arg); node.addArg(arg);
}
} }
return node; return node;
} }
...@@ -711,19 +715,23 @@ public class InsnDecoder { ...@@ -711,19 +715,23 @@ public class InsnDecoder {
public static int getPrevInsnOffset(Object[] insnArr, int offset) { public static int getPrevInsnOffset(Object[] insnArr, int offset) {
int i = offset - 1; int i = offset - 1;
while (i >= 0 && insnArr[i] == null) while (i >= 0 && insnArr[i] == null) {
i--; i--;
if (i < 0) }
if (i < 0) {
return -1; return -1;
}
return i; return i;
} }
public static int getNextInsnOffset(Object[] insnArr, int offset) { public static int getNextInsnOffset(Object[] insnArr, int offset) {
int i = offset + 1; int i = offset + 1;
while (i < insnArr.length && insnArr[i] == null) while (i < insnArr.length && insnArr[i] == null) {
i++; i++;
if (i >= insnArr.length) }
if (i >= insnArr.length) {
return -1; return -1;
}
return i; return i;
} }
} }
...@@ -19,8 +19,9 @@ public class InvokeNode extends InsnNode { ...@@ -19,8 +19,9 @@ public class InvokeNode extends InsnNode {
this.mth = mth; this.mth = mth;
this.type = type; this.type = type;
if (resReg >= 0) if (resReg >= 0) {
setResult(InsnArg.reg(resReg, mth.getReturnType())); setResult(InsnArg.reg(resReg, mth.getReturnType()));
}
int k = isRange ? insn.getA() : 0; int k = isRange ? insn.getA() : 0;
if (type != InvokeType.STATIC) { if (type != InvokeType.STATIC) {
......
...@@ -42,8 +42,9 @@ public class SwitchNode extends InsnNode { ...@@ -42,8 +42,9 @@ public class SwitchNode extends InsnNode {
targ.append('['); targ.append('[');
for (int i = 0; i < targets.length; i++) { for (int i = 0; i < targets.length; i++) {
targ.append(InsnUtils.formatOffset(targets[i])); targ.append(InsnUtils.formatOffset(targets[i]));
if (i < targets.length - 1) if (i < targets.length - 1) {
targ.append(", "); targ.append(", ");
}
} }
targ.append(']'); targ.append(']');
return super.toString() + " k:" + Arrays.toString(keys) + " t:" + targ; return super.toString() + " k:" + Arrays.toString(keys) + " t:" + targ;
......
...@@ -30,17 +30,19 @@ public enum PrimitiveType { ...@@ -30,17 +30,19 @@ public enum PrimitiveType {
} }
public static PrimitiveType getWidest(PrimitiveType a, PrimitiveType b) { public static PrimitiveType getWidest(PrimitiveType a, PrimitiveType b) {
if (a.ordinal() > b.ordinal()) if (a.ordinal() > b.ordinal()) {
return a; return a;
else } else {
return b; return b;
}
} }
public static PrimitiveType getSmaller(PrimitiveType a, PrimitiveType b) { public static PrimitiveType getSmaller(PrimitiveType a, PrimitiveType b) {
if (a.ordinal() < b.ordinal()) if (a.ordinal() < b.ordinal()) {
return a; return a;
else } else {
return b; return b;
}
} }
@Override @Override
......
...@@ -40,12 +40,13 @@ public class RegisterArg extends InsnArg { ...@@ -40,12 +40,13 @@ public class RegisterArg extends InsnArg {
public InsnNode getAssignInsn() { public InsnNode getAssignInsn() {
for (InsnArg arg : getTypedVar().getUseList()) { for (InsnArg arg : getTypedVar().getUseList()) {
InsnNode assignInsn = arg.getParentInsn(); InsnNode assignInsn = arg.getParentInsn();
if (assignInsn == null) if (assignInsn == null) {
// assign as function argument // assign as function argument
return null; return null;
else if (assignInsn.getResult() != null } else if (assignInsn.getResult() != null
&& assignInsn.getResult().getRegNum() == regNum) && assignInsn.getResult().getRegNum() == regNum) {
return assignInsn; return assignInsn;
}
} }
return null; return null;
} }
...@@ -109,12 +110,22 @@ public class RegisterArg extends InsnArg { ...@@ -109,12 +110,22 @@ public class RegisterArg extends InsnArg {
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (this == obj) return true; if (this == obj) {
if (obj == null) return false; return true;
if (getClass() != obj.getClass()) return false; }
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
RegisterArg other = (RegisterArg) obj; RegisterArg other = (RegisterArg) obj;
if (regNum != other.regNum) return false; if (regNum != other.regNum) {
if (!typedVar.equals(other.typedVar)) return false; return false;
}
if (!typedVar.equals(other.typedVar)) {
return false;
}
return true; return true;
} }
......
...@@ -70,13 +70,23 @@ public class TypedVar { ...@@ -70,13 +70,23 @@ public class TypedVar {
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (this == obj) return true; if (this == obj) {
if (obj == null) return false; return true;
if (!(obj instanceof TypedVar)) return false; }
if (obj == null) {
return false;
}
if (!(obj instanceof TypedVar)) {
return false;
}
TypedVar other = (TypedVar) obj; TypedVar other = (TypedVar) obj;
if (!type.equals(other.type)) return false; if (!type.equals(other.type)) {
return false;
}
if (name == null) { if (name == null) {
if (other.name != null) return false; if (other.name != null) {
return false;
}
} else if (!name.equals(other.name)) { } else if (!name.equals(other.name)) {
return false; return false;
} }
...@@ -86,8 +96,9 @@ public class TypedVar { ...@@ -86,8 +96,9 @@ public class TypedVar {
@Override @Override
public String toString() { public String toString() {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
if (name != null) if (name != null) {
sb.append('\'').append(name).append("' "); sb.append('\'').append(name).append("' ");
}
sb.append(type); sb.append(type);
return sb.toString(); return sb.toString();
} }
......
...@@ -72,15 +72,17 @@ public class BlockNode extends AttrNode implements IBlock { ...@@ -72,15 +72,17 @@ public class BlockNode extends AttrNode implements IBlock {
LoopAttr loop = (LoopAttr) block.getAttributes().get(AttributeType.LOOP); LoopAttr loop = (LoopAttr) block.getAttributes().get(AttributeType.LOOP);
if (loop == null) { if (loop == null) {
for (BlockNode b : sucList) { for (BlockNode b : sucList) {
if (!b.getAttributes().contains(AttributeType.EXC_HANDLER)) if (!b.getAttributes().contains(AttributeType.EXC_HANDLER)) {
nodes.add(b); nodes.add(b);
}
} }
} else { } else {
for (BlockNode b : sucList) { for (BlockNode b : sucList) {
if (!b.getAttributes().contains(AttributeType.EXC_HANDLER)) { if (!b.getAttributes().contains(AttributeType.EXC_HANDLER)) {
// don't follow back edge // don't follow back edge
if (loop.getStart() == b && loop.getEnd() == block) if (loop.getStart() == b && loop.getEnd() == block) {
continue; continue;
}
nodes.add(b); nodes.add(b);
} }
} }
...@@ -153,13 +155,25 @@ public class BlockNode extends AttrNode implements IBlock { ...@@ -153,13 +155,25 @@ public class BlockNode extends AttrNode implements IBlock {
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (this == obj) return true; if (this == obj) {
if (obj == null) return false; return true;
if (hashCode() != obj.hashCode()) return false; }
if (!(obj instanceof BlockNode)) return false; if (obj == null) {
return false;
}
if (hashCode() != obj.hashCode()) {
return false;
}
if (!(obj instanceof BlockNode)) {
return false;
}
BlockNode other = (BlockNode) obj; BlockNode other = (BlockNode) obj;
if (id != other.id) return false; if (id != other.id) {
if (startOffset != other.startOffset) return false; return false;
}
if (startOffset != other.startOffset) {
return false;
}
return true; return true;
} }
......
...@@ -48,8 +48,12 @@ public class FieldNode extends LineAttrNode { ...@@ -48,8 +48,12 @@ public class FieldNode extends LineAttrNode {
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (this == obj) return true; if (this == obj) {
if (obj == null || getClass() != obj.getClass()) return false; return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
FieldNode other = (FieldNode) obj; FieldNode other = (FieldNode) obj;
return fieldInfo.equals(other.fieldInfo); return fieldInfo.equals(other.fieldInfo);
} }
......
...@@ -32,15 +32,17 @@ public class InsnNode extends LineAttrNode { ...@@ -32,15 +32,17 @@ public class InsnNode extends LineAttrNode {
this.insnType = type; this.insnType = type;
this.offset = -1; this.offset = -1;
if (argsCount == 0) if (argsCount == 0) {
this.arguments = Collections.emptyList(); this.arguments = Collections.emptyList();
else } else {
this.arguments = new ArrayList<InsnArg>(argsCount); this.arguments = new ArrayList<InsnArg>(argsCount);
}
} }
public void setResult(RegisterArg res) { public void setResult(RegisterArg res) {
if (res != null) if (res != null) {
res.setParentInsn(this); res.setParentInsn(this);
}
this.result = res; this.result = res;
} }
...@@ -71,8 +73,9 @@ public class InsnNode extends LineAttrNode { ...@@ -71,8 +73,9 @@ public class InsnNode extends LineAttrNode {
public boolean containsArg(RegisterArg arg) { public boolean containsArg(RegisterArg arg) {
for (InsnArg a : arguments) { for (InsnArg a : arguments) {
if (a == arg || (a.isRegister() && ((RegisterArg) a).getRegNum() == arg.getRegNum())) if (a == arg || (a.isRegister() && ((RegisterArg) a).getRegNum() == arg.getRegNum())) {
return true; return true;
}
} }
return false; return false;
} }
...@@ -92,8 +95,9 @@ public class InsnNode extends LineAttrNode { ...@@ -92,8 +95,9 @@ public class InsnNode extends LineAttrNode {
setArg(i, to); setArg(i, to);
return true; return true;
} else if (arg.isInsnWrap()) { } else if (arg.isInsnWrap()) {
if (((InsnWrapArg) arg).getWrapInsn().replaceArg(from, to)) if (((InsnWrapArg) arg).getWrapInsn().replaceArg(from, to)) {
return true; return true;
}
} }
} }
return false; return false;
...@@ -176,14 +180,25 @@ public class InsnNode extends LineAttrNode { ...@@ -176,14 +180,25 @@ public class InsnNode extends LineAttrNode {
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (this == obj) return true; if (this == obj) {
if (obj == null) return false; return true;
if (hashCode() != obj.hashCode()) return false; }
if (!(obj instanceof InsnNode)) return false; if (obj == null) {
return false;
}
if (hashCode() != obj.hashCode()) {
return false;
}
if (!(obj instanceof InsnNode)) {
return false;
}
InsnNode other = (InsnNode) obj; InsnNode other = (InsnNode) obj;
if (insnType != other.insnType) return false; if (insnType != other.insnType) {
if (arguments.size() != other.arguments.size()) return false; return false;
}
if (arguments.size() != other.arguments.size()) {
return false;
}
// TODO !!! finish equals // TODO !!! finish equals
return true; return true;
......
...@@ -90,8 +90,9 @@ public class MethodNode extends LineAttrNode implements ILoadable { ...@@ -90,8 +90,9 @@ public class MethodNode extends LineAttrNode implements ILoadable {
InsnNode[] insnByOffset = decoder.run(); InsnNode[] insnByOffset = decoder.run();
instructions = new ArrayList<InsnNode>(); instructions = new ArrayList<InsnNode>();
for (InsnNode insn : insnByOffset) { for (InsnNode insn : insnByOffset) {
if (insn != null) if (insn != null) {
instructions.add(insn); instructions.add(insn);
}
} }
((ArrayList<InsnNode>) instructions).trimToSize(); ((ArrayList<InsnNode>) instructions).trimToSize();
...@@ -127,18 +128,23 @@ public class MethodNode extends LineAttrNode implements ILoadable { ...@@ -127,18 +128,23 @@ public class MethodNode extends LineAttrNode implements ILoadable {
if (noCode) { if (noCode) {
return; return;
} }
if (instructions != null) instructions.clear(); if (instructions != null) {
instructions.clear();
}
blocks = null; blocks = null;
exitBlocks = null; exitBlocks = null;
if (exceptionHandlers != null) exceptionHandlers.clear(); if (exceptionHandlers != null) {
exceptionHandlers.clear();
}
noCode = true; noCode = true;
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private boolean parseSignature() { private boolean parseSignature() {
Annotation a = getAttributes().getAnnotation(Consts.DALVIK_SIGNATURE); Annotation a = getAttributes().getAnnotation(Consts.DALVIK_SIGNATURE);
if (a == null) if (a == null) {
return false; return false;
}
String sign = Utils.mergeSignature((List<String>) a.getDefaultValue()); String sign = Utils.mergeSignature((List<String>) a.getDefaultValue());
...@@ -162,8 +168,9 @@ public class MethodNode extends LineAttrNode implements ILoadable { ...@@ -162,8 +168,9 @@ public class MethodNode extends LineAttrNode implements ILoadable {
} }
List<ArgType> argsTypes = ArgType.parseSignatureList(argsTypesStr); List<ArgType> argsTypes = ArgType.parseSignatureList(argsTypesStr);
if (argsTypes == null) if (argsTypes == null) {
return false; return false;
}
List<ArgType> mthArgs = mthInfo.getArgumentsTypes(); List<ArgType> mthArgs = mthInfo.getArgumentsTypes();
if (argsTypes.size() != mthArgs.size()) { if (argsTypes.size() != mthArgs.size()) {
...@@ -197,8 +204,9 @@ public class MethodNode extends LineAttrNode implements ILoadable { ...@@ -197,8 +204,9 @@ public class MethodNode extends LineAttrNode implements ILoadable {
pos = 1; pos = 1;
} else { } else {
pos = regsCount; pos = regsCount;
for (ArgType arg : args) for (ArgType arg : args) {
pos -= arg.getRegCount(); pos -= arg.getRegCount();
}
} }
if (accFlags.isStatic()) { if (accFlags.isStatic()) {
thisArg = null; thisArg = null;
...@@ -289,11 +297,15 @@ public class MethodNode extends LineAttrNode implements ILoadable { ...@@ -289,11 +297,15 @@ public class MethodNode extends LineAttrNode implements ILoadable {
// resolve nested try blocks: // resolve nested try blocks:
// inner block contains all handlers from outer block => remove these handlers from inner block // inner block contains all handlers from outer block => remove these handlers from inner block
// each handler must be only in one try/catch block // each handler must be only in one try/catch block
for (TryCatchBlock ct1 : catches) for (TryCatchBlock ct1 : catches) {
for (TryCatchBlock ct2 : catches) for (TryCatchBlock ct2 : catches) {
if (ct1 != ct2 && ct2.getHandlers().containsAll(ct1.getHandlers())) if (ct1 != ct2 && ct2.getHandlers().containsAll(ct1.getHandlers())) {
for (ExceptionHandler h : ct1.getHandlers()) for (ExceptionHandler h : ct1.getHandlers()) {
ct2.removeHandler(this, h); ct2.removeHandler(this, h);
}
}
}
}
} }
// attach EXC_HANDLER attributes to instructions // attach EXC_HANDLER attributes to instructions
...@@ -319,8 +331,9 @@ public class MethodNode extends LineAttrNode implements ILoadable { ...@@ -319,8 +331,9 @@ public class MethodNode extends LineAttrNode implements ILoadable {
block.addInsn(insnByOffset[offset]); block.addInsn(insnByOffset[offset]);
offset = InsnDecoder.getNextInsnOffset(insnByOffset, offset); offset = InsnDecoder.getNextInsnOffset(insnByOffset, offset);
} }
if (insnByOffset[end] != null) if (insnByOffset[end] != null) {
insnByOffset[end].getAttributes().add(AttributeFlag.TRY_LEAVE); insnByOffset[end].getAttributes().add(AttributeFlag.TRY_LEAVE);
}
} }
} }
...@@ -335,15 +348,17 @@ public class MethodNode extends LineAttrNode implements ILoadable { ...@@ -335,15 +348,17 @@ public class MethodNode extends LineAttrNode implements ILoadable {
} }
// default case // default case
int next = InsnDecoder.getNextInsnOffset(insnByOffset, offset); int next = InsnDecoder.getNextInsnOffset(insnByOffset, offset);
if (next != -1) if (next != -1) {
addJump(insnByOffset, offset, next); addJump(insnByOffset, offset, next);
}
break; break;
} }
case IF: case IF:
int next = InsnDecoder.getNextInsnOffset(insnByOffset, offset); int next = InsnDecoder.getNextInsnOffset(insnByOffset, offset);
if (next != -1) if (next != -1) {
addJump(insnByOffset, offset, next); addJump(insnByOffset, offset, next);
}
addJump(insnByOffset, offset, ((IfNode) insn).getTarget()); addJump(insnByOffset, offset, ((IfNode) insn).getTarget());
break; break;
...@@ -363,10 +378,11 @@ public class MethodNode extends LineAttrNode implements ILoadable { ...@@ -363,10 +378,11 @@ public class MethodNode extends LineAttrNode implements ILoadable {
public String getName() { public String getName() {
String name = mthInfo.getName(); String name = mthInfo.getName();
if (name.equals(parentClass.getShortName())) if (name.equals(parentClass.getShortName())) {
return name + "_"; return name + "_";
else } else {
return name; return name;
}
} }
public ClassNode getParentClass() { public ClassNode getParentClass() {
...@@ -397,8 +413,9 @@ public class MethodNode extends LineAttrNode implements ILoadable { ...@@ -397,8 +413,9 @@ public class MethodNode extends LineAttrNode implements ILoadable {
blocks = Collections.unmodifiableList(blocks); blocks = Collections.unmodifiableList(blocks);
exitBlocks = Collections.unmodifiableList(exitBlocks); exitBlocks = Collections.unmodifiableList(exitBlocks);
for (BlockNode block : blocks) for (BlockNode block : blocks) {
block.lock(); block.lock();
}
} }
public List<BlockNode> getBasicBlocks() { public List<BlockNode> getBasicBlocks() {
...@@ -430,8 +447,9 @@ public class MethodNode extends LineAttrNode implements ILoadable { ...@@ -430,8 +447,9 @@ public class MethodNode extends LineAttrNode implements ILoadable {
public LoopAttr getLoopForBlock(BlockNode block) { public LoopAttr getLoopForBlock(BlockNode block) {
for (LoopAttr loop : loops) { for (LoopAttr loop : loops) {
if (loop.getLoopBlocks().contains(block)) if (loop.getLoopBlocks().contains(block)) {
return loop; return loop;
}
} }
return null; return null;
} }
...@@ -445,8 +463,9 @@ public class MethodNode extends LineAttrNode implements ILoadable { ...@@ -445,8 +463,9 @@ public class MethodNode extends LineAttrNode implements ILoadable {
exceptionHandlers = new ArrayList<ExceptionHandler>(2); exceptionHandlers = new ArrayList<ExceptionHandler>(2);
} else { } else {
for (ExceptionHandler h : exceptionHandlers) { for (ExceptionHandler h : exceptionHandlers) {
if (h == handler || h.getHandleOffset() == handler.getHandleOffset()) if (h == handler || h.getHandleOffset() == handler.getHandleOffset()) {
return h; return h;
}
} }
} }
exceptionHandlers.add(handler); exceptionHandlers.add(handler);
...@@ -471,8 +490,9 @@ public class MethodNode extends LineAttrNode implements ILoadable { ...@@ -471,8 +490,9 @@ public class MethodNode extends LineAttrNode implements ILoadable {
for (MethodNode method : methods) { for (MethodNode method : methods) {
if (this != method if (this != method
&& method.getName().equals(name) && method.getName().equals(name)
&& method.mthInfo.getArgumentsTypes().size() == argsCount) && method.mthInfo.getArgumentsTypes().size() == argsCount) {
return true; return true;
}
} }
return false; return false;
} }
...@@ -508,8 +528,12 @@ public class MethodNode extends LineAttrNode implements ILoadable { ...@@ -508,8 +528,12 @@ public class MethodNode extends LineAttrNode implements ILoadable {
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (this == obj) return true; if (this == obj) {
if (obj == null || getClass() != obj.getClass()) return false; return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
MethodNode other = (MethodNode) obj; MethodNode other = (MethodNode) obj;
return mthInfo.equals(other.mthInfo); return mthInfo.equals(other.mthInfo);
} }
......
...@@ -59,8 +59,9 @@ public class RootNode { ...@@ -59,8 +59,9 @@ public class RootNode {
// move inner classes // move inner classes
List<ClassNode> inner = new ArrayList<ClassNode>(); List<ClassNode> inner = new ArrayList<ClassNode>();
for (ClassNode cls : classes) { for (ClassNode cls : classes) {
if (cls.getClassInfo().isInner()) if (cls.getClassInfo().isInner()) {
inner.add(cls); inner.add(cls);
}
} }
for (ClassNode cls : inner) { for (ClassNode cls : inner) {
ClassNode parent = resolveClass(cls.getClassInfo().getParentClass()); ClassNode parent = resolveClass(cls.getClassInfo().getParentClass());
...@@ -81,8 +82,9 @@ public class RootNode { ...@@ -81,8 +82,9 @@ public class RootNode {
if (includeInner) { if (includeInner) {
classes.add(cls); classes.add(cls);
} else { } else {
if (!cls.getClassInfo().isInner()) if (!cls.getClassInfo().isInner()) {
classes.add(cls); classes.add(cls);
}
} }
} }
} }
......
...@@ -61,8 +61,6 @@ public class AnnotationsParser { ...@@ -61,8 +61,6 @@ public class AnnotationsParser {
private AnnotationsList readAnnotationSet(int offset) throws DecodeException { private AnnotationsList readAnnotationSet(int offset) throws DecodeException {
Section section = dex.openSection(offset); Section section = dex.openSection(offset);
int size = section.readInt(); int size = section.readInt();
if (size > 100)
section.toString();
List<Annotation> list = new ArrayList<Annotation>(size); List<Annotation> list = new ArrayList<Annotation>(size);
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
Section anSection = dex.openSection(section.readInt()); Section anSection = dex.openSection(section.readInt());
......
...@@ -162,18 +162,19 @@ public class DebugInfoParser { ...@@ -162,18 +162,19 @@ public class DebugInfoParser {
int newAddr = addr + addrInc; int newAddr = addr + addrInc;
for (int i = addr + 1; i <= newAddr; i++) { for (int i = addr + 1; i <= newAddr; i++) {
InsnNode insn = insnByOffset[i]; InsnNode insn = insnByOffset[i];
if (insn == null) if (insn == null) {
continue; continue;
}
insn.setSourceLine(line); insn.setSourceLine(line);
for (InsnArg arg : insn.getArguments()) for (InsnArg arg : insn.getArguments()) {
if (arg.isRegister()) { if (arg.isRegister()) {
activeRegisters[((RegisterArg) arg).getRegNum()] = arg; activeRegisters[((RegisterArg) arg).getRegNum()] = arg;
} }
}
RegisterArg res = insn.getResult(); RegisterArg res = insn.getResult();
if (res != null) if (res != null) {
activeRegisters[res.getRegNum()] = res; activeRegisters[res.getRegNum()] = res;
}
} }
return newAddr; return newAddr;
} }
...@@ -195,18 +196,20 @@ public class DebugInfoParser { ...@@ -195,18 +196,20 @@ public class DebugInfoParser {
for (int i = start; i <= end; i++) { for (int i = start; i <= end; i++) {
InsnNode insn = insnByOffset[i]; InsnNode insn = insnByOffset[i];
if (insn != null) if (insn != null) {
fillLocals(insn, var); fillLocals(insn, var);
}
} }
merge(activeRegisters[var.getRegNum()], var); merge(activeRegisters[var.getRegNum()], var);
} }
private static void fillLocals(InsnNode insn, LocalVar var) { private static void fillLocals(InsnNode insn, LocalVar var) {
if (insn.getResult() != null) 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) {
......
...@@ -53,11 +53,13 @@ public final class IfCondition { ...@@ -53,11 +53,13 @@ public final class IfCondition {
} }
public InsnArg getB() { public InsnArg getB() {
if (insn.isZeroCmp()) if (insn.isZeroCmp()) {
return InsnArg.lit(0, getA().getType()); return InsnArg.lit(0, getA().getType());
else } else {
return insn.getArg(1); return insn.getArg(1);
}
} }
public Compare invert() { public Compare invert() {
insn.invertCondition(); insn.invertCondition();
return this; return this;
......
...@@ -51,10 +51,12 @@ public final class IfRegion extends AbstractRegion { ...@@ -51,10 +51,12 @@ public final class IfRegion extends AbstractRegion {
public List<IContainer> getSubBlocks() { public List<IContainer> getSubBlocks() {
ArrayList<IContainer> all = new ArrayList<IContainer>(3); ArrayList<IContainer> all = new ArrayList<IContainer>(3);
all.add(header); all.add(header);
if (thenRegion != null) if (thenRegion != null) {
all.add(thenRegion); all.add(thenRegion);
if (elseRegion != null) }
if (elseRegion != null) {
all.add(elseRegion); all.add(elseRegion);
}
return Collections.unmodifiableList(all); return Collections.unmodifiableList(all);
} }
......
...@@ -68,9 +68,9 @@ public final class LoopRegion extends AbstractRegion { ...@@ -68,9 +68,9 @@ public final class LoopRegion extends AbstractRegion {
*/ */
public boolean checkPreCondition() { public boolean checkPreCondition() {
List<InsnNode> insns = preCondition.getInstructions(); List<InsnNode> insns = preCondition.getInstructions();
if (insns.isEmpty()) if (insns.isEmpty()) {
return true; return true;
}
IfNode ifInsn = getIfInsn(); IfNode ifInsn = getIfInsn();
int size = insns.size(); int size = insns.size();
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
...@@ -79,21 +79,23 @@ public final class LoopRegion extends AbstractRegion { ...@@ -79,21 +79,23 @@ public final class LoopRegion extends AbstractRegion {
return false; return false;
} else { } else {
RegisterArg res = insn.getResult(); RegisterArg res = insn.getResult();
if (res.getTypedVar().getUseList().size() > 2) if (res.getTypedVar().getUseList().size() > 2) {
return false; return false;
}
boolean found = false; boolean found = false;
// search result arg in other insns // search result arg in other insns
for (int j = i + 1; j < size; j++) { for (int j = i + 1; j < size; j++) {
if (insns.get(i).containsArg(res)) if (insns.get(i).containsArg(res)) {
found = true; found = true;
}
} }
// or in if insn // or in if insn
if (!found && ifInsn.containsArg(res)) if (!found && ifInsn.containsArg(res)) {
found = true; found = true;
}
if (!found) if (!found) {
return false; return false;
}
} }
} }
return true; return true;
...@@ -117,10 +119,12 @@ public final class LoopRegion extends AbstractRegion { ...@@ -117,10 +119,12 @@ public final class LoopRegion extends AbstractRegion {
@Override @Override
public List<IContainer> getSubBlocks() { public List<IContainer> getSubBlocks() {
List<IContainer> all = new ArrayList<IContainer>(3); List<IContainer> all = new ArrayList<IContainer>(3);
if (preCondition != null) if (preCondition != null) {
all.add(preCondition); all.add(preCondition);
if (conditionBlock != null) }
if (conditionBlock != null) {
all.add(conditionBlock); all.add(conditionBlock);
}
all.add(body); all.add(body);
return Collections.unmodifiableList(all); return Collections.unmodifiableList(all);
} }
......
...@@ -28,8 +28,9 @@ public final class Region extends AbstractRegion { ...@@ -28,8 +28,9 @@ public final class Region extends AbstractRegion {
sb.append(blocks.size()); sb.append(blocks.size());
if (blocks.size() != 0) { if (blocks.size() != 0) {
for (IContainer cont : blocks) { for (IContainer cont : blocks) {
if (cont instanceof BlockNode) if (cont instanceof BlockNode) {
sb.append(((BlockNode) cont).getId()); sb.append(((BlockNode) cont).getId());
}
} }
} }
return sb.toString(); return sb.toString();
......
...@@ -53,8 +53,9 @@ public final class SwitchRegion extends AbstractRegion { ...@@ -53,8 +53,9 @@ public final class SwitchRegion extends AbstractRegion {
List<IContainer> all = new ArrayList<IContainer>(cases.size() + 2); List<IContainer> all = new ArrayList<IContainer>(cases.size() + 2);
all.add(header); all.add(header);
all.addAll(cases); all.addAll(cases);
if (defCase != null) if (defCase != null) {
all.add(defCase); all.add(defCase);
}
return Collections.unmodifiableList(all); return Collections.unmodifiableList(all);
} }
......
...@@ -86,13 +86,23 @@ public class ExceptionHandler { ...@@ -86,13 +86,23 @@ public class ExceptionHandler {
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (this == obj) return true; if (this == obj) {
if (obj == null) return false; return true;
if (getClass() != obj.getClass()) return false; }
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
ExceptionHandler other = (ExceptionHandler) obj; ExceptionHandler other = (ExceptionHandler) obj;
if (catchType == null) { if (catchType == null) {
if (other.catchType != null) return false; if (other.catchType != null) {
} else if (!catchType.equals(other.catchType)) return false; return false;
}
} else if (!catchType.equals(other.catchType)) {
return false;
}
return handleOffset == other.handleOffset; return handleOffset == other.handleOffset;
} }
......
...@@ -22,14 +22,15 @@ public class ConstInlinerVisitor extends AbstractVisitor { ...@@ -22,14 +22,15 @@ public class ConstInlinerVisitor extends AbstractVisitor {
@Override @Override
public void visit(MethodNode mth) throws JadxException { public void visit(MethodNode mth) throws JadxException {
if (mth.isNoCode()) if (mth.isNoCode()) {
return; return;
}
for (BlockNode block : mth.getBasicBlocks()) { for (BlockNode block : mth.getBasicBlocks()) {
for (Iterator<InsnNode> it = block.getInstructions().iterator(); it.hasNext(); ) { for (Iterator<InsnNode> it = block.getInstructions().iterator(); it.hasNext(); ) {
InsnNode insn = it.next(); InsnNode insn = it.next();
if (checkInsn(mth, block, insn)) if (checkInsn(mth, block, insn)) {
it.remove(); it.remove();
}
} }
} }
} }
...@@ -57,9 +58,9 @@ public class ConstInlinerVisitor extends AbstractVisitor { ...@@ -57,9 +58,9 @@ public class ConstInlinerVisitor extends AbstractVisitor {
int replace = 0; int replace = 0;
for (InsnArg arg : use) { for (InsnArg arg : use) {
InsnNode useInsn = arg.getParentInsn(); InsnNode useInsn = arg.getParentInsn();
if (useInsn == null) if (useInsn == null) {
continue; continue;
}
BlockNode useBlock = BlockUtils.getBlockByInsn(mth, useInsn); BlockNode useBlock = BlockUtils.getBlockByInsn(mth, useInsn);
if (useBlock == block || useBlock.isDominator(block)) { if (useBlock == block || useBlock.isDominator(block)) {
if (arg != insn.getResult() && !registerReassignOnPath(block, useBlock, insn)) { if (arg != insn.getResult() && !registerReassignOnPath(block, useBlock, insn)) {
...@@ -77,9 +78,9 @@ public class ConstInlinerVisitor extends AbstractVisitor { ...@@ -77,9 +78,9 @@ public class ConstInlinerVisitor extends AbstractVisitor {
} }
private static boolean registerReassignOnPath(BlockNode block, BlockNode useBlock, InsnNode assignInsn) { private static boolean registerReassignOnPath(BlockNode block, BlockNode useBlock, InsnNode assignInsn) {
if (block == useBlock) if (block == useBlock) {
return false; return false;
}
Set<BlockNode> blocks = BlockUtils.getAllPathsBlocks(block, useBlock); Set<BlockNode> blocks = BlockUtils.getAllPathsBlocks(block, useBlock);
// TODO store list of assign insn for each register // TODO store list of assign insn for each register
int regNum = assignInsn.getResult().getRegNum(); int regNum = assignInsn.getResult().getRegNum();
...@@ -87,8 +88,9 @@ public class ConstInlinerVisitor extends AbstractVisitor { ...@@ -87,8 +88,9 @@ public class ConstInlinerVisitor extends AbstractVisitor {
for (InsnNode insn : b.getInstructions()) { for (InsnNode insn : b.getInstructions()) {
if (insn.getResult() != null if (insn.getResult() != null
&& insn != assignInsn && insn != assignInsn
&& insn.getResult().getRegNum() == regNum) && insn.getResult().getRegNum() == regNum) {
return true; return true;
}
} }
} }
return false; return false;
...@@ -156,10 +158,11 @@ public class ConstInlinerVisitor extends AbstractVisitor { ...@@ -156,10 +158,11 @@ public class ConstInlinerVisitor extends AbstractVisitor {
InsnArg arg = insn.getArg(i); InsnArg arg = insn.getArg(i);
if (!arg.getType().isTypeKnown()) { if (!arg.getType().isTypeKnown()) {
ArgType type; ArgType type;
if (k >= 0) if (k >= 0) {
type = types.get(k); type = types.get(k);
else } else {
type = mth.getParentClass().getClassInfo().getType(); type = mth.getParentClass().getClassInfo().getType();
}
arg.merge(type); arg.merge(type);
} }
k++; k++;
......
...@@ -9,10 +9,12 @@ public class DepthTraverser { ...@@ -9,10 +9,12 @@ public class DepthTraverser {
public static void visit(IDexTreeVisitor visitor, ClassNode cls) { public static void visit(IDexTreeVisitor visitor, ClassNode cls) {
try { try {
if (visitor.visit(cls)) { if (visitor.visit(cls)) {
for (ClassNode inCls : cls.getInnerClasses()) for (ClassNode inCls : cls.getInnerClasses()) {
visit(visitor, inCls); visit(visitor, inCls);
for (MethodNode mth : cls.getMethods()) }
for (MethodNode mth : cls.getMethods()) {
visit(visitor, mth); visit(visitor, mth);
}
} }
} catch (Throwable e) { } catch (Throwable e) {
ErrorsCounter.classError(cls, ErrorsCounter.classError(cls,
......
...@@ -36,9 +36,9 @@ public class DotGraphVisitor extends AbstractVisitor { ...@@ -36,9 +36,9 @@ public class DotGraphVisitor extends AbstractVisitor {
@Override @Override
public void visit(MethodNode mth) { public void visit(MethodNode mth) {
if (mth.isNoCode()) if (mth.isNoCode()) {
return; return;
}
CodeWriter dot = new CodeWriter(); CodeWriter dot = new CodeWriter();
CodeWriter conn = new CodeWriter(); CodeWriter conn = new CodeWriter();
...@@ -47,18 +47,22 @@ public class DotGraphVisitor extends AbstractVisitor { ...@@ -47,18 +47,22 @@ public class DotGraphVisitor extends AbstractVisitor {
+ "\" {"); + "\" {");
if (useRegions) { if (useRegions) {
if (mth.getRegion() == null) if (mth.getRegion() == null) {
return; return;
}
processRegion(mth, mth.getRegion(), dot, conn); processRegion(mth, mth.getRegion(), dot, conn);
if (mth.getExceptionHandlers() != null) { if (mth.getExceptionHandlers() != null) {
for (ExceptionHandler h : mth.getExceptionHandlers()) for (ExceptionHandler h : mth.getExceptionHandlers()) {
if (h.getHandlerRegion() != null) if (h.getHandlerRegion() != null) {
processRegion(mth, h.getHandlerRegion(), dot, conn); processRegion(mth, h.getHandlerRegion(), dot, conn);
}
}
} }
} else { } else {
for (BlockNode block : mth.getBasicBlocks()) for (BlockNode block : mth.getBasicBlocks()) {
processBlock(mth, block, dot, conn); processBlock(mth, block, dot, conn);
}
} }
String attrs = attributesString(mth); String attrs = attributesString(mth);
...@@ -109,8 +113,9 @@ public class DotGraphVisitor extends AbstractVisitor { ...@@ -109,8 +113,9 @@ public class DotGraphVisitor extends AbstractVisitor {
String attrs = attributesString(block); String attrs = attributesString(block);
if (PRINT_REGISTERS_STATES) { if (PRINT_REGISTERS_STATES) {
if (block.getStartState() != null) { if (block.getStartState() != null) {
if (attrs.length() != 0) if (attrs.length() != 0) {
attrs += "|"; attrs += "|";
}
attrs += escape("RS: " + block.getStartState()) + NL; attrs += escape("RS: " + block.getStartState()) + NL;
attrs += escape("RE: " + block.getEndState()) + NL; attrs += escape("RE: " + block.getEndState()) + NL;
} }
...@@ -125,16 +130,17 @@ public class DotGraphVisitor extends AbstractVisitor { ...@@ -125,16 +130,17 @@ public class DotGraphVisitor extends AbstractVisitor {
+ (insns.length() == 0 ? "" : "|" + insns) + (insns.length() == 0 ? "" : "|" + insns)
+ "}\"];"); + "}\"];");
for (BlockNode next : block.getSuccessors()) for (BlockNode next : block.getSuccessors()) {
conn.startLine(makeName(block) + " -> " + makeName(next) + ";"); conn.startLine(makeName(block) + " -> " + makeName(next) + ";");
}
for (BlockNode next : block.getDominatesOn()) for (BlockNode next : block.getDominatesOn()) {
conn.startLine(makeName(block) + " -> " + makeName(next) + "[style=dotted];"); conn.startLine(makeName(block) + " -> " + makeName(next) + "[style=dotted];");
}
// add all dominators connections // add all dominators connections
if (false) { if (false) {
for (BlockNode next : BlockUtils.bitsetToBlocks(mth, block.getDoms())) for (BlockNode next : BlockUtils.bitsetToBlocks(mth, block.getDoms())) {
conn.startLine(makeName(block) + " -> " + makeName(next) + "[style=dotted, color=green];"); conn.startLine(makeName(block) + " -> " + makeName(next) + "[style=dotted, color=green];");
}
} }
} }
...@@ -168,8 +174,9 @@ public class DotGraphVisitor extends AbstractVisitor { ...@@ -168,8 +174,9 @@ public class DotGraphVisitor extends AbstractVisitor {
CodeWriter code = new CodeWriter(0); CodeWriter code = new CodeWriter(0);
MethodGen.makeFallbackInsns(code, mth, block.getInstructions(), false); MethodGen.makeFallbackInsns(code, mth, block.getInstructions(), false);
String str = escape(code.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());
}
return str; return str;
} }
} }
......
...@@ -10,9 +10,9 @@ public class FallbackModeVisitor extends AbstractVisitor { ...@@ -10,9 +10,9 @@ public class FallbackModeVisitor extends AbstractVisitor {
@Override @Override
public void visit(MethodNode mth) throws JadxException { public void visit(MethodNode mth) throws JadxException {
if (mth.isNoCode()) if (mth.isNoCode()) {
return; return;
}
for (InsnNode insn : mth.getInstructions()) { for (InsnNode insn : mth.getInstructions()) {
// remove 'exception catch' for instruction which don't throw any exceptions // remove 'exception catch' for instruction which don't throw any exceptions
CatchAttr catchAttr = (CatchAttr) insn.getAttributes().get(AttributeType.CATCH_BLOCK); CatchAttr catchAttr = (CatchAttr) insn.getAttributes().get(AttributeType.CATCH_BLOCK);
......
...@@ -22,18 +22,20 @@ public class CheckRegions extends AbstractVisitor { ...@@ -22,18 +22,20 @@ public class CheckRegions extends AbstractVisitor {
@Override @Override
public void visit(MethodNode mth) throws JadxException { public void visit(MethodNode mth) throws JadxException {
if (mth.isNoCode() || mth.getBasicBlocks().size() == 0) if (mth.isNoCode() || mth.getBasicBlocks().size() == 0) {
return; return;
}
// check if all blocks included in regions // check if all blocks included in regions
final Set<BlockNode> blocksInRegions = new HashSet<BlockNode>(); final Set<BlockNode> blocksInRegions = new HashSet<BlockNode>();
IRegionVisitor collectBlocks = new AbstractRegionVisitor() { IRegionVisitor collectBlocks = new AbstractRegionVisitor() {
@Override @Override
public void processBlock(MethodNode mth, IBlock container) { public void processBlock(MethodNode mth, IBlock container) {
if (container instanceof BlockNode) if (container instanceof BlockNode) {
blocksInRegions.add((BlockNode) container); blocksInRegions.add((BlockNode) container);
else } else {
LOG.warn("Not block node : " + container.getClass().getSimpleName()); LOG.warn("Not block node : " + container.getClass().getSimpleName());
}
} }
}; };
DepthRegionTraverser.traverseAll(mth, collectBlocks); DepthRegionTraverser.traverseAll(mth, collectBlocks);
...@@ -44,10 +46,11 @@ public class CheckRegions extends AbstractVisitor { ...@@ -44,10 +46,11 @@ public class CheckRegions extends AbstractVisitor {
if (!block.getInstructions().isEmpty() if (!block.getInstructions().isEmpty()
&& !block.getAttributes().contains(AttributeFlag.SKIP)) { && !block.getAttributes().contains(AttributeFlag.SKIP)) {
mth.getAttributes().add(AttributeFlag.INCONSISTENT_CODE); mth.getAttributes().add(AttributeFlag.INCONSISTENT_CODE);
if (Consts.DEBUG) if (Consts.DEBUG) {
LOG.debug(" Missing block: {} in {}", block, mth); LOG.debug(" Missing block: {} in {}", block, mth);
else } else {
break; break;
}
} }
} }
} }
......
...@@ -18,14 +18,15 @@ public class CleanRegions extends AbstractVisitor { ...@@ -18,14 +18,15 @@ public class CleanRegions extends AbstractVisitor {
@Override @Override
public void visit(MethodNode mth) throws JadxException { public void visit(MethodNode mth) throws JadxException {
if (mth.isNoCode() || mth.getBasicBlocks().size() == 0) if (mth.isNoCode() || mth.getBasicBlocks().size() == 0) {
return; return;
}
IRegionVisitor removeEmptyBlocks = new AbstractRegionVisitor() { IRegionVisitor removeEmptyBlocks = new AbstractRegionVisitor() {
@Override @Override
public void enterRegion(MethodNode mth, IRegion region) { public void enterRegion(MethodNode mth, IRegion region) {
if (!(region instanceof Region)) if (!(region instanceof Region)) {
return; return;
}
for (Iterator<IContainer> it = region.getSubBlocks().iterator(); it.hasNext(); ) { for (Iterator<IContainer> it = region.getSubBlocks().iterator(); it.hasNext(); ) {
IContainer container = it.next(); IContainer container = it.next();
...@@ -44,6 +45,5 @@ public class CleanRegions extends AbstractVisitor { ...@@ -44,6 +45,5 @@ public class CleanRegions extends AbstractVisitor {
} }
}; };
DepthRegionTraverser.traverseAll(mth, removeEmptyBlocks); DepthRegionTraverser.traverseAll(mth, removeEmptyBlocks);
} }
} }
...@@ -25,8 +25,9 @@ public class DepthRegionTraverser { ...@@ -25,8 +25,9 @@ public class DepthRegionTraverser {
traverse(mth, visitor, mth.getRegion()); traverse(mth, visitor, mth.getRegion());
if (mth.getExceptionHandlers() != null) { if (mth.getExceptionHandlers() != null) {
for (ExceptionHandler h : mth.getExceptionHandlers()) for (ExceptionHandler h : mth.getExceptionHandlers()) {
traverse(mth, visitor, h.getHandlerRegion()); traverse(mth, visitor, h.getHandlerRegion());
}
} }
} }
} }
...@@ -141,12 +141,13 @@ public class ProcessVariables extends AbstractVisitor { ...@@ -141,12 +141,13 @@ public class ProcessVariables extends AbstractVisitor {
for (Iterator<IRegion> it = set.iterator(); it.hasNext(); ) { for (Iterator<IRegion> it = set.iterator(); it.hasNext(); ) {
IRegion r = it.next(); IRegion r = it.next();
IRegion parent = r.getParent(); IRegion parent = r.getParent();
if (parent != null && set.contains(parent)) if (parent != null && set.contains(parent)) {
it.remove(); it.remove();
}
} }
if (set.isEmpty()) if (set.isEmpty()) {
continue; continue;
}
IRegion region = set.iterator().next(); IRegion region = set.iterator().next();
IRegion parent = region; IRegion parent = region;
boolean declare = false; boolean declare = false;
...@@ -178,12 +179,14 @@ public class ProcessVariables extends AbstractVisitor { ...@@ -178,12 +179,14 @@ public class ProcessVariables extends AbstractVisitor {
private boolean canDeclareInRegion(Usage u, IRegion region) { private boolean canDeclareInRegion(Usage u, IRegion region) {
for (IRegion r : u.getAssigns()) { for (IRegion r : u.getAssigns()) {
if (!RegionUtils.isRegionContainsRegion(region, r)) if (!RegionUtils.isRegionContainsRegion(region, r)) {
return false; return false;
}
} }
for (IRegion r : u.getUseRegions()) { for (IRegion r : u.getUseRegions()) {
if (!RegionUtils.isRegionContainsRegion(region, r)) if (!RegionUtils.isRegionContainsRegion(region, r)) {
return false; return false;
}
} }
return true; return true;
} }
......
...@@ -12,9 +12,9 @@ public class RegionMakerVisitor extends AbstractVisitor { ...@@ -12,9 +12,9 @@ public class RegionMakerVisitor extends AbstractVisitor {
@Override @Override
public void visit(MethodNode mth) throws JadxException { public void visit(MethodNode mth) throws JadxException {
if (mth.isNoCode()) if (mth.isNoCode()) {
return; return;
}
RegionMaker rm = new RegionMaker(mth); RegionMaker rm = new RegionMaker(mth);
RegionStack state = new RegionStack(mth); RegionStack state = new RegionStack(mth);
......
...@@ -17,8 +17,9 @@ final class RegionStack { ...@@ -17,8 +17,9 @@ final class RegionStack {
private static final boolean DEBUG = false; private static final boolean DEBUG = false;
static { static {
if (DEBUG) if (DEBUG) {
LOG.debug("Debug enabled for {}", RegionStack.class); LOG.debug("Debug enabled for {}", RegionStack.class);
}
} }
private static final class State { private static final class State {
...@@ -47,27 +48,30 @@ final class RegionStack { ...@@ -47,27 +48,30 @@ final class RegionStack {
private State curState; private State curState;
public RegionStack(MethodNode mth) { public RegionStack(MethodNode mth) {
if (DEBUG) if (DEBUG) {
LOG.debug("New RegionStack: {}", mth); LOG.debug("New RegionStack: {}", mth);
}
this.stack = new ArrayDeque<State>(); this.stack = new ArrayDeque<State>();
this.curState = new State(); this.curState = new State();
} }
public void push(IRegion region) { public void push(IRegion region) {
stack.push(curState); stack.push(curState);
if (stack.size() > 1000) if (stack.size() > 1000) {
throw new StackOverflowError("Deep code hierarchy"); throw new StackOverflowError("Deep code hierarchy");
}
curState = curState.copy(); curState = curState.copy();
curState.region = region; curState.region = region;
if (DEBUG) if (DEBUG) {
LOG.debug("Stack push: {}: {}", size(), curState); LOG.debug("Stack push: {}: {}", size(), curState);
}
} }
public void pop() { public void pop() {
curState = stack.pop(); curState = stack.pop();
if (DEBUG) if (DEBUG) {
LOG.debug("Stack pop: {}: {}", size(), curState); LOG.debug("Stack pop: {}: {}", size(), curState);
}
} }
/** /**
...@@ -76,8 +80,9 @@ final class RegionStack { ...@@ -76,8 +80,9 @@ final class RegionStack {
* @param exit boundary node, null will be ignored * @param exit boundary node, null will be ignored
*/ */
public void addExit(BlockNode exit) { public void addExit(BlockNode exit) {
if (exit != null) if (exit != null) {
curState.exits.add(exit); curState.exits.add(exit);
}
} }
public boolean containsExit(BlockNode exit) { public boolean containsExit(BlockNode exit) {
......
...@@ -12,31 +12,39 @@ public class FinishTypeResolver extends AbstractVisitor { ...@@ -12,31 +12,39 @@ public class FinishTypeResolver extends AbstractVisitor {
@Override @Override
public void visit(MethodNode mth) { public void visit(MethodNode mth) {
if (mth.isNoCode()) if (mth.isNoCode()) {
return; return;
}
boolean change; boolean change;
int i = 0; int i = 0;
do { do {
change = false; change = false;
for (BlockNode block : mth.getBasicBlocks()) { for (BlockNode block : mth.getBasicBlocks()) {
for (InsnNode insn : block.getInstructions()) for (InsnNode insn : block.getInstructions()) {
if (PostTypeResolver.visit(mth, insn)) if (PostTypeResolver.visit(mth, insn)) {
change = true; change = true;
}
}
} }
i++; i++;
if (i > 1000) if (i > 1000) {
break; break;
}
} while (change); } while (change);
// last chance to set correct value (just use first type from 'possible' list) // last chance to set correct value (just use first type from 'possible' list)
for (BlockNode block : mth.getBasicBlocks()) for (BlockNode block : mth.getBasicBlocks()) {
for (InsnNode insn : block.getInstructions()) for (InsnNode insn : block.getInstructions()) {
SelectTypeVisitor.visit(insn); SelectTypeVisitor.visit(insn);
}
}
// check // check
for (BlockNode block : mth.getBasicBlocks()) for (BlockNode block : mth.getBasicBlocks()) {
for (InsnNode insn : block.getInstructions()) for (InsnNode insn : block.getInstructions()) {
CheckTypeVisitor.visit(mth, insn); CheckTypeVisitor.visit(mth, insn);
}
}
} }
} }
...@@ -16,9 +16,9 @@ public class TypeResolver extends AbstractVisitor { ...@@ -16,9 +16,9 @@ public class TypeResolver extends AbstractVisitor {
@Override @Override
public void visit(MethodNode mth) { public void visit(MethodNode mth) {
if (mth.isNoCode()) if (mth.isNoCode()) {
return; return;
}
prepare(mth); prepare(mth);
visitBlocks(mth); visitBlocks(mth);
...@@ -60,11 +60,13 @@ public class TypeResolver extends AbstractVisitor { ...@@ -60,11 +60,13 @@ public class TypeResolver extends AbstractVisitor {
for (InsnNode insn : block.getInstructions()) { for (InsnNode insn : block.getInstructions()) {
for (InsnArg arg : insn.getArguments()) { for (InsnArg arg : insn.getArguments()) {
if (arg.isRegister()) if (arg.isRegister()) {
state.use((RegisterArg) arg); state.use((RegisterArg) arg);
}
} }
if (insn.getResult() != null) if (insn.getResult() != null) {
state.assignReg(insn.getResult()); state.assignReg(insn.getResult());
}
} }
block.setEndState(new BlockRegState(state)); block.setEndState(new BlockRegState(state));
...@@ -78,8 +80,9 @@ public class TypeResolver extends AbstractVisitor { ...@@ -78,8 +80,9 @@ public class TypeResolver extends AbstractVisitor {
changed = false; changed = false;
for (BlockNode block : preds) { for (BlockNode block : preds) {
for (BlockNode pred : block.getPredecessors()) { for (BlockNode pred : block.getPredecessors()) {
if (connectEdges(mth, pred, block, true)) if (connectEdges(mth, pred, block, true)) {
changed = true; changed = true;
}
} }
} }
} while (changed); } while (changed);
......
...@@ -39,10 +39,12 @@ public class PostTypeResolver { ...@@ -39,10 +39,12 @@ public class PostTypeResolver {
case MOVE: { case MOVE: {
boolean change = false; boolean change = false;
if (insn.getResult().merge(insn.getArg(0))) if (insn.getResult().merge(insn.getArg(0))) {
change = true; change = true;
if (insn.getArg(0).merge(insn.getResult())) }
if (insn.getArg(0).merge(insn.getResult())) {
change = true; change = true;
}
return change; return change;
} }
...@@ -56,10 +58,12 @@ public class PostTypeResolver { ...@@ -56,10 +58,12 @@ public class PostTypeResolver {
boolean change = false; boolean change = false;
IfNode ifnode = (IfNode) insn; IfNode ifnode = (IfNode) insn;
if (!ifnode.isZeroCmp()) { if (!ifnode.isZeroCmp()) {
if (insn.getArg(1).merge(insn.getArg(0))) if (insn.getArg(1).merge(insn.getArg(0))) {
change = true; change = true;
if (insn.getArg(0).merge(insn.getArg(1))) }
if (insn.getArg(0).merge(insn.getArg(1))) {
change = true; change = true;
}
} }
return change; return change;
} }
...@@ -94,10 +98,12 @@ public class PostTypeResolver { ...@@ -94,10 +98,12 @@ public class PostTypeResolver {
private static boolean fixArrayTypes(InsnArg array, InsnArg elem) { private static boolean fixArrayTypes(InsnArg array, InsnArg elem) {
boolean change = false; boolean change = false;
if (!elem.getType().isTypeKnown() && elem.merge(array.getType().getArrayElement())) if (!elem.getType().isTypeKnown() && elem.merge(array.getType().getArrayElement())) {
change = true; change = true;
if (!array.getType().isTypeKnown() && array.merge(ArgType.array(elem.getType()))) }
if (!array.getType().isTypeKnown() && array.merge(ArgType.array(elem.getType()))) {
change = true; change = true;
}
return change; return change;
} }
} }
...@@ -13,8 +13,9 @@ public class SelectTypeVisitor { ...@@ -13,8 +13,9 @@ public class SelectTypeVisitor {
} }
for (InsnArg arg : insn.getArguments()) { for (InsnArg arg : insn.getArguments()) {
if (!arg.getType().isTypeKnown()) if (!arg.getType().isTypeKnown()) {
selectType(arg); selectType(arg);
}
} }
} }
......
...@@ -33,25 +33,27 @@ public class BlockUtils { ...@@ -33,25 +33,27 @@ public class BlockUtils {
} }
assert list.size() == 2 : "too many nodes for selectOther: " + node + " in " + list; assert list.size() == 2 : "too many nodes for selectOther: " + node + " in " + list;
BlockNode first = list.get(0); BlockNode first = list.get(0);
if (first != node) if (first != node) {
return first; return first;
else } else {
return list.get(1); return list.get(1);
}
} }
private static List<BlockNode> cleanBlockList(List<BlockNode> list) { private static List<BlockNode> cleanBlockList(List<BlockNode> list) {
List<BlockNode> ret = new ArrayList<BlockNode>(list.size()); List<BlockNode> ret = new ArrayList<BlockNode>(list.size());
for (BlockNode block : list) { for (BlockNode block : list) {
if (!block.getAttributes().contains(AttributeType.EXC_HANDLER)) if (!block.getAttributes().contains(AttributeType.EXC_HANDLER)) {
ret.add(block); ret.add(block);
}
} }
return ret; return ret;
} }
public static boolean isBackEdge(BlockNode from, BlockNode to) { public static boolean isBackEdge(BlockNode from, BlockNode to) {
if (from.getCleanSuccessors().contains(to)) if (from.getCleanSuccessors().contains(to)) {
return false; // already checked return false; // already checked
}
return from.getSuccessors().contains(to); return from.getSuccessors().contains(to);
} }
...@@ -61,8 +63,9 @@ public class BlockUtils { ...@@ -61,8 +63,9 @@ public class BlockUtils {
public static void cleanBitSet(MethodNode mth, BitSet bs) { public static void cleanBitSet(MethodNode mth, BitSet bs) {
for (int i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i + 1)) { for (int i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i + 1)) {
BlockNode block = mth.getBasicBlocks().get(i); BlockNode block = mth.getBasicBlocks().get(i);
if (block.getAttributes().contains(AttributeType.EXC_HANDLER)) if (block.getAttributes().contains(AttributeType.EXC_HANDLER)) {
bs.clear(i); bs.clear(i);
}
} }
} }
...@@ -81,17 +84,18 @@ public class BlockUtils { ...@@ -81,17 +84,18 @@ public class BlockUtils {
*/ */
public static boolean blockContains(BlockNode block, InsnNode insn) { public static boolean blockContains(BlockNode block, InsnNode insn) {
for (InsnNode bi : block.getInstructions()) { for (InsnNode bi : block.getInstructions()) {
if (bi == insn) if (bi == insn) {
return true; return true;
}
} }
return false; return false;
} }
public static boolean lastInsnType(BlockNode block, InsnType type) { public static boolean lastInsnType(BlockNode block, InsnType type) {
List<InsnNode> insns = block.getInstructions(); List<InsnNode> insns = block.getInstructions();
if (insns.isEmpty()) if (insns.isEmpty()) {
return false; return false;
}
InsnNode insn = insns.get(insns.size() - 1); InsnNode insn = insns.get(insns.size() - 1);
return insn.getType() == type; return insn.getType() == type;
} }
...@@ -99,8 +103,9 @@ public class BlockUtils { ...@@ -99,8 +103,9 @@ public class BlockUtils {
public static BlockNode getBlockByInsn(MethodNode mth, InsnNode insn) { public static BlockNode getBlockByInsn(MethodNode mth, InsnNode insn) {
assert insn != null; assert insn != null;
for (BlockNode bn : mth.getBasicBlocks()) { for (BlockNode bn : mth.getBasicBlocks()) {
if (blockContains(bn, insn)) if (blockContains(bn, insn)) {
return bn; return bn;
}
} }
return null; return null;
} }
...@@ -136,8 +141,9 @@ public class BlockUtils { ...@@ -136,8 +141,9 @@ public class BlockUtils {
public static Set<BlockNode> getAllPathsBlocks(BlockNode start, BlockNode end) { public static Set<BlockNode> getAllPathsBlocks(BlockNode start, BlockNode end) {
Set<BlockNode> set = new HashSet<BlockNode>(); Set<BlockNode> set = new HashSet<BlockNode>();
set.add(start); set.add(start);
if (start != end) if (start != end) {
addPredcessors(set, end, start); addPredcessors(set, end, start);
}
return set; return set;
} }
...@@ -152,29 +158,29 @@ public class BlockUtils { ...@@ -152,29 +158,29 @@ public class BlockUtils {
private static boolean traverseSuccessorsUntil(BlockNode from, BlockNode until, Set<BlockNode> checked) { private static boolean traverseSuccessorsUntil(BlockNode from, BlockNode until, Set<BlockNode> checked) {
for (BlockNode s : from.getCleanSuccessors()) { for (BlockNode s : from.getCleanSuccessors()) {
if (s == until) if (s == until) {
return true; return true;
}
if (!checked.contains(s)) { if (!checked.contains(s)) {
checked.add(s); checked.add(s);
if (until.isDominator(s)) {
if (until.isDominator(s))
return true; return true;
}
if (traverseSuccessorsUntil(s, until, checked)) if (traverseSuccessorsUntil(s, until, checked)) {
return true; return true;
}
} }
} }
return false; return false;
} }
public static boolean isPathExists(BlockNode start, BlockNode end) { public static boolean isPathExists(BlockNode start, BlockNode end) {
if (start == end) if (start == end) {
return true; return true;
}
if (end.isDominator(start)) if (end.isDominator(start)) {
return true; return true;
}
return traverseSuccessorsUntil(start, end, new HashSet<BlockNode>()); return traverseSuccessorsUntil(start, end, new HashSet<BlockNode>());
} }
...@@ -203,8 +209,9 @@ public class BlockUtils { ...@@ -203,8 +209,9 @@ public class BlockUtils {
return node; return node;
} else { } else {
BlockNode out = traverseWhileDominates(block, node); BlockNode out = traverseWhileDominates(block, node);
if (out != null) if (out != null) {
return out; return out;
}
} }
} }
return null; return null;
......
...@@ -81,10 +81,11 @@ public class ErrorsCounter { ...@@ -81,10 +81,11 @@ public class ErrorsCounter {
} }
private static String formatException(Throwable e) { private static String formatException(Throwable e) {
if (e == null || e.getMessage() == null) if (e == null || e.getMessage() == null) {
return ""; return "";
else } else {
return "\n error: " + e.getMessage(); return "\n error: " + e.getMessage();
}
} }
public static String formatErrorMsg(ClassNode cls, String msg, Throwable e) { public static String formatErrorMsg(ClassNode cls, String msg, Throwable e) {
......
...@@ -40,12 +40,13 @@ public class InsnUtils { ...@@ -40,12 +40,13 @@ public class InsnUtils {
} }
public static String indexToString(Object index) { public static String indexToString(Object index) {
if (index == null) if (index == null) {
return ""; return "";
}
if (index instanceof String) if (index instanceof String) {
return "\"" + index + "\""; return "\"" + index + "\"";
else } else {
return " " + index.toString(); return " " + index.toString();
}
} }
} }
...@@ -32,8 +32,9 @@ public class InstructionRemover { ...@@ -32,8 +32,9 @@ public class InstructionRemover {
} }
public static void unbindInsnList(List<InsnNode> unbind) { public static void unbindInsnList(List<InsnNode> unbind) {
for (InsnNode rem : unbind) for (InsnNode rem : unbind) {
unbindInsn(rem); unbindInsn(rem);
}
} }
public static void unbindInsn(InsnNode insn) { public static void unbindInsn(InsnNode insn) {
...@@ -56,8 +57,9 @@ public class InstructionRemover { ...@@ -56,8 +57,9 @@ public class InstructionRemover {
// and here can be several instructions with same content // and here can be several instructions with same content
public static void removeAll(List<InsnNode> insns, List<InsnNode> toRemove) { public static void removeAll(List<InsnNode> insns, List<InsnNode> toRemove) {
if (insns == toRemove) { if (insns == toRemove) {
for (InsnNode rem : toRemove) for (InsnNode rem : toRemove) {
unbindInsn(rem); unbindInsn(rem);
}
return; return;
} }
......
...@@ -19,8 +19,9 @@ public class RegionUtils { ...@@ -19,8 +19,9 @@ public class RegionUtils {
} else if (container instanceof IRegion) { } else if (container instanceof IRegion) {
IRegion region = (IRegion) container; IRegion region = (IRegion) container;
List<IContainer> blocks = region.getSubBlocks(); List<IContainer> blocks = region.getSubBlocks();
if (blocks.isEmpty()) if (blocks.isEmpty()) {
return false; return false;
}
return hasExitEdge(blocks.get(blocks.size() - 1)); return hasExitEdge(blocks.get(blocks.size() - 1));
} else { } else {
throw new JadxRuntimeException("Unknown container type: " + container.getClass()); throw new JadxRuntimeException("Unknown container type: " + container.getClass());
...@@ -33,8 +34,9 @@ public class RegionUtils { ...@@ -33,8 +34,9 @@ public class RegionUtils {
} else if (container instanceof IRegion) { } else if (container instanceof IRegion) {
IRegion region = (IRegion) container; IRegion region = (IRegion) container;
for (IContainer block : region.getSubBlocks()) { for (IContainer block : region.getSubBlocks()) {
if (notEmpty(block)) if (notEmpty(block)) {
return true; return true;
}
} }
return false; return false;
} else { } else {
...@@ -61,8 +63,9 @@ public class RegionUtils { ...@@ -61,8 +63,9 @@ public class RegionUtils {
} else if (container instanceof IRegion) { } else if (container instanceof IRegion) {
IRegion region = (IRegion) container; IRegion region = (IRegion) container;
for (IContainer b : region.getSubBlocks()) { for (IContainer b : region.getSubBlocks()) {
if (isRegionContainsBlock(b, block)) if (isRegionContainsBlock(b, block)) {
return true; return true;
}
} }
return false; return false;
} else { } else {
...@@ -71,8 +74,9 @@ public class RegionUtils { ...@@ -71,8 +74,9 @@ public class RegionUtils {
} }
private static boolean isRegionContainsExcHandlerRegion(IContainer container, IRegion region) { private static boolean isRegionContainsExcHandlerRegion(IContainer container, IRegion region) {
if (container == region) if (container == region) {
return true; return true;
}
if (container instanceof IRegion) { if (container instanceof IRegion) {
IRegion r = (IRegion) container; IRegion r = (IRegion) container;
...@@ -84,16 +88,19 @@ public class RegionUtils { ...@@ -84,16 +88,19 @@ public class RegionUtils {
if (cb != null && (b instanceof IRegion)) { if (cb != null && (b instanceof IRegion)) {
TryCatchBlock tb = cb.getTryBlock(); TryCatchBlock tb = cb.getTryBlock();
for (ExceptionHandler eh : tb.getHandlers()) { for (ExceptionHandler eh : tb.getHandlers()) {
if (isRegionContainsRegion(eh.getHandlerRegion(), region)) if (isRegionContainsRegion(eh.getHandlerRegion(), region)) {
return true; return true;
}
} }
if (tb.getFinalBlock() != null) { if (tb.getFinalBlock() != null) {
if (isRegionContainsRegion(tb.getFinalBlock(), region)) if (isRegionContainsRegion(tb.getFinalBlock(), region)) {
return true; return true;
}
} }
} }
if (isRegionContainsRegion(b, region)) if (isRegionContainsRegion(b, region)) {
return true; return true;
}
} }
} }
return false; return false;
...@@ -105,16 +112,20 @@ public class RegionUtils { ...@@ -105,16 +112,20 @@ public class RegionUtils {
* otherwise run recursive search because exception handlers can have several parents * otherwise run recursive search because exception handlers can have several parents
*/ */
public static boolean isRegionContainsRegion(IContainer container, IRegion region) { public static boolean isRegionContainsRegion(IContainer container, IRegion region) {
if (container == region) return true; if (container == region) {
if (region == null) return false; return true;
}
if (region == null) {
return false;
}
IRegion parent = region.getParent(); IRegion parent = region.getParent();
while (container != parent) { while (container != parent) {
if (parent == null) { if (parent == null) {
if (region.getAttributes().contains(AttributeType.EXC_HANDLER)) if (region.getAttributes().contains(AttributeType.EXC_HANDLER)) {
return isRegionContainsExcHandlerRegion(container, region); return isRegionContainsExcHandlerRegion(container, region);
else } else {
return false; return false;
}
} }
region = parent; region = parent;
parent = region.getParent(); parent = region.getParent();
...@@ -123,11 +134,9 @@ public class RegionUtils { ...@@ -123,11 +134,9 @@ public class RegionUtils {
} }
public static boolean isDominaterBy(BlockNode dom, IContainer cont) { public static boolean isDominaterBy(BlockNode dom, IContainer cont) {
assert cont != null; if (dom == cont) {
if (dom == cont)
return true; return true;
}
if (cont instanceof BlockNode) { if (cont instanceof BlockNode) {
BlockNode block = (BlockNode) cont; BlockNode block = (BlockNode) cont;
return block.isDominator(dom); return block.isDominator(dom);
...@@ -145,16 +154,17 @@ public class RegionUtils { ...@@ -145,16 +154,17 @@ public class RegionUtils {
} }
public static boolean hasPathThruBlock(BlockNode block, IContainer cont) { public static boolean hasPathThruBlock(BlockNode block, IContainer cont) {
if (block == cont) if (block == cont) {
return true; return true;
}
if (cont instanceof BlockNode) { if (cont instanceof BlockNode) {
return BlockUtils.isPathExists(block, (BlockNode) cont); return BlockUtils.isPathExists(block, (BlockNode) cont);
} else if (cont instanceof IRegion) { } else if (cont instanceof IRegion) {
IRegion region = (IRegion) cont; IRegion region = (IRegion) cont;
for (IContainer c : region.getSubBlocks()) { for (IContainer c : region.getSubBlocks()) {
if (!hasPathThruBlock(block, c)) if (!hasPathThruBlock(block, c)) {
return false; return false;
}
} }
return true; return true;
} else { } else {
......
...@@ -14,9 +14,9 @@ public class StringUtils { ...@@ -14,9 +14,9 @@ public class StringUtils {
} }
public static String unescapeChar(char ch) { public static String unescapeChar(char ch) {
if (ch == '\'') if (ch == '\'') {
return "'\\\''"; return "'\\\''";
}
StringBuilder res = new StringBuilder(); StringBuilder res = new StringBuilder();
processChar(ch, res); processChar(ch, res);
return '\'' + res.toString() + '\''; return '\'' + res.toString() + '\'';
......
...@@ -16,10 +16,11 @@ public class Utils { ...@@ -16,10 +16,11 @@ public class Utils {
public static String cleanObjectName(String obj) { public static String cleanObjectName(String obj) {
int last = obj.length() - 1; int last = obj.length() - 1;
if (obj.charAt(0) == 'L' && obj.charAt(last) == ';') if (obj.charAt(0) == 'L' && obj.charAt(last) == ';') {
return obj.substring(1, last).replace('/', '.'); return obj.substring(1, last).replace('/', '.');
else } else {
return obj; return obj;
}
} }
public static String makeQualifiedObjectName(String obj) { public static String makeQualifiedObjectName(String obj) {
...@@ -61,27 +62,29 @@ public class Utils { ...@@ -61,27 +62,29 @@ public class Utils {
} }
public static String listToString(Iterable<?> list) { public static String listToString(Iterable<?> list) {
if (list == null) if (list == null) {
return ""; return "";
}
StringBuilder str = new StringBuilder(); StringBuilder str = new StringBuilder();
for (Iterator<?> it = list.iterator(); it.hasNext(); ) { for (Iterator<?> it = list.iterator(); it.hasNext(); ) {
Object o = it.next(); Object o = it.next();
str.append(o); str.append(o);
if (it.hasNext()) if (it.hasNext()) {
str.append(", "); str.append(", ");
}
} }
return str.toString(); return str.toString();
} }
public static String arrayToString(Object[] array) { public static String arrayToString(Object[] array) {
if (array == null) if (array == null) {
return ""; return "";
}
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
for (int i = 0; i < array.length; i++) { for (int i = 0; i < array.length; i++) {
if (i != 0) if (i != 0) {
sb.append(", "); sb.append(", ");
}
sb.append(array[i]); sb.append(array[i]);
} }
return sb.toString(); return sb.toString();
...@@ -108,11 +111,11 @@ public class Utils { ...@@ -108,11 +111,11 @@ public class Utils {
int pair = 1; int pair = 1;
for (int pos = 1; pos < sign.length(); pos++) { for (int pos = 1; pos < sign.length(); pos++) {
char c = sign.charAt(pos); char c = sign.charAt(pos);
if (c == '<') if (c == '<') {
pair++; pair++;
else if (c == '>') } else if (c == '>') {
pair--; pair--;
}
if (pair == 0) { if (pair == 0) {
end = pos; end = pos;
break; break;
...@@ -127,8 +130,9 @@ public class Utils { ...@@ -127,8 +130,9 @@ public class Utils {
if (!dir.exists()) { if (!dir.exists()) {
// if directory already created in other thread mkdirs will return false, // if directory already created in other thread mkdirs will return false,
// so check dir existence again // so check dir existence again
if (!dir.mkdirs() && !dir.exists()) if (!dir.mkdirs() && !dir.exists()) {
throw new JadxRuntimeException("Can't create directory " + dir); throw new JadxRuntimeException("Can't create directory " + dir);
}
} }
} }
} }
...@@ -26,7 +26,6 @@ public class InputFile { ...@@ -26,7 +26,6 @@ public class InputFile {
if (!file.exists()) { if (!file.exists()) {
throw new IOException("File not found: " + file.getAbsolutePath()); throw new IOException("File not found: " + file.getAbsolutePath());
} }
String fileName = file.getName(); String fileName = file.getName();
if (fileName.endsWith(".dex")) { if (fileName.endsWith(".dex")) {
...@@ -49,8 +48,9 @@ public class InputFile { ...@@ -49,8 +48,9 @@ public class InputFile {
throw new DecodeException( throw new DecodeException(
"java class to dex conversion error:\n " + e.getMessage(), e); "java class to dex conversion error:\n " + e.getMessage(), e);
} }
} else } else {
throw new DecodeException("Unsupported input file: " + file); throw new DecodeException("Unsupported input file: " + file);
}
} }
private byte[] openDexFromApk(File file) throws IOException { private byte[] openDexFromApk(File file) throws IOException {
......
...@@ -29,8 +29,8 @@ public class TestStringBuilderElimination extends InternalJadxTest { ...@@ -29,8 +29,8 @@ public class TestStringBuilderElimination extends InternalJadxTest {
String code = cls.getCode().toString(); String code = cls.getCode().toString();
System.out.println(code); System.out.println(code);
assertThat(code, containsString("MyException(String str, Exception e) {")); assertThat(code, containsString("MyException(String str, Exception e) {"));
assertThat(code, containsString("super(\"msg:\" + str, e);")); assertThat(code, containsString("super(\"msg:\" + str, e);"));
assertThat(code, not(containsString("new StringBuilder"))); assertThat(code, not(containsString("new StringBuilder")));
assertThat(code, containsString("System.out.println(\"k=\" + k);")); assertThat(code, containsString("System.out.println(\"k=\" + k);"));
......
...@@ -6,9 +6,7 @@ import jadx.core.dex.nodes.ClassNode; ...@@ -6,9 +6,7 @@ import jadx.core.dex.nodes.ClassNode;
import org.junit.Test; import org.junit.Test;
import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.not;
import static org.junit.Assert.assertThat; import static org.junit.Assert.assertThat;
import static org.mockito.AdditionalMatchers.or;
public class TestSwitchLabels extends InternalJadxTest { public class TestSwitchLabels extends InternalJadxTest {
public static class TestCls { public static class TestCls {
...@@ -17,6 +15,7 @@ public class TestSwitchLabels extends InternalJadxTest { ...@@ -17,6 +15,7 @@ public class TestSwitchLabels extends InternalJadxTest {
public static class Inner { public static class Inner {
private static final int CONST_CDE_PRIVATE = 0xCDE; private static final int CONST_CDE_PRIVATE = 0xCDE;
public int f1(int arg0) { public int f1(int arg0) {
switch (arg0) { switch (arg0) {
case CONST_CDE_PRIVATE: case CONST_CDE_PRIVATE:
......
...@@ -19,7 +19,7 @@ public class TestInline3 extends InternalJadxTest { ...@@ -19,7 +19,7 @@ public class TestInline3 extends InternalJadxTest {
public TestCls(int a1, int a2, int a3, int a4, int a5) { public TestCls(int a1, int a2, int a3, int a4, int a5) {
} }
public class A extends TestCls{ public class A extends TestCls {
public A(int a) { public A(int a) {
super(a, a); super(a, a);
} }
......
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