protected override void HandleSetInstructionBreakpointsRequestAsync()

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));
            }
        }