1 //
2 // Author:
3 //   Juerg Billeter (j@bitron.ch)
4 //
5 // (C) 2008 Juerg Billeter
6 //
7 // Licensed under the MIT/X11 license.
8 //
9 
10 using System;
11 using System.Runtime.InteropServices;
12 
13 using Mono.Cecil.Cil;
14 using Mono.Collections.Generic;
15 
16 #if !READ_ONLY
17 
18 namespace Mono.Cecil.Pdb
19 {
20 	internal class SymWriter
21 	{
22 		[DllImport("ole32.dll")]
CoCreateInstance( [In] ref Guid rclsid, [In, MarshalAs (UnmanagedType.IUnknown)] object pUnkOuter, [In] uint dwClsContext, [In] ref Guid riid, [Out, MarshalAs (UnmanagedType.Interface)] out object ppv)23 		static extern int CoCreateInstance (
24 			[In] ref Guid rclsid,
25 			[In, MarshalAs (UnmanagedType.IUnknown)] object pUnkOuter,
26 			[In] uint dwClsContext,
27 			[In] ref Guid riid,
28 			[Out, MarshalAs (UnmanagedType.Interface)] out object ppv);
29 
30 		static Guid s_symUnmangedWriterIID = new Guid("0b97726e-9e6d-4f05-9a26-424022093caa");
31 		static Guid s_CorSymWriter_SxS_ClassID = new Guid ("108296c1-281e-11d3-bd22-0000f80849bd");
32 
33 		readonly ISymUnmanagedWriter2 m_writer;
34 		readonly Collection<ISymUnmanagedDocumentWriter> documents;
35 
SymWriter()36 		public SymWriter ()
37 		{
38 			object objWriter;
39 			CoCreateInstance (ref s_CorSymWriter_SxS_ClassID, null, 1, ref s_symUnmangedWriterIID, out objWriter);
40 
41 			m_writer = (ISymUnmanagedWriter2) objWriter;
42 			documents = new Collection<ISymUnmanagedDocumentWriter> ();
43 		}
44 
GetDebugInfo(out ImageDebugDirectory idd)45 		public byte[] GetDebugInfo (out ImageDebugDirectory idd)
46 		{
47 			int size;
48 
49 			// get size of debug info
50 			m_writer.GetDebugInfo (out idd, 0, out size, null);
51 
52 			byte[] debug_info = new byte[size];
53 			m_writer.GetDebugInfo (out idd, size, out size, debug_info);
54 
55 			return debug_info;
56 		}
57 
DefineLocalVariable2( string name, VariableAttributes attributes, int sigToken, int addr1, int addr2, int addr3, int startOffset, int endOffset)58 		public void DefineLocalVariable2 (
59 			string name,
60 			VariableAttributes attributes,
61 			int sigToken,
62 			int addr1,
63 			int addr2,
64 			int addr3,
65 			int startOffset,
66 			int endOffset)
67 		{
68 			m_writer.DefineLocalVariable2 (name, (int)attributes, sigToken, 1 /* ILOffset*/, addr1, addr2, addr3, startOffset, endOffset);
69 		}
70 
DefineConstant2(string name, object value, int sigToken)71 		public void DefineConstant2 (string name, object value, int sigToken)
72 		{
73 			if (value == null) {
74 				m_writer.DefineConstant2 (name, 0, sigToken);
75 				return;
76 			}
77 
78 			m_writer.DefineConstant2 (name, value, sigToken);
79 		}
80 
Close()81 		public void Close ()
82 		{
83 			m_writer.Close ();
84 			Marshal.ReleaseComObject (m_writer);
85 
86 			foreach (var document in documents)
87 				Marshal.ReleaseComObject (document);
88 		}
89 
CloseMethod()90 		public void CloseMethod ()
91 		{
92 			m_writer.CloseMethod ();
93 		}
94 
CloseNamespace()95 		public void CloseNamespace ()
96 		{
97 			m_writer.CloseNamespace ();
98 		}
99 
CloseScope(int endOffset)100 		public void CloseScope (int endOffset)
101 		{
102 			m_writer.CloseScope (endOffset);
103 		}
104 
DefineDocument(string url, Guid language, Guid languageVendor, Guid documentType)105 		public SymDocumentWriter DefineDocument (string url, Guid language, Guid languageVendor, Guid documentType)
106 		{
107 			ISymUnmanagedDocumentWriter unmanagedDocumentWriter;
108 			m_writer.DefineDocument (url, ref language, ref languageVendor, ref documentType, out unmanagedDocumentWriter);
109 
110 			documents.Add (unmanagedDocumentWriter);
111 			return new SymDocumentWriter (unmanagedDocumentWriter);
112 		}
113 
DefineSequencePoints(SymDocumentWriter document, int[] offsets, int[] lines, int[] columns, int[] endLines, int[] endColumns)114 		public void DefineSequencePoints (SymDocumentWriter document, int[] offsets, int[] lines, int[] columns, int[] endLines, int[] endColumns)
115 		{
116 			m_writer.DefineSequencePoints (document.GetUnmanaged(), offsets.Length, offsets, lines, columns, endLines, endColumns);
117 		}
118 
Initialize(object emitter, string filename, bool fFullBuild)119 		public void Initialize (object emitter, string filename, bool fFullBuild)
120 		{
121 			m_writer.Initialize (emitter, filename, null, fFullBuild);
122 		}
123 
SetUserEntryPoint(int methodToken)124 		public void SetUserEntryPoint (int methodToken)
125 		{
126 			m_writer.SetUserEntryPoint (methodToken);
127 		}
128 
OpenMethod(int methodToken)129 		public void OpenMethod (int methodToken)
130 		{
131 			m_writer.OpenMethod (methodToken);
132 		}
133 
OpenNamespace(string name)134 		public void OpenNamespace (string name)
135 		{
136 			m_writer.OpenNamespace (name);
137 		}
138 
OpenScope(int startOffset)139 		public int OpenScope (int startOffset)
140 		{
141 			int result;
142 			m_writer.OpenScope (startOffset, out result);
143 			return result;
144 		}
145 
UsingNamespace(string fullName)146 		public void UsingNamespace (string fullName)
147 		{
148 			m_writer.UsingNamespace (fullName);
149 		}
150 
DefineCustomMetadata(string name, byte [] metadata)151 		public void DefineCustomMetadata (string name, byte [] metadata)
152 		{
153 			var handle = GCHandle.Alloc (metadata, GCHandleType.Pinned);
154 			m_writer.SetSymAttribute (0, name, (uint) metadata.Length, handle.AddrOfPinnedObject ());
155 			handle.Free ();
156 		}
157 	}
158 }
159 
160 #endif
161