diff --git a/src/main/java/net/md_5/specialsource/JarMapping.java b/src/main/java/net/md_5/specialsource/JarMapping.java index bf6d71b..0f19c77 100644 --- a/src/main/java/net/md_5/specialsource/JarMapping.java +++ b/src/main/java/net/md_5/specialsource/JarMapping.java @@ -39,6 +39,7 @@ import net.md_5.specialsource.transformer.MethodDescriptor; import net.md_5.specialsource.transformer.ChainingTransformer; import net.md_5.specialsource.transformer.MappingTransformer; import java.io.*; +import java.lang.reflect.Modifier; import java.util.*; public class JarMapping { @@ -90,11 +91,11 @@ public class JarMapping { return false; } - public String tryClimb(Map map, NodeType type, String owner, String name) { + public String tryClimb(Map map, NodeType type, String owner, String name, int access) { String key = owner + "/" + name; String mapped = map.get(key); - if (mapped == null) { + if (mapped == null && !Modifier.isPrivate(access) && !Modifier.isStatic(access)) { Collection parents = null; if (inheritanceMap.hasParents(owner)) { @@ -107,7 +108,7 @@ public class JarMapping { if (parents != null) { // climb the inheritance tree for (String parent : parents) { - mapped = tryClimb(map, type, parent, name); + mapped = tryClimb(map, type, parent, name, access); if (mapped != null) { return mapped; } diff --git a/src/main/java/net/md_5/specialsource/JarRemapper.java b/src/main/java/net/md_5/specialsource/JarRemapper.java index 68c86fc..728b98d 100644 --- a/src/main/java/net/md_5/specialsource/JarRemapper.java +++ b/src/main/java/net/md_5/specialsource/JarRemapper.java @@ -45,7 +45,6 @@ import org.objectweb.asm.FieldVisitor; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.commons.Remapper; import org.objectweb.asm.commons.RemappingClassAdapter; -import org.objectweb.asm.commons.RemappingFieldAdapter; import org.objectweb.asm.tree.ClassNode; import static org.objectweb.asm.ClassWriter.*; @@ -71,8 +70,8 @@ public class JarRemapper extends Remapper { /** * Enable or disable API-only generation. * - * If enabled, only symbols will be output to the remapped jar, suitable for use as a library. - * Code and resources will be excluded. + * If enabled, only symbols will be output to the remapped jar, suitable for + * use as a library. Code and resources will be excluded. */ public void setGenerateAPI(boolean generateAPI) { if (generateAPI) { @@ -150,13 +149,13 @@ public class JarRemapper extends Remapper { @Override public String mapFieldName(String owner, String name, String desc) { - String mapped = jarMapping.tryClimb(jarMapping.fields, NodeType.FIELD, owner, name); + String mapped = jarMapping.tryClimb(jarMapping.fields, NodeType.FIELD, owner, name, 0); return mapped == null ? name : mapped; } @Override - public String mapMethodName(String owner, String name, String desc) { - String mapped = jarMapping.tryClimb(jarMapping.methods, NodeType.METHOD, owner, name + " " + desc); + public String mapMethodName(String owner, String name, String desc, int access) { + String mapped = jarMapping.tryClimb(jarMapping.methods, NodeType.METHOD, owner, name + " " + desc, access); return mapped == null ? name : mapped; } @@ -189,7 +188,9 @@ public class JarRemapper extends Remapper { continue; } else { // copy other resources - if (!copyResources) continue; // unless generating an API + if (!copyResources) { + continue; // unless generating an API + } entry = new JarEntry(name); ByteArrayOutputStream buffer = new ByteArrayOutputStream(); @@ -234,62 +235,78 @@ public class JarRemapper extends Remapper { } ClassNode node = new ClassNode(); - RemappingClassAdapter mapper = new RemappingClassAdapter(node, this) - { + RemappingClassAdapter mapper = new RemappingClassAdapter(node, this) { @Override - protected MethodVisitor createRemappingMethodAdapter(int access, String newDesc, MethodVisitor sup) - { + public MethodVisitor visitMethod(int access, String name, String desc, + String signature, String[] exceptions) { + String newDesc = remapper.mapMethodDesc(desc); + MethodVisitor mv = super.visitMethod(access, remapper.mapMethodName( + className, name, desc, access), newDesc, remapper.mapSignature( + signature, false), + exceptions == null ? null : remapper.mapTypes(exceptions)); + return mv == null ? null : createRemappingMethodAdapter(access, + newDesc, mv); + } + + @Override + protected MethodVisitor createRemappingMethodAdapter(int access, String newDesc, MethodVisitor sup) { MethodVisitor remap = new UnsortedRemappingMethodAdapter(access, newDesc, sup, remapper); - return new MethodVisitor(Opcodes.ASM4, remap) - { + return new MethodVisitor(Opcodes.ASM4, remap) { @Override - public void visitAttribute(Attribute attr) - { - if (SpecialSource.kill_lvt && attr.type.equals("LocalVariableTable")) return; - if (SpecialSource.kill_generics && attr.type.equals("LocalVariableTypeTable")) return; - if (mv != null) mv.visitAttribute(attr); + public void visitAttribute(Attribute attr) { + if (SpecialSource.kill_lvt && attr.type.equals("LocalVariableTable")) { + return; + } + if (SpecialSource.kill_generics && attr.type.equals("LocalVariableTypeTable")) { + return; + } + if (mv != null) { + mv.visitAttribute(attr); + } } }; } @Override - protected FieldVisitor createRemappingFieldAdapter(FieldVisitor sup) - { - FieldVisitor remap = new RemappingFieldAdapter(sup, remapper); - return new FieldVisitor(Opcodes.ASM4, sup) - { + protected FieldVisitor createRemappingFieldAdapter(FieldVisitor sup) { + return new FieldVisitor(Opcodes.ASM4, sup) { @Override - public void visitAttribute(Attribute attr) - { - if (SpecialSource.kill_lvt && attr.type.equals("LocalVariableTable")) return; - if (SpecialSource.kill_generics && attr.type.equals("LocalVariableTypeTable")) return; - if (fv != null) fv.visitAttribute(attr); + public void visitAttribute(Attribute attr) { + if (SpecialSource.kill_lvt && attr.type.equals("LocalVariableTable")) { + return; + } + if (SpecialSource.kill_generics && attr.type.equals("LocalVariableTypeTable")) { + return; + } + if (fv != null) { + fv.visitAttribute(attr); + } } }; } @Override - public void visitSource(String source, String debug) - { - if (!SpecialSource.kill_source && cv != null) - { + public void visitSource(String source, String debug) { + if (!SpecialSource.kill_source && cv != null) { cv.visitSource(source, debug); } } @Override - public void visitAttribute(Attribute attr) - { - if (SpecialSource.kill_generics && attr.type.equals("Signature")) return; - if (cv != null) cv.visitAttribute(attr); + public void visitAttribute(Attribute attr) { + if (SpecialSource.kill_generics && attr.type.equals("Signature")) { + return; + } + if (cv != null) { + cv.visitAttribute(attr); + } } }; reader.accept(mapper, readerFlags); ClassWriter wr = new ClassWriter(writerFlags); node.accept(wr); - if (SpecialSource.identifier != null) - { + if (SpecialSource.identifier != null) { wr.newUTF8(SpecialSource.identifier); } return wr.toByteArray(); diff --git a/src/main/java/net/md_5/specialsource/RemapperPreprocessor.java b/src/main/java/net/md_5/specialsource/RemapperPreprocessor.java index 591d71f..378ef08 100644 --- a/src/main/java/net/md_5/specialsource/RemapperPreprocessor.java +++ b/src/main/java/net/md_5/specialsource/RemapperPreprocessor.java @@ -227,7 +227,7 @@ public class RemapperPreprocessor { } String className = ((Type) ldcClass.cst).getInternalName(); - String newName = jarMapping.tryClimb(jarMapping.fields, NodeType.FIELD, className, fieldName); + String newName = jarMapping.tryClimb(jarMapping.fields, NodeType.FIELD, className, fieldName, 0); logR("Remapping " + className + "/" + fieldName + " -> " + newName); if (newName != null) { diff --git a/src/main/java/org/objectweb/asm/commons/Remapper.java b/src/main/java/org/objectweb/asm/commons/Remapper.java new file mode 100644 index 0000000..8b04b4a --- /dev/null +++ b/src/main/java/org/objectweb/asm/commons/Remapper.java @@ -0,0 +1,229 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2011 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.objectweb.asm.commons; + +import org.objectweb.asm.Handle; +import org.objectweb.asm.Type; +import org.objectweb.asm.signature.SignatureReader; +import org.objectweb.asm.signature.SignatureVisitor; +import org.objectweb.asm.signature.SignatureWriter; + +/** + * A class responsible for remapping types and names. Subclasses can override + * the following methods: + * + *
    + *
  • {@link #map(String)} - map type
  • + *
  • {@link #mapFieldName(String, String, String)} - map field name
  • + *
  • {@link #mapMethodName(String, String, String)} - map method name
  • + *
+ * + * @author Eugene Kuleshov + */ +public abstract class Remapper { + + public String mapDesc(String desc) { + Type t = Type.getType(desc); + switch (t.getSort()) { + case Type.ARRAY: + String s = mapDesc(t.getElementType().getDescriptor()); + for (int i = 0; i < t.getDimensions(); ++i) { + s = '[' + s; + } + return s; + case Type.OBJECT: + String newType = map(t.getInternalName()); + if (newType != null) { + return 'L' + newType + ';'; + } + } + return desc; + } + + private Type mapType(Type t) { + switch (t.getSort()) { + case Type.ARRAY: + String s = mapDesc(t.getElementType().getDescriptor()); + for (int i = 0; i < t.getDimensions(); ++i) { + s = '[' + s; + } + return Type.getType(s); + case Type.OBJECT: + s = map(t.getInternalName()); + return s != null ? Type.getObjectType(s) : t; + case Type.METHOD: + return Type.getMethodType(mapMethodDesc(t.getDescriptor())); + } + return t; + } + + public String mapType(String type) { + if (type == null) { + return null; + } + return mapType(Type.getObjectType(type)).getInternalName(); + } + + public String[] mapTypes(String[] types) { + String[] newTypes = null; + boolean needMapping = false; + for (int i = 0; i < types.length; i++) { + String type = types[i]; + String newType = map(type); + if (newType != null && newTypes == null) { + newTypes = new String[types.length]; + if (i > 0) { + System.arraycopy(types, 0, newTypes, 0, i); + } + needMapping = true; + } + if (needMapping) { + newTypes[i] = newType == null ? type : newType; + } + } + return needMapping ? newTypes : types; + } + + public String mapMethodDesc(String desc) { + if ("()V".equals(desc)) { + return desc; + } + + Type[] args = Type.getArgumentTypes(desc); + StringBuffer s = new StringBuffer("("); + for (int i = 0; i < args.length; i++) { + s.append(mapDesc(args[i].getDescriptor())); + } + Type returnType = Type.getReturnType(desc); + if (returnType == Type.VOID_TYPE) { + s.append(")V"); + return s.toString(); + } + s.append(')').append(mapDesc(returnType.getDescriptor())); + return s.toString(); + } + + public Object mapValue(Object value) { + if (value instanceof Type) { + return mapType((Type) value); + } + if (value instanceof Handle) { + Handle h = (Handle) value; + return new Handle(h.getTag(), mapType(h.getOwner()), mapMethodName( + h.getOwner(), h.getName(), h.getDesc()), + mapMethodDesc(h.getDesc())); + } + return value; + } + + /** + * + * @param typeSignature + * true if signature is a FieldTypeSignature, such as the + * signature parameter of the ClassVisitor.visitField or + * MethodVisitor.visitLocalVariable methods + */ + public String mapSignature(String signature, boolean typeSignature) { + if (signature == null) { + return null; + } + SignatureReader r = new SignatureReader(signature); + SignatureWriter w = new SignatureWriter(); + SignatureVisitor a = createRemappingSignatureAdapter(w); + if (typeSignature) { + r.acceptType(a); + } else { + r.accept(a); + } + return w.toString(); + } + + protected SignatureVisitor createRemappingSignatureAdapter( + SignatureVisitor v) { + return new RemappingSignatureAdapter(v, this); + } + + /** + * Map method name to the new name. Subclasses can override. + * + * @param owner + * owner of the method. + * @param name + * name of the method. + * @param desc + * descriptor of the method. + * @return new name of the method + */ + public String mapMethodName(String owner, String name, String desc) { + return mapMethodName(owner, name, desc, 0); // Spigot + } + + // SS Start + public String mapMethodName(String owner, String name, String desc, int access) { + return name; + } + // SS End + + /** + * Map invokedynamic method name to the new name. Subclasses can override. + * + * @param name + * name of the invokedynamic. + * @param desc + * descriptor of the invokedynamic. + * @return new invokdynamic name. + */ + public String mapInvokeDynamicMethodName(String name, String desc) { + return name; + } + + /** + * Map field name to the new name. Subclasses can override. + * + * @param owner + * owner of the field. + * @param name + * name of the field + * @param desc + * descriptor of the field + * @return new name of the field. + */ + public String mapFieldName(String owner, String name, String desc) { + return name; + } + + /** + * Map type name to the new name. Subclasses can override. + */ + public String map(String typeName) { + return typeName; + } +}