/* * Copyright (c) Contributors, http://opensimulator.org/ * See CONTRIBUTORS.TXT for a full list of copyright holders. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the OpenSim Project nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ using System; using System.Collections.Generic; using System.IO; using OpenSim.Region.ExtensionsScriptModule.JVMEngine.Types; using OpenSim.Region.ExtensionsScriptModule.JVMEngine.Types.PrimitiveTypes; namespace OpenSim.Region.ExtensionsScriptModule.JVMEngine.JVM { public class ClassRecord { private ushort m_majorVersion; private ushort m_minorVersion; private ushort m_constantPoolCount; private ushort m_accessFlags; private ushort m_thisClass; private ushort m_supperClass; private ushort m_interfaceCount; private ushort m_fieldCount; private ushort m_methodCount; //private ushort _attributeCount; //private string _name; public Dictionary StaticFields = new Dictionary(); public PoolClass MClass; public List m_constantsPool = new List(); private List m_methodsList = new List(); private List m_fieldList = new List(); public ClassRecord() { } public ClassInstance CreateNewInstance() { ClassInstance classInst = new ClassInstance(); classInst.ClassRec = this; //TODO: set fields return classInst; } public void LoadClassFromFile(string fileName) { Console.WriteLine("loading script " + fileName); FileStream fs = File.OpenRead(fileName); LoadClassFromBytes(ReadFully(fs)); fs.Close(); } public void LoadClassFromBytes(byte[] data) { int i = 0; i += 4; m_minorVersion = (ushort) ((data[i++] << 8) + data[i++]); m_majorVersion = (ushort) ((data[i++] << 8) + data[i++]); m_constantPoolCount = (ushort) ((data[i++] << 8) + data[i++]); Console.WriteLine("there should be " + m_constantPoolCount + " items in the pool"); for (int count = 0; count < (m_constantPoolCount - 1); count++) { //read in the constant pool byte pooltype = data[i++]; Console.WriteLine("#" + count + ": new constant type = " + pooltype); //Console.WriteLine("start position is: " + i); switch (pooltype) { case 1: //Utf8 ushort uLength = (ushort) ((data[i++] << 8) + data[i++]); // Console.WriteLine("new utf8 type, length is " + uLength); PoolUtf8 utf8 = new PoolUtf8(); utf8.readValue(data, ref i, uLength); m_constantsPool.Add(utf8); break; case 3: //Int break; case 4: //Float break; case 7: //Class PoolClass pClass = new PoolClass(this); pClass.readValue(data, ref i); m_constantsPool.Add(pClass); break; case 9: //FieldRef PoolFieldRef pField = new PoolFieldRef(this); pField.readValue(data, ref i); m_constantsPool.Add(pField); break; case 10: //Method PoolMethodRef pMeth = new PoolMethodRef(this); pMeth.readValue(data, ref i); m_constantsPool.Add(pMeth); break; case 12: //NamedType PoolNamedType pNamed = new PoolNamedType(this); pNamed.readValue(data, ref i); m_constantsPool.Add(pNamed); break; } } m_accessFlags = (ushort) ((data[i++] << 8) + data[i++]); m_thisClass = (ushort) ((data[i++] << 8) + data[i++]); m_supperClass = (ushort) ((data[i++] << 8) + data[i++]); if (m_constantsPool[m_thisClass - 1] is PoolClass) { MClass = ((PoolClass) m_constantsPool[m_thisClass - 1]); } m_interfaceCount = (ushort) ((data[i++] << 8) + data[i++]); //should now read in the info for each interface m_fieldCount = (ushort) ((data[i++] << 8) + data[i++]); //should now read in the info for each field for (int count = 0; count < m_fieldCount; count++) { FieldInfo fieldInf = new FieldInfo(this); fieldInf.ReadData(data, ref i); m_fieldList.Add(fieldInf); } m_methodCount = (ushort) ((data[i++] << 8) + data[i++]); for (int count = 0; count < m_methodCount; count++) { MethodInfo methInf = new MethodInfo(this); methInf.ReadData(data, ref i); m_methodsList.Add(methInf); } } public void AddMethodsToMemory(MethodMemory memory) { for (int count = 0; count < m_methodCount; count++) { m_methodsList[count].AddMethodCode(memory); } } public bool StartMethod(Thread thread, string methodName) { for (int count = 0; count < m_methodCount; count++) { if (m_constantsPool[m_methodsList[count].NameIndex - 1] is PoolUtf8) { if (((PoolUtf8) m_constantsPool[m_methodsList[count].NameIndex - 1]).Value == methodName) { //Console.WriteLine("found method: " + ((PoolUtf8)this._constantsPool[this._methodsList[count].NameIndex - 1]).Value); thread.SetPC(m_methodsList[count].CodePointer); return true; } } } return false; } public void PrintToConsole() { Console.WriteLine("Class File:"); Console.WriteLine("Major version: " + m_majorVersion); Console.WriteLine("Minor version: " + m_minorVersion); Console.WriteLine("Pool size: " + m_constantPoolCount); for (int i = 0; i < m_constantsPool.Count; i++) { m_constantsPool[i].Print(); } Console.WriteLine("Access flags: " + m_accessFlags); Console.WriteLine("This class: " + m_thisClass); Console.WriteLine("Super class: " + m_supperClass); for (int count = 0; count < m_fieldCount; count++) { Console.WriteLine(); m_fieldList[count].Print(); } for (int count = 0; count < m_methodCount; count++) { Console.WriteLine(); m_methodsList[count].Print(); } Console.WriteLine("class name is " + MClass.Name.Value); } public static byte[] ReadFully(Stream stream) { byte[] buffer = new byte[1024]; using (MemoryStream ms = new MemoryStream()) { while (true) { int read = stream.Read(buffer, 0, buffer.Length); if (read <= 0) return ms.ToArray(); ms.Write(buffer, 0, read); } } } #region nested classes public class PoolItem { public virtual void Print() { } } public class PoolUtf8 : PoolItem { public string Value = String.Empty; public void readValue(byte[] data, ref int pointer, int length) { for (int i = 0; i < length; i++) { int a = (int) data[pointer++]; if ((a & 0x80) == 0) { Value = Value + (char) a; } else if ((a & 0x20) == 0) { int b = (int) data[pointer++]; Value = Value + (char) (((a & 0x1f) << 6) + (b & 0x3f)); } else { int b = (int) data[pointer++]; int c = (int) data[pointer++]; Value = Value + (char) (((a & 0xf) << 12) + ((b & 0x3f) << 6) + (c & 0x3f)); } } } public override void Print() { Console.WriteLine("Utf8 type: " + Value); } } private class PoolInt : PoolItem { } public class PoolClass : PoolItem { //public string name = String.Empty; public ushort namePointer = 0; private ClassRecord parent; public PoolUtf8 Name; public PoolClass(ClassRecord paren) { parent = paren; } public void readValue(byte[] data, ref int pointer) { namePointer = (ushort) ((data[pointer++] << 8) + data[pointer++]); } public override void Print() { Name = ((PoolUtf8) parent.m_constantsPool[namePointer - 1]); Console.Write("Class type: " + namePointer); Console.WriteLine(" // " + ((PoolUtf8) parent.m_constantsPool[namePointer - 1]).Value); } } public class PoolFieldRef : PoolItem { public ushort classPointer = 0; public ushort nameTypePointer = 0; public PoolNamedType mNameType; public PoolClass mClass; private ClassRecord parent; public PoolFieldRef(ClassRecord paren) { parent = paren; } public void readValue(byte[] data, ref int pointer) { classPointer = (ushort) ((data[pointer++] << 8) + data[pointer++]); nameTypePointer = (ushort) ((data[pointer++] << 8) + data[pointer++]); } public override void Print() { mNameType = ((PoolNamedType) parent.m_constantsPool[nameTypePointer - 1]); mClass = ((PoolClass) parent.m_constantsPool[classPointer - 1]); Console.WriteLine("FieldRef type: " + classPointer + " , " + nameTypePointer); } } public class PoolMethodRef : PoolItem { public ushort classPointer = 0; public ushort nameTypePointer = 0; public PoolNamedType mNameType; public PoolClass mClass; private ClassRecord parent; public PoolMethodRef(ClassRecord paren) { parent = paren; } public void readValue(byte[] data, ref int pointer) { classPointer = (ushort) ((data[pointer++] << 8) + data[pointer++]); nameTypePointer = (ushort) ((data[pointer++] << 8) + data[pointer++]); } public override void Print() { mNameType = ((PoolNamedType) parent.m_constantsPool[nameTypePointer - 1]); mClass = ((PoolClass) parent.m_constantsPool[classPointer - 1]); Console.WriteLine("MethodRef type: " + classPointer + " , " + nameTypePointer); } } public class PoolNamedType : PoolItem { public ushort namePointer = 0; public ushort typePointer = 0; private ClassRecord parent; public PoolUtf8 Name; public PoolUtf8 Type; public PoolNamedType(ClassRecord paren) { parent = paren; } public void readValue(byte[] data, ref int pointer) { namePointer = (ushort) ((data[pointer++] << 8) + data[pointer++]); typePointer = (ushort) ((data[pointer++] << 8) + data[pointer++]); } public override void Print() { Name = ((PoolUtf8) parent.m_constantsPool[namePointer - 1]); Type = ((PoolUtf8) parent.m_constantsPool[typePointer - 1]); Console.Write("Named type: " + namePointer + " , " + typePointer); Console.WriteLine(" // " + ((PoolUtf8) parent.m_constantsPool[namePointer - 1]).Value); } } //*********************** public class MethodInfo { public ushort AccessFlags = 0; public ushort NameIndex = 0; public string Name = String.Empty; public ushort DescriptorIndex = 0; public ushort AttributeCount = 0; public List Attributes = new List(); private ClassRecord parent; public int CodePointer = 0; public MethodInfo(ClassRecord paren) { parent = paren; } public void AddMethodCode(MethodMemory memory) { Array.Copy(Attributes[0].Code, 0, memory.MethodBuffer, memory.NextMethodPC, Attributes[0].Code.Length); memory.Methodcount++; CodePointer = memory.NextMethodPC; memory.NextMethodPC += Attributes[0].Code.Length; } public void ReadData(byte[] data, ref int pointer) { AccessFlags = (ushort) ((data[pointer++] << 8) + data[pointer++]); NameIndex = (ushort) ((data[pointer++] << 8) + data[pointer++]); DescriptorIndex = (ushort) ((data[pointer++] << 8) + data[pointer++]); AttributeCount = (ushort) ((data[pointer++] << 8) + data[pointer++]); for (int i = 0; i < AttributeCount; i++) { MethodAttribute attri = new MethodAttribute(parent); attri.ReadData(data, ref pointer); Attributes.Add(attri); } } public void Print() { Console.WriteLine("Method Info Struct: "); Console.WriteLine("AccessFlags: " + AccessFlags); Console.WriteLine("NameIndex: " + NameIndex + " // " + ((PoolUtf8) parent.m_constantsPool[NameIndex - 1]).Value); Console.WriteLine("DescriptorIndex: " + DescriptorIndex + " // " + ((PoolUtf8) parent.m_constantsPool[DescriptorIndex - 1]).Value); Console.WriteLine("Attribute Count:" + AttributeCount); for (int i = 0; i < AttributeCount; i++) { Attributes[i].Print(); } } public class MethodAttribute { public ushort NameIndex = 0; public string Name = String.Empty; public Int32 Length = 0; //for now only support code attribute public ushort MaxStack = 0; public ushort MaxLocals = 0; public Int32 CodeLength = 0; public byte[] Code; public ushort ExceptionTableLength = 0; public ushort SubAttributeCount = 0; public List SubAttributes = new List(); private ClassRecord parent; public MethodAttribute(ClassRecord paren) { parent = paren; } public void ReadData(byte[] data, ref int pointer) { NameIndex = (ushort) ((data[pointer++] << 8) + data[pointer++]); Length = (Int32) ((data[pointer++] << 24) + (data[pointer++] << 16) + (data[pointer++] << 8) + data[pointer++]); MaxStack = (ushort) ((data[pointer++] << 8) + data[pointer++]); MaxLocals = (ushort) ((data[pointer++] << 8) + data[pointer++]); CodeLength = (Int32) ((data[pointer++] << 24) + (data[pointer++] << 16) + (data[pointer++] << 8) + data[pointer++]); Code = new byte[CodeLength]; for (int i = 0; i < CodeLength; i++) { Code[i] = data[pointer++]; } ExceptionTableLength = (ushort) ((data[pointer++] << 8) + data[pointer++]); SubAttributeCount = (ushort) ((data[pointer++] << 8) + data[pointer++]); for (int i = 0; i < SubAttributeCount; i++) { SubAttribute subAttri = new SubAttribute(parent); subAttri.ReadData(data, ref pointer); SubAttributes.Add(subAttri); } } public void Print() { Console.WriteLine("Method Attribute: "); Console.WriteLine("Name Index: " + NameIndex + " // " + ((PoolUtf8) parent.m_constantsPool[NameIndex - 1]).Value); Console.WriteLine("Length: " + Length); Console.WriteLine("MaxStack: " + MaxStack); Console.WriteLine("MaxLocals: " + MaxLocals); Console.WriteLine("CodeLength: " + CodeLength); for (int i = 0; i < Code.Length; i++) { Console.WriteLine("OpCode #" + i + " is: " + Code[i]); } Console.WriteLine("SubAttributes: " + SubAttributeCount); for (int i = 0; i < SubAttributeCount; i++) { SubAttributes[i].Print(); } } public class SubAttribute { public ushort NameIndex = 0; public string Name = String.Empty; public Int32 Length = 0; public byte[] Data; private ClassRecord parent; public SubAttribute(ClassRecord paren) { parent = paren; } public void ReadData(byte[] data, ref int pointer) { NameIndex = (ushort) ((data[pointer++] << 8) + data[pointer++]); Length = (Int32) ((data[pointer++] << 24) + (data[pointer++] << 16) + (data[pointer++] << 8) + data[pointer++]); Data = new byte[Length]; for (int i = 0; i < Length; i++) { Data[i] = data[pointer++]; } } public void Print() { Console.WriteLine("SubAttribute: NameIndex: " + NameIndex + " // " + ((PoolUtf8) parent.m_constantsPool[NameIndex - 1]).Value); } } } } private class InterfaceInfo { public void ReadData(byte[] data, ref int i) { } } public class FieldInfo { public ushort AccessFlags = 0; public ushort NameIndex = 0; public string Name = String.Empty; public ushort DescriptorIndex = 0; public ushort AttributeCount = 0; public List Attributes = new List(); private ClassRecord parent; public FieldInfo(ClassRecord paren) { parent = paren; } public void ReadData(byte[] data, ref int pointer) { AccessFlags = (ushort) ((data[pointer++] << 8) + data[pointer++]); NameIndex = (ushort) ((data[pointer++] << 8) + data[pointer++]); DescriptorIndex = (ushort) ((data[pointer++] << 8) + data[pointer++]); AttributeCount = (ushort) ((data[pointer++] << 8) + data[pointer++]); for (int i = 0; i < AttributeCount; i++) { FieldAttribute attri = new FieldAttribute(parent); attri.ReadData(data, ref pointer); Attributes.Add(attri); } } public void Print() { Console.WriteLine("Field Info Struct: "); Console.WriteLine("AccessFlags: " + AccessFlags); Console.WriteLine("NameIndex: " + NameIndex + " // " + ((PoolUtf8) parent.m_constantsPool[NameIndex - 1]).Value); Console.WriteLine("DescriptorIndex: " + DescriptorIndex + " // " + ((PoolUtf8) parent.m_constantsPool[DescriptorIndex - 1]).Value); Console.WriteLine("Attribute Count:" + AttributeCount); //if static, add to static field list // if (this.AccessFlags == 9) //public and static if ((AccessFlags & 0x08) != 0) { switch (((PoolUtf8) parent.m_constantsPool[DescriptorIndex - 1]).Value) { case "I": Int newin = new Int(); parent.StaticFields.Add(((PoolUtf8) parent.m_constantsPool[NameIndex - 1]).Value, newin); break; case "F": Float newfl = new Float(); parent.StaticFields.Add(((PoolUtf8) parent.m_constantsPool[NameIndex - 1]).Value, newfl); break; } } for (int i = 0; i < AttributeCount; i++) { Attributes[i].Print(); } } public class FieldAttribute { public ushort NameIndex = 0; public string Name = String.Empty; public Int32 Length = 0; public byte[] Data; private ClassRecord parent; public FieldAttribute(ClassRecord paren) { parent = paren; } public void ReadData(byte[] data, ref int pointer) { NameIndex = (ushort) ((data[pointer++] << 8) + data[pointer++]); Length = (Int32) ((data[pointer++] << 24) + (data[pointer++] << 16) + (data[pointer++] << 8) + data[pointer++]); Data = new byte[Length]; for (int i = 0; i < Length; i++) { Data[i] = data[pointer++]; } } public void Print() { Console.WriteLine("FieldAttribute: NameIndex: " + NameIndex + " // " + ((PoolUtf8) parent.m_constantsPool[NameIndex - 1]).Value); } } } private class AttributeInfo { public void ReadData(byte[] data, ref int i) { } } #endregion } }