Initial implementation of field reflection remapper
Remaps the string constant in class.getDeclaredField("fieldname")
This commit is contained in:
parent
874e759a9d
commit
6e34774a46
91
src/main/java/net/md_5/specialsource/ReflectionRemapper.java
Normal file
91
src/main/java/net/md_5/specialsource/ReflectionRemapper.java
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
package net.md_5.specialsource;
|
||||||
|
|
||||||
|
import org.objectweb.asm.ClassReader;
|
||||||
|
import org.objectweb.asm.ClassWriter;
|
||||||
|
import org.objectweb.asm.Opcodes;
|
||||||
|
import org.objectweb.asm.tree.*;
|
||||||
|
import org.objectweb.asm.Type;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class ReflectionRemapper {
|
||||||
|
|
||||||
|
private JarMapping jarMapping;
|
||||||
|
private IInheritanceProvider inheritanceProvider;
|
||||||
|
|
||||||
|
public ReflectionRemapper(JarMapping jarMapping, IInheritanceProvider inheritanceProvider) {
|
||||||
|
this.jarMapping = jarMapping;
|
||||||
|
this.inheritanceProvider = inheritanceProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public byte[] remapClassFile(InputStream is) throws IOException {
|
||||||
|
ClassReader cr = new ClassReader(is);
|
||||||
|
ClassNode classNode = new ClassNode();
|
||||||
|
ClassWriter cw = new ClassWriter(0);
|
||||||
|
|
||||||
|
cr.accept(classNode, ClassReader.SKIP_DEBUG);
|
||||||
|
|
||||||
|
for (MethodNode methodNode : (List<MethodNode>) classNode.methods) {
|
||||||
|
AbstractInsnNode insn = methodNode.instructions.getFirst();
|
||||||
|
while (insn != null) {
|
||||||
|
if (insn.getOpcode() == Opcodes.INVOKEVIRTUAL) {
|
||||||
|
remapGetDeclaredField(insn);
|
||||||
|
}
|
||||||
|
|
||||||
|
insn = insn.getNext();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
classNode.accept(cw);
|
||||||
|
|
||||||
|
return cw.toByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void remapGetDeclaredField(AbstractInsnNode insn) {
|
||||||
|
MethodInsnNode mi = (MethodInsnNode) insn;
|
||||||
|
|
||||||
|
System.out.println("methodnode "+mi.owner+" "+mi.name+" "+mi.desc);
|
||||||
|
if (!mi.owner.equals("java/lang/Class") || !mi.name.equals("getDeclaredField") || !mi.desc.equals("(Ljava/lang/String;)Ljava/lang/reflect/Field;")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println("found getDeclaredField!");
|
||||||
|
|
||||||
|
if (insn.getPrevious() == null || insn.getPrevious().getOpcode() != Opcodes.LDC) {
|
||||||
|
System.out.println("- not constant field; skipping");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LdcInsnNode ldcField = (LdcInsnNode) insn.getPrevious();
|
||||||
|
System.out.println("field constant = "+ldcField.cst);
|
||||||
|
if (!(ldcField.cst instanceof String)) {
|
||||||
|
System.out.println("- not field string; skipping");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String fieldName = (String) ldcField.cst;
|
||||||
|
|
||||||
|
if (ldcField.getPrevious() == null || ldcField.getPrevious().getOpcode() != Opcodes.LDC) {
|
||||||
|
System.out.println("- not constant class; skipping");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LdcInsnNode ldcClass = (LdcInsnNode) ldcField.getPrevious();
|
||||||
|
if (!(ldcClass.cst instanceof Type)) {
|
||||||
|
System.out.println("- not class type; skipping");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
System.out.println("class = "+ldcClass.cst);
|
||||||
|
String className = ((Type) ldcClass.cst).getInternalName();
|
||||||
|
|
||||||
|
System.out.println("Remapping "+className+"/"+fieldName);
|
||||||
|
|
||||||
|
String newName = jarMapping.fields.get(className + "/" + fieldName); // TODO: tryClimb etc
|
||||||
|
if (newName != null) {
|
||||||
|
// Change the string literal to the correct name
|
||||||
|
ldcField.cst = newName;
|
||||||
|
//ldcClass.cst = className; // not remapped here - taken care of by JarRemapper
|
||||||
|
System.out.println(" -> to "+newName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -92,6 +92,8 @@ public class SpecialSource {
|
|||||||
.withRequiredArg()
|
.withRequiredArg()
|
||||||
.ofType(File.class);
|
.ofType(File.class);
|
||||||
|
|
||||||
|
//acceptsAll(asList("G", "remap-reflect-field"), "Remap reflection calls to getDeclaredField()"); // TODO
|
||||||
|
|
||||||
acceptsAll(asList("q", "quiet"), "Quiet mode");
|
acceptsAll(asList("q", "quiet"), "Quiet mode");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user