summaryrefslogtreecommitdiff
path: root/src/main/java/ftbsc/lll/mapper/tools
diff options
context:
space:
mode:
author zaaarf <zaaarf@proton.me>2023-06-11 14:48:24 +0200
committer zaaarf <zaaarf@proton.me>2023-06-11 14:48:24 +0200
commit7c427316a675cbe7e81a04294781c59f2606239d (patch)
tree3a4efc720f44205db6c518ee854f03eebf215e7c /src/main/java/ftbsc/lll/mapper/tools
feat: initial implementation, created interface and moved stuff from processor
Diffstat (limited to 'src/main/java/ftbsc/lll/mapper/tools')
-rw-r--r--src/main/java/ftbsc/lll/mapper/tools/ClassData.java100
-rw-r--r--src/main/java/ftbsc/lll/mapper/tools/MappingUtils.java56
2 files changed, 156 insertions, 0 deletions
diff --git a/src/main/java/ftbsc/lll/mapper/tools/ClassData.java b/src/main/java/ftbsc/lll/mapper/tools/ClassData.java
new file mode 100644
index 0000000..a9fbcec
--- /dev/null
+++ b/src/main/java/ftbsc/lll/mapper/tools/ClassData.java
@@ -0,0 +1,100 @@
+package ftbsc.lll.mapper.tools;
+
+import ftbsc.lll.exceptions.AmbiguousMappingException;
+import ftbsc.lll.exceptions.MappingNotFoundException;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * Container class used to store information about classes.
+ */
+public class ClassData {
+ /**
+ * The unobfuscated name (FQN with '/' instad of '.') of the class.
+ */
+ public final String unobf;
+
+ /**
+ * The obfuscated internal name (FQN with '/' instad of '.') of the class.
+ */
+ public final String obf;
+
+ /**
+ * A {@link Map} tying each member's name or signature to its
+ * obfuscated counterpart.
+ */
+ public final Map<String, String> members;
+
+ /**
+ * The constructor. It takes in the names (obfuscated and non-obfuscated)
+ * of a class.
+ * @param unobf the unobfuscated name
+ * @param obf the obfuscated name
+ */
+ public ClassData(String unobf, String obf) {
+ this.unobf = unobf;
+ this.obf = obf;
+ this.members = new HashMap<>();
+ }
+
+ /**
+ * Adds a member to the target class.
+ * For fields only the names are required; for methods,
+ * this takes in the full signature ({@code name + " " + space}).
+ * @param s the String representing the declaration line
+ */
+ public void addMember(String s) {
+ String[] split = s.trim().split(" ");
+ if(split.length == 2) //field
+ members.put(split[0], split[1]);
+ else if (split.length == 3) //method
+ members.put(split[0] + " " + split[1], split[2]);
+ }
+
+ /**
+ * Gets an obfuscated member given the method name and a method descriptor,
+ * which may be partial (i.e. not include return type) or null if the member
+ * is not a method.
+ * @param memberName member name
+ * @param methodDescriptor the method descriptor, or null if it's not a method
+ * @return the requested obfuscated name, or null if nothing was found
+ * @throws AmbiguousMappingException if not enough data was given to uniquely identify a mapping
+ */
+ public String get(String memberName, String methodDescriptor) {
+
+ //find all keys that start with the name
+ List<String> candidates = members.keySet().stream().filter(
+ m -> m.split(" ")[0].equals(memberName)
+ ).collect(Collectors.toList());
+
+ if(methodDescriptor != null) {
+ String signature = String.format("%s %s", memberName, methodDescriptor);
+ candidates = candidates.stream().filter(
+ m -> m.equals(signature)
+ ).collect(Collectors.toList());
+ }
+
+ switch(candidates.size()) {
+ case 0:
+ throw new MappingNotFoundException(String.format(
+ "%s.%s%s",
+ this.unobf,
+ memberName,
+ methodDescriptor == null ? "" : "()"
+ ));
+ case 1:
+ return members.get(candidates.get(0));
+ default:
+ throw new AmbiguousMappingException(String.format(
+ "Mapper could not uniquely identify member %s.%s%s, found %d!",
+ this.unobf,
+ memberName,
+ methodDescriptor == null ? "" : "()",
+ candidates.size()
+ ));
+ }
+ }
+} \ No newline at end of file
diff --git a/src/main/java/ftbsc/lll/mapper/tools/MappingUtils.java b/src/main/java/ftbsc/lll/mapper/tools/MappingUtils.java
new file mode 100644
index 0000000..918052a
--- /dev/null
+++ b/src/main/java/ftbsc/lll/mapper/tools/MappingUtils.java
@@ -0,0 +1,56 @@
+package ftbsc.lll.mapper.tools;
+
+import ftbsc.lll.exceptions.MappingNotFoundException;
+import ftbsc.lll.mapper.IMapper;
+import ftbsc.lll.tools.DescriptorBuilder;
+import org.objectweb.asm.Type;
+
+public class MappingUtils {
+ /**
+ * Obfuscates a method descriptor, replacing its class references
+ * with their obfuscated counterparts.
+ * @param descriptor a {@link String} containing the descriptor
+ * @return the obfuscated descriptor
+ */
+ public static String obfuscateMethodDescriptor(String descriptor, IMapper mapper) {
+ Type method = Type.getMethodType(descriptor);
+ Type[] arguments = method.getArgumentTypes();
+ Type returnType = method.getReturnType();
+
+ Type[] obfArguments = new Type[arguments.length];
+ for(int i = 0; i < obfArguments.length; i++)
+ obfArguments[i] = obfuscateType(arguments[i], mapper);
+
+ return Type.getMethodDescriptor(obfuscateType(returnType, mapper), obfArguments);
+ }
+
+ /**
+ * Given a {@link Type} and a valid {@link IMapper} it returns its obfuscated
+ * counterpart.
+ * @param type the type in question
+ * @return the obfuscated type
+ */
+ public static Type obfuscateType(Type type, IMapper mapper) {
+ //unwrap arrays
+ Type unwrapped = type;
+ int arrayLevel = 0;
+ while(unwrapped.getSort() == Type.ARRAY) {
+ unwrapped = unwrapped.getElementType();
+ arrayLevel++;
+ }
+
+ //if it's a primitive no operation is needed
+ if(type.getSort() < Type.ARRAY)
+ return type;
+
+ String internalName = type.getInternalName();
+
+ String internalNameObf;
+ try {
+ internalNameObf = mapper.obfuscateClass(internalName);
+ return Type.getType(DescriptorBuilder.nameToDescriptor(internalNameObf, arrayLevel));
+ } catch(MappingNotFoundException e) {
+ return type;
+ }
+ }
+}