1 19 20 package jode.jvm; 21 import jode.GlobalOptions; 22 import jode.bytecode.BytecodeInfo; 23 import jode.bytecode.ClassInfo; 24 import jode.bytecode.FieldInfo; 25 import jode.bytecode.Handler; 26 import jode.bytecode.Instruction; 27 import jode.bytecode.MethodInfo; 28 import jode.bytecode.Opcodes; 29 import jode.bytecode.Reference; 30 import jode.bytecode.TypeSignature; 31 import jode.type.Type; 32 import jode.type.MethodType; 33 34 import java.lang.reflect.Modifier ; 35 36 import java.util.Iterator ; 37 38 public class SyntheticAnalyzer implements Opcodes { 39 public final static int UNKNOWN = 0; 40 public final static int GETCLASS = 1; 41 public final static int ACCESSGETFIELD = 2; 42 public final static int ACCESSPUTFIELD = 3; 43 public final static int ACCESSMETHOD = 4; 44 public final static int ACCESSGETSTATIC = 5; 45 public final static int ACCESSPUTSTATIC = 6; 46 public final static int ACCESSSTATICMETHOD = 7; 47 public final static int ACCESSCONSTRUCTOR = 8; 48 public final static int ACCESSDUPPUTFIELD = 9; 49 public final static int ACCESSDUPPUTSTATIC = 10; 50 51 int kind = UNKNOWN; 52 Reference reference; 53 MethodInfo method; 54 int unifyParam = -1; 55 56 public SyntheticAnalyzer(MethodInfo method, boolean checkName) { 57 this.method = method; 58 if (method.getBytecode() == null) 59 return; 60 if (!checkName || method.getName().equals("class$")) 61 if (checkGetClass()) 62 return; 63 if (!checkName || method.getName().startsWith("access$")) 64 if (checkAccess()) 65 return; 66 if (method.getName().equals("<init>")) 67 if (checkConstructorAccess()) 68 return; 69 } 70 71 public int getKind() { 72 return kind; 73 } 74 75 public Reference getReference() { 76 return reference; 77 } 78 79 83 public int getUnifyParam() { 84 return unifyParam; 85 } 86 87 private static final int[] getClassOpcodes = { 88 opc_aload, opc_invokestatic, opc_areturn, 89 opc_astore, opc_new, opc_dup, opc_aload, 90 opc_invokevirtual, opc_invokespecial, opc_athrow 91 }; 92 private static final Reference[] getClassRefs = { 93 null, Reference.getReference("Ljava/lang/Class;", "forName", 94 "(Ljava/lang/String;)Ljava/lang/Class;"), 95 null, null, null, null, null, 96 Reference.getReference("Ljava/lang/Throwable;", "getMessage", 97 "()Ljava/lang/String;"), 98 Reference.getReference("Ljava/lang/NoClassDefFoundError;", "<init>", 99 "(Ljava/lang/String;)V"), null 100 }; 101 102 103 boolean checkGetClass() { 104 if (!method.isStatic() 105 || !(method.getType() 106 .equals("(Ljava/lang/String;)Ljava/lang/Class;"))) 107 return false; 108 109 BytecodeInfo bytecode = method.getBytecode(); 110 111 Handler[] excHandlers = bytecode.getExceptionHandlers(); 112 if (excHandlers.length != 1 113 || !"java.lang.ClassNotFoundException".equals(excHandlers[0].type)) 114 return false; 115 116 int excSlot = -1; 117 int i = 0; 118 for (Iterator iter = bytecode.getInstructions().iterator(); iter.hasNext(); i++) { 119 Instruction instr = (Instruction) iter.next(); 120 while (instr.getOpcode() == opc_nop && iter.hasNext()) 121 instr = (Instruction) iter.next(); 122 if (i == getClassOpcodes.length 123 || instr.getOpcode() != getClassOpcodes[i]) 124 return false; 125 if (i == 0 && (instr.getLocalSlot() != 0 126 || excHandlers[0].start != instr)) 127 return false; 128 if (i == 2 && excHandlers[0].end != instr) 129 return false; 130 if (i == 3) { 131 if (excHandlers[0].catcher != instr) 132 return false; 133 excSlot = instr.getLocalSlot(); 134 } 135 if (i == 4 && !instr.getClazzType().equals 136 ("Ljava/lang/NoClassDefFoundError;")) 137 return false; 138 if (i == 6 && instr.getLocalSlot() != excSlot) 139 return false; 140 if (getClassRefs[i] != null 141 && !getClassRefs[i].equals(instr.getReference())) 142 return false; 143 } 144 this.kind = GETCLASS; 145 return true; 146 } 147 148 private final int modifierMask = Modifier.PUBLIC | Modifier.STATIC; 149 150 public boolean checkStaticAccess() { 151 ClassInfo clazzInfo = method.getClazzInfo(); 152 BytecodeInfo bytecode = method.getBytecode(); 153 Iterator iter = bytecode.getInstructions().iterator(); 154 boolean dupSeen = false; 155 156 Instruction instr = (Instruction) iter.next(); 157 while (instr.getOpcode() == opc_nop && iter.hasNext()) 158 instr = (Instruction) iter.next(); 159 if (instr.getOpcode() == opc_getstatic) { 160 Reference ref = instr.getReference(); 161 ClassInfo refClazz = TypeSignature.getClassInfo(ref.getClazz()); 162 if (!refClazz.superClassOf(clazzInfo)) 163 return false; 164 FieldInfo refField 165 = refClazz.findField(ref.getName(), ref.getType()); 166 if ((refField.getModifiers() & modifierMask) != Modifier.STATIC) 167 return false; 168 instr = (Instruction) iter.next(); 169 while (instr.getOpcode() == opc_nop && iter.hasNext()) 170 instr = (Instruction) iter.next(); 171 if (instr.getOpcode() < opc_ireturn 172 || instr.getOpcode() > opc_areturn) 173 return false; 174 175 reference = ref; 176 kind = ACCESSGETSTATIC; 177 return true; 178 } 179 int params = 0, slot = 0; 180 while (instr.getOpcode() >= opc_iload 181 && instr.getOpcode() <= opc_aload 182 && instr.getLocalSlot() == slot) { 183 params++; 184 slot += (instr.getOpcode() == opc_lload 185 || instr.getOpcode() == opc_dload) ? 2 : 1; 186 instr = (Instruction) iter.next(); 187 while (instr.getOpcode() == opc_nop && iter.hasNext()) 188 instr = (Instruction) iter.next(); 189 } 190 if (instr.getOpcode() == (opc_dup - 3) + 3 * slot) { 191 194 instr = (Instruction) iter.next(); 195 while (instr.getOpcode() == opc_nop && iter.hasNext()) 196 instr = (Instruction) iter.next(); 197 if (instr.getOpcode() != opc_putstatic) 198 return false; 199 dupSeen = true; 200 } 201 if (instr.getOpcode() == opc_putstatic) { 202 if (params != 1) 203 return false; 204 205 Reference ref = instr.getReference(); 206 ClassInfo refClazz = TypeSignature.getClassInfo(ref.getClazz()); 207 if (!refClazz.superClassOf(clazzInfo)) 208 return false; 209 FieldInfo refField 210 = refClazz.findField(ref.getName(), ref.getType()); 211 if ((refField.getModifiers() & modifierMask) != Modifier.STATIC) 212 return false; 213 instr = (Instruction) iter.next(); 214 while (instr.getOpcode() == opc_nop && iter.hasNext()) 215 instr = (Instruction) iter.next(); 216 if (dupSeen) { 217 if (instr.getOpcode() < opc_ireturn 218 || instr.getOpcode() > opc_areturn) 219 return false; 220 kind = ACCESSDUPPUTSTATIC; 221 } else { 222 if (instr.getOpcode() != opc_return) 223 return false; 224 kind = ACCESSPUTSTATIC; 225 } 226 reference = ref; 227 return true; 228 } 229 if (instr.getOpcode() == opc_invokestatic) { 230 Reference ref = instr.getReference(); 231 ClassInfo refClazz = TypeSignature.getClassInfo(ref.getClazz()); 232 if (!refClazz.superClassOf(clazzInfo)) 233 return false; 234 MethodInfo refMethod 235 = refClazz.findMethod(ref.getName(), ref.getType()); 236 MethodType refType = Type.tMethod(ref.getType()); 237 if ((refMethod.getModifiers() & modifierMask) != Modifier.STATIC 238 || refType.getParameterTypes().length != params) 239 return false; 240 instr = (Instruction) iter.next(); 241 while (instr.getOpcode() == opc_nop && iter.hasNext()) 242 instr = (Instruction) iter.next(); 243 if (refType.getReturnType() == Type.tVoid) { 244 if (instr.getOpcode() != opc_return) 245 return false; 246 } else { 247 if (instr.getOpcode() < opc_ireturn 248 || instr.getOpcode() > opc_areturn) 249 return false; 250 } 251 252 253 reference = ref; 254 kind = ACCESSSTATICMETHOD; 255 return true; 256 } 257 return false; 258 } 259 260 public boolean checkAccess() { 261 ClassInfo clazzInfo = method.getClazzInfo(); 262 BytecodeInfo bytecode = method.getBytecode(); 263 Handler[] excHandlers = bytecode.getExceptionHandlers(); 264 boolean dupSeen = false; 265 if (excHandlers != null && excHandlers.length != 0) 266 return false; 267 268 if (method.isStatic()) { 269 if (checkStaticAccess()) 270 return true; 271 } 272 273 Iterator iter = bytecode.getInstructions().iterator(); 274 Instruction instr = (Instruction) iter.next(); 275 while (instr.getOpcode() == opc_nop && iter.hasNext()) 276 instr = (Instruction) iter.next(); 277 if (instr.getOpcode() != opc_aload || instr.getLocalSlot() != 0) 278 return false; 279 instr = (Instruction) iter.next(); 280 while (instr.getOpcode() == opc_nop && iter.hasNext()) 281 instr = (Instruction) iter.next(); 282 283 if (instr.getOpcode() == opc_getfield) { 284 Reference ref = instr.getReference(); 285 ClassInfo refClazz = TypeSignature.getClassInfo(ref.getClazz()); 286 if (!refClazz.superClassOf(clazzInfo)) 287 return false; 288 FieldInfo refField 289 = refClazz.findField(ref.getName(), ref.getType()); 290 if ((refField.getModifiers() & modifierMask) != 0) 291 return false; 292 instr = (Instruction) iter.next(); 293 while (instr.getOpcode() == opc_nop && iter.hasNext()) 294 instr = (Instruction) iter.next(); 295 if (instr.getOpcode() < opc_ireturn 296 || instr.getOpcode() > opc_areturn) 297 return false; 298 299 reference = ref; 300 kind = ACCESSGETFIELD; 301 return true; 302 } 303 int params = 0, slot = 1; 304 while (instr.getOpcode() >= opc_iload 305 && instr.getOpcode() <= opc_aload 306 && instr.getLocalSlot() == slot) { 307 params++; 308 slot += (instr.getOpcode() == opc_lload 309 || instr.getOpcode() == opc_dload) ? 2 : 1; 310 instr = (Instruction) iter.next(); 311 while (instr.getOpcode() == opc_nop && iter.hasNext()) 312 instr = (Instruction) iter.next(); 313 } 314 if (instr.getOpcode() == (opc_dup_x1 - 6) + 3 * slot) { 315 318 instr = (Instruction) iter.next(); 319 while (instr.getOpcode() == opc_nop && iter.hasNext()) 320 instr = (Instruction) iter.next(); 321 if (instr.getOpcode() != opc_putfield) 322 return false; 323 dupSeen = true; 324 } 325 if (instr.getOpcode() == opc_putfield) { 326 if (params != 1) 327 return false; 328 329 Reference ref = instr.getReference(); 330 ClassInfo refClazz = TypeSignature.getClassInfo(ref.getClazz()); 331 if (!refClazz.superClassOf(clazzInfo)) 332 return false; 333 FieldInfo refField 334 = refClazz.findField(ref.getName(), ref.getType()); 335 if ((refField.getModifiers() & modifierMask) != 0) 336 return false; 337 338 instr = (Instruction) iter.next(); 339 while (instr.getOpcode() == opc_nop && iter.hasNext()) 340 instr = (Instruction) iter.next(); 341 if (dupSeen) { 342 if (instr.getOpcode() < opc_ireturn 343 || instr.getOpcode() > opc_areturn) 344 return false; 345 kind = ACCESSDUPPUTFIELD; 346 } else { 347 if (instr.getOpcode() != opc_return) 348 return false; 349 kind = ACCESSPUTFIELD; 350 } 351 reference = ref; 352 return true; 353 } 354 if (instr.getOpcode() == opc_invokespecial) { 355 Reference ref = instr.getReference(); 356 ClassInfo refClazz = TypeSignature.getClassInfo(ref.getClazz()); 357 if (!refClazz.superClassOf(clazzInfo)) 358 return false; 359 MethodInfo refMethod 360 = refClazz.findMethod(ref.getName(), ref.getType()); 361 MethodType refType = Type.tMethod(ref.getType()); 362 if ((refMethod.getModifiers() & modifierMask) != 0 363 || refType.getParameterTypes().length != params) 364 return false; 365 instr = (Instruction) iter.next(); 366 while (instr.getOpcode() == opc_nop && iter.hasNext()) 367 instr = (Instruction) iter.next(); 368 if (refType.getReturnType() == Type.tVoid) { 369 if (instr.getOpcode() != opc_return) 370 return false; 371 } else { 372 if (instr.getOpcode() < opc_ireturn 373 || instr.getOpcode() > opc_areturn) 374 return false; 375 } 376 377 378 reference = ref; 379 kind = ACCESSMETHOD; 380 return true; 381 } 382 return false; 383 } 384 385 public boolean checkConstructorAccess() { 386 ClassInfo clazzInfo = method.getClazzInfo(); 387 BytecodeInfo bytecode = method.getBytecode(); 388 String [] paramTypes 389 = TypeSignature.getParameterTypes(method.getType()); 390 Handler[] excHandlers = bytecode.getExceptionHandlers(); 391 if (excHandlers != null && excHandlers.length != 0) 392 return false; 393 Iterator iter = bytecode.getInstructions().iterator(); 394 395 Instruction instr = (Instruction) iter.next(); 396 while (instr.getOpcode() == opc_nop && iter.hasNext()) 397 instr = (Instruction) iter.next(); 398 int params = 0, slot = 0; 399 while (instr.getOpcode() >= opc_iload 400 && instr.getOpcode() <= opc_aload) { 401 402 if (instr.getLocalSlot() > slot 403 && unifyParam == -1 && params > 0 404 && paramTypes[params - 1].charAt(0) == 'L') { 405 unifyParam = params; 406 params++; 407 slot++; 408 } 409 if (instr.getLocalSlot() != slot) 410 return false; 411 412 params++; 413 slot += (instr.getOpcode() == opc_lload 414 || instr.getOpcode() == opc_dload) ? 2 : 1; 415 instr = (Instruction) iter.next(); 416 } 417 if (params > 0 && instr.getOpcode() == opc_invokespecial) { 418 419 if (unifyParam == -1 && params <= paramTypes.length 420 && paramTypes[params - 1].charAt(0) == 'L') 421 unifyParam = params++; 422 423 Reference ref = instr.getReference(); 424 ClassInfo refClazz = TypeSignature.getClassInfo(ref.getClazz()); 425 if (refClazz != clazzInfo) 426 return false; 427 MethodInfo refMethod 428 = refClazz.findMethod(ref.getName(), ref.getType()); 429 MethodType refType = Type.tMethod(ref.getType()); 430 if ((refMethod.getModifiers() & modifierMask) != 0 431 || !refMethod.getName().equals("<init>") 432 || unifyParam == -1 433 || refType.getParameterTypes().length != params - 2) 434 return false; 435 436 instr = (Instruction) iter.next(); 437 if (instr.getOpcode() != opc_return) 438 return false; 439 440 444 reference = ref; 445 kind = ACCESSCONSTRUCTOR; 446 return true; 447 } 448 return false; 449 } 450 } 451 452 | Popular Tags |