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 <p> 26 This object represents the local variable table. The local 27 variable table is an attribute that may be in the attribute table 28 of the code attribute (codeAttr object). This attribute is 29 generated by the Java compiler when debug is turned on (-g). 30 <p> 31 The JVM Spec. states: 32 33 <blockquote> 34 It may be used by debuggers to determine the value of a given 35 local variable during the execution of a method. If 36 LocalVariableTable attributes are present in the attributes table 37 of a given Code attribute, then they may appear in any 38 order. There may be no more than one LocalVariableTable attribute 39 per local variable in the Code attribute. (JVM 4.7.9) 40 </blockquote> 41 42 <p> 43 This is rather misleading. The local variable table contains 44 information about the local variable declarations. There is one 45 entry for each local variable (the table includes the class 46 reference variable "this"). 47 <p> 48 The LocalVariableTable attribute has the format 49 50 <pre> 51 LocalVariableTable_attribute { 52 53 u2 attribute_name_index; 54 u4 attribute_length; 55 u2 local_variable_table_length; 56 localVarEnt local_variable_table[local_variable_table_length]; 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 63 class constructor. 64 <p> 65 The localVarEnt is 66 67 <pre> 68 localVarEnt { 69 u2 start_pc; 70 u2 length; 71 u2 name_index; 72 u2 descriptor_index; 73 u2 index; 74 } 75 </pre> 76 77 <p> 78 There is one localVarEnt structure for each local variable. 79 80 <p> 81 The JVM Spec (4.7.9) states: 82 83 <blockquote> 84 The given local variable must have a value at indices into the 85 code array in the interval [start_pc, start_pc+length], that is, 86 between start_pc and start_pc+length inclusive. The value of 87 start_pc must be a valid index into the code array of this Code 88 attribute of the opcode of an instruction. The value of 89 start_pc+length must be either a valid index into the code array 90 of this Code attribute of the opcode of an instruction, or the 91 first index beyond the end of that code array. 92 </blockquote> 93 94 <p> 95 So the byte code from start_pc to start_pc+length seems to indicate 96 the live range for the variable. That is, the variable is assigned 97 a value at the start of the range and may be assigned other values 98 through out the range. The range ends with the last reference to 99 the variable. 100 <p> 101 If an optimizing compiler generated the code and the variable is 102 "dead" at a point in the source where a a debugger asks for its 103 value or attempts to write the value then the debugger can report 104 that the value is unavailable. 105 <p> 106 The start_pc (the offset into the code array) is 16-bits. However, 107 the size of the code array is 32-bits. In theory this means that 108 there may be indices that can't be referenced. In practice the 109 size of Java objects seems to be limited (at least up through 110 release 1.2). 111 <p> 112 The name_index is an index into the constant table for the 113 constUtf8 object for the variable name. 114 <p> 115 The descriptor_index is an index into the constant table for the 116 constUtf8 object for the variable descriptor that describes the 117 object. 118 <p> 119 The index field is the frame offset location for the local 120 variable. 121 <p> 122 The JVM Spec states for the index: 123 124 <blockquote> 125 The given local variable must be at index in its method's local 126 variables. If the local variable at index is a two-word type 127 (double or long), it occupies both index and index+1. 128 </blockquote> 129 130 <p> 131 By local variables, the JVM Spec is referring to the local frame. 132 Note that frames are not necessarily allocated on the stack. 133 134 @author Ian Kaplan 135 136 */ 137 class localVarlocalVarTabAttr attrInfo { 138 localVarEnt localVarTab[]; 139 140 /** 141 142 Local variable entry in the local variable table. 143 144 */ 145 class localVarEnt { 146 int start_pc; 147 int length; 148 constUtf8 memberName = null; 149 constUtf8 memberDesc = null; 150 int index; 151 152 localVarEnt( DataInputStream dStream, constPool constPoolSec ) { 153 int name_index; 154 int descriptor_index; 155 constBase obj; 156 157 start_pc = readU2( dStream ); 158 length = readU2( dStream ); 159 name_index = readU2( dStream ); 160 descriptor_index = readU2( dStream ); 161 index = readU2( dStream ); 162 163 if (name_index > 0) { 164 obj = constPoolSec.constPoolElem( name_index ); 165 if (obj != null && obj instanceof constUtf8) { 166 memberName = (constUtf8)obj; 167 } 168 } 169 170 if (descriptor_index > 0) { 171 obj = constPoolSec.constPoolElem( descriptor_index ); 172 if (obj != null && obj instanceof constUtf8) { 173 memberDesc = (constUtf8)obj; 174 } 175 } 176 } // localVarEnt class constructor 177 178 179 /** 180 Return a String for the local variable declaration or 181 null if memberDesc or member name are null. 182 183 */ 184 String getLocalVarDecl() { 185 String localDecl = null; 186 187 if (memberDesc != null && memberName != null) { 188 String type; 189 String name; 190 191 type = typeDesc.decodeFieldDesc( memberDesc.getString() ); 192 name = memberName.getString(); 193 localDecl = type + " " + name + ";" + " // index = " + index; 194 } 195 196 return localDecl; 197 } // getLocalVarDecl 198 199 200 } // localVarEnt class 201 202 203 localVarTabAttr( String name, int length, 204 DataInputStream dStream, constPool constPoolSec ) { 205 super( name, length ); 206 int numVarEnt = readU2( dStream ); 207 208 if (numVarEnt > 0) { 209 localVarTab = new localVarEnt[ numVarEnt ]; 210 211 for (int i = 0; i < numVarEnt; i++) { 212 localVarTab[i] = new localVarEnt( dStream, constPoolSec ); 213 } 214 } 215 } 216 217 218 public Vector getLocalVarVec() { 219 Vector localVarVec = null; 220 String localDecl; 221 222 if (localVarTab != null) { 223 for (int i = 0; i < localVarTab.length; i++) { 224 if (localVarVec == null) 225 localVarVec = new Vector(); 226 227 localDecl = localVarTab[i].getLocalVarDecl(); 228 localVarVec.addElement( localDecl ); 229 } 230 } 231 return localVarVec; 232 } // getLocalVarVec 233 234 235 } // localVarTabAttr 236