Skip to content
Merged
Show file tree
Hide file tree
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
12 changes: 12 additions & 0 deletions src/DebugEngineHost.Stub/DebugEngineHost.ref.cs
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,18 @@ public static IDebugDocumentPosition2 GetDocumentPositionForIntPtr(IntPtr docume
throw new NotImplementedException();
}

/// <summary>
/// Obtains a function position interface given the specified IntPtr of the location.
/// </summary>
/// <param name="locationId">In VS, the IUnknown pointer to QI for a function position. In VS Code,
/// the identifier for the function position</param>
/// <returns>Function position object</returns>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "ForInt")]
public static IDebugFunctionPosition2 GetDebugFunctionPositionForIntPtr(IntPtr locationId)
{
throw new NotImplementedException();
}

/// <summary>
/// Obtains an event callback interface that can be used to send events on any threads
/// </summary>
Expand Down
13 changes: 13 additions & 0 deletions src/DebugEngineHost/HostMarshal.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,19 @@ public static IDebugDocumentPosition2 GetDocumentPositionForIntPtr(IntPtr docume
return (IDebugDocumentPosition2)Marshal.GetObjectForIUnknown(documentPositionId);
}

/// <summary>
/// Obtains a function position interface given the specified IntPtr of the location.
/// </summary>
/// <param name="locationId">In VS, the IUnknown pointer to QI for a function position. In VS Code,
/// the identifier for the function position</param>
/// <returns>Function position object</returns>
public static IDebugFunctionPosition2 GetDebugFunctionPositionForIntPtr(IntPtr locationId)
{
// TODO: It looks like the MIEngine currently leaks the native document position. Fix that.

return (IDebugFunctionPosition2)Marshal.GetObjectForIUnknown(locationId);
}

/// <summary>
/// Obtains an event callback interface that can be used to send events on any threads
/// </summary>
Expand Down
16 changes: 15 additions & 1 deletion src/MICore/MICommandFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,7 @@ public virtual async Task Terminate()

#region Breakpoints

public virtual async Task<Results> BreakInsert(string filename, uint line, string condition, ResultClass resultClass = ResultClass.done)
private StringBuilder BuildBreakInsert(string condition)
{
StringBuilder cmd = new StringBuilder("-break-insert -f ");
if (condition != null)
Expand All @@ -393,12 +393,26 @@ public virtual async Task<Results> BreakInsert(string filename, uint line, strin
cmd.Append(condition);
cmd.Append("\" ");
}
return cmd;
}

public virtual async Task<Results> BreakInsert(string filename, uint line, string condition, ResultClass resultClass = ResultClass.done)
{
StringBuilder cmd = BuildBreakInsert(condition);
cmd.Append(filename);
cmd.Append(":");
cmd.Append(line.ToString());
return await _debugger.CmdAsync(cmd.ToString(), resultClass);
}

public virtual async Task<Results> BreakInsert(string functionName, string condition, ResultClass resultClass = ResultClass.done)
{
StringBuilder cmd = BuildBreakInsert(condition);
// TODO: Add support of break function type filename:function locations
cmd.Append(functionName);
return await _debugger.CmdAsync(cmd.ToString(), resultClass);
}

