Initial implementation of field reflection remapper

Remaps the string constant in class.getDeclaredField("fieldname")
This commit is contained in:
Agaricus 2013-02-05 21:09:08 -08:00
parent 874e759a9d
commit 6e34774a46
2 changed files with 93 additions and 0 deletions

View 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);
}
}
}

View File

@ -92,6 +92,8 @@ public class SpecialSource {
.withRequiredArg()
.ofType(File.class);
//acceptsAll(asList("G", "remap-reflect-field"), "Remap reflection calls to getDeclaredField()"); // TODO
acceptsAll(asList("q", "quiet"), "Quiet mode");
}
};