ClassFileInput.java 10 KB

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