fix: update to Mapping-IO 0.5 (PR #2029)

* Update to Mapping-IO 0.5

* Fix Spotless error

* Fix Spotless error (2)

* Sort mappings by name when exporting
This commit is contained in:
Julian Burner
2023-10-09 19:46:51 +02:00
committed by GitHub
parent 6433fcef72
commit d129be7e86
8 changed files with 77 additions and 71 deletions
@@ -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));
}
@@ -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")
}
}
@@ -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;
}
@@ -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);
@@ -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<String, ClassMapping> clsRenamesMap;
private Map<String, ClassMappingView> 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;
@@ -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;
@@ -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<SimpleEntry<VarNode, Integer>> collectMethodVars(MethodNode methodNode) {
private List<Entry<VarNode, Entry<Integer, Integer>>> collectMethodVars(MethodNode methodNode) {
ICodeInfo codeInfo = methodNode.getTopParentClass().getCode();
int mthDefPos = methodNode.getDefPosition();
int mthLineEndPos = CodeUtils.getLineEndForPos(codeInfo.getCodeStr(), mthDefPos);
List<SimpleEntry<VarNode, Integer>> vars = new ArrayList<>();
List<Entry<VarNode, Entry<Integer, Integer>>> 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, Integer>(varNode, lastOffset.get()));
if (!vars.isEmpty()) {
vars.get(vars.size() - 1).getValue().setValue(lastOffset.get() - 1);
}
vars.add(new SimpleEntry<VarNode, Entry<Integer, Integer>>(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<String> mappedClasses = new HashSet<>();
// Map < DeclClass + ShortId >
@@ -102,7 +110,7 @@ public class MappingExporter {
Set<String> methodsWithMappedElements = new HashSet<>();
// Map < DeclClass + MethodShortId + CodeRef, NewName >
Map<String, String> mappedMethodArgsAndVars = new HashMap<>();
// Map < DeclClass + *ShortId + *CodeRef, Comment >
// Map < DeclClass [+ ShortId] [+ CodeRef], Comment >
Map<String, String> 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<SimpleEntry<VarNode, Integer>> vars = collectMethodVars(mth);
for (SimpleEntry<VarNode, Integer> 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);
}
}