2009-02-08 12:30:55 +03:00
/ *
Copyright ( C ) 2009 Volker Berlin ( vberlin @inetsoftware . de )
This software is provided ' as - is ' , without any express or implied
warranty . In no event will the authors be held liable for any damages
arising from the use of this software .
Permission is granted to anyone to use this software for any purpose ,
including commercial applications , and to alter it and redistribute it
freely , subject to the following restrictions :
1. The origin of this software must not be misrepresented ; you must not
claim that you wrote the original software . If you use this software
in a product , an acknowledgment in the product documentation would be
appreciated but is not required .
2. Altered source versions must be plainly marked as such , and must not be
misrepresented as being the original software .
3. This notice may not be removed or altered from any source distribution .
Jeroen Frijters
jeroen @frijters . net
* /
2009-02-15 01:03:22 +03:00
2009-02-04 22:24:29 +03:00
using System ;
2009-02-04 22:08:20 +03:00
using System.Collections.Generic ;
using System.Text ;
2009-02-15 01:03:22 +03:00
using ikvm.debugger.requests ;
2009-02-21 01:20:41 +03:00
using ikvm.debugger.win ;
2009-02-04 22:08:20 +03:00
namespace ikvm.debugger
{
/// <summary>
/// Implementation of the JDWP Protocol. The documentation is at:
/// http://java.sun.com/javase/6/docs/platform/jpda/jdwp/jdwp-protocol.html
/// </summary>
class JdwpHandler
{
private readonly JdwpConnection conn ;
2009-02-08 12:30:55 +03:00
// TODO Create a real implementation
private readonly TargetVM target ;
internal JdwpHandler ( JdwpConnection conn , TargetVM target )
2009-02-04 22:08:20 +03:00
{
this . conn = conn ;
2009-02-08 12:30:55 +03:00
this . target = target ;
2009-02-04 22:08:20 +03:00
}
internal void Run ( )
{
while ( true )
{
Packet packet = conn . ReadPacket ( ) ;
2009-02-12 23:49:23 +03:00
Console . Error . WriteLine ( "Packet:" + packet . CommandSet + " " + packet . Command ) ;
2009-02-04 22:08:20 +03:00
switch ( packet . CommandSet )
{
case CommandSet . VirtualMachine :
CommandSetVirtualMachine ( packet ) ;
break ;
2009-02-12 23:49:23 +03:00
case CommandSet . ReferenceType :
CommandSetReferenceType ( packet ) ;
break ;
2009-02-05 00:27:01 +03:00
case CommandSet . EventRequest :
CommandSetEventRequest ( packet ) ;
break ;
2009-02-04 22:08:20 +03:00
default :
2009-02-05 00:27:01 +03:00
NotImplementedPacket ( packet ) ;
2009-02-04 22:08:20 +03:00
break ;
}
2009-02-21 12:27:04 +03:00
conn . SendPacket ( packet ) ;
2009-02-04 22:08:20 +03:00
}
}
2009-02-08 12:30:55 +03:00
/// <summary>
/// http://java.sun.com/javase/6/docs/platform/jpda/jdwp/jdwp-protocol.html#JDWP_VirtualMachine
/// </summary>
/// <param name="packet"></param>
2009-02-04 22:08:20 +03:00
private void CommandSetVirtualMachine ( Packet packet )
{
switch ( packet . Command )
{
2009-02-05 23:27:10 +03:00
case VirtualMachine . Version :
packet . WriteString ( "IKVM Debugger" ) ;
packet . WriteInt ( 1 ) ;
packet . WriteInt ( 6 ) ;
packet . WriteString ( "1.6.0" ) ;
packet . WriteString ( "IKVM.NET" ) ;
2009-02-12 23:49:23 +03:00
break ;
case VirtualMachine . ClassesBySignature :
String jniClassName = packet . ReadString ( ) ;
2009-02-21 01:20:41 +03:00
IList < TargetType > types = target . FindTypes ( jniClassName ) ;
packet . WriteInt ( types . Count ) ; // count
2009-02-12 23:49:23 +03:00
2009-02-21 01:20:41 +03:00
foreach ( TargetType type in types )
{
Console . Error . WriteLine ( "FindTypes:" + jniClassName + ":" + type . TypeId ) ;
packet . WriteByte ( TypeTag . CLASS ) ; //TODO can also a interface
packet . WriteObjectID ( type . TypeId ) ;
packet . WriteInt ( ClassStatus . INITIALIZED ) ;
}
2009-02-12 23:49:23 +03:00
2009-02-05 23:27:10 +03:00
break ;
2009-02-08 12:30:55 +03:00
case VirtualMachine . AllThreads :
int [ ] ids = target . GetThreadIDs ( ) ;
packet . WriteInt ( ids . Length ) ;
for ( int i = 0 ; i < ids . Length ; i + + )
{
packet . WriteObjectID ( ids [ i ] ) ;
}
break ;
2009-02-04 22:08:20 +03:00
case VirtualMachine . IDSizes :
2009-02-15 01:03:22 +03:00
int size = 4 ; //we use a size of 4, a value of 8 is also possible
2009-02-04 22:08:20 +03:00
packet . WriteInt ( size ) ; // fieldID size in bytes
packet . WriteInt ( size ) ; // methodID size in bytes
packet . WriteInt ( size ) ; // objectID size in bytes
packet . WriteInt ( size ) ; // referenceTypeID size in bytes
packet . WriteInt ( size ) ; // frameID size in bytes
break ;
2009-02-15 23:57:01 +03:00
case VirtualMachine . Suspend :
target . Suspend ( ) ;
break ;
2009-02-19 00:39:49 +03:00
case VirtualMachine . Resume :
target . Resume ( ) ;
break ;
2009-02-12 23:49:23 +03:00
case VirtualMachine . Exit :
2009-02-19 00:39:49 +03:00
target . Exit ( packet . ReadInt ( ) ) ;
2009-02-21 12:27:04 +03:00
break ;
case VirtualMachine . Capabilities :
packet . WriteBool ( false ) ; // Can the VM watch field modification, and therefore can it send the Modification Watchpoint Event?
packet . WriteBool ( false ) ; // Can the VM watch field access, and therefore can it send the Access Watchpoint Event?
packet . WriteBool ( false ) ; // Can the VM get the bytecodes of a given method?
packet . WriteBool ( false ) ; // Can the VM determine whether a field or method is synthetic? (that is, can the VM determine if the method or the field was invented by the compiler?)
packet . WriteBool ( false ) ; // Can the VM get the owned monitors infornation for a thread?
packet . WriteBool ( false ) ; // Can the VM get the current contended monitor of a thread?
packet . WriteBool ( false ) ; // Can the VM get the monitor information for a given object?
break ;
case VirtualMachine . CapabilitiesNew :
packet . WriteBool ( false ) ; // Can the VM watch field modification, and therefore can it send the Modification Watchpoint Event?
packet . WriteBool ( false ) ; // Can the VM watch field access, and therefore can it send the Access Watchpoint Event?
packet . WriteBool ( false ) ; // Can the VM get the bytecodes of a given method?
packet . WriteBool ( false ) ; // Can the VM determine whether a field or method is synthetic? (that is, can the VM determine if the method or the field was invented by the compiler?)
packet . WriteBool ( false ) ; // Can the VM get the owned monitors infornation for a thread?
packet . WriteBool ( false ) ; // Can the VM get the current contended monitor of a thread?
packet . WriteBool ( false ) ; // Can the VM get the monitor information for a given object?
packet . WriteBool ( false ) ; // Can the VM redefine classes?
packet . WriteBool ( false ) ; // Can the VM add methods when redefining classes?
packet . WriteBool ( false ) ; // Can the VM redefine classesin arbitrary ways?
packet . WriteBool ( false ) ; // Can the VM pop stack frames?
packet . WriteBool ( false ) ; // Can the VM filter events by specific object?
packet . WriteBool ( false ) ; // Can the VM get the source debug extension?
packet . WriteBool ( false ) ; // Can the VM request VM death events?
packet . WriteBool ( false ) ; // Can the VM set a default stratum?
packet . WriteBool ( false ) ; // Can the VM return instances, counts of instances of classes and referring objects?
packet . WriteBool ( false ) ; // Can the VM request monitor events?
packet . WriteBool ( false ) ; // Can the VM get monitors with frame depth info?
packet . WriteBool ( false ) ; // Can the VM filter class prepare events by source name?
packet . WriteBool ( false ) ; // Can the VM return the constant pool information?
packet . WriteBool ( false ) ; // Can the VM force early return from a method?
packet . WriteBool ( false ) ; // reserved22
packet . WriteBool ( false ) ; // reserved23
packet . WriteBool ( false ) ; // reserved24
packet . WriteBool ( false ) ; // reserved25
packet . WriteBool ( false ) ; // reserved26
packet . WriteBool ( false ) ; // reserved27
packet . WriteBool ( false ) ; // reserved28
packet . WriteBool ( false ) ; // reserved29
packet . WriteBool ( false ) ; // reserved30
packet . WriteBool ( false ) ; // reserved31
packet . WriteBool ( false ) ; // reserved32
2009-02-12 23:49:23 +03:00
break ;
2009-02-04 22:08:20 +03:00
default :
2009-02-15 23:57:01 +03:00
NotImplementedPacket ( packet ) ; // include a SendPacket
2009-02-05 00:27:01 +03:00
break ;
}
}
2009-02-12 23:49:23 +03:00
/// <summary>
/// http://java.sun.com/javase/6/docs/platform/jpda/jdwp/jdwp-protocol.html#JDWP_ReferenceType
/// </summary>
/// <param name="packet"></param>
private void CommandSetReferenceType ( Packet packet )
{
switch ( packet . Command )
{
2009-02-21 01:20:41 +03:00
case ReferenceType . Signature :
int typeID = packet . ReadObjectID ( ) ;
TargetType type = target . FindType ( typeID ) ;
Console . Error . WriteLine ( typeID + ":" + type . GetJniSignature ( ) ) ;
packet . WriteString ( type . GetJniSignature ( ) ) ;
break ;
case ReferenceType . ClassLoader :
int classLoaderID = packet . ReadObjectID ( ) ;
packet . WriteObjectID ( 0 ) ; //TODO 0 - System Classloader, we can use module ID instead
break ;
2009-02-12 23:49:23 +03:00
case ReferenceType . MethodsWithGeneric :
2009-02-21 01:20:41 +03:00
typeID = packet . ReadObjectID ( ) ;
Console . Error . WriteLine ( typeID ) ;
type = target . FindType ( typeID ) ;
IList < TargetMethod > methods = type . GetMethods ( ) ;
packet . WriteInt ( methods . Count ) ;
foreach ( TargetMethod method in methods )
{
Console . Error . WriteLine ( method . MethodId + ":" + method . Name + ":" + method . JniSignature + ":" + method . GenericSignature + ":" + method . AccessFlags ) ;
packet . WriteObjectID ( method . MethodId ) ;
packet . WriteString ( method . Name ) ;
packet . WriteString ( method . JniSignature ) ;
packet . WriteString ( method . GenericSignature ) ;
packet . WriteInt ( method . AccessFlags ) ;
}
2009-02-12 23:49:23 +03:00
break ;
default :
NotImplementedPacket ( packet ) ;
break ;
}
}
/// <summary>
/// http://java.sun.com/javase/6/docs/platform/jpda/jdwp/jdwp-protocol.html#JDWP_EventRequest
/// </summary>
/// <param name="packet"></param>
2009-02-05 00:27:01 +03:00
private void CommandSetEventRequest ( Packet packet )
{
switch ( packet . Command )
{
2009-02-12 23:49:23 +03:00
case EventRequest . CmdSet :
EventRequest eventRequest = EventRequest . create ( packet ) ;
Console . Error . WriteLine ( eventRequest ) ;
if ( eventRequest = = null )
2009-02-05 23:27:10 +03:00
{
NotImplementedPacket ( packet ) ;
}
2009-02-12 23:49:23 +03:00
else
{
2009-02-22 12:09:41 +03:00
target . AddEventRequest ( eventRequest ) ;
packet . WriteInt ( eventRequest . RequestId ) ;
2009-02-12 23:49:23 +03:00
}
2009-02-05 23:27:10 +03:00
break ;
2009-02-05 00:27:01 +03:00
default :
NotImplementedPacket ( packet ) ;
2009-02-04 22:08:20 +03:00
break ;
}
}
2009-02-05 00:27:01 +03:00
private void NotImplementedPacket ( Packet packet )
2009-02-04 22:08:20 +03:00
{
2009-02-21 12:27:04 +03:00
Console . Error . WriteLine ( "================================" ) ;
2009-02-05 00:27:01 +03:00
Console . Error . WriteLine ( "Not Implemented Packet:" + packet . CommandSet + "-" + packet . Command ) ;
2009-02-21 12:27:04 +03:00
Console . Error . WriteLine ( "================================" ) ;
2009-02-04 22:08:20 +03:00
packet . Error = Error . NOT_IMPLEMENTED ;
}
}
}