Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for LogPoints in OpenDebugAD7 #1013

Merged
merged 8 commits into from
Jun 26, 2020
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 101 additions & 16 deletions src/OpenDebugAD7/AD7DebugSession.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ internal class AD7DebugSession : DebugAdapterBase, IDebugPortNotify2, IDebugEven
private bool m_isAttach;
private bool m_isCoreDump;
private bool m_isStopped = false;
private bool m_isStepping = false;

private readonly TaskCompletionSource<object> m_configurationDoneTCS = new TaskCompletionSource<object>();

Expand Down Expand Up @@ -237,6 +238,37 @@ private ProtocolException VerifyProcessId(string processId, string telemetryEven
return null;
}

private IList<Tracepoint> GetTracepoints(IDebugBreakpointEvent2 debugEvent)
{
IList<Tracepoint> tracepoints = new List<Tracepoint>();

if (debugEvent != null)
{
debugEvent.EnumBreakpoints(out IEnumDebugBoundBreakpoints2 pBoundBreakpoints);
IDebugBoundBreakpoint2[] boundBp = new IDebugBoundBreakpoint2[1];

uint numReturned = 0;
while (pBoundBreakpoints.Next(1, boundBp, ref numReturned) == HRConstants.S_OK && numReturned == 1)
{
if (boundBp[0].GetPendingBreakpoint(out IDebugPendingBreakpoint2 ppPendingBreakpoint) == HRConstants.S_OK)
WardenGnaw marked this conversation as resolved.
Show resolved Hide resolved
{
if (ppPendingBreakpoint.GetBreakpointRequest(out IDebugBreakpointRequest2 ppBPRequest) == HRConstants.S_OK)
{
if (ppBPRequest is AD7BreakPointRequest ad7BreakpointRequest)
{
if (ad7BreakpointRequest.HasTracepoint)
{
tracepoints.Add(ad7BreakpointRequest.Tracepoint);
}
}
}
}
}
}

return tracepoints;
}

#endregion

