123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363 |
- // Copyright (c) 1997, 2004, 2008 Per M.A. Bothner.
- // This is free software; for terms and warranty disclaimer see ./COPYING.
- package gnu.bytecode;
- import java.io.InputStream;
- import java.io.DataInputStream;
- import java.io.IOException;
- /** Class to read a ClassType from a DataInputStream (.class file).
- * @author Per Bothner
- */
- public class ClassFileInput extends DataInputStream
- {
- ClassType ctype;
- InputStream str;
- public ClassFileInput (InputStream str)
- throws IOException
- {
- super(str);
- }
- public ClassFileInput (ClassType ctype, InputStream str)
- throws IOException, ClassFormatError
- {
- super(str);
- this.ctype = ctype;
- if (!readHeader())
- throw new ClassFormatError("invalid magic number");
- ctype.constants = readConstants();
- readClassInfo();
- readFields();
- readMethods();
- readAttributes(ctype);
- }
-
- /** Read a class (in .class format) from an InputStream.
- * @return A new ClassType object representing the class that was read.
- */
- public static ClassType readClassType (InputStream str)
- throws IOException, ClassFormatError
- {
- ClassType ctype = new ClassType();
- new ClassFileInput(ctype, str);
- return ctype;
- }
- public boolean readHeader () throws IOException
- {
- int magic = readInt();
- if (magic != 0xcafebabe)
- return false;
- readFormatVersion();
- return true;
- }
- public void readFormatVersion () throws IOException
- {
- int minor = readUnsignedShort();
- int major = readUnsignedShort();
- ctype.classfileFormatVersion = major * 0x10000 + minor;
- }
- public ConstantPool readConstants () throws IOException
- {
- return new ConstantPool(this);
- }
- public void readClassInfo () throws IOException
- {
- ctype.access_flags = readUnsignedShort();
- CpoolClass clas;
- String name;
- ctype.thisClassIndex = readUnsignedShort();
- clas = getClassConstant(ctype.thisClassIndex);
- name = clas.name.string;
- ctype.this_name = name.replace('/', '.');
- ctype.setSignature("L"+name+";");
- ctype.superClassIndex = readUnsignedShort();
- if (ctype.superClassIndex == 0)
- ctype.setSuper((ClassType) null);
- else
- {
- clas = getClassConstant(ctype.superClassIndex);
- name = clas.name.string;
- ctype.setSuper(name.replace('/', '.'));
- }
- int nInterfaces = readUnsignedShort();
- if (nInterfaces > 0)
- {
- ctype.interfaces = new ClassType[nInterfaces];
- ctype.interfaceIndexes = new int[nInterfaces];
- for (int i = 0; i < nInterfaces; i++)
- {
- int index = readUnsignedShort();
- ctype.interfaceIndexes[i] = index;
- clas = (CpoolClass) ctype.constants.getForced(index,
- ConstantPool.CLASS);
- name = clas.name.string.replace('/', '.');
- ctype.interfaces[i] = ClassType.make(name);
- }
- }
- }
- public int readAttributes (AttrContainer container) throws IOException
- {
- int count = readUnsignedShort();
- Attribute last = container.getAttributes();
- for (int i = 0; i < count; i++)
- {
- if (last != null)
- {
- for (;;)
- {
- Attribute next = last.getNext();
- if (next == null)
- break;
- last = next;
- }
- }
-
- int index = readUnsignedShort();
- CpoolUtf8 nameConstant = (CpoolUtf8)
- ctype.constants.getForced(index, ConstantPool.UTF8);
- int length = readInt();
- nameConstant.intern();
- Attribute attr = readAttribute(nameConstant.string, length, container);
- if (attr != null)
- {
- if (attr.getNameIndex() == 0)
- attr.setNameIndex(index);
- if (last == null)
- container.setAttributes(attr);
- else
- {
- if (container.getAttributes()==attr)
- { /* Move to end. */
- container.setAttributes(attr.getNext());
- attr.setNext(null);
- }
- last.setNext(attr);
- }
- last = attr;
- }
- }
- return count;
- }
- public final void skipAttribute (int length)
- throws IOException
- {
- int read = 0;
- while (read < length)
- {
- int skipped = (int) skip(length - read);
- if (skipped == 0)
- {
- if (read() < 0)
- throw new java.io.EOFException
- ("EOF while reading class files attributes");
- skipped = 1;
- }
- read += skipped;
- }
- }
- public Attribute readAttribute (String name, int length, AttrContainer container)
- throws IOException
- {
- if (name == "SourceFile" && container instanceof ClassType)
- {
- return new SourceFileAttr(readUnsignedShort(), (ClassType) container);
- }
- else if (name == "Code" && container instanceof Method)
- {
- CodeAttr code = new CodeAttr((Method) container);
- code.fixup_count = -1;
- code.setMaxStack(readUnsignedShort());
- code.setMaxLocals(readUnsignedShort());
- int code_len = readInt();
- byte[] insns = new byte[code_len];
- readFully(insns);
- code.setCode(insns);
- int exception_table_length = readUnsignedShort();
- for (int i = 0; i < exception_table_length; i++)
- {
- int start_pc = readUnsignedShort();
- int end_pc = readUnsignedShort();
- int handler_pc = readUnsignedShort();
- int catch_type = readUnsignedShort();
- code.addHandler(start_pc, end_pc, handler_pc, catch_type);
- }
- readAttributes(code);
- return code;
- }
- else if (name == "LineNumberTable" && container instanceof CodeAttr)
- {
- int count = 2 * readUnsignedShort();
- short[] numbers = new short[count];
- for (int i = 0; i < count; i++)
- {
- numbers[i] = readShort();
- }
- return new LineNumbersAttr(numbers, (CodeAttr) container);
- }
- else if (name == "LocalVariableTable" && container instanceof CodeAttr)
- {
- CodeAttr code = (CodeAttr) container;
- LocalVarsAttr attr = new LocalVarsAttr(code);
- Method method = attr.getMethod();
- if (attr.parameter_scope == null)
- attr.parameter_scope = method.pushScope();
- Scope scope = attr.parameter_scope;
- if (scope.end == null)
- scope.end = new Label(code.PC);
- ConstantPool constants = method.getConstants();
- int count = readUnsignedShort();
- int prev_start = scope.start.position;
- int prev_end = scope.end.position;
- for (int i = 0; i < count; i++)
- {
- Variable var = new Variable();
- int start_pc = readUnsignedShort();
- int end_pc = start_pc + readUnsignedShort();
- if (start_pc != prev_start || end_pc != prev_end)
- {
- while (scope.parent != null
- && (start_pc < scope.start.position
- || end_pc > scope.end.position))
- scope = scope.parent;
- Scope parent = scope;
- scope = new Scope(new Label(start_pc), new Label(end_pc));
- scope.linkChild(parent);
- prev_start = start_pc;
- prev_end = end_pc;
- }
- scope.addVariable(var);
- var.setName(readUnsignedShort(), constants);
- var.setSignature(readUnsignedShort(), constants);
- var.offset = readUnsignedShort();
- }
- return attr;
- }
- else if (name == "Signature" && container instanceof Member)
- {
- return new SignatureAttr(readUnsignedShort(), (Member) container);
- }
- else if (name == "StackMapTable" && container instanceof CodeAttr)
- {
- byte[] data = new byte[length];
- readFully(data, 0, length);
- return new StackMapTableAttr(data, (CodeAttr) container);
- }
- else if ((name == "RuntimeVisibleAnnotations"
- || name == "RuntimeInvisibleAnnotations")
- && (container instanceof Field
- || container instanceof Method
- || container instanceof ClassType))
- {
- int numEntries = readUnsignedShort();
- AnnotationEntry[] entries = new AnnotationEntry[numEntries];
- for (int i = 0; i < numEntries; i++)
- {
- entries[i] = RuntimeAnnotationsAttr.readAnnotationEntry(this, container.getConstants());
- }
- return new RuntimeAnnotationsAttr(name, entries, numEntries, container);
- }
- else if (name == "ConstantValue" && container instanceof Field)
- {
- return new ConstantValueAttr(readUnsignedShort());
- }
- else if (name == "InnerClasses" && container instanceof ClassType)
- {
- int count = 4 * readUnsignedShort();
- short[] data = new short[count];
- for (int i = 0; i < count; i++)
- {
- data[i] = readShort();
- }
- return new InnerClassesAttr(data, (ClassType) container);
- }
- else if (name == "EnclosingMethod" && container instanceof ClassType)
- {
- int class_index = readUnsignedShort();
- int method_index = readUnsignedShort();
- return new EnclosingMethodAttr(class_index, method_index, (ClassType) container);
- }
- else if (name == "Exceptions" && container instanceof Method)
- {
- Method meth = (Method)container;
- int count = readUnsignedShort();
- short[] exn_indices = new short[count];
- for (int i = 0; i < count; ++i)
- exn_indices[i] = readShort();
- meth.setExceptions(exn_indices);
- return meth.getExceptionAttr();
- }
- else if (name == "SourceDebugExtension" && container instanceof ClassType)
- {
- SourceDebugExtAttr attr
- = new SourceDebugExtAttr((ClassType) container);
- byte[] data = new byte[length];
- readFully(data, 0, length);
- attr.data = data;
- attr.dlength = length;
- return attr;
- }
- else if (name == "AnnotationDefault" && container instanceof Method)
- {
- AnnotationEntry.Value value = RuntimeAnnotationsAttr.readAnnotationValue(this, container.getConstants());
- return new AnnotationDefaultAttr(name, value, container);
- }
- else
- {
- byte[] data = new byte[length];
- readFully(data, 0, length);
- return new MiscAttr(name, data);
- }
- }
- public void readFields () throws IOException
- {
- int nFields = readUnsignedShort();
- ConstantPool constants = ctype.constants;
- for (int i = 0; i < nFields; i++)
- {
- int flags = readUnsignedShort();
- int nameIndex = readUnsignedShort();
- int descriptorIndex = readUnsignedShort();
- Field fld = ctype.addField();
- fld.setName(nameIndex, constants);
- fld.setSignature(descriptorIndex, constants);
- fld.flags = flags;
- readAttributes(fld);
- }
- }
- public void readMethods () throws IOException
- {
- int nMethods = readUnsignedShort();
- for (int i = 0; i < nMethods; i++)
- {
- int flags = readUnsignedShort();
- int nameIndex = readUnsignedShort();
- int descriptorIndex = readUnsignedShort();
- Method meth = ctype.addMethod(null, flags);
- meth.setName(nameIndex);
- meth.setSignature(descriptorIndex);
- readAttributes(meth);
- }
- }
- CpoolClass getClassConstant (int index)
- {
- return (CpoolClass) ctype.constants.getForced(index, ConstantPool.CLASS);
- }
- }
|