1    
2    /**
3    
4      The author of this software is Ian Kaplan
5      Bear Products International
6      www.bearcave.com
7      iank@bearcave.com
8    
9      Copyright (c) Ian Kaplan, 1999, 2000
10   
11     See copyright file for usage and licensing
12   
13   */
14   
15   package attr;
16   
17   import java.util.Vector;
18   import java.io.*;
19   import util.*;
20   import jconst.*;
21   
22   
23   /**
24   
25      Attribute for the byte code for a Java method.  The attribute name
26      for the codeAttr is "Code".  Note that if the method is native or
27      abstract, then it can't have a "Code" attribute.
28   
29   <p>
30      The structure of a Code attribute is:
31   
32   <pre>
33      Code_attribute {
34        u2 name_index;
35        u4 total_length;
36        u2 max_stack;
37        u2 max_locals;
38        u4 code_length;
39        u1 code[ code_length ];
40        u2 exceptions_table_length;
41        exceptInfo except[ exceptions_table_length ];
42        u2 attributes_count;
43        attribute_info attributes[ attributes_count ];
44      }
45   </pre>
46   
47   <p>
48   
49      Where
50   
51   <pre>
52      exceptInfo {
53        u2 start_pc;
54        U2 end_pc;
55        u2 handler_pc;
56        u2 catch_type;
57      }
58   </pre>
59   
60   <p>
61      The attribute_name_index and attribute length are read by the
62      attrFactory.allocAttr method.  These values are passed into the class
63      constructor.
64   
65   <p>
66      In the exceptInfo the catch_type is an index into the constant
67      pool.  The object at this index must be a CONSTANT_Class_info
68      object (e.g., constClass_or_String) for an exception class that
69      this exception is designated to catch.  This class must be the
70      class Throwable or one of its subclasses.
71   <p>
72      Although code_length is 32-bits wide, its value must be less than
73      0x10000 (65536) (see JVM Spec 4.8.1).
74   <p>
75      The max_stack value is the size of the operand stack.  This in
76      in word units, where an int is one word and a long or double
77      is two:
78   
79        At any point in time an operand stack has an associated depth, 
80        where a value of type long or double contributes two units to 
81        the depth and a value of any other type contributes one unit. 
82        (JVM Spec 3.6.2)
83   
84      The max_locals value is the size of the local frame allocated on
85      entry to the method.  This frame will hold local variables and
86      method arguments.  As with max_stack, the units are words.  Like
87      the stack, the frame is word aligned so a boolean or a byte
88      occupies a word and a long or a double occupies two words (JVM
89      Spec 3.6.1).
90   
91      If max_locals is zero, then there are no local variables.
92   
93      If debug is turned and the method has local variables then
94      the codeAttributes table will contain a LocalVariableTable
95      attribute.  This attribute in turn contains a table of
96      local variable information.
97   
98      @author Ian Kaplan
99   
100   */
101  public class codeAttr extends attrInfo {
102    private int max_stack;
103    private int max_locals;
104    private byte codeBuf[];
105    private exceptInfo exceptTab[] = null;
106    private attrInfo codeAttributes[] = null;
107  
108  
109    //
110    // exceptInfo
111    //
112    // Exception information 
113    //
114    class exceptInfo {
115      int startPC;
116      int endPC;
117      int handlerPC;
118      constClass_or_String catch_type = null;
119  
120      exceptInfo( DataInputStream dStream, constPool constPoolSec ) {
121        startPC = readU2( dStream );
122        endPC = readU2( dStream );
123        handlerPC = readU2( dStream );
124        int catchTypeIx = readU2( dStream );
125  
126        if (catchTypeIx > 0) {
127  	constBase obj = constPoolSec.constPoolElem( catchTypeIx );
128  	if (obj != null && obj instanceof constClass_or_String) {
129  	  catch_type = (constClass_or_String)obj;
130  	}
131  	else {
132  	  errorMessage.errorPrint("exceptInfo: constClass_or_String expected in const pool index " + catchTypeIx );
133  	}
134        }
135      } // exceptInfo constructor
136  
137    } // exceptInfo (inner class)
138  
139  
140    /**
141       codeAttr constructor
142  
143       <p>  
144  
145       Here the length argument is the attribute length (e.g., the
146       total length of the attribute).
147  
148     */
149    public codeAttr( String name, int length, 
150  	    DataInputStream dStream, constPool constPoolSec ) {
151      super( name, length );  // invoke the attrInfo constructor
152  
153      max_stack = readU2( dStream );
154      max_locals = readU2( dStream );
155      int codeLen = readU4( dStream );
156  
157      if (codeLen > 0) {
158        codeBuf = new byte[ codeLen ];
159  
160        //
161        // Read the code into the code buffer.  The code is
162        // read byte by byte.  Since buffered input (e.g., the
163        // DataInputStream object) is used this should not be 
164        // a performace issue.
165        //
166        for (int i = 0; i < codeBuf.length; i++) {
167  	codeBuf[i] = (byte)readU1( dStream );
168        } // for
169      }
170  
171      int exceptLen = readU2( dStream );
172  
173      if (exceptLen > 0) {
174        exceptTab = new exceptInfo[ exceptLen ];
175  
176        for (int i = 0; i < exceptLen; i++) {
177  	exceptTab[i] = new exceptInfo( dStream, constPoolSec );
178        }
179      }
180  
181      int attrCount = readU2( dStream );
182  
183      if (attrCount > 0) {
184        codeAttributes = new attrInfo[ attrCount ];
185  
186        for (int i = 0; i < attrCount; i++) {
187  	codeAttributes[i] = attrFactory.allocAttr( dStream, constPoolSec );
188        } // for
189      }
190    } // codeAttr constructor
191  
192    /**
193      If there are local variables in the method, return a vector
194      containing the local variable name declarations.  There should
195      be only one localVarTabAttr in the codeAttributes table.
196     */
197    public Vector getLocalVarVec() {
198      Vector varVec = null;
199  
200      if (codeAttributes != null) {
201        for (int i = 0; i < codeAttributes.length; i++) {
202  	if (codeAttributes[i] instanceof localVarTabAttr) {
203  	  varVec = ((localVarTabAttr)codeAttributes[i]).getLocalVarVec();
204  	  break;
205  	}
206        } // for
207  
208      } // if
209  
210      return varVec;
211    }  // getLocalVarVec
212  
213  
214    public int getMax_locals() { return max_locals; }
215    public int getMax_stack() { return max_stack; }
216  
217  } // codeAttr
218