Skip to content

Commit

Permalink
feat: new implementation for type inference approach and variable dec…
Browse files Browse the repository at this point in the history
…laration

BREAKING CHANGE: some parts of jadx was rewritten from scratch
  - type inference
  - variable declaration
  - `finish` block extraction
  • Loading branch information
skylot committed Mar 26, 2019
2 parents eb2a173 + 3492ec3 commit e026345
Show file tree
Hide file tree
Showing 290 changed files with 8,645 additions and 4,608 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,4 @@ jadx-output/
*.dump
*.log
*.cfg
*.orig
2 changes: 1 addition & 1 deletion jadx-cli/src/main/java/jadx/cli/JadxCLIArgs.java
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ public boolean overrideProvided(String[] args) {
return process(jcw);
}

private boolean process(JCommanderWrapper<?> jcw) {
private boolean process(JCommanderWrapper<JadxCLIArgs> jcw) {
if (printHelp) {
jcw.printUsage();
return false;
Expand Down
4 changes: 4 additions & 0 deletions jadx-core/src/main/java/jadx/api/JadxDecompiler.java
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,10 @@ RootNode getRoot() {
return root;
}

List<IDexTreeVisitor> getPasses() {
return passes;
}

synchronized BinaryXMLParser getXmlParser() {
if (xmlParser == null) {
xmlParser = new BinaryXMLParser(root);
Expand Down
53 changes: 28 additions & 25 deletions jadx-core/src/main/java/jadx/core/Jadx.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,37 +11,39 @@

import jadx.api.JadxArgs;
import jadx.core.dex.visitors.ClassModifier;
import jadx.core.dex.visitors.CodeShrinker;
import jadx.core.dex.visitors.ConstInlineVisitor;
import jadx.core.dex.visitors.DebugInfoVisitor;
import jadx.core.dex.visitors.ConstructorVisitor;
import jadx.core.dex.visitors.DependencyCollector;
import jadx.core.dex.visitors.DotGraphVisitor;
import jadx.core.dex.visitors.EnumVisitor;
import jadx.core.dex.visitors.ExtractFieldInit;
import jadx.core.dex.visitors.FallbackModeVisitor;
import jadx.core.dex.visitors.FixAccessModifiers;
import jadx.core.dex.visitors.IDexTreeVisitor;
import jadx.core.dex.visitors.InitCodeVariables;
import jadx.core.dex.visitors.MarkFinallyVisitor;
import jadx.core.dex.visitors.MethodInlineVisitor;
import jadx.core.dex.visitors.ModVisitor;
import jadx.core.dex.visitors.PrepareForCodeGen;
import jadx.core.dex.visitors.ReSugarCode;
import jadx.core.dex.visitors.RenameVisitor;
import jadx.core.dex.visitors.SimplifyVisitor;
import jadx.core.dex.visitors.blocksmaker.BlockExceptionHandler;
import jadx.core.dex.visitors.blocksmaker.BlockFinallyExtract;
import jadx.core.dex.visitors.blocksmaker.BlockFinish;
import jadx.core.dex.visitors.blocksmaker.BlockProcessor;
import jadx.core.dex.visitors.blocksmaker.BlockSplitter;
import jadx.core.dex.visitors.debuginfo.DebugInfoApplyVisitor;
import jadx.core.dex.visitors.debuginfo.DebugInfoParseVisitor;
import jadx.core.dex.visitors.regions.CheckRegions;
import jadx.core.dex.visitors.regions.CleanRegions;
import jadx.core.dex.visitors.regions.IfRegionVisitor;
import jadx.core.dex.visitors.regions.LoopRegionVisitor;
import jadx.core.dex.visitors.regions.ProcessVariables;
import jadx.core.dex.visitors.regions.RegionMakerVisitor;
import jadx.core.dex.visitors.regions.ReturnVisitor;
import jadx.core.dex.visitors.ssa.EliminatePhiNodes;
import jadx.core.dex.visitors.regions.variables.ProcessVariables;
import jadx.core.dex.visitors.shrink.CodeShrinkVisitor;
import jadx.core.dex.visitors.ssa.SSATransform;
import jadx.core.dex.visitors.typeinference.FinishTypeInference;
import jadx.core.dex.visitors.typeinference.TypeInference;
import jadx.core.dex.visitors.typeinference.TypeInferenceVisitor;

public class Jadx {
private static final Logger LOG = LoggerFactory.getLogger(Jadx.class);
Expand All @@ -60,40 +62,42 @@ public static List<IDexTreeVisitor> getPassesList(JadxArgs args) {
if (args.isFallbackMode()) {
passes.add(new FallbackModeVisitor());
} else {
passes.add(new BlockSplitter());
passes.add(new BlockProcessor());
passes.add(new BlockExceptionHandler());
passes.add(new BlockFinallyExtract());
passes.add(new BlockFinish());

passes.add(new SSATransform());
if (args.isDebugInfo()) {
passes.add(new DebugInfoVisitor());
passes.add(new DebugInfoParseVisitor());
}
passes.add(new TypeInference());

passes.add(new BlockSplitter());
if (args.isRawCFGOutput()) {
passes.add(DotGraphVisitor.dumpRaw());
}

passes.add(new BlockProcessor());
passes.add(new BlockExceptionHandler());
passes.add(new BlockFinish());

passes.add(new SSATransform());
passes.add(new ConstructorVisitor());
passes.add(new InitCodeVariables());
passes.add(new MarkFinallyVisitor());
passes.add(new ConstInlineVisitor());
passes.add(new FinishTypeInference());
passes.add(new EliminatePhiNodes());
passes.add(new TypeInferenceVisitor());
if (args.isDebugInfo()) {
passes.add(new DebugInfoApplyVisitor());
}

passes.add(new ModVisitor());

passes.add(new CodeShrinker());
passes.add(new CodeShrinkVisitor());
passes.add(new ReSugarCode());

if (args.isCfgOutput()) {
passes.add(DotGraphVisitor.dump());
}

passes.add(new RegionMakerVisitor());
passes.add(new IfRegionVisitor());
passes.add(new ReturnVisitor());
passes.add(new CleanRegions());

passes.add(new CodeShrinker());
passes.add(new CodeShrinkVisitor());
passes.add(new SimplifyVisitor());
passes.add(new CheckRegions());

Expand All @@ -102,16 +106,15 @@ public static List<IDexTreeVisitor> getPassesList(JadxArgs args) {
passes.add(new ClassModifier());
passes.add(new MethodInlineVisitor());
passes.add(new EnumVisitor());
passes.add(new PrepareForCodeGen());
passes.add(new LoopRegionVisitor());
passes.add(new ProcessVariables());

passes.add(new ProcessVariables());
passes.add(new PrepareForCodeGen());
if (args.isCfgOutput()) {
passes.add(DotGraphVisitor.dumpRegions());
}

passes.add(new DependencyCollector());

passes.add(new RenameVisitor());
}
return passes;
Expand Down
8 changes: 7 additions & 1 deletion jadx-core/src/main/java/jadx/core/clsp/ClsSet.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ public class ClsSet {

private static final String STRING_CHARSET = "US-ASCII";

private static final NClass[] EMPTY_NCLASS_ARRAY = new NClass[0];

private NClass[] classes;

public void load(RootNode root) {
Expand Down Expand Up @@ -93,7 +95,11 @@ public static NClass[] makeParentsArray(ClassNode cls, Map<String, NClass> names
parents.add(c);
}
}
return parents.toArray(new NClass[parents.size()]);
int size = parents.size();
if (size == 0) {
return EMPTY_NCLASS_ARRAY;
}
return parents.toArray(new NClass[size]);
}

private static NClass getCls(String fullName, Map<String, NClass> names) {
Expand Down
21 changes: 19 additions & 2 deletions jadx-core/src/main/java/jadx/core/clsp/ClspGraph.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
public class ClspGraph {
private static final Logger LOG = LoggerFactory.getLogger(ClspGraph.class);

private final Map<String, Set<String>> ancestorCache = Collections.synchronizedMap(new WeakHashMap<String, Set<String>>());
private final Map<String, Set<String>> ancestorCache = Collections.synchronizedMap(new WeakHashMap<>());
private Map<String, NClass> nameMap;

private final Set<String> missingClasses = new HashSet<>();
Expand Down Expand Up @@ -58,18 +58,35 @@ public void addApp(List<ClassNode> classes) {
}
}

public boolean isClsKnown(String fullName) {
return nameMap.containsKey(fullName);
}

private NClass addClass(ClassNode cls) {
String rawName = cls.getRawName();
NClass nClass = new NClass(rawName, -1);
nameMap.put(rawName, nClass);
return nClass;
}

/**
* @return {@code clsName} instanceof {@code implClsName}
*/
public boolean isImplements(String clsName, String implClsName) {
Set<String> anc = getAncestors(clsName);
return anc.contains(implClsName);
}

public List<String> getImplementations(String clsName) {
List<String> list = new ArrayList<>();
for (String cls : nameMap.keySet()) {
if (isImplements(cls, clsName)) {
list.add(cls);
}
}
return list;
}

public String getCommonAncestor(String clsName, String implClsName) {
if (clsName.equals(implClsName)) {
return clsName;
Expand Down Expand Up @@ -100,7 +117,7 @@ private String searchCommonParent(Set<String> anc, NClass cls) {
return null;
}

private Set<String> getAncestors(String clsName) {
public Set<String> getAncestors(String clsName) {
Set<String> result = ancestorCache.get(clsName);
if (result != null) {
return result;
Expand Down
11 changes: 6 additions & 5 deletions jadx-core/src/main/java/jadx/core/codegen/ClassGen.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
import jadx.core.dex.attributes.nodes.EnumClassAttr;
import jadx.core.dex.attributes.nodes.EnumClassAttr.EnumField;
import jadx.core.dex.attributes.nodes.JadxError;
import jadx.core.dex.attributes.nodes.JadxWarn;
import jadx.core.dex.attributes.nodes.LineAttrNode;
import jadx.core.dex.attributes.nodes.SourceFileAttr;
import jadx.core.dex.info.AccessInfo;
Expand Down Expand Up @@ -263,10 +262,11 @@ private void addMethods(CodeWriter code) {
addMethod(code, mth);
} catch (Exception e) {
code.newLine().add("/*");
code.newLine().add(ErrorsCounter.methodError(mth, "Method generation error", e));
code.newLine().add(Utils.getStackTrace(e));
code.newLine().addMultiLine(ErrorsCounter.methodError(mth, "Method generation error", e));
code.newLine().addMultiLine(Utils.getStackTrace(e));
code.newLine().add("*/");
code.setIndent(savedIndent);
mth.addError("Method generation error: " + e.getMessage(), e);
}
}
}
Expand Down Expand Up @@ -331,7 +331,6 @@ private void addMethod(CodeWriter code, MethodNode mth) throws CodegenException

private void insertDecompilationProblems(CodeWriter code, AttrNode node) {
List<JadxError> errors = node.getAll(AType.JADX_ERROR);
List<JadxWarn> warns = node.getAll(AType.JADX_WARN);
if (!errors.isEmpty()) {
errors.forEach(err -> {
code.startLine("/* JADX ERROR: ").add(err.getError());
Expand All @@ -344,8 +343,10 @@ private void insertDecompilationProblems(CodeWriter code, AttrNode node) {
code.add("*/");
});
}
List<String> warns = node.getAll(AType.JADX_WARN);
if (!warns.isEmpty()) {
warns.forEach(warn -> code.startLine("/* JADX WARNING: ").addMultiLine(warn.getWarn()).add(" */"));
warns.stream().distinct()
.forEach(warn -> code.startLine("/* JADX WARNING: ").addMultiLine(warn).add(" */"));
}
}

Expand Down
Loading

0 comments on commit e026345

Please sign in to comment.