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