feat: new module/library for work with call graphs (#2890)
This commit is contained in:
@@ -11,6 +11,7 @@ dependencies {
|
||||
implementation(project(":jadx-core"))
|
||||
implementation(project(":jadx-plugins-tools"))
|
||||
implementation(project(":jadx-commons:jadx-app-commons"))
|
||||
implementation(project(":jadx-commons:jadx-analysis"))
|
||||
|
||||
runtimeOnly(project(":jadx-plugins:jadx-dex-input"))
|
||||
runtimeOnly(project(":jadx-plugins:jadx-java-input"))
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
package jadx.cli;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import jadx.analysis.callgraph.JadxCallGraph;
|
||||
import jadx.analysis.callgraph.api.ICallGraph;
|
||||
import jadx.api.JadxArgs;
|
||||
import jadx.api.JadxDecompiler;
|
||||
import jadx.api.impl.AnnotatedCodeWriter;
|
||||
@@ -16,6 +19,7 @@ import jadx.cli.LogHelper.LogLevelEnum;
|
||||
import jadx.cli.config.JadxConfigAdapter;
|
||||
import jadx.cli.plugins.JadxFilesGetter;
|
||||
import jadx.core.utils.exceptions.JadxArgsValidateException;
|
||||
import jadx.core.utils.exceptions.JadxRuntimeException;
|
||||
import jadx.plugins.tools.JadxExternalPluginsLoader;
|
||||
|
||||
public class JadxCLI {
|
||||
@@ -73,6 +77,7 @@ public class JadxCLI {
|
||||
if (checkForErrors(jadx)) {
|
||||
return 2;
|
||||
}
|
||||
writeCallGraph(jadx, cliArgs);
|
||||
if (!SingleClassMode.process(jadx, cliArgs)) {
|
||||
save(jadx);
|
||||
}
|
||||
@@ -131,4 +136,29 @@ public class JadxCLI {
|
||||
System.out.print(" \r");
|
||||
}
|
||||
}
|
||||
|
||||
private static void writeCallGraph(JadxDecompiler jadx, JadxCLIArgs cliArgs) {
|
||||
JadxCLIArgs.CallGraphSaveMode mode = cliArgs.callGraphSaveMode;
|
||||
if (mode == null || mode == JadxCLIArgs.CallGraphSaveMode.NONE) {
|
||||
return;
|
||||
}
|
||||
Path outPath = jadx.getArgs().getOutDir().toPath();
|
||||
ICallGraph callGraph = JadxCallGraph.builder(jadx)
|
||||
.resolvedOnly(true)
|
||||
.build();
|
||||
Path cgPath;
|
||||
switch (mode) {
|
||||
case JSON:
|
||||
cgPath = outPath.resolve("callgraph.json");
|
||||
callGraph.writeJson(cgPath);
|
||||
break;
|
||||
case DOT:
|
||||
cgPath = outPath.resolve("callgraph.dot");
|
||||
callGraph.writeDot(cgPath);
|
||||
break;
|
||||
default:
|
||||
throw new JadxRuntimeException("Unexpected call graph save mode: " + mode);
|
||||
}
|
||||
LOG.info("Call graph saved: {}", cgPath.toAbsolutePath());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -283,6 +283,13 @@ public class JadxCLIArgs implements IJadxConfig {
|
||||
@Parameter(names = { "--raw-cfg" }, description = "save methods control flow graph (use raw instructions)")
|
||||
protected boolean rawCfgOutput = false;
|
||||
|
||||
@Parameter(
|
||||
names = { "--call-graph" },
|
||||
description = "save app call graph in format: 'dot' or 'json'",
|
||||
converter = CallGraphSaveModeConverter.class
|
||||
)
|
||||
protected CallGraphSaveMode callGraphSaveMode = CallGraphSaveMode.NONE;
|
||||
|
||||
@Parameter(names = { "-f", "--fallback" }, description = "set '--decompilation-mode' to 'fallback' (deprecated)")
|
||||
protected boolean fallbackMode = false;
|
||||
|
||||
@@ -827,6 +834,14 @@ public class JadxCLIArgs implements IJadxConfig {
|
||||
this.rawCfgOutput = rawCfgOutput;
|
||||
}
|
||||
|
||||
public CallGraphSaveMode getCallGraphSaveMode() {
|
||||
return callGraphSaveMode;
|
||||
}
|
||||
|
||||
public void setCallGraphSaveMode(CallGraphSaveMode callGraphSaveMode) {
|
||||
this.callGraphSaveMode = callGraphSaveMode;
|
||||
}
|
||||
|
||||
public boolean isReplaceConsts() {
|
||||
return replaceConsts;
|
||||
}
|
||||
@@ -1022,6 +1037,18 @@ public class JadxCLIArgs implements IJadxConfig {
|
||||
}
|
||||
}
|
||||
|
||||
public enum CallGraphSaveMode {
|
||||
NONE,
|
||||
DOT,
|
||||
JSON,
|
||||
}
|
||||
|
||||
public static class CallGraphSaveModeConverter extends BaseEnumConverter<CallGraphSaveMode> {
|
||||
public CallGraphSaveModeConverter() {
|
||||
super(CallGraphSaveMode::valueOf, CallGraphSaveMode::values);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract static class BaseEnumConverter<E extends Enum<E>> implements IStringConverter<E> {
|
||||
private final Function<String, E> parse;
|
||||
private final Supplier<E[]> values;
|
||||
|
||||
Reference in New Issue
Block a user