private void OnHalted(HaltArguments args) { switch (args.Reason) { case HaltReason.Breakpoint: switch (args.BreakpointType) { case BreakpointType.AccessWatchpoint: case BreakpointType.WriteWatchpoint: case BreakpointType.ReadWatchpoint: beforeCommand += cmd => { commandsCounter++; if (commandsCounter > 15) { // this is a hack! // I noticed that GDB will send `step` command after receiving // information about watchpoint being hit. // As a result cpu would execute next instruction and stop again. // To prevent this situation we wait for `step` and ignore it, but // only in small time window (15 - instructions, value choosen at random) // and only after sending watchpoint-related stop reply. this.Log(LogLevel.Error, "Expected step command after watchpoint. Further debugging might not work properly"); beforeCommand = null; commandsCounter = 0; return(false); } if ((cmd is SingleStepCommand)) { SendPacket(new Packet(PacketData.StopReply(TrapSignal))); beforeCommand = null; commandsCounter = 0; return(true); } return(false); }; goto case BreakpointType.HardwareBreakpoint; case BreakpointType.HardwareBreakpoint: case BreakpointType.MemoryBreakpoint: SendPacket(new Packet(PacketData.StopReply(args.BreakpointType.Value, args.Address))); break; } return; case HaltReason.Step: case HaltReason.Pause: SendPacket(new Packet(PacketData.StopReply(TrapSignal))); return; case HaltReason.Abort: SendPacket(new Packet(PacketData.AbortReply(AbortSignal))); return; default: throw new ArgumentException("Unexpected halt reason"); } }
private void OnHalted(HaltArguments args) { using (var ctx = commHandler.OpenContext()) { // GDB counts threads starting from `1`, while Renode counts them from `0` - hence the incrementation var cpuId = args.CpuId + 1; switch (args.Reason) { case HaltReason.Breakpoint: switch (args.BreakpointType) { case BreakpointType.AccessWatchpoint: case BreakpointType.WriteWatchpoint: case BreakpointType.ReadWatchpoint: case BreakpointType.HardwareBreakpoint: case BreakpointType.MemoryBreakpoint: foreach (var cpu in commandsManager.ManagedCpus.Values) { cpu.IsHalted = true; } if (commandsManager.Machine.SystemBus.IsMultiCore) { commandsManager.SelectCpuForDebugging(cpuId); ctx.Send(new Packet(PacketData.StopReply(args.BreakpointType.Value, cpuId, args.Address))); } else { ctx.Send(new Packet(PacketData.StopReply(args.BreakpointType.Value, args.Address))); } break; } return; case HaltReason.Step: case HaltReason.Pause: if (commandsManager.Machine.SystemBus.IsMultiCore) { commandsManager.SelectCpuForDebugging(cpuId); ctx.Send(new Packet(PacketData.StopReply(TrapSignal, cpuId))); } else { ctx.Send(new Packet(PacketData.StopReply(TrapSignal))); } return; case HaltReason.Abort: ctx.Send(new Packet(PacketData.AbortReply(AbortSignal))); return; default: throw new ArgumentException("Unexpected halt reason"); } } }