in src/OpenDebugAD7/AD7DebugSession.cs [3028:3145]
protected override void HandleSetInstructionBreakpointsRequestAsync(IRequestResponder<SetInstructionBreakpointsArguments, SetInstructionBreakpointsResponse> responder)
{
if (responder.Arguments.Breakpoints == null)
{
responder.SetError(new ProtocolException("HandleSetInstructionBreakpointsRequest failed: Missing 'breakpoints'."));
return;
}
ErrorBuilder eb = new ErrorBuilder(() => AD7Resources.Error_UnableToSetInstructionBreakpoint);
SetInstructionBreakpointsResponse response = new SetInstructionBreakpointsResponse();
List<InstructionBreakpoint> breakpoints = responder.Arguments.Breakpoints;
Dictionary<ulong, IDebugPendingBreakpoint2> newBreakpoints = new Dictionary<ulong, IDebugPendingBreakpoint2>();
try
{
HashSet<ulong> requestAddresses = responder.Arguments.Breakpoints.Select(x => ResolveInstructionReference(x.InstructionReference, x.Offset)).ToHashSet();
foreach (KeyValuePair<ulong, IDebugPendingBreakpoint2> b in m_instructionBreakpoints)
{
if (requestAddresses.Contains(b.Key))
{
newBreakpoints[b.Key] = b.Value; // breakpoint still in new list
}
else
{
IDebugPendingBreakpoint2 pendingBp = b.Value;
if (pendingBp != null &&
pendingBp.GetBreakpointRequest(out IDebugBreakpointRequest2 request) == HRConstants.S_OK &&
request is AD7BreakPointRequest ad7Request)
{
HostMarshal.ReleaseCodeContextId(ad7Request.MemoryContextIntPtr);
}
else
{
Debug.Fail("Why can't we retrieve the MemoryContextIntPtr?");
}
b.Value.Delete(); // not in new list so delete it
}
}
foreach (var instructionBp in responder.Arguments.Breakpoints)
{
eb.CheckHR(GetMemoryContext(instructionBp.InstructionReference, instructionBp.Offset, out IDebugMemoryContext2 memoryContext, out ulong address));
if (m_instructionBreakpoints.ContainsKey(address))
{
IDebugBreakpointRequest2 breakpointRequest;
if (m_instructionBreakpoints[address].GetBreakpointRequest(out breakpointRequest) == 0 &&
breakpointRequest is AD7BreakPointRequest ad7BPRequest)
{
// Check to see if this breakpoint has a condition that has changed.
if (!StringComparer.Ordinal.Equals(ad7BPRequest.Condition, instructionBp.Condition))
{
// Condition has been modified. Delete breakpoint so it will be recreated with the updated condition.
var toRemove = m_instructionBreakpoints[address];
toRemove.Delete();
m_instructionBreakpoints.Remove(address);
}
else
{
if (ad7BPRequest.BindResult != null)
{
response.Breakpoints.Add(ad7BPRequest.BindResult);
}
else
{
response.Breakpoints.Add(new Breakpoint()
{
Id = (int)ad7BPRequest.Id,
Verified = true,
Line = 0
});
}
continue;
}
}
}
else
{
IDebugPendingBreakpoint2 pendingBp;
AD7BreakPointRequest pBPRequest = new AD7BreakPointRequest(memoryContext);
eb.CheckHR(m_engine.CreatePendingBreakpoint(pBPRequest, out pendingBp));
if (pendingBp != null && pendingBp.Bind() == HRConstants.S_OK)
{
newBreakpoints[address] = pendingBp;
response.Breakpoints.Add(new Breakpoint()
{
Id = (int)pBPRequest.Id,
Verified = true,
Line = 0
}); // success
}
else
{
response.Breakpoints.Add(new Breakpoint()
{
Id = (int)pBPRequest.Id,
Verified = false,
Line = 0,
Message = string.Format(CultureInfo.CurrentCulture, AD7Resources.Error_UnableToSetInstructionBreakpoint, address)
}); // couldn't create and/or bind
}
}
}
m_instructionBreakpoints = newBreakpoints;
responder.SetResponse(response);
}
catch (Exception e)
{
responder.SetError(new ProtocolException(e.Message));
}
}