aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine/YEngine/MMRScriptObjCode.cs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/ScriptEngine/YEngine/MMRScriptObjCode.cs245
1 files changed, 245 insertions, 0 deletions
diff --git a/OpenSim/Region/ScriptEngine/YEngine/MMRScriptObjCode.cs b/OpenSim/Region/ScriptEngine/YEngine/MMRScriptObjCode.cs
new file mode 100644
index 0000000..d5b08f0
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/YEngine/MMRScriptObjCode.cs
@@ -0,0 +1,245 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using OpenSim.Region.ScriptEngine.Yengine;
29using System;
30using System.Collections.Generic;
31using System.IO;
32using System.Reflection;
33using System.Reflection.Emit;
34
35namespace OpenSim.Region.ScriptEngine.Yengine
36{
37 public delegate void ScriptEventHandler(XMRInstAbstract instance);
38
39 /*
40 * This object represents the output of the compilation.
41 * Once the compilation is complete, its contents should be
42 * considered 'read-only', so it can be shared among multiple
43 * instances of the script.
44 *
45 * It gets created by ScriptCodeGen.
46 * It gets used by XMRInstance to create script instances.
47 */
48 public class ScriptObjCode
49 {
50 public string sourceHash; // source text hash code
51 public XMRInstArSizes glblSizes = new XMRInstArSizes();
52 // number of global variables of various types
53
54 public string[] stateNames; // convert state number to corresponding string
55 public ScriptEventHandler[,] scriptEventHandlerTable;
56 // entrypoints to all event handler functions
57 // 1st subscript = state code number (0=default)
58 // 2nd subscript = event code number
59 // null entry means no handler defined for that state,event
60
61 public Dictionary<string, TokenDeclSDType> sdObjTypesName;
62 // all script-defined types by name
63
64 public TokenDeclSDType[] sdObjTypesIndx;
65 // all script-defined types by sdTypeIndex
66
67 public Dictionary<Type, string> sdDelTypes;
68 // all script-defined delegates (including anonymous)
69
70 public Dictionary<string, DynamicMethod> dynamicMethods;
71 // all dyanmic methods
72
73 public Dictionary<string, KeyValuePair<int, ScriptSrcLoc>[]> scriptSrcLocss;
74 // method,iloffset -> source file,line,posn
75
76 public int refCount; // used by engine to keep track of number of
77 // instances that are using this object code
78
79 public Dictionary<string, Dictionary<int, string>> globalVarNames = new Dictionary<string, Dictionary<int, string>>();
80
81 /**
82 * @brief Fill in ScriptObjCode from an YEngine object file.
83 * 'objFileReader' is a serialized form of the CIL code we generated
84 * 'asmFileWriter' is where we write the disassembly to (or null if not wanted)
85 * 'srcFileWriter' is where we write the decompilation to (or null if not wanted)
86 * Throws an exception if there is any error (theoretically).
87 */
88 public ScriptObjCode(BinaryReader objFileReader, TextWriter asmFileWriter, TextWriter srcFileWriter)
89 {
90 /*
91 * Check version number to make sure we know how to process file contents.
92 */
93 char[] ocm = objFileReader.ReadChars(ScriptCodeGen.OBJECT_CODE_MAGIC.Length);
94 if(new String(ocm) != ScriptCodeGen.OBJECT_CODE_MAGIC)
95 throw new Exception("not an XMR object file (bad magic)");
96
97 int cvv = objFileReader.ReadInt32();
98 if(cvv != ScriptCodeGen.COMPILED_VERSION_VALUE)
99 throw new CVVMismatchException(cvv, ScriptCodeGen.COMPILED_VERSION_VALUE);
100
101 // Fill in simple parts of scriptObjCode object.
102 sourceHash = objFileReader.ReadString();
103 glblSizes.ReadFromFile(objFileReader);
104 int nStates = objFileReader.ReadInt32();
105
106 stateNames = new string[nStates];
107 for(int i = 0; i < nStates; i++)
108 {
109 stateNames[i] = objFileReader.ReadString();
110 if(asmFileWriter != null)
111 asmFileWriter.WriteLine(" state[{0}] = {1}", i, stateNames[i]);
112 }
113
114 if(asmFileWriter != null)
115 glblSizes.WriteAsmFile(asmFileWriter, "numGbl");
116
117 string gblName;
118 while((gblName = objFileReader.ReadString()) != "")
119 {
120 string gblType = objFileReader.ReadString();
121 int gblIndex = objFileReader.ReadInt32();
122 Dictionary<int, string> names;
123 if(!globalVarNames.TryGetValue(gblType, out names))
124 {
125 names = new Dictionary<int, string>();
126 globalVarNames.Add(gblType, names);
127 }
128 names.Add(gblIndex, gblName);
129 if(asmFileWriter != null)
130 asmFileWriter.WriteLine(" {0} = {1}[{2}]", gblName, gblType, gblIndex);
131 }
132
133 // Read in script-defined types.
134 sdObjTypesName = new Dictionary<string, TokenDeclSDType>();
135 sdDelTypes = new Dictionary<Type, string>();
136 int maxIndex = -1;
137 while((gblName = objFileReader.ReadString()) != "")
138 {
139 TokenDeclSDType sdt = TokenDeclSDType.ReadFromFile(sdObjTypesName,
140 gblName, objFileReader, asmFileWriter);
141 sdObjTypesName.Add(gblName, sdt);
142 if(maxIndex < sdt.sdTypeIndex)
143 maxIndex = sdt.sdTypeIndex;
144 if(sdt is TokenDeclSDTypeDelegate)
145 sdDelTypes.Add(sdt.GetSysType(), gblName);
146 }
147 sdObjTypesIndx = new TokenDeclSDType[maxIndex + 1];
148 foreach(TokenDeclSDType sdt in sdObjTypesName.Values)
149 sdObjTypesIndx[sdt.sdTypeIndex] = sdt;
150
151 // Now fill in the methods (the hard part).
152 scriptEventHandlerTable = new ScriptEventHandler[nStates, (int)ScriptEventCode.Size];
153 dynamicMethods = new Dictionary<string, DynamicMethod>();
154 scriptSrcLocss = new Dictionary<string, KeyValuePair<int, ScriptSrcLoc>[]>();
155
156 ObjectTokens objectTokens = null;
157 if(asmFileWriter != null)
158 objectTokens = new OTDisassemble(this, asmFileWriter);
159 else if(srcFileWriter != null)
160 objectTokens = new OTDecompile(this, srcFileWriter);
161
162 try
163 {
164 ScriptObjWriter.CreateObjCode(sdObjTypesName, objFileReader, this, objectTokens);
165 }
166 finally
167 {
168 if(objectTokens != null)
169 objectTokens.Close();
170 }
171
172 // We enter all script event handler methods in the ScriptEventHandler table.
173 // They are named: <statename> <eventname>
174 foreach(KeyValuePair<string, DynamicMethod> kvp in dynamicMethods)
175 {
176 string methName = kvp.Key;
177 int i = methName.IndexOf(' ');
178 if(i < 0)
179 continue;
180 string stateName = methName.Substring(0, i);
181 string eventName = methName.Substring(++i);
182 int stateCode;
183 for(stateCode = stateNames.Length; --stateCode >= 0;)
184 if(stateNames[stateCode] == stateName)
185 break;
186
187 int eventCode = (int)Enum.Parse(typeof(ScriptEventCode), eventName);
188 scriptEventHandlerTable[stateCode, eventCode] =
189 (ScriptEventHandler)kvp.Value.CreateDelegate(typeof(ScriptEventHandler));
190 }
191
192 // Fill in all script-defined class vtables.
193 foreach(TokenDeclSDType sdt in sdObjTypesIndx)
194 {
195 if((sdt != null) && (sdt is TokenDeclSDTypeClass))
196 {
197 TokenDeclSDTypeClass sdtc = (TokenDeclSDTypeClass)sdt;
198 sdtc.FillVTables(this);
199 }
200 }
201 }
202
203 /**
204 * @brief Called once for every method found in objFileReader file.
205 * It enters the method in the ScriptObjCode object table so it can be called.
206 */
207 public void EndMethod(DynamicMethod method, Dictionary<int, ScriptSrcLoc> srcLocs)
208 {
209 /*
210 * Save method object code pointer.
211 */
212 dynamicMethods.Add(method.Name, method);
213
214 /*
215 * Build and sort iloffset -> source code location array.
216 */
217 int n = srcLocs.Count;
218 KeyValuePair<int, ScriptSrcLoc>[] srcLocArray = new KeyValuePair<int, ScriptSrcLoc>[n];
219 n = 0;
220 foreach(KeyValuePair<int, ScriptSrcLoc> kvp in srcLocs)
221 srcLocArray[n++] = kvp;
222 Array.Sort(srcLocArray, endMethodWrapper);
223
224 /*
225 * Save sorted array.
226 */
227 scriptSrcLocss.Add(method.Name, srcLocArray);
228 }
229
230 /**
231 * @brief Called once for every method found in objFileReader file.
232 * It enters the method in the ScriptObjCode object table so it can be called.
233 */
234 private static EndMethodWrapper endMethodWrapper = new EndMethodWrapper();
235 private class EndMethodWrapper: System.Collections.IComparer
236 {
237 public int Compare(object x, object y)
238 {
239 KeyValuePair<int, ScriptSrcLoc> kvpx = (KeyValuePair<int, ScriptSrcLoc>)x;
240 KeyValuePair<int, ScriptSrcLoc> kvpy = (KeyValuePair<int, ScriptSrcLoc>)y;
241 return kvpx.Key - kvpy.Key;
242 }
243 }
244 }
245}