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

avoid "Unable to open file" popups caused by missing source code #1038

Merged
merged 6 commits into from
Jan 3, 2022
Merged
Changes from all 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
308 changes: 177 additions & 131 deletions src/OpenDebugAD7/AD7DebugSession.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1522,192 +1522,238 @@ protected override void HandleGotoTargetsRequestAsync(IRequestResponder<GotoTarg
responder.SetResponse(response);
}

protected override void HandleStackTraceRequestAsync(IRequestResponder<StackTraceArguments, StackTraceResponse> responder)
protected override async void HandleStackTraceRequestAsync(IRequestResponder<StackTraceArguments, StackTraceResponse> responder)
{
int threadReference = responder.Arguments.ThreadId;
int startFrame = responder.Arguments.StartFrame.GetValueOrDefault(0);
int levels = responder.Arguments.Levels.GetValueOrDefault(0);

StackTraceResponse response = new StackTraceResponse()
try
{
TotalFrames = 0
};
int threadReference = responder.Arguments.ThreadId;
int startFrame = responder.Arguments.StartFrame.GetValueOrDefault(0);
int levels = responder.Arguments.Levels.GetValueOrDefault(0);

var response = new StackTraceResponse()
{
TotalFrames = 0
};

// Make sure we are stopped and receiving valid input or else return an empty stack trace
if (!m_isStopped || startFrame < 0 || levels < 0)
{
responder.SetResponse(response);
return;
}

// Make sure we are stopped and receiving valid input or else return an empty stack trace
if (m_isStopped && startFrame >= 0 && levels >= 0)
{
ThreadFrameEnumInfo frameEnumInfo = null;
IDebugThread2 thread;
lock (m_threads)
{
if (m_threads.TryGetValue(threadReference, out thread))
if (!m_threads.TryGetValue(threadReference, out thread))
{
enum_FRAMEINFO_FLAGS flags = enum_FRAMEINFO_FLAGS.FIF_FUNCNAME | // need a function name
enum_FRAMEINFO_FLAGS.FIF_FRAME | // need a frame object
enum_FRAMEINFO_FLAGS.FIF_FLAGS |
enum_FRAMEINFO_FLAGS.FIF_DEBUG_MODULEP;

uint radix = Constants.EvaluationRadix;

if (responder.Arguments.Format != null)
{
StackFrameFormat format = responder.Arguments.Format;

if (format.Hex == true)
{
radix = 16;
}

if (format.Line == true)
{
flags |= enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_LINES;
}
// Invalid thread specified
responder.SetError(new ProtocolException(String.Format(CultureInfo.CurrentCulture, AD7Resources.Error_PropertyInvalid, StackTraceRequest.RequestType, "threadId")));
return;
}

if (format.Module == true)
{
flags |= enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_MODULE;
}
enum_FRAMEINFO_FLAGS flags = enum_FRAMEINFO_FLAGS.FIF_FUNCNAME | // need a function name
enum_FRAMEINFO_FLAGS.FIF_FRAME | // need a frame object
enum_FRAMEINFO_FLAGS.FIF_FLAGS |
enum_FRAMEINFO_FLAGS.FIF_DEBUG_MODULEP;

if (format.Parameters == true)
{
flags |= enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_ARGS;
}
uint radix = Constants.EvaluationRadix;

if (format.ParameterNames == true)
{
flags |= enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_ARGS_NAMES;
}

if (format.ParameterTypes == true)
{
flags |= enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_ARGS_TYPES;
}
if (responder.Arguments.Format != null)
{
StackFrameFormat format = responder.Arguments.Format;

if (format.ParameterValues == true)
{
flags |= enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_ARGS_VALUES;
}
if (format.Hex == true)
{
radix = 16;
}
else

if (format.Line == true)
{
// No formatting flags provided in the request - use the default format, which includes the module name and argument names / types
flags |= enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_MODULE |
enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_ARGS |
enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_ARGS_TYPES |
enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_ARGS_NAMES;
flags |= enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_LINES;
}

if (m_settingsCallback != null)
if (format.Module == true)
{
// MIEngine generally gets the radix from IDebugSettingsCallback110 rather than using the radix passed
m_settingsCallback.Radix = radix;
flags |= enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_MODULE;
}

ErrorBuilder eb = new ErrorBuilder(() => AD7Resources.Error_Scenario_StackTrace);
if (format.Parameters == true)
{
flags |= enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_ARGS;
}

try
if (format.ParameterNames == true)
{
eb.CheckHR(thread.EnumFrameInfo(flags, radix, out IEnumDebugFrameInfo2 frameEnum));
eb.CheckHR(frameEnum.GetCount(out uint totalFrames));
flags |= enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_ARGS_NAMES;
}

frameEnumInfo = new ThreadFrameEnumInfo(frameEnum, totalFrames);
if (format.ParameterTypes == true)
{
flags |= enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_ARGS_TYPES;
}
catch (AD7Exception ex)

if (format.ParameterValues == true)
{
responder.SetError(new ProtocolException(ex.Message, ex));
return;
flags |= enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_ARGS_VALUES;
}
}
else
{
// Invalid thread specified
responder.SetError(new ProtocolException(String.Format(CultureInfo.CurrentCulture, AD7Resources.Error_PropertyInvalid, StackTraceRequest.RequestType, "threadId")));
return;
// No formatting flags provided in the request - use the default format, which includes the module name and argument names / types
flags |= enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_MODULE |
enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_ARGS |
enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_ARGS_TYPES |
enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_ARGS_NAMES;
}
}

if (startFrame < frameEnumInfo.TotalFrames)
{
if (startFrame != frameEnumInfo.CurrentPosition)
if (m_settingsCallback != null)
{
frameEnumInfo.FrameEnum.Reset();
frameEnumInfo.CurrentPosition = (uint)startFrame;

if (startFrame > 0)
{
frameEnumInfo.FrameEnum.Skip((uint)startFrame);
}
// MIEngine generally gets the radix from IDebugSettingsCallback110 rather than using the radix passed
m_settingsCallback.Radix = radix;
}

if (levels == 0)
ErrorBuilder eb = new ErrorBuilder(() => AD7Resources.Error_Scenario_StackTrace);

try
{
// take the rest of the stack frames
levels = (int)frameEnumInfo.TotalFrames - startFrame;
eb.CheckHR(thread.EnumFrameInfo(flags, radix, out IEnumDebugFrameInfo2 frameEnum));
eb.CheckHR(frameEnum.GetCount(out uint totalFrames));

frameEnumInfo = new ThreadFrameEnumInfo(frameEnum, totalFrames);
}
else
catch (AD7Exception ex)
{
levels = Math.Min((int)frameEnumInfo.TotalFrames - startFrame, levels);
responder.SetError(new ProtocolException(ex.Message, ex));
return;
}
}

if (startFrame >= frameEnumInfo.TotalFrames)
{
responder.SetResponse(response);
return;
}

FRAMEINFO[] frameInfoArray = new FRAMEINFO[levels];
uint framesFetched = 0;
frameEnumInfo.FrameEnum.Next((uint)frameInfoArray.Length, frameInfoArray, ref framesFetched);
frameEnumInfo.CurrentPosition += framesFetched;
if (startFrame != frameEnumInfo.CurrentPosition)
{
frameEnumInfo.FrameEnum.Reset();
frameEnumInfo.CurrentPosition = (uint)startFrame;

for (int i = 0; i < framesFetched; i++)
if (startFrame > 0)
{
// TODO: annotated frames?
var frameInfo = frameInfoArray[i];
IDebugStackFrame2 frame = frameInfo.m_pFrame;
frameEnumInfo.FrameEnum.Skip((uint)startFrame);
}
}

int frameReference = 0;
TextPositionTuple textPosition = TextPositionTuple.Nil;
IDebugCodeContext2 memoryAddress = null;
if (levels == 0)
{
// take the rest of the stack frames
levels = (int)frameEnumInfo.TotalFrames - startFrame;
}
else
{
levels = Math.Min((int)frameEnumInfo.TotalFrames - startFrame, levels);
}

if (frame != null)
var frameInfoArray = new FRAMEINFO[levels];
uint framesFetched = 0;
frameEnumInfo.FrameEnum.Next((uint)frameInfoArray.Length, frameInfoArray, ref framesFetched);
frameEnumInfo.CurrentPosition += framesFetched;

for (int i = 0; i < framesFetched; i++)
{
// TODO: annotated frames?
var frameInfo = frameInfoArray[i];
IDebugStackFrame2 frame = frameInfo.m_pFrame;

int frameReference = 0;
TextPositionTuple textPosition = TextPositionTuple.Nil;
IDebugCodeContext2 memoryAddress = null;

if (frame != null)
{
frameReference = m_frameHandles.Create(frame);
textPosition = TextPositionTuple.GetTextPositionOfFrame(m_pathConverter, frame) ?? TextPositionTuple.Nil;
frame.GetCodeContext(out memoryAddress);
}

int? moduleId = null;
IDebugModule2 module = frameInfo.m_pModule;
if (module != null)
{
lock (m_moduleMap)
{
frameReference = m_frameHandles.Create(frame);
textPosition = TextPositionTuple.GetTextPositionOfFrame(m_pathConverter, frame) ?? TextPositionTuple.Nil;
frame.GetCodeContext(out memoryAddress);
if (m_moduleMap.TryGetValue(module, out int mapModuleId))
{
moduleId = mapModuleId;
}
}
}

string instructionPointerReference = null;
var contextInfo = new CONTEXT_INFO[1];
if (memoryAddress?.GetInfo(enum_CONTEXT_INFO_FIELDS.CIF_ADDRESS, contextInfo) == HRConstants.S_OK && contextInfo[0].dwFields.HasFlag(enum_CONTEXT_INFO_FIELDS.CIF_ADDRESS))
{
instructionPointerReference = contextInfo[0].bstrAddress;
}

int? moduleId = null;
IDebugModule2 module = frameInfo.m_pModule;
if (module != null)
response.StackFrames.Add(new ProtocolMessages.StackFrame()
{
Id = frameReference,
Name = frameInfo.m_bstrFuncName,
Source = textPosition.Source,
Line = textPosition.Line,
Column = textPosition.Column,
ModuleId = moduleId,
InstructionPointerReference = instructionPointerReference
});
}

if (!IsClientVS)
{
var cancellationTokenSource = new CancellationTokenSource();
try
{
CancellationToken cancellationToken = cancellationTokenSource.Token;
var frameTasks = response.StackFrames.Select(frame => Task.Run(() =>
{
lock (m_moduleMap)
cancellationToken.ThrowIfCancellationRequested();
if (frame.Source != null && !File.Exists(frame.Source.Path))
{
if (m_moduleMap.TryGetValue(module, out int mapModuleId))
{
moduleId = mapModuleId;
}
cancellationToken.ThrowIfCancellationRequested();
// mark the stack frame to be skipped by default
frame.Source.PresentationHint = Source.PresentationHintValue.Deemphasize;
}
}
}));

string instructionPointerReference = null;
var contextInfo = new CONTEXT_INFO[1];
if (memoryAddress?.GetInfo(enum_CONTEXT_INFO_FIELDS.CIF_ADDRESS, contextInfo) == HRConstants.S_OK && contextInfo[0].dwFields.HasFlag(enum_CONTEXT_INFO_FIELDS.CIF_ADDRESS))
Task allFramesComplete = Task.WhenAll(frameTasks);
Task timeoutTask = Task.Delay(1000, cancellationToken);
try
{
instructionPointerReference = contextInfo[0].bstrAddress;
await Task.WhenAny(allFramesComplete, timeoutTask);
}

response.StackFrames.Add(new ProtocolMessages.StackFrame()
catch (Exception e)
{
Id = frameReference,
Name = frameInfo.m_bstrFuncName,
Source = textPosition.Source,
Line = textPosition.Line,
Column = textPosition.Column,
ModuleId = moduleId,
InstructionPointerReference = instructionPointerReference
});
Debug.Fail("Ignoring exception computing frame state: " + e.ToString());
}
}
finally
{
cancellationTokenSource.Cancel();
cancellationTokenSource.Dispose();
}

response.TotalFrames = (int)frameEnumInfo.TotalFrames;
}
}
Trass3r marked this conversation as resolved.
Show resolved Hide resolved

responder.SetResponse(response);
response.TotalFrames = (int)frameEnumInfo.TotalFrames;

responder.SetResponse(response);
}
catch (Exception e)
{
responder.SetError(new ProtocolException(e.Message));
}
}

protected override void HandleScopesRequestAsync(IRequestResponder<ScopesArguments, ScopesResponse> responder)
Expand Down