2008-07-31 07:00:10 +00:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using System.Text.RegularExpressions;
|
2009-06-02 19:05:54 +00:00
|
|
|
|
using System.Threading;
|
2008-07-31 07:00:10 +00:00
|
|
|
|
using System.Globalization;
|
|
|
|
|
using AbstractPipe;
|
|
|
|
|
using DebugProtocol;
|
2011-08-02 19:54:03 +00:00
|
|
|
|
using System.Diagnostics;
|
2008-07-31 07:00:10 +00:00
|
|
|
|
|
|
|
|
|
namespace KDBGProtocol
|
|
|
|
|
{
|
|
|
|
|
public class KDBG : IDebugProtocol
|
|
|
|
|
{
|
2011-08-02 19:54:03 +00:00
|
|
|
|
#region Regular expressions
|
2008-07-31 07:00:10 +00:00
|
|
|
|
static Regex mMemoryRowUpdate = new Regex("<(?<addr>[^>]+)>: (?<row>[0-9a-fA-F? ]*)");
|
|
|
|
|
static Regex mModuleOffset = new Regex("(?<modname>[^:]+):(?<offset>[0-9a-fA-f]+).*");
|
|
|
|
|
static Regex mModuleUpdate = new Regex("(?<base>[0-9a-fA-F]+) (?<size>[0-9a-fA-F]+) (?<modname>\\w+\\.\\w+)");
|
|
|
|
|
static Regex mRegLineCS_EIP = new Regex("CS:EIP 0x(?<cs>[0-9a-fA-F]+):0x(?<eip>[0-9a-fA-F]+).*");
|
|
|
|
|
static Regex mRegLineSS_ESP = new Regex("SS:ESP 0x(?<ss>[0-9a-fA-F]+):0x(?<esp>[0-9a-fA-F]+).*");
|
|
|
|
|
static Regex mRegLineEAX_EBX = new Regex("EAX 0x(?<eax>[0-9a-fA-F]+)[ \t]+EBX 0x(?<ebx>[0-9a-fA-F]+).*");
|
|
|
|
|
static Regex mRegLineECX_EDX = new Regex("ECX 0x(?<ecx>[0-9a-fA-F]+)[ \t]+EDX 0x(?<edx>[0-9a-fA-F]+).*");
|
|
|
|
|
static Regex mRegLineEBP = new Regex("EBP 0x(?<ebp>[0-9a-fA-F]+).*");
|
|
|
|
|
static Regex mRegLineEFLAGS = new Regex("EFLAGS 0x(?<eflags>[0-9a-fA-F]+).*");
|
|
|
|
|
static Regex mSregLine = new Regex("[CDEFGS]S 0x(?<seg>[0-9a-fA-F]+).*");
|
2008-08-12 10:48:38 +00:00
|
|
|
|
static Regex mProcListHeading = new Regex("PID[ \\t]+State[ \\t]+Filename.*");
|
|
|
|
|
static Regex mThreadListHeading = new Regex("TID[ \\t]+State[ \\t]+Prio.*");
|
2008-10-12 21:34:05 +00:00
|
|
|
|
static Regex mProcListEntry = new Regex("^(?<cur>([*]|))0x(?<pid>[0-9a-fA-F]+)[ \\t](?<state>[a-zA-Z ]+)[ \\t](?<name>[a-zA-Z. ]+).*");
|
2008-08-17 11:44:03 +00:00
|
|
|
|
static Regex mThreadListEntry = new Regex("^(?<cur>([*]|))0x(?<tid>[0-9a-fA-F]+)[ \\t]+(?<state>.*)0x(?<eip>[0-9a-fA-F]*)");
|
2011-08-02 19:54:03 +00:00
|
|
|
|
static Regex mBreakpointListEntry = new Regex("^\\*?(?<id>[0-9]{3})[ \\t]+(?<type>BP[X|M])[ \\t]+0x(?<address>[0-9a-fA-F]+)(?<rest>.+)");
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region Fields
|
|
|
|
|
bool mRunning = true;
|
|
|
|
|
Pipe mConnection;
|
|
|
|
|
Queue<string> mCommandBuffer = new Queue<string>();
|
|
|
|
|
Dictionary<string, ulong> mModuleList = new Dictionary<string, ulong>();
|
|
|
|
|
ulong[] mRegisters = new ulong[32];
|
|
|
|
|
IList<Breakpoint> mBreakpoints = new List<Breakpoint>();
|
2008-07-31 07:00:10 +00:00
|
|
|
|
|
2008-08-02 09:48:48 +00:00
|
|
|
|
bool mFirstModuleUpdate = false;
|
2008-08-12 10:48:38 +00:00
|
|
|
|
bool mReceivingProcs = false;
|
|
|
|
|
bool mReceivingThreads = false;
|
2011-08-02 19:54:03 +00:00
|
|
|
|
bool mReceivingBreakpoints = false;
|
2008-07-31 07:00:10 +00:00
|
|
|
|
StringBuilder mInputBuffer = new StringBuilder();
|
2008-08-12 10:48:38 +00:00
|
|
|
|
int mUsedInput;
|
2011-08-02 19:54:03 +00:00
|
|
|
|
#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)
|
|
|
|
|
{
|
|
|
|
|
}
|
2008-07-31 07:00:10 +00:00
|
|
|
|
|
|
|
|
|
void PipeReceiveEvent(object sender, PipeReceiveEventArgs args)
|
|
|
|
|
{
|
|
|
|
|
bool tookText = false;
|
|
|
|
|
string inbufStr;
|
|
|
|
|
int promptIdx;
|
|
|
|
|
|
|
|
|
|
mInputBuffer.Append(args.Received);
|
|
|
|
|
|
2008-08-12 10:48:38 +00:00
|
|
|
|
if (mInputBuffer.ToString().Substring(mUsedInput).Contains("key to continue"))
|
2008-07-31 07:00:10 +00:00
|
|
|
|
{
|
|
|
|
|
mConnection.Write("\r");
|
2008-08-12 10:48:38 +00:00
|
|
|
|
mUsedInput = mInputBuffer.Length;
|
2008-07-31 07:00:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
while ((promptIdx = (inbufStr = mInputBuffer.ToString()).IndexOf("kdb:> ")) != -1)
|
|
|
|
|
{
|
|
|
|
|
string pretext = inbufStr.Substring(0, promptIdx);
|
|
|
|
|
string[] theInput = pretext.Split(new char[] { '\n' });
|
|
|
|
|
int remove = pretext.Length + "kdb:> ".Length;
|
|
|
|
|
|
|
|
|
|
mInputBuffer.Remove(0, remove);
|
2008-08-12 10:48:38 +00:00
|
|
|
|
mUsedInput = Math.Max(0, mUsedInput - remove);
|
2008-07-31 07:00:10 +00:00
|
|
|
|
|
|
|
|
|
if (!tookText)
|
|
|
|
|
{
|
|
|
|
|
if (mRunning)
|
|
|
|
|
{
|
|
|
|
|
mRunning = false;
|
|
|
|
|
}
|
|
|
|
|
tookText = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach (string line in theInput)
|
|
|
|
|
{
|
|
|
|
|
string cleanedLine = line.Trim();
|
|
|
|
|
try
|
|
|
|
|
{
|
2009-05-31 12:50:16 +00:00
|
|
|
|
if (cleanedLine.Contains("Entered debugger on "))
|
2008-07-31 07:00:10 +00:00
|
|
|
|
{
|
2008-08-12 10:48:38 +00:00
|
|
|
|
mReceivingProcs = false;
|
|
|
|
|
mReceivingThreads = false;
|
2008-07-31 07:00:10 +00:00
|
|
|
|
GetRegisterUpdate();
|
2008-08-12 10:48:38 +00:00
|
|
|
|
GetProcesses();
|
2008-07-31 07:00:10 +00:00
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2008-08-02 09:48:48 +00:00
|
|
|
|
if (!mFirstModuleUpdate)
|
|
|
|
|
{
|
|
|
|
|
GetModuleUpdate();
|
|
|
|
|
mFirstModuleUpdate = true;
|
|
|
|
|
}
|
|
|
|
|
|
2011-08-02 19:54:03 +00:00
|
|
|
|
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 */ }
|
|
|
|
|
}
|
|
|
|
|
}
|
2008-07-31 07:00:10 +00:00
|
|
|
|
|
2011-08-02 19:54:03 +00:00
|
|
|
|
if (tookText)
|
|
|
|
|
{
|
|
|
|
|
lock (mCommandBuffer)
|
|
|
|
|
{
|
|
|
|
|
if (mCommandBuffer.Count > 0)
|
|
|
|
|
{
|
|
|
|
|
string firstCommand = mCommandBuffer.Dequeue();
|
|
|
|
|
mConnection.Write(firstCommand + "\r");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endregion
|
2008-07-31 07:00:10 +00:00
|
|
|
|
|
2011-08-02 19:54:03 +00:00
|
|
|
|
#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++)
|
2008-07-31 07:00:10 +00:00
|
|
|
|
{
|
2011-08-02 19:54:03 +00:00
|
|
|
|
updateBytes[ctr] = (byte)(wordParsed & 0xff);
|
|
|
|
|
wordParsed >>= 8;
|
2008-07-31 07:00:10 +00:00
|
|
|
|
}
|
2011-08-02 19:54:03 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (MemoryUpdateEvent != null)
|
|
|
|
|
MemoryUpdateEvent(this, new MemoryUpdateEventArgs(updateAddress, updateBytes));
|
2008-07-31 07:00:10 +00:00
|
|
|
|
|
2011-08-02 19:54:03 +00:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2008-07-31 07:00:10 +00:00
|
|
|
|
|
2011-08-02 19:54:03 +00:00
|
|
|
|
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;
|
|
|
|
|
}
|
2008-07-31 07:00:10 +00:00
|
|
|
|
|
2011-08-02 19:54:03 +00:00
|
|
|
|
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;
|
|
|
|
|
}
|
2008-07-31 07:00:10 +00:00
|
|
|
|
|
2011-08-02 19:54:03 +00:00
|
|
|
|
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;
|
|
|
|
|
}
|
2008-07-31 07:00:10 +00:00
|
|
|
|
|
2011-08-02 19:54:03 +00:00
|
|
|
|
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;
|
|
|
|
|
}
|
2008-07-31 07:00:10 +00:00
|
|
|
|
|
2011-08-02 19:54:03 +00:00
|
|
|
|
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;
|
|
|
|
|
}
|
2008-07-31 07:00:10 +00:00
|
|
|
|
|
2011-08-02 19:54:03 +00:00
|
|
|
|
Match ebpMatch = mRegLineEBP.Match(cleanedLine);
|
|
|
|
|
if (ebpMatch.Success)
|
|
|
|
|
{
|
|
|
|
|
ulong ebp = ulong.Parse(ebpMatch.Groups["ebp"].ToString(), NumberStyles.HexNumber);
|
|
|
|
|
mRegisters[5] = ebp;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2008-08-12 10:48:38 +00:00
|
|
|
|
|
2011-08-02 19:54:03 +00:00
|
|
|
|
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;
|
|
|
|
|
}
|
2008-08-12 10:48:38 +00:00
|
|
|
|
|
2011-08-02 19:54:03 +00:00
|
|
|
|
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;
|
2008-08-12 10:48:38 +00:00
|
|
|
|
}
|
2008-07-31 07:00:10 +00:00
|
|
|
|
}
|
2011-08-02 19:54:03 +00:00
|
|
|
|
return true;
|
2008-07-31 07:00:10 +00:00
|
|
|
|
}
|
2011-08-02 19:54:03 +00:00
|
|
|
|
return false;
|
|
|
|
|
}
|
2008-07-31 07:00:10 +00:00
|
|
|
|
|
2011-08-02 19:54:03 +00:00
|
|
|
|
private bool TryParsePID(string cleanedLine)
|
|
|
|
|
{
|
|
|
|
|
Match pidHeadMatch = mProcListHeading.Match(cleanedLine);
|
|
|
|
|
if (pidHeadMatch.Success)
|
2008-07-31 07:00:10 +00:00
|
|
|
|
{
|
2011-08-02 19:54:03 +00:00
|
|
|
|
mReceivingThreads = false;
|
|
|
|
|
mReceivingProcs = true;
|
|
|
|
|
if (ProcessListEvent != null)
|
|
|
|
|
ProcessListEvent(this, new ProcessListEventArgs());
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Match pidEntryMatch = mProcListEntry.Match(cleanedLine);
|
|
|
|
|
if (pidEntryMatch.Success && mReceivingProcs)
|
2008-07-31 07:00:10 +00:00
|
|
|
|
{
|
2011-08-02 19:54:03 +00:00
|
|
|
|
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)
|
2008-07-31 07:00:10 +00:00
|
|
|
|
{
|
2011-08-02 19:54:03 +00:00
|
|
|
|
ProcessListEvent(this, new ProcessListEventArgs(true));
|
|
|
|
|
mReceivingProcs = false;
|
|
|
|
|
return true;
|
2008-07-31 07:00:10 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-08-02 19:54:03 +00:00
|
|
|
|
return false;
|
2008-07-31 07:00:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
2011-08-02 19:54:03 +00:00
|
|
|
|
private bool TryParseTID(string cleanedLine)
|
2008-07-31 07:00:10 +00:00
|
|
|
|
{
|
2011-08-02 19:54:03 +00:00
|
|
|
|
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;
|
2008-07-31 07:00:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
2011-08-02 19:54:03 +00:00
|
|
|
|
private bool TryParseBreakpoint(string cleanedLine)
|
2008-07-31 07:00:10 +00:00
|
|
|
|
{
|
2011-08-02 19:54:03 +00:00
|
|
|
|
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);
|
|
|
|
|
}
|
2008-07-31 07:00:10 +00:00
|
|
|
|
|
2011-08-02 19:54:03 +00:00
|
|
|
|
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;
|
|
|
|
|
}
|
2008-07-31 07:00:10 +00:00
|
|
|
|
|
2011-08-02 19:54:03 +00:00
|
|
|
|
// 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;
|
2008-07-31 07:00:10 +00:00
|
|
|
|
}
|
2011-08-02 19:54:03 +00:00
|
|
|
|
#endregion
|
2008-07-31 07:00:10 +00:00
|
|
|
|
|
2011-08-02 19:54:03 +00:00
|
|
|
|
#region Upstream commands
|
2008-07-31 07:00:10 +00:00
|
|
|
|
public void QueueCommand(string command)
|
|
|
|
|
{
|
|
|
|
|
lock (mCommandBuffer)
|
|
|
|
|
{
|
2011-08-02 19:54:03 +00:00
|
|
|
|
mCommandBuffer.Enqueue(command);
|
2008-07-31 07:00:10 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2009-08-29 16:03:13 +00:00
|
|
|
|
public void Write(string wr)
|
|
|
|
|
{
|
|
|
|
|
/* Forward user input from RawTraffic if connected to kdbg */
|
|
|
|
|
if (!mRunning)
|
|
|
|
|
{
|
|
|
|
|
mConnection.Write(wr + "\r");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Close()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2011-08-02 19:54:03 +00:00
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region Immediately executed commands
|
2008-07-31 07:00:10 +00:00
|
|
|
|
public void Step()
|
|
|
|
|
{
|
2009-08-29 16:03:13 +00:00
|
|
|
|
Write("step");
|
2008-07-31 07:00:10 +00:00
|
|
|
|
GetRegisterUpdate();
|
2008-08-02 09:48:48 +00:00
|
|
|
|
GetModuleUpdate();
|
2008-08-12 10:48:38 +00:00
|
|
|
|
GetProcesses();
|
2008-07-31 07:00:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Next()
|
|
|
|
|
{
|
2009-08-29 16:03:13 +00:00
|
|
|
|
Write("next");
|
2009-06-02 19:05:54 +00:00
|
|
|
|
Thread.Sleep(100);
|
2008-07-31 07:00:10 +00:00
|
|
|
|
GetRegisterUpdate();
|
2008-08-02 09:48:48 +00:00
|
|
|
|
GetModuleUpdate();
|
2008-08-12 10:48:38 +00:00
|
|
|
|
GetProcesses();
|
2008-07-31 07:00:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Break()
|
|
|
|
|
{
|
2009-08-29 16:03:13 +00:00
|
|
|
|
Write("");
|
2008-07-31 07:00:10 +00:00
|
|
|
|
GetRegisterUpdate();
|
2008-08-02 09:48:48 +00:00
|
|
|
|
GetModuleUpdate();
|
2008-07-31 07:00:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Go(ulong address)
|
|
|
|
|
{
|
2009-08-29 16:03:13 +00:00
|
|
|
|
Write("cont");
|
2008-07-31 07:00:10 +00:00
|
|
|
|
mRunning = true;
|
2008-08-02 09:48:48 +00:00
|
|
|
|
mFirstModuleUpdate = false;
|
2008-07-31 07:00:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
2011-08-02 19:54:03 +00:00
|
|
|
|
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)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2009-08-29 16:03:13 +00:00
|
|
|
|
public void GetMemoryUpdate(ulong address, int len)
|
|
|
|
|
{
|
|
|
|
|
Write(string.Format("x 0x{0:X} L {1}", address, len));
|
|
|
|
|
}
|
2011-08-02 19:54:03 +00:00
|
|
|
|
#endregion
|
2009-08-29 16:03:13 +00:00
|
|
|
|
|
2011-08-02 19:54:03 +00:00
|
|
|
|
#region Commands placed into the command queue
|
2008-08-12 10:48:38 +00:00
|
|
|
|
public void GetProcesses()
|
|
|
|
|
{
|
|
|
|
|
QueueCommand("proc list");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void GetThreads(ulong pid)
|
|
|
|
|
{
|
2009-05-26 18:50:09 +00:00
|
|
|
|
if (pid != 0)
|
|
|
|
|
QueueCommand(string.Format("thread list 0x{0:X8}", pid));
|
2008-08-12 10:48:38 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void SetProcess(ulong pid)
|
|
|
|
|
{
|
|
|
|
|
QueueCommand(string.Format("proc attach 0x{0:X8}", pid));
|
|
|
|
|
GetRegisterUpdate();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void SetThread(ulong tid)
|
|
|
|
|
{
|
|
|
|
|
QueueCommand(string.Format("thread attach 0x{0:X8}", tid));
|
|
|
|
|
GetRegisterUpdate();
|
|
|
|
|
}
|
|
|
|
|
|
2009-08-29 16:03:13 +00:00
|
|
|
|
public void GetRegisterUpdate()
|
2009-08-26 15:08:02 +00:00
|
|
|
|
{
|
2009-08-29 16:03:13 +00:00
|
|
|
|
QueueCommand("regs");
|
|
|
|
|
QueueCommand("sregs");
|
2009-08-26 15:08:02 +00:00
|
|
|
|
}
|
2008-07-31 07:00:10 +00:00
|
|
|
|
|
2009-08-29 16:03:13 +00:00
|
|
|
|
public void GetModuleUpdate()
|
2008-07-31 07:00:10 +00:00
|
|
|
|
{
|
2009-08-29 16:03:13 +00:00
|
|
|
|
QueueCommand("mod");
|
2008-07-31 07:00:10 +00:00
|
|
|
|
}
|
2011-08-02 19:54:03 +00:00
|
|
|
|
|
|
|
|
|
#endregion
|
2008-07-31 07:00:10 +00:00
|
|
|
|
}
|
|
|
|
|
}
|