OLD | NEW |
| (Empty) |
1 // Copyright 2009 The Native Client Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can | |
3 // be found in the LICENSE file. | |
4 | |
5 using System; | |
6 using System.Collections.Generic; | |
7 using System.Diagnostics; | |
8 using System.Runtime.InteropServices; | |
9 using Google.MsAd7.BaseImpl; | |
10 using Google.MsAd7.BaseImpl.Ad7Enumerators; | |
11 using Google.MsAd7.BaseImpl.Interfaces; | |
12 using Microsoft.VisualStudio; | |
13 using Microsoft.VisualStudio.Debugger.Interop; | |
14 | |
15 namespace Google.NaClVsx.DebugSupport { | |
16 /// <summary> | |
17 /// For documentation of IDebugEngine3 and IDebugEngineLaunch2 members, please
see the VS 2008 | |
18 /// MSDN documentation. | |
19 /// </summary> | |
20 [ComVisible(true)] | |
21 [Guid(kClsId)] | |
22 [ClassInterface(ClassInterfaceType.None)] | |
23 public class Engine : IDebugEngine3, IDebugEngineLaunch2 { | |
24 #region constants | |
25 | |
26 public const string kClsId = "547F36D7-FC60-47F5-AE6A-0F351E9F7D8C"; | |
27 public const string kId = "2E061BBF-B1ED-40D8-8D5D-8E2F9B2ADEC7"; | |
28 public const string kName = "NaCl"; | |
29 | |
30 #endregion | |
31 | |
32 public Engine() { | |
33 Trace.WriteLine("NaCl Debug Engine Loaded"); | |
34 } | |
35 | |
36 public List<PendingBreakpoint> Breakpoints { | |
37 get { return breakpoints_; } | |
38 } | |
39 | |
40 /// <summary> | |
41 /// This function can change the state of all breakpoints, managed by this e
ngine. | |
42 /// </summary> | |
43 /// <param name="enable">If |enable| is true, enables all breakpoints, else
disables them. | |
44 /// </param> | |
45 public void EnableAllBreakpoints(bool enable) { | |
46 foreach (PendingBreakpoint bp in breakpoints_) { | |
47 bp.Enable(enable ? 1 : 0); | |
48 } | |
49 } | |
50 | |
51 #region Implementation of IDebugEngine3 | |
52 | |
53 public int EnumPrograms(out IEnumDebugPrograms2 ppEnum) { | |
54 Debug.WriteLine("DebugEngine.EnumPrograms"); | |
55 ppEnum = new ProgramEnumerator( | |
56 programs_.ConvertAll(n => (IDebugProgram2) n)); | |
57 return VSConstants.S_OK; | |
58 } | |
59 | |
60 public int Attach(IDebugProgram2[] rgpPrograms, | |
61 IDebugProgramNode2[] rgpProgramNodes, | |
62 uint celtPrograms, | |
63 IDebugEventCallback2 pCallback, | |
64 enum_ATTACH_REASON dwReason) { | |
65 Debug.WriteLine("DebugEngine.Attach"); | |
66 debugEventCallback_ = pCallback; | |
67 | |
68 SendEvent(null, null, new Ad7Events.DebugEngineCreateEvent(this)); | |
69 | |
70 for (uint i = 0; i < celtPrograms; ++i) { | |
71 var prog = rgpPrograms[i] as ProgramNode; | |
72 if (prog == null) { | |
73 continue; | |
74 } | |
75 | |
76 programs_.Add(prog); | |
77 prog.AttachEngine(this); | |
78 } | |
79 return VSConstants.S_OK; | |
80 } | |
81 | |
82 public int CreatePendingBreakpoint( | |
83 IDebugBreakpointRequest2 pBPRequest, | |
84 out IDebugPendingBreakpoint2 ppPendingBP) { | |
85 Debug.WriteLine("DebugEngine.CreatePendingBreakpoint"); | |
86 //var breakpointCreated = VSConstants.S_FALSE; | |
87 var rq = new BreakpointRequest(pBPRequest); | |
88 var bp = new PendingBreakpoint(programs_[0].Dbg, rq); | |
89 IEnumDebugErrorBreakpoints2 bindErrors; | |
90 int canBindResult = bp.CanBind(out bindErrors); | |
91 if (canBindResult != VSConstants.S_OK) { | |
92 uint errorCount; | |
93 if (bindErrors.GetCount(out errorCount) == VSConstants.S_OK) { | |
94 uint errorsInArray = 0; | |
95 var errorArray = new IDebugErrorBreakpoint2[1]; | |
96 for (uint i = 0; i < errorCount; ++i) { | |
97 if ((bindErrors.Next(1, errorArray, ref errorsInArray) != | |
98 VSConstants.S_OK) || (errorsInArray != 1)) { | |
99 continue; | |
100 } | |
101 var errorEvent = | |
102 new Ad7Events.DebugBreakpointErrorEvent(errorArray[0]); | |
103 SendEvent(null, null, errorEvent); | |
104 } | |
105 } | |
106 } | |
107 ppPendingBP = bp; | |
108 breakpoints_.Add(bp); | |
109 return VSConstants.S_OK; | |
110 } | |
111 | |
112 public int SetException(EXCEPTION_INFO[] pException) { | |
113 Debug.WriteLine("DebugEngine.SetException"); | |
114 throw new NotImplementedException(); | |
115 } | |
116 | |
117 public int RemoveSetException(EXCEPTION_INFO[] pException) { | |
118 Debug.WriteLine("DebugEngine.RemoveSetException"); | |
119 throw new NotImplementedException(); | |
120 } | |
121 | |
122 public int RemoveAllSetExceptions(ref Guid guidType) { | |
123 Debug.WriteLine("DebugEngine.RemoveAllSetExceptions"); | |
124 throw new NotImplementedException(); | |
125 } | |
126 | |
127 public int GetEngineId(out Guid pguidEngine) { | |
128 Debug.WriteLine("DebugEngine.GetEngineId"); | |
129 pguidEngine = engineGuid_; | |
130 return VSConstants.S_OK; | |
131 } | |
132 | |
133 public int DestroyProgram(IDebugProgram2 pProgram) { | |
134 Debug.WriteLine("DebugEngine.DestroyProgram"); | |
135 throw new NotImplementedException(); | |
136 } | |
137 | |
138 public int ContinueFromSynchronousEvent(IDebugEvent2 pEvent) { | |
139 Debug.WriteLine("DebugEngine.ContinueFromSynchronousEvent"); | |
140 throw new NotImplementedException(); | |
141 } | |
142 | |
143 public int SetLocale(ushort wLangID) { | |
144 Debug.WriteLine("DebugEngine.SetLocale"); | |
145 locale_ = wLangID; | |
146 return VSConstants.S_OK; | |
147 } | |
148 | |
149 public int SetRegistryRoot(string pszRegistryRoot) { | |
150 Debug.WriteLine("DebugEngine.SetRegistryRoot"); | |
151 registryRoot_ = pszRegistryRoot; | |
152 return VSConstants.S_OK; | |
153 } | |
154 | |
155 public int SetMetric(string pszMetric, object varValue) { | |
156 Debug.WriteLine("DebugEngine.SetMetric"); | |
157 throw new NotImplementedException(); | |
158 } | |
159 | |
160 public int CauseBreak() { | |
161 Debug.WriteLine("DebugEngine.CauseBreak"); | |
162 throw new NotImplementedException(); | |
163 } | |
164 | |
165 public int SetSymbolPath(string szSymbolSearchPath, | |
166 string szSymbolCachePath, | |
167 uint Flags) { | |
168 Debug.WriteLine("DebugEngine.SetSymbolPath"); | |
169 symbolSearchPath_ = szSymbolSearchPath; | |
170 symbolCachePath_ = szSymbolCachePath; | |
171 return VSConstants.S_OK; | |
172 } | |
173 | |
174 public int LoadSymbols() { | |
175 Debug.WriteLine("DebugEngine.LoadSymbols"); | |
176 throw new NotImplementedException(); | |
177 } | |
178 | |
179 public int SetJustMyCodeState(int fUpdate, | |
180 uint dwModules, | |
181 JMC_CODE_SPEC[] rgJMCSpec) { | |
182 Debug.WriteLine("DebugEngine.SetJustMyCodeState"); | |
183 throw new NotImplementedException(); | |
184 } | |
185 | |
186 public int SetEngineGuid(ref Guid guidEngine) { | |
187 Debug.WriteLine("DebugEngine.SetEngineGuid"); | |
188 engineGuid_ = guidEngine; | |
189 return VSConstants.S_OK; | |
190 } | |
191 | |
192 public int SetAllExceptions(enum_EXCEPTION_STATE dwState) { | |
193 Debug.WriteLine("DebugEngine.SetAllExceptions"); | |
194 throw new NotImplementedException(); | |
195 } | |
196 | |
197 #endregion | |
198 | |
199 #region Private Implementation | |
200 | |
201 private readonly List<PendingBreakpoint> breakpoints_ = | |
202 new List<PendingBreakpoint>(); | |
203 | |
204 private readonly List<ProgramNode> programs_ = new List<ProgramNode>(); | |
205 private IDebugEventCallback2 debugEventCallback_; | |
206 private Guid engineGuid_; | |
207 private ushort locale_; | |
208 private string registryRoot_; | |
209 private string symbolCachePath_; | |
210 private string symbolSearchPath_; | |
211 | |
212 #endregion | |
213 | |
214 #region Implementation of IDebugEngineLaunch2 | |
215 | |
216 public int LaunchSuspended(string pszServer, | |
217 IDebugPort2 pPort, | |
218 string pszExe, | |
219 string pszArgs, | |
220 string pszDir, | |
221 string bstrEnv, | |
222 string pszOptions, | |
223 enum_LAUNCH_FLAGS dwLaunchFlags, | |
224 uint hStdInput, | |
225 uint hStdOutput, | |
226 uint hStdError, | |
227 IDebugEventCallback2 pCallback, | |
228 out IDebugProcess2 ppProcess) { | |
229 Debug.WriteLine("DebugEngine.LaunchSuspended"); | |
230 | |
231 var port = (NaClPort) pPort; | |
232 | |
233 ppProcess = null; | |
234 debugEventCallback_ = pCallback; | |
235 | |
236 var psi = new ProcessStartInfo { | |
237 Arguments = pszArgs, | |
238 FileName = pszExe, | |
239 WorkingDirectory = pszDir | |
240 }; | |
241 | |
242 | |
243 ppProcess = port.CreateProcess(psi); | |
244 | |
245 return VSConstants.S_OK; | |
246 } | |
247 | |
248 public int ResumeProcess(IDebugProcess2 pProcess) { | |
249 Debug.WriteLine("DebugEngine.ResumeProcess"); | |
250 | |
251 var proc = (NaClDebugProcess) pProcess; | |
252 NaClPort port = proc.NaClPort; | |
253 var program = new ProgramNode(proc); | |
254 program.Dbg.Opened += | |
255 (sender, status, msg) => OnDebuggerOpened(sender, program); | |
256 ComUtils.RequireOk(port.AddProgramNode(program)); | |
257 // program.Continue(null); | |
258 return VSConstants.S_OK; | |
259 } | |
260 | |
261 | |
262 public int CanTerminateProcess(IDebugProcess2 pProcess) { | |
263 Debug.WriteLine("DebugEngine.CanTerminateProcess"); | |
264 return VSConstants.S_OK; | |
265 } | |
266 | |
267 public int TerminateProcess(IDebugProcess2 pProcess) { | |
268 Debug.WriteLine("DebugEngine.TerminateProcess"); | |
269 pProcess.Terminate(); | |
270 return VSConstants.S_OK; | |
271 } | |
272 | |
273 #endregion | |
274 | |
275 #region Private Implementation | |
276 | |
277 private void ForEachProgram(IDebugProcess2 process, ProgramDelegate action)
{ | |
278 IEnumDebugPrograms2 programs; | |
279 process.EnumPrograms(out programs); | |
280 var prog = new IDebugProgram2[1]; | |
281 uint count = 0; | |
282 while (programs.Next(1, prog, ref count) == VSConstants.S_OK) { | |
283 action(prog[0]); | |
284 } | |
285 } | |
286 | |
287 private void OnDebuggerOpened(ISimpleDebugger sender, ProgramNode program) { | |
288 SendEvent( | |
289 program, program.MainThread, new Ad7Events.DebugLoadCompleteEvent()); | |
290 } | |
291 | |
292 #endregion | |
293 | |
294 #region Private Implementation | |
295 | |
296 private delegate void ProgramDelegate(IDebugProgram2 p); | |
297 | |
298 #endregion | |
299 | |
300 internal void SendEvent(IDebugProgram2 prog, | |
301 IDebugThread2 thread, | |
302 Ad7Events.DebugEvent evt) { | |
303 Debug.WriteLine(string.Format("DebugEngine.SendEvent({0})", evt)); | |
304 Ad7Events.SendEvent(debugEventCallback_, this, null, prog, thread, evt); | |
305 } | |
306 } | |
307 } | |
OLD | NEW |