PageRenderTime 51ms CodeModel.GetById 15ms app.highlight 31ms RepoModel.GetById 1ms app.codeStats 1ms

/src/kilim/tools/DumpClass.java

http://github.com/kilim/kilim
Java | 428 lines | 360 code | 51 blank | 17 comment | 44 complexity | 9977bba56d7808df0549545d969fc852 MD5 | raw file
  1/* Copyright (c) 2006, Sriram Srinivasan
  2 *
  3 * You may distribute this software under the terms of the license 
  4 * specified in the file "License"
  5 */
  6
  7package kilim.tools;
  8import static kilim.analysis.Utils.dedent;
  9import static kilim.analysis.Utils.indent;
 10import static kilim.analysis.Utils.p;
 11import static kilim.analysis.Utils.pn;
 12import static kilim.analysis.Utils.resetIndentation;
 13
 14import java.io.FileInputStream;
 15import java.io.IOException;
 16import java.io.InputStream;
 17import java.lang.reflect.Modifier;
 18import java.util.Enumeration;
 19import java.util.Formatter;
 20import java.util.HashMap;
 21import java.util.jar.JarEntry;
 22import java.util.jar.JarFile;
 23import java.util.zip.ZipEntry;
 24import kilim.Constants;
 25
 26import kilim.analysis.TypeDesc;
 27
 28import org.objectweb.asm.AnnotationVisitor;
 29import org.objectweb.asm.Attribute;
 30import org.objectweb.asm.ClassReader;
 31import org.objectweb.asm.ClassVisitor;
 32import org.objectweb.asm.FieldVisitor;
 33import org.objectweb.asm.Handle;
 34import org.objectweb.asm.Label;
 35import org.objectweb.asm.MethodVisitor;
 36import org.objectweb.asm.Opcodes;
 37
 38/**
 39 * Equivalent to javap -c -l -private, but the output is in jasmin's format 
 40 * meant to be parseable by Asm.
 41 * @author sriram
 42 */
 43public class DumpClass extends ClassVisitor implements Opcodes {
 44    
 45    static boolean lineNumbers = true;
 46    
 47    public static void main(String[] args) throws IOException {
 48        String name = args.length == 2 ? args[1] : args[0];
 49        
 50        if (name.endsWith(".jar")) {
 51            try {
 52                Enumeration<JarEntry> e = new JarFile(name).entries();
 53                while (e.hasMoreElements()) {
 54                    ZipEntry en = (ZipEntry) e.nextElement();
 55                    String n = en.getName();
 56                    if (!n.endsWith(".class")) continue;
 57                    n = n.substring(0, n.length() - 6).replace('/','.');
 58                    new DumpClass(n);
 59                }
 60            } catch (Exception e) {
 61                e.printStackTrace();
 62            }
 63        } else {
 64            new DumpClass(name);
 65        }
 66    }
 67    
 68
 69    public DumpClass(InputStream is) throws IOException {
 70        super(Constants.KILIM_ASM);
 71        ClassReader cr = new ClassReader(is);
 72        cr.accept(this, /*flags*/ 0);
 73    }
 74
 75    public DumpClass(String className) throws IOException {
 76        super(Constants.KILIM_ASM);
 77        ClassReader cr;
 78        if (className.endsWith(".class")) {
 79            FileInputStream fis = new FileInputStream(className);
 80            cr = new ClassReader(fis);
 81        } else {
 82            cr = new ClassReader(className);
 83        }
 84        cr.accept(this, /*flags*/ClassReader.EXPAND_FRAMES);
 85    }
 86
 87    public void visit(int version, int access, String name, String signature, 
 88            String superName, String[] interfaces) 
 89    {
 90        p(".class "); 
 91        p(Modifier.toString(access));
 92        p(" ");
 93        pn(name);
 94        if (superName != null) 
 95            pn(".super " + superName);
 96        
 97        if (interfaces != null) {
 98            for (int i = 0; i < interfaces.length; i++) {
 99                p(".implements ");
100                pn(interfaces[i]);
101            }
102        }
103    }
104
105    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
106        pn(".annotation " + (visible ? "visible " : "") + desc);
107        pn(".end annotation");
108        return new DummyAnnotationVisitor();
109    }
110
111    public void visitAttribute(Attribute attr) {}
112
113    public void visitEnd() {}
114
115    public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) {
116        p(".field ");
117        p(Modifier.toString(access));
118        p(" ");
119        p(name);
120        p(" ");
121        p(desc);
122        if (value != null) {
123            p(" = ");
124            if (value instanceof String) {
125                pn("\"" + value + "\"");
126            } else {
127                pn(value.toString());
128            }
129        } else {
130            pn();
131        }
132        return null;
133    }
134
135    public void visitInnerClass(String name, String outerName, String innerName, int access) {
136    }
137
138    public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
139        pn("");
140        pn("; -------------------------------------------------------------");
141        p(".method ");
142        p(Modifier.toString(access));
143        p(" ");
144        p(name);
145        pn(desc);
146        pn("; signature = " + signature);
147        pn("; -------------------------------------------------------------\n");
148        if (exceptions != null) {
149            for (int i = 0; i < exceptions.length; i++) {
150                p(".throws ");
151                pn(exceptions[i]);
152            }
153        }
154        return new DumpMethodVisitor();
155    }
156
157    public void visitOuterClass(String owner, String name, String desc) {
158    }
159
160    // fixme - if jasmin supports nestmates, then these should output the correct syntax
161    public void visitNestMember(String nestMember) {}
162    public void visitNestHost(String nestHost) {}
163
164    public void visitSource(String source, String debug) {}
165}
166
167class DummyAnnotationVisitor extends AnnotationVisitor {
168    public DummyAnnotationVisitor() {
169        super(Constants.KILIM_ASM);
170        // TODO Auto-generated constructor stub
171    }
172    public void visit(String name, Object value) {
173//        System.out.println("visit: name = " + name + ", value = "  + value);
174    }
175    public AnnotationVisitor visitAnnotation(String name, String desc) {
176//        System.out.println("visitAnnotation: name = " + name + ", desc = " + desc);
177        return this;
178    }
179
180    public AnnotationVisitor visitArray(String name) {
181//        System.out.println("visitArray: name = " + name);
182        return this;
183    }
184
185    public void visitEnd() {
186//        System.out.println("visitEnd");
187    }
188
189    public void visitEnum(String name, String desc, String value) {
190//        System.out.println("visitEnum: " + name + ", desc = "  + desc + ", value = " + value);
191    }
192}
193
194class DumpMethodVisitor extends MethodVisitor implements Opcodes {
195
196    public DumpMethodVisitor() {
197        super(Constants.KILIM_ASM);
198    }
199
200    static String[] os = {
201        "nop","aconst_null","iconst_m1","iconst_0","iconst_1","iconst_2",
202        "iconst_3","iconst_4","iconst_5","lconst_0","lconst_1","fconst_0",
203        "fconst_1","fconst_2","dconst_0","dconst_1","bipush","sipush",
204        "ldc","ldc_w","ldc_w","iload","lload","fload","dload","aload",
205        "iload_0","iload_1","iload_2","iload_3","lload_0","lload_1","lload_2",
206        "lload_3","fload_0","fload_1","fload_2","fload_3","dload_0","dload_1",
207        "dload_2","dload_3","aload_0","aload_1","aload_2","aload_3","iaload",
208        "laload","faload","daload","aaload","baload","caload","saload",
209        "istore","lstore","fstore","dstore","astore","istore_0","istore_1",
210        "istore_2","istore_3","lstore_0","lstore_1","lstore_2","lstore_3",
211        "fstore_0","fstore_1","fstore_2","fstore_3","dstore_0","dstore_1",
212        "dstore_2","dstore_3","astore_0","astore_1","astore_2","astore_3",
213        "iastore","lastore","fastore","dastore","aastore","bastore",
214        "castore","sastore","pop","pop2","dup","dup_x1","dup_x2","dup2",
215        "dup2_x1","dup2_x2","swap","iadd","ladd","fadd","dadd","isub",
216        "lsub","fsub","dsub","imul","lmul","fmul","dmul","idiv","ldiv",
217        "fdiv","ddiv","irem","lrem","frem","drem","ineg","lneg","fneg","dneg",
218        "ishl","lshl","ishr","lshr","iushr","lushr","iand","land","ior","lor",
219        "ixor","lxor","iinc","i2l","i2f","i2d","l2i","l2f","l2d","f2i","f2l",
220        "f2d","d2i","d2l","d2f","i2b","i2c","i2s","lcmp","fcmpl","fcmpg",
221        "dcmpl","dcmpg","ifeq","ifne","iflt","ifge","ifgt","ifle","if_icmpeq",
222        "if_icmpne","if_icmplt","if_icmpge","if_icmpgt","if_icmple","if_acmpeq",
223        "if_acmpne","goto","jsr","ret","tableswitch","lookupswitch","ireturn",
224        "lreturn","freturn","dreturn","areturn","return","getstatic",
225        "putstatic","getfield","putfield","invokevirtual","invokespecial",
226        "invokestatic","invokeinterface","unused","new","newarray","anewarray",
227        "arraylength","athrow","checkcast","instanceof","monitorenter",
228        "monitorexit","wide","multianewarray","ifnull","ifnonnull","goto_w","jsr_w"
229    };
230    int line = 0;
231    static StringBuilder fsb = new StringBuilder(100);
232    static Formatter formatter = new Formatter(fsb);
233    public void ppn(String s) {
234        if (DumpClass.lineNumbers) {
235            fsb.setLength(0);
236            formatter.format("%-70s ; %d", s, (line++));
237            pn(fsb.toString());
238        } else {
239            pn(s); 
240        }
241    }
242
243    public void visitFieldInsn(int opcode, String owner, String name, String desc) {
244        ppn(os[opcode] + " " + owner + "/" + name + " " + desc);
245    }
246
247    public void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack) {
248        pn("; Frame " + type);
249        
250        p (";  Locals - ");
251        for(int i = 0; i < nLocal; i++) {
252            Object o = local[i];
253            System.out.print("#" + i + "."  + type(o) + "  ");
254        }
255        System.out.println();
256        p(";  Stack - ");
257        for(int i = 0; i < nStack; i++) {
258            Object o = stack[i];
259            System.out.print("#" + i + "."  + type(o) + "  ");
260        }
261        System.out.println("");
262    }
263
264    private String type(Object o) {
265        if (o == null) {
266            return "null";
267        } else if (o instanceof Integer) {
268            switch (((Integer)o).intValue()) {
269            case 0: return "Top";
270            case 1: return "Integer";
271            case 2: return "Float";
272            case 3: return "Double";
273            case 4: return "Long";
274            case 5: return "Null";
275            case 6: return "Uninitialized_This";            }
276        } else if (o instanceof String) {
277            return (String)o;
278        }
279        return "??UNKNOWN??" + o.getClass() + ":" + o;
280    }
281
282    public void visitIincInsn(int var, int increment) {
283        ppn("iinc " + var + " " + increment);
284    }
285
286    public void visitInsn(int opcode) {
287        ppn(os[opcode]);
288    }
289
290    public void visitIntInsn(int opcode, int operand) {
291        if (opcode == NEWARRAY) {
292            String t = "UNDEFINED";
293            switch (operand) {
294                case T_BOOLEAN: t = " boolean"; break;
295                case T_CHAR:    t = " char"; break;
296                case T_FLOAT:   t = " float"; break;
297                case T_DOUBLE:  t = " double"; break;
298                case T_BYTE:    t = " byte"; break;
299                case T_SHORT:   t = " short"; break;
300                case T_INT:     t = " int"; break;
301                case T_LONG:    t = " long"; break;
302            }
303            ppn(os[opcode] + t);
304        } else {
305            ppn(os[opcode] + " " +operand);
306        }
307    }
308
309    public void visitJumpInsn(int opcode, Label label) {
310        ppn(os[opcode] + " " + lab(label));
311    }
312
313    public void visitLabel(Label label) {
314        dedent(2);
315        pn(lab(label) + ":");
316        indent(2);
317    }
318
319    public void visitLdcInsn(Object cst) {
320        String op = (cst instanceof Double) || (cst instanceof Long) ? "ldc2_w " : "ldc ";
321        String type = (cst instanceof String) ? "\"" + esc((String)cst) + "\"" : cst.toString();
322        ppn(op  + type);
323    }
324
325    public void visitLineNumber(int line, Label start) {
326        pn(".line " + line);
327    }
328
329    public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index) {
330        pn(".var " + index + " is "+  name + " " + desc + " from " + lab(start) + " to " + lab(end));
331    }
332
333    public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) {
334        ppn("lookupswitch");
335        indent(4);
336        for (int i= 0; i < keys.length; i++) {
337            pn(keys[i] + ": " + lab(labels[i]));
338        }
339        pn("default: " + lab(dflt));
340        dedent(4);
341    }
342
343    public void visitMethodInsn(int opcode, String owner, String name, String desc,boolean itf) {
344        String str = os[opcode] + " " + owner + "/" + name + desc;
345        if (opcode == INVOKEINTERFACE) {
346            ppn(str + ", " + (TypeDesc.getNumArgumentTypes(desc)+1));
347        } else {
348            ppn(str);
349        }
350    }
351    
352    public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
353            Object... bsmArgs) {
354        ppn("invokedynamic " + name + desc);
355        indent(4);
356        pn("; bootstrap = " + bsm.getOwner() + "." + bsm.getName() + bsm.getDesc());
357        for (int i = 0; i < bsmArgs.length; i++) {
358            pn("; arg[" + i + "] = " + bsmArgs[0]);
359        }
360        dedent(4);
361    }
362
363    public void visitMultiANewArrayInsn(String desc, int dims) {
364        ppn("multinewarray " + desc + " " + dims) ;
365    }
366
367    public void visitTableSwitchInsn(int min, int max, Label dflt, Label... labels) {
368        ppn("tableswitch  " + min);
369        indent(4);
370        for (int i = min; i <= max; i++) {
371            pn(lab(labels[i - min]));
372        }
373        pn("default: " + lab(dflt));
374        dedent(4);
375    }
376
377    public void visitTryCatchBlock(Label start, Label end, Label handler, String type) {
378        pn(".catch " + type + " from " + lab(start) + " to " + lab(end) + 
379                " using " + lab(handler));
380    }
381
382    public void visitTypeInsn(int opcode, String desc) {
383        ppn(os[opcode] + " " +desc);
384    }
385
386    public void visitVarInsn(int opcode, int var) {
387        ppn(os[opcode] + " " + var);
388    }
389    
390    HashMap<Label,String> labels = new HashMap<Label, String>();
391    int labCount = 1;
392    private String lab(Label label) {
393        String ret = labels.get(label);
394        if (ret == null) {
395            ret = "L"+ labCount++;
396            labels.put(label, ret);
397        }
398        return ret;
399    }
400    public AnnotationVisitor visitAnnotationDefault() {
401        return new DummyAnnotationVisitor();
402    }
403    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
404        pn(".annotation " + (visible ? "visible " : "") + desc);
405        pn(".end annotation");
406        return new DummyAnnotationVisitor();
407    }
408    public AnnotationVisitor visitParameterAnnotation(int parameter, String desc, boolean visible) {
409        return new DummyAnnotationVisitor();
410    }
411    public void visitAttribute(Attribute attr) {
412    }
413    public void visitCode() {
414        indent(4);
415    }
416    public void visitMaxs(int maxStack, int maxLocals) {
417        pn(".limit stack " + maxStack);
418        pn(".limit locals " + maxLocals);
419    }
420    public void visitEnd() {
421        resetIndentation();
422        pn(".end method");
423    }
424    
425    private static String esc(String s) {
426        return s.replace("\\", "\\\\").replace("\"", "\\\"").replace("\n", "\\n");
427    }
428}