#region AD7EventHandlers helper methods
Expand All @@ -245,6 +277,7 @@ public void BeforeContinue()
{
if (!m_isCoreDump)
{
m_isStepping = false;
m_isStopped = false;
m_variableManager.Reset();
m_frameHandles.Reset();
Expand Down Expand Up @@ -499,7 +532,6 @@ private void StepInternal(int threadId, enum_STEPKIND stepKind, enum_STEPUNIT st
// If we are already running ignore additional step requests
if (m_isStopped)
{

IDebugThread2 thread = null;
lock (m_threads)
{
Expand All @@ -513,6 +545,7 @@ private void StepInternal(int threadId, enum_STEPKIND stepKind, enum_STEPUNIT st
ErrorBuilder builder = new ErrorBuilder(() => errorMessage);
try
{
m_isStepping = true;
WardenGnaw marked this conversation as resolved.
Show resolved Hide resolved
builder.CheckHR(m_program.Step(thread, stepKind, stepUnit));
}
catch (AD7Exception)
Expand Down Expand Up @@ -590,7 +623,8 @@ protected override void HandleInitializeRequestAsync(IRequestResponder<Initializ
SupportsFunctionBreakpoints = m_engineConfiguration.FunctionBP,
SupportsConditionalBreakpoints = m_engineConfiguration.ConditionalBP,
ExceptionBreakpointFilters = m_engineConfiguration.ExceptionSettings.ExceptionBreakpointFilters.Select(item => new ExceptionBreakpointsFilter() { Default = item.@default, Filter = item.filter, Label = item.label }).ToList(),
SupportsClipboardContext = m_engineConfiguration.ClipboardContext
SupportsClipboardContext = m_engineConfiguration.ClipboardContext,
SupportsLogPoints = true
};

responder.SetResponse(initializeResponse);
Expand Down Expand Up @@ -1607,6 +1641,14 @@ protected override void HandleSetBreakpointsRequestAsync(IRequestResponder<SetBr
toRemove.Delete();
dict.Remove(bp.Line);
}
// Check to see if tracepoint changed
else if (!StringComparer.Ordinal.Equals(ad7BPRequest.LogMessage, bp.LogMessage))
{
ad7BPRequest.ClearTracepoint();
var toRemove = dict[bp.Line];
toRemove.Delete();
dict.Remove(bp.Line);
}
else
{
if (ad7BPRequest.BindResult != null)
Expand Down Expand Up @@ -1641,12 +1683,32 @@ protected override void HandleSetBreakpointsRequestAsync(IRequestResponder<SetBr
eb.CheckHR(pendingBp.Bind());

dict[bp.Line] = pendingBp;
resBreakpoints.Add(new Breakpoint()

bool verified = true;
if (!string.IsNullOrEmpty(bp.LogMessage))
{
Id = (int)pBPRequest.Id,
Verified = true,
Line = bp.Line
});
verified = pBPRequest.SetLogMessage(bp.LogMessage);
}

if (verified)
{
resBreakpoints.Add(new Breakpoint()
{
Id = (int)pBPRequest.Id,
Verified = verified,
Line = bp.Line
});
}
else
{
resBreakpoints.Add(new Breakpoint()
{
Id = (int)pBPRequest.Id,
Verified = verified,
Line = bp.Line,
Message = "Unable to parse logMessage."
WardenGnaw marked this conversation as resolved.
Show resolved Hide resolved
});
}
}
catch (Exception e)
{
Expand Down Expand Up @@ -1893,12 +1955,10 @@ protected override void HandleEvaluateRequestAsync(IRequestResponder<EvaluateArg
hr = frame.GetExpressionContext(out expressionContext);
eb.CheckHR(hr);

const uint InputRadix = 10;
DAPEvalFlags dapEvalFlags = DAPEvalFlags.NONE;
IDebugExpression2 expressionObject;
string error;
uint errorIndex;
hr = expressionContext.ParseText(expression, enum_PARSEFLAGS.PARSE_EXPRESSION, InputRadix, out expressionObject, out error, out errorIndex);
hr = expressionContext.ParseText(expression, enum_PARSEFLAGS.PARSE_EXPRESSION, Constants.EvaluationRadix, out expressionObject, out error, out errorIndex);
WardenGnaw marked this conversation as resolved.
Show resolved Hide resolved
if (!string.IsNullOrEmpty(error))
{
// TODO: Is this how errors should be returned?
Expand All @@ -1919,14 +1979,14 @@ protected override void HandleEvaluateRequestAsync(IRequestResponder<EvaluateArg
flags |= enum_EVALFLAGS.EVAL_NOSIDEEFFECTS;
}

if (context == EvaluateArguments.ContextValue.Clipboard)
{
dapEvalFlags |= DAPEvalFlags.CLIPBOARD_CONTEXT;
}

IDebugProperty2 property;
if (expressionObject is IDebugExpressionDAP expressionDapObject)
{
DAPEvalFlags dapEvalFlags = DAPEvalFlags.NONE;
if (context == EvaluateArguments.ContextValue.Clipboard)
{
dapEvalFlags |= DAPEvalFlags.CLIPBOARD_CONTEXT;
}
hr = expressionDapObject.EvaluateSync(flags, dapEvalFlags, Constants.EvaluationTimeout, null, out property);
}
else
Expand Down Expand Up @@ -2094,7 +2154,32 @@ public void HandleIDebugEntryPointEvent2(IDebugEngine2 pEngine, IDebugProcess2 p

public void HandleIDebugBreakpointEvent2(IDebugEngine2 pEngine, IDebugProcess2 pProcess, IDebugProgram2 pProgram, IDebugThread2 pThread, IDebugEvent2 pEvent)
{
FireStoppedEvent(pThread, StoppedEvent.ReasonValue.Breakpoint);
IList<Tracepoint> tracepoints = GetTracepoints(pEvent as IDebugBreakpointEvent2);
if (tracepoints.Any())
{
ThreadPool.QueueUserWorkItem((o) =>
{
foreach (var tp in tracepoints)
{
string logMessage = tp.GetLogMessage(pThread, Constants.EvaluationRadix, m_processName);

m_logger.WriteLine(LoggingCategory.DebuggerStatus, logMessage);
}
});
}

if (!m_isStepping && tracepoints.Any())
WardenGnaw marked this conversation as resolved.
Show resolved Hide resolved
{
ThreadPool.QueueUserWorkItem((o) =>
{
BeforeContinue();
m_program.Continue(pThread);
});
}
else
{
FireStoppedEvent(pThread, StoppedEvent.ReasonValue.Breakpoint);
}
WardenGnaw marked this conversation as resolved.
Show resolved Hide resolved
}

public void HandleIDebugBreakEvent2(IDebugEngine2 pEngine, IDebugProcess2 pProcess, IDebugProgram2 pProgram, IDebugThread2 pThread, IDebugEvent2 pEvent)
Expand Down
51 changes: 51 additions & 0 deletions src/OpenDebugAD7/AD7Impl/AD7BreakPointRequest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -112,5 +112,56 @@ public int GetChecksum(ref Guid guidAlgorithm, CHECKSUM_DATA[] checksumData)
return HRConstants.E_FAIL;
}
}

#region Tracepoints

private string m_logMessage;
private Tracepoint m_Tracepoint;

public void ClearTracepoint()
{
m_logMessage = null;
m_Tracepoint = null;
}

public bool SetLogMessage(string logMessage)
{
try
{
m_Tracepoint = Tracepoint.CreateTracepoint(logMessage);
}
catch (InvalidTracepointException e)
{
return false;
}
m_logMessage = logMessage;
return true;
}

public string LogMessage
WardenGnaw marked this conversation as resolved.
Show resolved Hide resolved
{
get
{
return m_logMessage;
}
}

public bool HasTracepoint
{
get
{
return !string.IsNullOrEmpty(m_logMessage) && m_Tracepoint != null;
}
}

public Tracepoint Tracepoint
{
get
{
return m_Tracepoint;
}
}

#endregion
}
}
1 change: 1 addition & 0 deletions src/OpenDebugAD7/OpenDebugAD7.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@
<Compile Include="Telemetry\TelemetryHelper.cs" />
<Compile Include="TextPositionTuple.cs" />
<Compile Include="ThreadFrameEnumInfo.cs" />
<Compile Include="Tracepoint.cs" />
<Compile Include="VariableManager.cs" />
<Compile Include="AD7DebugSession.cs" />
</ItemGroup>
Expand Down
2 changes: 2 additions & 0 deletions src/OpenDebugAD7/Telemetry/DebuggerTelemetry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ internal sealed class DebuggerTelemetry
public const string TelemetryAttachEventName = "Attach";
public const string TelemetryEvaluateEventName = "Evaluate";
public const string TelemetryPauseEventName = "Pause";
public const string TelemetryTracepointEventName = "Tracepoint";
WardenGnaw marked this conversation as resolved.
Show resolved Hide resolved

// Common telemetry properties
public const string TelemetryErrorType = "ErrorType";
Expand Down Expand Up @@ -55,6 +56,7 @@ internal sealed class DebuggerTelemetry
public const string TelemetrySourceFileMappings = "SourceFileMappings";
public const string TelemetryMIMode = "MIMode";
public const string TelemetryStackFrameId = TelemetryExecuteInConsole + ".ExecuteInConsole";
WardenGnaw marked this conversation as resolved.
Show resolved Hide resolved
public const string TelemetryTracepointTokens = ".Tokens";
WardenGnaw marked this conversation as resolved.
Show resolved Hide resolved

private DebuggerTelemetry(Action<DebugEvent> callback, TypeInfo engineType, TypeInfo hostType, string adapterId)
{
Expand Down
Loading