handling the first debuggee event (ThreadStart)

This commit is contained in:
smallsql 2009-02-22 09:09:41 +00:00
Родитель 8ffc7143ee
Коммит 291c094215
7 изменённых файлов: 139 добавлений и 46 удалений

Просмотреть файл

@ -66,7 +66,7 @@ namespace ikvm.debugger
JdwpConnection conn = new JdwpConnection(parameters);
conn.Connect();
Console.Error.WriteLine("Started");
TargetVM target = new TargetVM(pid);
TargetVM target = new TargetVM(pid, new JdwpEventHandler(conn));
JdwpHandler handler = new JdwpHandler(conn, target);
handler.Run();
//System.Threading.Thread.Sleep(5000);

Просмотреть файл

@ -36,15 +36,19 @@ namespace ikvm.debugger.requests
internal const int CmdClear = 2;
internal const int CmdClearAllBreakpoints = 3;
private byte eventKind;
private byte suspendPolicy;
private List<EventModifier> modifiers;
private static int eventRequestCounter;
private readonly byte eventKind;
private readonly byte suspendPolicy;
private readonly List<EventModifier> modifiers;
private readonly int requestId;
private EventRequest(byte eventKind, byte suspendPolicy, List<EventModifier> modifiers)
{
this.eventKind = eventKind;
this.suspendPolicy = suspendPolicy;
this.modifiers = modifiers;
this.requestId = ++eventRequestCounter;
}
/// <summary>
@ -57,29 +61,29 @@ namespace ikvm.debugger.requests
byte eventKind = packet.ReadByte(); // class EventKind
switch (eventKind)
{
case EventKind.SINGLE_STEP:
case EventKind.BREAKPOINT:
case EventKind.FRAME_POP:
case EventKind.EXCEPTION:
case EventKind.USER_DEFINED:
case EventKind.THREAD_START:
case EventKind.THREAD_DEATH:
case EventKind.CLASS_PREPARE:
case EventKind.CLASS_UNLOAD:
case EventKind.CLASS_LOAD:
case EventKind.FIELD_ACCESS:
case EventKind.FIELD_MODIFICATION:
case EventKind.EXCEPTION_CATCH:
case EventKind.METHOD_ENTRY:
case EventKind.METHOD_EXIT:
case EventKind.METHOD_EXIT_WITH_RETURN_VALUE:
case EventKind.MONITOR_CONTENDED_ENTER:
case EventKind.MONITOR_CONTENDED_ENTERED:
case EventKind.MONITOR_WAIT:
case EventKind.MONITOR_WAITED:
case EventKind.VM_START:
case EventKind.VM_DEATH:
case EventKind.VM_DISCONNECTED:
case ikvm.debugger.EventKind.SINGLE_STEP:
case ikvm.debugger.EventKind.BREAKPOINT:
case ikvm.debugger.EventKind.FRAME_POP:
case ikvm.debugger.EventKind.EXCEPTION:
case ikvm.debugger.EventKind.USER_DEFINED:
case ikvm.debugger.EventKind.THREAD_START:
case ikvm.debugger.EventKind.THREAD_DEATH:
case ikvm.debugger.EventKind.CLASS_PREPARE:
case ikvm.debugger.EventKind.CLASS_UNLOAD:
case ikvm.debugger.EventKind.CLASS_LOAD:
case ikvm.debugger.EventKind.FIELD_ACCESS:
case ikvm.debugger.EventKind.FIELD_MODIFICATION:
case ikvm.debugger.EventKind.EXCEPTION_CATCH:
case ikvm.debugger.EventKind.METHOD_ENTRY:
case ikvm.debugger.EventKind.METHOD_EXIT:
case ikvm.debugger.EventKind.METHOD_EXIT_WITH_RETURN_VALUE:
case ikvm.debugger.EventKind.MONITOR_CONTENDED_ENTER:
case ikvm.debugger.EventKind.MONITOR_CONTENDED_ENTERED:
case ikvm.debugger.EventKind.MONITOR_WAIT:
case ikvm.debugger.EventKind.MONITOR_WAITED:
case ikvm.debugger.EventKind.VM_START:
case ikvm.debugger.EventKind.VM_DEATH:
case ikvm.debugger.EventKind.VM_DISCONNECTED:
break;
default:
return null; //Invalid or not supported EventKind
@ -139,6 +143,16 @@ namespace ikvm.debugger.requests
return new EventRequest(eventKind, suspendPolicy, modifiers);
}
internal int RequestId
{
get { return requestId; }
}
internal int EventKind
{
get { return eventKind; }
}
public override String ToString()
{
//for debugging

Просмотреть файл

@ -36,10 +36,15 @@ namespace ikvm.debugger
private TcpClient client;
BufferedStream stream;
Stream stream;
/// <summary>
/// Shared buffer for reading and monitor for reading
/// </summary>
private readonly byte[] readHeader = new byte[11];
private readonly Object writeMonitor = new Object();
internal JdwpConnection(JdwpParameters parameters)
{
this.parameters = parameters;
@ -59,7 +64,8 @@ namespace ikvm.debugger
{
client = new TcpClient(parameters.Host, parameters.Port);
}
stream = new BufferedStream(client.GetStream());
stream = client.GetStream(); //TODO Bug in BufferedStream, work not asynchron
//stream = new BufferedStream(client.GetStream());
System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();
byte[] hello = encoding.GetBytes("JDWP-Handshake");
stream.Write(hello, 0, hello.Length);
@ -97,8 +103,11 @@ namespace ikvm.debugger
}
internal void SendPacket(Packet packet)
{
lock (writeMonitor)
{
packet.Send(stream);
}
}
}
}

