FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

GitHub Viewer

using System; using System.Runtime.InteropServices; using AlphaOmega.Debug.ConstantData; using AlphaOmega.Debug.AttributeData; namespace AlphaOmega.Debug { /// /// Each class file contains the definition of a single class or interface. /// Although a class or interface need not have an external representation literally contained in a file (for instance, because the class is generated by a class loader), we will colloquially refer to any valid representation of a class or interface as being in the class file format. /// /// https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html public class ClassFile : IDisposable { /// Class file loader private IImageLoader _loader; private readonly Jvm.ClassFile1 _header1; private Jvm.ClassFile2 _header2; private ConstantTables _constantPool; /// The magic item supplies the magic number identifying the class file format; it has the value 0xCAFEBABE public UInt32 Magic => this._header1.magic; /// Minor class file version public UInt16 MinorVersion => this._header1.minor_version; /// Major class file version public UInt16 MajorVersion => this._header1.major_version; /// A index is considered valid if it is greater than zero and less than , with the exception for constants of type long and double noted in §4.4.5 /// The value of the item is equal to the number of entries in the table plus one public UInt16 ConstantPoolCount => this._header1.constant_pool_count; /// /// The is a table of structures (§4.4) representing various string constants, class and interface names, field names, and other constants that are referred to within the ClassFile structure and its substructures. /// The format of each table entry is indicated by its first "tag" byte. /// /// The table is indexed from 1 to constant_pool_count-1 public ConstantTables ConstantPool { get { if(this._constantPool == null) { UInt32 offset = (UInt32)Marshal.SizeOf(typeof(Jvm.ClassFile1)); this._constantPool = new ConstantTables(this, ref offset); } return this._constantPool; } } /// The value of the access_flags item is a mask of flags used to denote access permissions to and properties of this class or interface public Jvm.ClassFile2.ACC AccessFlags => this._header2.access_flags; /// The entry at that index must be a structure (§4.4.1) representing the class or interface defined by this class file /// The value of the this_class item must be a valid index into the table public Utf8Row ThisClass { get { ClassRow row = this.ConstantPool.Class[this._header2.this_class]; return this.ConstantPool.Utf8[row.NameIndex.Index]; } } /// /// For a class, the value of the super_class item either must be zero or must be a valid index into the table. /// If the value of the super_class item is nonzero, the entry at that index must be a structure (§4.4.1) representing the direct superclass of the class defined by this class file. Neither the direct superclass nor any of its superclasses may have the ACC_FINAL flag set in the access_flags item of its ClassFile structure. /// /// If the value of the super_class item is zero, then this class file must represent the class Object, the only class or interface without a direct superclass. /// For an interface, the value of the super_class item must always be a valid index into the table. /// The entry at that index must be a structure representing the class Object. /// public Utf8Row SuperClass { get { if(this._header2.super_class == 0) return null; ClassRow row = this.ConstantPool.Class[this._header2.super_class]; return this.ConstantPool.Utf8[row.NameIndex.Index]; } } /// The value of the interfaces_count item gives the number of direct superinterfaces of this class or interface type public UInt16 InterfacesCount => this._header2.interfaces_count; /// The entry at each value of interfaces[i], where 0 ≤ i < interfaces_count, must be a structure (§4.4.1) representing an interface that is a direct superinterface of this class or interface type, in the left-to-right order given in the source for the type /// Each value in the interfaces array must be a valid index into the table public ClassRow[] Interfaces { get; private set; } /// /// Each value in the fields table must be a field_info (§4.5) structure giving a complete description of a field in this class or interface. /// The fields table includes only those fields that are declared by this class or interface. /// It does not include items representing fields that are inherited from superclasses or superinterfaces. /// public Field_Info[] Fields { get; private set; } /// /// Each value in the methods table must be a method_info (§4.6) structure giving a complete description of a method in this class or interface. /// If neither of the ACC_NATIVE and ACC_ABSTRACT flags are set in the access_flags item of a method_info structure, the Java Virtual Machine instructions implementing the method are also supplied. /// /// /// The method_info structures represent all methods declared by this class or interface type, including instance methods, class methods, instance initialization methods (§2.9), and any class or interface initialization method (§2.9). /// The methods table does not include items representing methods that are inherited from superclasses or superinterfaces. /// public MethodInfo[] Methods { get; private set; } /// Each value of the attributes table must be an attribute_info (§4.7) structure. /// /// The attributes defined by this specification as appearing in the attributes table of a ClassFile structure are the InnerClasses (§4.7.6), EnclosingMethod (§4.7.7), Synthetic (§4.7.8), Signature (§4.7.9), SourceFile (§4.7.10), SourceDebugExtension (§4.7.11), Deprecated (§4.7.15), RuntimeVisibleAnnotations (§4.7.16), RuntimeInvisibleAnnotations (§4.7.17), and BootstrapMethods (§4.7.21) attributes. /// If a Java Virtual Machine implementation recognizes class files whose version number is 49.0 or above, it must recognize and correctly read Signature (§4.7.9), RuntimeVisibleAnnotations (§4.7.16), and RuntimeInvisibleAnnotations (§4.7.17) attributes found in the attributes table of a ClassFile structure of a class file whose version number is 49.0 or above. /// If a Java Virtual Machine implementation recognizes class files whose version number is 51.0 or above, it must recognize and correctly read BootstrapMethods (§4.7.21) attributes found in the attributes table of a ClassFile structure of a class file whose version number is 51.0 or above. /// A Java Virtual Machine implementation is required to silently ignore any or all attributes in the attributes table of a ClassFile structure that it does not recognize. Attributes not defined in this specification are not allowed to affect the semantics of the class file, but only to provide additional descriptive information (§4.7.1). /// public AttributeReference[] Attributes { get; private set; } /// Class files is valid public Boolean IsValid => this._header1.IsValid; /// /// The values of the minor_version and major_version items are the minor and major version numbers of this class file. /// Together, a major and a minor version number determine the version of the class file format. /// If a class file has major version number M and minor version number m, we denote the version of its class file format as M.m. /// Thus, class file format versions may be ordered lexicographically, for example, 1.5 < 2.0 < 2.1. /// /// /// A Java Virtual Machine implementation can support a class file format of version v if and only if v lies in some contiguous range Mi.0 ≤ v ≤ Mj.m. /// The release level of the Java SE platform to which a Java Virtual Machine implementation conforms is responsible for determining the range. /// public Version Version => this._header1.Version; /// All attributes from all structures public AttributeTables AttributePool { get; } /// Create instance of Class file reader /// Image loader /// loader is null /// Magic number is invalid public ClassFile(IImageLoader loader) { this._loader = loader ?? throw new ArgumentNullException(nameof(loader)); this._loader.Endianness = EndianHelper.Endian.Big; this._header1 = this.PtrToStructure(0); if(!this._header1.IsValid) throw new ArgumentException("Invalid class file"); this.AttributePool = new AttributeTables(this); this.ReadClassFile(); } private void ReadClassFile() { /*offset += (UInt32)Marshal.SizeOf(typeof(Jvm.ClassFile1)); ConstantTables constantPool = new ConstantTables(this, ref offset);*/ UInt32 offset = (UInt32)Marshal.SizeOf(typeof(Jvm.ClassFile1)) + this.ConstantPool.DataLength; this._header2 = this.PtrToStructure(offset); offset += (UInt32)Marshal.SizeOf(typeof(Jvm.ClassFile2)); //interfaces this.Interfaces = new ClassRow[this._header2.interfaces_count]; for(Int32 loop = 0; loop < this.Interfaces.Length; loop++) { UInt16 classIndex = this.PtrToStructure(offset); offset += (UInt16)Marshal.SizeOf(typeof(UInt16)); this.Interfaces[loop] = this.ConstantPool.Class[classIndex]; } //fields UInt16 fields_count = this.PtrToStructure(offset); offset += (UInt16)Marshal.SizeOf(typeof(UInt16)); this.Fields = new Field_Info[fields_count]; for(Int32 loop = 0; loop < this.Fields.Length; loop++) { UInt32 start = offset; Jvm.field_info field = this.PtrToStructure(offset); offset += (UInt16)Marshal.SizeOf(typeof(Jvm.field_info)); AttributeReference[] attributes = this.AttributePool.ReadAttributes(field.attributes_count, ref offset); UInt32 dataLength = offset - start; this.Fields[loop] = new Field_Info(this, field, attributes, start, dataLength); } //methods UInt16 methods_count = this.PtrToStructure(offset); offset += (UInt16)Marshal.SizeOf(typeof(UInt16)); this.Methods = new MethodInfo[methods_count]; for(Int32 loop = 0; loop < this.Methods.Length; loop++) { UInt32 start = offset; Jvm.method_info method = this.PtrToStructure(offset); offset += (UInt16)Marshal.SizeOf(typeof(Jvm.method_info)); AttributeReference[] attributes = this.AttributePool.ReadAttributes(method.attributes_count, ref offset); UInt32 dataLength = offset - start; this.Methods[loop] = new MethodInfo(this, method, attributes, start, dataLength); } UInt16 attributes_count = this.PtrToStructure(offset); offset += (UInt16)Marshal.SizeOf(typeof(UInt16)); this.Attributes = this.AttributePool.ReadAttributes(attributes_count, ref offset); } /// Read bytes from image /// RVA to start address /// How much to read /// Read bytes public Byte[] ReadBytes(UInt32 offset, UInt32 length) { UInt32 rva = offset; /*if(!this.Loader.IsModuleMapped) rva = this.OffsetToRva(offset);*/ return this._loader.ReadBytes(rva, length); } /// Get structure from specific RVA /// Structure to map /// RVA to the beginning of structure /// Mapped structure public T PtrToStructure(UInt32 offset) where T : struct { UInt32 rva = offset; /*if(!this.Loader.IsModuleMapped) rva = this.OffsetToRva(offset);*/ UInt32 length = (UInt32)Marshal.SizeOf(typeof(T)); Byte[] data = this.ReadBytes(rva, length); return this._loader.PtrToStructure(rva); } /// Get string from specific RVA /// RVA to the beginning of string /// Mapped string public String PtrToStringAnsi(UInt32 offset) { UInt32 rva = offset; /*if(!this.Loader.IsModuleMapped) rva = this.OffsetToRva(offset);*/ return this._loader.PtrToStringAnsi(rva); } /// Close loader public void Dispose() { this.Dispose(true); GC.SuppressFinalize(this); } /// Dispose managed objects /// Dispose managed objects protected virtual void Dispose(Boolean disposing) { if(disposing && this._loader != null) { this._loader.Dispose(); this._loader = null; } } } }

Back | FazBrowse Home | New Git URL