зеркало из https://github.com/mono/ikvm-fork.git
handling the first debuggee event (ThreadStart)
This commit is contained in:
Родитель
8ffc7143ee
Коммит
291c094215
|
@ -66,7 +66,7 @@ namespace ikvm.debugger
|
||||||
JdwpConnection conn = new JdwpConnection(parameters);
|
JdwpConnection conn = new JdwpConnection(parameters);
|
||||||
conn.Connect();
|
conn.Connect();
|
||||||
Console.Error.WriteLine("Started");
|
Console.Error.WriteLine("Started");
|
||||||
TargetVM target = new TargetVM(pid);
|
TargetVM target = new TargetVM(pid, new JdwpEventHandler(conn));
|
||||||
JdwpHandler handler = new JdwpHandler(conn, target);
|
JdwpHandler handler = new JdwpHandler(conn, target);
|
||||||
handler.Run();
|
handler.Run();
|
||||||
//System.Threading.Thread.Sleep(5000);
|
//System.Threading.Thread.Sleep(5000);
|
||||||
|
|
|
@ -36,15 +36,19 @@ namespace ikvm.debugger.requests
|
||||||
internal const int CmdClear = 2;
|
internal const int CmdClear = 2;
|
||||||
internal const int CmdClearAllBreakpoints = 3;
|
internal const int CmdClearAllBreakpoints = 3;
|
||||||
|
|
||||||
private byte eventKind;
|
private static int eventRequestCounter;
|
||||||
private byte suspendPolicy;
|
|
||||||
private List<EventModifier> modifiers;
|
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)
|
private EventRequest(byte eventKind, byte suspendPolicy, List<EventModifier> modifiers)
|
||||||
{
|
{
|
||||||
this.eventKind = eventKind;
|
this.eventKind = eventKind;
|
||||||
this.suspendPolicy = suspendPolicy;
|
this.suspendPolicy = suspendPolicy;
|
||||||
this.modifiers = modifiers;
|
this.modifiers = modifiers;
|
||||||
|
this.requestId = ++eventRequestCounter;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -57,29 +61,29 @@ namespace ikvm.debugger.requests
|
||||||
byte eventKind = packet.ReadByte(); // class EventKind
|
byte eventKind = packet.ReadByte(); // class EventKind
|
||||||
switch (eventKind)
|
switch (eventKind)
|
||||||
{
|
{
|
||||||
case EventKind.SINGLE_STEP:
|
case ikvm.debugger.EventKind.SINGLE_STEP:
|
||||||
case EventKind.BREAKPOINT:
|
case ikvm.debugger.EventKind.BREAKPOINT:
|
||||||
case EventKind.FRAME_POP:
|
case ikvm.debugger.EventKind.FRAME_POP:
|
||||||
case EventKind.EXCEPTION:
|
case ikvm.debugger.EventKind.EXCEPTION:
|
||||||
case EventKind.USER_DEFINED:
|
case ikvm.debugger.EventKind.USER_DEFINED:
|
||||||
case EventKind.THREAD_START:
|
case ikvm.debugger.EventKind.THREAD_START:
|
||||||
case EventKind.THREAD_DEATH:
|
case ikvm.debugger.EventKind.THREAD_DEATH:
|
||||||
case EventKind.CLASS_PREPARE:
|
case ikvm.debugger.EventKind.CLASS_PREPARE:
|
||||||
case EventKind.CLASS_UNLOAD:
|
case ikvm.debugger.EventKind.CLASS_UNLOAD:
|
||||||
case EventKind.CLASS_LOAD:
|
case ikvm.debugger.EventKind.CLASS_LOAD:
|
||||||
case EventKind.FIELD_ACCESS:
|
case ikvm.debugger.EventKind.FIELD_ACCESS:
|
||||||
case EventKind.FIELD_MODIFICATION:
|
case ikvm.debugger.EventKind.FIELD_MODIFICATION:
|
||||||
case EventKind.EXCEPTION_CATCH:
|
case ikvm.debugger.EventKind.EXCEPTION_CATCH:
|
||||||
case EventKind.METHOD_ENTRY:
|
case ikvm.debugger.EventKind.METHOD_ENTRY:
|
||||||
case EventKind.METHOD_EXIT:
|
case ikvm.debugger.EventKind.METHOD_EXIT:
|
||||||
case EventKind.METHOD_EXIT_WITH_RETURN_VALUE:
|
case ikvm.debugger.EventKind.METHOD_EXIT_WITH_RETURN_VALUE:
|
||||||
case EventKind.MONITOR_CONTENDED_ENTER:
|
case ikvm.debugger.EventKind.MONITOR_CONTENDED_ENTER:
|
||||||
case EventKind.MONITOR_CONTENDED_ENTERED:
|
case ikvm.debugger.EventKind.MONITOR_CONTENDED_ENTERED:
|
||||||
case EventKind.MONITOR_WAIT:
|
case ikvm.debugger.EventKind.MONITOR_WAIT:
|
||||||
case EventKind.MONITOR_WAITED:
|
case ikvm.debugger.EventKind.MONITOR_WAITED:
|
||||||
case EventKind.VM_START:
|
case ikvm.debugger.EventKind.VM_START:
|
||||||
case EventKind.VM_DEATH:
|
case ikvm.debugger.EventKind.VM_DEATH:
|
||||||
case EventKind.VM_DISCONNECTED:
|
case ikvm.debugger.EventKind.VM_DISCONNECTED:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return null; //Invalid or not supported EventKind
|
return null; //Invalid or not supported EventKind
|
||||||
|
@ -139,6 +143,16 @@ namespace ikvm.debugger.requests
|
||||||
return new EventRequest(eventKind, suspendPolicy, modifiers);
|
return new EventRequest(eventKind, suspendPolicy, modifiers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal int RequestId
|
||||||
|
{
|
||||||
|
get { return requestId; }
|
||||||
|
}
|
||||||
|
|
||||||
|
internal int EventKind
|
||||||
|
{
|
||||||
|
get { return eventKind; }
|
||||||
|
}
|
||||||
|
|
||||||
public override String ToString()
|
public override String ToString()
|
||||||
{
|
{
|
||||||
//for debugging
|
//for debugging
|
||||||
|
|
|
@ -36,10 +36,15 @@ namespace ikvm.debugger
|
||||||
|
|
||||||
private TcpClient client;
|
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 byte[] readHeader = new byte[11];
|
||||||
|
|
||||||
|
private readonly Object writeMonitor = new Object();
|
||||||
|
|
||||||
internal JdwpConnection(JdwpParameters parameters)
|
internal JdwpConnection(JdwpParameters parameters)
|
||||||
{
|
{
|
||||||
this.parameters = parameters;
|
this.parameters = parameters;
|
||||||
|
@ -59,7 +64,8 @@ namespace ikvm.debugger
|
||||||
{
|
{
|
||||||
client = new TcpClient(parameters.Host, parameters.Port);
|
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();
|
System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();
|
||||||
byte[] hello = encoding.GetBytes("JDWP-Handshake");
|
byte[] hello = encoding.GetBytes("JDWP-Handshake");
|
||||||
stream.Write(hello, 0, hello.Length);
|
stream.Write(hello, 0, hello.Length);
|
||||||
|
@ -98,7 +104,10 @@ namespace ikvm.debugger
|
||||||
|
|
||||||
internal void SendPacket(Packet packet)
|
internal void SendPacket(Packet packet)
|
||||||
{
|
{
|
||||||
packet.Send(stream);
|
lock (writeMonitor)
|
||||||
|
{
|
||||||
|
packet.Send(stream);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -233,7 +233,8 @@ namespace ikvm.debugger
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
packet.WriteInt(packet.Id); // TODO should be EventID and not PacketID
|
target.AddEventRequest(eventRequest);
|
||||||
|
packet.WriteInt(eventRequest.RequestId);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -36,21 +36,25 @@ namespace ikvm.debugger
|
||||||
/// </summary>
|
/// </summary>
|
||||||
class Packet
|
class Packet
|
||||||
{
|
{
|
||||||
public const byte NoFlags = 0x0;
|
private static int packetCounter;
|
||||||
public const byte Reply = 0x80;
|
|
||||||
public const byte ReplyNoError = 0x0;
|
private const byte NoFlags = 0x0;
|
||||||
|
private const byte Reply = 0x80;
|
||||||
|
|
||||||
private byte[] data;
|
private byte[] data;
|
||||||
private int offset;
|
private int offset;
|
||||||
|
|
||||||
private int id;
|
private int id;
|
||||||
private byte flags;
|
|
||||||
private byte cmdSet;
|
private byte cmdSet;
|
||||||
private byte cmd;
|
private byte cmd;
|
||||||
private short errorCode;
|
private short errorCode;
|
||||||
|
private bool isEvent;
|
||||||
|
|
||||||
private Stream output = new MemoryStream();
|
private Stream output = new MemoryStream();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Private constructor, use the factory methods
|
||||||
|
/// </summary>
|
||||||
private Packet() { }
|
private Packet() { }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -65,13 +69,13 @@ namespace ikvm.debugger
|
||||||
Packet packet = new Packet();
|
Packet packet = new Packet();
|
||||||
packet.data = header;
|
packet.data = header;
|
||||||
int len = packet.ReadInt();
|
int len = packet.ReadInt();
|
||||||
if (len < 0)
|
if (len < 11)
|
||||||
{
|
{
|
||||||
throw new IOException("protocol error - invalid length");
|
throw new IOException("protocol error - invalid length");
|
||||||
}
|
}
|
||||||
packet.id = packet.ReadInt();
|
packet.id = packet.ReadInt();
|
||||||
packet.flags = packet.ReadByte();
|
int flags = packet.ReadByte();
|
||||||
if ((packet.flags & Packet.Reply) == 0)
|
if ((flags & Reply) == 0)
|
||||||
{
|
{
|
||||||
packet.cmdSet = packet.ReadByte();
|
packet.cmdSet = packet.ReadByte();
|
||||||
packet.cmd = packet.ReadByte();
|
packet.cmd = packet.ReadByte();
|
||||||
|
@ -81,12 +85,29 @@ namespace ikvm.debugger
|
||||||
packet.errorCode = packet.ReadShort();
|
packet.errorCode = packet.ReadShort();
|
||||||
}
|
}
|
||||||
packet.data = new byte[len - 11];
|
packet.data = new byte[len - 11];
|
||||||
Console.Error.WriteLine("Data Size:" + packet.data.Length);
|
|
||||||
DebuggerUtils.ReadFully(stream, packet.data);
|
DebuggerUtils.ReadFully(stream, packet.data);
|
||||||
packet.offset = 0;
|
packet.offset = 0;
|
||||||
return packet;
|
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)
|
internal void Send(Stream stream)
|
||||||
{
|
{
|
||||||
MemoryStream ms = (MemoryStream)output;
|
MemoryStream ms = (MemoryStream)output;
|
||||||
|
@ -95,8 +116,17 @@ Console.Error.WriteLine("Data Size:" + packet.data.Length);
|
||||||
output = stream;
|
output = stream;
|
||||||
WriteInt((int)ms.Length + 11);
|
WriteInt((int)ms.Length + 11);
|
||||||
WriteInt(id);
|
WriteInt(id);
|
||||||
WriteByte(Reply);
|
if (!isEvent)
|
||||||
WriteShort(errorCode);
|
{
|
||||||
|
WriteByte(Reply);
|
||||||
|
WriteShort(errorCode);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
WriteByte(NoFlags);
|
||||||
|
WriteByte(cmdSet);
|
||||||
|
WriteByte(cmd);
|
||||||
|
}
|
||||||
ms.WriteTo(stream);
|
ms.WriteTo(stream);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
|
|
|
@ -69,6 +69,7 @@
|
||||||
<Compile Include="EventRequest.cs" />
|
<Compile Include="EventRequest.cs" />
|
||||||
<Compile Include="JdwpConnection.cs" />
|
<Compile Include="JdwpConnection.cs" />
|
||||||
<Compile Include="JdwpConst.cs" />
|
<Compile Include="JdwpConst.cs" />
|
||||||
|
<Compile Include="JdwpEventHandler.cs" />
|
||||||
<Compile Include="JdwpHandler.cs" />
|
<Compile Include="JdwpHandler.cs" />
|
||||||
<Compile Include="JdwpParameters.cs" />
|
<Compile Include="JdwpParameters.cs" />
|
||||||
<Compile Include="Packet.cs" />
|
<Compile Include="Packet.cs" />
|
||||||
|
|
|
@ -30,6 +30,7 @@ using System.Collections;
|
||||||
using Debugger.MetaData;
|
using Debugger.MetaData;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using Debugger.Wrappers.MetaData;
|
using Debugger.Wrappers.MetaData;
|
||||||
|
using ikvm.debugger.requests;
|
||||||
|
|
||||||
|
|
||||||
namespace ikvm.debugger.win
|
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 Dictionary<String, IList<TargetType>> nameTypeMap = new Dictionary<String, IList<TargetType>>();
|
||||||
|
|
||||||
|
private readonly JdwpEventHandler jdwpEventHandler = null;
|
||||||
|
|
||||||
|
|
||||||
|
private EventRequest threadStartEventRequest;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new target VM for the giveb process id.
|
/// Create a new target VM for the giveb process id.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="pid">Process ID of the IKVM</param>
|
/// <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();
|
debugger = new NDebugger();
|
||||||
System.Diagnostics.Process sysProcess = System.Diagnostics.Process.GetProcessById(pid);
|
System.Diagnostics.Process sysProcess = System.Diagnostics.Process.GetProcessById(pid);
|
||||||
process = debugger.Attach(sysProcess);
|
process = debugger.Attach(sysProcess);
|
||||||
|
@ -60,7 +67,7 @@ namespace ikvm.debugger.win
|
||||||
process.ModuleLoaded += new EventHandler<ModuleEventArgs>(ModuleLoaded);
|
process.ModuleLoaded += new EventHandler<ModuleEventArgs>(ModuleLoaded);
|
||||||
process.Paused += new EventHandler<ProcessEventArgs>(Paused);
|
process.Paused += new EventHandler<ProcessEventArgs>(Paused);
|
||||||
process.Resumed += new EventHandler<ProcessEventArgs>(Resumed);
|
process.Resumed += new EventHandler<ProcessEventArgs>(Resumed);
|
||||||
|
process.ThreadStarted += new EventHandler<ThreadEventArgs>(ThreadStarted);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <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);
|
Console.Error.WriteLine("Paused:" + ev);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Resumed(object sender, ProcessEventArgs ev)
|
private void Resumed(object sender, ProcessEventArgs ev)
|
||||||
{
|
{
|
||||||
Console.Error.WriteLine("Resumed:" + 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)
|
private IList<DebugType> FindTypesInModules(String name)
|
||||||
{
|
{
|
||||||
List<DebugType> result = new List<DebugType>();
|
List<DebugType> result = new List<DebugType>();
|
||||||
|
@ -207,6 +233,18 @@ namespace ikvm.debugger.win
|
||||||
return result;
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче