1 30 package org.objectweb.asm.util; 31 32 import java.io.FileInputStream ; 33 import java.util.List ; 34 35 import org.objectweb.asm.AnnotationVisitor; 36 import org.objectweb.asm.FieldVisitor; 37 import org.objectweb.asm.ClassAdapter; 38 import org.objectweb.asm.ClassReader; 39 import org.objectweb.asm.ClassVisitor; 40 import org.objectweb.asm.MethodVisitor; 41 import org.objectweb.asm.Opcodes; 42 import org.objectweb.asm.Attribute; 43 import org.objectweb.asm.Type; 44 import org.objectweb.asm.tree.AbstractInsnNode; 45 import org.objectweb.asm.tree.MethodNode; 46 import org.objectweb.asm.tree.ClassNode; 47 import org.objectweb.asm.tree.analysis.Analyzer; 48 import org.objectweb.asm.tree.analysis.SimpleVerifier; 49 import org.objectweb.asm.tree.analysis.Frame; 50 51 62 public class CheckClassAdapter extends ClassAdapter { 63 64 67 private boolean start; 68 69 72 private boolean end; 73 74 83 public static void main(final String [] args) throws Exception { 84 if (args.length != 1) { 85 System.err.println("Verifies the given class."); 86 System.err.println("Usage: CheckClassAdapter " 87 + "<fully qualified class name or class file name>"); 88 System.exit(-1); 89 } 90 ClassReader cr; 91 if (args[0].endsWith(".class")) { 92 cr = new ClassReader(new FileInputStream (args[0])); 93 } else { 94 cr = new ClassReader(args[0]); 95 } 96 97 ClassNode cn = new ClassNode(); 98 cr.accept(new CheckClassAdapter(cn), true); 99 100 List methods = cn.methods; 101 for (int i = 0; i < methods.size(); ++i) { 102 MethodNode method = (MethodNode) methods.get(i); 103 if (method.instructions.size() > 0) { 104 Analyzer a = new Analyzer(new SimpleVerifier(Type.getType("L" 105 + cn.name + ";"), 106 Type.getType("L" + cn.superName + ";"), 107 (cn.access & Opcodes.ACC_INTERFACE) != 0)); 108 try { 109 a.analyze(cn.name, method); 110 continue; 111 } catch (Exception e) { 112 e.printStackTrace(); 113 } 114 final Frame[] frames = a.getFrames(); 115 116 System.out.println(method.name + method.desc); 117 TraceMethodVisitor mv = new TraceMethodVisitor() { 118 public void visitMaxs( 119 final int maxStack, 120 final int maxLocals) 121 { 122 for (int i = 0; i < text.size(); ++i) { 123 String s = frames[i] == null 124 ? "null" 125 : frames[i].toString(); 126 while (s.length() < maxStack + maxLocals + 1) { 127 s += " "; 128 } 129 System.out.print(Integer.toString(i + 100000) 130 .substring(1)); 131 System.out.print(" " + s + " : " + text.get(i)); 132 } 133 System.out.println(); 134 } 135 }; 136 for (int j = 0; j < method.instructions.size(); ++j) { 137 ((AbstractInsnNode) method.instructions.get(j)).accept(mv); 138 } 139 mv.visitMaxs(method.maxStack, method.maxLocals); 140 } 141 } 142 } 143 144 149 public CheckClassAdapter(final ClassVisitor cv) { 150 super(cv); 151 } 152 153 157 public void visit( 158 final int version, 159 final int access, 160 final String name, 161 final String signature, 162 final String superName, 163 final String [] interfaces) 164 { 165 if (start) { 166 throw new IllegalStateException ("visit must be called only once"); 167 } else { 168 start = true; 169 } 170 checkState(); 171 checkAccess(access, Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL 172 + Opcodes.ACC_SUPER + Opcodes.ACC_INTERFACE 173 + Opcodes.ACC_ABSTRACT + Opcodes.ACC_SYNTHETIC 174 + Opcodes.ACC_ANNOTATION + Opcodes.ACC_ENUM 175 + Opcodes.ACC_DEPRECATED); 176 CheckMethodAdapter.checkInternalName(name, "class name"); 177 if (name.equals("java/lang/Object")) { 178 if (superName != null) { 179 throw new IllegalArgumentException ("The super class name of the Object class must be 'null'"); 180 } 181 } else { 182 CheckMethodAdapter.checkInternalName(superName, "super class name"); 183 } 184 if (signature != null) { 185 } 187 if ((access & Opcodes.ACC_INTERFACE) != 0) { 188 if (!superName.equals("java/lang/Object")) { 189 throw new IllegalArgumentException ("The super class name of interfaces must be 'java/lang/Object'"); 190 } 191 } 192 if (interfaces != null) { 193 for (int i = 0; i < interfaces.length; ++i) { 194 CheckMethodAdapter.checkInternalName(interfaces[i], 195 "interface name at index " + i); 196 } 197 } 198 cv.visit(version, access, name, signature, superName, interfaces); 199 } 200 201 public void visitSource(final String file, final String debug) { 202 cv.visitSource(file, debug); 204 } 205 206 public void visitOuterClass( 207 final String owner, 208 final String name, 209 final String desc) 210 { 211 cv.visitOuterClass(owner, name, desc); 213 } 214 215 public void visitInnerClass( 216 final String name, 217 final String outerName, 218 final String innerName, 219 final int access) 220 { 221 checkState(); 222 CheckMethodAdapter.checkInternalName(name, "class name"); 223 if (outerName != null) { 224 CheckMethodAdapter.checkInternalName(outerName, "outer class name"); 225 } 226 if (innerName != null) { 227 CheckMethodAdapter.checkIdentifier(innerName, "inner class name"); 228 } 229 checkAccess(access, Opcodes.ACC_PUBLIC + Opcodes.ACC_PRIVATE 230 + Opcodes.ACC_PROTECTED + Opcodes.ACC_STATIC 231 + Opcodes.ACC_FINAL + Opcodes.ACC_INTERFACE 232 + Opcodes.ACC_ABSTRACT + Opcodes.ACC_SYNTHETIC 233 + Opcodes.ACC_ANNOTATION + Opcodes.ACC_ENUM); 234 cv.visitInnerClass(name, outerName, innerName, access); 235 } 236 237 public FieldVisitor visitField( 238 final int access, 239 final String name, 240 final String desc, 241 final String signature, 242 final Object value) 243 { 244 checkState(); 245 checkAccess(access, Opcodes.ACC_PUBLIC + Opcodes.ACC_PRIVATE 246 + Opcodes.ACC_PROTECTED + Opcodes.ACC_STATIC 247 + Opcodes.ACC_FINAL + Opcodes.ACC_VOLATILE 248 + Opcodes.ACC_TRANSIENT + Opcodes.ACC_SYNTHETIC 249 + Opcodes.ACC_ENUM + Opcodes.ACC_DEPRECATED); 250 CheckMethodAdapter.checkIdentifier(name, "field name"); 251 CheckMethodAdapter.checkDesc(desc, false); 252 if (signature != null) { 253 } 255 if (value != null) { 256 CheckMethodAdapter.checkConstant(value); 257 } 258 FieldVisitor av = cv.visitField(access, name, desc, signature, value); 259 return av; 261 } 262 263 public MethodVisitor visitMethod( 264 final int access, 265 final String name, 266 final String desc, 267 final String signature, 268 final String [] exceptions) 269 { 270 checkState(); 271 checkAccess(access, Opcodes.ACC_PUBLIC + Opcodes.ACC_PRIVATE 272 + Opcodes.ACC_PROTECTED + Opcodes.ACC_STATIC 273 + Opcodes.ACC_FINAL + Opcodes.ACC_SYNCHRONIZED 274 + Opcodes.ACC_BRIDGE + Opcodes.ACC_VARARGS + Opcodes.ACC_NATIVE 275 + Opcodes.ACC_ABSTRACT + Opcodes.ACC_STRICT 276 + Opcodes.ACC_SYNTHETIC + Opcodes.ACC_DEPRECATED); 277 CheckMethodAdapter.checkMethodIdentifier(name, "method name"); 278 CheckMethodAdapter.checkMethodDesc(desc); 279 if (signature != null) { 280 } 282 if (exceptions != null) { 283 for (int i = 0; i < exceptions.length; ++i) { 284 CheckMethodAdapter.checkInternalName(exceptions[i], 285 "exception name at index " + i); 286 } 287 } 288 return new CheckMethodAdapter(cv.visitMethod(access, 289 name, 290 desc, 291 signature, 292 exceptions)); 293 } 294 295 public AnnotationVisitor visitAnnotation( 296 final String desc, 297 final boolean visible) 298 { 299 return cv.visitAnnotation(desc, visible); 301 } 302 303 public void visitAttribute(final Attribute attr) { 304 checkState(); 305 if (attr == null) { 306 throw new IllegalArgumentException ("Invalid attribute (must not be null)"); 307 } 308 } 309 310 public void visitEnd() { 311 checkState(); 312 end = true; 313 cv.visitEnd(); 314 } 315 316 320 324 private void checkState() { 325 if (!start) { 326 throw new IllegalStateException ("Cannot visit member before visit has been called."); 327 } 328 if (end) { 329 throw new IllegalStateException ("Cannot visit member after visitEnd has been called."); 330 } 331 } 332 333 341 static void checkAccess(final int access, final int possibleAccess) { 342 if ((access & ~possibleAccess) != 0) { 343 throw new IllegalArgumentException ("Invalid access flags: " 344 + access); 345 } 346 int pub = ((access & Opcodes.ACC_PUBLIC) != 0 ? 1 : 0); 347 int pri = ((access & Opcodes.ACC_PRIVATE) != 0 ? 1 : 0); 348 int pro = ((access & Opcodes.ACC_PROTECTED) != 0 ? 1 : 0); 349 if (pub + pri + pro > 1) { 350 throw new IllegalArgumentException ("public private and protected are mutually exclusive: " 351 + access); 352 } 353 int fin = ((access & Opcodes.ACC_FINAL) != 0 ? 1 : 0); 354 int abs = ((access & Opcodes.ACC_ABSTRACT) != 0 ? 1 : 0); 355 if (fin + abs > 1) { 356 throw new IllegalArgumentException ("final and abstract are mutually exclusive: " 357 + access); 358 } 359 } 360 } 361 | Popular Tags |