зеркало из 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);
|
||||
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);
|
||||
|
@ -98,7 +104,10 @@ namespace ikvm.debugger
|
|||
|
||||
internal void SendPacket(Packet packet)
|
||||
{
|
||||
packet.Send(stream);
|
||||
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);
|
||||
WriteByte(Reply);
|
||||
WriteShort(errorCode);
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче