1 4 package gnu.bytecode; 5 import java.io.InputStream ; 6 import java.io.DataInputStream ; 7 import java.io.IOException ; 8 9 12 13 public class ClassFileInput extends DataInputStream 14 { 15 ClassType ctype; 16 InputStream str; 17 18 public ClassFileInput (InputStream str) 19 throws IOException 20 { 21 super(str); 22 } 23 24 public ClassFileInput (ClassType ctype, InputStream str) 25 throws IOException , ClassFormatError 26 { 27 super(str); 28 this.ctype = ctype; 29 if (!readHeader()) 30 throw new ClassFormatError ("invalid magic number"); 31 ctype.constants = readConstants(); 32 readClassInfo(); 33 readFields(); 34 readMethods(); 35 readAttributes(ctype); 36 } 37 38 41 public static ClassType readClassType (InputStream str) 42 throws IOException , ClassFormatError 43 { 44 ClassType ctype = new ClassType(); 45 new ClassFileInput(ctype, str); 46 return ctype; 47 } 48 49 public boolean readHeader () throws IOException 50 { 51 int magic = readInt(); 52 if (magic != 0xcafebabe) 53 return false; 54 int minor = readUnsignedShort(); 55 int major = readUnsignedShort(); 56 ctype.classfileFormatVersion = major * 0x10000 + minor; 57 return true; 58 } 59 60 public ConstantPool readConstants () throws IOException 61 { 62 return new ConstantPool(this); 63 } 64 65 public void readClassInfo () throws IOException 66 { 67 ctype.access_flags = readUnsignedShort(); 68 CpoolClass clas; 69 String name; 70 71 ctype.thisClassIndex = readUnsignedShort(); 72 clas = (CpoolClass) ctype.constants.getForced(ctype.thisClassIndex, 73 ConstantPool.CLASS); 74 name = clas.name.string; 75 ctype.this_name = name.replace('/', '.'); 76 ctype.setSignature("L"+name+";"); 77 78 ctype.superClassIndex = readUnsignedShort(); 79 if (ctype.superClassIndex == 0) 80 ctype.setSuper((ClassType) null); 81 else 82 { 83 clas = (CpoolClass) ctype.constants.getForced(ctype.superClassIndex, 84 ConstantPool.CLASS); 85 name = clas.name.string; 86 ctype.setSuper(name.replace('/', '.')); 87 } 88 89 int nInterfaces = readUnsignedShort(); 90 if (nInterfaces > 0) 91 { 92 ctype.interfaces = new ClassType[nInterfaces]; 93 ctype.interfaceIndexes = new int[nInterfaces]; 94 for (int i = 0; i < nInterfaces; i++) 95 { 96 int index = readUnsignedShort(); 97 ctype.interfaceIndexes[i] = index; 98 clas = (CpoolClass) ctype.constants.getForced(index, 99 ConstantPool.CLASS); 100 name = clas.name.string.replace('/', '.'); 101 ctype.interfaces[i] = ClassType.make(name); 102 } 103 } 104 } 105 106 public int readAttributes (AttrContainer container) throws IOException 107 { 108 int count = readUnsignedShort(); 109 Attribute last = container.getAttributes(); 110 for (int i = 0; i < count; i++) 111 { 112 if (last != null) 113 { 114 for (;;) 115 { 116 Attribute next = last.getNext(); 117 if (next == null) 118 break; 119 last = next; 120 } 121 } 122 123 int index = readUnsignedShort(); 124 CpoolUtf8 nameConstant = (CpoolUtf8) 125 ctype.constants.getForced(index, ConstantPool.UTF8); 126 int length = readInt(); 127 nameConstant.intern(); 128 Attribute attr = readAttribute(nameConstant.string, length, container); 129 if (attr != null) 130 { 131 if (attr.getNameIndex() == 0) 132 attr.setNameIndex(index); 133 if (last == null) 134 container.setAttributes(attr); 135 else 136 { 137 if (container.getAttributes()==attr) 138 { 139 container.setAttributes(attr.getNext()); 140 attr.setNext(null); 141 } 142 last.setNext(attr); 143 } 144 last = attr; 145 } 146 } 147 return count; 148 } 149 150 public final void skipAttribute (int length) 151 throws IOException 152 { 153 int read = 0; 154 while (read < length) 155 { 156 int skipped = (int) skip(length - read); 157 if (skipped == 0) 158 { 159 if (read() < 0) 160 throw new java.io.EOFException 161 ("EOF while reading class files attributes"); 162 skipped = 1; 163 } 164 read += skipped; 165 } 166 } 167 168 public Attribute readAttribute (String name, int length, AttrContainer container) 169 throws IOException 170 { 171 if (name == "SourceFile" && container instanceof ClassType) 172 { 173 return new SourceFileAttr(readUnsignedShort(), (ClassType) container); 174 } 175 else if (name == "Code" && container instanceof Method) 176 { 177 CodeAttr code = new CodeAttr((Method) container); 178 code.setMaxStack(readUnsignedShort()); 179 code.setMaxLocals(readUnsignedShort()); 180 int code_len = readInt(); 181 byte[] insns = new byte[code_len]; 182 readFully(insns); 183 code.setCode(insns); 184 int exception_table_length = readUnsignedShort(); 185 for (int i = 0; i < exception_table_length; i++) 186 { 187 int start_pc = readUnsignedShort(); 188 int end_pc = readUnsignedShort(); 189 int handler_pc = readUnsignedShort(); 190 int catch_type = readUnsignedShort(); 191 code.addHandler(start_pc, end_pc, handler_pc, catch_type); 192 } 193 readAttributes(code); 194 return code; 195 } 196 else if (name == "LineNumberTable" && container instanceof CodeAttr) 197 { 198 int count = 2 * readUnsignedShort(); 199 short[] numbers = new short[count]; 200 for (int i = 0; i < count; i++) 201 { 202 numbers[i] = readShort(); 203 } 204 return new LineNumbersAttr(numbers, (CodeAttr) container); 205 } 206 else if (name == "LocalVariableTable" && container instanceof CodeAttr) 207 { 208 CodeAttr code = (CodeAttr) container; 209 LocalVarsAttr attr = new LocalVarsAttr(code); 210 Method method = attr.getMethod(); 211 if (attr.parameter_scope == null) 212 attr.parameter_scope = method.pushScope(); 213 Scope scope = attr.parameter_scope; 214 if (scope.end == null) 215 scope.end = new Label(code.PC); 216 ConstantPool constants = method.getConstants(); 217 int count = readUnsignedShort(); 218 int prev_start = scope.start.position; 219 int prev_end = scope.end.position; 220 for (int i = 0; i < count; i++) 221 { 222 Variable var = new Variable(); 223 int start_pc = readUnsignedShort(); 224 int end_pc = start_pc + readUnsignedShort(); 225 226 if (start_pc != prev_start || end_pc != prev_end) 227 { 228 while (scope.parent != null 229 && (start_pc < scope.start.position 230 || end_pc > scope.end.position)) 231 scope = scope.parent; 232 Scope parent = scope; 233 scope = new Scope(new Label(start_pc), new Label(end_pc)); 234 scope.linkChild(parent); 235 prev_start = start_pc; 236 prev_end = end_pc; 237 } 238 scope.addVariable(var); 239 var.setName(readUnsignedShort(), constants); 240 var.setSignature(readUnsignedShort(), constants); 241 var.offset = readUnsignedShort(); 242 } 243 return attr; 244 } 245 else if (name == "ConstantValue" && container instanceof Field) 246 { 247 return new ConstantValueAttr(readUnsignedShort()); 248 } 249 else if (name == "InnerClasses" && container instanceof ClassType) 250 { 251 int count = 4 * readUnsignedShort(); 252 short[] data = new short[count]; 253 for (int i = 0; i < count; i++) 254 { 255 data[i] = readShort(); 256 } 257 return new InnerClassesAttr(data, (ClassType) container); 258 } 259 else if (name == "Exceptions" && container instanceof Method) 260 { 261 Method meth = (Method)container; 262 int count = readUnsignedShort(); 263 short[] exn_indices = new short[count]; 264 for (int i = 0; i < count; ++i) 265 exn_indices[i] = readShort(); 266 meth.setExceptions(exn_indices); 267 return meth.getExceptionAttr(); 268 } 269 else if (name == "SourceDebugExtension" && container instanceof ClassType) 270 { 271 SourceDebugExtAttr attr 272 = new SourceDebugExtAttr((ClassType) container); 273 byte[] data = new byte[length]; 274 readFully(data, 0, length); 275 attr.data = data; 276 attr.dlength = length; 277 return attr; 278 } 279 else 280 { 281 byte[] data = new byte[length]; 282 readFully(data, 0, length); 283 return new MiscAttr(name, data); 284 } 285 } 286 287 public void readFields () throws IOException 288 { 289 int nFields = readUnsignedShort(); 290 ConstantPool constants = ctype.constants; 291 for (int i = 0; i < nFields; i++) 292 { 293 int flags = readUnsignedShort(); 294 int nameIndex = readUnsignedShort(); 295 int descriptorIndex = readUnsignedShort(); 296 Field fld = ctype.addField(); 297 fld.setName(nameIndex, constants); 298 fld.setSignature(descriptorIndex, constants); 299 fld.flags = flags; 300 readAttributes(fld); 301 } 302 } 303 304 public void readMethods () throws IOException 305 { 306 int nMethods = readUnsignedShort(); 307 for (int i = 0; i < nMethods; i++) 308 { 309 int flags = readUnsignedShort(); 310 int nameIndex = readUnsignedShort(); 311 int descriptorIndex = readUnsignedShort(); 312 Method meth = ctype.addMethod(null, flags); 313 meth.setName(nameIndex); 314 meth.setSignature(descriptorIndex); 315 readAttributes(meth); 316 } 317 } 318 } 319 | Popular Tags |