1 /* 2 * ProGuard -- shrinking, optimization, obfuscation, and preverification 3 * of Java bytecode. 4 * 5 * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) 6 * 7 * This program is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License as published by the Free 9 * Software Foundation; either version 2 of the License, or (at your option) 10 * any later version. 11 * 12 * This program is distributed in the hope that it will be useful, but WITHOUT 13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 15 * more details. 16 * 17 * You should have received a copy of the GNU General Public License along 18 * with this program; if not, write to the Free Software Foundation, Inc., 19 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 */ 21 package proguard.optimize; 22 23 import proguard.classfile.*; 24 import proguard.classfile.attribute.*; 25 import proguard.classfile.attribute.visitor.AttributeVisitor; 26 import proguard.classfile.constant.*; 27 import proguard.classfile.constant.visitor.ConstantVisitor; 28 import proguard.classfile.editor.CodeAttributeEditor; 29 import proguard.classfile.instruction.*; 30 import proguard.classfile.instruction.visitor.InstructionVisitor; 31 import proguard.classfile.util.*; 32 import proguard.classfile.visitor.MemberVisitor; 33 34 /** 35 * This AttributeVisitor adds an additional integer parameter to the tweaked 36 * initialization method invocations that it visits. 37 */ 38 public class DuplicateInitializerInvocationFixer 39 extends SimplifiedVisitor 40 implements AttributeVisitor, 41 InstructionVisitor, 42 ConstantVisitor, 43 MemberVisitor 44 { 45 private static final boolean DEBUG = false; 46 47 private final InstructionVisitor extraAddedInstructionVisitor; 48 49 private final CodeAttributeEditor codeAttributeEditor = new CodeAttributeEditor(); 50 51 private String descriptor; 52 private int descriptorLengthDelta; 53 54 55 /** 56 * Creates a new DuplicateInitializerInvocationFixer. 57 */ DuplicateInitializerInvocationFixer()58 public DuplicateInitializerInvocationFixer() 59 { 60 this(null); 61 } 62 63 64 /** 65 * Creates a new DuplicateInitializerInvocationFixer. 66 * @param extraAddedInstructionVisitor an optional extra visitor for all 67 * added instructions. 68 */ DuplicateInitializerInvocationFixer(InstructionVisitor extraAddedInstructionVisitor)69 public DuplicateInitializerInvocationFixer(InstructionVisitor extraAddedInstructionVisitor) 70 { 71 this.extraAddedInstructionVisitor = extraAddedInstructionVisitor; 72 } 73 74 75 // Implementations for AttributeVisitor. 76 visitAnyAttribute(Clazz clazz, Attribute attribute)77 public void visitAnyAttribute(Clazz clazz, Attribute attribute) {} 78 79 visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)80 public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute) 81 { 82 83 // Reset the code changes. 84 codeAttributeEditor.reset(codeAttribute.u4codeLength); 85 86 // Fix any duplicate constructor invocations. 87 codeAttribute.instructionsAccept(clazz, 88 method, 89 this); 90 91 // Apply all accumulated changes to the code. 92 codeAttributeEditor.visitCodeAttribute(clazz, method, codeAttribute); 93 } 94 95 96 // Implementations for InstructionVisitor. 97 visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction)98 public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {} 99 100 visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)101 public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction) 102 { 103 if (constantInstruction.opcode == InstructionConstants.OP_INVOKESPECIAL) 104 { 105 descriptorLengthDelta = 0; 106 clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this); 107 108 if (descriptorLengthDelta > 0) 109 { 110 Instruction extraInstruction = 111 new SimpleInstruction(descriptorLengthDelta == 1 ? 112 InstructionConstants.OP_ICONST_0 : 113 InstructionConstants.OP_ACONST_NULL); 114 115 codeAttributeEditor.insertBeforeInstruction(offset, 116 extraInstruction); 117 118 if (DEBUG) 119 { 120 System.out.println(" ["+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz)+"] Inserting "+extraInstruction.toString()+" before "+constantInstruction.toString(offset)); 121 } 122 123 if (extraAddedInstructionVisitor != null) 124 { 125 extraInstruction.accept(null, null, null, offset, extraAddedInstructionVisitor); 126 } 127 } 128 } 129 } 130 131 132 // Implementations for ConstantVisitor. 133 visitAnyMethodrefConstant(Clazz clazz, RefConstant refConstant)134 public void visitAnyMethodrefConstant(Clazz clazz, RefConstant refConstant) 135 { 136 // Check the referenced constructor descriptor. 137 if (refConstant.getName(clazz).equals(ClassConstants.METHOD_NAME_INIT)) 138 { 139 descriptor = refConstant.getType(clazz); 140 141 refConstant.referencedMemberAccept(this); 142 } 143 } 144 145 146 // Implementations for MemberVisitor. 147 visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)148 public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod) {} 149 150 visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)151 public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod) 152 { 153 descriptorLengthDelta = 154 programMethod.getDescriptor(programClass).length() - descriptor.length(); 155 156 if (DEBUG) 157 { 158 if (descriptorLengthDelta > 0) 159 { 160 System.out.println("DuplicateInitializerInvocationFixer:"); 161 System.out.println(" ["+programClass.getName()+"."+programMethod.getName(programClass)+programMethod.getDescriptor(programClass)+"] ("+ClassUtil.externalClassAccessFlags(programMethod.getAccessFlags())+") referenced by:"); 162 } 163 } 164 } 165 } 166