Index: experimental/visual_studio_plugin/src/NaClVsx.Package/DebugSupport/ProgramNode.cs |
diff --git a/experimental/visual_studio_plugin/src/NaClVsx.Package/DebugSupport/ProgramNode.cs b/experimental/visual_studio_plugin/src/NaClVsx.Package/DebugSupport/ProgramNode.cs |
deleted file mode 100644 |
index f49f25c8441f1d250e22c6d80137ed103502975e..0000000000000000000000000000000000000000 |
--- a/experimental/visual_studio_plugin/src/NaClVsx.Package/DebugSupport/ProgramNode.cs |
+++ /dev/null |
@@ -1,462 +0,0 @@ |
-// Copyright (c) 2011 The Native Client Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-#region |
- |
-using System; |
-using System.Collections.Generic; |
-using System.Diagnostics; |
-using System.IO; |
-using System.Linq; |
-using System.Xml; |
-using System.Xml.Linq; |
-using Google.MsAd7.BaseImpl; |
-using Google.MsAd7.BaseImpl.Ad7Enumerators; |
-using Google.MsAd7.BaseImpl.Interfaces; |
-using Microsoft.VisualStudio; |
-using Microsoft.VisualStudio.Debugger.Interop; |
-using NaClVsx.DebugHelpers; |
- |
-#endregion |
- |
-namespace Google.NaClVsx.DebugSupport { |
- public class ProgramNode |
- : IDebugProgramNode2, |
- IDebugProgram2, |
- IDebugProgramNodeAttach2 { |
- public ProgramNode(NaClDebugProcess process) { |
- // |
- // Program nodes get created and destroyed a lot, so best to avoid |
- // doing much in this constructor. |
- // |
- Trace.WriteLine("Created ProgramNode"); |
- |
- process_ = process; |
- |
- mainThread_ = new Thread(this, "main", 0); |
- modules_.Add(mainModule_); |
- } |
- |
- public INaClDebugger Dbg { |
- get { return dbg_; } |
- } |
- |
- public Guid ProgramGuid { |
- get { return programGuid_; } |
- } |
- |
- public List<Thread> Threads { |
- get { return threads_; } |
- } |
- |
- public List<Module> Modules { |
- get { return modules_; } |
- } |
- |
- public string Arch { |
- get { return arch_; } |
- } |
- |
- public Thread MainThread { |
- get { return mainThread_; } |
- } |
- |
- public Module MainModule { |
- get { return mainModule_; } |
- } |
- |
- public Engine Engine { |
- get { return engine_; } |
- } |
- |
- public void AttachEngine(Engine eng) { |
- Debug.WriteLine("ProgramNode.AttachEngine"); |
- engine_ = eng; |
- |
- |
- dbg_.Stopped += OnStopEvent; |
- dbg_.Continuing += OnContinueEvent; |
- dbg_.StepFinished += OnStepFinished; |
- dbg_.ModuleLoaded += OnModuleLoaded; |
- |
- dbg_.Open(process_.NaClPort.ConnectionString); |
- |
- var tids = dbg_.GetThreads(); |
- foreach (var tid in tids) { |
- threads_.Add( |
- new Thread( |
- this, |
- String.Format("Thread {0}", tid), |
- tid)); |
- } |
- |
- SendEvent( |
- null, |
- new Ad7Events.DebugProgramCreateEvent( |
- enum_EVENTATTRIBUTES.EVENT_ASYNCHRONOUS)); |
- } |
- |
- #region IDebugProgram2 Members |
- |
- public int EnumThreads(out IEnumDebugThreads2 ppEnum) { |
- Debug.WriteLine("ProgramNode.EnumThreads"); |
- |
- ppEnum = new ThreadEnumerator(threads_.ConvertAll(t => (IDebugThread2) t)); |
- return VSConstants.S_OK; |
- } |
- |
- public int GetName(out string pbstrName) { |
- // (ilewis) commenting out the debug spew for this function |
- // because it's called with ludicrous frequency. |
- // Debug.WriteLine("ProgramNode.GetName"); |
- |
- pbstrName = process_.ImagePath; |
- return VSConstants.S_OK; |
- } |
- |
- public int GetProcess(out IDebugProcess2 ppProcess) { |
- Debug.WriteLine("ProgramNode.GetProcess"); |
- |
- // NOTE: not currently called by VS debugger |
- throw new NotImplementedException(); |
- } |
- |
- public int Terminate() { |
- Debug.WriteLine("ProgramNode.Terminate"); |
- // Since we have only one program per process, we |
- // don't do anything here. The DebugProcess instance |
- // will kill the process. |
- SendEvent(MainThread, new Ad7Events.DebugProgramDestroyEvent(0)); |
- return VSConstants.S_OK; |
- } |
- |
- public int Attach(IDebugEventCallback2 pCallback) { |
- Debug.WriteLine("ProgramNode.Attach"); |
- // NOTE: not currently called by VS debugger |
- throw new NotImplementedException(); |
- } |
- |
- public int CanDetach() { |
- Debug.WriteLine("ProgramNode.CanDetach"); |
- return VSConstants.S_OK; |
- } |
- |
- public int Detach() { |
- Debug.WriteLine("ProgramNode.Detach"); |
- |
- dbg_.Close(); |
- SendEvent(null, new Ad7Events.DebugProgramDestroyEvent(0)); |
- return VSConstants.S_OK; |
- } |
- |
- public int GetProgramId(out Guid pguidProgramId) { |
- Debug.WriteLine("ProgramNode.GetProgramId"); |
- pguidProgramId = programGuid_; |
- return VSConstants.S_OK; |
- } |
- |
- public int GetDebugProperty(out IDebugProperty2 ppProperty) { |
- Debug.WriteLine("ProgramNode.GetDebugProperty"); |
- throw new NotImplementedException(); |
- } |
- |
- public int Execute() { |
- Debug.WriteLine("ProgramNode.Execute"); |
- dbg_.Continue(); |
- return VSConstants.S_OK; |
- } |
- |
- public int Continue(IDebugThread2 pThread) { |
- Debug.WriteLine("ProgramNode.Continue"); |
- dbg_.Continue(); |
- return VSConstants.S_OK; |
- } |
- |
- public int Step(IDebugThread2 pThread, |
- enum_STEPKIND sk, |
- enum_STEPUNIT Step) { |
- uint id; |
- if (pThread.GetThreadId(out id) != VSConstants.S_OK) { |
- id = 0; |
- } |
- var thread = (Thread) pThread; |
- var stack = thread.GetStack(); |
- var addr = stack[1].ReturnAddress; |
- var rip = stack[0].ReturnAddress; |
- |
- switch (sk) { |
- /* |
- * In the STEP OUT case, we want to break when the IP hits |
- * the return address on the stack. |
- */ |
- case enum_STEPKIND.STEP_OUT: |
- dbg_.AddTempBreakpoint(addr); |
- dbg_.Continue(); |
- break; |
- |
- /* |
- * In the STEP INTO case, we want to single step until the line |
- * number changes. |
- * TODO(noelallen): This is over simplified, and should be fixed |
- */ |
- case enum_STEPKIND.STEP_INTO: |
- dbg_.Step(id); |
- break; |
- |
- /* |
- * In the STEP OVER case, we want to break on any line number |
- * change in the same function, or if we return, so we add |
- * breakpoints for all lines. |
- * TODO(noelallen): This is over simplified, and should be fixed |
- */ |
- case enum_STEPKIND.STEP_OVER: |
- // Add the 'return' case |
- dbg_.AddTempBreakpoint(addr); |
- DocumentPosition oldPos = null; |
- var addrs = dbg_.Symbols.GetAddressesInScope(rip); |
- foreach (var curraddr in addrs) { |
- var newPos = dbg_.Symbols.PositionFromAddress(curraddr); |
- if (newPos != oldPos) { |
- dbg_.AddTempBreakpoint(curraddr); |
- } |
- newPos = oldPos; |
- } |
- |
- dbg_.Continue(); |
- break; |
- } |
- return VSConstants.S_OK; |
- } |
- |
- public int CauseBreak() { |
- Debug.WriteLine("ProgramNode.CauseBreak"); |
- dbg_.Break(); |
- return VSConstants.S_OK; |
- } |
- |
- public int EnumCodeContexts(IDebugDocumentPosition2 pDocPos, |
- out IEnumDebugCodeContexts2 ppEnum) { |
- Debug.WriteLine("ProgramNode.EnumCodeContexts"); |
- throw new NotImplementedException(); |
- } |
- |
- public int GetMemoryBytes(out IDebugMemoryBytes2 ppMemoryBytes) { |
- Debug.WriteLine("ProgramNode.GetMemoryBytes"); |
- // TODO: replace hardcoded values with something real |
- ppMemoryBytes = new MemoryBytes(dbg_, 0, 65536); |
- return VSConstants.S_OK; |
- } |
- |
- public int GetDisassemblyStream( |
- enum_DISASSEMBLY_STREAM_SCOPE dwScope, |
- IDebugCodeContext2 pCodeContext, |
- out IDebugDisassemblyStream2 ppDisassemblyStream) { |
- Debug.WriteLine("ProgramNode.GetDisassemblyStream"); |
- throw new NotImplementedException(); |
- } |
- |
- public int EnumModules(out IEnumDebugModules2 ppEnum) { |
- Debug.WriteLine("ProgramNode.EnumModules"); |
- |
- ppEnum = new ModuleEnumerator(modules_.ConvertAll(m => (IDebugModule2) m)); |
- return VSConstants.S_OK; |
- } |
- |
- public int GetENCUpdate(out object ppUpdate) { |
- Debug.WriteLine("ProgramNode.GetENCUpdate"); |
- throw new NotImplementedException(); |
- } |
- |
- public int EnumCodePaths(string pszHint, |
- IDebugCodeContext2 pStart, |
- IDebugStackFrame2 pFrame, |
- int fSource, |
- out IEnumCodePaths2 ppEnum, |
- out IDebugCodeContext2 ppSafety) { |
- Debug.WriteLine("ProgramNode.EnumCodePaths"); |
- throw new NotImplementedException(); |
- } |
- |
- public int WriteDump(enum_DUMPTYPE DUMPTYPE, string pszDumpUrl) { |
- Debug.WriteLine("ProgramNode.WriteDump"); |
- throw new NotImplementedException(); |
- } |
- |
- #endregion |
- |
- #region IDebugProgramNode2 Members |
- |
- public int GetProgramName(out string pbstrProgramName) { |
- Debug.WriteLine("ProgramNode.GetProgramName"); |
- pbstrProgramName = null; |
- return VSConstants.S_OK; |
- } |
- |
- public int GetHostName(enum_GETHOSTNAME_TYPE dwHostNameType, |
- out string pbstrHostName) { |
- Debug.WriteLine("ProgramNode.GetHostName"); |
- pbstrHostName = null; |
- return VSConstants.S_OK; |
- } |
- |
- public int GetHostPid(AD_PROCESS_ID[] pHostProcessId) { |
- Debug.WriteLine("ProgramNode.GetHostPid"); |
- return process_.GetPhysicalProcessId(pHostProcessId); |
- } |
- |
- public int GetEngineInfo(out string pbstrEngine, out Guid pguidEngine) { |
- Debug.WriteLine("ProgramNode.GetEngineInfo"); |
- pbstrEngine = Engine.kName; |
- pguidEngine = new Guid(Engine.kId); |
- return VSConstants.S_OK; |
- } |
- |
- public int GetHostMachineName_V7(out string pbstrHostMachineName) { |
- Debug.WriteLine("ProgramNode.GetHostMachineName_V7"); |
- pbstrHostMachineName = null; |
- return VSConstants.E_NOTIMPL; |
- } |
- |
- public int Attach_V7(IDebugProgram2 pMDMProgram, |
- IDebugEventCallback2 pCallback, |
- uint dwReason) { |
- Debug.WriteLine("ProgramNode.Attach_V7"); |
- return VSConstants.E_NOTIMPL; |
- } |
- |
- public int DetachDebugger_V7() { |
- Debug.WriteLine("ProgramNode.DetachDebugger_V7"); |
- return VSConstants.E_NOTIMPL; |
- } |
- |
- #endregion |
- |
- #region Implementation of IDebugProgramNodeAttach2 |
- |
- public int OnAttach(ref Guid guidProgramId) { |
- Debug.WriteLine("ProgramNode.OnAttach"); |
- programGuid_ = guidProgramId; |
- return VSConstants.S_OK; |
- } |
- |
- #endregion |
- |
- #region Private Implementation |
- |
- private readonly INaClDebugger dbg_ = new NaClDebugger(); |
- |
- private readonly Module mainModule_ = new Module(); |
- private readonly Thread mainThread_; |
- private readonly List<Module> modules_ = new List<Module>(); |
- private readonly NaClDebugProcess process_; |
- |
- private readonly Dictionary<int, string> sourceIdToPath_ = |
- new Dictionary<int, string>(); |
- |
- private readonly List<Thread> threads_ = new List<Thread>(); |
- |
- // TODO(ilewis): get the base address from the debuggee instead |
- // of hardcoding it |
- |
- private string arch_; |
- private Engine engine_; |
- |
- private Dictionary<string, int> pathToSourceId_ = |
- new Dictionary<string, int>(); |
- |
- private Guid programGuid_ = Guid.NewGuid(); |
- |
- #endregion |
- |
- #region Private Implementation |
- |
- private void OnBreak(GdbProxy.ResultCode status, string msg, byte[] data) { |
- SendEvent(mainThread_, new Ad7Events.DebugBreakEvent()); |
- } |
- |
- void OnContinueEvent(ISimpleDebugger sender, |
- SimpleDebuggerTypes.EventType t, |
- SimpleDebuggerTypes.ResultCode status) { |
- Debug.WriteLine("Debug event: Continue"); |
- } |
- |
- private void OnModuleLoaded(ISimpleDebugger sender, |
- string modulepath, |
- string status) { |
- Debug.WriteLine(string.Format("{0}: {1}", modulepath, status)); |
- mainModule_.Url = modulepath; |
- mainModule_.Name = Path.GetFileName(modulepath); |
- mainModule_.UrlSymbolLocation = modulepath; |
- |
- SendEvent( |
- null, |
- new Ad7Events.DebugModuleLoadEvent( |
- mainModule_, |
- "Loading module", |
- true)); |
- |
- SendEvent( |
- null, |
- new Ad7Events.DebugSymbolSearchEvent( |
- mainModule_, |
- "DWARF symbols loaded", |
- enum_MODULE_INFO_FLAGS. |
- MIF_SYMBOLS_LOADED)); |
- } |
- |
- void OnStepFinished(ISimpleDebugger sender, |
- SimpleDebuggerTypes.EventType t, |
- SimpleDebuggerTypes.ResultCode status) { |
- SendEvent(mainThread_, new Ad7Events.DebugStepCompleteEvent()); |
- } |
- |
- void OnStopEvent(ISimpleDebugger sender, |
- SimpleDebuggerTypes.EventType eventType, |
- SimpleDebuggerTypes.ResultCode status) { |
- Debug.WriteLine("Debug event: Break"); |
- engine_.EnableAllBreakpoints(false); |
- SendEvent(mainThread_, new Ad7Events.DebugBreakEvent()); |
- } |
- |
- private void ParseArchString(string msg) { |
- Debug.WriteLine(msg); |
- try { |
- var targetString = XElement.Parse(msg); |
- var archElements = |
- targetString.Descendants("architecture"); |
- var el = archElements.FirstOrDefault(); |
- arch_ = el.Value; |
- } |
- catch (XmlException e) { |
- Debug.WriteLine(e.Message); |
- } |
- } |
- |
- private void ParseThreadsString(string msg) { |
- Debug.WriteLine(msg); |
- try { |
- var threadsString = XElement.Parse(msg); |
- foreach (var el in threadsString.Descendants("thread")) { |
- var tidStr = el.Attribute("id").Value; |
- var tid = Convert.ToUInt32(tidStr, 16); |
- |
- threads_.Add( |
- new Thread( |
- this, |
- String.Format("Thread {0}", tid), |
- tid)); |
- } |
- } |
- catch (Exception e) { |
- Debug.WriteLine(e.Message); |
- } |
- } |
- |
- #endregion |
- |
- internal void SendEvent(IDebugThread2 thread, Ad7Events.DebugEvent evt) { |
- engine_.SendEvent(this, thread, evt); |
- } |
- } |
-} |