feat: mapping-io import support (#1531)(PR #1532)

* Add new CLI args for mapping files and deprecate args regarding jobf files (will be moved to the cache dir in the future)

* Add support for importing method arg mappings

Also change `mapping-file` to `mappings-path`, since folders are supported, too

* Add GUI for importing mappings

* Also show save file dialog when exporting mappings

* Fix crash on startup when `--mappings-path` parameter is set

* Include imported renames when exporting mappings

* Add "close mappings" menu entry

* Don't instantiate MappingTree unless actually needed

* Terminology: `import` → `open`; `export` → `save`

* Save location of open mapping file into project data

* Correctly reset cache when loading new mappings

* Remove unused import

* Save opened mappings' last modified date to reset cache when changed

* Fix if statement

* Correctly handle absence of mappings path in project data

* Show overwrite warning for folders only if not empty

* Prevent crash when imported mappings don't have any namespaces

* Handle wrong mappings namespace count error

* Replace unneeded public with private

* Add option for saving open mappings directly to disk

* Correctly propagate and throw exceptions during decompiler init

* Respect opened mappings' existing namespaces; fix related crash

* Deduplicate code, add `DalvikToJavaBytecodeUtils` class

* Small cleanup; move more functionality to utility class

* Support for importing class, field and method mappings

* Handle mappings in RenameDialog

* Fix checkstyle

* Fix wrong naming order

* Use modified mapping-io JAR from https://github.com/skylot/jadx/commit/18070eb7a649db0b0daef38d456316d5b4650072

That commit got rid of redundant embedded libraries

* Add null checks

* Check if mapping tree is null before running MappingsVisitor

* Use working mapping-io build

* Handle cache invalidation directly in DiskCodeCache class

* Don't reset UserRenamesMappingsMode if project is just reloaded

* Fix checkstyle

Co-authored-by: Skylot <skylot@gmail.com>
This commit is contained in:
Julian Burner
2022-08-10 16:37:55 +02:00
committed by Skylot
parent cb1f3e9843
commit cb91c8c41c
37 changed files with 1156 additions and 198 deletions
@@ -1,5 +1,6 @@
package jadx.cli;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.HashMap;
@@ -22,8 +23,9 @@ import jadx.api.JadxArgs;
import jadx.api.JadxArgs.RenameEnum;
import jadx.api.JadxArgs.UseKotlinMethodsForVarNames;
import jadx.api.JadxDecompiler;
import jadx.api.args.DeobfuscationMapFileMode;
import jadx.api.args.GeneratedRenamesMappingFileMode;
import jadx.api.args.ResourceNameSource;
import jadx.api.args.UserRenamesMappingsMode;
import jadx.core.utils.exceptions.JadxException;
import jadx.core.utils.files.FileUtils;
@@ -106,6 +108,22 @@ public class JadxCLIArgs {
@Parameter(names = { "--respect-bytecode-access-modifiers" }, description = "don't change original access modifiers")
protected boolean respectBytecodeAccessModifiers = false;
@Parameter(
names = { "--mappings-path" },
description = "deobfuscation mappings file or directory. Allowed formats: Tiny and Tiny v2 (both '.tiny'), Enigma (.mapping) or Enigma directory"
)
protected Path userRenamesMappingsPath;
@Parameter(
names = { "--mappings-mode" },
description = "set mode for handling the deobfuscation mapping file:"
+ "\n 'read' - just read, user can always save manually (default)"
+ "\n 'read-and-autosave-every-change' - read and autosave after every change"
+ "\n 'read-and-autosave-before-closing' - read and autosave before exiting the app or closing the project"
+ "\n 'ignore' - don't read or save (can be used to skip loading mapping files referenced in the project file)"
)
protected UserRenamesMappingsMode userRenamesMappingsMode = UserRenamesMappingsMode.getDefault();
@Parameter(names = { "--deobf" }, description = "activate deobfuscation")
protected boolean deobfuscationOn = false;
@@ -115,22 +133,24 @@ public class JadxCLIArgs {
@Parameter(names = { "--deobf-max" }, description = "max length of name, renamed if longer")
protected int deobfuscationMaxLength = 64;
@Deprecated
@Parameter(
names = { "--deobf-cfg-file" },
description = "deobfuscation map file, default: same dir and name as input file with '.jobf' extension"
description = "deobfuscation mappings file used for JADX auto-generated names (in the JOBF file format), default: same dir and name as input file with '.jobf' extension (deprecated)"
)
protected String deobfuscationMapFile;
protected String generatedRenamesMappingFile;
@Deprecated
@Parameter(
names = { "--deobf-cfg-file-mode" },
description = "set mode for handle deobfuscation map file:"
description = "set mode for handling the JADX auto-generated names' deobfuscation map file (deprecated):"
+ "\n 'read' - read if found, don't save (default)"
+ "\n 'read-or-save' - read if found, save otherwise (don't overwrite)"
+ "\n 'overwrite' - don't read, always save"
+ "\n 'ignore' - don't read and don't save",
converter = DeobfuscationMapFileModeConverter.class
)
protected DeobfuscationMapFileMode deobfuscationMapFileMode = DeobfuscationMapFileMode.READ;
protected GeneratedRenamesMappingFileMode generatedRenamesMappingFileMode = GeneratedRenamesMappingFileMode.getDefault();
@Parameter(names = { "--deobf-use-sourcename" }, description = "use source file name as class name alias")
protected boolean deobfuscationUseSourceNameAsAlias = false;
@@ -273,9 +293,13 @@ public class JadxCLIArgs {
args.setCfgOutput(cfgOutput);
args.setRawCFGOutput(rawCfgOutput);
args.setReplaceConsts(replaceConsts);
if (userRenamesMappingsPath != null) {
args.setUserRenamesMappingsPath(userRenamesMappingsPath);
}
args.setUserRenamesMappingsMode(userRenamesMappingsMode);
args.setDeobfuscationOn(deobfuscationOn);
args.setDeobfuscationMapFile(FileUtils.toFile(deobfuscationMapFile));
args.setDeobfuscationMapFileMode(deobfuscationMapFileMode);
args.setGeneratedRenamesMappingFile(FileUtils.toFile(generatedRenamesMappingFile));
args.setGeneratedRenamesMappingFileMode(generatedRenamesMappingFileMode);
args.setDeobfuscationMinLength(deobfuscationMinLength);
args.setDeobfuscationMaxLength(deobfuscationMaxLength);
args.setUseSourceNameAsClassAlias(deobfuscationUseSourceNameAsAlias);
@@ -380,6 +404,14 @@ public class JadxCLIArgs {
return extractFinally;
}
public Path getUserRenamesMappingsPath() {
return userRenamesMappingsPath;
}
public UserRenamesMappingsMode getUserRenamesMappingsMode() {
return userRenamesMappingsMode;
}
public boolean isDeobfuscationOn() {
return deobfuscationOn;
}
@@ -392,12 +424,14 @@ public class JadxCLIArgs {
return deobfuscationMaxLength;
}
public String getDeobfuscationMapFile() {
return deobfuscationMapFile;
@Deprecated
public String getGeneratedRenamesMappingFile() {
return generatedRenamesMappingFile;
}
public DeobfuscationMapFileMode getDeobfuscationMapFileMode() {
return deobfuscationMapFileMode;
@Deprecated
public GeneratedRenamesMappingFileMode getGeneratedRenamesMappingFileMode() {
return generatedRenamesMappingFileMode;
}
public boolean isDeobfuscationUseSourceNameAsAlias() {
@@ -509,9 +543,9 @@ public class JadxCLIArgs {
}
}
public static class DeobfuscationMapFileModeConverter extends BaseEnumConverter<DeobfuscationMapFileMode> {
public static class DeobfuscationMapFileModeConverter extends BaseEnumConverter<GeneratedRenamesMappingFileMode> {
public DeobfuscationMapFileModeConverter() {
super(DeobfuscationMapFileMode::valueOf, DeobfuscationMapFileMode::values);
super(GeneratedRenamesMappingFileMode::valueOf, GeneratedRenamesMappingFileMode::values);
}
}