Skip to content

Commit fbbc993

Browse files
WardenGnawTrass3r
andauthored
Support GoToTargets Request (#1102)
Support DAP GoToTargets Co-authored-by: Andreas Hollandt <[email protected]>
1 parent a8678a0 commit fbbc993

File tree

9 files changed

+133
-37
lines changed

9 files changed

+133
-37
lines changed

src/MIDebugEngine/AD7.Impl/AD7Engine.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -839,7 +839,7 @@ public int EnumCodeContexts(IDebugDocumentPosition2 docPosition, out IEnumDebugC
839839
{
840840
var codeCxt = new AD7MemoryAddress(this, a, null);
841841
TEXT_POSITION pos;
842-
pos.dwLine = line;
842+
pos.dwLine = line - 1;
843843
pos.dwColumn = 0;
844844
MITextPosition textPosition = new MITextPosition(documentName, pos, pos);
845845
codeCxt.SetDocumentContext(new AD7DocumentContext(textPosition, codeCxt));

src/MIDebugEngine/AD7.Impl/AD7Events.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,7 @@ public AD7ExceptionEvent(string name, string description, uint code, Guid? excep
407407
{
408408
_name = name;
409409
_code = code;
410-
_description = description ?? name;
410+
_description = string.IsNullOrEmpty(description) ? name : description;
411411
_category = exceptionCategory ?? EngineConstants.EngineId;
412412

413413
switch (state)

src/MIDebugEngine/AD7.Impl/AD7MemoryAddress.cs

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,16 @@
22
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
33

44
using System;
5-
using System.Collections.Generic;
6-
using System.Text;
75
using Microsoft.VisualStudio.Debugger.Interop;
86
using MICore;
9-
using Microsoft.MIDebugEngine.Natvis;
107

118
namespace Microsoft.MIDebugEngine
129
{
1310
// And implementation of IDebugCodeContext2 and IDebugMemoryContext2.
1411
// IDebugMemoryContext2 represents a position in the address space of the machine running the program being debugged.
1512
// IDebugCodeContext2 represents the starting position of a code instruction.
1613
// For most run-time architectures today, a code context can be thought of as an address in a program's execution stream.
17-
internal class AD7MemoryAddress : IDebugCodeContext2
14+
internal sealed class AD7MemoryAddress : IDebugCodeContext2
1815
{
1916
private readonly AD7Engine _engine;
2017
private readonly ulong _address;
@@ -42,6 +39,9 @@ public void SetDocumentContext(IDebugDocumentContext2 docContext)
4239
// Adds a specified value to the current context's address to create a new context.
4340
public int Add(ulong dwCount, out IDebugMemoryContext2 newAddress)
4441
{
42+
// NB: this is not correct for IDebugCodeContext2 according to the docs
43+
// https://docs.microsoft.com/en-us/visualstudio/extensibility/debugger/reference/idebugcodecontext2#remarks
44+
// But it's not used in practice (instead: IDebugDisassemblyStream2.Seek)
4545
newAddress = new AD7MemoryAddress(_engine, (uint)dwCount + _address, null);
4646
return Constants.S_OK;
4747
}
@@ -160,19 +160,22 @@ public int GetInfo(enum_CONTEXT_INFO_FIELDS dwFields, CONTEXT_INFO[] pinfo)
160160
{
161161
pinfo[0].dwFields = 0;
162162

163-
if ((dwFields & enum_CONTEXT_INFO_FIELDS.CIF_ADDRESS) != 0)
163+
if ((dwFields & (enum_CONTEXT_INFO_FIELDS.CIF_ADDRESS | enum_CONTEXT_INFO_FIELDS.CIF_ADDRESSABSOLUTE)) != 0)
164164
{
165-
pinfo[0].bstrAddress = EngineUtils.AsAddr(_address, _engine.DebuggedProcess.Is64BitArch);
166-
pinfo[0].dwFields |= enum_CONTEXT_INFO_FIELDS.CIF_ADDRESS;
165+
string addr = EngineUtils.AsAddr(_address, _engine.DebuggedProcess.Is64BitArch);
166+
if ((dwFields & enum_CONTEXT_INFO_FIELDS.CIF_ADDRESS) != 0)
167+
{
168+
pinfo[0].bstrAddress = addr;
169+
pinfo[0].dwFields |= enum_CONTEXT_INFO_FIELDS.CIF_ADDRESS;
170+
}
171+
if ((dwFields & enum_CONTEXT_INFO_FIELDS.CIF_ADDRESSABSOLUTE) != 0)
172+
{
173+
pinfo[0].bstrAddressAbsolute = addr;
174+
pinfo[0].dwFields |= enum_CONTEXT_INFO_FIELDS.CIF_ADDRESSABSOLUTE;
175+
}
167176
}
168-
169177
// Fields not supported by the sample
170178
if ((dwFields & enum_CONTEXT_INFO_FIELDS.CIF_ADDRESSOFFSET) != 0) { }
171-
if ((dwFields & enum_CONTEXT_INFO_FIELDS.CIF_ADDRESSABSOLUTE) != 0)
172-
{
173-
pinfo[0].bstrAddressAbsolute = EngineUtils.AsAddr(_address, _engine.DebuggedProcess.Is64BitArch);
174-
pinfo[0].dwFields |= enum_CONTEXT_INFO_FIELDS.CIF_ADDRESSABSOLUTE;
175-
}
176179
if ((dwFields & enum_CONTEXT_INFO_FIELDS.CIF_MODULEURL) != 0)
177180
{
178181
DebuggedModule module = _engine.DebuggedProcess.ResolveAddress(_address);
@@ -195,7 +198,6 @@ public int GetInfo(enum_CONTEXT_INFO_FIELDS dwFields, CONTEXT_INFO[] pinfo)
195198
pinfo[0].dwFields |= enum_CONTEXT_INFO_FIELDS.CIF_FUNCTION;
196199
}
197200
}
198-
if ((dwFields & enum_CONTEXT_INFO_FIELDS.CIF_FUNCTIONOFFSET) != 0) { }
199201

200202
return Constants.S_OK;
201203
}
@@ -210,10 +212,10 @@ public int GetInfo(enum_CONTEXT_INFO_FIELDS dwFields, CONTEXT_INFO[] pinfo)
210212
}
211213

212214
// Gets the user-displayable name for this context
213-
// This is not supported by the sample engine.
214215
public int GetName(out string pbstrName)
215216
{
216-
throw new NotImplementedException();
217+
pbstrName = _functionName ?? Engine.GetAddressDescription(_address);
218+
return Constants.S_OK;
217219
}
218220

219221
// Subtracts a specified value from the current context's address to create a new context.

src/MIDebugEngine/AD7.Impl/AD7StackFrame.cs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ namespace Microsoft.MIDebugEngine
1414
{
1515
// Represents a logical stack frame on the thread stack.
1616
// Also implements the IDebugExpressionContext interface, which allows expression evaluation and watch windows.
17-
internal class AD7StackFrame : IDebugStackFrame2, IDebugExpressionContext2
17+
internal sealed class AD7StackFrame : IDebugStackFrame2, IDebugExpressionContext2
1818
{
1919
public AD7Engine Engine { get; private set; }
2020
public AD7Thread Thread { get; private set; }
@@ -53,11 +53,7 @@ public AD7StackFrame(AD7Engine engine, AD7Thread thread, ThreadContext threadCon
5353
if (_textPosition != null)
5454
{
5555
_documentCxt = new AD7DocumentContext(_textPosition, _codeCxt);
56-
57-
if (_codeCxt != null)
58-
{
59-
_codeCxt.SetDocumentContext(_documentCxt);
60-
}
56+
_codeCxt?.SetDocumentContext(_documentCxt);
6157
}
6258
}
6359

src/OpenDebugAD7/AD7DebugSession.cs

Lines changed: 88 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
33

44
using System;
5+
using System.Collections.Concurrent;
56
using System.Collections.Generic;
67
using System.Diagnostics;
78
using System.Globalization;
@@ -27,7 +28,7 @@
2728

2829
namespace OpenDebugAD7
2930
{
30-
internal class AD7DebugSession : DebugAdapterBase, IDebugPortNotify2, IDebugEventCallback2
31+
internal sealed class AD7DebugSession : DebugAdapterBase, IDebugPortNotify2, IDebugEventCallback2
3132
{
3233
// This is a general purpose lock. Don't hold it across long operations.
3334
private readonly object m_lock = new object();
@@ -44,6 +45,10 @@ internal class AD7DebugSession : DebugAdapterBase, IDebugPortNotify2, IDebugEven
4445

4546
private readonly DebugEventLogger m_logger;
4647
private readonly Dictionary<string, Dictionary<int, IDebugPendingBreakpoint2>> m_breakpoints;
48+
49+
private readonly ConcurrentDictionary<int, IDebugCodeContext2> m_gotoCodeContexts = new ConcurrentDictionary<int, IDebugCodeContext2>();
50+
private int m_nextContextId = 1;
51+
4752
private Dictionary<string, IDebugPendingBreakpoint2> m_functionBreakpoints;
4853
private readonly HandleCollection<IDebugStackFrame2> m_frameHandles;
4954

@@ -350,6 +355,7 @@ public void BeforeContinue()
350355
m_isStopped = false;
351356
m_variableManager.Reset();
352357
m_frameHandles.Reset();
358+
m_gotoCodeContexts.Clear();
353359
}
354360

355361
public void Stopped(IDebugThread2 thread)
@@ -793,6 +799,7 @@ protected override void HandleInitializeRequestAsync(IRequestResponder<Initializ
793799
SupportsReadMemoryRequest = m_engine is IDebugMemoryBytesDAP, // TODO: Read from configuration or query engine for capabilities.
794800
SupportsModulesRequest = true,
795801
AdditionalModuleColumns = additionalModuleColumns,
802+
SupportsGotoTargetsRequest = true,
796803
SupportsDisassembleRequest = true,
797804
SupportsValueFormattingOptions = true,
798805
};
@@ -1317,6 +1324,86 @@ protected override void HandlePauseRequestAsync(IRequestResponder<PauseArguments
13171324
responder.SetResponse(new PauseResponse());
13181325
}
13191326

1327+
protected override void HandleGotoRequestAsync(IRequestResponder<GotoArguments> responder)
1328+
{
1329+
responder.SetError(new ProtocolException(AD7Resources.Error_NotImplementedSetNextStatement));
1330+
}
1331+
1332+
protected override void HandleGotoTargetsRequestAsync(IRequestResponder<GotoTargetsArguments, GotoTargetsResponse> responder)
1333+
{
1334+
var response = new GotoTargetsResponse();
1335+
1336+
var source = responder.Arguments.Source;
1337+
1338+
// Virtual documents don't have paths
1339+
if (source.Path == null)
1340+
{
1341+
responder.SetResponse(response);
1342+
return;
1343+
}
1344+
1345+
try
1346+
{
1347+
string convertedPath = m_pathConverter.ConvertClientPathToDebugger(source.Path);
1348+
int line = m_pathConverter.ConvertClientLineToDebugger(responder.Arguments.Line);
1349+
var docPos = new AD7DocumentPosition(m_sessionConfig, convertedPath, line);
1350+
1351+
var targets = new List<GotoTarget>();
1352+
1353+
IEnumDebugCodeContexts2 codeContextsEnum;
1354+
if (m_program.EnumCodeContexts(docPos, out codeContextsEnum) == HRConstants.S_OK)
1355+
{
1356+
var codeContexts = new IDebugCodeContext2[1];
1357+
uint nProps = 0;
1358+
while (codeContextsEnum.Next(1, codeContexts, ref nProps) == HRConstants.S_OK)
1359+
{
1360+
var codeContext = codeContexts[0];
1361+
1362+
string contextName;
1363+
codeContext.GetName(out contextName);
1364+
1365+
line = responder.Arguments.Line;
1366+
IDebugDocumentContext2 documentContext;
1367+
if (codeContext.GetDocumentContext(out documentContext) == HRConstants.S_OK)
1368+
{
1369+
var startPos = new TEXT_POSITION[1];
1370+
var endPos = new TEXT_POSITION[1];
1371+
if (documentContext.GetStatementRange(startPos, endPos) == HRConstants.S_OK)
1372+
line = m_pathConverter.ConvertDebuggerLineToClient((int)startPos[0].dwLine);
1373+
}
1374+
1375+
string instructionPointerReference = null;
1376+
CONTEXT_INFO[] contextInfo = new CONTEXT_INFO[1];
1377+
if (codeContext.GetInfo(enum_CONTEXT_INFO_FIELDS.CIF_ADDRESS, contextInfo) == HRConstants.S_OK &&
1378+
contextInfo[0].dwFields.HasFlag(enum_CONTEXT_INFO_FIELDS.CIF_ADDRESS))
1379+
{
1380+
instructionPointerReference = contextInfo[0].bstrAddress;
1381+
}
1382+
1383+
int codeContextId = m_nextContextId++;
1384+
m_gotoCodeContexts.TryAdd(codeContextId, codeContext);
1385+
1386+
targets.Add(new GotoTarget()
1387+
{
1388+
Id = codeContextId,
1389+
Label = contextName,
1390+
Line = line,
1391+
InstructionPointerReference = instructionPointerReference
1392+
});
1393+
}
1394+
}
1395+
1396+
response.Targets = targets;
1397+
}
1398+
catch (AD7Exception e)
1399+
{
1400+
responder.SetError(new ProtocolException(e.Message));
1401+
return;
1402+
}
1403+
1404+
responder.SetResponse(response);
1405+
}
1406+
13201407
protected override void HandleStackTraceRequestAsync(IRequestResponder<StackTraceArguments, StackTraceResponse> responder)
13211408
{
13221409
int threadReference = responder.Arguments.ThreadId;

src/OpenDebugAD7/AD7Impl/AD7BreakPointRequest.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
namespace OpenDebugAD7.AD7Impl
1010
{
11-
internal class AD7BreakPointRequest : IDebugBreakpointRequest2, IDebugBreakpointChecksumRequest2
11+
internal sealed class AD7BreakPointRequest : IDebugBreakpointRequest2, IDebugBreakpointChecksumRequest2
1212
{
1313
private static uint s_nextBreakpointId = 0;
1414

src/OpenDebugAD7/AD7Impl/AD7DocumentPosition.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
namespace OpenDebugAD7.AD7Impl
1010
{
11-
internal class AD7DocumentPosition : IDebugDocumentPosition2, IDebugDocumentPosition110
11+
internal sealed class AD7DocumentPosition : IDebugDocumentPosition2, IDebugDocumentPosition110
1212
{
1313
public string Path
1414
{

src/OpenDebugAD7/AD7Resources.Designer.cs

Lines changed: 18 additions & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/OpenDebugAD7/AD7Resources.resx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,4 +298,7 @@
298298
<data name="Error_Scenario_StackTrace" xml:space="preserve">
299299
<value>Unable to retrieve stack trace. {0}</value>
300300
</data>
301+
<data name="Error_NotImplementedSetNextStatement" xml:space="preserve">
302+
<value>Set next statement is not supported by the current debugger.</value>
303+
</data>
301304
</root>

0 commit comments

Comments
 (0)