Skip to content

Commit

Permalink
refactor: use own dex parser instead deprecated dx lib
Browse files Browse the repository at this point in the history
  • Loading branch information
skylot committed May 21, 2020
1 parent 09e267f commit 0d69e0a
Show file tree
Hide file tree
Showing 181 changed files with 6,772 additions and 3,065 deletions.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ jadx-output/
*-tmp/
**/tmp/

*.dex
*.class
*.dump
*.log
Expand Down
3 changes: 3 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ allprojects {

dependencies {
compile 'org.slf4j:slf4j-api:1.7.30'
compileOnly 'org.jetbrains:annotations:19.0.0'

testCompile 'ch.qos.logback:logback-classic:1.2.3'
testCompile 'org.hamcrest:hamcrest-library:2.2'
Expand All @@ -44,6 +45,7 @@ allprojects {
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.6.2'

testCompile 'org.eclipse.jdt.core.compiler:ecj:4.6.1'
testCompileOnly 'org.jetbrains:annotations:19.0.0'
}

test {
Expand Down Expand Up @@ -86,6 +88,7 @@ spotless {
include 'jadx-cli/src/**/java/**/*.java'
include 'jadx-core/src/**/java/**/*.java'
include 'jadx-gui/src/**/java/**/*.java'
include 'jadx-plugins/**/java/**/*.java'
}

importOrderFile 'config/code-formatter/eclipse.importorder'
Expand Down
4 changes: 4 additions & 0 deletions jadx-cli/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ plugins {

dependencies {
compile(project(':jadx-core'))

runtime(project(':jadx-plugins:jadx-dex-input'))
runtime(project(':jadx-plugins:jadx-java-convert'))

compile 'com.beust:jcommander:1.78'
compile 'ch.qos.logback:logback-classic:1.2.3'
}
Expand Down
32 changes: 15 additions & 17 deletions jadx-cli/src/main/java/jadx/cli/JadxCLI.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,11 @@ public static void main(String[] args) {
try {
JadxCLIArgs jadxArgs = new JadxCLIArgs();
if (jadxArgs.processArgs(args)) {
result = processAndSave(jadxArgs);
result = processAndSave(jadxArgs.toJadxArgs());
}
} catch (JadxArgsValidateException e) {
LOG.error("Incorrect arguments: {}", e.getMessage());
result = 1;
} catch (Exception e) {
LOG.error("jadx error: {}", e.getMessage(), e);
result = 1;
Expand All @@ -28,23 +31,18 @@ public static void main(String[] args) {
}
}

static int processAndSave(JadxCLIArgs inputArgs) {
JadxArgs args = inputArgs.toJadxArgs();
args.setCodeCache(new NoOpCodeCache());
JadxDecompiler jadx = new JadxDecompiler(args);
try {
static int processAndSave(JadxArgs jadxArgs) {
jadxArgs.setCodeCache(new NoOpCodeCache());
try (JadxDecompiler jadx = new JadxDecompiler(jadxArgs)) {
jadx.load();
} catch (JadxArgsValidateException e) {
LOG.error("Incorrect arguments: {}", e.getMessage());
return 1;
}
jadx.save();
int errorsCount = jadx.getErrorsCount();
if (errorsCount != 0) {
jadx.printErrorsReport();
LOG.error("finished with errors, count: {}", errorsCount);
} else {
LOG.info("done");
jadx.save();
int errorsCount = jadx.getErrorsCount();
if (errorsCount != 0) {
jadx.printErrorsReport();
LOG.error("finished with errors, count: {}", errorsCount);
} else {
LOG.info("done");
}
}
return 0;
}
Expand Down
11 changes: 8 additions & 3 deletions jadx-core/build.gradle
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
plugins {
id 'java-library'
}

dependencies {
runtime files('clsp-data/android-29-clst.jar')
runtime files('clsp-data/android-29-res.jar')

compile files('lib/dx-1.16.jar') // TODO: dx don't support java version > 9 (53)
api(project(':jadx-plugins:jadx-plugins-api'))

compile 'org.ow2.asm:asm:8.0.1'
compile 'org.jetbrains:annotations:19.0.0'
compile 'com.google.code.gson:gson:2.8.6'

compile 'org.smali:baksmali:2.4.0'
Expand All @@ -15,6 +17,9 @@ dependencies {
compile 'com.google.guava:guava:29.0-jre'

testCompile 'org.apache.commons:commons-lang3:3.9'

testRuntime(project(':jadx-plugins:jadx-dex-input'))
testRuntime(project(':jadx-plugins:jadx-java-convert'))
}

test {
Expand Down
76 changes: 49 additions & 27 deletions jadx-core/src/main/java/jadx/api/JadxDecompiler.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package jadx.api;

import java.io.Closeable;
import java.io.File;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
Expand All @@ -17,6 +19,10 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import jadx.api.plugins.JadxPlugin;
import jadx.api.plugins.JadxPluginManager;
import jadx.api.plugins.input.JadxInputPlugin;
import jadx.api.plugins.input.data.ILoadResult;
import jadx.core.Jadx;
import jadx.core.dex.attributes.AFlag;
import jadx.core.dex.attributes.nodes.LineAttrNode;
Expand All @@ -26,8 +32,8 @@
import jadx.core.dex.nodes.RootNode;
import jadx.core.dex.visitors.SaveCode;
import jadx.core.export.ExportGradleProject;
import jadx.core.utils.Utils;
import jadx.core.utils.exceptions.JadxRuntimeException;
import jadx.core.utils.files.InputFile;
import jadx.core.xmlgen.BinaryXMLParser;
import jadx.core.xmlgen.ResourcesSaver;

Expand All @@ -39,10 +45,10 @@
* JadxArgs args = new JadxArgs();
* args.getInputFiles().add(new File("test.apk"));
* args.setOutDir(new File("jadx-test-output"));
*
* JadxDecompiler jadx = new JadxDecompiler(args);
* jadx.load();
* jadx.save();
* try (JadxDecompiler jadx = new JadxDecompiler(args)) {
* jadx.load();
* jadx.save();
* }
* </code>
* </pre>
* <p>
Expand All @@ -56,21 +62,22 @@
* </code>
* </pre>
*/
public final class JadxDecompiler {
public final class JadxDecompiler implements Closeable {
private static final Logger LOG = LoggerFactory.getLogger(JadxDecompiler.class);

private JadxArgs args;
private List<InputFile> inputFiles;
private JadxPluginManager pluginManager = new JadxPluginManager();
private List<ILoadResult> loadedInputs = new ArrayList<>();

private RootNode root;
private List<JavaClass> classes;
private List<ResourceFile> resources;

private BinaryXMLParser xmlParser;

private Map<ClassNode, JavaClass> classesMap = new ConcurrentHashMap<>();
private Map<MethodNode, JavaMethod> methodsMap = new ConcurrentHashMap<>();
private Map<FieldNode, JavaField> fieldsMap = new ConcurrentHashMap<>();
private final Map<ClassNode, JavaClass> classesMap = new ConcurrentHashMap<>();
private final Map<MethodNode, JavaMethod> methodsMap = new ConcurrentHashMap<>();
private final Map<FieldNode, JavaField> fieldsMap = new ConcurrentHashMap<>();

public JadxDecompiler() {
this(new JadxArgs());
Expand All @@ -84,16 +91,23 @@ public void load() {
reset();
JadxArgsValidator.validate(args);
LOG.info("loading ...");

inputFiles = loadFiles(args.getInputFiles());
loadInputFiles();

root = new RootNode(args);
root.load(inputFiles);
root.loadClasses(loadedInputs);
root.initClassPath();
root.loadResources(getResources());
root.initPasses();
}

private void loadInputFiles() {
loadedInputs.clear();
List<Path> inputPaths = Utils.collectionMap(args.getInputFiles(), File::toPath);
for (JadxInputPlugin inputPlugin : pluginManager.getInputPlugins()) {
loadedInputs.add(inputPlugin.loadFiles(inputPaths));
}
}

private void reset() {
root = null;
classes = null;
Expand All @@ -103,25 +117,32 @@ private void reset() {
classesMap.clear();
methodsMap.clear();
fieldsMap.clear();
}

public static String getVersion() {
return Jadx.getVersion();
closeInputs();
}

private List<InputFile> loadFiles(List<File> files) {
if (files.isEmpty()) {
throw new JadxRuntimeException("Empty file list");
}
List<InputFile> filesList = new ArrayList<>();
for (File file : files) {
private void closeInputs() {
loadedInputs.forEach(load -> {
try {
InputFile.addFilesFrom(file, filesList, args.isSkipSources());
load.close();
} catch (Exception e) {
throw new JadxRuntimeException("Error load file: " + file, e);
LOG.error("Failed to close input", e);
}
}
return filesList;
});
loadedInputs.clear();
}

@Override
public void close() {
reset();
}

public void registerPlugin(JadxPlugin plugin) {
pluginManager.register(plugin);
}

public static String getVersion() {
return Jadx.getVersion();
}

public void save() {
Expand Down Expand Up @@ -232,7 +253,7 @@ public List<ResourceFile> getResources() {
if (root == null) {
return Collections.emptyList();
}
resources = new ResourcesLoader(this).load(inputFiles);
resources = new ResourcesLoader(this).load();
}
return resources;
}
Expand Down Expand Up @@ -432,4 +453,5 @@ public JadxArgs getArgs() {
public String toString() {
return "jadx decompiler " + getVersion();
}

}
2 changes: 1 addition & 1 deletion jadx-core/src/main/java/jadx/api/JavaField.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public AccessInfo getAccessFlags() {
}

public ArgType getType() {
return ArgType.tryToResolveClassAlias(field.dex(), field.getType());
return ArgType.tryToResolveClassAlias(field.root(), field.getType());
}

@Override
Expand Down
4 changes: 2 additions & 2 deletions jadx-core/src/main/java/jadx/api/JavaMethod.java
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,12 @@ public List<ArgType> getArguments() {
}
List<ArgType> arguments = mth.getArgTypes();
return Utils.collectionMap(arguments,
type -> ArgType.tryToResolveClassAlias(mth.dex(), type));
type -> ArgType.tryToResolveClassAlias(mth.root(), type));
}

public ArgType getReturnType() {
ArgType retType = mth.getReturnType();
return ArgType.tryToResolveClassAlias(mth.dex(), retType);
return ArgType.tryToResolveClassAlias(mth.root(), retType);
}

public boolean isConstructor() {
Expand Down
8 changes: 4 additions & 4 deletions jadx-core/src/main/java/jadx/api/ResourcesLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
import jadx.core.utils.Utils;
import jadx.core.utils.android.Res9patchStreamDecoder;
import jadx.core.utils.exceptions.JadxException;
import jadx.core.utils.files.InputFile;
import jadx.core.utils.files.ZipSecurity;
import jadx.core.xmlgen.ResContainer;
import jadx.core.xmlgen.ResTableParser;
Expand All @@ -39,10 +38,11 @@ public final class ResourcesLoader {
this.jadxRef = jadxRef;
}

List<ResourceFile> load(List<InputFile> inputFiles) {
List<ResourceFile> load() {
List<File> inputFiles = jadxRef.getArgs().getInputFiles();
List<ResourceFile> list = new ArrayList<>(inputFiles.size());
for (InputFile file : inputFiles) {
loadFile(list, file.getFile());
for (File file : inputFiles) {
loadFile(list, file);
}
return list;
}
Expand Down
10 changes: 5 additions & 5 deletions jadx-core/src/main/java/jadx/core/Consts.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ public class Consts {

public static final String CLASS_STRING_BUILDER = "java.lang.StringBuilder";

public static final String DALVIK_ANNOTATION_PKG = "dalvik.annotation.";
public static final String DALVIK_SIGNATURE = "dalvik.annotation.Signature";
public static final String DALVIK_INNER_CLASS = "dalvik.annotation.InnerClass";
public static final String DALVIK_THROWS = "dalvik.annotation.Throws";
public static final String DALVIK_ANNOTATION_DEFAULT = "dalvik.annotation.AnnotationDefault";
public static final String DALVIK_ANNOTATION_PKG = "Ldalvik/annotation/";
public static final String DALVIK_SIGNATURE = "Ldalvik/annotation/Signature;";
public static final String DALVIK_INNER_CLASS = "Ldalvik/annotation/InnerClass;";
public static final String DALVIK_THROWS = "Ldalvik/annotation/Throws;";
public static final String DALVIK_ANNOTATION_DEFAULT = "Ldalvik/annotation/AnnotationDefault;";

public static final String DEFAULT_PACKAGE_NAME = "defpackage";
public static final String ANONYMOUS_CLASS_PREFIX = "AnonymousClass";
Expand Down
Loading

0 comments on commit 0d69e0a

Please sign in to comment.