From b874c5c514151bbeb90cc46a9b81d0a587f48d00 Mon Sep 17 00:00:00 2001 From: Andreas Hollandt Date: Sat, 1 Aug 2020 20:58:07 +0200 Subject: [PATCH 01/11] implement DAP Goto Request --- .../CommandFactories/MICommandFactory.cs | 6 ++ src/MICore/CommandFactories/gdb.cs | 23 ++++- src/MICore/CommandFactories/lldb.cs | 13 +++ src/MIDebugEngine/AD7.Impl/AD7Engine.cs | 38 ++++++++ .../AD7.Impl/AD7MemoryAddress.cs | 38 ++++---- src/MIDebugEngine/AD7.Impl/AD7Thread.cs | 24 +++-- .../Engine.Impl/DebuggedProcess.cs | 10 +++ src/OpenDebugAD7/AD7DebugSession.cs | 90 ++++++++++++++++++- .../AD7Impl/AD7BreakPointRequest.cs | 2 +- .../AD7Impl/AD7DocumentPosition.cs | 2 +- src/OpenDebugAD7/AD7Resources.Designer.cs | 11 +++ src/OpenDebugAD7/AD7Resources.resx | 3 + 12 files changed, 225 insertions(+), 35 deletions(-) diff --git a/src/MICore/CommandFactories/MICommandFactory.cs b/src/MICore/CommandFactories/MICommandFactory.cs index ff0d3d078..4ec9fd469 100644 --- a/src/MICore/CommandFactories/MICommandFactory.cs +++ b/src/MICore/CommandFactories/MICommandFactory.cs @@ -242,6 +242,12 @@ public async Task ExecNextInstruction(int threadId, ResultClass resultClass = Re await ThreadFrameCmdAsync(command, resultClass, threadId, 0); } + /// + /// Jumps to a specified target location + /// + abstract public Task ExecJump(string filename, int line); + abstract public Task ExecJump(ulong address); + /// /// Tells GDB to spawn a target process previous setup with -file-exec-and-symbols or similar /// diff --git a/src/MICore/CommandFactories/gdb.cs b/src/MICore/CommandFactories/gdb.cs index 4bcb24b30..f65d9846f 100644 --- a/src/MICore/CommandFactories/gdb.cs +++ b/src/MICore/CommandFactories/gdb.cs @@ -157,7 +157,7 @@ public override async Task ThreadInfo(uint? threadId = null) public override async Task> StartAddressesForLine(string file, uint line) { - string cmd = "info line " + file + ":" + line; + string cmd = "info line -s " + file + " -li " + line; var result = await _debugger.ConsoleCmdAsync(cmd, allowWhileRunning: false); List addresses = new List(); using (StringReader stringReader = new StringReader(result)) @@ -173,7 +173,7 @@ public override async Task> StartAddressesForLine(string file, uint { ulong address; string addrStr = resultLine.Substring(pos + 18); - if (MICommandFactory.SpanNextAddr(addrStr, out address) != null) + if (SpanNextAddr(addrStr, out address) != null) { addresses.Add(address); } @@ -183,6 +183,25 @@ public override async Task> StartAddressesForLine(string file, uint return addresses; } + private async Task JumpInternal(string target) + { + // temporary breakpoint + jump + await _debugger.CmdAsync("-break-insert -t " + target, ResultClass.done); + await _debugger.CmdAsync("-exec-jump " + target, ResultClass.running); + } + + public override Task ExecJump(string filename, int line) + { + string target = "--source " + filename + " --line " + line.ToString(CultureInfo.InvariantCulture); + return JumpInternal(target); + } + + public override Task ExecJump(ulong address) + { + string target = "*" + string.Format(CultureInfo.InvariantCulture, "0x{0:X}", address); + return JumpInternal(target); + } + public override Task EnableTargetAsyncOption() { // Linux attach TODO: GDB will fail this command when attaching. This is worked around diff --git a/src/MICore/CommandFactories/lldb.cs b/src/MICore/CommandFactories/lldb.cs index 3cb2d9467..80fe9f8f6 100644 --- a/src/MICore/CommandFactories/lldb.cs +++ b/src/MICore/CommandFactories/lldb.cs @@ -177,6 +177,19 @@ public override Task Catch(string name, bool onlyOnce = false, ResultClass resul throw new NotImplementedException("lldb catch command"); } + // TODO: update these if they become available in lldb-mi + public override async Task ExecJump(string filename, int line) + { + string command = "jump " + filename + ":" + line; + await _debugger.CmdAsync(command, ResultClass.running); + } + + public override async Task ExecJump(ulong address) + { + string command = "jump *" + string.Format("0x{0:X}", address); + await _debugger.CmdAsync(command, ResultClass.running); + } + /// /// Assigns the value of an expression to a variable. /// Since LLDB only accepts assigning values to variables, the expression may need to be evaluated. diff --git a/src/MIDebugEngine/AD7.Impl/AD7Engine.cs b/src/MIDebugEngine/AD7.Impl/AD7Engine.cs index 7865a3887..fdf0359ac 100755 --- a/src/MIDebugEngine/AD7.Impl/AD7Engine.cs +++ b/src/MIDebugEngine/AD7.Impl/AD7Engine.cs @@ -182,6 +182,44 @@ public object GetMetric(string metric) return _configStore.GetEngineMetric(metric); } + public int Jump(string filename, int line) + { + try + { + _debuggedProcess.WorkerThread.RunOperation(() => _debuggedProcess.Jump(filename, line)); + } + catch (InvalidCoreDumpOperationException) + { + return AD7_HRESULT.E_CRASHDUMP_UNSUPPORTED; + } + catch (Exception e) + { + _engineCallback.OnError(EngineUtils.GetExceptionDescription(e)); + return Constants.E_ABORT; + } + + return Constants.S_OK; + } + + public int Jump(ulong address) + { + try + { + _debuggedProcess.WorkerThread.RunOperation(() => _debuggedProcess.Jump(address)); + } + catch (InvalidCoreDumpOperationException) + { + return AD7_HRESULT.E_CRASHDUMP_UNSUPPORTED; + } + catch (Exception e) + { + _engineCallback.OnError(EngineUtils.GetExceptionDescription(e)); + return Constants.E_ABORT; + } + + return Constants.S_OK; + } + #region IDebugEngine2 Members // Attach the debug engine to a program. diff --git a/src/MIDebugEngine/AD7.Impl/AD7MemoryAddress.cs b/src/MIDebugEngine/AD7.Impl/AD7MemoryAddress.cs index f478379ad..09bc6a277 100644 --- a/src/MIDebugEngine/AD7.Impl/AD7MemoryAddress.cs +++ b/src/MIDebugEngine/AD7.Impl/AD7MemoryAddress.cs @@ -2,11 +2,8 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System; -using System.Collections.Generic; -using System.Text; using Microsoft.VisualStudio.Debugger.Interop; using MICore; -using Microsoft.MIDebugEngine.Natvis; namespace Microsoft.MIDebugEngine { @@ -14,7 +11,7 @@ namespace Microsoft.MIDebugEngine // IDebugMemoryContext2 represents a position in the address space of the machine running the program being debugged. // IDebugCodeContext2 represents the starting position of a code instruction. // For most run-time architectures today, a code context can be thought of as an address in a program's execution stream. - internal class AD7MemoryAddress : IDebugCodeContext2 + internal sealed class AD7MemoryAddress : IDebugCodeContext2 { private readonly AD7Engine _engine; private readonly ulong _address; @@ -42,6 +39,9 @@ public void SetDocumentContext(IDebugDocumentContext2 docContext) // Adds a specified value to the current context's address to create a new context. public int Add(ulong dwCount, out IDebugMemoryContext2 newAddress) { + // NB: this is not correct for IDebugCodeContext2 according to the docs + // https://docs.microsoft.com/en-us/visualstudio/extensibility/debugger/reference/idebugcodecontext2#remarks + // But it's not used in practice (instead: IDebugDisassemblyStream2.Seek) newAddress = new AD7MemoryAddress(_engine, (uint)dwCount + _address, null); return Constants.S_OK; } @@ -160,19 +160,22 @@ public int GetInfo(enum_CONTEXT_INFO_FIELDS dwFields, CONTEXT_INFO[] pinfo) { pinfo[0].dwFields = 0; - if ((dwFields & enum_CONTEXT_INFO_FIELDS.CIF_ADDRESS) != 0) + if ((dwFields & (enum_CONTEXT_INFO_FIELDS.CIF_ADDRESS | enum_CONTEXT_INFO_FIELDS.CIF_ADDRESSABSOLUTE)) != 0) { - pinfo[0].bstrAddress = EngineUtils.AsAddr(_address, _engine.DebuggedProcess.Is64BitArch); - pinfo[0].dwFields |= enum_CONTEXT_INFO_FIELDS.CIF_ADDRESS; + string addr = EngineUtils.AsAddr(_address, _engine.DebuggedProcess.Is64BitArch); + if ((dwFields & enum_CONTEXT_INFO_FIELDS.CIF_ADDRESS) != 0) + { + pinfo[0].bstrAddress = addr; + pinfo[0].dwFields |= enum_CONTEXT_INFO_FIELDS.CIF_ADDRESS; + } + if ((dwFields & enum_CONTEXT_INFO_FIELDS.CIF_ADDRESSABSOLUTE) != 0) + { + pinfo[0].bstrAddressAbsolute = addr; + pinfo[0].dwFields |= enum_CONTEXT_INFO_FIELDS.CIF_ADDRESSABSOLUTE; + } } - // Fields not supported by the sample if ((dwFields & enum_CONTEXT_INFO_FIELDS.CIF_ADDRESSOFFSET) != 0) { } - if ((dwFields & enum_CONTEXT_INFO_FIELDS.CIF_ADDRESSABSOLUTE) != 0) - { - pinfo[0].bstrAddressAbsolute = EngineUtils.AsAddr(_address, _engine.DebuggedProcess.Is64BitArch); - pinfo[0].dwFields |= enum_CONTEXT_INFO_FIELDS.CIF_ADDRESSABSOLUTE; - } if ((dwFields & enum_CONTEXT_INFO_FIELDS.CIF_MODULEURL) != 0) { DebuggedModule module = _engine.DebuggedProcess.ResolveAddress(_address); @@ -195,7 +198,10 @@ public int GetInfo(enum_CONTEXT_INFO_FIELDS dwFields, CONTEXT_INFO[] pinfo) pinfo[0].dwFields |= enum_CONTEXT_INFO_FIELDS.CIF_FUNCTION; } } - if ((dwFields & enum_CONTEXT_INFO_FIELDS.CIF_FUNCTIONOFFSET) != 0) { } + if ((dwFields & enum_CONTEXT_INFO_FIELDS.CIF_FUNCTIONOFFSET) != 0) + { + // TODO: + } return Constants.S_OK; } @@ -210,10 +216,10 @@ public int GetInfo(enum_CONTEXT_INFO_FIELDS dwFields, CONTEXT_INFO[] pinfo) } // Gets the user-displayable name for this context - // This is not supported by the sample engine. public int GetName(out string pbstrName) { - throw new NotImplementedException(); + pbstrName = _functionName ?? Engine.GetAddressDescription(_address); + return Constants.S_OK; } // Subtracts a specified value from the current context's address to create a new context. diff --git a/src/MIDebugEngine/AD7.Impl/AD7Thread.cs b/src/MIDebugEngine/AD7.Impl/AD7Thread.cs index b2b0a8d35..f5457c011 100644 --- a/src/MIDebugEngine/AD7.Impl/AD7Thread.cs +++ b/src/MIDebugEngine/AD7.Impl/AD7Thread.cs @@ -282,27 +282,23 @@ int IDebugThread2.Resume(out uint suspendCount) } // Sets the next statement to the given stack frame and code context. + // https://docs.microsoft.com/en-us/visualstudio/extensibility/debugger/reference/idebugthread2-setnextstatement int IDebugThread2.SetNextStatement(IDebugStackFrame2 stackFrame, IDebugCodeContext2 codeContext) { - ulong addr = ((AD7MemoryAddress)codeContext).Address; - AD7StackFrame frame = ((AD7StackFrame)stackFrame); - if (frame.ThreadContext.Level != 0 || frame.Thread != this || !frame.ThreadContext.pc.HasValue) - { + // VS does provide a frame so at least do some sanity checks + AD7StackFrame frame = stackFrame as AD7StackFrame; + if (frame != null && (frame.ThreadContext.Level != 0 || frame.Thread != this)) return Constants.S_FALSE; - } - string toFunc = EngineUtils.GetAddressDescription(_engine.DebuggedProcess, addr); - string fromFunc = EngineUtils.GetAddressDescription(_engine.DebuggedProcess, frame.ThreadContext.pc.Value); - if (toFunc != fromFunc) + + try { - return Constants.S_FALSE; + ulong addr = ((AD7MemoryAddress)codeContext).Address; + return _engine.Jump(addr); } - string result = frame.EvaluateExpression("$pc=" + EngineUtils.AsAddr(addr, _engine.DebuggedProcess.Is64BitArch)); - if (result != null) + catch (Exception) { - _engine.DebuggedProcess.ThreadCache.MarkDirty(); - return Constants.S_OK; + return Constants.S_FALSE; } - return Constants.S_FALSE; } // suspend a thread. diff --git a/src/MIDebugEngine/Engine.Impl/DebuggedProcess.cs b/src/MIDebugEngine/Engine.Impl/DebuggedProcess.cs index eddad0aec..219c85e7d 100755 --- a/src/MIDebugEngine/Engine.Impl/DebuggedProcess.cs +++ b/src/MIDebugEngine/Engine.Impl/DebuggedProcess.cs @@ -1601,6 +1601,16 @@ public Task Continue(DebuggedThread thread) return Execute(thread); } + public async Task Jump(string filename, int line) + { + await MICommandFactory.ExecJump(filename, line); + } + + public async Task Jump(ulong address) + { + await MICommandFactory.ExecJump(address); + } + public async Task Step(int threadId, enum_STEPKIND kind, enum_STEPUNIT unit) { this.VerifyNotDebuggingCoreDump(); diff --git a/src/OpenDebugAD7/AD7DebugSession.cs b/src/OpenDebugAD7/AD7DebugSession.cs index 9921e0019..84bf9108a 100644 --- a/src/OpenDebugAD7/AD7DebugSession.cs +++ b/src/OpenDebugAD7/AD7DebugSession.cs @@ -27,7 +27,7 @@ namespace OpenDebugAD7 { - internal class AD7DebugSession : DebugAdapterBase, IDebugPortNotify2, IDebugEventCallback2 + internal sealed class AD7DebugSession : DebugAdapterBase, IDebugPortNotify2, IDebugEventCallback2 { // This is a general purpose lock. Don't hold it across long operations. private readonly object m_lock = new object(); @@ -44,6 +44,8 @@ internal class AD7DebugSession : DebugAdapterBase, IDebugPortNotify2, IDebugEven private readonly DebugEventLogger m_logger; private readonly Dictionary> m_breakpoints; + private readonly List m_gotoCodeContexts = new List(); + private Dictionary m_functionBreakpoints; private readonly HandleCollection m_frameHandles; @@ -350,6 +352,7 @@ public void BeforeContinue() m_isStopped = false; m_variableManager.Reset(); m_frameHandles.Reset(); + m_gotoCodeContexts.Clear(); } public void Stopped(IDebugThread2 thread) @@ -793,6 +796,7 @@ protected override void HandleInitializeRequestAsync(IRequestResponder responder) + { + var response = new GotoResponse(); + if (!m_isStopped) + { + responder.SetResponse(response); + return; + } + + var builder = new ErrorBuilder(() => AD7Resources.Error_UnableToSetNextStatement); + try + { + var gotoTarget = m_gotoCodeContexts[responder.Arguments.TargetId]; + IDebugThread2 thread = null; + lock (m_threads) + { + if (!m_threads.TryGetValue(responder.Arguments.ThreadId, out thread)) + throw new AD7Exception("Unknown thread id: " + responder.Arguments.ThreadId.ToString(CultureInfo.InvariantCulture)); + } + BeforeContinue(); + builder.CheckHR(thread.SetNextStatement(null, gotoTarget)); + } + catch (AD7Exception e) + { + m_isStopped = true; + responder.SetError(new ProtocolException(e.Message)); + } + + responder.SetResponse(response); + } + + protected override void HandleGotoTargetsRequestAsync(IRequestResponder responder) + { + var response = new GotoTargetsResponse(); + + var source = responder.Arguments.Source; + // TODO: handle this for disassembly debugging + if (source.Path == null) + { + responder.SetResponse(response); + return; + } + + try + { + string convertedPath = m_pathConverter.ConvertClientPathToDebugger(source.Path); + int line = m_pathConverter.ConvertClientLineToDebugger(responder.Arguments.Line); + var docPos = new AD7DocumentPosition(m_sessionConfig, convertedPath, line); + + var targets = new List(); + + IEnumDebugCodeContexts2 codeContextsEnum; + if (m_program.EnumCodeContexts(docPos, out codeContextsEnum) == HRConstants.S_OK) + { + var codeContexts = new IDebugCodeContext2[1]; + uint nProps = 0; + while (codeContextsEnum.Next(1, codeContexts, ref nProps) == HRConstants.S_OK) + { + var codeContext = codeContexts[0]; + string contextName; + codeContext.GetName(out contextName); + line = responder.Arguments.Line; + IDebugDocumentContext2 documentContext; + if (codeContext.GetDocumentContext(out documentContext) == HRConstants.S_OK) + { + var pos = new TEXT_POSITION[1]; + if (documentContext.GetStatementRange(pos, null) == HRConstants.S_OK) + line = m_pathConverter.ConvertDebuggerLineToClient((int)pos[0].dwLine); + } + targets.Add(new GotoTarget(m_gotoCodeContexts.Create(codeContext), contextName, line)); + } + } + + response.Targets = targets; + } + catch (AD7Exception e) + { + responder.SetError(new ProtocolException(e.Message)); + return; + } + + responder.SetResponse(response); + } + protected override void HandleStackTraceRequestAsync(IRequestResponder responder) { int threadReference = responder.Arguments.ThreadId; diff --git a/src/OpenDebugAD7/AD7Impl/AD7BreakPointRequest.cs b/src/OpenDebugAD7/AD7Impl/AD7BreakPointRequest.cs index 1528236a1..96d36f1d7 100644 --- a/src/OpenDebugAD7/AD7Impl/AD7BreakPointRequest.cs +++ b/src/OpenDebugAD7/AD7Impl/AD7BreakPointRequest.cs @@ -8,7 +8,7 @@ namespace OpenDebugAD7.AD7Impl { - internal class AD7BreakPointRequest : IDebugBreakpointRequest2, IDebugBreakpointChecksumRequest2 + internal sealed class AD7BreakPointRequest : IDebugBreakpointRequest2, IDebugBreakpointChecksumRequest2 { private static uint s_nextBreakpointId = 0; diff --git a/src/OpenDebugAD7/AD7Impl/AD7DocumentPosition.cs b/src/OpenDebugAD7/AD7Impl/AD7DocumentPosition.cs index be69bd49a..002ffa8d7 100644 --- a/src/OpenDebugAD7/AD7Impl/AD7DocumentPosition.cs +++ b/src/OpenDebugAD7/AD7Impl/AD7DocumentPosition.cs @@ -8,7 +8,7 @@ namespace OpenDebugAD7.AD7Impl { - internal class AD7DocumentPosition : IDebugDocumentPosition2, IDebugDocumentPosition110 + internal sealed class AD7DocumentPosition : IDebugDocumentPosition2, IDebugDocumentPosition110 { public string Path { diff --git a/src/OpenDebugAD7/AD7Resources.Designer.cs b/src/OpenDebugAD7/AD7Resources.Designer.cs index ccfa43728..974168470 100644 --- a/src/OpenDebugAD7/AD7Resources.Designer.cs +++ b/src/OpenDebugAD7/AD7Resources.Designer.cs @@ -397,6 +397,17 @@ internal static string Error_UnableToSetBreakpoint { } } + /// + /// Looks up a localized string similar to Error setting next statement. {0}. + /// + internal static string Error_UnableToSetNextStatement + { + get + { + return ResourceManager.GetString("Error_UnableToSetNextStatement", resourceCulture); + } + } + /// /// Looks up a localized string similar to '{0}' cannot be assigned to. /// diff --git a/src/OpenDebugAD7/AD7Resources.resx b/src/OpenDebugAD7/AD7Resources.resx index 33a8db067..42237a129 100644 --- a/src/OpenDebugAD7/AD7Resources.resx +++ b/src/OpenDebugAD7/AD7Resources.resx @@ -195,6 +195,9 @@ Error setting breakpoint. {0} + + Error setting next statement. {0} + Unable to parse 'logMessage'. From a64c8d5f957d1660ffdf88925fdf0c1750c4fd9e Mon Sep 17 00:00:00 2001 From: Andreas Hollandt Date: Wed, 9 Sep 2020 09:48:38 +0200 Subject: [PATCH 02/11] use List for HandleCollection --- .../VSCode/HandleCollection.cs | 49 +++++++------------ src/OpenDebugAD7/AD7DebugSession.cs | 2 +- src/OpenDebugAD7/VariableManager.cs | 2 +- 3 files changed, 20 insertions(+), 33 deletions(-) diff --git a/src/DebugEngineHost.VSCode/VSCode/HandleCollection.cs b/src/DebugEngineHost.VSCode/VSCode/HandleCollection.cs index 1d23ea8a7..64a26d7fe 100644 --- a/src/DebugEngineHost.VSCode/VSCode/HandleCollection.cs +++ b/src/DebugEngineHost.VSCode/VSCode/HandleCollection.cs @@ -2,8 +2,6 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. -using System; -using System.Linq; using System.Collections.Generic; namespace Microsoft.DebugEngineHost.VSCode @@ -11,73 +9,62 @@ namespace Microsoft.DebugEngineHost.VSCode public sealed class HandleCollection { private const int START_HANDLE = 1000; + private List _collection = new List(); - private int _nextHandle; - private Dictionary _handleMap; - - public HandleCollection() - { - _nextHandle = START_HANDLE; - _handleMap = new Dictionary(); - } - - public void Reset() + public void Clear() { - _nextHandle = START_HANDLE; - _handleMap.Clear(); + _collection.Clear(); } public int Create(T value) { - var handle = _nextHandle++; - _handleMap[handle] = value; - return handle; + _collection.Add(value); + return _collection.Count + START_HANDLE - 1; } public bool TryGet(int handle, out T value) { - if (_handleMap.TryGetValue(handle, out value)) + if (handle < 0 || handle - START_HANDLE >= _collection.Count) { - return true; + value = default; + return false; } - return false; + + value = _collection[handle - START_HANDLE]; + return true; } public bool TryGetFirst(out T value) { if (IsEmpty) { - value = default(T); + value = default; return false; } - return TryGet(_handleMap.Keys.Min(), out value); + value = _collection[0]; + return true; } public T this[int handle] { get { - T value; - if (!TryGet(handle, out value)) - { - throw new ArgumentOutOfRangeException(nameof(handle)); - } - - return value; + return _collection[handle - START_HANDLE]; } } public bool Remove(int handle) { - return _handleMap.Remove(handle); + _collection.RemoveAt(handle - START_HANDLE); + return true; } public bool IsEmpty { get { - return _handleMap.Count == 0; + return _collection.Count == 0; } } } diff --git a/src/OpenDebugAD7/AD7DebugSession.cs b/src/OpenDebugAD7/AD7DebugSession.cs index 84bf9108a..8cc65253e 100644 --- a/src/OpenDebugAD7/AD7DebugSession.cs +++ b/src/OpenDebugAD7/AD7DebugSession.cs @@ -351,7 +351,7 @@ public void BeforeContinue() m_isStepping = false; m_isStopped = false; m_variableManager.Reset(); - m_frameHandles.Reset(); + m_frameHandles.Clear(); m_gotoCodeContexts.Clear(); } diff --git a/src/OpenDebugAD7/VariableManager.cs b/src/OpenDebugAD7/VariableManager.cs index def25f74d..d8b2a49a4 100644 --- a/src/OpenDebugAD7/VariableManager.cs +++ b/src/OpenDebugAD7/VariableManager.cs @@ -38,7 +38,7 @@ internal VariableManager() internal void Reset() { - m_variableHandles.Reset(); + m_variableHandles.Clear(); } internal Boolean IsEmpty() From 1138d4eea5ee4f0f397aa37096c9d3db4d746093 Mon Sep 17 00:00:00 2001 From: Andreas Hollandt Date: Wed, 9 Sep 2020 09:49:15 +0200 Subject: [PATCH 03/11] use HandleCollection for goto targets --- src/OpenDebugAD7/AD7DebugSession.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OpenDebugAD7/AD7DebugSession.cs b/src/OpenDebugAD7/AD7DebugSession.cs index 8cc65253e..6d66180fe 100644 --- a/src/OpenDebugAD7/AD7DebugSession.cs +++ b/src/OpenDebugAD7/AD7DebugSession.cs @@ -44,7 +44,7 @@ internal sealed class AD7DebugSession : DebugAdapterBase, IDebugPortNotify2, IDe private readonly DebugEventLogger m_logger; private readonly Dictionary> m_breakpoints; - private readonly List m_gotoCodeContexts = new List(); + private readonly HandleCollection m_gotoCodeContexts = new HandleCollection(); private Dictionary m_functionBreakpoints; private readonly HandleCollection m_frameHandles; From 57f5d33face9c21852e78192c70dc8d94df8ba1f Mon Sep 17 00:00:00 2001 From: Andreas Hollandt Date: Fri, 11 Sep 2020 13:11:27 +0200 Subject: [PATCH 04/11] cleanup --- src/MIDebugEngine/AD7.Impl/AD7StackFrame.cs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/MIDebugEngine/AD7.Impl/AD7StackFrame.cs b/src/MIDebugEngine/AD7.Impl/AD7StackFrame.cs index 82ec4c1e5..9033f3740 100644 --- a/src/MIDebugEngine/AD7.Impl/AD7StackFrame.cs +++ b/src/MIDebugEngine/AD7.Impl/AD7StackFrame.cs @@ -14,7 +14,7 @@ namespace Microsoft.MIDebugEngine { // Represents a logical stack frame on the thread stack. // Also implements the IDebugExpressionContext interface, which allows expression evaluation and watch windows. - internal class AD7StackFrame : IDebugStackFrame2, IDebugExpressionContext2 + internal sealed class AD7StackFrame : IDebugStackFrame2, IDebugExpressionContext2 { public AD7Engine Engine { get; private set; } public AD7Thread Thread { get; private set; } @@ -53,11 +53,7 @@ public AD7StackFrame(AD7Engine engine, AD7Thread thread, ThreadContext threadCon if (_textPosition != null) { _documentCxt = new AD7DocumentContext(_textPosition, _codeCxt); - - if (_codeCxt != null) - { - _codeCxt.SetDocumentContext(_documentCxt); - } + _codeCxt?.SetDocumentContext(_documentCxt); } } From 9b887642b28c6234fabc8f684f0e7151c73a933f Mon Sep 17 00:00:00 2001 From: Andreas Hollandt Date: Tue, 20 Oct 2020 21:04:14 +0200 Subject: [PATCH 05/11] Revert "use HandleCollection for goto targets" Revert "use List for HandleCollection" --- .../VSCode/HandleCollection.cs | 49 ++++++++++++------- src/OpenDebugAD7/AD7DebugSession.cs | 4 +- src/OpenDebugAD7/VariableManager.cs | 2 +- 3 files changed, 34 insertions(+), 21 deletions(-) diff --git a/src/DebugEngineHost.VSCode/VSCode/HandleCollection.cs b/src/DebugEngineHost.VSCode/VSCode/HandleCollection.cs index 64a26d7fe..1d23ea8a7 100644 --- a/src/DebugEngineHost.VSCode/VSCode/HandleCollection.cs +++ b/src/DebugEngineHost.VSCode/VSCode/HandleCollection.cs @@ -2,6 +2,8 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. +using System; +using System.Linq; using System.Collections.Generic; namespace Microsoft.DebugEngineHost.VSCode @@ -9,62 +11,73 @@ namespace Microsoft.DebugEngineHost.VSCode public sealed class HandleCollection { private const int START_HANDLE = 1000; - private List _collection = new List(); - public void Clear() + private int _nextHandle; + private Dictionary _handleMap; + + public HandleCollection() + { + _nextHandle = START_HANDLE; + _handleMap = new Dictionary(); + } + + public void Reset() { - _collection.Clear(); + _nextHandle = START_HANDLE; + _handleMap.Clear(); } public int Create(T value) { - _collection.Add(value); - return _collection.Count + START_HANDLE - 1; + var handle = _nextHandle++; + _handleMap[handle] = value; + return handle; } public bool TryGet(int handle, out T value) { - if (handle < 0 || handle - START_HANDLE >= _collection.Count) + if (_handleMap.TryGetValue(handle, out value)) { - value = default; - return false; + return true; } - - value = _collection[handle - START_HANDLE]; - return true; + return false; } public bool TryGetFirst(out T value) { if (IsEmpty) { - value = default; + value = default(T); return false; } - value = _collection[0]; - return true; + return TryGet(_handleMap.Keys.Min(), out value); } public T this[int handle] { get { - return _collection[handle - START_HANDLE]; + T value; + if (!TryGet(handle, out value)) + { + throw new ArgumentOutOfRangeException(nameof(handle)); + } + + return value; } } public bool Remove(int handle) { - _collection.RemoveAt(handle - START_HANDLE); - return true; + return _handleMap.Remove(handle); } public bool IsEmpty { get { - return _collection.Count == 0; + return _handleMap.Count == 0; } } } diff --git a/src/OpenDebugAD7/AD7DebugSession.cs b/src/OpenDebugAD7/AD7DebugSession.cs index 6d66180fe..84bf9108a 100644 --- a/src/OpenDebugAD7/AD7DebugSession.cs +++ b/src/OpenDebugAD7/AD7DebugSession.cs @@ -44,7 +44,7 @@ internal sealed class AD7DebugSession : DebugAdapterBase, IDebugPortNotify2, IDe private readonly DebugEventLogger m_logger; private readonly Dictionary> m_breakpoints; - private readonly HandleCollection m_gotoCodeContexts = new HandleCollection(); + private readonly List m_gotoCodeContexts = new List(); private Dictionary m_functionBreakpoints; private readonly HandleCollection m_frameHandles; @@ -351,7 +351,7 @@ public void BeforeContinue() m_isStepping = false; m_isStopped = false; m_variableManager.Reset(); - m_frameHandles.Clear(); + m_frameHandles.Reset(); m_gotoCodeContexts.Clear(); } diff --git a/src/OpenDebugAD7/VariableManager.cs b/src/OpenDebugAD7/VariableManager.cs index d8b2a49a4..def25f74d 100644 --- a/src/OpenDebugAD7/VariableManager.cs +++ b/src/OpenDebugAD7/VariableManager.cs @@ -38,7 +38,7 @@ internal VariableManager() internal void Reset() { - m_variableHandles.Clear(); + m_variableHandles.Reset(); } internal Boolean IsEmpty() From f119e0c10e86c021ed4fc8d438fa82ad4ebdb1f8 Mon Sep 17 00:00:00 2001 From: Andrew Wang Date: Wed, 28 Oct 2020 16:47:34 -0700 Subject: [PATCH 06/11] Fixing todo --- src/MICore/CommandFactories/lldb.cs | 2 +- src/OpenDebugAD7/AD7DebugSession.cs | 34 +++++++++++++++++++---------- 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/src/MICore/CommandFactories/lldb.cs b/src/MICore/CommandFactories/lldb.cs index 80fe9f8f6..e2181942c 100644 --- a/src/MICore/CommandFactories/lldb.cs +++ b/src/MICore/CommandFactories/lldb.cs @@ -186,7 +186,7 @@ public override async Task ExecJump(string filename, int line) public override async Task ExecJump(ulong address) { - string command = "jump *" + string.Format("0x{0:X}", address); + string command = "jump *" + string.Format(CultureInfo.InvariantCulture, "0x{0:X}", address); await _debugger.CmdAsync(command, ResultClass.running); } diff --git a/src/OpenDebugAD7/AD7DebugSession.cs b/src/OpenDebugAD7/AD7DebugSession.cs index 84bf9108a..7ed6475a3 100644 --- a/src/OpenDebugAD7/AD7DebugSession.cs +++ b/src/OpenDebugAD7/AD7DebugSession.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; @@ -44,7 +45,9 @@ internal sealed class AD7DebugSession : DebugAdapterBase, IDebugPortNotify2, IDe private readonly DebugEventLogger m_logger; private readonly Dictionary> m_breakpoints; - private readonly List m_gotoCodeContexts = new List(); + + private readonly ConcurrentDictionary m_gotoCodeContexts = new ConcurrentDictionary(); + private int m_nextContextId = 1; private Dictionary m_functionBreakpoints; private readonly HandleCollection m_frameHandles; @@ -1333,15 +1336,17 @@ protected override void HandleGotoRequestAsync(IRequestResponder var builder = new ErrorBuilder(() => AD7Resources.Error_UnableToSetNextStatement); try { - var gotoTarget = m_gotoCodeContexts[responder.Arguments.TargetId]; - IDebugThread2 thread = null; - lock (m_threads) + if (m_gotoCodeContexts.TryGetValue(responder.Arguments.TargetId, out IDebugCodeContext2 gotoTarget)) { - if (!m_threads.TryGetValue(responder.Arguments.ThreadId, out thread)) - throw new AD7Exception("Unknown thread id: " + responder.Arguments.ThreadId.ToString(CultureInfo.InvariantCulture)); + IDebugThread2 thread = null; + lock (m_threads) + { + if (!m_threads.TryGetValue(responder.Arguments.ThreadId, out thread)) + throw new AD7Exception("Unknown thread id: " + responder.Arguments.ThreadId.ToString(CultureInfo.InvariantCulture)); + } + BeforeContinue(); + builder.CheckHR(thread.SetNextStatement(null, gotoTarget)); } - BeforeContinue(); - builder.CheckHR(thread.SetNextStatement(null, gotoTarget)); } catch (AD7Exception e) { @@ -1386,11 +1391,16 @@ protected override void HandleGotoTargetsRequestAsync(IRequestResponder Date: Fri, 6 Nov 2020 17:01:06 +0100 Subject: [PATCH 07/11] add comment about potential race condition --- src/MICore/CommandFactories/gdb.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/MICore/CommandFactories/gdb.cs b/src/MICore/CommandFactories/gdb.cs index f65d9846f..5df01be1c 100644 --- a/src/MICore/CommandFactories/gdb.cs +++ b/src/MICore/CommandFactories/gdb.cs @@ -186,6 +186,9 @@ public override async Task> StartAddressesForLine(string file, uint private async Task JumpInternal(string target) { // temporary breakpoint + jump + // NB: the gdb docs state: "Resume execution at line linespec. Execution stops again immediately if there is a breakpoint there." + // We rely on this. If another thread hits a breakpoint before that we have a UX problem + // and would need to handle this via scheduler-locking for all-stop mode and ??? for non-stop mode. await _debugger.CmdAsync("-break-insert -t " + target, ResultClass.done); await _debugger.CmdAsync("-exec-jump " + target, ResultClass.running); } From a2558e7fff09509c4ebb183c949d08df9a6243fa Mon Sep 17 00:00:00 2001 From: Andreas Hollandt Date: Sat, 9 Jan 2021 16:29:43 +0100 Subject: [PATCH 08/11] fix exception description so it shows something in vscode --- src/MIDebugEngine/AD7.Impl/AD7Events.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/MIDebugEngine/AD7.Impl/AD7Events.cs b/src/MIDebugEngine/AD7.Impl/AD7Events.cs index 2b031bfd4..022d24908 100644 --- a/src/MIDebugEngine/AD7.Impl/AD7Events.cs +++ b/src/MIDebugEngine/AD7.Impl/AD7Events.cs @@ -407,7 +407,7 @@ public AD7ExceptionEvent(string name, string description, uint code, Guid? excep { _name = name; _code = code; - _description = description ?? name; + _description = string.IsNullOrEmpty(description) ? name : description; _category = exceptionCategory ?? EngineConstants.EngineId; switch (state) From 15de6625669aad25b03830b5d17f07cfa93868f0 Mon Sep 17 00:00:00 2001 From: Andreas Hollandt Date: Sat, 9 Jan 2021 16:30:34 +0100 Subject: [PATCH 09/11] send "goto" stopped event after sending the command response --- src/OpenDebugAD7/AD7DebugSession.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/OpenDebugAD7/AD7DebugSession.cs b/src/OpenDebugAD7/AD7DebugSession.cs index 7ed6475a3..0a265ae84 100644 --- a/src/OpenDebugAD7/AD7DebugSession.cs +++ b/src/OpenDebugAD7/AD7DebugSession.cs @@ -1334,11 +1334,11 @@ protected override void HandleGotoRequestAsync(IRequestResponder } var builder = new ErrorBuilder(() => AD7Resources.Error_UnableToSetNextStatement); + IDebugThread2 thread = null; try { if (m_gotoCodeContexts.TryGetValue(responder.Arguments.TargetId, out IDebugCodeContext2 gotoTarget)) { - IDebugThread2 thread = null; lock (m_threads) { if (!m_threads.TryGetValue(responder.Arguments.ThreadId, out thread)) @@ -1352,9 +1352,11 @@ protected override void HandleGotoRequestAsync(IRequestResponder { m_isStopped = true; responder.SetError(new ProtocolException(e.Message)); + return; } responder.SetResponse(response); + FireStoppedEvent(thread, StoppedEvent.ReasonValue.Goto); } protected override void HandleGotoTargetsRequestAsync(IRequestResponder responder) From f37fe48f6417c1525b29e30b8c4f238616bee8e6 Mon Sep 17 00:00:00 2001 From: Andrew Wang Date: Thu, 28 Jan 2021 15:45:49 -0800 Subject: [PATCH 10/11] Remove Jump for only GoToTarget and add memory ref --- .../CommandFactories/MICommandFactory.cs | 6 --- src/MICore/CommandFactories/gdb.cs | 26 +--------- src/MICore/CommandFactories/lldb.cs | 13 ----- src/MIDebugEngine/AD7.Impl/AD7Engine.cs | 40 +-------------- .../AD7.Impl/AD7MemoryAddress.cs | 4 -- src/MIDebugEngine/AD7.Impl/AD7Thread.cs | 24 +++++---- .../Engine.Impl/DebuggedProcess.cs | 10 ---- src/OpenDebugAD7/AD7DebugSession.cs | 49 +++++++------------ src/OpenDebugAD7/AD7Resources.Designer.cs | 11 ----- src/OpenDebugAD7/AD7Resources.resx | 3 -- 10 files changed, 34 insertions(+), 152 deletions(-) diff --git a/src/MICore/CommandFactories/MICommandFactory.cs b/src/MICore/CommandFactories/MICommandFactory.cs index 4ec9fd469..ff0d3d078 100644 --- a/src/MICore/CommandFactories/MICommandFactory.cs +++ b/src/MICore/CommandFactories/MICommandFactory.cs @@ -242,12 +242,6 @@ public async Task ExecNextInstruction(int threadId, ResultClass resultClass = Re await ThreadFrameCmdAsync(command, resultClass, threadId, 0); } - /// - /// Jumps to a specified target location - /// - abstract public Task ExecJump(string filename, int line); - abstract public Task ExecJump(ulong address); - /// /// Tells GDB to spawn a target process previous setup with -file-exec-and-symbols or similar /// diff --git a/src/MICore/CommandFactories/gdb.cs b/src/MICore/CommandFactories/gdb.cs index 5df01be1c..4bcb24b30 100644 --- a/src/MICore/CommandFactories/gdb.cs +++ b/src/MICore/CommandFactories/gdb.cs @@ -157,7 +157,7 @@ public override async Task ThreadInfo(uint? threadId = null) public override async Task> StartAddressesForLine(string file, uint line) { - string cmd = "info line -s " + file + " -li " + line; + string cmd = "info line " + file + ":" + line; var result = await _debugger.ConsoleCmdAsync(cmd, allowWhileRunning: false); List addresses = new List(); using (StringReader stringReader = new StringReader(result)) @@ -173,7 +173,7 @@ public override async Task> StartAddressesForLine(string file, uint { ulong address; string addrStr = resultLine.Substring(pos + 18); - if (SpanNextAddr(addrStr, out address) != null) + if (MICommandFactory.SpanNextAddr(addrStr, out address) != null) { addresses.Add(address); } @@ -183,28 +183,6 @@ public override async Task> StartAddressesForLine(string file, uint return addresses; } - private async Task JumpInternal(string target) - { - // temporary breakpoint + jump - // NB: the gdb docs state: "Resume execution at line linespec. Execution stops again immediately if there is a breakpoint there." - // We rely on this. If another thread hits a breakpoint before that we have a UX problem - // and would need to handle this via scheduler-locking for all-stop mode and ??? for non-stop mode. - await _debugger.CmdAsync("-break-insert -t " + target, ResultClass.done); - await _debugger.CmdAsync("-exec-jump " + target, ResultClass.running); - } - - public override Task ExecJump(string filename, int line) - { - string target = "--source " + filename + " --line " + line.ToString(CultureInfo.InvariantCulture); - return JumpInternal(target); - } - - public override Task ExecJump(ulong address) - { - string target = "*" + string.Format(CultureInfo.InvariantCulture, "0x{0:X}", address); - return JumpInternal(target); - } - public override Task EnableTargetAsyncOption() { // Linux attach TODO: GDB will fail this command when attaching. This is worked around diff --git a/src/MICore/CommandFactories/lldb.cs b/src/MICore/CommandFactories/lldb.cs index e2181942c..3cb2d9467 100644 --- a/src/MICore/CommandFactories/lldb.cs +++ b/src/MICore/CommandFactories/lldb.cs @@ -177,19 +177,6 @@ public override Task Catch(string name, bool onlyOnce = false, ResultClass resul throw new NotImplementedException("lldb catch command"); } - // TODO: update these if they become available in lldb-mi - public override async Task ExecJump(string filename, int line) - { - string command = "jump " + filename + ":" + line; - await _debugger.CmdAsync(command, ResultClass.running); - } - - public override async Task ExecJump(ulong address) - { - string command = "jump *" + string.Format(CultureInfo.InvariantCulture, "0x{0:X}", address); - await _debugger.CmdAsync(command, ResultClass.running); - } - /// /// Assigns the value of an expression to a variable. /// Since LLDB only accepts assigning values to variables, the expression may need to be evaluated. diff --git a/src/MIDebugEngine/AD7.Impl/AD7Engine.cs b/src/MIDebugEngine/AD7.Impl/AD7Engine.cs index fdf0359ac..a99f43dd4 100755 --- a/src/MIDebugEngine/AD7.Impl/AD7Engine.cs +++ b/src/MIDebugEngine/AD7.Impl/AD7Engine.cs @@ -182,44 +182,6 @@ public object GetMetric(string metric) return _configStore.GetEngineMetric(metric); } - public int Jump(string filename, int line) - { - try - { - _debuggedProcess.WorkerThread.RunOperation(() => _debuggedProcess.Jump(filename, line)); - } - catch (InvalidCoreDumpOperationException) - { - return AD7_HRESULT.E_CRASHDUMP_UNSUPPORTED; - } - catch (Exception e) - { - _engineCallback.OnError(EngineUtils.GetExceptionDescription(e)); - return Constants.E_ABORT; - } - - return Constants.S_OK; - } - - public int Jump(ulong address) - { - try - { - _debuggedProcess.WorkerThread.RunOperation(() => _debuggedProcess.Jump(address)); - } - catch (InvalidCoreDumpOperationException) - { - return AD7_HRESULT.E_CRASHDUMP_UNSUPPORTED; - } - catch (Exception e) - { - _engineCallback.OnError(EngineUtils.GetExceptionDescription(e)); - return Constants.E_ABORT; - } - - return Constants.S_OK; - } - #region IDebugEngine2 Members // Attach the debug engine to a program. @@ -877,7 +839,7 @@ public int EnumCodeContexts(IDebugDocumentPosition2 docPosition, out IEnumDebugC { var codeCxt = new AD7MemoryAddress(this, a, null); TEXT_POSITION pos; - pos.dwLine = line; + pos.dwLine = line - 1; pos.dwColumn = 0; MITextPosition textPosition = new MITextPosition(documentName, pos, pos); codeCxt.SetDocumentContext(new AD7DocumentContext(textPosition, codeCxt)); diff --git a/src/MIDebugEngine/AD7.Impl/AD7MemoryAddress.cs b/src/MIDebugEngine/AD7.Impl/AD7MemoryAddress.cs index 09bc6a277..318e50e2e 100644 --- a/src/MIDebugEngine/AD7.Impl/AD7MemoryAddress.cs +++ b/src/MIDebugEngine/AD7.Impl/AD7MemoryAddress.cs @@ -198,10 +198,6 @@ public int GetInfo(enum_CONTEXT_INFO_FIELDS dwFields, CONTEXT_INFO[] pinfo) pinfo[0].dwFields |= enum_CONTEXT_INFO_FIELDS.CIF_FUNCTION; } } - if ((dwFields & enum_CONTEXT_INFO_FIELDS.CIF_FUNCTIONOFFSET) != 0) - { - // TODO: - } return Constants.S_OK; } diff --git a/src/MIDebugEngine/AD7.Impl/AD7Thread.cs b/src/MIDebugEngine/AD7.Impl/AD7Thread.cs index f5457c011..b2b0a8d35 100644 --- a/src/MIDebugEngine/AD7.Impl/AD7Thread.cs +++ b/src/MIDebugEngine/AD7.Impl/AD7Thread.cs @@ -282,23 +282,27 @@ int IDebugThread2.Resume(out uint suspendCount) } // Sets the next statement to the given stack frame and code context. - // https://docs.microsoft.com/en-us/visualstudio/extensibility/debugger/reference/idebugthread2-setnextstatement int IDebugThread2.SetNextStatement(IDebugStackFrame2 stackFrame, IDebugCodeContext2 codeContext) { - // VS does provide a frame so at least do some sanity checks - AD7StackFrame frame = stackFrame as AD7StackFrame; - if (frame != null && (frame.ThreadContext.Level != 0 || frame.Thread != this)) - return Constants.S_FALSE; - - try + ulong addr = ((AD7MemoryAddress)codeContext).Address; + AD7StackFrame frame = ((AD7StackFrame)stackFrame); + if (frame.ThreadContext.Level != 0 || frame.Thread != this || !frame.ThreadContext.pc.HasValue) { - ulong addr = ((AD7MemoryAddress)codeContext).Address; - return _engine.Jump(addr); + return Constants.S_FALSE; } - catch (Exception) + string toFunc = EngineUtils.GetAddressDescription(_engine.DebuggedProcess, addr); + string fromFunc = EngineUtils.GetAddressDescription(_engine.DebuggedProcess, frame.ThreadContext.pc.Value); + if (toFunc != fromFunc) { return Constants.S_FALSE; } + string result = frame.EvaluateExpression("$pc=" + EngineUtils.AsAddr(addr, _engine.DebuggedProcess.Is64BitArch)); + if (result != null) + { + _engine.DebuggedProcess.ThreadCache.MarkDirty(); + return Constants.S_OK; + } + return Constants.S_FALSE; } // suspend a thread. diff --git a/src/MIDebugEngine/Engine.Impl/DebuggedProcess.cs b/src/MIDebugEngine/Engine.Impl/DebuggedProcess.cs index 219c85e7d..eddad0aec 100755 --- a/src/MIDebugEngine/Engine.Impl/DebuggedProcess.cs +++ b/src/MIDebugEngine/Engine.Impl/DebuggedProcess.cs @@ -1601,16 +1601,6 @@ public Task Continue(DebuggedThread thread) return Execute(thread); } - public async Task Jump(string filename, int line) - { - await MICommandFactory.ExecJump(filename, line); - } - - public async Task Jump(ulong address) - { - await MICommandFactory.ExecJump(address); - } - public async Task Step(int threadId, enum_STEPKIND kind, enum_STEPUNIT unit) { this.VerifyNotDebuggingCoreDump(); diff --git a/src/OpenDebugAD7/AD7DebugSession.cs b/src/OpenDebugAD7/AD7DebugSession.cs index 0a265ae84..92d842121 100644 --- a/src/OpenDebugAD7/AD7DebugSession.cs +++ b/src/OpenDebugAD7/AD7DebugSession.cs @@ -1326,37 +1326,7 @@ protected override void HandlePauseRequestAsync(IRequestResponder responder) { - var response = new GotoResponse(); - if (!m_isStopped) - { - responder.SetResponse(response); - return; - } - - var builder = new ErrorBuilder(() => AD7Resources.Error_UnableToSetNextStatement); - IDebugThread2 thread = null; - try - { - if (m_gotoCodeContexts.TryGetValue(responder.Arguments.TargetId, out IDebugCodeContext2 gotoTarget)) - { - lock (m_threads) - { - if (!m_threads.TryGetValue(responder.Arguments.ThreadId, out thread)) - throw new AD7Exception("Unknown thread id: " + responder.Arguments.ThreadId.ToString(CultureInfo.InvariantCulture)); - } - BeforeContinue(); - builder.CheckHR(thread.SetNextStatement(null, gotoTarget)); - } - } - catch (AD7Exception e) - { - m_isStopped = true; - responder.SetError(new ProtocolException(e.Message)); - return; - } - - responder.SetResponse(response); - FireStoppedEvent(thread, StoppedEvent.ReasonValue.Goto); + responder.SetError(new ProtocolException("Not implemented exception.")); } protected override void HandleGotoTargetsRequestAsync(IRequestResponder responder) @@ -1387,8 +1357,10 @@ protected override void HandleGotoTargetsRequestAsync(IRequestResponder - /// Looks up a localized string similar to Error setting next statement. {0}. - /// - internal static string Error_UnableToSetNextStatement - { - get - { - return ResourceManager.GetString("Error_UnableToSetNextStatement", resourceCulture); - } - } - /// /// Looks up a localized string similar to '{0}' cannot be assigned to. /// diff --git a/src/OpenDebugAD7/AD7Resources.resx b/src/OpenDebugAD7/AD7Resources.resx index 42237a129..33a8db067 100644 --- a/src/OpenDebugAD7/AD7Resources.resx +++ b/src/OpenDebugAD7/AD7Resources.resx @@ -195,9 +195,6 @@ Error setting breakpoint. {0} - - Error setting next statement. {0} - Unable to parse 'logMessage'. From 8fe364ac26c76a26ab77caff01965d9328d21bd7 Mon Sep 17 00:00:00 2001 From: Andrew Wang Date: Fri, 29 Jan 2021 11:51:37 -0800 Subject: [PATCH 11/11] Addressing PR issues --- src/OpenDebugAD7/AD7DebugSession.cs | 10 ++++---- src/OpenDebugAD7/AD7Resources.Designer.cs | 28 +++++++++++++++-------- src/OpenDebugAD7/AD7Resources.resx | 3 +++ 3 files changed, 27 insertions(+), 14 deletions(-) diff --git a/src/OpenDebugAD7/AD7DebugSession.cs b/src/OpenDebugAD7/AD7DebugSession.cs index 92d842121..b5eb9d671 100644 --- a/src/OpenDebugAD7/AD7DebugSession.cs +++ b/src/OpenDebugAD7/AD7DebugSession.cs @@ -355,7 +355,7 @@ public void BeforeContinue() m_isStopped = false; m_variableManager.Reset(); m_frameHandles.Reset(); - m_gotoCodeContexts.Clear(); + m_gotoCodeContexts.Clear(); } public void Stopped(IDebugThread2 thread) @@ -1326,7 +1326,7 @@ protected override void HandlePauseRequestAsync(IRequestResponder responder) { - responder.SetError(new ProtocolException("Not implemented exception.")); + responder.SetError(new ProtocolException(AD7Resources.Error_NotImplementedSetNextStatement)); } protected override void HandleGotoTargetsRequestAsync(IRequestResponder responder) @@ -1334,7 +1334,8 @@ protected override void HandleGotoTargetsRequestAsync(IRequestResponder + /// Looks up a localized string similar to Set next statement is not supported by the current debugger.. + /// + internal static string Error_NotImplementedSetNextStatement { + get { + return ResourceManager.GetString("Error_NotImplementedSetNextStatement", resourceCulture); + } + } + /// /// Looks up a localized string similar to {0}: property '{1}' is invalid.. /// @@ -433,16 +442,6 @@ internal static string Locals_Scope_Name { } } - /// - /// Looks up a localized string similar to Registers. - /// - internal static string Registers_Scope_Name - { - get { - return ResourceManager.GetString("Registers_Scope_Name", resourceCulture); - } - } - /// /// Looks up a localized string similar to Debugger failed to signal process termination.. /// @@ -534,6 +533,15 @@ internal static string ProcessExitMessage { } } + /// + /// Looks up a localized string similar to Registers. + /// + internal static string Registers_Scope_Name { + get { + return ResourceManager.GetString("Registers_Scope_Name", resourceCulture); + } + } + /// /// Looks up a localized string similar to Could not detect launch url.. /// diff --git a/src/OpenDebugAD7/AD7Resources.resx b/src/OpenDebugAD7/AD7Resources.resx index 33a8db067..bc916064d 100644 --- a/src/OpenDebugAD7/AD7Resources.resx +++ b/src/OpenDebugAD7/AD7Resources.resx @@ -298,4 +298,7 @@ Unable to retrieve stack trace. {0} + + Set next statement is not supported by the current debugger. + \ No newline at end of file