reactosdbg/DebugProtocol/DebugMemoryStream.cs
Art Yerkes 6030ecd415 A debugging shell for use with KDBG. Not perfect yet but it can display the
locals and stack trace at the place where reactos is stopped.

svn path=/trunk/tools/reactosdbg/; revision=759
2008-07-31 07:00:10 +00:00

182 lines
5.5 KiB
C#

using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace DebugProtocol
{
public class DebugMemoryStream : Stream
{
DebugConnection mConnection;
ulong mReadAddr;
int mCopyOffset, mCopyCount;
byte[] mReadBuffer;
long[] mBytesReceived;
EventWaitHandle mReadComplete = new EventWaitHandle(false, EventResetMode.AutoReset);
public override bool CanRead
{
get { return true; }
}
public override bool CanSeek
{
get { return true; }
}
public override bool CanWrite
{
get { return true; }
}
public override long Length
{
get { return 1L << 32; }
}
long mPosition;
public override long Position
{
get { return mPosition; }
set { mPosition = value; }
}
public override void Flush() { }
public override long Seek(long position, SeekOrigin origin)
{
long prev = mPosition;
switch (origin)
{
case SeekOrigin.Begin:
mPosition = position;
break;
case SeekOrigin.Current:
mPosition += position;
break;
case SeekOrigin.End:
mPosition = ((1L << 32) - position) & ((1L << 32) - 1);
break;
}
return prev;
}
public override void SetLength(long len) { }
int RoundUp(int count, int factor)
{
return (count + (factor - 1)) & ~(factor - 1);
}
public override int Read(byte[] buffer, int offset, int count)
{
lock (this)
{
mReadAddr = (ulong)mPosition;
mBytesReceived = new long[RoundUp(count, 64) / 64];
SetBits(count, RoundUp(count, 64));
mCopyOffset = offset;
mCopyCount = count;
mReadBuffer = buffer;
mConnection.Debugger.GetMemoryUpdate(mReadAddr, count);
}
mReadComplete.WaitOne();
lock (this)
{
mBytesReceived = null;
return mCopyCount == 0 ? -1 : mCopyCount;
}
}
public override void Write(byte[] buffer, int offset, int count)
{
}
void SetBits(int start, int end)
{
int longOfStart = start >> 6, longOfEnd = (end - 1) >> 6;
if (longOfStart == longOfEnd)
{
end -= start & ~63;
start &= 63;
long mask = ~((1L << start) - 1);
mask &= end == 64 ? -1 : ((1L << end) - 1);
mBytesReceived[longOfStart] |= mask;
}
else
{
int nextStart = (start + 64) & ~63;
SetBits(start, nextStart);
while (nextStart >> 6 != longOfEnd)
{
start = nextStart;
nextStart = start + 64;
SetBits(start, nextStart);
}
}
}
bool ReadComplete()
{
foreach (long l in mBytesReceived) if (l != -1) return false;
if (mCopyCount > 0) mPosition += mCopyCount;
return true;
}
public void Update(ulong Address, byte[] Memory)
{
lock (this)
{
if (mBytesReceived == null) return;
if (Address >= mReadAddr)
{
long diff = (long)(Address - mReadAddr);
if (Memory == null)
{
if (diff >= mCopyCount) return;
SetBits((int)diff, mCopyCount);
mCopyCount = Math.Min(mCopyCount, (int)diff);
}
else
{
long toCopy = Math.Min(Memory.Length, mCopyCount - diff);
if (toCopy <= 0 || diff >= mCopyCount) return;
Array.Copy(Memory, 0, mReadBuffer, mCopyOffset + diff, toCopy);
SetBits(mCopyOffset + (int)diff, (int)(mCopyOffset + diff + toCopy));
}
}
else
{
long diff = (long)(mReadAddr - Address);
if (Memory == null)
{
if (diff >= 4096) return;
mCopyCount = 0;
}
else
{
long toCopy = Math.Min(mReadBuffer.Length - mCopyOffset, Math.Min(mCopyCount - diff, Memory.Length));
if (toCopy <= 0 || diff >= Memory.Length) return;
Array.Copy(Memory, (int)diff, mReadBuffer, mCopyOffset, (int)toCopy);
SetBits(0, (int)toCopy);
}
}
if (ReadComplete()) mReadComplete.Set();
}
}
public DebugMemoryStream(DebugConnection conn)
{
mConnection = conn;
}
}
}