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.annotation.*; 26 import proguard.classfile.attribute.preverification.*; 27 import proguard.classfile.attribute.visitor.AttributeVisitor; 28 import proguard.classfile.util.ClassUtil; 29 30 /** 31 * This AttributeVisitor delegates its call to another AttributeVisitor, and 32 * prints out the code if the other visitor has changed it. 33 * 34 * @author Eric Lafortune 35 */ 36 public class ChangedCodePrinter 37 implements AttributeVisitor 38 { 39 private final AttributeVisitor attributeVisitor; 40 41 ChangedCodePrinter(AttributeVisitor attributeVisitor)42 public ChangedCodePrinter(AttributeVisitor attributeVisitor) 43 { 44 this.attributeVisitor = attributeVisitor; 45 } 46 47 48 // Implementations for AttributeVisitor. 49 visitUnknownAttribute(Clazz clazz, UnknownAttribute unknownAttribute)50 public void visitUnknownAttribute(Clazz clazz, UnknownAttribute unknownAttribute) 51 { 52 attributeVisitor.visitUnknownAttribute(clazz, unknownAttribute); 53 } 54 55 visitBootstrapMethodsAttribute(Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute)56 public void visitBootstrapMethodsAttribute(Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute) 57 { 58 attributeVisitor.visitBootstrapMethodsAttribute(clazz, bootstrapMethodsAttribute); 59 } 60 61 visitSourceFileAttribute(Clazz clazz, SourceFileAttribute sourceFileAttribute)62 public void visitSourceFileAttribute(Clazz clazz, SourceFileAttribute sourceFileAttribute) 63 { 64 attributeVisitor.visitSourceFileAttribute(clazz, sourceFileAttribute); 65 } 66 67 visitSourceDirAttribute(Clazz clazz, SourceDirAttribute sourceDirAttribute)68 public void visitSourceDirAttribute(Clazz clazz, SourceDirAttribute sourceDirAttribute) 69 { 70 attributeVisitor.visitSourceDirAttribute(clazz, sourceDirAttribute); 71 } 72 73 visitInnerClassesAttribute(Clazz clazz, InnerClassesAttribute innerClassesAttribute)74 public void visitInnerClassesAttribute(Clazz clazz, InnerClassesAttribute innerClassesAttribute) 75 { 76 attributeVisitor.visitInnerClassesAttribute(clazz, innerClassesAttribute); 77 } 78 79 visitEnclosingMethodAttribute(Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute)80 public void visitEnclosingMethodAttribute(Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute) 81 { 82 attributeVisitor.visitEnclosingMethodAttribute(clazz, enclosingMethodAttribute); 83 } 84 85 visitDeprecatedAttribute(Clazz clazz, DeprecatedAttribute deprecatedAttribute)86 public void visitDeprecatedAttribute(Clazz clazz, DeprecatedAttribute deprecatedAttribute) 87 { 88 attributeVisitor.visitDeprecatedAttribute(clazz, deprecatedAttribute); 89 } 90 91 visitSyntheticAttribute(Clazz clazz, SyntheticAttribute syntheticAttribute)92 public void visitSyntheticAttribute(Clazz clazz, SyntheticAttribute syntheticAttribute) 93 { 94 attributeVisitor.visitSyntheticAttribute(clazz, syntheticAttribute); 95 } 96 97 visitSignatureAttribute(Clazz clazz, SignatureAttribute syntheticAttribute)98 public void visitSignatureAttribute(Clazz clazz, SignatureAttribute syntheticAttribute) 99 { 100 attributeVisitor.visitSignatureAttribute(clazz, syntheticAttribute); 101 } 102 103 visitDeprecatedAttribute(Clazz clazz, Field field, DeprecatedAttribute deprecatedAttribute)104 public void visitDeprecatedAttribute(Clazz clazz, Field field, DeprecatedAttribute deprecatedAttribute) 105 { 106 attributeVisitor.visitDeprecatedAttribute(clazz, field, deprecatedAttribute); 107 } 108 109 visitSyntheticAttribute(Clazz clazz, Field field, SyntheticAttribute syntheticAttribute)110 public void visitSyntheticAttribute(Clazz clazz, Field field, SyntheticAttribute syntheticAttribute) 111 { 112 attributeVisitor.visitSyntheticAttribute(clazz, field, syntheticAttribute); 113 } 114 115 visitSignatureAttribute(Clazz clazz, Field field, SignatureAttribute syntheticAttribute)116 public void visitSignatureAttribute(Clazz clazz, Field field, SignatureAttribute syntheticAttribute) 117 { 118 attributeVisitor.visitSignatureAttribute(clazz, field, syntheticAttribute); 119 } 120 121 visitDeprecatedAttribute(Clazz clazz, Method method, DeprecatedAttribute deprecatedAttribute)122 public void visitDeprecatedAttribute(Clazz clazz, Method method, DeprecatedAttribute deprecatedAttribute) 123 { 124 attributeVisitor.visitDeprecatedAttribute(clazz, method, deprecatedAttribute); 125 } 126 127 visitSyntheticAttribute(Clazz clazz, Method method, SyntheticAttribute syntheticAttribute)128 public void visitSyntheticAttribute(Clazz clazz, Method method, SyntheticAttribute syntheticAttribute) 129 { 130 attributeVisitor.visitSyntheticAttribute(clazz, method, syntheticAttribute); 131 } 132 133 visitSignatureAttribute(Clazz clazz, Method method, SignatureAttribute syntheticAttribute)134 public void visitSignatureAttribute(Clazz clazz, Method method, SignatureAttribute syntheticAttribute) 135 { 136 attributeVisitor.visitSignatureAttribute(clazz, method, syntheticAttribute); 137 } 138 139 visitConstantValueAttribute(Clazz clazz, Field field, ConstantValueAttribute constantValueAttribute)140 public void visitConstantValueAttribute(Clazz clazz, Field field, ConstantValueAttribute constantValueAttribute) 141 { 142 attributeVisitor.visitConstantValueAttribute(clazz, field, constantValueAttribute); 143 } 144 145 visitMethodParametersAttribute(Clazz clazz, Method method, MethodParametersAttribute exceptionsAttribute)146 public void visitMethodParametersAttribute(Clazz clazz, Method method, MethodParametersAttribute exceptionsAttribute) 147 { 148 attributeVisitor.visitMethodParametersAttribute(clazz, method, exceptionsAttribute); 149 } 150 151 visitExceptionsAttribute(Clazz clazz, Method method, ExceptionsAttribute exceptionsAttribute)152 public void visitExceptionsAttribute(Clazz clazz, Method method, ExceptionsAttribute exceptionsAttribute) 153 { 154 attributeVisitor.visitExceptionsAttribute(clazz, method, exceptionsAttribute); 155 } 156 157 visitStackMapAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapAttribute stackMapAttribute)158 public void visitStackMapAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapAttribute stackMapAttribute) 159 { 160 attributeVisitor.visitStackMapAttribute(clazz, method, codeAttribute, stackMapAttribute); 161 } 162 163 visitStackMapTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapTableAttribute stackMapTableAttribute)164 public void visitStackMapTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapTableAttribute stackMapTableAttribute) 165 { 166 attributeVisitor.visitStackMapTableAttribute(clazz, method, codeAttribute, stackMapTableAttribute); 167 } 168 169 visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute)170 public void visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute) 171 { 172 attributeVisitor.visitLineNumberTableAttribute(clazz, method, codeAttribute, lineNumberTableAttribute); 173 } 174 175 visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute)176 public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute) 177 { 178 attributeVisitor.visitLocalVariableTableAttribute(clazz, method, codeAttribute, localVariableTableAttribute); 179 } 180 181 visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute)182 public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute) 183 { 184 attributeVisitor.visitLocalVariableTypeTableAttribute(clazz, method, codeAttribute, localVariableTypeTableAttribute); 185 } 186 187 visitRuntimeVisibleAnnotationsAttribute(Clazz clazz, RuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute)188 public void visitRuntimeVisibleAnnotationsAttribute(Clazz clazz, RuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute) 189 { 190 attributeVisitor.visitRuntimeVisibleAnnotationsAttribute(clazz, runtimeVisibleAnnotationsAttribute); 191 } 192 193 visitRuntimeInvisibleAnnotationsAttribute(Clazz clazz, RuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute)194 public void visitRuntimeInvisibleAnnotationsAttribute(Clazz clazz, RuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute) 195 { 196 attributeVisitor.visitRuntimeInvisibleAnnotationsAttribute(clazz, runtimeInvisibleAnnotationsAttribute); 197 } 198 199 visitRuntimeVisibleAnnotationsAttribute(Clazz clazz, Field field, RuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute)200 public void visitRuntimeVisibleAnnotationsAttribute(Clazz clazz, Field field, RuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute) 201 { 202 attributeVisitor.visitRuntimeVisibleAnnotationsAttribute(clazz, field, runtimeVisibleAnnotationsAttribute); 203 } 204 205 visitRuntimeInvisibleAnnotationsAttribute(Clazz clazz, Field field, RuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute)206 public void visitRuntimeInvisibleAnnotationsAttribute(Clazz clazz, Field field, RuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute) 207 { 208 attributeVisitor.visitRuntimeInvisibleAnnotationsAttribute(clazz, field, runtimeInvisibleAnnotationsAttribute); 209 } 210 211 visitRuntimeVisibleAnnotationsAttribute(Clazz clazz, Method method, RuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute)212 public void visitRuntimeVisibleAnnotationsAttribute(Clazz clazz, Method method, RuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute) 213 { 214 attributeVisitor.visitRuntimeVisibleAnnotationsAttribute(clazz, method, runtimeVisibleAnnotationsAttribute); 215 } 216 217 visitRuntimeInvisibleAnnotationsAttribute(Clazz clazz, Method method, RuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute)218 public void visitRuntimeInvisibleAnnotationsAttribute(Clazz clazz, Method method, RuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute) 219 { 220 attributeVisitor.visitRuntimeInvisibleAnnotationsAttribute(clazz, method, runtimeInvisibleAnnotationsAttribute); 221 } 222 223 visitRuntimeVisibleParameterAnnotationsAttribute(Clazz clazz, Method method, RuntimeVisibleParameterAnnotationsAttribute runtimeVisibleParameterAnnotationsAttribute)224 public void visitRuntimeVisibleParameterAnnotationsAttribute(Clazz clazz, Method method, RuntimeVisibleParameterAnnotationsAttribute runtimeVisibleParameterAnnotationsAttribute) 225 { 226 attributeVisitor.visitRuntimeVisibleParameterAnnotationsAttribute(clazz, method, runtimeVisibleParameterAnnotationsAttribute); 227 } 228 229 visitRuntimeInvisibleParameterAnnotationsAttribute(Clazz clazz, Method method, RuntimeInvisibleParameterAnnotationsAttribute runtimeInvisibleParameterAnnotationsAttribute)230 public void visitRuntimeInvisibleParameterAnnotationsAttribute(Clazz clazz, Method method, RuntimeInvisibleParameterAnnotationsAttribute runtimeInvisibleParameterAnnotationsAttribute) 231 { 232 attributeVisitor.visitRuntimeInvisibleParameterAnnotationsAttribute(clazz, method, runtimeInvisibleParameterAnnotationsAttribute); 233 } 234 235 visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute)236 public void visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute) 237 { 238 attributeVisitor.visitRuntimeVisibleTypeAnnotationsAttribute(clazz, runtimeVisibleTypeAnnotationsAttribute); 239 } 240 241 visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, Field field, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute)242 public void visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, Field field, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute) 243 { 244 attributeVisitor.visitRuntimeVisibleTypeAnnotationsAttribute(clazz, field, runtimeVisibleTypeAnnotationsAttribute); 245 } 246 247 visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, Method method, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute)248 public void visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, Method method, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute) 249 { 250 attributeVisitor.visitRuntimeVisibleTypeAnnotationsAttribute(clazz, method, runtimeVisibleTypeAnnotationsAttribute); 251 } 252 253 visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute)254 public void visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute) 255 { 256 attributeVisitor.visitRuntimeVisibleTypeAnnotationsAttribute(clazz, method, codeAttribute, runtimeVisibleTypeAnnotationsAttribute); 257 } 258 259 visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute)260 public void visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute) 261 { 262 attributeVisitor.visitRuntimeInvisibleTypeAnnotationsAttribute(clazz, runtimeInvisibleTypeAnnotationsAttribute); 263 } 264 265 visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, Field field, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute)266 public void visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, Field field, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute) 267 { 268 attributeVisitor.visitRuntimeInvisibleTypeAnnotationsAttribute(clazz, field, runtimeInvisibleTypeAnnotationsAttribute); 269 } 270 271 visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, Method method, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute)272 public void visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, Method method, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute) 273 { 274 attributeVisitor.visitRuntimeInvisibleTypeAnnotationsAttribute(clazz, method, runtimeInvisibleTypeAnnotationsAttribute); 275 } 276 277 visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute)278 public void visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute) 279 { 280 attributeVisitor.visitRuntimeInvisibleTypeAnnotationsAttribute(clazz, method, codeAttribute, runtimeInvisibleTypeAnnotationsAttribute); 281 } 282 283 visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute)284 public void visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute) 285 { 286 attributeVisitor.visitAnnotationDefaultAttribute(clazz, method, annotationDefaultAttribute); 287 } 288 289 visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)290 public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute) 291 { 292 byte[] code = codeAttribute.code; 293 byte[] oldCode = new byte[code.length]; 294 295 // Copy the current code. 296 System.arraycopy(code, 0, oldCode, 0, codeAttribute.u4codeLength); 297 298 // Delegate to the real visitor. 299 attributeVisitor.visitCodeAttribute(clazz, method, codeAttribute); 300 301 // Check if the code has changed. 302 if (codeHasChanged(codeAttribute, oldCode)) 303 { 304 printChangedCode(clazz, method, codeAttribute, oldCode); 305 } 306 } 307 308 309 // Small utility methods. 310 codeHasChanged(CodeAttribute codeAttribute, byte[] oldCode)311 private boolean codeHasChanged(CodeAttribute codeAttribute, byte[] oldCode) 312 { 313 if (oldCode.length != codeAttribute.u4codeLength) 314 { 315 return true; 316 } 317 318 for (int index = 0; index < codeAttribute.u4codeLength; index++) 319 { 320 if (oldCode[index] != codeAttribute.code[index]) 321 { 322 return true; 323 } 324 } 325 326 return false; 327 } 328 329 printChangedCode(Clazz clazz, Method method, CodeAttribute codeAttribute, byte[] oldCode)330 private void printChangedCode(Clazz clazz, 331 Method method, 332 CodeAttribute codeAttribute, 333 byte[] oldCode) 334 { 335 System.out.println("Class "+ClassUtil.externalClassName(clazz.getName())); 336 System.out.println("Method "+ClassUtil.externalFullMethodDescription(clazz.getName(), 337 0, 338 method.getName(clazz), 339 method.getDescriptor(clazz))); 340 341 for (int index = 0; index < codeAttribute.u4codeLength; index++) 342 { 343 System.out.println( 344 (oldCode[index] == codeAttribute.code[index]? " -- ":" => ")+ 345 index+": "+ 346 Integer.toHexString(0x100|oldCode[index] &0xff).substring(1)+" "+ 347 Integer.toHexString(0x100|codeAttribute.code[index]&0xff).substring(1)); 348 } 349 } 350 } 351