Просмотреть файл

@ -233,7 +233,8 @@ namespace ikvm.debugger
}
else
{
packet.WriteInt(packet.Id); // TODO should be EventID and not PacketID
target.AddEventRequest(eventRequest);
packet.WriteInt(eventRequest.RequestId);
}
break;
default:

Просмотреть файл

@ -36,21 +36,25 @@ namespace ikvm.debugger
/// </summary>
class Packet
{
public const byte NoFlags = 0x0;
public const byte Reply = 0x80;
public const byte ReplyNoError = 0x0;
private static int packetCounter;
private const byte NoFlags = 0x0;
private const byte Reply = 0x80;
private byte[] data;
private int offset;
private int id;
private byte flags;
private byte cmdSet;
private byte cmd;
private short errorCode;
private bool isEvent;
private Stream output = new MemoryStream();
/// <summary>
/// Private constructor, use the factory methods
/// </summary>
private Packet() { }
/// <summary>
@ -65,13 +69,13 @@ namespace ikvm.debugger
Packet packet = new Packet();
packet.data = header;
int len = packet.ReadInt();
if (len < 0)
if (len < 11)
{
throw new IOException("protocol error - invalid length");
}
packet.id = packet.ReadInt();
packet.flags = packet.ReadByte();
if ((packet.flags & Packet.Reply) == 0)
int flags = packet.ReadByte();
if ((flags & Reply) == 0)
{
packet.cmdSet = packet.ReadByte();
packet.cmd = packet.ReadByte();
@ -81,12 +85,29 @@ namespace ikvm.debugger
packet.errorCode = packet.ReadShort();
}
packet.data = new byte[len - 11];
Console.Error.WriteLine("Data Size:" + packet.data.Length);
DebuggerUtils.ReadFully(stream, packet.data);
packet.offset = 0;
return packet;
}
/// <summary>
/// Create a empty packet to send an Event from the target VM (debuggee) to the debugger.
/// </summary>
/// <returns>a new packet</returns>
internal static Packet CreateEventPacket()
{
Packet packet = new Packet();
packet.id = ++packetCounter;
packet.cmdSet = ikvm.debugger.CommandSet.Event;
packet.cmd = 100;
packet.isEvent = true;
return packet;
}
/// <summary>
/// Is used from JdwpConnection. You should use jdwpConnection.Send(Packet).
/// </summary>
/// <param name="stream"></param>
internal void Send(Stream stream)
{
MemoryStream ms = (MemoryStream)output;
@ -95,8 +116,17 @@ Console.Error.WriteLine("Data Size:" + packet.data.Length);
output = stream;
WriteInt((int)ms.Length + 11);
WriteInt(id);
if (!isEvent)
{
WriteByte(Reply);
WriteShort(errorCode);
}
else
{
WriteByte(NoFlags);
WriteByte(cmdSet);
WriteByte(cmd);
}
ms.WriteTo(stream);
}
finally

