diff --git a/jadx-gui/src/main/java/jadx/gui/plugins/mappings/RenameMappingsGui.java b/jadx-gui/src/main/java/jadx/gui/plugins/mappings/RenameMappingsGui.java index 6224c0000..bc2fa0bfc 100644 --- a/jadx-gui/src/main/java/jadx/gui/plugins/mappings/RenameMappingsGui.java +++ b/jadx-gui/src/main/java/jadx/gui/plugins/mappings/RenameMappingsGui.java @@ -61,15 +61,16 @@ public class RenameMappingsGui { public void addMenuActions(JMenu menu) { openMappingsMenu = new JMenu(NLS.str("file.open_mappings")); - openMappingsMenu.add(new ActionHandler(ev -> openMappings(MappingFormat.PROGUARD, true)).withNameAndDesc("Proguard (inverted)")); - openMappingsMenu.add(new ActionHandler(ev -> openMappings(MappingFormat.PROGUARD, false)).withNameAndDesc("Proguard")); + openMappingsMenu.add(new ActionHandler(ev -> openMappings(MappingFormat.PROGUARD_FILE, true)) + .withNameAndDesc("Proguard (inverted)")); + openMappingsMenu.add(new ActionHandler(ev -> openMappings(MappingFormat.PROGUARD_FILE, false)).withNameAndDesc("Proguard")); saveMappingsAction = new ActionHandler(this::saveMappings).withNameAndDesc(NLS.str("file.save_mappings")); saveMappingsAsMenu = new JMenu(NLS.str("file.save_mappings_as")); for (MappingFormat mappingFormat : MappingFormat.values()) { - if (mappingFormat != MappingFormat.PROGUARD) { + if (mappingFormat != MappingFormat.PROGUARD_FILE) { openMappingsMenu.add(new ActionHandler(ev -> openMappings(mappingFormat, false)) .withNameAndDesc(mappingFormat.name)); } diff --git a/jadx-plugins/jadx-rename-mappings/build.gradle.kts b/jadx-plugins/jadx-rename-mappings/build.gradle.kts index 82245ba60..3425cab8c 100644 --- a/jadx-plugins/jadx-rename-mappings/build.gradle.kts +++ b/jadx-plugins/jadx-rename-mappings/build.gradle.kts @@ -6,12 +6,8 @@ plugins { dependencies { api(project(":jadx-core")) - // TODO: Switch back to upstream once this PR gets merged: - // https://github.com/FabricMC/mapping-io/pull/19 - // implementation 'net.fabricmc:mapping-io:0.3.0' - api(files("libs/mapping-io-0.4.0-SNAPSHOT.jar")) - - constraints { - runtimeOnly("org.ow2.asm:asm:9.5") + api("net.fabricmc:mapping-io:0.5.0-beta.1") { + exclude("org.ow2.asm:asm") + exclude("net.fabricmc:tiny-remapper") } } diff --git a/jadx-plugins/jadx-rename-mappings/libs/mapping-io-0.4.0-SNAPSHOT.jar b/jadx-plugins/jadx-rename-mappings/libs/mapping-io-0.4.0-SNAPSHOT.jar deleted file mode 100644 index 68be1ce1e..000000000 Binary files a/jadx-plugins/jadx-rename-mappings/libs/mapping-io-0.4.0-SNAPSHOT.jar and /dev/null differ diff --git a/jadx-plugins/jadx-rename-mappings/src/main/java/jadx/plugins/mappings/RenameMappingsData.java b/jadx-plugins/jadx-rename-mappings/src/main/java/jadx/plugins/mappings/RenameMappingsData.java index d7761d57a..c9db3dad4 100644 --- a/jadx-plugins/jadx-rename-mappings/src/main/java/jadx/plugins/mappings/RenameMappingsData.java +++ b/jadx-plugins/jadx-rename-mappings/src/main/java/jadx/plugins/mappings/RenameMappingsData.java @@ -2,7 +2,7 @@ package jadx.plugins.mappings; import org.jetbrains.annotations.Nullable; -import net.fabricmc.mappingio.tree.MappingTree; +import net.fabricmc.mappingio.tree.MappingTreeView; import jadx.api.plugins.input.data.attributes.IJadxAttrType; import jadx.api.plugins.input.data.attributes.IJadxAttribute; @@ -16,18 +16,18 @@ public class RenameMappingsData implements IJadxAttribute { return root.getAttributes().get(DATA); } - public static @Nullable MappingTree getTree(RootNode root) { + public static @Nullable MappingTreeView getTree(RootNode root) { RenameMappingsData data = getData(root); return data == null ? null : data.getMappings(); } - private final MappingTree mappings; + private final MappingTreeView mappings; - public RenameMappingsData(MappingTree mappings) { + public RenameMappingsData(MappingTreeView mappings) { this.mappings = mappings; } - public MappingTree getMappings() { + public MappingTreeView getMappings() { return mappings; } diff --git a/jadx-plugins/jadx-rename-mappings/src/main/java/jadx/plugins/mappings/load/ApplyMappingsPass.java b/jadx-plugins/jadx-rename-mappings/src/main/java/jadx/plugins/mappings/load/ApplyMappingsPass.java index e0bdf1f49..5b4e70fd4 100644 --- a/jadx-plugins/jadx-rename-mappings/src/main/java/jadx/plugins/mappings/load/ApplyMappingsPass.java +++ b/jadx-plugins/jadx-rename-mappings/src/main/java/jadx/plugins/mappings/load/ApplyMappingsPass.java @@ -1,9 +1,9 @@ package jadx.plugins.mappings.load; -import net.fabricmc.mappingio.tree.MappingTree; -import net.fabricmc.mappingio.tree.MappingTree.ClassMapping; -import net.fabricmc.mappingio.tree.MappingTree.FieldMapping; -import net.fabricmc.mappingio.tree.MappingTree.MethodMapping; +import net.fabricmc.mappingio.tree.MappingTreeView; +import net.fabricmc.mappingio.tree.MappingTreeView.ClassMappingView; +import net.fabricmc.mappingio.tree.MappingTreeView.FieldMappingView; +import net.fabricmc.mappingio.tree.MappingTreeView.MethodMappingView; import jadx.api.plugins.pass.JadxPassInfo; import jadx.api.plugins.pass.impl.OrderedJadxPassInfo; @@ -34,22 +34,22 @@ public class ApplyMappingsPass implements JadxPreparePass { if (data == null) { return; } - MappingTree mappingTree = data.getMappings(); + MappingTreeView mappingTree = data.getMappings(); process(root, mappingTree); root.registerCodeDataUpdateListener(codeData -> process(root, mappingTree)); } - private void process(RootNode root, MappingTree mappingTree) { + private void process(RootNode root, MappingTreeView mappingTree) { for (ClassNode cls : root.getClasses()) { String clsRawName = cls.getClassInfo().getRawName().replace('.', '/'); - ClassMapping mapping = mappingTree.getClass(clsRawName); + ClassMappingView mapping = mappingTree.getClass(clsRawName); if (mapping != null) { processClass(cls, mapping); } } } - private static void processClass(ClassNode cls, ClassMapping classMapping) { + private static void processClass(ClassNode cls, ClassMappingView classMapping) { String alias = classMapping.getDstName(0); if (alias != null) { cls.rename(alias.replace('/', '.')); @@ -60,7 +60,7 @@ public class ApplyMappingsPass implements JadxPreparePass { for (FieldNode field : cls.getFields()) { FieldInfo fieldInfo = field.getFieldInfo(); String signature = TypeGen.signature(fieldInfo.getType()); - FieldMapping fieldMapping = classMapping.getField(fieldInfo.getName(), signature); + FieldMappingView fieldMapping = classMapping.getField(fieldInfo.getName(), signature); if (fieldMapping != null) { processField(field, fieldMapping); } @@ -69,14 +69,14 @@ public class ApplyMappingsPass implements JadxPreparePass { MethodInfo methodInfo = method.getMethodInfo(); String methodName = methodInfo.getName(); String methodDesc = methodInfo.getShortId().substring(methodName.length()); - MethodMapping methodMapping = classMapping.getMethod(methodName, methodDesc); + MethodMappingView methodMapping = classMapping.getMethod(methodName, methodDesc); if (methodMapping != null) { processMethod(method, methodMapping); } } } - private static void processField(FieldNode field, FieldMapping fieldMapping) { + private static void processField(FieldNode field, FieldMappingView fieldMapping) { String alias = fieldMapping.getDstName(0); if (alias != null) { field.rename(alias); @@ -87,7 +87,7 @@ public class ApplyMappingsPass implements JadxPreparePass { } } - private static void processMethod(MethodNode method, MethodMapping methodMapping) { + private static void processMethod(MethodNode method, MethodMappingView methodMapping) { String alias = methodMapping.getDstName(0); if (alias != null) { method.rename(alias); diff --git a/jadx-plugins/jadx-rename-mappings/src/main/java/jadx/plugins/mappings/load/CodeMappingsPass.java b/jadx-plugins/jadx-rename-mappings/src/main/java/jadx/plugins/mappings/load/CodeMappingsPass.java index bd1c24a92..e6922dfb0 100644 --- a/jadx-plugins/jadx-rename-mappings/src/main/java/jadx/plugins/mappings/load/CodeMappingsPass.java +++ b/jadx-plugins/jadx-rename-mappings/src/main/java/jadx/plugins/mappings/load/CodeMappingsPass.java @@ -4,10 +4,10 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import net.fabricmc.mappingio.tree.MappingTree; -import net.fabricmc.mappingio.tree.MappingTree.ClassMapping; -import net.fabricmc.mappingio.tree.MappingTree.MethodArgMapping; -import net.fabricmc.mappingio.tree.MappingTree.MethodMapping; +import net.fabricmc.mappingio.tree.MappingTreeView; +import net.fabricmc.mappingio.tree.MappingTreeView.ClassMappingView; +import net.fabricmc.mappingio.tree.MappingTreeView.MethodArgMappingView; +import net.fabricmc.mappingio.tree.MappingTreeView.MethodMappingView; import jadx.api.plugins.pass.JadxPassInfo; import jadx.api.plugins.pass.impl.OrderedJadxPassInfo; @@ -20,7 +20,7 @@ import jadx.plugins.mappings.RenameMappingsData; import jadx.plugins.mappings.utils.DalvikToJavaBytecodeUtils; public class CodeMappingsPass implements JadxDecompilePass { - private Map clsRenamesMap; + private Map clsRenamesMap; @Override public JadxPassInfo getInfo() { @@ -36,14 +36,14 @@ public class CodeMappingsPass implements JadxDecompilePass { if (data == null) { return; } - MappingTree mappingTree = data.getMappings(); + MappingTreeView mappingTree = data.getMappings(); updateMappingsMap(mappingTree); root.registerCodeDataUpdateListener(codeData -> updateMappingsMap(mappingTree)); } @Override public boolean visit(ClassNode cls) { - ClassMapping classMapping = getMapping(cls); + ClassMappingView classMapping = getMapping(cls); if (classMapping != null) { applyRenames(cls, classMapping); } @@ -55,7 +55,7 @@ public class CodeMappingsPass implements JadxDecompilePass { public void visit(MethodNode mth) { } - private static void applyRenames(ClassNode cls, ClassMapping classMapping) { + private static void applyRenames(ClassNode cls, ClassMappingView classMapping) { for (MethodNode mth : cls.getMethods()) { String methodName = mth.getMethodInfo().getName(); String methodDesc = mth.getMethodInfo().getShortId().substring(methodName.length()); @@ -63,12 +63,12 @@ public class CodeMappingsPass implements JadxDecompilePass { if (ssaVars.isEmpty()) { continue; } - MethodMapping methodMapping = classMapping.getMethod(methodName, methodDesc); + MethodMappingView methodMapping = classMapping.getMethod(methodName, methodDesc); if (methodMapping == null) { continue; } // Method args - for (MethodArgMapping argMapping : methodMapping.getArgs()) { + for (MethodArgMappingView argMapping : methodMapping.getArgs()) { Integer mappingLvIndex = argMapping.getLvIndex(); for (SSAVar ssaVar : ssaVars) { Integer actualLvIndex = DalvikToJavaBytecodeUtils.getMethodArgLvIndex(ssaVar, mth); @@ -82,7 +82,7 @@ public class CodeMappingsPass implements JadxDecompilePass { } } - private ClassMapping getMapping(ClassNode cls) { + private ClassMappingView getMapping(ClassNode cls) { if (clsRenamesMap == null || clsRenamesMap.isEmpty()) { return null; } @@ -90,10 +90,10 @@ public class CodeMappingsPass implements JadxDecompilePass { return clsRenamesMap.get(classPath); } - private void updateMappingsMap(MappingTree mappings) { + private void updateMappingsMap(MappingTreeView mappings) { clsRenamesMap = new HashMap<>(); - for (ClassMapping cls : mappings.getClasses()) { - for (MethodMapping mth : cls.getMethods()) { + for (ClassMappingView cls : mappings.getClasses()) { + for (MethodMappingView mth : cls.getMethods()) { if (!mth.getArgs().isEmpty() || !mth.getVars().isEmpty()) { clsRenamesMap.put(cls.getSrcName(), cls); break; diff --git a/jadx-plugins/jadx-rename-mappings/src/main/java/jadx/plugins/mappings/load/LoadMappingsPass.java b/jadx-plugins/jadx-rename-mappings/src/main/java/jadx/plugins/mappings/load/LoadMappingsPass.java index 47be5dcfd..9bfea0add 100644 --- a/jadx-plugins/jadx-rename-mappings/src/main/java/jadx/plugins/mappings/load/LoadMappingsPass.java +++ b/jadx-plugins/jadx-rename-mappings/src/main/java/jadx/plugins/mappings/load/LoadMappingsPass.java @@ -6,8 +6,9 @@ import java.util.Collections; import net.fabricmc.mappingio.MappingReader; import net.fabricmc.mappingio.MappingUtil; import net.fabricmc.mappingio.adapter.MappingSourceNsSwitch; -import net.fabricmc.mappingio.tree.MappingTree; +import net.fabricmc.mappingio.tree.MappingTreeView; import net.fabricmc.mappingio.tree.MemoryMappingTree; +import net.fabricmc.mappingio.tree.VisitableMappingTree; import jadx.api.JadxArgs; import jadx.api.plugins.pass.JadxPassInfo; @@ -33,14 +34,14 @@ public class LoadMappingsPass implements JadxPreparePass { @Override public void init(RootNode root) { - MappingTree mappings = loadMapping(root.getArgs()); + MappingTreeView mappings = loadMapping(root.getArgs()); root.getAttributes().add(new RenameMappingsData(mappings)); } - private MappingTree loadMapping(JadxArgs args) { + private MappingTreeView loadMapping(JadxArgs args) { try { Path mappingsPath = args.getUserRenamesMappingsPath(); - MemoryMappingTree mappingTree = new MemoryMappingTree(); + VisitableMappingTree mappingTree = new MemoryMappingTree(); MappingReader.read(mappingsPath, options.getFormat(), mappingTree); if (mappingTree.getSrcNamespace() == null) { mappingTree.setSrcNamespace(MappingUtil.NS_SOURCE_FALLBACK); @@ -53,7 +54,7 @@ public class LoadMappingsPass implements JadxPreparePass { mappingTree.getDstNamespaces().size())); } if (options.isInvert()) { - MemoryMappingTree invertedMappingTree = new MemoryMappingTree(); + VisitableMappingTree invertedMappingTree = new MemoryMappingTree(); String dstNamespace = mappingTree.getDstNamespaces().get(0); mappingTree.accept(new MappingSourceNsSwitch(invertedMappingTree, dstNamespace)); return invertedMappingTree; diff --git a/jadx-plugins/jadx-rename-mappings/src/main/java/jadx/plugins/mappings/save/MappingExporter.java b/jadx-plugins/jadx-rename-mappings/src/main/java/jadx/plugins/mappings/save/MappingExporter.java index 462d203a4..a7671f347 100644 --- a/jadx-plugins/jadx-rename-mappings/src/main/java/jadx/plugins/mappings/save/MappingExporter.java +++ b/jadx-plugins/jadx-rename-mappings/src/main/java/jadx/plugins/mappings/save/MappingExporter.java @@ -10,6 +10,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; @@ -21,8 +22,10 @@ import net.fabricmc.mappingio.MappedElementKind; import net.fabricmc.mappingio.MappingUtil; import net.fabricmc.mappingio.MappingWriter; import net.fabricmc.mappingio.format.MappingFormat; -import net.fabricmc.mappingio.tree.MappingTree; +import net.fabricmc.mappingio.tree.MappingTreeView; import net.fabricmc.mappingio.tree.MemoryMappingTree; +import net.fabricmc.mappingio.tree.VisitOrder; +import net.fabricmc.mappingio.tree.VisitableMappingTree; import jadx.api.ICodeInfo; import jadx.api.data.ICodeComment; @@ -52,19 +55,19 @@ public class MappingExporter { private static final Logger LOG = LoggerFactory.getLogger(MappingExporter.class); private final RootNode root; - private final @Nullable MappingTree loadedMappingTree; + private final @Nullable MappingTreeView loadedMappingTree; public MappingExporter(RootNode root) { this.root = root; this.loadedMappingTree = RenameMappingsData.getTree(this.root); } - private List> collectMethodVars(MethodNode methodNode) { + private List>> collectMethodVars(MethodNode methodNode) { ICodeInfo codeInfo = methodNode.getTopParentClass().getCode(); int mthDefPos = methodNode.getDefPosition(); int mthLineEndPos = CodeUtils.getLineEndForPos(codeInfo.getCodeStr(), mthDefPos); - List> vars = new ArrayList<>(); + List>> vars = new ArrayList<>(); AtomicInteger lastOffset = new AtomicInteger(-1); codeInfo.getCodeMetadata().searchDown(mthLineEndPos, (pos, ann) -> { if (ann instanceof InsnCodeOffset) { @@ -74,12 +77,17 @@ public class MappingExporter { ICodeNodeRef declRef = ((NodeDeclareRef) ann).getNode(); if (declRef instanceof VarNode) { VarNode varNode = (VarNode) declRef; - if (!varNode.getMth().equals(methodNode)) { - // Stop if we've gone too far and have entered a different method + if (!varNode.getMth().equals(methodNode)) { // Stop if we've gone too far and have entered a different method + if (!vars.isEmpty()) { + vars.get(vars.size() - 1).getValue().setValue(declRef.getDefPosition() - 1); + } return Boolean.TRUE; } if (lastOffset.get() != -1) { - vars.add(new SimpleEntry(varNode, lastOffset.get())); + if (!vars.isEmpty()) { + vars.get(vars.size() - 1).getValue().setValue(lastOffset.get() - 1); + } + vars.add(new SimpleEntry>(varNode, new SimpleEntry<>(lastOffset.get(), null))); } else { LOG.warn("Local variable not present in bytecode, skipping: " + methodNode.getMethodInfo().getRawFullId() + "#" + varNode.getName()); @@ -93,7 +101,7 @@ public class MappingExporter { } public void exportMappings(Path path, JadxCodeData codeData, MappingFormat mappingFormat) { - MemoryMappingTree mappingTree = new MemoryMappingTree(); + VisitableMappingTree mappingTree = new MemoryMappingTree(); // Map < SrcName > Set mappedClasses = new HashSet<>(); // Map < DeclClass + ShortId > @@ -102,7 +110,7 @@ public class MappingExporter { Set methodsWithMappedElements = new HashSet<>(); // Map < DeclClass + MethodShortId + CodeRef, NewName > Map mappedMethodArgsAndVars = new HashMap<>(); - // Map < DeclClass + *ShortId + *CodeRef, Comment > + // Map < DeclClass [+ ShortId] [+ CodeRef], Comment > Map comments = new HashMap<>(); // We have to do this so we know for sure which elements are *manually* renamed @@ -222,10 +230,12 @@ public class MappingExporter { // Not checking for comments since method args can't have any } // Method vars - List> vars = collectMethodVars(mth); - for (SimpleEntry entry : vars) { + var vars = collectMethodVars(mth); + for (int i = 0; i < vars.size(); i++) { + var entry = vars.get(i); VarNode var = entry.getKey(); - int offset = entry.getValue(); + int startOpIdx = entry.getValue().getKey(); + int endOpIdx = entry.getValue().getValue(); Integer lvIndex = DalvikToJavaBytecodeUtils.getMethodVarLvIndex(var); if (lvIndex == null) { lvIndex = -1; @@ -233,12 +243,12 @@ public class MappingExporter { String key = rawClassName + methodInfo.getShortId() + JadxCodeRef.forVar(var.getReg(), var.getSsa()); if (mappedMethodArgsAndVars.containsKey(key)) { - visitMethodVar(mappingTree, classPath, methodName, methodDesc, lvtIndex, lvIndex, offset); + visitMethodVar(mappingTree, classPath, methodName, methodDesc, lvtIndex, lvIndex, startOpIdx, endOpIdx); mappingTree.visitDstName(MappedElementKind.METHOD_VAR, 0, mappedMethodArgsAndVars.get(key)); } - key = rawClassName + methodInfo.getShortId() + JadxCodeRef.forInsn(offset); + key = rawClassName + methodInfo.getShortId() + JadxCodeRef.forInsn(startOpIdx); if (comments.containsKey(key)) { - visitMethodVar(mappingTree, classPath, methodName, methodDesc, lvtIndex, lvIndex, offset); + visitMethodVar(mappingTree, classPath, methodName, methodDesc, lvtIndex, lvIndex, startOpIdx, endOpIdx); mappingTree.visitComment(MappedElementKind.METHOD_VAR, comments.get(key)); } lvtIndex++; @@ -246,34 +256,32 @@ public class MappingExporter { } } // Write file - MappingWriter writer = MappingWriter.create(path, mappingFormat); - mappingTree.accept(writer); + mappingTree.accept(MappingWriter.create(path, mappingFormat), VisitOrder.createByName()); mappingTree.visitEnd(); - writer.close(); } catch (IOException e) { LOG.error("Failed to save deobfuscation map file '{}'", path.toAbsolutePath(), e); } } - private void visitField(MemoryMappingTree tree, String classPath, String srcName, String srcDesc) { + private void visitField(VisitableMappingTree tree, String classPath, String srcName, String srcDesc) throws IOException { tree.visitClass(classPath); tree.visitField(srcName, srcDesc); } - private void visitMethod(MemoryMappingTree tree, String classPath, String srcName, String srcDesc) { + private void visitMethod(VisitableMappingTree tree, String classPath, String srcName, String srcDesc) throws IOException { tree.visitClass(classPath); tree.visitMethod(srcName, srcDesc); } - private void visitMethodArg(MemoryMappingTree tree, String classPath, String methodSrcName, String methodSrcDesc, int argPosition, - int lvIndex) { + private void visitMethodArg(VisitableMappingTree tree, String classPath, String methodSrcName, String methodSrcDesc, int argPosition, + int lvIndex) throws IOException { visitMethod(tree, classPath, methodSrcName, methodSrcDesc); tree.visitMethodArg(argPosition, lvIndex, null); } - private void visitMethodVar(MemoryMappingTree tree, String classPath, String methodSrcName, String methodSrcDesc, int lvtIndex, - int lvIndex, int startOpIdx) { + private void visitMethodVar(VisitableMappingTree tree, String classPath, String methodSrcName, String methodSrcDesc, int lvtIndex, + int lvIndex, int startOpIdx, int endOpIdx) throws IOException { visitMethod(tree, classPath, methodSrcName, methodSrcDesc); - tree.visitMethodVar(lvtIndex, lvIndex, startOpIdx, null); + tree.visitMethodVar(lvtIndex, lvIndex, startOpIdx, endOpIdx, null); } }