public virtual async Task<TupleValue> BreakInfo(string bkptno)
{
Results bindResult = await _debugger.CmdAsync("-break-info " + bkptno, ResultClass.None);
Expand Down
40 changes: 31 additions & 9 deletions src/MIDebugEngine/AD7.Impl/AD7PendingBreakpoint.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,10 @@ private bool VerifyCondition(BP_CONDITION request)

private bool CanBind()
{
// The sample engine only supports breakpoints on a file and line number. No other types of breakpoints are supported.
if (_deleted || _bpRequestInfo.bpLocation.bpLocationType != (uint)enum_BP_LOCATION_TYPE.BPLT_CODE_FILE_LINE)
// The sample engine only supports breakpoints on a file and line number or function name. No other types of breakpoints are supported.
if (_deleted ||
(_bpRequestInfo.bpLocation.bpLocationType != (uint)enum_BP_LOCATION_TYPE.BPLT_CODE_FILE_LINE
&& _bpRequestInfo.bpLocation.bpLocationType != (uint)enum_BP_LOCATION_TYPE.BPLT_CODE_FUNC_OFFSET))
{
_BPError = new AD7ErrorBreakpoint(this, ResourceStrings.UnsupportedBreakpoint, enum_BP_ERROR_TYPE.BPET_GENERAL_ERROR);
return false;
Expand Down Expand Up @@ -184,6 +186,7 @@ internal async Task BindAsync()
if (CanBind())
{
string documentName = null;
string functionName = null;
TEXT_POSITION[] startPosition = new TEXT_POSITION[1];
TEXT_POSITION[] endPosition = new TEXT_POSITION[1];
string condition = null;
Expand All @@ -195,22 +198,41 @@ internal async Task BindAsync()
Debug.Fail("Breakpoint already bound");
return;
}
IDebugDocumentPosition2 docPosition = HostMarshal.GetDocumentPositionForIntPtr(_bpRequestInfo.bpLocation.unionmember2);
if ((_bpRequestInfo.dwFields & enum_BPREQI_FIELDS.BPREQI_BPLOCATION) != 0)
{
if (_bpRequestInfo.bpLocation.bpLocationType == (uint)enum_BP_LOCATION_TYPE.BPLT_CODE_FUNC_OFFSET)
{
IDebugFunctionPosition2 functionPosition = HostMarshal.GetDebugFunctionPositionForIntPtr(_bpRequestInfo.bpLocation.unionmember2);
EngineUtils.CheckOk(functionPosition.GetFunctionName(out functionName));
}
else if (_bpRequestInfo.bpLocation.bpLocationType == (uint)enum_BP_LOCATION_TYPE.BPLT_CODE_FILE_LINE)
{
IDebugDocumentPosition2 docPosition = HostMarshal.GetDocumentPositionForIntPtr(_bpRequestInfo.bpLocation.unionmember2);

// Get the name of the document that the breakpoint was put in
EngineUtils.CheckOk(docPosition.GetFileName(out documentName));
// Get the name of the document that the breakpoint was put in
EngineUtils.CheckOk(docPosition.GetFileName(out documentName));

// Get the location in the document that the breakpoint is in.
EngineUtils.CheckOk(docPosition.GetRange(startPosition, endPosition));
// Get the location in the document that the breakpoint is in.
EngineUtils.CheckOk(docPosition.GetRange(startPosition, endPosition));
}
}
if ((_bpRequestInfo.dwFields & enum_BPREQI_FIELDS.BPREQI_CONDITION) != 0
&& _bpRequestInfo.bpCondition.styleCondition == enum_BP_COND_STYLE.BP_COND_WHEN_TRUE)
{
condition = _bpRequestInfo.bpCondition.bstrCondition;
}
}

}
PendingBreakpoint.BindResult bindResult;
// Bind all breakpoints that match this source and line number.
PendingBreakpoint.BindResult bindResult = await PendingBreakpoint.Bind(documentName, startPosition[0].dwLine + 1, startPosition[0].dwColumn, _engine.DebuggedProcess, condition, this);
if (documentName != null)
{
bindResult = await PendingBreakpoint.Bind(documentName, startPosition[0].dwLine + 1, startPosition[0].dwColumn, _engine.DebuggedProcess, condition, this);
}
else
{
bindResult = await PendingBreakpoint.Bind(functionName, _engine.DebuggedProcess, condition, this);
}

lock (_boundBreakpoints)
{
Expand Down
11 changes: 10 additions & 1 deletion src/MIDebugEngine/Engine.Impl/Breakpoints.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,19 @@ private static MIBreakpointState StringToBreakpointState(string addr)
}
}

internal static async Task<BindResult> Bind(string functionName, DebuggedProcess process, string condition, AD7PendingBreakpoint pbreak)
{
return EvalBindResult(await process.MICommandFactory.BreakInsert(functionName, condition, ResultClass.None), pbreak);
}

internal static async Task<BindResult> Bind(string documentName, uint line, uint column, DebuggedProcess process, string condition, AD7PendingBreakpoint pbreak)
{
string basename = System.IO.Path.GetFileName(documentName); // get basename from Windows path
Results bindResult = await process.MICommandFactory.BreakInsert(process.EscapePath(basename), line, condition, ResultClass.None);
return EvalBindResult(await process.MICommandFactory.BreakInsert(process.EscapePath(basename), line, condition, ResultClass.None), pbreak);
}

private static BindResult EvalBindResult(Results bindResult, AD7PendingBreakpoint pbreak)
{
string errormsg = "Unknown error";
if (bindResult.ResultClass == ResultClass.error)
{
Expand Down