Просмотреть файл

@ -69,6 +69,7 @@
<Compile Include="EventRequest.cs" />
<Compile Include="JdwpConnection.cs" />
<Compile Include="JdwpConst.cs" />
<Compile Include="JdwpEventHandler.cs" />
<Compile Include="JdwpHandler.cs" />
<Compile Include="JdwpParameters.cs" />
<Compile Include="Packet.cs" />

Просмотреть файл

@ -30,6 +30,7 @@ using System.Collections;
using Debugger.MetaData;
using System.Windows.Forms;
using Debugger.Wrappers.MetaData;
using ikvm.debugger.requests;
namespace ikvm.debugger.win
@ -46,12 +47,18 @@ namespace ikvm.debugger.win
private readonly Dictionary<String, IList<TargetType>> nameTypeMap = new Dictionary<String, IList<TargetType>>();
private readonly JdwpEventHandler jdwpEventHandler = null;
private EventRequest threadStartEventRequest;
/// <summary>
/// Create a new target VM for the giveb process id.
/// </summary>
/// <param name="pid">Process ID of the IKVM</param>
internal TargetVM(int pid)
internal TargetVM(int pid, JdwpEventHandler jdwpEventHandler)
{
this.jdwpEventHandler = jdwpEventHandler;
debugger = new NDebugger();
System.Diagnostics.Process sysProcess = System.Diagnostics.Process.GetProcessById(pid);
process = debugger.Attach(sysProcess);
@ -60,7 +67,7 @@ namespace ikvm.debugger.win
process.ModuleLoaded += new EventHandler<ModuleEventArgs>(ModuleLoaded);
process.Paused += new EventHandler<ProcessEventArgs>(Paused);
process.Resumed += new EventHandler<ProcessEventArgs>(Resumed);
process.ThreadStarted += new EventHandler<ThreadEventArgs>(ThreadStarted);
}
/// <summary>
@ -171,16 +178,35 @@ namespace ikvm.debugger.win
}
}
void Paused(object sender, ProcessEventArgs ev)
private void Paused(object sender, ProcessEventArgs ev)
{
Console.Error.WriteLine("Paused:" + ev);
}
void Resumed(object sender, ProcessEventArgs ev)
private void Resumed(object sender, ProcessEventArgs ev)
{
Console.Error.WriteLine("Resumed:" + ev);
}
private void ThreadStarted(object sender, ThreadEventArgs ev)
{
EventRequest eventRequest = threadStartEventRequest;
if (eventRequest != null)
{
Thread th = ev.Thread;
jdwpEventHandler.Send(SuspendPolicy.EVENT_THREAD, EventKind.THREAD_START, eventRequest.RequestId, (int)th.ID);
ev.Thread.Exited += new EventHandler<ThreadEventArgs>(ThreadExited);
}
Console.Error.WriteLine("ThreadStarted:" + ev.Thread.ID+ " " + eventRequest);
}
private void ThreadExited(object sender, ThreadEventArgs ev)
{
Console.Error.WriteLine("ThreadExited:" + ev.Thread.ID);
}
private IList<DebugType> FindTypesInModules(String name)
{
List<DebugType> result = new List<DebugType>();
@ -207,6 +233,18 @@ namespace ikvm.debugger.win
return result;
}
/// <summary>
/// Set an EventRequest received from debugger.
/// </summary>
/// <param name="eventRequest">the new EventRequest</param>
internal void AddEventRequest(ikvm.debugger.requests.EventRequest eventRequest)
{
switch (eventRequest.EventKind)
{
case EventKind.THREAD_START:
threadStartEventRequest = eventRequest;
break;
}
}
}
}