diff --git a/src/main/java/ftbsc/lll/mapper/AbstractMapper.java b/src/main/java/ftbsc/lll/mapper/AbstractMapper.java index 037e7c9..62585c4 100644 --- a/src/main/java/ftbsc/lll/mapper/AbstractMapper.java +++ b/src/main/java/ftbsc/lll/mapper/AbstractMapper.java @@ -1,11 +1,11 @@ package ftbsc.lll.mapper; -import ftbsc.lll.exceptions.MalformedMappingsException; import ftbsc.lll.exceptions.MappingNotFoundException; import ftbsc.lll.mapper.tools.data.ClassData; +import ftbsc.lll.mapper.tools.data.FieldData; +import ftbsc.lll.mapper.tools.data.MethodData; import java.util.HashMap; -import java.util.List; import java.util.Map; /** @@ -19,124 +19,43 @@ public abstract class AbstractMapper implements IMapper { */ protected final Map mappings = new HashMap<>(); - /** - * A {@link Map} tying each obfuscated name to its class data. - */ - protected final Map mappingsInverted = new HashMap<>(); - - /** - * Populates the {@link IMapper} given the lines, ignoring errors depending on the - * given ignoreErrors flag. - * @param lines the lines to read - * @param ignoreErrors try to ignore errors and keep going - * @throws MalformedMappingsException if an error is encountered and ignoreErrors is false - */ - @Override - public void populate(List lines, boolean ignoreErrors) throws MalformedMappingsException { - this.processLines(lines, ignoreErrors); - this.mappings.forEach((name, data) -> { - ClassData reverse = data.generateReverseMappings(this); - this.mappingsInverted.put(data.nameMapped, reverse); - }); - } - - /** - * Reads the given lines of text and attempts to interpret them as - * mappings of the given type. - * @param lines the lines to read - * @param ignoreErrors try to ignore errors and keep going - * @throws MalformedMappingsException if an error is encountered and ignoreErrors is false - */ - protected abstract void processLines(List lines, boolean ignoreErrors) throws MalformedMappingsException; - - /** - * Completely resets the mapper, clearing it of all existing mappings. - */ @Override public void reset() { this.mappings.clear(); - this.mappingsInverted.clear(); + } + + @Override + public IMapper getInverted() { + AbstractMapper inverted = newInstance(); + this.mappings.forEach((name, data) -> { + ClassData reverse = data.generateReverseMappings(this); + inverted.mappings.put(data.nameMapped, reverse); + }); + return inverted; } /** - * Gets a name of a class from the given {@link Map}. - * @param name the name - * @param mappings the {@link Map} to pull data from - * @return the mapped name - * @throws MappingNotFoundException if no mapping is found + * Creates a new instance of this type of mapper. + * @return the new, empty instance */ - private static String mapClass(String name, Map mappings) { - ClassData data = mappings.get(name.replace('.', '/')); + protected abstract AbstractMapper newInstance(); + + + @Override + public ClassData getClassData(String name) { + ClassData data = this.mappings.get(name.replace('.', '/')); if(data == null) throw new MappingNotFoundException("class", name); - else return data.nameMapped; + else return data; } - /** - * Gets the obfuscated name of the class. - * @param name the plain internal name of the desired class - * @return the obfuscated name of the class - * @throws MappingNotFoundException if no mapping is found - */ @Override - public String obfuscateClass(String name) { - return mapClass(name, this.mappings); + public MethodData getMethodData(String parent, String name, String descriptor) { + return this.getClassData(parent).mapMethod(name, descriptor); } - /** - * Gets the plain name of the class. - * @param nameObf the obfuscated internal name of the desired class - * @return the plain name of the class - * @throws MappingNotFoundException if no mapping is found - */ @Override - public String deobfuscateClass(String nameObf) throws MappingNotFoundException { - return mapClass(nameObf, this.mappingsInverted); - } - - /** - * Gets the name of a member from the given {@link Map}. - * @param parentName the parent class - * @param mappings the {@link Map} to pull data from - * @param memberName the field or method name - * @param methodDescriptor the method descriptor, may be null or partial - * @return the mapped member name - * @throws MappingNotFoundException if no mapping is found - */ - private static String mapMember(String parentName, Map mappings, - String memberName, String methodDescriptor) { - ClassData data = mappings.get(parentName.replace('.', '/')); - if(data == null) - throw new MappingNotFoundException("class", parentName); - - if(methodDescriptor == null) - return data.mapField(memberName).name; - else return data.mapMethod(memberName, methodDescriptor).signature.name; - } - - /** - * Gets the obfuscated name of a class member (field or method). - * @param parentName the unobfuscated internal name of the parent class - * @param memberName the field or method name - * @param methodDescriptor the optional descriptor of the member, may be null or partial - * @return the obfuscated name of the given member - * @throws MappingNotFoundException if no mapping is found - */ - @Override - public String obfuscateMember(String parentName, String memberName, String methodDescriptor) { - return mapMember(parentName, this.mappings, memberName, methodDescriptor); - } - - /** - * Gets the plain name of a class member (field or method). - * @param parentName the obfuscated internal name of the parent class - * @param memberName the obfuscated field name or method signature - * @param methodDescriptor the obfuscated descriptor of the member (only for methods) - * @return the plain name of the given member - * @throws MappingNotFoundException if no mapping is found - */ - @Override - public String deobfuscateMember(String parentName, String memberName, String methodDescriptor) throws MappingNotFoundException { - return mapMember(parentName, this.mappingsInverted, memberName, methodDescriptor); + public FieldData getFieldData(String parent, String name) throws MappingNotFoundException { + return this.getClassData(parent).mapField(name); } } diff --git a/src/main/java/ftbsc/lll/mapper/IMapper.java b/src/main/java/ftbsc/lll/mapper/IMapper.java index 96b5d6f..1fe04ca 100644 --- a/src/main/java/ftbsc/lll/mapper/IMapper.java +++ b/src/main/java/ftbsc/lll/mapper/IMapper.java @@ -2,11 +2,14 @@ package ftbsc.lll.mapper; import ftbsc.lll.exceptions.MalformedMappingsException; import ftbsc.lll.exceptions.MappingNotFoundException; +import ftbsc.lll.mapper.tools.data.ClassData; +import ftbsc.lll.mapper.tools.data.FieldData; +import ftbsc.lll.mapper.tools.data.MethodData; import java.util.*; /** - * A generic obfuscation mapper. + * The shared interface between all mappers. */ public interface IMapper { /** @@ -36,45 +39,42 @@ public interface IMapper { */ void populate(List lines, boolean ignoreErrors) throws MalformedMappingsException; + /** + * Builds an {@link IMapper} that functions in reverse to this one (i.e. one that + * considers as "mapped" what this one considers plain, and vice versa). + * @return the inverted mapper + */ + IMapper getInverted(); + /** * Completely resets the mapper, clearing it of all existing mappings. */ void reset(); /** - * Gets the obfuscated name of the class. + * Gets the {@link ClassData} * @param name the plain internal name of the desired class * @return the obfuscated name of the class * @throws MappingNotFoundException if no mapping is found */ - String obfuscateClass(String name) throws MappingNotFoundException; - - /** - * Gets the plain name of the class. - * @param nameObf the obfuscated internal name of the desired class - * @return the plain name of the class - * @throws MappingNotFoundException if no mapping is found - */ - String deobfuscateClass(String nameObf) throws MappingNotFoundException; + ClassData getClassData(String name) throws MappingNotFoundException; /** * Gets the obfuscated name of a class member (field or method). - * @param parentName the plain internal name of the parent class - * @param memberName the field name or method signature - * @param methodDescriptor the descriptor of the member (only for methods) + * @param parent the plain internal name of the parent class + * @param name the field name + * @param descriptor the descriptor of the member (only for methods) * @return the obfuscated name of the given member * @throws MappingNotFoundException if no mapping is found */ - String obfuscateMember(String parentName, String memberName, String methodDescriptor) throws MappingNotFoundException; + MethodData getMethodData(String parent, String name, String descriptor) throws MappingNotFoundException; /** - * Gets the plain name of a class member (field or method). - * @param parentName the obfuscated internal name of the parent class - * @param memberName the obfuscated field name or method signature - * @param methodDescriptor the obfuscated descriptor of the member (only for methods) - * @return the plain name of the given member + * Gets the obfuscated name of a class member (field or method). + * @param parent the plain internal name of the parent class + * @param name the field name + * @return the obfuscated name of the given member * @throws MappingNotFoundException if no mapping is found */ - String deobfuscateMember(String parentName, String memberName, String methodDescriptor) throws MappingNotFoundException; - + FieldData getFieldData(String parent, String name) throws MappingNotFoundException; } diff --git a/src/main/java/ftbsc/lll/mapper/impl/MultiMapper.java b/src/main/java/ftbsc/lll/mapper/impl/MultiMapper.java index 20cb2a5..db12235 100644 --- a/src/main/java/ftbsc/lll/mapper/impl/MultiMapper.java +++ b/src/main/java/ftbsc/lll/mapper/impl/MultiMapper.java @@ -6,8 +6,12 @@ import ftbsc.lll.exceptions.MappingNotFoundException; import ftbsc.lll.mapper.IMapper; import ftbsc.lll.mapper.MapperProvider; import ftbsc.lll.mapper.tools.MappingUtils; +import ftbsc.lll.mapper.tools.data.ClassData; +import ftbsc.lll.mapper.tools.data.FieldData; +import ftbsc.lll.mapper.tools.data.MethodData; import java.util.ArrayList; +import java.util.Collections; import java.util.List; /** @@ -22,23 +26,11 @@ public class MultiMapper implements IMapper { */ private final List mapperList = new ArrayList<>(); - /** - * Checks whether this mapper can process the given lines. - * @param lines the lines to read - * @return whether this type of mapper can process these lines - */ @Override public boolean claim(List lines) { return lines.get(0).equals("lll multimapper"); } - /** - * Populates the {@link IMapper} given the lines, ignoring errors depending on the - * given ignoreErrors flag. - * @param lines the lines to read - * @param ignoreErrors try to ignore errors and keep going - * @throws MalformedMappingsException if an error is encountered and ignoreErrors is false - */ @Override public void populate(List lines, boolean ignoreErrors) throws MalformedMappingsException { for(int i = 1; i < lines.size(); i++) { @@ -49,75 +41,44 @@ public class MultiMapper implements IMapper { } } - /** - * Completely resets the mapper, clearing it of all existing mappings. - */ + @Override + public IMapper getInverted() { + MultiMapper reverse = new MultiMapper(); + this.mapperList.forEach(m -> reverse.mapperList.add(m.getInverted())); + Collections.reverse(reverse.mapperList); + return reverse; + } + @Override public void reset() { this.mapperList.forEach(IMapper::reset); this.mapperList.clear(); } - /** - * Gets the obfuscated name of the class. - * @param name the plain internal name of the desired class - * @return the obfuscated name of the class - * @throws MappingNotFoundException if no mapping is found - */ @Override - public String obfuscateClass(String name) throws MappingNotFoundException { - for(IMapper mapper : this.mapperList) - name = mapper.obfuscateClass(name); - return name; + public ClassData getClassData(String name) throws MappingNotFoundException { + ClassData classData = this.mapperList.get(0).getClassData(name); + for(int i = 1; i < this.mapperList.size(); i++) + classData = this.mapperList.get(i).getClassData(classData.nameMapped); + return classData; } - /** - * Gets the plain name of the class. - * @param nameObf the obfuscated internal name of the desired class - * @return the plain name of the class - * @throws MappingNotFoundException if no mapping is found - */ @Override - public String deobfuscateClass(String nameObf) throws MappingNotFoundException { - for(int i = this.mapperList.size() - 1; i >= 0; i--) - nameObf = this.mapperList.get(i).deobfuscateClass(nameObf); - return nameObf; - } - - /** - * Gets the obfuscated name of a class member (field or method). - * @param parentName the plain internal name of the parent class - * @param memberName the field name or method signature - * @param methodDescriptor the descriptor of the member (only for methods) - * @return the obfuscated name of the given member - * @throws MappingNotFoundException if no mapping is found - */ - @Override - public String obfuscateMember(String parentName, String memberName, String methodDescriptor) throws MappingNotFoundException { - for(IMapper mapper : this.mapperList) { - memberName = mapper.obfuscateMember(parentName, memberName, methodDescriptor); - methodDescriptor = MappingUtils.mapMethodDescriptor(methodDescriptor, mapper, false); - parentName = mapper.obfuscateClass(parentName); - } - return memberName; - } - - /** - * Gets the plain name of a class member (field or method). - * @param parentName the obfuscated internal name of the parent class - * @param memberName the obfuscated field name or method signature - * @param methodDescriptor the obfuscated descriptor of the member (only for methods) - * @return the plain name of the given member - * @throws MappingNotFoundException if no mapping is found - */ - @Override - public String deobfuscateMember(String parentName, String memberName, String methodDescriptor) throws MappingNotFoundException { - for(int i = this.mapperList.size() - 1; i >= 0; i--) { + public MethodData getMethodData(String parent, String name, String descriptor) throws MappingNotFoundException { + MethodData methodData = this.mapperList.get(0).getMethodData(parent, name, descriptor); + for(int i = 1; i < this.mapperList.size(); i++) { IMapper mapper = this.mapperList.get(i); - memberName = mapper.deobfuscateMember(parentName, memberName, methodDescriptor); - methodDescriptor = MappingUtils.mapMethodDescriptor(methodDescriptor, mapper, true); - parentName = mapper.deobfuscateClass(parentName); + methodData = mapper.getMethodData(methodData.parentClass.nameMapped, methodData.nameMapped, + MappingUtils.mapMethodDescriptor(methodData.signature.descriptor, mapper, false)); } - return memberName; + return methodData; + } + + @Override + public FieldData getFieldData(String parent, String name) throws MappingNotFoundException { + FieldData fieldData = this.mapperList.get(0).getFieldData(parent, name); + for(int i = 1; i < this.mapperList.size(); i++) + fieldData = this.mapperList.get(i).getFieldData(fieldData.parentClass.nameMapped, fieldData.nameMapped); + return fieldData; } } diff --git a/src/main/java/ftbsc/lll/mapper/impl/SRGMapper.java b/src/main/java/ftbsc/lll/mapper/impl/SRGMapper.java index 442c204..e47ca38 100644 --- a/src/main/java/ftbsc/lll/mapper/impl/SRGMapper.java +++ b/src/main/java/ftbsc/lll/mapper/impl/SRGMapper.java @@ -6,18 +6,24 @@ import ftbsc.lll.mapper.AbstractMapper; import ftbsc.lll.mapper.IMapper; import ftbsc.lll.mapper.tools.data.ClassData; +import java.util.HashMap; import java.util.List; +import java.util.Map; /** * A {@link IMapper} capable of parsing SRG mappings. */ @AutoService(IMapper.class) public class SRGMapper extends AbstractMapper { + /** - * Checks whether this mapper can process the given lines. - * @param lines the lines to read - * @return whether this type of mapper can process these lines + * A {@link Map} tying each obfuscated name to its class data. + * Done this way because SRG files provide mapped descriptors in advance, + * so we can populate this right a way in a less expensive way. */ + private final Map mappingsInverted = new HashMap<>(); + + @Override public boolean claim(List lines) { String[] firstLineTokens = lines.get(0).trim().split(" "); @@ -27,13 +33,6 @@ public class SRGMapper extends AbstractMapper { || firstLineTokens[0].equals("FD:")); } - /** - * Populates the {@link IMapper} given the lines, ignoring errors depending on the - * given ignoreErrors flag. - * @param lines the lines to read - * @param ignoreErrors try to ignore errors and keep going - * @throws MalformedMappingsException if an error is encountered and ignoreErrors is false - */ @Override public void populate(List lines, boolean ignoreErrors) throws MalformedMappingsException { for(int i = 0; i < lines.size(); i++) { @@ -84,14 +83,6 @@ public class SRGMapper extends AbstractMapper { return true; } - /** - * This does nothing as it is never called for this type of mapper. - * @param lines the lines to read - * @param ignoreErrors try to ignore errors and keep going - */ - @Override - protected void processLines(List lines, boolean ignoreErrors) {} - /** * Registers a class in the mapper, if it isn't already. * @param name the name @@ -128,4 +119,17 @@ public class SRGMapper extends AbstractMapper { dataReverse.addMethod(nameMapped, name, descriptorMapped); } } + + @Override + public IMapper getInverted() { + SRGMapper inverted = new SRGMapper(); + inverted.mappings.putAll(this.mappingsInverted); + inverted.mappingsInverted.putAll(this.mappings); //in case some weirdo calls getInverted() twice + return inverted; + } + + @Override + protected AbstractMapper newInstance() { //not really used but whatever + return new SRGMapper(); + } } \ No newline at end of file diff --git a/src/main/java/ftbsc/lll/mapper/impl/TSRGMapper.java b/src/main/java/ftbsc/lll/mapper/impl/TSRGMapper.java index ad4c65e..9cd96d1 100644 --- a/src/main/java/ftbsc/lll/mapper/impl/TSRGMapper.java +++ b/src/main/java/ftbsc/lll/mapper/impl/TSRGMapper.java @@ -16,25 +16,13 @@ import java.util.List; @AutoService(IMapper.class) public class TSRGMapper extends AbstractMapper { - /** - * Checks whether this mapper can process the given lines. - * @param lines the lines to read - * @return whether this type of mapper can process these lines - */ @Override public boolean claim(List lines) { return lines.get(0).startsWith("tsrg2 left right"); } - /** - * Reads the given lines of text and attempts to interpret them as - * mappings of the given type. - * @param lines the lines to read - * @param ignoreErrors try to ignore errors and keep going - * @throws MalformedMappingsException if an error is encountered and ignoreErrors is false - */ @Override - protected void processLines(List lines, boolean ignoreErrors) throws MalformedMappingsException { + public void populate(List lines, boolean ignoreErrors) throws MalformedMappingsException { String currentClass = ""; for(int i = 1; i < lines.size(); i++) { //start from 1 to skip header String currentLine = lines.get(i); @@ -55,4 +43,9 @@ public class TSRGMapper extends AbstractMapper { } } } + + @Override + protected AbstractMapper newInstance() { + return new TSRGMapper(); + } } diff --git a/src/main/java/ftbsc/lll/mapper/impl/TinyV2Mapper.java b/src/main/java/ftbsc/lll/mapper/impl/TinyV2Mapper.java index 37c8f80..d27756d 100644 --- a/src/main/java/ftbsc/lll/mapper/impl/TinyV2Mapper.java +++ b/src/main/java/ftbsc/lll/mapper/impl/TinyV2Mapper.java @@ -15,26 +15,14 @@ import java.util.regex.Pattern; @AutoService(IMapper.class) public class TinyV2Mapper extends AbstractMapper { - /** - * Checks whether this mapper can process the given lines. - * @param lines the lines to read - * @return whether this type of mapper can process these lines - */ @Override public boolean claim(List lines) { return Pattern.compile("tiny\t2\t[0-9]\t[a-zA-Z]*\t[a-zA-Z]*") .matcher(lines.get(0)).matches(); } - /** - * Reads the given lines of text and attempts to interpret them as - * mappings of the given type. - * @param lines the lines to read - * @param ignoreErrors try to ignore errors and keep going - * @throws MalformedMappingsException if an error is encountered and ignoreErrors is false - */ @Override - protected void processLines(List lines, boolean ignoreErrors) throws MalformedMappingsException { + public void populate(List lines, boolean ignoreErrors) throws MalformedMappingsException { String currentClass = ""; for(int i = 1; i < lines.size(); i++) { String currentLine = lines.get(i); @@ -76,4 +64,9 @@ public class TinyV2Mapper extends AbstractMapper { throw new MalformedMappingsException(i, "wrong number of space-separated tokens"); } } + + @Override + protected AbstractMapper newInstance() { + return new TinyV2Mapper(); + } } diff --git a/src/main/java/ftbsc/lll/mapper/tools/MappingUtils.java b/src/main/java/ftbsc/lll/mapper/tools/MappingUtils.java index c8d76af..fcc5525 100644 --- a/src/main/java/ftbsc/lll/mapper/tools/MappingUtils.java +++ b/src/main/java/ftbsc/lll/mapper/tools/MappingUtils.java @@ -15,7 +15,7 @@ public class MappingUtils { * Maps a method descriptor, replacing its class references with their mapped counterparts. * @param descriptor a {@link String} containing the descriptor * @param mapper the {@link IMapper} to use for the process - * @param reverse whether it should deobfuscate rather than obfuscate + * @param reverse if true it uses the inverted mapper rather than the normal one * @return the mapped descriptor */ public static String mapMethodDescriptor(String descriptor, IMapper mapper, boolean reverse) { @@ -34,8 +34,8 @@ public class MappingUtils { * Given a {@link Type} and a valid {@link IMapper} it returns its mapped counterpart. * @param type the type in question * @param mapper the {@link IMapper} to use for the process - * @param reverse whether it should deobfuscate rather than obfuscate - * @return the obfuscated type + * @param reverse if true it uses the inverted mapper rather than the normal one + * @return the mapped type */ public static Type mapType(Type type, IMapper mapper, boolean reverse) { //unwrap arrays @@ -55,8 +55,8 @@ public class MappingUtils { String internalNameMapped; try { internalNameMapped = reverse - ? mapper.deobfuscateClass(internalName) - : mapper.obfuscateClass(internalName); + ? mapper.getInverted().getClassData(internalName).nameMapped + : mapper.getClassData(internalName).nameMapped; return Type.getType(DescriptorBuilder.nameToDescriptor(internalNameMapped, arrayLevel)); } catch(MappingNotFoundException e) { return type; diff --git a/src/main/java/ftbsc/lll/mapper/tools/data/MethodData.java b/src/main/java/ftbsc/lll/mapper/tools/data/MethodData.java index 27c418c..699b0b0 100644 --- a/src/main/java/ftbsc/lll/mapper/tools/data/MethodData.java +++ b/src/main/java/ftbsc/lll/mapper/tools/data/MethodData.java @@ -18,7 +18,7 @@ public class MethodData { /** * The mapped name of the method. */ - final String nameMapped; + public final String nameMapped; /** * Constructs a new {@link MethodData}.