1 21 package proguard.classfile.editor; 22 23 import proguard.classfile.*; 24 import proguard.classfile.attribute.*; 25 import proguard.classfile.attribute.annotation.*; 26 import proguard.classfile.attribute.annotation.visitor.*; 27 import proguard.classfile.attribute.visitor.AttributeVisitor; 28 import proguard.classfile.constant.*; 29 import proguard.classfile.constant.visitor.ConstantVisitor; 30 import proguard.classfile.util.*; 31 import proguard.classfile.visitor.*; 32 33 39 public class MemberReferenceFixer 40 extends SimplifiedVisitor 41 implements ClassVisitor, 42 ConstantVisitor, 43 MemberVisitor, 44 AttributeVisitor, 45 AnnotationVisitor, 46 ElementValueVisitor 47 { 48 private static final boolean DEBUG = false; 49 50 51 private ConstantPoolEditor constantPoolEditor = new ConstantPoolEditor(); 52 private StackSizeUpdater stackSizeUpdater = new StackSizeUpdater(); 53 54 private int constantIndex; 56 57 private boolean isInterfaceMethod; 59 private boolean stackSizesMayHaveChanged; 60 61 62 64 public void visitProgramClass(ProgramClass programClass) 65 { 66 stackSizesMayHaveChanged = false; 67 68 for (int index = 1; index < programClass.u2constantPoolCount; index++) 70 { 71 Constant constant = programClass.constantPool[index]; 72 if (constant != null) 73 { 74 this.constantIndex = index; 76 77 constant.accept(programClass, this); 78 } 79 } 80 81 programClass.fieldsAccept(this); 83 programClass.methodsAccept(this); 84 85 programClass.attributesAccept(this); 87 } 88 89 90 92 public void visitAnyConstant(Clazz clazz, Constant constant) {} 93 94 95 public void visitStringConstant(Clazz clazz, StringConstant stringConstant) 96 { 97 Member referencedMember = stringConstant.referencedMember; 100 if (referencedMember != null) 101 { 102 Clazz referencedClass = stringConstant.referencedClass; 103 104 String newName = referencedMember.getName(referencedClass); 106 107 if (!stringConstant.getString(clazz).equals(newName)) 108 { 109 if (DEBUG) 110 { 111 debug(clazz, stringConstant, referencedClass, referencedMember); 112 } 113 114 stringConstant.u2stringIndex = 116 constantPoolEditor.addUtf8Constant((ProgramClass)clazz, 117 newName); 118 } 119 } 120 } 121 122 123 public void visitFieldrefConstant(Clazz clazz, FieldrefConstant fieldrefConstant) 124 { 125 Member referencedMember = fieldrefConstant.referencedMember; 127 if (referencedMember != null) 128 { 129 Clazz referencedClass = fieldrefConstant.referencedClass; 130 131 String newName = referencedMember.getName(referencedClass); 133 String newType = referencedMember.getDescriptor(referencedClass); 134 135 if (!fieldrefConstant.getName(clazz).equals(newName) || 136 !fieldrefConstant.getType(clazz).equals(newType)) 137 { 138 if (DEBUG) 139 { 140 debug(clazz, fieldrefConstant, referencedClass, referencedMember); 141 } 142 143 fieldrefConstant.u2nameAndTypeIndex = 145 constantPoolEditor.addNameAndTypeConstant((ProgramClass)clazz, 146 newName, 147 newType); 148 } 149 } 150 } 151 152 153 public void visitInterfaceMethodrefConstant(Clazz clazz, InterfaceMethodrefConstant interfaceMethodrefConstant) 154 { 155 Member referencedMember = interfaceMethodrefConstant.referencedMember; 157 if (referencedMember != null) 158 { 159 Clazz referencedClass = interfaceMethodrefConstant.referencedClass; 160 161 String newName = referencedMember.getName(referencedClass); 163 String newType = referencedMember.getDescriptor(referencedClass); 164 165 if (!interfaceMethodrefConstant.getName(clazz).equals(newName) || 166 !interfaceMethodrefConstant.getType(clazz).equals(newType)) 167 { 168 if (DEBUG) 169 { 170 debug(clazz, interfaceMethodrefConstant, referencedClass, referencedMember); 171 } 172 173 interfaceMethodrefConstant.u2nameAndTypeIndex = 175 constantPoolEditor.addNameAndTypeConstant((ProgramClass)clazz, 176 newName, 177 newType); 178 179 stackSizesMayHaveChanged = true; 182 } 183 184 isInterfaceMethod = true; 186 clazz.constantPoolEntryAccept(interfaceMethodrefConstant.u2classIndex, this); 187 188 if (!isInterfaceMethod) 190 { 191 if (DEBUG) 192 { 193 System.out.println("MemberReferenceFixer:"); 194 System.out.println(" Class file = "+clazz.getName()); 195 System.out.println(" Ref class = "+referencedClass.getName()); 196 System.out.println(" Ref method = "+interfaceMethodrefConstant.getName(clazz)+interfaceMethodrefConstant.getType(clazz)); 197 System.out.println(" -> ordinary method"); 198 } 199 200 ((ProgramClass)clazz).constantPool[this.constantIndex] = 202 new MethodrefConstant(interfaceMethodrefConstant.u2classIndex, 203 interfaceMethodrefConstant.u2nameAndTypeIndex, 204 referencedClass, 205 referencedMember); 206 } 207 } 208 } 209 210 211 public void visitMethodrefConstant(Clazz clazz, MethodrefConstant methodrefConstant) 212 { 213 Member referencedMember = methodrefConstant.referencedMember; 215 if (referencedMember != null) 216 { 217 Clazz referencedClass = methodrefConstant.referencedClass; 218 219 String newName = referencedMember.getName(referencedClass); 221 String newType = referencedMember.getDescriptor(referencedClass); 222 223 if (!methodrefConstant.getName(clazz).equals(newName) || 224 !methodrefConstant.getType(clazz).equals(newType)) 225 { 226 if (DEBUG) 227 { 228 debug(clazz, methodrefConstant, referencedClass, referencedMember); 229 } 230 231 methodrefConstant.u2nameAndTypeIndex = 233 constantPoolEditor.addNameAndTypeConstant((ProgramClass)clazz, 234 newName, 235 newType); 236 237 stackSizesMayHaveChanged = true; 240 } 241 242 isInterfaceMethod = false; 244 clazz.constantPoolEntryAccept(methodrefConstant.u2classIndex, this); 245 246 if (isInterfaceMethod) 248 { 249 if (DEBUG) 250 { 251 System.out.println("MemberReferenceFixer:"); 252 System.out.println(" Class file = "+clazz.getName()); 253 System.out.println(" Ref class = "+referencedClass.getName()); 254 System.out.println(" Ref method = "+methodrefConstant.getName(clazz)+methodrefConstant.getType(clazz)); 255 System.out.println(" -> interface method"); 256 } 257 258 ((ProgramClass)clazz).constantPool[this.constantIndex] = 260 new InterfaceMethodrefConstant(methodrefConstant.u2classIndex, 261 methodrefConstant.u2nameAndTypeIndex, 262 referencedClass, 263 referencedMember); 264 } 265 } 266 } 267 268 269 public void visitClassConstant(Clazz clazz, ClassConstant classConstant) 270 { 271 if (ClassUtil.isInternalArrayType(classConstant.getName(clazz))) 273 { 274 isInterfaceMethod = false; 275 } 276 else 277 { 278 Clazz referencedClass = classConstant.referencedClass; 280 if (referencedClass != null) 281 { 282 isInterfaceMethod = (referencedClass.getAccessFlags() & ClassConstants.INTERNAL_ACC_INTERFACE) != 0; 283 } 284 } 285 } 286 287 288 290 public void visitProgramMember(ProgramClass programClass, ProgramMember programMember) 291 { 292 programMember.attributesAccept(programClass, this); 294 } 295 296 297 299 public void visitAnyAttribute(Clazz clazz, Attribute attribute) {} 300 301 302 public void visitEnclosingMethodAttribute(Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute) 303 { 304 Member referencedMember = enclosingMethodAttribute.referencedMethod; 305 if (referencedMember != null) 306 { 307 Clazz referencedClass = enclosingMethodAttribute.referencedClass; 308 309 if (!enclosingMethodAttribute.getClassName(clazz).equals(referencedClass.getName())) 311 { 312 enclosingMethodAttribute.u2classIndex = 314 constantPoolEditor.addClassConstant((ProgramClass)clazz, 315 referencedClass); 316 } 317 318 if (!enclosingMethodAttribute.getName(clazz).equals(referencedMember.getName(referencedClass)) || 320 !enclosingMethodAttribute.getType(clazz).equals(referencedMember.getDescriptor(referencedClass))) 321 { 322 enclosingMethodAttribute.u2nameAndTypeIndex = 324 constantPoolEditor.addNameAndTypeConstant((ProgramClass)clazz, 325 referencedMember.getName(referencedClass), 326 referencedMember.getDescriptor(referencedClass)); 327 } 328 } 329 } 330 331 332 public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute) 333 { 334 if (stackSizesMayHaveChanged) 336 { 337 stackSizeUpdater.visitCodeAttribute(clazz, method, codeAttribute); 338 } 339 340 codeAttribute.attributesAccept(clazz, method, this); 342 } 343 344 345 public void visitAnyAnnotationsAttribute(Clazz clazz, AnnotationsAttribute annotationsAttribute) 346 { 347 annotationsAttribute.annotationsAccept(clazz, this); 349 } 350 351 352 public void visitAnyParameterAnnotationsAttribute(Clazz clazz, Method method, ParameterAnnotationsAttribute parameterAnnotationsAttribute) 353 { 354 parameterAnnotationsAttribute.annotationsAccept(clazz, method, this); 356 } 357 358 359 public void visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute) 360 { 361 annotationDefaultAttribute.defaultValueAccept(clazz, this); 363 } 364 365 366 368 public void visitAnnotation(Clazz clazz, Annotation annotation) 369 { 370 annotation.elementValuesAccept(clazz, this); 372 } 373 374 375 377 public void visitConstantElementValue(Clazz clazz, Annotation annotation, ConstantElementValue constantElementValue) 378 { 379 fixElementValue(clazz, annotation, constantElementValue); 380 } 381 382 383 public void visitEnumConstantElementValue(Clazz clazz, Annotation annotation, EnumConstantElementValue enumConstantElementValue) 384 { 385 fixElementValue(clazz, annotation, enumConstantElementValue); 386 } 387 388 389 public void visitClassElementValue(Clazz clazz, Annotation annotation, ClassElementValue classElementValue) 390 { 391 fixElementValue(clazz, annotation, classElementValue); 392 } 393 394 395 public void visitAnnotationElementValue(Clazz clazz, Annotation annotation, AnnotationElementValue annotationElementValue) 396 { 397 fixElementValue(clazz, annotation, annotationElementValue); 398 399 annotationElementValue.annotationAccept(clazz, this); 401 } 402 403 404 public void visitArrayElementValue(Clazz clazz, Annotation annotation, ArrayElementValue arrayElementValue) 405 { 406 fixElementValue(clazz, annotation, arrayElementValue); 407 408 arrayElementValue.elementValuesAccept(clazz, annotation, this); 410 } 411 412 413 415 418 private void fixElementValue(Clazz clazz, 419 Annotation annotation, 420 ElementValue elementValue) 421 { 422 Member referencedMember = elementValue.referencedMethod; 424 if (referencedMember != null) 425 { 426 String methodName = elementValue.getMethodName(clazz); 428 String newMethodName = referencedMember.getName(elementValue.referencedClass); 429 430 if (!methodName.equals(newMethodName)) 431 { 432 elementValue.u2elementNameIndex = 434 constantPoolEditor.addUtf8Constant((ProgramClass)clazz, 435 newMethodName); 436 } 437 } 438 } 439 440 441 private void debug(Clazz clazz, 442 StringConstant stringConstant, 443 Clazz referencedClass, 444 Member referencedMember) 445 { 446 System.out.println("MemberReferenceFixer:"); 447 System.out.println(" Class file = "+clazz.getName()); 448 System.out.println(" Ref class = "+referencedClass.getName()); 449 System.out.println(" Ref member name = "+stringConstant.getString(clazz)); 450 System.out.println(" -> "+referencedMember.getName(referencedClass)); 451 } 452 453 454 private void debug(Clazz clazz, 455 RefConstant refConstant, 456 Clazz referencedClass, 457 Member referencedMember) 458 { 459 System.out.println("MemberReferenceFixer:"); 460 System.out.println(" Class file = "+clazz.getName()); 461 System.out.println(" Ref class = "+referencedClass.getName()); 462 System.out.println(" Ref member name = "+refConstant.getName(clazz)); 463 System.out.println(" -> "+referencedMember.getName(referencedClass)); 464 System.out.println(" Ref descriptor = "+refConstant.getType(clazz)); 465 System.out.println(" -> "+referencedMember.getDescriptor(referencedClass)); 466 } 467 } 468 | Popular Tags |