1 /*
2  * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 package com.sun.tools.classfile;
27 
28 import java.io.IOException;
29 import java.util.Iterator;
30 import java.util.NoSuchElementException;
31 
32 /**
33  * See JVMS, section 4.8.3.
34  *
35  *  <p><b>This is NOT part of any supported API.
36  *  If you write code that depends on this, you do so at your own risk.
37  *  This code and its internal interfaces are subject to change or
38  *  deletion without notice.</b>
39  */
40 public class Code_attribute extends Attribute {
41     public static class InvalidIndex extends AttributeException {
42         private static final long serialVersionUID = -8904527774589382802L;
InvalidIndex(int index)43         InvalidIndex(int index) {
44             this.index = index;
45         }
46 
47         @Override
getMessage()48         public String getMessage() {
49             // i18n
50             return "invalid index " + index + " in Code attribute";
51         }
52 
53         public final int index;
54     }
55 
Code_attribute(ClassReader cr, int name_index, int length)56     Code_attribute(ClassReader cr, int name_index, int length)
57             throws IOException, ConstantPoolException {
58         super(name_index, length);
59         max_stack = cr.readUnsignedShort();
60         max_locals = cr.readUnsignedShort();
61         code_length = cr.readInt();
62         code = new byte[code_length];
63         cr.readFully(code);
64         exception_table_length = cr.readUnsignedShort();
65         exception_table = new Exception_data[exception_table_length];
66         for (int i = 0; i < exception_table_length; i++)
67             exception_table[i] = new Exception_data(cr);
68         attributes = new Attributes(cr);
69     }
70 
getByte(int offset)71     public int getByte(int offset) throws InvalidIndex {
72         if (offset < 0 || offset >= code.length)
73             throw new InvalidIndex(offset);
74         return code[offset];
75     }
76 
getUnsignedByte(int offset)77     public int getUnsignedByte(int offset) throws InvalidIndex {
78         if (offset < 0 || offset >= code.length)
79             throw new InvalidIndex(offset);
80         return code[offset] & 0xff;
81     }
82 
getShort(int offset)83     public int getShort(int offset) throws InvalidIndex {
84         if (offset < 0 || offset + 1 >= code.length)
85             throw new InvalidIndex(offset);
86         return (code[offset] << 8) | (code[offset + 1] & 0xFF);
87     }
88 
getUnsignedShort(int offset)89     public int getUnsignedShort(int offset) throws InvalidIndex {
90         if (offset < 0 || offset + 1 >= code.length)
91             throw new InvalidIndex(offset);
92         return ((code[offset] << 8) | (code[offset + 1] & 0xFF)) & 0xFFFF;
93     }
94 
getInt(int offset)95     public int getInt(int offset) throws InvalidIndex {
96         if (offset < 0 || offset + 3 >= code.length)
97             throw new InvalidIndex(offset);
98         return (getShort(offset) << 16) | (getShort(offset + 2) & 0xFFFF);
99     }
100 
accept(Visitor<R, D> visitor, D data)101     public <R, D> R accept(Visitor<R, D> visitor, D data) {
102         return visitor.visitCode(this, data);
103     }
104 
getInstructions()105     public Iterable<Instruction> getInstructions() {
106         return () -> new Iterator<Instruction>() {
107 
108             public boolean hasNext() {
109                 return (next != null);
110             }
111 
112             public Instruction next() {
113                 if (next == null)
114                     throw new NoSuchElementException();
115 
116                 current = next;
117                 pc += current.length();
118                 next = (pc < code.length ? new Instruction(code, pc) : null);
119                 return current;
120             }
121 
122             public void remove() {
123                 throw new UnsupportedOperationException("Not supported.");
124             }
125 
126             Instruction current = null;
127             int pc = 0;
128             Instruction next = new Instruction(code, pc);
129 
130         };
131     }
132 
133     public final int max_stack;
134     public final int max_locals;
135     public final int code_length;
136     public final byte[] code;
137     public final int exception_table_length;
138     public final Exception_data[] exception_table;
139     public final Attributes attributes;
140 
141     public static class Exception_data {
142         Exception_data(ClassReader cr) throws IOException {
143             start_pc = cr.readUnsignedShort();
144             end_pc = cr.readUnsignedShort();
145             handler_pc = cr.readUnsignedShort();
146             catch_type = cr.readUnsignedShort();
147         }
148 
149         public final int start_pc;
150         public final int end_pc;
151         public final int handler_pc;
152         public final int catch_type;
153     }
154 }
155