OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [classpath/] [tools/] [external/] [asm/] [org/] [objectweb/] [asm/] [util/] [CheckClassAdapter.java] - Blame information for rev 779

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 779 jeremybenn
/***
2
 * ASM: a very small and fast Java bytecode manipulation framework
3
 * Copyright (c) 2000-2005 INRIA, France Telecom
4
 * All rights reserved.
5
 *
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions
8
 * are met:
9
 * 1. Redistributions of source code must retain the above copyright
10
 *    notice, this list of conditions and the following disclaimer.
11
 * 2. Redistributions in binary form must reproduce the above copyright
12
 *    notice, this list of conditions and the following disclaimer in the
13
 *    documentation and/or other materials provided with the distribution.
14
 * 3. Neither the name of the copyright holders nor the names of its
15
 *    contributors may be used to endorse or promote products derived from
16
 *    this software without specific prior written permission.
17
 *
18
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
28
 * THE POSSIBILITY OF SUCH DAMAGE.
29
 */
30
package org.objectweb.asm.util;
31
 
32
import java.io.FileInputStream;
33
import java.io.PrintWriter;
34
import java.util.List;
35
 
36
import org.objectweb.asm.AnnotationVisitor;
37
import org.objectweb.asm.FieldVisitor;
38
import org.objectweb.asm.ClassAdapter;
39
import org.objectweb.asm.ClassReader;
40
import org.objectweb.asm.ClassVisitor;
41
import org.objectweb.asm.MethodVisitor;
42
import org.objectweb.asm.Opcodes;
43
import org.objectweb.asm.Attribute;
44
import org.objectweb.asm.Type;
45
import org.objectweb.asm.tree.AbstractInsnNode;
46
import org.objectweb.asm.tree.MethodNode;
47
import org.objectweb.asm.tree.ClassNode;
48
import org.objectweb.asm.tree.TryCatchBlockNode;
49
import org.objectweb.asm.tree.analysis.Analyzer;
50
import org.objectweb.asm.tree.analysis.SimpleVerifier;
51
import org.objectweb.asm.tree.analysis.Frame;
52
 
53
/**
54
 * A {@link ClassAdapter} that checks that its methods are properly used. More
55
 * precisely this class adapter checks each method call individually, based
56
 * <i>only</i> on its arguments, but does <i>not</i> check the <i>sequence</i>
57
 * of method calls. For example, the invalid sequence
58
 * <tt>visitField(ACC_PUBLIC, "i", "I", null)</tt> <tt>visitField(ACC_PUBLIC,
59
 * "i", "D", null)</tt>
60
 * will <i>not</i> be detected by this class adapter.
61
 *
62
 * @author Eric Bruneton
63
 */
