1 21 package proguard.classfile.util; 22 23 import proguard.classfile.instruction.visitor.InstructionVisitor; 24 import proguard.classfile.instruction.*; 25 import proguard.classfile.constant.visitor.ConstantVisitor; 26 import proguard.classfile.constant.*; 27 import proguard.classfile.attribute.visitor.*; 28 import proguard.classfile.attribute.*; 29 import proguard.classfile.*; 30 import proguard.util.ClassNameListMatcher; 31 32 50 public class DynamicMemberReferenceInitializer 51 extends SimplifiedVisitor 52 implements InstructionVisitor, 53 ConstantVisitor, 54 AttributeVisitor 55 { 56 public static final int X = InstructionSequenceMatcher.X; 57 public static final int Y = InstructionSequenceMatcher.Y; 58 public static final int Z = InstructionSequenceMatcher.Z; 59 60 public static final int A = InstructionSequenceMatcher.A; 61 public static final int B = InstructionSequenceMatcher.B; 62 public static final int C = InstructionSequenceMatcher.C; 63 public static final int D = InstructionSequenceMatcher.D; 64 65 66 private Constant[] GET_FIELD_CONSTANTS = new Constant[] 67 { 68 new MethodrefConstant(1, 2, null, null), 69 new ClassConstant(3, null), 70 new NameAndTypeConstant(4, 5), 71 new Utf8Constant(ClassConstants.INTERNAL_CLASS_NAME_JAVA_LANG_CLASS), 72 new Utf8Constant(ClassConstants.INTERNAL_METHOD_NAME_CLASS_GET_FIELD), 73 new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_CLASS_GET_FIELD), 74 }; 75 76 private Constant[] GET_DECLARED_FIELD_CONSTANTS = new Constant[] 77 { 78 new MethodrefConstant(1, 2, null, null), 79 new ClassConstant(3, null), 80 new NameAndTypeConstant(4, 5), 81 new Utf8Constant(ClassConstants.INTERNAL_CLASS_NAME_JAVA_LANG_CLASS), 82 new Utf8Constant(ClassConstants.INTERNAL_METHOD_NAME_CLASS_GET_DECLARED_FIELD), 83 new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_CLASS_GET_DECLARED_FIELD), 84 }; 85 86 private Constant[] GET_METHOD_CONSTANTS = new Constant[] 87 { 88 new MethodrefConstant(1, 2, null, null), 89 new ClassConstant(3, null), 90 new NameAndTypeConstant(4, 5), 91 new Utf8Constant(ClassConstants.INTERNAL_CLASS_NAME_JAVA_LANG_CLASS), 92 new Utf8Constant(ClassConstants.INTERNAL_METHOD_NAME_CLASS_GET_METHOD), 93 new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_CLASS_GET_METHOD), 94 }; 95 96 private Constant[] GET_DECLARED_METHOD_CONSTANTS = new Constant[] 97 { 98 new MethodrefConstant(1, 2, null, null), 99 new ClassConstant(3, null), 100 new NameAndTypeConstant(4, 5), 101 new Utf8Constant(ClassConstants.INTERNAL_CLASS_NAME_JAVA_LANG_CLASS), 102 new Utf8Constant(ClassConstants.INTERNAL_METHOD_NAME_CLASS_GET_DECLARED_METHOD), 103 new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_CLASS_GET_DECLARED_METHOD), 104 }; 105 106 private Instruction[] CONSTANT_GET_FIELD_INSTRUCTIONS = new Instruction[] 108 { 109 new ConstantInstruction(InstructionConstants.OP_LDC, X), 110 new ConstantInstruction(InstructionConstants.OP_LDC, Y), 111 new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0), 112 }; 113 114 private Instruction[] CONSTANT_GET_METHOD_INSTRUCTIONS0 = new Instruction[] 116 { 117 new ConstantInstruction(InstructionConstants.OP_LDC, X), 118 new ConstantInstruction(InstructionConstants.OP_LDC, Y), 119 new SimpleInstruction(InstructionConstants.OP_ICONST_0), 120 new ConstantInstruction(InstructionConstants.OP_ANEWARRAY, 1), 121 new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0), 122 }; 123 124 private Instruction[] CONSTANT_GET_METHOD_INSTRUCTIONS1 = new Instruction[] 126 { 127 new ConstantInstruction(InstructionConstants.OP_LDC, X), 128 new ConstantInstruction(InstructionConstants.OP_LDC, Y), 129 new SimpleInstruction(InstructionConstants.OP_ICONST_1), 130 new ConstantInstruction(InstructionConstants.OP_ANEWARRAY, 1), 131 new SimpleInstruction(InstructionConstants.OP_DUP), 132 new SimpleInstruction(InstructionConstants.OP_ICONST_0), 133 new ConstantInstruction(InstructionConstants.OP_LDC, A), 134 new SimpleInstruction(InstructionConstants.OP_AASTORE), 135 new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0), 136 }; 137 138 private Instruction[] CONSTANT_GET_METHOD_INSTRUCTIONS2 = new Instruction[] 140 { 141 new ConstantInstruction(InstructionConstants.OP_LDC, X), 142 new ConstantInstruction(InstructionConstants.OP_LDC, Y), 143 new SimpleInstruction(InstructionConstants.OP_ICONST_2), 144 new ConstantInstruction(InstructionConstants.OP_ANEWARRAY, 1), 145 new SimpleInstruction(InstructionConstants.OP_DUP), 146 new SimpleInstruction(InstructionConstants.OP_ICONST_0), 147 new ConstantInstruction(InstructionConstants.OP_LDC, A), 148 new SimpleInstruction(InstructionConstants.OP_AASTORE), 149 new SimpleInstruction(InstructionConstants.OP_DUP), 150 new SimpleInstruction(InstructionConstants.OP_ICONST_1), 151 new ConstantInstruction(InstructionConstants.OP_LDC, B), 152 new SimpleInstruction(InstructionConstants.OP_AASTORE), 153 new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0), 154 }; 155 156 private Instruction[] GET_FIELD_INSTRUCTIONS = new Instruction[] 158 { 159 new ConstantInstruction(InstructionConstants.OP_LDC, Y), 160 new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0), 161 }; 162 163 private Instruction[] GET_METHOD_INSTRUCTIONS0 = new Instruction[] 165 { 166 new ConstantInstruction(InstructionConstants.OP_LDC, Y), 167 new SimpleInstruction(InstructionConstants.OP_ICONST_0), 168 new ConstantInstruction(InstructionConstants.OP_ANEWARRAY, 1), 169 new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0), 170 }; 171 172 private Instruction[] GET_METHOD_INSTRUCTIONS1 = new Instruction[] 174 { 175 new ConstantInstruction(InstructionConstants.OP_LDC, Y), 176 new SimpleInstruction(InstructionConstants.OP_ICONST_1), 177 new ConstantInstruction(InstructionConstants.OP_ANEWARRAY, 1), 178 new SimpleInstruction(InstructionConstants.OP_DUP), 179 new SimpleInstruction(InstructionConstants.OP_ICONST_0), 180 new ConstantInstruction(InstructionConstants.OP_LDC, A), 181 new SimpleInstruction(InstructionConstants.OP_AASTORE), 182 new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0), 183 }; 184 185 private Instruction[] GET_METHOD_INSTRUCTIONS2 = new Instruction[] 187 { 188 new ConstantInstruction(InstructionConstants.OP_LDC, Y), 189 new SimpleInstruction(InstructionConstants.OP_ICONST_2), 190 new ConstantInstruction(InstructionConstants.OP_ANEWARRAY, 1), 191 new SimpleInstruction(InstructionConstants.OP_DUP), 192 new SimpleInstruction(InstructionConstants.OP_ICONST_0), 193 new ConstantInstruction(InstructionConstants.OP_LDC, A), 194 new SimpleInstruction(InstructionConstants.OP_AASTORE), 195 new SimpleInstruction(InstructionConstants.OP_DUP), 196 new SimpleInstruction(InstructionConstants.OP_ICONST_1), 197 new ConstantInstruction(InstructionConstants.OP_LDC, B), 198 new SimpleInstruction(InstructionConstants.OP_AASTORE), 199 new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0), 200 }; 201 202 203 private WarningPrinter notePrinter; 204 private ClassNameListMatcher noteFieldExceptionMatcher; 205 private ClassNameListMatcher noteMethodExceptionMatcher; 206 207 208 private InstructionSequenceMatcher constantGetFieldMatcher = 209 new InstructionSequenceMatcher(GET_FIELD_CONSTANTS, 210 CONSTANT_GET_FIELD_INSTRUCTIONS); 211 212 private InstructionSequenceMatcher constantGetDeclaredFieldMatcher = 213 new InstructionSequenceMatcher(GET_DECLARED_FIELD_CONSTANTS, 214 CONSTANT_GET_FIELD_INSTRUCTIONS); 215 216 private InstructionSequenceMatcher constantGetMethodMatcher0 = 217 new InstructionSequenceMatcher(GET_METHOD_CONSTANTS, 218 CONSTANT_GET_METHOD_INSTRUCTIONS0); 219 220 private InstructionSequenceMatcher constantGetDeclaredMethodMatcher0 = 221 new InstructionSequenceMatcher(GET_DECLARED_METHOD_CONSTANTS, 222 CONSTANT_GET_METHOD_INSTRUCTIONS0); 223 224 private InstructionSequenceMatcher constantGetMethodMatcher1 = 225 new InstructionSequenceMatcher(GET_METHOD_CONSTANTS, 226 CONSTANT_GET_METHOD_INSTRUCTIONS1); 227 228 private InstructionSequenceMatcher constantGetDeclaredMethodMatcher1 = 229 new InstructionSequenceMatcher(GET_DECLARED_METHOD_CONSTANTS, 230 CONSTANT_GET_METHOD_INSTRUCTIONS1); 231 232 private InstructionSequenceMatcher constantGetMethodMatcher2 = 233 new InstructionSequenceMatcher(GET_METHOD_CONSTANTS, 234 CONSTANT_GET_METHOD_INSTRUCTIONS2); 235 236 private InstructionSequenceMatcher constantGetDeclaredMethodMatcher2 = 237 new InstructionSequenceMatcher(GET_DECLARED_METHOD_CONSTANTS, 238 CONSTANT_GET_METHOD_INSTRUCTIONS2); 239 240 private InstructionSequenceMatcher getFieldMatcher = 241 new InstructionSequenceMatcher(GET_FIELD_CONSTANTS, 242 GET_FIELD_INSTRUCTIONS); 243 244 private InstructionSequenceMatcher getDeclaredFieldMatcher = 245 new InstructionSequenceMatcher(GET_DECLARED_FIELD_CONSTANTS, 246 GET_FIELD_INSTRUCTIONS); 247 248 private InstructionSequenceMatcher getMethodMatcher0 = 249 new InstructionSequenceMatcher(GET_METHOD_CONSTANTS, 250 GET_METHOD_INSTRUCTIONS0); 251 252 private InstructionSequenceMatcher getDeclaredMethodMatcher0 = 253 new InstructionSequenceMatcher(GET_DECLARED_METHOD_CONSTANTS, 254 GET_METHOD_INSTRUCTIONS0); 255 256 private InstructionSequenceMatcher getMethodMatcher1 = 257 new InstructionSequenceMatcher(GET_METHOD_CONSTANTS, 258 GET_METHOD_INSTRUCTIONS1); 259 260 private InstructionSequenceMatcher getDeclaredMethodMatcher1 = 261 new InstructionSequenceMatcher(GET_DECLARED_METHOD_CONSTANTS, 262 GET_METHOD_INSTRUCTIONS1); 263 264 private InstructionSequenceMatcher getMethodMatcher2 = 265 new InstructionSequenceMatcher(GET_METHOD_CONSTANTS, 266 GET_METHOD_INSTRUCTIONS2); 267 268 private InstructionSequenceMatcher getDeclaredMethodMatcher2 = 269 new InstructionSequenceMatcher(GET_DECLARED_METHOD_CONSTANTS, 270 GET_METHOD_INSTRUCTIONS2); 271 272 private MemberFinder memberFinder = new MemberFinder(); 273 274 275 private Clazz referencedClass; 277 private boolean isDeclared; 278 private boolean isField; 279 280 281 282 285 public DynamicMemberReferenceInitializer(WarningPrinter notePrinter, 286 ClassNameListMatcher noteFieldExceptionMatcher, 287 ClassNameListMatcher noteMethodExceptionMatcher) 288 { 289 this.notePrinter = notePrinter; 290 this.noteFieldExceptionMatcher = noteFieldExceptionMatcher; 291 this.noteMethodExceptionMatcher = noteMethodExceptionMatcher; 292 } 293 294 295 297 public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) 298 { 299 matchGetMember(clazz, method, codeAttribute, offset, instruction, 301 constantGetFieldMatcher, 302 getFieldMatcher, true, false); 303 304 matchGetMember(clazz, method, codeAttribute, offset, instruction, 306 constantGetDeclaredFieldMatcher, 307 getDeclaredFieldMatcher, true, true); 308 309 matchGetMember(clazz, method, codeAttribute, offset, instruction, 312 constantGetMethodMatcher0, 313 getMethodMatcher0, false, false); 314 315 matchGetMember(clazz, method, codeAttribute, offset, instruction, 318 constantGetDeclaredMethodMatcher0, 319 getDeclaredMethodMatcher0, false, true); 320 321 matchGetMember(clazz, method, codeAttribute, offset, instruction, 324 constantGetMethodMatcher1, 325 getMethodMatcher1, false, false); 326 327 matchGetMember(clazz, method, codeAttribute, offset, instruction, 330 constantGetDeclaredMethodMatcher1, 331 getDeclaredMethodMatcher1, false, true); 332 333 matchGetMember(clazz, method, codeAttribute, offset, instruction, 336 constantGetMethodMatcher2, 337 getMethodMatcher2, false, false); 338 339 matchGetMember(clazz, method, codeAttribute, offset, instruction, 342 constantGetDeclaredMethodMatcher2, 343 getDeclaredMethodMatcher2, false, true); 344 } 345 346 347 351 private void matchGetMember(Clazz clazz, 352 Method method, 353 CodeAttribute codeAttribute, 354 int offset, 355 Instruction instruction, 356 InstructionSequenceMatcher constantSequenceMatcher, 357 InstructionSequenceMatcher variableSequenceMatcher, 358 boolean isField, 359 boolean isDeclared) 360 { 361 instruction.accept(clazz, method, codeAttribute, offset, 363 constantSequenceMatcher); 364 365 if (constantSequenceMatcher.isMatching()) 367 { 368 this.isField = isField; 369 this.isDeclared = isDeclared; 370 371 clazz.constantPoolEntryAccept(constantSequenceMatcher.matchedConstantIndex(X), this); 373 374 clazz.constantPoolEntryAccept(constantSequenceMatcher.matchedConstantIndex(Y), this); 376 377 variableSequenceMatcher.reset(); 379 } 380 381 instruction.accept(clazz, method, codeAttribute, offset, 383 variableSequenceMatcher); 384 385 if (variableSequenceMatcher.isMatching()) 387 { 388 printDynamicInvocationNote(clazz, 390 variableSequenceMatcher, 391 isField, 392 isDeclared); 393 } 394 } 395 396 397 399 402 public void visitClassConstant(Clazz clazz, ClassConstant classConstant) 403 { 404 referencedClass = ClassUtil.isInternalArrayType(classConstant.getName(clazz)) ? 406 null : 407 classConstant.referencedClass; 408 } 409 410 411 414 public void visitStringConstant(Clazz clazz, StringConstant stringConstant) 415 { 416 if (referencedClass != null) 417 { 418 String name = stringConstant.getString(clazz); 419 420 Member referencedMember = isDeclared ? isField ? 423 (Member)referencedClass.findField(name, null) : 424 (Member)referencedClass.findMethod(name, null) : 425 (Member)memberFinder.findMember(clazz, 426 referencedClass, 427 name, 428 null, 429 isField); 430 if (referencedMember != null) 431 { 432 stringConstant.referencedMember = referencedMember; 433 stringConstant.referencedClass = isDeclared ? 434 referencedClass : 435 memberFinder.correspondingClass(); 436 } 437 } 438 } 439 440 441 443 446 private void printDynamicInvocationNote(Clazz clazz, 447 InstructionSequenceMatcher noteSequenceMatcher, 448 boolean isField, 449 boolean isDeclared) 450 { 451 if (notePrinter != null) 453 { 454 ClassNameListMatcher noteExceptionMatcher = isField ? 456 noteFieldExceptionMatcher : 457 noteMethodExceptionMatcher; 458 459 int memberNameIndex = noteSequenceMatcher.matchedConstantIndex(Y); 460 String memberName = clazz.getStringString(memberNameIndex); 461 462 if (noteExceptionMatcher == null || 463 !noteExceptionMatcher.matches(memberName)) 464 { 465 String memberDescription = memberName; 466 467 if (!isField) 469 { 470 memberDescription += '('; 471 for (int count = 0; count < 2; count++) 472 { 473 int memberArgumentIndex = noteSequenceMatcher.matchedConstantIndex(A + count); 474 if (memberArgumentIndex > 0) 475 { 476 if (count > 0) 477 { 478 memberDescription += ','; 479 } 480 String className = clazz.getClassName(memberArgumentIndex); 481 memberDescription += ClassUtil.isInternalArrayType(className) ? 482 ClassUtil.externalType(className) : 483 ClassUtil.externalClassName(className); 484 } 485 } 486 memberDescription += ')'; 487 } 488 489 notePrinter.print("Note: " + 491 ClassUtil.externalClassName(clazz.getName()) + 492 " accesses a " + 493 (isDeclared ? "declared " : "") + 494 (isField ? "field" : "method") + 495 " '" + 496 memberDescription + 497 "' dynamically"); 498 } 499 } 500 } 501 } 502 | Popular Tags |