diff --git a/src/DebugEngineHost.Stub/DebugEngineHost.ref.cs b/src/DebugEngineHost.Stub/DebugEngineHost.ref.cs
index c47b1c105..63d622d95 100644
--- a/src/DebugEngineHost.Stub/DebugEngineHost.ref.cs
+++ b/src/DebugEngineHost.Stub/DebugEngineHost.ref.cs
@@ -229,6 +229,18 @@ public static IDebugDocumentPosition2 GetDocumentPositionForIntPtr(IntPtr docume
throw new NotImplementedException();
}
+ ///
+ /// Obtains a function position interface given the specified IntPtr of the location.
+ ///
+ /// In VS, the IUnknown pointer to QI for a function position. In VS Code,
+ /// the identifier for the function position
+ /// Function position object
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "ForInt")]
+ public static IDebugFunctionPosition2 GetDebugFunctionPositionForIntPtr(IntPtr locationId)
+ {
+ throw new NotImplementedException();
+ }
+
///
/// Obtains an event callback interface that can be used to send events on any threads
///
diff --git a/src/DebugEngineHost/HostMarshal.cs b/src/DebugEngineHost/HostMarshal.cs
index f4940eda4..85aed6b6d 100644
--- a/src/DebugEngineHost/HostMarshal.cs
+++ b/src/DebugEngineHost/HostMarshal.cs
@@ -45,6 +45,19 @@ public static IDebugDocumentPosition2 GetDocumentPositionForIntPtr(IntPtr docume
return (IDebugDocumentPosition2)Marshal.GetObjectForIUnknown(documentPositionId);
}
+ ///
+ /// Obtains a function position interface given the specified IntPtr of the location.
+ ///
+ /// In VS, the IUnknown pointer to QI for a function position. In VS Code,
+ /// the identifier for the function position
+ /// Function position object
+ 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);
+ }
+
///
/// Obtains an event callback interface that can be used to send events on any threads
///
diff --git a/src/MICore/MICommandFactory.cs b/src/MICore/MICommandFactory.cs
index b2c446d6b..1a19f462b 100644
--- a/src/MICore/MICommandFactory.cs
+++ b/src/MICore/MICommandFactory.cs
@@ -384,7 +384,7 @@ public virtual async Task Terminate()
#region Breakpoints
- public virtual async Task 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)
@@ -393,12 +393,26 @@ public virtual async Task BreakInsert(string filename, uint line, strin
cmd.Append(condition);
cmd.Append("\" ");
}
+ return cmd;
+ }
+
+ public virtual async Task 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 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 BreakInfo(string bkptno)
{
Results bindResult = await _debugger.CmdAsync("-break-info " + bkptno, ResultClass.None);
diff --git a/src/MIDebugEngine/AD7.Impl/AD7PendingBreakpoint.cs b/src/MIDebugEngine/AD7.Impl/AD7PendingBreakpoint.cs
index 5c3a5bf00..8bf5ef521 100644
--- a/src/MIDebugEngine/AD7.Impl/AD7PendingBreakpoint.cs
+++ b/src/MIDebugEngine/AD7.Impl/AD7PendingBreakpoint.cs
@@ -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;
@@ -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;
@@ -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)
{
diff --git a/src/MIDebugEngine/Engine.Impl/Breakpoints.cs b/src/MIDebugEngine/Engine.Impl/Breakpoints.cs
index 5e27d5c04..8cd9afd94 100644
--- a/src/MIDebugEngine/Engine.Impl/Breakpoints.cs
+++ b/src/MIDebugEngine/Engine.Impl/Breakpoints.cs
@@ -84,10 +84,19 @@ private static MIBreakpointState StringToBreakpointState(string addr)
}
}
+ internal static async Task Bind(string functionName, DebuggedProcess process, string condition, AD7PendingBreakpoint pbreak)
+ {
+ return EvalBindResult(await process.MICommandFactory.BreakInsert(functionName, condition, ResultClass.None), pbreak);
+ }
+
internal static async Task 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)
{