From bb47046df554bd3f1873d8cb1fce95fa45abe71b Mon Sep 17 00:00:00 2001 From: Oscar Boykin Date: Tue, 3 Oct 2023 12:37:15 -1000 Subject: [PATCH] Revert "Merge MethodSignatureProcessor into JarTransformerChain (#30)" This reverts commit 61aa594d345b129e0412a263996ff3ed129a8a5b. --- .../github/johnynek/jarjar/MainProcessor.java | 4 +- .../MethodSignatureClassTransformer.java | 82 ------------- .../jarjar/MethodSignatureProcessor.java | 114 ++++++++++++++++++ .../johnynek/jarjar/MethodRewriterTest.java | 5 +- 4 files changed, 117 insertions(+), 88 deletions(-) delete mode 100644 src/main/java/com/github/johnynek/jarjar/MethodSignatureClassTransformer.java create mode 100644 src/main/java/com/github/johnynek/jarjar/MethodSignatureProcessor.java diff --git a/src/main/java/com/github/johnynek/jarjar/MainProcessor.java b/src/main/java/com/github/johnynek/jarjar/MainProcessor.java index 0f26caf..13bfe60 100644 --- a/src/main/java/com/github/johnynek/jarjar/MainProcessor.java +++ b/src/main/java/com/github/johnynek/jarjar/MainProcessor.java @@ -76,9 +76,9 @@ public MainProcessor(List patterns, boolean verbose, boolean ski processors.add(new ZapProcessor(zapList)); processors.add(misplacedClassProcessor); processors.add(new JarTransformerChain(new RemappingClassTransformer[] { - new RemappingClassTransformer(pr), - new MethodSignatureClassTransformer(pr), + new RemappingClassTransformer(pr) })); + processors.add(new MethodSignatureProcessor(pr)); processors.add(new ResourceProcessor(pr)); chain = new JarProcessorChain(processors.toArray(new JarProcessor[processors.size()])); } diff --git a/src/main/java/com/github/johnynek/jarjar/MethodSignatureClassTransformer.java b/src/main/java/com/github/johnynek/jarjar/MethodSignatureClassTransformer.java deleted file mode 100644 index d6fa0d4..0000000 --- a/src/main/java/com/github/johnynek/jarjar/MethodSignatureClassTransformer.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.github.johnynek.jarjar; - -import com.github.johnynek.jarjar.util.RemappingClassTransformer; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.commons.Remapper; - -/** - * Remaps string values representing method signatures to use the new package. - * - *

{@link PackageRemapper} is only able to remap string values which exactly match the package - * being renamed. Method signatures are more difficult to detect so this class keeps track of which - * methods definitely take method signatures and remaps those explicitly. - */ -public class MethodSignatureClassTransformer extends RemappingClassTransformer { - - /** - * List of method names which take a method signature as their parameter. - * - *

Right now we assume all these methods take exactly one parameter and that it's a stirng. - */ - private static final Set METHOD_NAMES_WITH_PARAMS_TO_REWRITE = - new HashSet(Arrays.asList("getImplMethodSignature")); - - public MethodSignatureClassTransformer(Remapper remapper) { - super(remapper); - } - - @Override - public MethodVisitor visitMethod( - int access, - java.lang.String name, - java.lang.String descriptor, - java.lang.String signature, - java.lang.String[] exceptions) { - return new MethodSignatureRemapperMethodVisitor( - cv.visitMethod(access, name, descriptor, signature, exceptions)); - } - - private class MethodSignatureRemapperMethodVisitor extends MethodVisitor { - - // Whether to attempt to rewrite the next ldc instruction we see. - // This will be safe because we will only look for methods that will always immediately take - // a string. - private boolean rewriteNextLdcInstruction = false; - - private MethodSignatureRemapperMethodVisitor(MethodVisitor methodVisitor) { - super(Opcodes.ASM9, methodVisitor); - } - - private boolean shouldMarkNextLdcForRewrite(int opcode, String name) { - return opcode == Opcodes.INVOKEVIRTUAL && METHOD_NAMES_WITH_PARAMS_TO_REWRITE.contains(name); - } - - @Override - public void visitMethodInsn(int opcode, String owner, String name, String descriptor) { - rewriteNextLdcInstruction = shouldMarkNextLdcForRewrite(opcode, name); - mv.visitMethodInsn(opcode, owner, name, descriptor); - } - - @Override - public void visitMethodInsn( - int opcode, String owner, String name, String descriptor, boolean isInterface) { - rewriteNextLdcInstruction = shouldMarkNextLdcForRewrite(opcode, name); - mv.visitMethodInsn(opcode, owner, name, descriptor, isInterface); - } - - @Override - public void visitLdcInsn(Object value) { - if (rewriteNextLdcInstruction && value instanceof String) { - rewriteNextLdcInstruction = false; - mv.visitLdcInsn(remapper.mapSignature((String) value, false)); - } else { - mv.visitLdcInsn(value); - } - } - } -} diff --git a/src/main/java/com/github/johnynek/jarjar/MethodSignatureProcessor.java b/src/main/java/com/github/johnynek/jarjar/MethodSignatureProcessor.java new file mode 100644 index 0000000..147077b --- /dev/null +++ b/src/main/java/com/github/johnynek/jarjar/MethodSignatureProcessor.java @@ -0,0 +1,114 @@ +package com.github.johnynek.jarjar; + +import java.io.IOException; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.commons.Remapper; +import com.github.johnynek.jarjar.util.EntryStruct; +import com.github.johnynek.jarjar.util.JarProcessor; + +/** + * Remaps string values representing method signatures to use the new package. + * + *

{@link PackageRemapper} is only able to remap string values which exactly match the package + * being renamed. Method signatures are more difficult to detect so this class keeps track of which + * methods definitely take method signatures and remaps those explicitly. + */ +public class MethodSignatureProcessor implements JarProcessor { + + /** + * List of method names which take a method signature as their parameter. + * + *

Right now we assume all these methods take exactly one parameter and that it's a stirng. + */ + private static final Set METHOD_NAMES_WITH_PARAMS_TO_REWRITE = + new HashSet(Arrays.asList("getImplMethodSignature")); + + private final Remapper remapper; + + public MethodSignatureProcessor(Remapper remapper) { + this.remapper = remapper; + } + + @Override + public boolean process(final EntryStruct struct) throws IOException { + if (!struct.name.endsWith(".class") || struct.skipTransform) { + return true; + } + ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_MAXS); + ClassReader reader; + try { + reader = new ClassReader(struct.data); + } catch (RuntimeException e) { + System.err.println("Unable to read bytecode from " + struct.name); + e.printStackTrace(); + return true; + } + reader.accept(new MethodSignatureRemapperClassVisitor(classWriter), ClassReader.EXPAND_FRAMES); + struct.data = classWriter.toByteArray(); + return true; + } + + private class MethodSignatureRemapperClassVisitor extends ClassVisitor { + + private class MethodSignatureRemapperMethodVisitor extends MethodVisitor { + + // Whether to attempt to rewrite the next ldc instruction we see. + // This will be safe because we will only look for methods that will always immediately take + // a string. + private boolean rewriteNextLdcInstruction = false; + + private MethodSignatureRemapperMethodVisitor(MethodVisitor methodVisitor) { + super(Opcodes.ASM9, methodVisitor); + } + + private boolean shouldMarkNextLdcForRewrite(int opcode, String name) { + return opcode == Opcodes.INVOKEVIRTUAL && METHOD_NAMES_WITH_PARAMS_TO_REWRITE.contains(name); + } + + @Override + public void visitMethodInsn(int opcode, String owner, String name, String descriptor) { + rewriteNextLdcInstruction = shouldMarkNextLdcForRewrite(opcode, name); + mv.visitMethodInsn(opcode, owner, name, descriptor); + } + + @Override + public void visitMethodInsn( + int opcode, String owner, String name, String descriptor, boolean isInterface) { + rewriteNextLdcInstruction = shouldMarkNextLdcForRewrite(opcode, name); + mv.visitMethodInsn(opcode, owner, name, descriptor, isInterface); + } + + @Override + public void visitLdcInsn(Object value) { + if (rewriteNextLdcInstruction && value instanceof String) { + rewriteNextLdcInstruction = false; + mv.visitLdcInsn(remapper.mapSignature((String) value, false)); + } else { + mv.visitLdcInsn(value); + } + } + } + + public MethodSignatureRemapperClassVisitor(ClassVisitor classVisitor) { + super(Opcodes.ASM9, classVisitor); + } + + @Override + public MethodVisitor visitMethod( + int access, + java.lang.String name, + java.lang.String descriptor, + java.lang.String signature, + java.lang.String[] exceptions) { + return new MethodSignatureRemapperMethodVisitor( + cv.visitMethod(access, name, descriptor, signature, exceptions)); + } + } +} diff --git a/src/test/java/com/github/johnynek/jarjar/MethodRewriterTest.java b/src/test/java/com/github/johnynek/jarjar/MethodRewriterTest.java index b3125e6..0b66502 100644 --- a/src/test/java/com/github/johnynek/jarjar/MethodRewriterTest.java +++ b/src/test/java/com/github/johnynek/jarjar/MethodRewriterTest.java @@ -1,7 +1,5 @@ package com.github.johnynek.jarjar; -import com.github.johnynek.jarjar.util.JarTransformerChain; -import com.github.johnynek.jarjar.util.RemappingClassTransformer; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; @@ -67,8 +65,7 @@ public void testRewriteMethod() throws IOException { Rule rule = new Rule(); rule.setPattern("com.google.**"); rule.setResult("com.googleshaded.@1"); - new JarTransformerChain(new RemappingClassTransformer[]{ - new MethodSignatureClassTransformer(new PackageRemapper(Arrays.asList(rule), false))}) + new MethodSignatureProcessor(new PackageRemapper(Arrays.asList(rule), false)) .process(entryStruct); new ClassReader(entryStruct.data) .accept(new VerifyingClassVisitor(), ClassReader.EXPAND_FRAMES);