From 9868a9e7f5d30d4efbc0bf69191aedfe02d8905c Mon Sep 17 00:00:00 2001 From: Aleksey Bragin Date: Tue, 2 Aug 2011 19:54:03 +0000 Subject: [PATCH] Willem Alexander Hajenius - KDBG/IDebugProtocol: parse/add/delete/enable/disable breakpoints. Some other refactorings done to reduce method size. - Dockable window that shows current list of breakpoints with add/delete/edit button (you can also double-click to edit). Breakpoints can easily be enabled/disabled with a checkbox. - Dialog window to add or edit breakpoint details. GUI tries to prevent invalid input. - Add svn:ignore to RosDBG directory. svn path=/trunk/reactosdbg/; revision=1308 --- DebugProtocol/Breakpoint.cs | 32 +- DebugProtocol/DebugConnection.cs | 20 +- DebugProtocol/IDebugProtocol.cs | 20 +- DebugProtocol/KDBG.cs | 642 +++++++++++------- .../BreakpointWindow.Designer.cs | 200 ++++++ RosDBG/Dockable Objects/BreakpointWindow.cs | 193 ++++++ RosDBG/Dockable Objects/BreakpointWindow.resx | 152 +++++ RosDBG/EditBreakpointDialog.Designer.cs | 331 +++++++++ RosDBG/EditBreakpointDialog.cs | 179 +++++ RosDBG/EditBreakpointDialog.resx | 120 ++++ RosDBG/MainWindow.cs | 6 +- RosDBG/Properties/AssemblyInfo.cs | 4 +- RosDBG/Properties/DataSources/.gitignore | 0 RosDBG/RosDBG.csproj | 21 + 14 files changed, 1679 insertions(+), 241 deletions(-) create mode 100644 RosDBG/Dockable Objects/BreakpointWindow.Designer.cs create mode 100644 RosDBG/Dockable Objects/BreakpointWindow.cs create mode 100644 RosDBG/Dockable Objects/BreakpointWindow.resx create mode 100644 RosDBG/EditBreakpointDialog.Designer.cs create mode 100644 RosDBG/EditBreakpointDialog.cs create mode 100644 RosDBG/EditBreakpointDialog.resx create mode 100644 RosDBG/Properties/DataSources/.gitignore diff --git a/DebugProtocol/Breakpoint.cs b/DebugProtocol/Breakpoint.cs index 2a1e1e1..2b8cc64 100644 --- a/DebugProtocol/Breakpoint.cs +++ b/DebugProtocol/Breakpoint.cs @@ -8,19 +8,38 @@ namespace DebugProtocol public class Breakpoint { public enum BPType { Software, Hardware, WriteWatch, ReadWatch, AccessWatch }; - public readonly BPType BreakpointType; - public readonly long Address; - public readonly int Length; - public Breakpoint(BPType type, long addr, int len) + + public int ID { get; set; } + public BPType BreakpointType { get; set; } + public ulong Address { get; set; } + public int Length { get; set; } + public string Condition { get; set; } + public bool Enabled { get; set; } + + public Breakpoint(int id) { + ID = id; + BreakpointType = BPType.Software; + Address = 0; + Length = 1; + Condition = string.Empty; + Enabled = false; + } + + public Breakpoint(int id, BPType type, ulong addr, int len, string cond) + { + ID = id; BreakpointType = type; Address = addr; Length = len; + Condition = cond; + Enabled = false; } + //TODO: include condition/enabled in hashcode? public override int GetHashCode() { - return (int)(((int)BreakpointType) ^ Address ^ (Length << 28)); + return (int)(((int)BreakpointType) ^ (int)Address ^ (Length << 28)); } public override bool Equals(object other) @@ -28,9 +47,10 @@ namespace DebugProtocol Breakpoint otherbp = other as Breakpoint; if (otherbp == null) return false; return + otherbp.ID == ID;/* (otherbp.BreakpointType == BreakpointType) && (otherbp.Address == Address) && - (otherbp.Length == Length); + (otherbp.Length == Length);*/ } } } diff --git a/DebugProtocol/DebugConnection.cs b/DebugProtocol/DebugConnection.cs index 06439f0..078ef09 100644 --- a/DebugProtocol/DebugConnection.cs +++ b/DebugProtocol/DebugConnection.cs @@ -42,6 +42,16 @@ namespace DebugProtocol } public delegate void DebugRegisterChangeEventHandler(object sender, DebugRegisterChangeEventArgs args); + public class DebugBreakpointChangeEventArgs : EventArgs + { + public readonly IList Breakpoints; + public DebugBreakpointChangeEventArgs(IList breakpoints) + { + Breakpoints = breakpoints; + } + } + public delegate void DebugBreakpointChangeEventHandler(object sender, DebugBreakpointChangeEventArgs args); + public class DebugRunningChangeEventArgs : EventArgs { public readonly bool Running; @@ -180,6 +190,7 @@ namespace DebugProtocol #endregion public event DebugRegisterChangeEventHandler DebugRegisterChangeEvent; + public event DebugBreakpointChangeEventHandler DebugBreakpointChangeEvent; public event DebugConnectedEventHandler DebugConnectionConnectedEvent; public event DebugConnectionModeChangedEventHandler DebugConnectionModeChangedEvent; public event DebugRunningChangeEventHandler DebugRunningChangeEvent; @@ -219,6 +230,7 @@ namespace DebugProtocol { //set up tab handlers mKdb.RegisterChangeEvent += RegisterChangeEvent; + mKdb.BreakpointChangeEvent += BreakpointChangeEvent; mKdb.ModuleListEvent += ModuleListEvent; mKdb.MemoryUpdateEvent += MemoryUpdateEvent; mKdb.ProcessListEvent += ProcessListEvent; @@ -292,7 +304,7 @@ namespace DebugProtocol ConnectEventHandlers(); Running = true; } - catch (Exception) + catch (Exception ex) { ConnectionMode = Mode.ClosedMode; //error signal? @@ -442,6 +454,12 @@ namespace DebugProtocol DebugRegisterChangeEvent(this, new DebugRegisterChangeEventArgs(mRegisters)); } + void BreakpointChangeEvent(object sender, BreakpointChangeEventArgs args) + { + if (DebugBreakpointChangeEvent != null) + DebugBreakpointChangeEvent(this, new DebugBreakpointChangeEventArgs(args.Breakpoints)); + } + public void Break() { if (mKdb != null) diff --git a/DebugProtocol/IDebugProtocol.cs b/DebugProtocol/IDebugProtocol.cs index ecc3834..06f7f62 100644 --- a/DebugProtocol/IDebugProtocol.cs +++ b/DebugProtocol/IDebugProtocol.cs @@ -26,6 +26,16 @@ namespace DebugProtocol } public delegate void RegisterChangeEventHandler(object sender, RegisterChangeEventArgs args); + public class BreakpointChangeEventArgs : EventArgs + { + public readonly IList Breakpoints; + public BreakpointChangeEventArgs(IEnumerable breakpoints) + { + Breakpoints = new List(breakpoints); + } + } + public delegate void BreakpointChangeEventHandler(object sender, BreakpointChangeEventArgs args); + public class SignalDeliveredEventArgs : EventArgs { public readonly int Signal; @@ -96,11 +106,9 @@ namespace DebugProtocol public interface IDebugProtocol { - void SetBreakpoint(Breakpoint bp); - void RemoveBreakpoint(Breakpoint bp); - event ConsoleOutputEventHandler ConsoleOutputEvent; event RegisterChangeEventHandler RegisterChangeEvent; + event BreakpointChangeEventHandler BreakpointChangeEvent; event SignalDeliveredEventHandler SignalDeliveredEvent; event RemoteGDBErrorHandler RemoteGDBError; event MemoryUpdateEventHandler MemoryUpdateEvent; @@ -119,6 +127,12 @@ namespace DebugProtocol void Break(); void Go(ulong address); + void GetBreakpoints(); + void SetBreakpoint(Breakpoint bp); + void RemoveBreakpoint(int id); + void EnableBreakpoint(int id); + void DisableBreakpoint(int id); + void SetProcess(ulong pid); void SetThread(ulong tid); diff --git a/DebugProtocol/KDBG.cs b/DebugProtocol/KDBG.cs index e7eedc5..4b210f5 100644 --- a/DebugProtocol/KDBG.cs +++ b/DebugProtocol/KDBG.cs @@ -7,28 +7,13 @@ using System.Threading; using System.Globalization; using AbstractPipe; using DebugProtocol; +using System.Diagnostics; namespace KDBGProtocol { public class KDBG : IDebugProtocol { - bool mRunning = true; - Pipe mConnection; - List mCommandBuffer = new List(); - Dictionary mModuleList = new Dictionary(); - ulong []mRegisters = new ulong[32]; - - public KDBG(Pipe connection) - { - mConnection = connection; - mConnection.PipeReceiveEvent += PipeReceiveEvent; - mConnection.PipeErrorEvent += PipeErrorEvent; - } - - void PipeErrorEvent(object sender, PipeErrorEventArgs args) - { - } - + #region Regular expressions static Regex mMemoryRowUpdate = new Regex("<(?[^>]+)>: (?[0-9a-fA-F? ]*)"); static Regex mModuleOffset = new Regex("(?[^:]+):(?[0-9a-fA-f]+).*"); static Regex mModuleUpdate = new Regex("(?[0-9a-fA-F]+) (?[0-9a-fA-F]+) (?\\w+\\.\\w+)"); @@ -43,12 +28,48 @@ namespace KDBGProtocol static Regex mThreadListHeading = new Regex("TID[ \\t]+State[ \\t]+Prio.*"); static Regex mProcListEntry = new Regex("^(?([*]|))0x(?[0-9a-fA-F]+)[ \\t](?[a-zA-Z ]+)[ \\t](?[a-zA-Z. ]+).*"); static Regex mThreadListEntry = new Regex("^(?([*]|))0x(?[0-9a-fA-F]+)[ \\t]+(?.*)0x(?[0-9a-fA-F]*)"); + static Regex mBreakpointListEntry = new Regex("^\\*?(?[0-9]{3})[ \\t]+(?BP[X|M])[ \\t]+0x(?
[0-9a-fA-F]+)(?.+)"); + #endregion + + #region Fields + bool mRunning = true; + Pipe mConnection; + Queue mCommandBuffer = new Queue(); + Dictionary mModuleList = new Dictionary(); + ulong[] mRegisters = new ulong[32]; + IList mBreakpoints = new List(); bool mFirstModuleUpdate = false; bool mReceivingProcs = false; bool mReceivingThreads = false; + bool mReceivingBreakpoints = false; StringBuilder mInputBuffer = new StringBuilder(); int mUsedInput; + #endregion + + #region Events + public event ConsoleOutputEventHandler ConsoleOutputEvent; + public event RegisterChangeEventHandler RegisterChangeEvent; + public event BreakpointChangeEventHandler BreakpointChangeEvent; + public event SignalDeliveredEventHandler SignalDeliveredEvent; + public event RemoteGDBErrorHandler RemoteGDBError; + public event MemoryUpdateEventHandler MemoryUpdateEvent; + public event ModuleListEventHandler ModuleListEvent; + public event ProcessListEventHandler ProcessListEvent; + public event ThreadListEventHandler ThreadListEvent; + #endregion + + public KDBG(Pipe connection) + { + mConnection = connection; + mConnection.PipeReceiveEvent += PipeReceiveEvent; + mConnection.PipeErrorEvent += PipeErrorEvent; + } + + #region Event handlers + void PipeErrorEvent(object sender, PipeErrorEventArgs args) + { + } void PipeReceiveEvent(object sender, PipeReceiveEventArgs args) { @@ -102,200 +123,13 @@ namespace KDBGProtocol mFirstModuleUpdate = true; } - Match memoryMatch = mMemoryRowUpdate.Match(cleanedLine); - if (memoryMatch.Success) - { - string addrStr = memoryMatch.Groups["addr"].ToString(); - Match modOffset = mModuleOffset.Match(addrStr); - ulong updateAddress; - if (modOffset.Success) - { - string modname = modOffset.Groups["modname"].ToString(); - ulong offset = ulong.Parse(modOffset.Groups["offset"].ToString(), NumberStyles.HexNumber); - ulong modbase; - if (mModuleList.TryGetValue(modname.ToUpper(), out modbase)) - updateAddress = modbase + offset; - else - continue; // Couldn't resolve the address of the named module ... - } - else - { - updateAddress = ulong.Parse(addrStr, NumberStyles.HexNumber); - } - string[] memWords = memoryMatch.Groups["row"].ToString().Split(new char[] { ' ' }); - byte []updateBytes = new byte[4 * memWords.Length]; - int ctr = 0; - foreach (string word in memWords) - { - if (word[0] == '?') - { - if (MemoryUpdateEvent != null) - MemoryUpdateEvent(this, new MemoryUpdateEventArgs((updateAddress & ~0xfffUL), null)); - } - else - { - int wordParsed = int.Parse(word, NumberStyles.HexNumber); - int curCtr = ctr; - for (ctr = curCtr; ctr < curCtr + 4; ctr++) - { - updateBytes[ctr] = (byte)(wordParsed & 0xff); - wordParsed >>= 8; - } - } - } - if (MemoryUpdateEvent != null) - MemoryUpdateEvent(this, new MemoryUpdateEventArgs(updateAddress, updateBytes)); - - continue; - } - - Match moduleMatch = mModuleUpdate.Match(cleanedLine); - if (moduleMatch.Success) - { - ulong baseAddress = ulong.Parse(moduleMatch.Groups["base"].ToString(), NumberStyles.HexNumber); - uint moduleSize = uint.Parse(moduleMatch.Groups["size"].ToString(), NumberStyles.HexNumber); - string moduleName = moduleMatch.Groups["modname"].ToString(); - mModuleList[moduleName.ToUpper()] = baseAddress; - if (ModuleListEvent != null) - ModuleListEvent(this, new ModuleListEventArgs(moduleName, baseAddress)); - continue; - } - - Match csEipMatch = mRegLineCS_EIP.Match(cleanedLine); - if (csEipMatch.Success) - { - uint cs = uint.Parse(csEipMatch.Groups["cs"].ToString(), NumberStyles.HexNumber); - ulong eip = ulong.Parse(csEipMatch.Groups["eip"].ToString(), NumberStyles.HexNumber); - mRegisters[8] = eip; - mRegisters[10] = cs; - continue; - } - - Match ssEspMatch = mRegLineSS_ESP.Match(cleanedLine); - if (ssEspMatch.Success) - { - uint ss = uint.Parse(ssEspMatch.Groups["ss"].ToString(), NumberStyles.HexNumber); - ulong esp = ulong.Parse(ssEspMatch.Groups["esp"].ToString(), NumberStyles.HexNumber); - mRegisters[4] = esp; - mRegisters[15] = ss; - continue; - } - - Match eaxEbxMatch = mRegLineEAX_EBX.Match(cleanedLine); - if (eaxEbxMatch.Success) - { - ulong eax = ulong.Parse(eaxEbxMatch.Groups["eax"].ToString(), NumberStyles.HexNumber); - ulong ebx = ulong.Parse(eaxEbxMatch.Groups["ebx"].ToString(), NumberStyles.HexNumber); - mRegisters[0] = eax; - mRegisters[3] = ebx; - continue; - } - - Match ecxEdxMatch = mRegLineECX_EDX.Match(cleanedLine); - if (ecxEdxMatch.Success) - { - ulong ecx = ulong.Parse(ecxEdxMatch.Groups["ecx"].ToString(), NumberStyles.HexNumber); - ulong edx = ulong.Parse(ecxEdxMatch.Groups["edx"].ToString(), NumberStyles.HexNumber); - mRegisters[1] = ecx; - mRegisters[2] = edx; - continue; - } - - Match ebpMatch = mRegLineEBP.Match(cleanedLine); - if (ebpMatch.Success) - { - ulong ebp = ulong.Parse(ebpMatch.Groups["ebp"].ToString(), NumberStyles.HexNumber); - mRegisters[5] = ebp; - continue; - } - - Match eflagsMatch = mRegLineEFLAGS.Match(cleanedLine); - if (eflagsMatch.Success) - { - ulong eflags = ulong.Parse(eflagsMatch.Groups["eflags"].ToString(), NumberStyles.HexNumber); - mRegisters[9] = eflags; - if (RegisterChangeEvent != null) - RegisterChangeEvent(this, new RegisterChangeEventArgs(mRegisters)); - continue; - } - - Match sregMatch = mSregLine.Match(cleanedLine); - if (sregMatch.Success) - { - char []segmap = new char[] { 'C','D','E','F','G','S' }; - uint sreg = uint.Parse(sregMatch.Groups["seg"].ToString(), NumberStyles.HexNumber); - int findSeg; - for (findSeg = 0; findSeg < segmap.Length; findSeg++) - { - if (segmap[findSeg] == cleanedLine[0]) - { - mRegisters[10 + findSeg] = sreg; - if (segmap[findSeg] == 'S' && RegisterChangeEvent != null) - RegisterChangeEvent(this, new RegisterChangeEventArgs(mRegisters)); - break; - } - } - continue; - } - - Match pidHeadMatch = mProcListHeading.Match(cleanedLine); - if (pidHeadMatch.Success) - { - mReceivingThreads = false; - mReceivingProcs = true; - if (ProcessListEvent != null) - ProcessListEvent(this, new ProcessListEventArgs()); - continue; - } - else - { - Match pidEntryMatch = mProcListEntry.Match(cleanedLine); - if (pidEntryMatch.Success && mReceivingProcs) - { - if (ProcessListEvent != null) - ProcessListEvent(this, new ProcessListEventArgs(ulong.Parse(pidEntryMatch.Groups["pid"].ToString(), NumberStyles.HexNumber), pidEntryMatch.Groups["cur"].Length > 0, - pidEntryMatch.Groups["state"].ToString(), pidEntryMatch.Groups["name"].ToString())); - continue; - } - else - { - if ((mReceivingProcs || cleanedLine.Contains("No processes")) && ProcessListEvent != null) - { - ProcessListEvent(this, new ProcessListEventArgs(true)); - mReceivingProcs = false; - continue; - } - } - } - - Match tidHeadMatch = mThreadListHeading.Match(cleanedLine); - if (tidHeadMatch.Success) - { - mReceivingThreads = true; - mReceivingProcs = false; - if (ThreadListEvent != null) - ThreadListEvent(this, new ThreadListEventArgs()); - continue; - } - else - { - Match tidEntryMatch = mThreadListEntry.Match(cleanedLine); - if (tidEntryMatch.Success && mReceivingThreads) - { - if (ThreadListEvent != null) - ThreadListEvent(this, new ThreadListEventArgs(ulong.Parse(tidEntryMatch.Groups["tid"].ToString(), NumberStyles.HexNumber), tidEntryMatch.Groups["cur"].Length > 0, ulong.Parse(tidEntryMatch.Groups["eip"].ToString(), NumberStyles.HexNumber))); - continue; - } - else - { - if (mReceivingThreads && ThreadListEvent != null) - { - ThreadListEvent(this, new ThreadListEventArgs(true)); - mReceivingThreads = false; - continue; - } - } - } + if (TryParseMemory(cleanedLine)) continue; + if (TryParseModule(cleanedLine)) continue; + if (TryParseRegisters(cleanedLine)) continue; + if (TryParseSegmentRegisters(cleanedLine)) continue; + if (TryParsePID(cleanedLine)) continue; + if (TryParseTID(cleanedLine)) continue; + if (TryParseBreakpoint(cleanedLine)) continue; } catch (Exception) { /* Error line ... we'll ignore it for now */ } } @@ -307,40 +141,323 @@ namespace KDBGProtocol { if (mCommandBuffer.Count > 0) { - string firstCommand = mCommandBuffer[0]; - mCommandBuffer.RemoveAt(0); + string firstCommand = mCommandBuffer.Dequeue(); mConnection.Write(firstCommand + "\r"); } } } } + #endregion - public void SetBreakpoint(Breakpoint bp) + #region Individual parsing methods, each one looking for a specific item + private bool TryParseMemory(string cleanedLine) { + Match memoryMatch = mMemoryRowUpdate.Match(cleanedLine); + if (memoryMatch.Success) + { + string addrStr = memoryMatch.Groups["addr"].ToString(); + Match modOffset = mModuleOffset.Match(addrStr); + ulong updateAddress; + if (modOffset.Success) + { + string modname = modOffset.Groups["modname"].ToString(); + ulong offset = ulong.Parse(modOffset.Groups["offset"].ToString(), NumberStyles.HexNumber); + ulong modbase; + if (mModuleList.TryGetValue(modname.ToUpper(), out modbase)) + updateAddress = modbase + offset; + else + return true; // Couldn't resolve the address of the named module ... + } + else + { + updateAddress = ulong.Parse(addrStr, NumberStyles.HexNumber); + } + string[] memWords = memoryMatch.Groups["row"].ToString().Split(new char[] { ' ' }); + byte[] updateBytes = new byte[4 * memWords.Length]; + int ctr = 0; + foreach (string word in memWords) + { + if (word[0] == '?') + { + if (MemoryUpdateEvent != null) + MemoryUpdateEvent(this, new MemoryUpdateEventArgs((updateAddress & ~0xfffUL), null)); + } + else + { + int wordParsed = int.Parse(word, NumberStyles.HexNumber); + int curCtr = ctr; + for (ctr = curCtr; ctr < curCtr + 4; ctr++) + { + updateBytes[ctr] = (byte)(wordParsed & 0xff); + wordParsed >>= 8; + } + } + } + if (MemoryUpdateEvent != null) + MemoryUpdateEvent(this, new MemoryUpdateEventArgs(updateAddress, updateBytes)); + + return true; + } + return false; } - public void RemoveBreakpoint(Breakpoint bp) + private bool TryParseModule(string cleanedLine) { + Match moduleMatch = mModuleUpdate.Match(cleanedLine); + if (moduleMatch.Success) + { + ulong baseAddress = ulong.Parse(moduleMatch.Groups["base"].ToString(), NumberStyles.HexNumber); + uint moduleSize = uint.Parse(moduleMatch.Groups["size"].ToString(), NumberStyles.HexNumber); + string moduleName = moduleMatch.Groups["modname"].ToString(); + mModuleList[moduleName.ToUpper()] = baseAddress; + if (ModuleListEvent != null) + ModuleListEvent(this, new ModuleListEventArgs(moduleName, baseAddress)); + return true; + } + return false; } - public event ConsoleOutputEventHandler ConsoleOutputEvent; - public event RegisterChangeEventHandler RegisterChangeEvent; - public event SignalDeliveredEventHandler SignalDeliveredEvent; - public event RemoteGDBErrorHandler RemoteGDBError; - public event MemoryUpdateEventHandler MemoryUpdateEvent; - public event ModuleListEventHandler ModuleListEvent; - public event ProcessListEventHandler ProcessListEvent; - public event ThreadListEventHandler ThreadListEvent; - - public void WriteMemory(ulong address, byte[] buf) + private bool TryParseRegisters(string cleanedLine) { + Match csEipMatch = mRegLineCS_EIP.Match(cleanedLine); + if (csEipMatch.Success) + { + uint cs = uint.Parse(csEipMatch.Groups["cs"].ToString(), NumberStyles.HexNumber); + ulong eip = ulong.Parse(csEipMatch.Groups["eip"].ToString(), NumberStyles.HexNumber); + mRegisters[8] = eip; + mRegisters[10] = cs; + return true; + } + + Match ssEspMatch = mRegLineSS_ESP.Match(cleanedLine); + if (ssEspMatch.Success) + { + uint ss = uint.Parse(ssEspMatch.Groups["ss"].ToString(), NumberStyles.HexNumber); + ulong esp = ulong.Parse(ssEspMatch.Groups["esp"].ToString(), NumberStyles.HexNumber); + mRegisters[4] = esp; + mRegisters[15] = ss; + return true; + } + + Match eaxEbxMatch = mRegLineEAX_EBX.Match(cleanedLine); + if (eaxEbxMatch.Success) + { + ulong eax = ulong.Parse(eaxEbxMatch.Groups["eax"].ToString(), NumberStyles.HexNumber); + ulong ebx = ulong.Parse(eaxEbxMatch.Groups["ebx"].ToString(), NumberStyles.HexNumber); + mRegisters[0] = eax; + mRegisters[3] = ebx; + return true; + } + + Match ecxEdxMatch = mRegLineECX_EDX.Match(cleanedLine); + if (ecxEdxMatch.Success) + { + ulong ecx = ulong.Parse(ecxEdxMatch.Groups["ecx"].ToString(), NumberStyles.HexNumber); + ulong edx = ulong.Parse(ecxEdxMatch.Groups["edx"].ToString(), NumberStyles.HexNumber); + mRegisters[1] = ecx; + mRegisters[2] = edx; + return true; + } + + Match ebpMatch = mRegLineEBP.Match(cleanedLine); + if (ebpMatch.Success) + { + ulong ebp = ulong.Parse(ebpMatch.Groups["ebp"].ToString(), NumberStyles.HexNumber); + mRegisters[5] = ebp; + return true; + } + + Match eflagsMatch = mRegLineEFLAGS.Match(cleanedLine); + if (eflagsMatch.Success) + { + ulong eflags = ulong.Parse(eflagsMatch.Groups["eflags"].ToString(), NumberStyles.HexNumber); + mRegisters[9] = eflags; + if (RegisterChangeEvent != null) + RegisterChangeEvent(this, new RegisterChangeEventArgs(mRegisters)); + return true; + } + return false; } + private bool TryParseSegmentRegisters(string cleanedLine) + { + Match sregMatch = mSregLine.Match(cleanedLine); + if (sregMatch.Success) + { + char[] segmap = new char[] { 'C', 'D', 'E', 'F', 'G', 'S' }; + uint sreg = uint.Parse(sregMatch.Groups["seg"].ToString(), NumberStyles.HexNumber); + int findSeg; + for (findSeg = 0; findSeg < segmap.Length; findSeg++) + { + if (segmap[findSeg] == cleanedLine[0]) + { + mRegisters[10 + findSeg] = sreg; + if (segmap[findSeg] == 'S' && RegisterChangeEvent != null) + RegisterChangeEvent(this, new RegisterChangeEventArgs(mRegisters)); + break; + } + } + return true; + } + return false; + } + + private bool TryParsePID(string cleanedLine) + { + Match pidHeadMatch = mProcListHeading.Match(cleanedLine); + if (pidHeadMatch.Success) + { + mReceivingThreads = false; + mReceivingProcs = true; + if (ProcessListEvent != null) + ProcessListEvent(this, new ProcessListEventArgs()); + return true; + } + else + { + Match pidEntryMatch = mProcListEntry.Match(cleanedLine); + if (pidEntryMatch.Success && mReceivingProcs) + { + if (ProcessListEvent != null) + ProcessListEvent(this, new ProcessListEventArgs(ulong.Parse(pidEntryMatch.Groups["pid"].ToString(), NumberStyles.HexNumber), pidEntryMatch.Groups["cur"].Length > 0, + pidEntryMatch.Groups["state"].ToString(), pidEntryMatch.Groups["name"].ToString())); + return true; + } + else + { + if ((mReceivingProcs || cleanedLine.Contains("No processes")) && ProcessListEvent != null) + { + ProcessListEvent(this, new ProcessListEventArgs(true)); + mReceivingProcs = false; + return true; + } + } + } + return false; + } + + private bool TryParseTID(string cleanedLine) + { + Match tidHeadMatch = mThreadListHeading.Match(cleanedLine); + if (tidHeadMatch.Success) + { + mReceivingThreads = true; + mReceivingProcs = false; + if (ThreadListEvent != null) + ThreadListEvent(this, new ThreadListEventArgs()); + return true; + } + else + { + Match tidEntryMatch = mThreadListEntry.Match(cleanedLine); + if (tidEntryMatch.Success && mReceivingThreads) + { + if (ThreadListEvent != null) + ThreadListEvent(this, new ThreadListEventArgs(ulong.Parse(tidEntryMatch.Groups["tid"].ToString(), NumberStyles.HexNumber), tidEntryMatch.Groups["cur"].Length > 0, ulong.Parse(tidEntryMatch.Groups["eip"].ToString(), NumberStyles.HexNumber))); + return true; + } + else + { + if (mReceivingThreads && ThreadListEvent != null) + { + ThreadListEvent(this, new ThreadListEventArgs(true)); + mReceivingThreads = false; + return true; + } + } + } + return false; + } + + private bool TryParseBreakpoint(string cleanedLine) + { + if (cleanedLine.Equals("Breakpoints:")) // Start looking for breakpoint data + { + mReceivingBreakpoints = true; + return true; + } + else if (cleanedLine.Equals("No breakpoints.")) // Nothing present + { + mReceivingBreakpoints = false; + mBreakpoints.Clear(); + if (BreakpointChangeEvent != null) + BreakpointChangeEvent(this, new BreakpointChangeEventArgs(mBreakpoints)); + return true; + } + else if (mReceivingBreakpoints) + { + Match breakpointMatch = mBreakpointListEntry.Match(cleanedLine); + if (breakpointMatch.Success) + { + // Process breakpoint data + int id = int.Parse(breakpointMatch.Groups["id"].ToString(), NumberStyles.Integer); + Breakpoint bp = new Breakpoint(id); + + string type = breakpointMatch.Groups["type"].ToString(); + bp.Address = ulong.Parse(breakpointMatch.Groups["address"].ToString(), NumberStyles.HexNumber); + bp.Enabled = true; + bp.Condition = string.Empty; + + string rest = breakpointMatch.Groups["rest"].ToString(); + int cond_start = rest.LastIndexOf("IF"); + if (cond_start >= 0) // Separate the condition from the other properties + { + bp.Condition = rest.Substring(cond_start + 2).Trim(); + rest = rest.Substring(0, cond_start); + } + + string[] properties = rest.Split(' '); + foreach (string property in properties) + { + if (type.Equals("BPM")) + { + if (property.Equals("read")) + bp.BreakpointType = Breakpoint.BPType.ReadWatch; + else if (property.Equals("write")) + bp.BreakpointType = Breakpoint.BPType.WriteWatch; + else if (property.Equals("rdwr")) + bp.BreakpointType = Breakpoint.BPType.AccessWatch; + else if (property.Equals("exec")) + bp.BreakpointType = Breakpoint.BPType.Hardware; + else if (property.Equals("byte")) + bp.Length = 1; + else if (property.Equals("word")) + bp.Length = 2; + else if (property.Equals("dword")) + bp.Length = 4; + } + else if (type.Equals("BPX")) + { + bp.BreakpointType = Breakpoint.BPType.Software; + } + + // Common properties + if (property.Equals("disabled")) + bp.Enabled = false; + } + + mBreakpoints.Add(bp); + return true; + } + else // Something else; it implies that we've got all the breakpoint data + { + if (BreakpointChangeEvent != null) + BreakpointChangeEvent(this, new BreakpointChangeEventArgs(mBreakpoints)); + mBreakpoints.Clear(); + mReceivingBreakpoints = false; + return false; + } + } + return false; + } + #endregion + + #region Upstream commands public void QueueCommand(string command) { lock (mCommandBuffer) { - mCommandBuffer.Add(command); + mCommandBuffer.Enqueue(command); } } @@ -357,7 +474,9 @@ namespace KDBGProtocol { } - /* Immediately executed commands */ + #endregion + + #region Immediately executed commands public void Step() { Write("step"); @@ -389,12 +508,77 @@ namespace KDBGProtocol mFirstModuleUpdate = false; } + public void GetBreakpoints() + { + Write("bl"); + } + + public void SetBreakpoint(Breakpoint bp) + { + string length = "byte"; + if (bp.Length == 2) length = "word"; + else if (bp.Length == 4) length = "dword"; + + StringBuilder command = new StringBuilder(); + + switch (bp.BreakpointType) + { + case Breakpoint.BPType.Software: + command.AppendFormat("bpx 0x{0:x8}", bp.Address); + break; + case Breakpoint.BPType.Hardware: + command.AppendFormat("bpm x {0} 0x{1:x8}", "byte", bp.Address); + break; + case Breakpoint.BPType.ReadWatch: + command.AppendFormat("bpm r {0} 0x{1:x8}", length, bp.Address); + break; + case Breakpoint.BPType.WriteWatch: + command.AppendFormat("bpm w {0} 0x{1:x8}", length, bp.Address); + break; + case Breakpoint.BPType.AccessWatch: + command.AppendFormat("bpm rw {0} 0x{1:x8}", length, bp.Address); + break; + } + + if (!string.IsNullOrEmpty(bp.Condition)) + command.AppendFormat(" IF {0}", bp.Condition); + + Write(command.ToString()); + GetBreakpoints(); + } + + public void RemoveBreakpoint(int id) + { + if (id >= 0) + Write("bc " + id); + GetBreakpoints(); + } + + public void EnableBreakpoint(int id) + { + if (id >= 0) + Write("be " + id); + GetBreakpoints(); + } + + public void DisableBreakpoint(int id) + { + if (id >= 0) + Write("bd " + id); + GetBreakpoints(); + } + + public void WriteMemory(ulong address, byte[] buf) + { + } + public void GetMemoryUpdate(ulong address, int len) { Write(string.Format("x 0x{0:X} L {1}", address, len)); } + #endregion - /* Commands placed into the cmd queue */ + #region Commands placed into the command queue public void GetProcesses() { QueueCommand("proc list"); @@ -428,5 +612,7 @@ namespace KDBGProtocol { QueueCommand("mod"); } + + #endregion } } diff --git a/RosDBG/Dockable Objects/BreakpointWindow.Designer.cs b/RosDBG/Dockable Objects/BreakpointWindow.Designer.cs new file mode 100644 index 0000000..0d31a73 --- /dev/null +++ b/RosDBG/Dockable Objects/BreakpointWindow.Designer.cs @@ -0,0 +1,200 @@ +namespace RosDBG +{ + partial class BreakpointWindow + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle1 = new System.Windows.Forms.DataGridViewCellStyle(); + System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle2 = new System.Windows.Forms.DataGridViewCellStyle(); + System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle3 = new System.Windows.Forms.DataGridViewCellStyle(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(BreakpointWindow)); + this.grid = new System.Windows.Forms.DataGridView(); + this.columnEnabled = new System.Windows.Forms.DataGridViewCheckBoxColumn(); + this.columnID = new System.Windows.Forms.DataGridViewTextBoxColumn(); + this.columnAddress = new System.Windows.Forms.DataGridViewTextBoxColumn(); + this.columnType = new System.Windows.Forms.DataGridViewTextBoxColumn(); + this.columnCondition = new System.Windows.Forms.DataGridViewTextBoxColumn(); + this.breakpointBindingSource = new System.Windows.Forms.BindingSource(this.components); + this.btnAddBreakpoint = new System.Windows.Forms.Button(); + this.btnDeleteBreakpoint = new System.Windows.Forms.Button(); + this.btnEditBreakpoint = new System.Windows.Forms.Button(); + ((System.ComponentModel.ISupportInitialize)(this.grid)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.breakpointBindingSource)).BeginInit(); + this.SuspendLayout(); + // + // grid + // + this.grid.AllowUserToAddRows = false; + this.grid.AllowUserToDeleteRows = false; + this.grid.AllowUserToResizeRows = false; + this.grid.AutoGenerateColumns = false; + this.grid.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.AllCellsExceptHeader; + this.grid.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; + this.grid.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] { + this.columnEnabled, + this.columnID, + this.columnAddress, + this.columnType, + this.columnCondition}); + this.grid.DataSource = this.breakpointBindingSource; + this.grid.Dock = System.Windows.Forms.DockStyle.Top; + this.grid.Location = new System.Drawing.Point(0, 0); + this.grid.MultiSelect = false; + this.grid.Name = "grid"; + this.grid.RowHeadersVisible = false; + this.grid.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect; + this.grid.Size = new System.Drawing.Size(318, 228); + this.grid.StandardTab = true; + this.grid.TabIndex = 1; + this.grid.CellDoubleClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.grid_CellDoubleClick); + this.grid.CellFormatting += new System.Windows.Forms.DataGridViewCellFormattingEventHandler(this.grid_CellFormatting); + this.grid.CellValueChanged += new System.Windows.Forms.DataGridViewCellEventHandler(this.grid_CellValueChanged); + this.grid.CurrentCellDirtyStateChanged += new System.EventHandler(this.grid_CurrentCellDirtyStateChanged); + // + // columnEnabled + // + this.columnEnabled.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.AllCellsExceptHeader; + this.columnEnabled.DataPropertyName = "Enabled"; + this.columnEnabled.HeaderText = ""; + this.columnEnabled.Name = "columnEnabled"; + this.columnEnabled.Width = 5; + // + // columnID + // + this.columnID.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.AllCellsExceptHeader; + this.columnID.DataPropertyName = "ID"; + dataGridViewCellStyle1.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleRight; + this.columnID.DefaultCellStyle = dataGridViewCellStyle1; + this.columnID.HeaderText = "ID"; + this.columnID.Name = "columnID"; + this.columnID.ReadOnly = true; + this.columnID.Width = 5; + // + // columnAddress + // + this.columnAddress.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.AllCells; + this.columnAddress.DataPropertyName = "Address"; + dataGridViewCellStyle2.Format = "X8"; + this.columnAddress.DefaultCellStyle = dataGridViewCellStyle2; + this.columnAddress.HeaderText = "Address"; + this.columnAddress.Name = "columnAddress"; + this.columnAddress.ReadOnly = true; + this.columnAddress.Width = 70; + // + // columnType + // + this.columnType.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.AllCells; + this.columnType.DataPropertyName = "BreakpointType"; + dataGridViewCellStyle3.NullValue = null; + this.columnType.DefaultCellStyle = dataGridViewCellStyle3; + this.columnType.HeaderText = "Type"; + this.columnType.Name = "columnType"; + this.columnType.ReadOnly = true; + this.columnType.Width = 56; + // + // columnCondition + // + this.columnCondition.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.AllCells; + this.columnCondition.DataPropertyName = "Condition"; + this.columnCondition.HeaderText = "Condition"; + this.columnCondition.Name = "columnCondition"; + this.columnCondition.ReadOnly = true; + this.columnCondition.Width = 76; + // + // breakpointBindingSource + // + this.breakpointBindingSource.DataSource = typeof(DebugProtocol.Breakpoint); + // + // btnAddBreakpoint + // + this.btnAddBreakpoint.Enabled = false; + this.btnAddBreakpoint.Location = new System.Drawing.Point(12, 234); + this.btnAddBreakpoint.Name = "btnAddBreakpoint"; + this.btnAddBreakpoint.Size = new System.Drawing.Size(48, 23); + this.btnAddBreakpoint.TabIndex = 2; + this.btnAddBreakpoint.Text = "&Add..."; + this.btnAddBreakpoint.UseVisualStyleBackColor = true; + this.btnAddBreakpoint.Click += new System.EventHandler(this.btnAddBreakpoint_Click); + // + // btnDeleteBreakpoint + // + this.btnDeleteBreakpoint.Enabled = false; + this.btnDeleteBreakpoint.Location = new System.Drawing.Point(66, 234); + this.btnDeleteBreakpoint.Name = "btnDeleteBreakpoint"; + this.btnDeleteBreakpoint.Size = new System.Drawing.Size(48, 23); + this.btnDeleteBreakpoint.TabIndex = 4; + this.btnDeleteBreakpoint.Text = "&Delete"; + this.btnDeleteBreakpoint.UseVisualStyleBackColor = true; + this.btnDeleteBreakpoint.Click += new System.EventHandler(this.btnDelete_Click); + // + // btnEditBreakpoint + // + this.btnEditBreakpoint.Enabled = false; + this.btnEditBreakpoint.Location = new System.Drawing.Point(120, 234); + this.btnEditBreakpoint.Name = "btnEditBreakpoint"; + this.btnEditBreakpoint.Size = new System.Drawing.Size(48, 23); + this.btnEditBreakpoint.TabIndex = 5; + this.btnEditBreakpoint.Text = "&Edit..."; + this.btnEditBreakpoint.UseVisualStyleBackColor = true; + this.btnEditBreakpoint.Click += new System.EventHandler(this.btnEdit_Click); + // + // BreakpointWindow + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(318, 262); + this.Controls.Add(this.btnEditBreakpoint); + this.Controls.Add(this.btnDeleteBreakpoint); + this.Controls.Add(this.btnAddBreakpoint); + this.Controls.Add(this.grid); + this.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.HideOnClose = true; + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.Name = "BreakpointWindow"; + this.Text = "Breakpoints"; + ((System.ComponentModel.ISupportInitialize)(this.grid)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.breakpointBindingSource)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.DataGridView grid; + private System.Windows.Forms.Button btnAddBreakpoint; + private System.Windows.Forms.BindingSource breakpointBindingSource; + private System.Windows.Forms.Button btnDeleteBreakpoint; + private System.Windows.Forms.Button btnEditBreakpoint; + private System.Windows.Forms.DataGridViewCheckBoxColumn columnEnabled; + private System.Windows.Forms.DataGridViewTextBoxColumn columnID; + private System.Windows.Forms.DataGridViewTextBoxColumn columnAddress; + private System.Windows.Forms.DataGridViewTextBoxColumn columnType; + private System.Windows.Forms.DataGridViewTextBoxColumn columnCondition; + + } +} diff --git a/RosDBG/Dockable Objects/BreakpointWindow.cs b/RosDBG/Dockable Objects/BreakpointWindow.cs new file mode 100644 index 0000000..f40f2ce --- /dev/null +++ b/RosDBG/Dockable Objects/BreakpointWindow.cs @@ -0,0 +1,193 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.Data; +using System.Linq; +using System.Text; +using System.Windows.Forms; +using System.Globalization; +using System.Threading; +using DebugProtocol; +using WeifenLuo.WinFormsUI.Docking; + +namespace RosDBG +{ + [DebugControl] + public partial class BreakpointWindow : ToolWindow, IUseDebugConnection + { + DebugConnection mConnection; + bool mRunning = true; + ulong last_EIP; + IList mBreakpoints; + + public BreakpointWindow() + { + InitializeComponent(); + grid.DataSource = mBreakpoints; + } + + public void SetDebugConnection(DebugConnection conn) + { + mConnection = conn; + conn.DebugRunningChangeEvent += DebugRunningChangeEvent; + conn.DebugRegisterChangeEvent += new DebugRegisterChangeEventHandler(DebugRegisterChangeEvent); + conn.DebugBreakpointChangeEvent += new DebugBreakpointChangeEventHandler(DebugBreakpointChangeEvent); + mRunning = conn.Running; + if (!mConnection.Running) + mConnection.Debugger.GetBreakpoints(); + } + + #region Debugger events + void DebugRegisterChangeEvent(object sender, DebugRegisterChangeEventArgs args) + { + last_EIP = args.Registers.Eip; + } + + void DebugBreakpointChangeEvent(object sender, DebugBreakpointChangeEventArgs args) + { + mBreakpoints = args.Breakpoints; + RefreshView(); + } + + void DebugRunningChangeEvent(object sender, DebugRunningChangeEventArgs args) + { + this.UIThread(delegate + { + mRunning = args.Running; + grid.Enabled = !mRunning; + btnAddBreakpoint.Enabled = !mRunning; + btnDeleteBreakpoint.Enabled = !mRunning; + btnEditBreakpoint.Enabled = !mRunning; + }); + } + #endregion + + #region Utility methods + private void RefreshView() + { + this.UIThread(delegate + { + if (!mRunning) + { + // Track selected row + DataGridViewSelectedRowCollection sel_rows = grid.SelectedRows; + int sel_row = (sel_rows.Count >= 1 ? sel_rows[0].Index : 0); + + grid.DataSource = null; + grid.DataSource = mBreakpoints; + grid.Refresh(); + + // Restore selected row, if possible + if (sel_row < grid.RowCount) grid.Rows[sel_row].Selected = true; + } + }); + } + + private string GetLengthString(int length) + { + switch (length) + { + case 1: return "byte"; + case 2: return "word"; + case 4: return "dword"; + default: return ""; + } + } + + private void EditBreakpoint(Breakpoint storedBreakpoint) + { + using (EditBreakpointDialog dialog = new EditBreakpointDialog(storedBreakpoint)) + { + dialog.ShowDialog(); + if (dialog.DialogResult == DialogResult.OK && dialog.Breakpoint != null) + { + Breakpoint bp = dialog.Breakpoint; + if (storedBreakpoint.ID >= 0) + mConnection.Debugger.RemoveBreakpoint(storedBreakpoint.ID); + mConnection.Debugger.SetBreakpoint(bp); + } + } + } + + #endregion + + #region User interface event handlers + + // See the note in the Remarks section at the MSDN entry for DataGridViewCheckboxColumn + private void grid_CurrentCellDirtyStateChanged(object sender, EventArgs e) + { + if (grid.CurrentCell is DataGridViewCheckBoxCell) + { + grid.CommitEdit(DataGridViewDataErrorContexts.Commit); + } + } + + private void grid_CellValueChanged(object sender, DataGridViewCellEventArgs e) + { + if (e.RowIndex >= 0 && e.RowIndex < grid.Rows.Count && e.ColumnIndex == this.columnEnabled.Index) + { + DataGridViewCheckBoxCell cell = grid[e.ColumnIndex, e.RowIndex] as DataGridViewCheckBoxCell; + if (cell != null && !mConnection.Running) + { + Breakpoint bp = grid.Rows[e.RowIndex].DataBoundItem as Breakpoint; + if ((bool)cell.Value) + mConnection.Debugger.EnableBreakpoint(bp.ID); + else + mConnection.Debugger.DisableBreakpoint(bp.ID); + } + } + } + + private void grid_CellDoubleClick(object sender, DataGridViewCellEventArgs e) + { + if (e.RowIndex >= 0 && e.RowIndex < grid.Rows.Count && e.RowIndex < mBreakpoints.Count) + { + Breakpoint storedBreakpoint = mBreakpoints[e.RowIndex]; + EditBreakpoint(storedBreakpoint); + } + } + + private void grid_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e) + { + Breakpoint bp = grid.Rows[e.RowIndex].DataBoundItem as Breakpoint; + if (e.ColumnIndex == columnType.Index) + { + switch (bp.BreakpointType) + { + case Breakpoint.BPType.Software: e.Value = "execute"; break; + case Breakpoint.BPType.Hardware: e.Value = "exec " + GetLengthString(bp.Length); break; + case Breakpoint.BPType.ReadWatch: e.Value = "read " +GetLengthString(bp.Length); break; + case Breakpoint.BPType.WriteWatch: e.Value = "write " + GetLengthString(bp.Length); break; + case Breakpoint.BPType.AccessWatch: e.Value = "r/w " + GetLengthString(bp.Length); break; + default: e.Value = "?"; break; + } + } + } + + private void btnAddBreakpoint_Click(object sender, EventArgs e) + { + Breakpoint orig_bp = new Breakpoint(-1, Breakpoint.BPType.Software, last_EIP, 1, ""); + EditBreakpoint(orig_bp); + } + + private void btnDelete_Click(object sender, EventArgs e) + { + if (grid.SelectedRows.Count >= 1) + { + Breakpoint bp = grid.SelectedRows[0].DataBoundItem as Breakpoint; + mConnection.Debugger.RemoveBreakpoint(bp.ID); + } + } + + private void btnEdit_Click(object sender, EventArgs e) + { + if (grid.SelectedRows.Count >= 1) + { + Breakpoint storedBreakpoint = grid.SelectedRows[0].DataBoundItem as Breakpoint; + EditBreakpoint(storedBreakpoint); + } + } + #endregion + } +} diff --git a/RosDBG/Dockable Objects/BreakpointWindow.resx b/RosDBG/Dockable Objects/BreakpointWindow.resx new file mode 100644 index 0000000..6b41e3c --- /dev/null +++ b/RosDBG/Dockable Objects/BreakpointWindow.resx @@ -0,0 +1,152 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + + + AAABAAEAEBAAAAAAAABoBQAAFgAAACgAAAAQAAAAIAAAAAEACAAAAAAAQAEAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA////AISKiADDyscAoKOiAOzu7gC0urgAz9fTAJOZlwC+wMAAio+NALm/vQCHi4kAhYqIAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANDQ0AAAAAAAAAAAAADQ0A + DQUNAA0NAAAAAAAADQUJDQQHBA0JBQ0AAAAAAA0JBwcHBwcHBwkNAAAAAAAADQUGCggCAwcNAAAAAAAN + DQQHCgAAAAIHBA0NAAAADQUHBwgAAAAIBwcFDQAAAA0NBAcCAAAADAcEDQ0AAAAAAA0HBgIIAgsHDQAA + AAAAAA0JBwcHBwcHBwkNAAAAAAANBQkNBAcEDQkFDQAAAAAAAA0NAA0FDQANDQAAAAAAAAAAAAANDQ0A + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//AAD//wAA/H8AAORPAADABwAAwAcAAOAPAACDgwAAg4MAAIOD + AADgDwAAwAcAAMAHAADkTwAA/H8AAP//AAA= + + + diff --git a/RosDBG/EditBreakpointDialog.Designer.cs b/RosDBG/EditBreakpointDialog.Designer.cs new file mode 100644 index 0000000..7c5461a --- /dev/null +++ b/RosDBG/EditBreakpointDialog.Designer.cs @@ -0,0 +1,331 @@ +namespace RosDBG +{ + partial class EditBreakpointDialog + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.splitContainer1 = new System.Windows.Forms.SplitContainer(); + this.txtCondition = new System.Windows.Forms.TextBox(); + this.label2 = new System.Windows.Forms.Label(); + this.txtAddress = new System.Windows.Forms.TextBox(); + this.gbxScope = new System.Windows.Forms.GroupBox(); + this.radDword = new System.Windows.Forms.RadioButton(); + this.radWord = new System.Windows.Forms.RadioButton(); + this.radByte = new System.Windows.Forms.RadioButton(); + this.gbxTrigger = new System.Windows.Forms.GroupBox(); + this.radExecute = new System.Windows.Forms.RadioButton(); + this.radReadWrite = new System.Windows.Forms.RadioButton(); + this.radWrite = new System.Windows.Forms.RadioButton(); + this.radRead = new System.Windows.Forms.RadioButton(); + this.label1 = new System.Windows.Forms.Label(); + this.gbxType = new System.Windows.Forms.GroupBox(); + this.radBPM = new System.Windows.Forms.RadioButton(); + this.radBPX = new System.Windows.Forms.RadioButton(); + this.btnOK = new System.Windows.Forms.Button(); + this.btnCancel = new System.Windows.Forms.Button(); + this.splitContainer1.Panel1.SuspendLayout(); + this.splitContainer1.Panel2.SuspendLayout(); + this.splitContainer1.SuspendLayout(); + this.gbxScope.SuspendLayout(); + this.gbxTrigger.SuspendLayout(); + this.gbxType.SuspendLayout(); + this.SuspendLayout(); + // + // splitContainer1 + // + this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill; + this.splitContainer1.FixedPanel = System.Windows.Forms.FixedPanel.Panel2; + this.splitContainer1.IsSplitterFixed = true; + this.splitContainer1.Location = new System.Drawing.Point(0, 0); + this.splitContainer1.Name = "splitContainer1"; + this.splitContainer1.Orientation = System.Windows.Forms.Orientation.Horizontal; + // + // splitContainer1.Panel1 + // + this.splitContainer1.Panel1.Controls.Add(this.txtCondition); + this.splitContainer1.Panel1.Controls.Add(this.label2); + this.splitContainer1.Panel1.Controls.Add(this.txtAddress); + this.splitContainer1.Panel1.Controls.Add(this.gbxScope); + this.splitContainer1.Panel1.Controls.Add(this.gbxTrigger); + this.splitContainer1.Panel1.Controls.Add(this.label1); + this.splitContainer1.Panel1.Controls.Add(this.gbxType); + // + // splitContainer1.Panel2 + // + this.splitContainer1.Panel2.Controls.Add(this.btnOK); + this.splitContainer1.Panel2.Controls.Add(this.btnCancel); + this.splitContainer1.Size = new System.Drawing.Size(330, 200); + this.splitContainer1.SplitterDistance = 167; + this.splitContainer1.TabIndex = 0; + // + // txtCondition + // + this.txtCondition.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.txtCondition.Location = new System.Drawing.Point(82, 135); + this.txtCondition.Margin = new System.Windows.Forms.Padding(3, 3, 6, 3); + this.txtCondition.Name = "txtCondition"; + this.txtCondition.Size = new System.Drawing.Size(239, 20); + this.txtCondition.TabIndex = 5; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(18, 138); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(54, 13); + this.label2.TabIndex = 7; + this.label2.Text = "Condition:"; + // + // txtAddress + // + this.txtAddress.Location = new System.Drawing.Point(81, 99); + this.txtAddress.Margin = new System.Windows.Forms.Padding(3, 3, 6, 3); + this.txtAddress.MaxLength = 8; + this.txtAddress.Name = "txtAddress"; + this.txtAddress.Size = new System.Drawing.Size(58, 20); + this.txtAddress.TabIndex = 1; + this.txtAddress.Validating += new System.ComponentModel.CancelEventHandler(this.txtAddress_Validating); + // + // gbxScope + // + this.gbxScope.Controls.Add(this.radDword); + this.gbxScope.Controls.Add(this.radWord); + this.gbxScope.Controls.Add(this.radByte); + this.gbxScope.Location = new System.Drawing.Point(251, 12); + this.gbxScope.Name = "gbxScope"; + this.gbxScope.Size = new System.Drawing.Size(70, 117); + this.gbxScope.TabIndex = 4; + this.gbxScope.TabStop = false; + this.gbxScope.Text = "Scope"; + // + // radDword + // + this.radDword.AutoSize = true; + this.radDword.Location = new System.Drawing.Point(6, 65); + this.radDword.Name = "radDword"; + this.radDword.Size = new System.Drawing.Size(59, 17); + this.radDword.TabIndex = 2; + this.radDword.Text = "DWord"; + this.radDword.UseVisualStyleBackColor = true; + // + // radWord + // + this.radWord.AutoSize = true; + this.radWord.Location = new System.Drawing.Point(6, 42); + this.radWord.Name = "radWord"; + this.radWord.Size = new System.Drawing.Size(51, 17); + this.radWord.TabIndex = 1; + this.radWord.Text = "Word"; + this.radWord.UseVisualStyleBackColor = true; + // + // radByte + // + this.radByte.AutoSize = true; + this.radByte.Checked = true; + this.radByte.Location = new System.Drawing.Point(6, 19); + this.radByte.Name = "radByte"; + this.radByte.Size = new System.Drawing.Size(46, 17); + this.radByte.TabIndex = 0; + this.radByte.TabStop = true; + this.radByte.Text = "Byte"; + this.radByte.UseVisualStyleBackColor = true; + // + // gbxTrigger + // + this.gbxTrigger.Controls.Add(this.radExecute); + this.gbxTrigger.Controls.Add(this.radReadWrite); + this.gbxTrigger.Controls.Add(this.radWrite); + this.gbxTrigger.Controls.Add(this.radRead); + this.gbxTrigger.Location = new System.Drawing.Point(148, 12); + this.gbxTrigger.Name = "gbxTrigger"; + this.gbxTrigger.Size = new System.Drawing.Size(97, 117); + this.gbxTrigger.TabIndex = 3; + this.gbxTrigger.TabStop = false; + this.gbxTrigger.Text = "Trigger"; + // + // radExecute + // + this.radExecute.AutoSize = true; + this.radExecute.Location = new System.Drawing.Point(6, 88); + this.radExecute.Name = "radExecute"; + this.radExecute.Size = new System.Drawing.Size(72, 17); + this.radExecute.TabIndex = 3; + this.radExecute.Text = "Execution"; + this.radExecute.UseVisualStyleBackColor = true; + // + // radReadWrite + // + this.radReadWrite.AutoSize = true; + this.radReadWrite.Location = new System.Drawing.Point(6, 65); + this.radReadWrite.Name = "radReadWrite"; + this.radReadWrite.Size = new System.Drawing.Size(81, 17); + this.radReadWrite.TabIndex = 2; + this.radReadWrite.Text = "Read/Write"; + this.radReadWrite.UseVisualStyleBackColor = true; + // + // radWrite + // + this.radWrite.AutoSize = true; + this.radWrite.Location = new System.Drawing.Point(6, 42); + this.radWrite.Name = "radWrite"; + this.radWrite.Size = new System.Drawing.Size(50, 17); + this.radWrite.TabIndex = 1; + this.radWrite.Text = "Write"; + this.radWrite.UseVisualStyleBackColor = true; + // + // radRead + // + this.radRead.AutoSize = true; + this.radRead.Checked = true; + this.radRead.Location = new System.Drawing.Point(6, 19); + this.radRead.Name = "radRead"; + this.radRead.Size = new System.Drawing.Size(51, 17); + this.radRead.TabIndex = 0; + this.radRead.TabStop = true; + this.radRead.Text = "Read"; + this.radRead.UseVisualStyleBackColor = true; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(18, 102); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(48, 13); + this.label1.TabIndex = 9; + this.label1.Text = "Address:"; + // + // gbxType + // + this.gbxType.Controls.Add(this.radBPM); + this.gbxType.Controls.Add(this.radBPX); + this.gbxType.Location = new System.Drawing.Point(12, 12); + this.gbxType.Name = "gbxType"; + this.gbxType.Size = new System.Drawing.Size(130, 73); + this.gbxType.TabIndex = 2; + this.gbxType.TabStop = false; + this.gbxType.Text = "Type"; + // + // radBPM + // + this.radBPM.AutoSize = true; + this.radBPM.Location = new System.Drawing.Point(9, 44); + this.radBPM.Name = "radBPM"; + this.radBPM.Size = new System.Drawing.Size(103, 17); + this.radBPM.TabIndex = 1; + this.radBPM.Text = "Hardware (BPM)"; + this.radBPM.UseVisualStyleBackColor = true; + // + // radBPX + // + this.radBPX.AutoSize = true; + this.radBPX.Checked = true; + this.radBPX.Location = new System.Drawing.Point(9, 21); + this.radBPX.Name = "radBPX"; + this.radBPX.Size = new System.Drawing.Size(97, 17); + this.radBPX.TabIndex = 0; + this.radBPX.TabStop = true; + this.radBPX.Text = "Software (BPX)"; + this.radBPX.UseVisualStyleBackColor = true; + // + // btnOK + // + this.btnOK.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.btnOK.Location = new System.Drawing.Point(171, 3); + this.btnOK.Name = "btnOK"; + this.btnOK.Size = new System.Drawing.Size(75, 23); + this.btnOK.TabIndex = 6; + this.btnOK.Text = "OK"; + this.btnOK.UseVisualStyleBackColor = true; + this.btnOK.Click += new System.EventHandler(this.btnOK_Click); + // + // btnCancel + // + this.btnCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.btnCancel.Location = new System.Drawing.Point(252, 3); + this.btnCancel.Name = "btnCancel"; + this.btnCancel.Size = new System.Drawing.Size(75, 23); + this.btnCancel.TabIndex = 7; + this.btnCancel.Text = "Cancel"; + this.btnCancel.UseVisualStyleBackColor = true; + this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click); + // + // EditBreakpoint + // + this.AcceptButton = this.btnOK; + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.btnCancel; + this.ClientSize = new System.Drawing.Size(330, 200); + this.Controls.Add(this.splitContainer1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "EditBreakpoint"; + this.ShowInTaskbar = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "Add or edit breakpoint"; + this.Activated += new System.EventHandler(this.EditBreakpoint_Activated); + this.splitContainer1.Panel1.ResumeLayout(false); + this.splitContainer1.Panel1.PerformLayout(); + this.splitContainer1.Panel2.ResumeLayout(false); + this.splitContainer1.ResumeLayout(false); + this.gbxScope.ResumeLayout(false); + this.gbxScope.PerformLayout(); + this.gbxTrigger.ResumeLayout(false); + this.gbxTrigger.PerformLayout(); + this.gbxType.ResumeLayout(false); + this.gbxType.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.SplitContainer splitContainer1; + private System.Windows.Forms.Button btnOK; + private System.Windows.Forms.Button btnCancel; + private System.Windows.Forms.TextBox txtAddress; + private System.Windows.Forms.GroupBox gbxScope; + private System.Windows.Forms.RadioButton radDword; + private System.Windows.Forms.RadioButton radWord; + private System.Windows.Forms.RadioButton radByte; + private System.Windows.Forms.GroupBox gbxTrigger; + private System.Windows.Forms.RadioButton radExecute; + private System.Windows.Forms.RadioButton radReadWrite; + private System.Windows.Forms.RadioButton radWrite; + private System.Windows.Forms.RadioButton radRead; + private System.Windows.Forms.GroupBox gbxType; + private System.Windows.Forms.RadioButton radBPM; + private System.Windows.Forms.RadioButton radBPX; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.TextBox txtCondition; + + } +} diff --git a/RosDBG/EditBreakpointDialog.cs b/RosDBG/EditBreakpointDialog.cs new file mode 100644 index 0000000..cdede0b --- /dev/null +++ b/RosDBG/EditBreakpointDialog.cs @@ -0,0 +1,179 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Configuration; +using System.Windows.Forms; +using System.Drawing.Design; +using System.IO; +using System.IO.Ports; +using System.Globalization; +using DebugProtocol; + +namespace RosDBG +{ + /// + /// Use this form as a dialog to edit beakpoint data. DialogResult will be OK or Cancel; + /// if OK, you can get the chosen data from the Breakpoint property. + /// + public partial class EditBreakpointDialog : Form + { + /// + /// Chosen breakpoint data if OK pressed, or null if Cancel pressed + /// + public Breakpoint Breakpoint { get; private set; } + + /// + /// Constructor + /// + /// Breakpoint data to prefill in the form (skipped if null) + public EditBreakpointDialog(Breakpoint breakpoint) + { + InitializeComponent(); + Breakpoint = breakpoint; + + radBPX.CheckedChanged += new EventHandler(radioButtonChanged); + radBPM.CheckedChanged += new EventHandler(radioButtonChanged); + radByte.CheckedChanged += new EventHandler(radioButtonChanged); + radWord.CheckedChanged += new EventHandler(radioButtonChanged); + radDword.CheckedChanged += new EventHandler(radioButtonChanged); + radRead.CheckedChanged += new EventHandler(radioButtonChanged); + radWrite.CheckedChanged += new EventHandler(radioButtonChanged); + radReadWrite.CheckedChanged += new EventHandler(radioButtonChanged); + radExecute.CheckedChanged += new EventHandler(radioButtonChanged); + + // Prefill the form with the data from the given breakpoint + if (breakpoint != null) + { + switch (breakpoint.BreakpointType) + { + case DebugProtocol.Breakpoint.BPType.Software: + radBPX.Select(); + break; + case DebugProtocol.Breakpoint.BPType.Hardware: + radBPM.Select(); + radExecute.Select(); + break; + case DebugProtocol.Breakpoint.BPType.ReadWatch: + radBPM.Select(); + radRead.Select(); + break; + case DebugProtocol.Breakpoint.BPType.WriteWatch: + radBPM.Select(); + radWrite.Select(); + break; + case DebugProtocol.Breakpoint.BPType.AccessWatch: + radBPM.Select(); + radReadWrite.Select(); + break; + } + + if (breakpoint.BreakpointType != DebugProtocol.Breakpoint.BPType.Software) + { + switch (breakpoint.Length) + { + case 1: radByte.Select(); break; + case 2: radWord.Select(); break; + case 4: radDword.Select(); break; + } + } + + txtAddress.Text = breakpoint.Address.ToString("X8"); + txtCondition.Text = breakpoint.Condition; + } + + } + + #region Event handlers + private void EditBreakpoint_Activated(object sender, EventArgs e) + { + ValidateForm(); + txtAddress.Focus(); + txtAddress.SelectAll(); + } + + private void radioButtonChanged(object sender, EventArgs e) + { + RadioButton rb = sender as RadioButton; + if (rb != null && rb.Checked) + ValidateForm(); + } + + private void btnCancel_Click(object sender, EventArgs e) + { + Breakpoint = null; + DialogResult = DialogResult.Cancel; + Close(); + } + + private void btnOK_Click(object sender, EventArgs e) + { + try + { + if (Breakpoint == null) + Breakpoint = new Breakpoint(-1); + + Breakpoint.Enabled = false; + Breakpoint.Address = ulong.Parse(txtAddress.Text, NumberStyles.HexNumber); + Breakpoint.Condition = txtCondition.Text; + + if (radBPX.Checked) + { + Breakpoint.BreakpointType = DebugProtocol.Breakpoint.BPType.Software; + Breakpoint.Length = 1; + } + else if (radBPM.Checked) + { + if (radRead.Checked) + Breakpoint.BreakpointType = DebugProtocol.Breakpoint.BPType.ReadWatch; + else if (radWrite.Checked) + Breakpoint.BreakpointType = DebugProtocol.Breakpoint.BPType.WriteWatch; + else if (radReadWrite.Checked) + Breakpoint.BreakpointType = DebugProtocol.Breakpoint.BPType.AccessWatch; + else if (radExecute.Checked) + Breakpoint.BreakpointType = DebugProtocol.Breakpoint.BPType.Hardware; + + if (radByte.Checked) Breakpoint.Length = 1; + else if (radWord.Checked) Breakpoint.Length = 2; + else if (radDword.Checked) Breakpoint.Length = 4; + } + + DialogResult = DialogResult.OK; + Close(); + } + catch (Exception) { } // If something goes wrong, don't close + } + + private void txtAddress_Validating(object sender, CancelEventArgs e) + { + ulong answer; + if (ulong.TryParse(txtAddress.Text, NumberStyles.HexNumber, null, out answer)) + { + e.Cancel = false; + txtAddress.BackColor = SystemColors.Window; + } + else + { + e.Cancel = true; + txtAddress.BackColor = Color.Yellow; + } + } + + #endregion + + #region Utility methods + private void ValidateForm() + { + bool addressFocused = txtAddress.Focused; + gbxScope.Enabled = radBPM.Checked; + gbxTrigger.Enabled = radBPM.Checked; + if (radExecute.Checked) radByte.Select(); + if (addressFocused) txtAddress.Focus(); + } + #endregion + } +} diff --git a/RosDBG/EditBreakpointDialog.resx b/RosDBG/EditBreakpointDialog.resx new file mode 100644 index 0000000..11113e4 --- /dev/null +++ b/RosDBG/EditBreakpointDialog.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + diff --git a/RosDBG/MainWindow.cs b/RosDBG/MainWindow.cs index 6b2157c..73b5408 100644 --- a/RosDBG/MainWindow.cs +++ b/RosDBG/MainWindow.cs @@ -28,7 +28,8 @@ namespace RosDBG private Locals m_Locals = new Locals(); private MemoryWindow m_MemoryWindow = new MemoryWindow(); private ProcThread m_ProcThread = new ProcThread(); - private Modules m_Modules = new Modules(); + private Modules m_Modules = new Modules(); + private BreakpointWindow m_Breakpoints = new BreakpointWindow(); private bool mRunning; private DebugConnection.Mode mConnectionMode; @@ -60,9 +61,12 @@ namespace RosDBG RegisterControl(m_MemoryWindow); RegisterControl(m_ProcThread); RegisterControl(m_Modules); + RegisterControl(m_Breakpoints); m_Locals.Show(dockPanel, DockState.DockRight); m_RegView.Show(dockPanel, DockState.DockRight); + m_Breakpoints.Show(dockPanel, DockState.DockRight); + m_RegView.Activate(); m_BackTrace.Show(dockPanel, DockState.DockBottom); m_RawTraffic.Show(dockPanel); m_Modules.Show(dockPanel); diff --git a/RosDBG/Properties/AssemblyInfo.cs b/RosDBG/Properties/AssemblyInfo.cs index 752289f..ce2e795 100644 --- a/RosDBG/Properties/AssemblyInfo.cs +++ b/RosDBG/Properties/AssemblyInfo.cs @@ -39,5 +39,5 @@ using System.Runtime.InteropServices; // will be increased as well. MSI installers must not be generated with the same Build Number // otherwise they won't upgrade the old installation! -[assembly: AssemblyVersion("1.0.23.7")] -[assembly: AssemblyFileVersion("1.0.23.7")] +[assembly: AssemblyVersion("1.0.23.10")] +[assembly: AssemblyFileVersion("1.0.23.10")] diff --git a/RosDBG/Properties/DataSources/.gitignore b/RosDBG/Properties/DataSources/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/RosDBG/RosDBG.csproj b/RosDBG/RosDBG.csproj index 55c4283..7b97f8d 100644 --- a/RosDBG/RosDBG.csproj +++ b/RosDBG/RosDBG.csproj @@ -106,6 +106,12 @@ Connect.cs + + Form + + + EditBreakpointDialog.cs + Form @@ -117,6 +123,12 @@ Code + + Form + + + BreakpointWindow.cs + Form @@ -185,10 +197,18 @@ Connect.cs Designer + + EditBreakpointDialog.cs + Designer + BackTrace.cs Designer + + BreakpointWindow.cs + Designer + Locals.cs Designer @@ -246,6 +266,7 @@ Resources.resx True + SettingsSingleFileGenerator Settings.Designer.cs