1 //
2 // SymbolWriterImpl.cs
3 //
4 // Author:
5 //   Lluis Sanchez Gual (lluis@novell.com)
6 //
7 // (C) 2005 Novell, Inc.  http://www.novell.com
8 //
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
17 //
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
20 //
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 //
29 
30 
31 using System;
32 using System.Reflection;
33 using System.Reflection.Emit;
34 using System.Runtime.CompilerServices;
35 using System.Collections;
36 using System.IO;
37 using System.Diagnostics.SymbolStore;
38 
39 namespace Mono.CompilerServices.SymbolWriter
40 {
41 	public class SymbolWriterImpl: ISymbolWriter
42 	{
43 		MonoSymbolWriter msw;
44 
45 		int nextLocalIndex;
46 		int currentToken;
47 		string methodName;
48 		Stack namespaceStack = new Stack ();
49 		bool methodOpened;
50 
51 		Hashtable documents = new Hashtable ();
52 
53 #if !CECIL && !MOBILE
54 		ModuleBuilder mb;
GetGuidFunc(ModuleBuilder mb)55 		delegate Guid GetGuidFunc (ModuleBuilder mb);
56 		GetGuidFunc get_guid_func;
57 
SymbolWriterImpl(ModuleBuilder mb)58 		public SymbolWriterImpl (ModuleBuilder mb)
59 		{
60 			this.mb = mb;
61 		}
62 
Close()63 		public void Close ()
64 		{
65 			MethodInfo mi = typeof (ModuleBuilder).GetMethod (
66 				"Mono_GetGuid",
67 				BindingFlags.Static | BindingFlags.NonPublic);
68 			if (mi == null)
69 				return;
70 
71 			get_guid_func = (GetGuidFunc) System.Delegate.CreateDelegate (
72 				typeof (GetGuidFunc), mi);
73 
74 			msw.WriteSymbolFile (get_guid_func (mb));
75 		}
76 #else
77 		Guid guid;
78 
SymbolWriterImpl(Guid guid)79 		public SymbolWriterImpl (Guid guid)
80 		{
81 			this.guid = guid;
82 		}
83 
Close()84 		public void Close ()
85 		{
86 			msw.WriteSymbolFile (guid);
87 		}
88 #endif
89 
CloseMethod()90 		public void CloseMethod ()
91 		{
92 			if (methodOpened) {
93 				methodOpened = false;
94 				nextLocalIndex = 0;
95 				msw.CloseMethod ();
96 			}
97 		}
98 
CloseNamespace()99 		public void CloseNamespace ()
100 		{
101 			namespaceStack.Pop ();
102 			msw.CloseNamespace ();
103 		}
104 
CloseScope(int endOffset)105 		public void CloseScope (int endOffset)
106 		{
107 			msw.CloseScope (endOffset);
108 		}
109 
DefineDocument( string url, Guid language, Guid languageVendor, Guid documentType)110 		public ISymbolDocumentWriter DefineDocument (
111 			string url,
112 			Guid language,
113 			Guid languageVendor,
114 			Guid documentType)
115 		{
116 			SymbolDocumentWriterImpl doc = (SymbolDocumentWriterImpl) documents [url];
117 			if (doc == null) {
118 				SourceFileEntry entry = msw.DefineDocument (url);
119 				CompileUnitEntry comp_unit = msw.DefineCompilationUnit (entry);
120 				doc = new SymbolDocumentWriterImpl (comp_unit);
121 				documents [url] = doc;
122 			}
123 			return doc;
124 		}
125 
DefineField( SymbolToken parent, string name, FieldAttributes attributes, byte[] signature, SymAddressKind addrKind, int addr1, int addr2, int addr3)126 		public void DefineField (
127 			SymbolToken parent,
128 			string name,
129 			FieldAttributes attributes,
130 			byte[] signature,
131 			SymAddressKind addrKind,
132 			int addr1,
133 			int addr2,
134 			int addr3)
135 		{
136 		}
137 
DefineGlobalVariable( string name, FieldAttributes attributes, byte[] signature, SymAddressKind addrKind, int addr1, int addr2, int addr3)138 		public void DefineGlobalVariable (
139 			string name,
140 			FieldAttributes attributes,
141 			byte[] signature,
142 			SymAddressKind addrKind,
143 			int addr1,
144 			int addr2,
145 			int addr3)
146 		{
147 		}
148 
DefineLocalVariable( string name, FieldAttributes attributes, byte[] signature, SymAddressKind addrKind, int addr1, int addr2, int addr3, int startOffset, int endOffset)149 		public void DefineLocalVariable (
150 			string name,
151 			FieldAttributes attributes,
152 			byte[] signature,
153 			SymAddressKind addrKind,
154 			int addr1,
155 			int addr2,
156 			int addr3,
157 			int startOffset,
158 			int endOffset)
159 		{
160 			msw.DefineLocalVariable (nextLocalIndex++, name);
161 		}
162 
DefineParameter( string name, ParameterAttributes attributes, int sequence, SymAddressKind addrKind, int addr1, int addr2, int addr3)163 		public void DefineParameter (
164 			string name,
165 			ParameterAttributes attributes,
166 			int sequence,
167 			SymAddressKind addrKind,
168 			int addr1,
169 			int addr2,
170 			int addr3)
171 		{
172 		}
173 
DefineSequencePoints( ISymbolDocumentWriter document, int[] offsets, int[] lines, int[] columns, int[] endLines, int[] endColumns)174 		public void DefineSequencePoints (
175 			ISymbolDocumentWriter document,
176 			int[] offsets,
177 			int[] lines,
178 			int[] columns,
179 			int[] endLines,
180 			int[] endColumns)
181 		{
182 			SymbolDocumentWriterImpl doc = (SymbolDocumentWriterImpl) document;
183 			SourceFileEntry file = doc != null ? doc.Entry.SourceFile : null;
184 
185 			for (int n=0; n<offsets.Length; n++) {
186 				if (n > 0 && offsets[n] == offsets[n-1] && lines[n] == lines[n-1] && columns[n] == columns[n-1])
187 					continue;
188 				msw.MarkSequencePoint (offsets[n], file, lines[n], columns[n], false);
189 			}
190 		}
191 
Initialize(IntPtr emitter, string filename, bool fFullBuild)192 		public void Initialize (IntPtr emitter, string filename, bool fFullBuild)
193 		{
194 			msw = new MonoSymbolWriter (filename);
195 		}
196 
OpenMethod(SymbolToken method)197 		public void OpenMethod (SymbolToken method)
198 		{
199 			currentToken = method.GetToken ();
200 		}
201 
OpenNamespace(string name)202 		public void OpenNamespace (string name)
203 		{
204 			NamespaceInfo n = new NamespaceInfo ();
205 			n.NamespaceID = -1;
206 			n.Name = name;
207 			namespaceStack.Push (n);
208 		}
209 
OpenScope(int startOffset)210 		public int OpenScope (int startOffset)
211 		{
212 			return msw.OpenScope (startOffset);
213 		}
214 
SetMethodSourceRange( ISymbolDocumentWriter startDoc, int startLine, int startColumn, ISymbolDocumentWriter endDoc, int endLine, int endColumn)215 		public void SetMethodSourceRange (
216 			ISymbolDocumentWriter startDoc,
217 			int startLine,
218 			int startColumn,
219 			ISymbolDocumentWriter endDoc,
220 			int endLine,
221 			int endColumn)
222 		{
223 			int nsId = GetCurrentNamespace (startDoc);
224 			SourceMethodImpl sm = new SourceMethodImpl (methodName, currentToken, nsId);
225 			msw.OpenMethod (((ICompileUnit)startDoc).Entry, nsId, sm);
226 			methodOpened = true;
227 		}
228 
SetScopeRange(int scopeID, int startOffset, int endOffset)229 		public void SetScopeRange (int scopeID, int startOffset, int endOffset)
230 		{
231 		}
232 
SetSymAttribute(SymbolToken parent, string name, byte[] data)233 		public void SetSymAttribute (SymbolToken parent, string name, byte[] data)
234 		{
235 			// This is a hack! but MonoSymbolWriter needs the method name
236 			// and ISymbolWriter does not have any method for providing it
237 			if (name == "__name")
238 				methodName = System.Text.Encoding.UTF8.GetString (data);
239 		}
240 
SetUnderlyingWriter(IntPtr underlyingWriter)241 		public void SetUnderlyingWriter (IntPtr underlyingWriter)
242 		{
243 		}
244 
SetUserEntryPoint(SymbolToken entryMethod)245 		public void SetUserEntryPoint (SymbolToken entryMethod)
246 		{
247 		}
248 
UsingNamespace(string fullName)249 		public void UsingNamespace (string fullName)
250 		{
251 			if (namespaceStack.Count == 0) {
252 				OpenNamespace ("");
253 			}
254 
255 			NamespaceInfo ni = (NamespaceInfo) namespaceStack.Peek ();
256 			if (ni.NamespaceID != -1) {
257 				NamespaceInfo old = ni;
258 				CloseNamespace ();
259 				OpenNamespace (old.Name);
260 				ni = (NamespaceInfo) namespaceStack.Peek ();
261 				ni.UsingClauses = old.UsingClauses;
262 			}
263 			ni.UsingClauses.Add (fullName);
264 		}
265 
GetCurrentNamespace(ISymbolDocumentWriter doc)266 		int GetCurrentNamespace (ISymbolDocumentWriter doc)
267 		{
268 			if (namespaceStack.Count == 0) {
269 				OpenNamespace ("");
270 			}
271 
272 			NamespaceInfo ni = (NamespaceInfo) namespaceStack.Peek ();
273 			if (ni.NamespaceID == -1)
274 			{
275 				string[] usings = (string[]) ni.UsingClauses.ToArray (typeof(string));
276 
277 				int parentId = 0;
278 				if (namespaceStack.Count > 1) {
279 					namespaceStack.Pop ();
280 					parentId = ((NamespaceInfo) namespaceStack.Peek ()).NamespaceID;
281 					namespaceStack.Push (ni);
282 				}
283 
284 				ni.NamespaceID = msw.DefineNamespace (ni.Name, ((ICompileUnit)doc).Entry, usings, parentId);
285 			}
286 			return ni.NamespaceID;
287 		}
288 
289 	}
290 
291 	class SymbolDocumentWriterImpl: ISymbolDocumentWriter, ISourceFile, ICompileUnit
292 	{
293 		CompileUnitEntry comp_unit;
294 
SymbolDocumentWriterImpl(CompileUnitEntry comp_unit)295 		public SymbolDocumentWriterImpl (CompileUnitEntry comp_unit)
296 		{
297 			this.comp_unit = comp_unit;
298 		}
299 
SetCheckSum(Guid algorithmId, byte[] checkSum)300 		public void SetCheckSum (Guid algorithmId, byte[] checkSum)
301 		{
302 		}
303 
SetSource(byte[] source)304 		public void SetSource (byte[] source)
305 		{
306 		}
307 
308 		SourceFileEntry ISourceFile.Entry {
309 			get { return comp_unit.SourceFile; }
310 		}
311 
312 		public CompileUnitEntry Entry {
313 			get { return comp_unit; }
314 		}
315 	}
316 
317 	class SourceMethodImpl: IMethodDef
318 	{
319 		string name;
320 		int token;
321 		int namespaceID;
322 
SourceMethodImpl(string name, int token, int namespaceID)323 		public SourceMethodImpl (string name, int token, int namespaceID)
324 		{
325 			this.name = name;
326 			this.token = token;
327 			this.namespaceID = namespaceID;
328 		}
329 
330 		public string Name {
331 			get { return name; }
332 		}
333 
334 		public int NamespaceID {
335 			get { return namespaceID; }
336 		}
337 
338 		public int Token {
339 			get { return token; }
340 		}
341 	}
342 
343 	class NamespaceInfo
344 	{
345 		public string Name;
346 		public int NamespaceID;
347 		public ArrayList UsingClauses = new ArrayList ();
348 	}
349 }
350