64
public class CheckClassAdapter extends ClassAdapter {
65
 
66
    /**
67
     * <tt>true</tt> if the visit method has been called.
68
     */
69
    private boolean start;
70
 
71
    /**
72
     * <tt>true</tt> if the visitSource method has been called.
73
     */
74
    private boolean source;
75
 
76
    /**
77
     * <tt>true</tt> if the visitOuterClass method has been called.
78
     */
79
    private boolean outer;
80
 
81
    /**
82
     * <tt>true</tt> if the visitEnd method has been called.
83
     */
84
    private boolean end;
85
 
86
    /**
87
     * Checks a given class. <p> Usage: CheckClassAdapter &lt;fully qualified
88
     * class name or class file name&gt;
89
     *
90
     * @param args the command line arguments.
91
     *
92
     * @throws Exception if the class cannot be found, or if an IO exception
93
     *         occurs.
94
     */
95
    public static void main(final String[] args) throws Exception {
96
        if (args.length != 1) {
97
            System.err.println("Verifies the given class.");
98
            System.err.println("Usage: CheckClassAdapter "
99
                    + "<fully qualified class name or class file name>");
100
            return;
101
        }
102
        ClassReader cr;
103
        if (args[0].endsWith(".class")) {
104
            cr = new ClassReader(new FileInputStream(args[0]));
105
        } else {
106
            cr = new ClassReader(args[0]);
107
        }
108
 
109
        verify(cr, false, new PrintWriter(System.err));
110
    }
111
 
112
    /**
113
     * Checks a given class
114
     *
115
     * @param cr a <code>ClassReader</code> that contains bytecode for the analysis.
116
     * @param dump true if bytecode should be printed out not only when errors are found.
117
     * @param pw write where results going to be printed
118
     */
119
    public static void verify(ClassReader cr, boolean dump, PrintWriter pw) {
120
        ClassNode cn = new ClassNode();
121
        cr.accept(new CheckClassAdapter(cn), true);
122
 
123
        List methods = cn.methods;
124
        for (int i = 0; i < methods.size(); ++i) {
125
            MethodNode method = (MethodNode) methods.get(i);
126
            if (method.instructions.size() > 0) {
127
                Analyzer a = new Analyzer(new SimpleVerifier(Type.getType("L"
128
                        + cn.name + ";"),
129
                        Type.getType("L" + cn.superName + ";"),
130
                        (cn.access & Opcodes.ACC_INTERFACE) != 0));
131
                try {
132
                    a.analyze(cn.name, method);
133
                    if (!dump) {
134
                        continue;
135
                    }
136
                } catch (Exception e) {
137
                    e.printStackTrace();
138
                }
139
                Frame[] frames = a.getFrames();
140
 
141
                TraceMethodVisitor mv = new TraceMethodVisitor();
142
 
143
                pw.println(method.name + method.desc);
144
                for (int j = 0; j < method.instructions.size(); ++j) {
145
                    ((AbstractInsnNode) method.instructions.get(j)).accept(mv);
146
 
147
                    StringBuffer s = new StringBuffer();
148
                    Frame f = frames[j];
149
                    if (f == null) {
150
                        s.append('?');
151
                    } else {
152
                        for (int k = 0; k < f.getLocals(); ++k) {
153
                            s.append(getShortName(f.getLocal(k).toString()))
154
                                    .append(' ');
155
                        }
156
                        s.append(" : ");
157
                        for (int k = 0; k < f.getStackSize(); ++k) {
158
                            s.append(getShortName(f.getStack(k).toString()))
159
                                    .append(' ');
160
                        }
161
                    }
162
                    while (s.length() < method.maxStack + method.maxLocals + 1)
163
                    {
164
                        s.append(' ');
165
                    }
166
                    pw.print(Integer.toString(j + 100000).substring(1));
167
                    pw.print(" " + s + " : " + mv.buf); // mv.text.get(j));
168
                }
169
                for (int j = 0; j < method.tryCatchBlocks.size(); ++j) {
170
                    ((TryCatchBlockNode) method.tryCatchBlocks.get(j)).accept(mv);
171
                    pw.print(" " + mv.buf);
172
                }
173
                pw.println();
174
            }
175
        }
176
    }
177
 
178
    private static String getShortName(String name) {
179
        int n = name.lastIndexOf('/');
180
        int k = name.length();
181
        if(name.charAt(k-1)==';') k--;
182
        return n==-1 ? name : name.substring(n+1, k);
183
    }
184
 
185
    /**
186
     * Constructs a new {@link CheckClassAdapter}.
187
     *
188
     * @param cv the class visitor to which this adapter must delegate calls.
189
     */
190
    public CheckClassAdapter(final ClassVisitor cv) {
191
        super(cv);
192
    }
193
 
194
    // ------------------------------------------------------------------------
195
    // Implementation of the ClassVisitor interface
196
    // ------------------------------------------------------------------------
197
 
198
    public void visit(
199
        final int version,
200
        final int access,
201
        final String name,
202
        final String signature,
203
        final String superName,
204
        final String[] interfaces)
205
    {
206
        if (start) {
207
            throw new IllegalStateException("visit must be called only once");
208
        } else {
209
            start = true;
210
        }
211
        checkState();
212
        checkAccess(access, Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL
213
                + Opcodes.ACC_SUPER + Opcodes.ACC_INTERFACE
214
                + Opcodes.ACC_ABSTRACT + Opcodes.ACC_SYNTHETIC
215
                + Opcodes.ACC_ANNOTATION + Opcodes.ACC_ENUM
216
                + Opcodes.ACC_DEPRECATED);
217
        CheckMethodAdapter.checkInternalName(name, "class name");
218
        if ("java/lang/Object".equals(name)) {
219
            if (superName != null) {
220
                throw new IllegalArgumentException("The super class name of the Object class must be 'null'");
221
            }
222
        } else {
223
            CheckMethodAdapter.checkInternalName(superName, "super class name");
224
        }
225
        if (signature != null) {
226
            // TODO
227
        }
228
        if ((access & Opcodes.ACC_INTERFACE) != 0) {
229
            if (!"java/lang/Object".equals(superName)) {
230
                throw new IllegalArgumentException("The super class name of interfaces must be 'java/lang/Object'");
231
            }
232
        }
233
        if (interfaces != null) {
234
            for (int i = 0; i < interfaces.length; ++i) {
235
                CheckMethodAdapter.checkInternalName(interfaces[i],
236
                        "interface name at index " + i);
237
            }
238
        }
239
        cv.visit(version, access, name, signature, superName, interfaces);
240
    }
241
 
242
    public void visitSource(final String file, final String debug) {
243
        checkState();
244
        if (source) {
245
            throw new IllegalStateException("visitSource can be called only once.");
246
        }
247
        source = true;
248
        cv.visitSource(file, debug);
249
    }
250
 
251
    public void visitOuterClass(
252
        final String owner,
253
        final String name,
254
        final String desc)
255
    {
256
        checkState();
257
        if (outer) {
258
            throw new IllegalStateException("visitSource can be called only once.");
259
        }
260
        outer = true;
261
        if (owner == null) {
262
            throw new IllegalArgumentException("Illegal outer class owner");
263
        }
264
        if (desc != null) {
265
            CheckMethodAdapter.checkMethodDesc(desc);
266
        }
267
        cv.visitOuterClass(owner, name, desc);
268
    }
269
 
270
    public void visitInnerClass(
271
        final String name,
272
        final String outerName,
273
        final String innerName,
274
        final int access)
275
    {
276
        checkState();
277
        CheckMethodAdapter.checkInternalName(name, "class name");
278
        if (outerName != null) {
279
            CheckMethodAdapter.checkInternalName(outerName, "outer class name");
280
        }
281
        if (innerName != null) {
282
            CheckMethodAdapter.checkIdentifier(innerName, "inner class name");
283
        }
284
        checkAccess(access, Opcodes.ACC_PUBLIC + Opcodes.ACC_PRIVATE
285
                + Opcodes.ACC_PROTECTED + Opcodes.ACC_STATIC
286
                + Opcodes.ACC_FINAL + Opcodes.ACC_INTERFACE
287
                + Opcodes.ACC_ABSTRACT + Opcodes.ACC_SYNTHETIC
288
                + Opcodes.ACC_ANNOTATION + Opcodes.ACC_ENUM);
289
        cv.visitInnerClass(name, outerName, innerName, access);
290
    }
291
 
292
    public FieldVisitor visitField(
293
        final int access,
294
        final String name,
295
        final String desc,
296
        final String signature,
297
        final Object value)
298
    {
299
        checkState();
300
        checkAccess(access, Opcodes.ACC_PUBLIC + Opcodes.ACC_PRIVATE
301
                + Opcodes.ACC_PROTECTED + Opcodes.ACC_STATIC
302
                + Opcodes.ACC_FINAL + Opcodes.ACC_VOLATILE
303
                + Opcodes.ACC_TRANSIENT + Opcodes.ACC_SYNTHETIC
304
                + Opcodes.ACC_ENUM + Opcodes.ACC_DEPRECATED);
305
        CheckMethodAdapter.checkIdentifier(name, "field name");
306
        CheckMethodAdapter.checkDesc(desc, false);
307
        if (signature != null) {
308
            // TODO
309
        }
310
        if (value != null) {
311
            CheckMethodAdapter.checkConstant(value);
312
        }
313
        FieldVisitor av = cv.visitField(access, name, desc, signature, value);
314
        return new CheckFieldAdapter(av);
315
    }
316
 
317
    public MethodVisitor visitMethod(
318
        final int access,
319
        final String name,
320
        final String desc,
321
        final String signature,
322
        final String[] exceptions)
323
    {
324
        checkState();
325
        checkAccess(access, Opcodes.ACC_PUBLIC + Opcodes.ACC_PRIVATE
326
                + Opcodes.ACC_PROTECTED + Opcodes.ACC_STATIC
327
                + Opcodes.ACC_FINAL + Opcodes.ACC_SYNCHRONIZED
328
                + Opcodes.ACC_BRIDGE + Opcodes.ACC_VARARGS + Opcodes.ACC_NATIVE
329
                + Opcodes.ACC_ABSTRACT + Opcodes.ACC_STRICT
330
                + Opcodes.ACC_SYNTHETIC + Opcodes.ACC_DEPRECATED);
331
        CheckMethodAdapter.checkMethodIdentifier(name, "method name");
332
        CheckMethodAdapter.checkMethodDesc(desc);
333
        if (signature != null) {
334
            // TODO
335
        }
336
        if (exceptions != null) {
337
            for (int i = 0; i < exceptions.length; ++i) {
338
                CheckMethodAdapter.checkInternalName(exceptions[i],
339
                        "exception name at index " + i);
340
            }
341
        }
342
        return new CheckMethodAdapter(cv.visitMethod(access,
343
                name,
344
                desc,
345
                signature,
346
                exceptions));
347
    }
348
 
349
    public AnnotationVisitor visitAnnotation(
350
        final String desc,
351
        final boolean visible)
352
    {
353
        checkState();
354
        CheckMethodAdapter.checkDesc(desc, false);
355
        return new CheckAnnotationAdapter(cv.visitAnnotation(desc, visible));
356
    }
357
 
358
    public void visitAttribute(final Attribute attr) {
359
        checkState();
360
        if (attr == null) {
361
            throw new IllegalArgumentException("Invalid attribute (must not be null)");
362
        }
363
        cv.visitAttribute(attr);
364
    }
365
 
366
    public void visitEnd() {
367
        checkState();
368
        end = true;
369
        cv.visitEnd();
370
    }
371
 
372
    // ------------------------------------------------------------------------
373
    // Utility methods
374
    // ------------------------------------------------------------------------
375
 
376
    /**
377
     * Checks that the visit method has been called and that visitEnd has not
378
     * been called.
379
     */
380
    private void checkState() {
381
        if (!start) {
382
            throw new IllegalStateException("Cannot visit member before visit has been called.");
383
        }
384
        if (end) {
385
            throw new IllegalStateException("Cannot visit member after visitEnd has been called.");
386
        }
387
    }
388
 
389
    /**
390
     * Checks that the given access flags do not contain invalid flags. This
391
     * method also checks that mutually incompatible flags are not set
392
     * simultaneously.
393
     *
394
     * @param access the access flags to be checked
395
     * @param possibleAccess the valid access flags.
396
     */
397
    static void checkAccess(final int access, final int possibleAccess) {
398
        if ((access & ~possibleAccess) != 0) {
399
            throw new IllegalArgumentException("Invalid access flags: "
400
                    + access);
401
        }
402
        int pub = ((access & Opcodes.ACC_PUBLIC) != 0 ? 1 : 0);
403
        int pri = ((access & Opcodes.ACC_PRIVATE) != 0 ? 1 : 0);
404
        int pro = ((access & Opcodes.ACC_PROTECTED) != 0 ? 1 : 0);
405
        if (pub + pri + pro > 1) {
406
            throw new IllegalArgumentException("public private and protected are mutually exclusive: "
407
                    + access);
408
        }
409
        int fin = ((access & Opcodes.ACC_FINAL) != 0 ? 1 : 0);
410
        int abs = ((access & Opcodes.ACC_ABSTRACT) != 0 ? 1 : 0);
411
        if (fin + abs > 1) {
412
            throw new IllegalArgumentException("final and abstract are mutually exclusive: "
413
                    + access);
414
        }
415
    }
416
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.