summaryrefslogtreecommitdiff
path: root/tools/external/asm/org/objectweb/asm/util/TraceClassVisitor.java
diff options
context:
space:
mode:
Diffstat (limited to 'tools/external/asm/org/objectweb/asm/util/TraceClassVisitor.java')
-rw-r--r--tools/external/asm/org/objectweb/asm/util/TraceClassVisitor.java534
1 files changed, 534 insertions, 0 deletions
diff --git a/tools/external/asm/org/objectweb/asm/util/TraceClassVisitor.java b/tools/external/asm/org/objectweb/asm/util/TraceClassVisitor.java
new file mode 100644
index 000000000..9a727e50f
--- /dev/null
+++ b/tools/external/asm/org/objectweb/asm/util/TraceClassVisitor.java
@@ -0,0 +1,534 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.objectweb.asm.util;
+
+import java.io.FileInputStream;
+import java.io.PrintWriter;
+
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.Attribute;
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.FieldVisitor;
+import org.objectweb.asm.signature.SignatureReader;
+
+/**
+ * A {@link ClassVisitor} that prints a disassembled view of the classes it
+ * visits. This class visitor can be used alone (see the {@link #main main}
+ * method) to disassemble a class. It can also be used in the middle of class
+ * visitor chain to trace the class that is visited at a given point in this
+ * chain. This may be uselful for debugging purposes. <p> The trace printed when
+ * visiting the <tt>Hello</tt> class is the following: <p> <blockquote>
+ *
+ * <pre>
+ * // class version 49.0 (49)
+ * // access flags 33
+ * public class Hello {
+ *
+ * // compiled from: Hello.java
+ *
+ * // access flags 1
+ * public &lt;init&gt; ()V
+ * ALOAD 0
+ * INVOKESPECIAL java/lang/Object &lt;init&gt; ()V
+ * RETURN
+ * MAXSTACK = 1
+ * MAXLOCALS = 1
+ *
+ * // access flags 9
+ * public static main ([Ljava/lang/String;)V
+ * GETSTATIC java/lang/System out Ljava/io/PrintStream;
+ * LDC &quot;hello&quot;
+ * INVOKEVIRTUAL java/io/PrintStream println (Ljava/lang/String;)V
+ * RETURN
+ * MAXSTACK = 2
+ * MAXLOCALS = 1
+ * }
+ * </pre>
+ *
+ * </blockquote> where <tt>Hello</tt> is defined by: <p> <blockquote>
+ *
+ * <pre>
+ * public class Hello {
+ *
+ * public static void main(String[] args) {
+ * System.out.println(&quot;hello&quot;);
+ * }
+ * }
+ * </pre>
+ *
+ * </blockquote>
+ *
+ * @author Eric Bruneton
+ * @author Eugene Kuleshov
+ */
+public class TraceClassVisitor extends TraceAbstractVisitor implements
+ ClassVisitor
+{
+
+ /**
+ * The {@link ClassVisitor} to which this visitor delegates calls. May be
+ * <tt>null</tt>.
+ */
+ protected final ClassVisitor cv;
+
+ /**
+ * The print writer to be used to print the class.
+ */
+ protected final PrintWriter pw;
+
+ /**
+ * Prints a disassembled view of the given class to the standard output. <p>
+ * Usage: TraceClassVisitor [-debug] &lt;fully qualified class name or class
+ * file name &gt;
+ *
+ * @param args the command line arguments.
+ *
+ * @throws Exception if the class cannot be found, or if an IO exception
+ * occurs.
+ */
+ public static void main(final String[] args) throws Exception {
+ int i = 0;
+ boolean skipDebug = true;
+
+ boolean ok = true;
+ if (args.length < 1 || args.length > 2) {
+ ok = false;
+ }
+ if (ok && args[0].equals("-debug")) {
+ i = 1;
+ skipDebug = false;
+ if (args.length != 2) {
+ ok = false;
+ }
+ }
+ if (!ok) {
+ System.err.println("Prints a disassembled view of the given class.");
+ System.err.println("Usage: TraceClassVisitor [-debug] "
+ + "<fully qualified class name or class file name>");
+ return;
+ }
+ ClassReader cr;
+ if (args[i].endsWith(".class") || args[i].indexOf('\\') > -1
+ || args[i].indexOf('/') > -1)
+ {
+ cr = new ClassReader(new FileInputStream(args[i]));
+ } else {
+ cr = new ClassReader(args[i]);
+ }
+ cr.accept(new TraceClassVisitor(new PrintWriter(System.out)),
+ getDefaultAttributes(),
+ skipDebug);
+ }
+
+ /**
+ * Constructs a new {@link TraceClassVisitor}.
+ *
+ * @param pw the print writer to be used to print the class.
+ */
+ public TraceClassVisitor(final PrintWriter pw) {
+ this(null, pw);
+ }
+
+ /**
+ * Constructs a new {@link TraceClassVisitor}.
+ *
+ * @param cv the {@link ClassVisitor} to which this visitor delegates calls.
+ * May be <tt>null</tt>.
+ * @param pw the print writer to be used to print the class.
+ */
+ public TraceClassVisitor(final ClassVisitor cv, final PrintWriter pw) {
+ this.cv = cv;
+ this.pw = pw;
+ }
+
+ // ------------------------------------------------------------------------
+ // Implementation of the ClassVisitor interface
+ // ------------------------------------------------------------------------
+
+ public void visit(
+ final int version,
+ final int access,
+ final String name,
+ final String signature,
+ final String superName,
+ final String[] interfaces)
+ {
+ int major = version & 0xFFFF;
+ int minor = version >>> 16;
+ buf.setLength(0);
+ buf.append("// class version ")
+ .append(major)
+ .append('.')
+ .append(minor)
+ .append(" (")
+ .append(version)
+ .append(")\n");
+ if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+ buf.append("// DEPRECATED\n");
+ }
+ buf.append("// access flags ").append(access).append('\n');
+
+ appendDescriptor(CLASS_SIGNATURE, signature);
+ if (signature != null) {
+ TraceSignatureVisitor sv = new TraceSignatureVisitor(access);
+ SignatureReader r = new SignatureReader(signature);
+ r.accept(sv);
+ buf.append("// declaration: ")
+ .append(name)
+ .append(sv.getDeclaration())
+ .append('\n');
+ }
+
+ appendAccess(access & ~Opcodes.ACC_SUPER);
+ if ((access & Opcodes.ACC_ANNOTATION) != 0) {
+ buf.append("@interface ");
+ } else if ((access & Opcodes.ACC_INTERFACE) != 0) {
+ buf.append("interface ");
+ } else if ((access & Opcodes.ACC_ENUM) != 0) {
+ buf.append("enum ");
+ } else {
+ buf.append("class ");
+ }
+ appendDescriptor(INTERNAL_NAME, name);
+
+ if (superName != null && !superName.equals("java/lang/Object")) {
+ buf.append(" extends ");
+ appendDescriptor(INTERNAL_NAME, superName);
+ buf.append(' ');
+ }
+ if (interfaces != null && interfaces.length > 0) {
+ buf.append(" implements ");
+ for (int i = 0; i < interfaces.length; ++i) {
+ appendDescriptor(INTERNAL_NAME, interfaces[i]);
+ buf.append(' ');
+ }
+ }
+ buf.append(" {\n\n");
+
+ text.add(buf.toString());
+
+ if (cv != null) {
+ cv.visit(version, access, name, signature, superName, interfaces);
+ }
+ }
+
+ public void visitSource(final String file, final String debug) {
+ buf.setLength(0);
+ if (file != null) {
+ buf.append(tab)
+ .append("// compiled from: ")
+ .append(file)
+ .append('\n');
+ }
+ if (debug != null) {
+ buf.append(tab)
+ .append("// debug info: ")
+ .append(debug)
+ .append('\n');
+ }
+ if (buf.length() > 0) {
+ text.add(buf.toString());
+ }
+
+ if (cv != null) {
+ cv.visitSource(file, debug);
+ }
+ }
+
+ public void visitOuterClass(
+ final String owner,
+ final String name,
+ final String desc)
+ {
+ buf.setLength(0);
+ buf.append(tab).append("OUTERCLASS ");
+ appendDescriptor(INTERNAL_NAME, owner);
+ // if enclosing name is null, so why should we show this info?
+ if (name != null) {
+ buf.append(' ').append(name).append(' ');
+ } else {
+ buf.append(' ');
+ }
+ appendDescriptor(METHOD_DESCRIPTOR, desc);
+ buf.append('\n');
+ text.add(buf.toString());
+
+ if (cv != null) {
+ cv.visitOuterClass(owner, name, desc);
+ }
+ }
+
+ public AnnotationVisitor visitAnnotation(
+ final String desc,
+ final boolean visible)
+ {
+ text.add("\n");
+ AnnotationVisitor tav = super.visitAnnotation(desc, visible);
+ if (cv != null) {
+ ((TraceAnnotationVisitor) tav).av = cv.visitAnnotation(desc,
+ visible);
+ }
+ return tav;
+ }
+
+ public void visitAttribute(final Attribute attr) {
+ text.add("\n");
+ super.visitAttribute(attr);
+
+ if (cv != null) {
+ cv.visitAttribute(attr);
+ }
+ }
+
+ public void visitInnerClass(
+ final String name,
+ final String outerName,
+ final String innerName,
+ final int access)
+ {
+ buf.setLength(0);
+ buf.append(tab).append("// access flags ").append(access
+ & ~Opcodes.ACC_SUPER).append('\n');
+ buf.append(tab);
+ appendAccess(access);
+ buf.append("INNERCLASS ");
+ if ((access & Opcodes.ACC_ENUM) != 0) {
+ buf.append("enum ");
+ }
+ appendDescriptor(INTERNAL_NAME, name);
+ buf.append(' ');
+ appendDescriptor(INTERNAL_NAME, outerName);
+ buf.append(' ');
+ appendDescriptor(INTERNAL_NAME, innerName);
+ buf.append('\n');
+ text.add(buf.toString());
+
+ if (cv != null) {
+ cv.visitInnerClass(name, outerName, innerName, access);
+ }
+ }
+
+ public FieldVisitor visitField(
+ final int access,
+ final String name,
+ final String desc,
+ final String signature,
+ final Object value)
+ {
+ buf.setLength(0);
+ buf.append('\n');
+ if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+ buf.append(tab).append("// DEPRECATED\n");
+ }
+ buf.append(tab).append("// access flags ").append(access).append('\n');
+ if (signature != null) {
+ buf.append(tab);
+ appendDescriptor(FIELD_SIGNATURE, signature);
+
+ TraceSignatureVisitor sv = new TraceSignatureVisitor(0);
+ SignatureReader r = new SignatureReader(signature);
+ r.acceptType(sv);
+ buf.append(tab)
+ .append("// declaration: ")
+ .append(sv.getDeclaration())
+ .append('\n');
+ }
+
+ buf.append(tab);
+ appendAccess(access);
+ if ((access & Opcodes.ACC_ENUM) != 0) {
+ buf.append("enum ");
+ }
+
+ appendDescriptor(FIELD_DESCRIPTOR, desc);
+ buf.append(' ').append(name);
+ if (value != null) {
+ buf.append(" = ");
+ if (value instanceof String) {
+ buf.append("\"").append(value).append("\"");
+ } else {
+ buf.append(value);
+ }
+ }
+
+ buf.append('\n');
+ text.add(buf.toString());
+
+ TraceFieldVisitor tav = createTraceFieldVisitor();
+ text.add(tav.getText());
+
+ if (cv != null) {
+ tav.fv = cv.visitField(access, name, desc, signature, value);
+ }
+
+ return tav;
+ }
+
+ public MethodVisitor visitMethod(
+ final int access,
+ final String name,
+ final String desc,
+ final String signature,
+ final String[] exceptions)
+ {
+ buf.setLength(0);
+ buf.append('\n');
+ if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+ buf.append(tab).append("// DEPRECATED\n");
+ }
+ buf.append(tab).append("// access flags ").append(access).append('\n');
+ buf.append(tab);
+ appendDescriptor(METHOD_SIGNATURE, signature);
+
+ if (signature != null) {
+ TraceSignatureVisitor v = new TraceSignatureVisitor(0);
+ SignatureReader r = new SignatureReader(signature);
+ r.accept(v);
+ String genericDecl = v.getDeclaration();
+ String genericReturn = v.getReturnType();
+ String genericExceptions = v.getExceptions();
+
+ buf.append(tab)
+ .append("// declaration: ")
+ .append(genericReturn)
+ .append(' ')
+ .append(name)
+ .append(genericDecl);
+ if (genericExceptions != null) {
+ buf.append(" throws ").append(genericExceptions);
+ }
+ buf.append('\n');
+ }
+
+ appendAccess(access);
+ if ((access & Opcodes.ACC_NATIVE) != 0) {
+ buf.append("native ");
+ }
+ if ((access & Opcodes.ACC_VARARGS) != 0) {
+ buf.append("varargs ");
+ }
+ if ((access & Opcodes.ACC_BRIDGE) != 0) {
+ buf.append("bridge ");
+ }
+
+ buf.append(name);
+ appendDescriptor(METHOD_DESCRIPTOR, desc);
+ if (exceptions != null && exceptions.length > 0) {
+ buf.append(" throws ");
+ for (int i = 0; i < exceptions.length; ++i) {
+ appendDescriptor(INTERNAL_NAME, exceptions[i]);
+ buf.append(' ');
+ }
+ }
+
+ buf.append('\n');
+ text.add(buf.toString());
+
+ TraceMethodVisitor tcv = createTraceMethodVisitor();
+ text.add(tcv.getText());
+
+ if (cv != null) {
+ tcv.mv = cv.visitMethod(access, name, desc, signature, exceptions);
+ }
+
+ return tcv;
+ }
+
+ public void visitEnd() {
+ text.add("}\n");
+
+ printList(pw, text);
+ pw.flush();
+
+ if (cv != null) {
+ cv.visitEnd();
+ }
+ }
+
+ // ------------------------------------------------------------------------
+ // Utility methods
+ // ------------------------------------------------------------------------
+
+ protected TraceFieldVisitor createTraceFieldVisitor() {
+ return new TraceFieldVisitor();
+ }
+
+ protected TraceMethodVisitor createTraceMethodVisitor() {
+ return new TraceMethodVisitor();
+ }
+
+ /**
+ * Appends a string representation of the given access modifiers to {@link
+ * #buf buf}.
+ *
+ * @param access some access modifiers.
+ */
+ private void appendAccess(final int access) {
+ if ((access & Opcodes.ACC_PUBLIC) != 0) {
+ buf.append("public ");
+ }
+ if ((access & Opcodes.ACC_PRIVATE) != 0) {
+ buf.append("private ");
+ }
+ if ((access & Opcodes.ACC_PROTECTED) != 0) {
+ buf.append("protected ");
+ }
+ if ((access & Opcodes.ACC_FINAL) != 0) {
+ buf.append("final ");
+ }
+ if ((access & Opcodes.ACC_STATIC) != 0) {
+ buf.append("static ");
+ }
+ if ((access & Opcodes.ACC_SYNCHRONIZED) != 0) {
+ buf.append("synchronized ");
+ }
+ if ((access & Opcodes.ACC_VOLATILE) != 0) {
+ buf.append("volatile ");
+ }
+ if ((access & Opcodes.ACC_TRANSIENT) != 0) {
+ buf.append("transient ");
+ }
+ // if ((access & Constants.ACC_NATIVE) != 0) {
+ // buf.append("native ");
+ // }
+ if ((access & Opcodes.ACC_ABSTRACT) != 0) {
+ buf.append("abstract ");
+ }
+ if ((access & Opcodes.ACC_STRICT) != 0) {
+ buf.append("strictfp ");
+ }
+ if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+ buf.append("synthetic ");
+ }
+ }
+}