/// <summary> // Sets the value of one or more local variables. Each variable must be visible at the current frame code index. // For primitive values, the value's type must match the variable's type exactly. For object values, there must // be a widening reference conversion from the value's type to the variable's type and the variable's type must // be loaded. // Even if local variable information is not available, values can be set, if the front-end is able to determine // the correct local variable index. (Typically, this index can be determined for method arguments from the // method signature without access to the local variable table information.) /// </summary> public Task SetValuesAsync(ThreadId threadId, FrameId frameId, params SlotValue[] slotValues) { var conn = ConnectionOrError; DLog.Debug(DContext.DebuggerLibCommands, () => string.Format("StackFrame.SetValues {0}", string.Join(", ", slotValues.Select(x => x.ToString())))); var t = conn.SendAsync(JdwpPacket.CreateCommand(conn, Nr, 2, 4000 /* we don't know how long the packet is going to be... */, x => { var data = x.Data; threadId.WriteTo(data); frameId.WriteTo(data); data.SetInt(slotValues.Length); foreach (var value in slotValues) { value.Write(data); } x.Length = data.Offset; })); return(t.ContinueWith(x => { x.ForwardException(); var result = x.Result; result.ThrowOnError(); })); }
/// <summary> /// Read an untagged value. /// </summary> private static object ReadUntaggedValue(JdwpPacket.DataReaderWriter readerWriter, Jdwp.Tag tag) { switch (tag) { case Jdwp.Tag.Array: case Jdwp.Tag.Object: case Jdwp.Tag.String: case Jdwp.Tag.Thread: case Jdwp.Tag.ThreadGroup: case Jdwp.Tag.ClassLoader: case Jdwp.Tag.ClassObject: return new ObjectId(readerWriter); case Jdwp.Tag.Byte: return readerWriter.GetByte(); case Jdwp.Tag.Char: return (char)readerWriter.GetInt16(); case Jdwp.Tag.Float: return readerWriter.GetFloat(); case Jdwp.Tag.Double: return readerWriter.GetDouble(); case Jdwp.Tag.Int: return readerWriter.GetInt(); case Jdwp.Tag.Long: return readerWriter.GetLong(); case Jdwp.Tag.Short: return readerWriter.GetInt16(); case Jdwp.Tag.Void: return null; case Jdwp.Tag.Boolean: return readerWriter.GetBoolean(); default: throw new ArgumentException("Unknown tag " + (int)tag); } }
/// <summary> /// Gets the current call stack of the thread with given id. /// </summary> public Task <List <Tuple <FrameId, Location> > > FramesAsync(ThreadId id, int length = -1) { var conn = ConnectionOrError; var sizeInfo = conn.GetIdSizeInfo(); var t = conn.SendAsync(JdwpPacket.CreateCommand(conn, Nr, 6, sizeInfo.ObjectIdSize + 8, x => { id.WriteTo(x.Data); x.Data.SetInt(0); // start frame x.Data.SetInt(length); // length -1 == all })); return(t.ContinueWith(x => { x.ForwardException(); var result = x.Result; result.ThrowOnError(); var count = result.Data.GetInt(); var list = new List <Tuple <FrameId, Location> >(count); for (var i = 0; i < count; i++) { var frame = new FrameId(result.Data, sizeInfo); var location = new Location(result.Data); list.Add(Tuple.Create(frame, location)); } return list; })); }
/// <summary> /// Returns variable information for the method, including generic signatures for the variables. The variable table includes arguments and /// locals declared within the method. For instance methods, the "this" reference is included in the table. Also, synthetic variables may be /// present. Generic signatures are described in the signature attribute section in the Java Virtual Machine Specification, 3rd Edition. /// Since JDWP version 1.5. /// </summary> public Task <List <VariableInfo> > VariableTableWithGenericAsync(ReferenceTypeId typeId, MethodId methodId) { var conn = ConnectionOrError; var t = conn.SendAsync(JdwpPacket.CreateCommand(conn, Nr, 5, typeId.Size + methodId.Size, x => { var data = x.Data; typeId.WriteTo(data); methodId.WriteTo(data); })); return(t.ContinueWith(x => { x.ForwardException(); var result = x.Result; result.ThrowOnError(); var data = result.Data; var argCnt = data.GetInt(); var count = data.GetInt(); var list = new List <VariableInfo>(count); for (var i = 0; i < count; i++) { var codeIndex = data.GetLong(); var name = data.GetString(); var signature = data.GetString(); var genericSignature = data.GetString(); var length = data.GetInt(); var slot = data.GetInt(); list.Add(new VariableInfo(codeIndex, name, signature, genericSignature, length, slot)); } return list; })); }
private void HandleCompositeCommand(JdwpPacket packet) { var data = packet.Data; var suspendPolicy = (Jdwp.SuspendPolicy) data.GetByte(); var count = data.GetInt(); for (var i = 0; i < count; i++) { var eventKind = (Jdwp.EventKind) data.GetByte(); JdwpEvent evt; switch (eventKind) { case Jdwp.EventKind.VmInit: evt = new VmStart(data); break; case Jdwp.EventKind.SingleStep: evt = new SingleStep(data); break; case Jdwp.EventKind.BreakPoint: evt = new Breakpoint(data); break; case Jdwp.EventKind.MethodEntry: evt = new MethodEntry(data); break; case Jdwp.EventKind.MethodExit: evt = new MethodExit(data); break; case Jdwp.EventKind.Exception: evt = new Exception(data); break; case Jdwp.EventKind.ThreadStart: evt = new ThreadStart(data); break; case Jdwp.EventKind.ThreadEnd: evt = new ThreadDeath(data); break; case Jdwp.EventKind.ClassPrepare: evt = new ClassPrepare(data); break; case Jdwp.EventKind.ClassUnload: evt = new ClassUnload(data); break; case Jdwp.EventKind.FieldAccess: evt = new FieldAccess(data); break; case Jdwp.EventKind.FieldModification: evt = new FieldModification(data); break; case Jdwp.EventKind.VmDeath: evt = new VmDeath(data); break; default: throw new ArgumentException("Unknown event kind in compositive command " + (int)eventKind); } DLog.Debug(DContext.DebuggerLibDebugger, "JDWP event {0} {1}", eventKind, evt); Task.Factory.StartNew(() => { evt.Accept(compositeCommandProcessor, suspendPolicy); }); } }
/// <summary> /// Returns the value of one or more instance fields. Each field must be member of the object's type or one of its superclasses, /// superinterfaces, or implemented interfaces. Access control is not enforced; for example, the values of private fields can be obtained. /// </summary> public Task <List <Value> > GetValuesAsync(ObjectId objectId, FieldId[] fields) { var conn = ConnectionOrError; var sizeInfo = conn.GetIdSizeInfo(); var t = conn.SendAsync(JdwpPacket.CreateCommand(conn, Nr, 2, objectId.Size + 4 + (sizeInfo.FieldIdSize * fields.Length), x => { var data = x.Data; objectId.WriteTo(data); data.SetInt(fields.Length); foreach (var fieldId in fields) { fieldId.WriteTo(data); } })); return(t.ContinueWith(x => { x.ForwardException(); var result = x.Result; result.ThrowOnError(); var data = result.Data; var count = data.GetInt(); var list = new List <Value>(count); for (var i = 0; i < count; i++) { var value = new Value(data); list.Add(value); } return list; })); }
/// <summary> /// Returns the value of one or more local variables in a given frame. Each variable must be visible at the frame's code index. /// Even if local variable information is not available, values can be retrieved if the front-end is able to determine the correct /// local variable index. (Typically, this index can be determined for method arguments from the method signature without access to /// the local variable table information.) /// </summary> public Task <List <Value> > GetValuesAsync(ThreadId threadId, FrameId frameId, SlotRequest[] slots) { var conn = ConnectionOrError; DLog.Debug(DContext.DebuggerLibCommands, () => string.Format("StackFrame.GetValues {0}", string.Join(", ", slots.Select(x => x.ToString())))); var t = conn.SendAsync(JdwpPacket.CreateCommand(conn, Nr, 1, threadId.Size + frameId.Size + 4 + (slots.Length * 5), x => { var data = x.Data; threadId.WriteTo(data); frameId.WriteTo(data); data.SetInt(slots.Length); foreach (var slot in slots) { data.SetInt(slot.Slot); data.SetByte((byte)slot.Tag); } })); return(t.ContinueWith(x => { x.ForwardException(); var result = x.Result; result.ThrowOnError(); var data = result.Data; var count = data.GetInt(); var list = new List <Value>(count); for (var i = 0; i < count; i++) { var value = new Value(data); list.Add(value); } return list; })); }
/// <summary> /// Returns reference types for all classes currently loaded by the target VM. /// </summary> public Task <List <ClassInfo> > AllClassesWithGenericAsync() { var conn = ConnectionOrError; var sizeInfo = conn.GetIdSizeInfo(); var t = conn.SendAsync(JdwpPacket.CreateCommand(conn, Nr, 20, 0)); return(t.ContinueWith(x => { x.ForwardException(); var result = x.Result; result.ThrowOnError(); var data = result.Data; var count = data.GetInt(); var list = new List <ClassInfo>(); while (count > 0) { count--; var typeId = ReferenceTypeId.Read(data); var signature = data.GetString(); var genericSignature = data.GetString(); var status = data.GetInt(); list.Add(new ClassInfo(typeId, signature, genericSignature, (Jdwp.ClassStatus)status)); } return list; })); }
/// <summary> /// Returns information for each method in a reference type. Inherited methods are not included. The list of methods will include constructors /// (identified with the name "<init>"), the initialization method (identified with the name "<clinit>") if present, and any synthetic methods /// created by the compiler. Methods are returned in the order they occur in the class file. /// </summary> public Task <List <MethodInfo> > MethodsAsync(ReferenceTypeId id) { var conn = ConnectionOrError; var sizeInfo = conn.GetIdSizeInfo(); var t = conn.SendAsync(JdwpPacket.CreateCommand(conn, Nr, 15, sizeInfo.ReferenceTypeIdSize, x => id.WriteTo(x.Data))); return(t.ContinueWith(x => { x.ForwardException(); var result = x.Result; result.ThrowOnError(); var data = result.Data; var count = data.GetInt(); var list = new List <MethodInfo>(count); for (var i = 0; i < count; i++) { var methodId = new MethodId(data); var name = data.GetString(); var signature = data.GetString(); var genericSignature = data.GetString(); var accessFlags = data.GetInt(); list.Add(new MethodInfo(methodId, name, signature, genericSignature, accessFlags)); } return list; })); }
/// <summary> /// Returns a range of array components. The specified range must be within the bounds of the array. /// </summary> public Task <List <Value> > GetValuesAsync(ObjectId objectId, string elementSignature, int firstIndex, int length) { var conn = ConnectionOrError; var t = conn.SendAsync(JdwpPacket.CreateCommand(conn, Nr, 2, objectId.Size + 8, x => { var data = x.Data; objectId.WriteTo(data); data.SetInt(firstIndex); data.SetInt(length); })); return(t.ContinueWith(x => { x.ForwardException(); var result = x.Result; result.ThrowOnError(); var data = result.Data; var arrayElementTag = (Jdwp.Tag)data.GetByte(); var arrayElementIsObject = !arrayElementTag.IsPrimitive(); var count = data.GetInt(); var list = new List <Value>(count); for (var i = 0; i < count; i++) { var value = arrayElementIsObject ? new Value(data) : new Value(data, arrayElementTag); list.Add(value); } return list; })); }
/// <summary> /// Handle the given non-DDM, non-reply packet. /// </summary> private void PacketHandler(JdwpPacket packet) { if ((packet.CommandSet == 64) && (packet.Command == 100)) { // Composite command HandleCompositeCommand(packet); } }
/// <summary> /// Send the entire packet towards the target VM. /// </summary> protected internal void AddToWriteQueue(JdwpPacket packet) { packet.Id = GetNextId(); lock (writeQueueLock) { writeQueue.Enqueue(packet); Monitor.Pulse(writeQueueLock); } }
/// <summary> /// Removes all set breakpoints, a no-op if there are no breakpoints set. /// </summary> public Task ClearAllBreakpointsAsync() { var conn = ConnectionOrError; var t = conn.SendAsync(JdwpPacket.CreateCommand(conn, Nr, 3, 0)); return(t.ContinueWith(x => { x.ForwardException(); var result = x.Result; result.ThrowOnError(); })); }
/// <summary> /// Returns the immediate superclass of a class. /// </summary> public Task <ClassId> SuperclassAsync(ReferenceTypeId id) { var conn = ConnectionOrError; var t = conn.SendAsync(JdwpPacket.CreateCommand(conn, Nr, 1, id.Size, x => id.WriteTo(x.Data))); return(t.ContinueWith(x => { x.ForwardException(); var result = x.Result; result.ThrowOnError(); return new ClassId(result.Data); })); }
/// <summary> /// Resume the thread with given id. /// </summary> public Task ResumeAsync(ThreadId id) { var conn = ConnectionOrError; var sizeInfo = conn.GetIdSizeInfo(); var t = conn.SendAsync(JdwpPacket.CreateCommand(conn, Nr, 3, sizeInfo.ObjectIdSize, x => id.WriteTo(x.Data))); return(t.ContinueWith(x => { x.ForwardException(); var result = x.Result; result.ThrowOnError(); })); }
/// <summary> /// Returns the JNI signature of a reference type. JNI signature formats are described in the Java Native Inteface Specification /// For primitive classes the returned signature is the signature of the corresponding primitive type; for example, "I" is returned /// as the signature of the class represented by java.lang.Integer.TYPE. /// </summary> public Task <string> SignatureAsync(ReferenceTypeId id) { var conn = ConnectionOrError; var sizeInfo = conn.GetIdSizeInfo(); var t = conn.SendAsync(JdwpPacket.CreateCommand(conn, Nr, 1, sizeInfo.ReferenceTypeIdSize, x => id.WriteTo(x.Data))); return(t.ContinueWith(x => { x.ForwardException(); var result = x.Result; result.ThrowOnError(); return result.Data.GetString(); })); }
/// <summary> /// Request exit. /// </summary> public void Exit(int exitCode) { // Send exit command var conn = ConnectionOrError; conn.SendAsync(JdwpPacket.CreateCommand(conn, Nr, 10, 4, x => x.Data.SetInt(exitCode))); // Wait until write queue is empty conn.WaitUntilWriteQueueEmpty(); // Disconnect Debugger.Disconnect(); }
/// <summary> /// Create a command packet. /// </summary> public static JdwpPacket CreateCommand(IJdwpServerInfo serverInfo, int commandSet, int command, int dataLength, Action <JdwpPacket> initialize = null) { var data = new byte[HeaderLength + dataLength]; var packet = new JdwpPacket(serverInfo, data, 0) { CommandSet = commandSet, Command = command, Length = data.Length }; if (initialize != null) { initialize(packet); } return(packet); }
/// <summary> /// Try to find a packet in the given buffer. /// </summary> /// <returns>Null if not found</returns> private static JdwpPacket FindPacket(IJdwpServerInfo serverInfo, byte[] buffer, int length) { if (length < JdwpPacket.HeaderLength) { return(null); } var pkt = new JdwpPacket(serverInfo, buffer, 0); if (pkt.Length > length) { return(null); } return(new JdwpPacket(serverInfo, buffer, 0, true)); }
/// <summary> /// Clear an event request. See JDWP.EventKind for a complete list of events that can be cleared. Only the event request matching the /// specified event kind and requestID is cleared. If there isn't a matching event request the command is a no-op and does not result /// in an error. Automatically generated events do not have a corresponding event request and may not be cleared using this command. /// </summary> public Task ClearAsync(Jdwp.EventKind eventKind, int requestId) { var conn = ConnectionOrError; var t = conn.SendAsync(JdwpPacket.CreateCommand(conn, Nr, 2, 5, x => { var data = x.Data; data.SetByte((byte)eventKind); data.SetInt(requestId); })); return(t.ContinueWith(x => { x.ForwardException(); var result = x.Result; result.ThrowOnError(); })); }
/// <summary> /// Gets the status of a thread. /// </summary> public Task <ThreadStatusInfo> StatusAsync(ThreadId id) { var conn = ConnectionOrError; var sizeInfo = conn.GetIdSizeInfo(); var t = conn.SendAsync(JdwpPacket.CreateCommand(conn, Nr, 4, sizeInfo.ObjectIdSize, x => id.WriteTo(x.Data))); return(t.ContinueWith(x => { x.ForwardException(); var result = x.Result; result.ThrowOnError(); var threadStatus = result.Data.GetInt(); var suspendStatus = result.Data.GetInt(); return new ThreadStatusInfo((Jdwp.ThreadStatus)threadStatus, (Jdwp.SuspendStatus)suspendStatus); })); }
/// <summary> /// Request ID size information /// </summary> public Task <IdSizeInfo> IdSizesAsync() { var t = SendAsync(JdwpPacket.CreateCommand(this, 1, 7, 0)); return(t.ContinueWith(x => { x.ForwardException(); var result = x.Result; result.ThrowOnError(); var fieldIdSize = result.Data.GetInt(); var methodIdSize = result.Data.GetInt(); var objectIdSize = result.Data.GetInt(); var referenceTypeIdSize = result.Data.GetInt(); var frameIdSize = result.Data.GetInt(); return new IdSizeInfo(fieldIdSize, methodIdSize, objectIdSize, referenceTypeIdSize, frameIdSize); })); }
/// <summary> /// Returns the runtime type of the object. The runtime type will be a class or an array. /// </summary> public Task <ReferenceTypeId> ReferenceTypeAsync(ObjectId objectId) { var conn = ConnectionOrError; var t = conn.SendAsync(JdwpPacket.CreateCommand(conn, Nr, 1, objectId.Size, x => { var data = x.Data; objectId.WriteTo(data); })); return(t.ContinueWith(x => { x.ForwardException(); var result = x.Result; result.ThrowOnError(); return ReferenceTypeId.Read(result.Data); })); }
/// <summary> /// Request version data /// </summary> public Task <VersionInfo> VersionAsync() { var t = SendAsync(JdwpPacket.CreateCommand(this, 1, 1, 0)); return(t.ContinueWith(x => { x.ForwardException(); var result = x.Result; result.ThrowOnError(); var description = result.Data.GetString(); var major = result.Data.GetInt(); var minor = result.Data.GetInt(); var vmVersion = result.Data.GetString(); var vmName = result.Data.GetString(); return new VersionInfo(description, major, minor, vmVersion, vmName); })); }
/// <summary> /// Gets all threads in the VM. /// </summary> public Task <List <ThreadId> > AllThreadsAsync() { var conn = ConnectionOrError; var t = conn.SendAsync(JdwpPacket.CreateCommand(conn, Nr, 4, 0)); return(t.ContinueWith(x => { x.ForwardException(); var result = x.Result; result.ThrowOnError(); var count = result.Data.GetInt(); var list = new List <ThreadId>(); while (count > 0) { count--; list.Add(new ThreadId(result.Data)); } return list; })); }
/// <summary> /// Returns the value of one or more local variables in a given frame. Each variable must be visible at the frame's code index. /// Even if local variable information is not available, values can be retrieved if the front-end is able to determine the correct /// local variable index. (Typically, this index can be determined for method arguments from the method signature without access to /// the local variable table information.) /// </summary> public Task <List <Value> > GetValuesAsync(ThreadId threadId, FrameId frameId, SlotRequest[] slots) { var conn = ConnectionOrError; DLog.Debug(DContext.DebuggerLibCommands, () => string.Format("StackFrame.GetValues {0}", string.Join(", ", slots.Select(x => x.ToString())))); var t = conn.SendAsync(JdwpPacket.CreateCommand(conn, Nr, 1, threadId.Size + frameId.Size + 4 + (slots.Length * 5), x => { var data = x.Data; threadId.WriteTo(data); frameId.WriteTo(data); data.SetInt(slots.Length); foreach (var slot in slots) { if (slot.Slot == 1000) { // I have seen this crash the VM on a CyanogenMod Android 4.4.4 // Samsung GT-I9195. Might be a bug in CyanogenMod. // https://android.googlesource.com/platform/art/+/ffcd9d25199a944625bd3c9a766349c23dcbdb66/runtime/debugger.cc DLog.Debug(DContext.DebuggerLibEvent, "accessing variable with Slot=1000"); } data.SetInt(slot.Slot); data.SetByte((byte)slot.Tag); } })); return(t.ContinueWith(x => { x.ForwardException(); var result = x.Result; result.ThrowOnError(); var data = result.Data; var count = data.GetInt(); var list = new List <Value>(count); for (var i = 0; i < count; i++) { var value = new Value(data); list.Add(value); } return list; })); }
/// <summary> /// Returns the reference type reflected by this class object. /// </summary> public Task <ReferenceTypeId> ReflectedTypeAsync(ObjectId classObjectId) { var conn = ConnectionOrError; var t = conn.SendAsync(JdwpPacket.CreateCommand(conn, Nr, 1, classObjectId.Size, x => classObjectId.WriteTo(x.Data))); return(t.ContinueWith(x => { x.ForwardException(); var result = x.Result; result.ThrowOnError(); var kind = (Jdwp.TypeTag)x.Result.Data.GetByte(); if (kind == Jdwp.TypeTag.Array) { return (ReferenceTypeId) new ArrayTypeId(result.Data); } if (kind == Jdwp.TypeTag.Interface) { return new InterfaceId(result.Data); } return new ClassId(result.Data); })); }
/// <summary> /// Set an event request. When the event described by this request occurs, an event is sent from the target VM. /// If an event occurs that has not been requested then it is not sent from the target VM. The two exceptions to this are the /// VM Start Event and the VM Death Event which are automatically generated events - see Composite Command for further details. /// </summary> /// <returns>Task that returns a requestId</returns> public Task <int> SetAsync(Jdwp.EventKind eventKind, Jdwp.SuspendPolicy suspendPolicy, params EventModifier[] modifiers) { var conn = ConnectionOrError; var sizeInfo = conn.GetIdSizeInfo(); var size = 6 + modifiers.Sum(x => x.DataSize); var t = conn.SendAsync(JdwpPacket.CreateCommand(conn, Nr, 1, size, x => { var data = x.Data; data.SetByte((byte)eventKind); data.SetByte((byte)suspendPolicy); data.SetInt(modifiers.Length); foreach (var modifier in modifiers) { modifier.WriteTo(data); } })); return(t.ContinueWith(x => { x.ForwardException(); var result = x.Result; result.ThrowOnError(); return result.Data.GetInt(); })); }
/// <summary> /// Returns reference types that match the given signature. /// </summary> public Task <List <ClassInfo> > ClassBySignatureAsync(string signature) { var conn = ConnectionOrError; var sizeInfo = conn.GetIdSizeInfo(); var t = conn.SendAsync(JdwpPacket.CreateCommand(conn, Nr, 2, JdwpPacket.DataReaderWriter.GetStringSize(signature), x => x.Data.SetString(signature))); return(t.ContinueWith(x => { x.ForwardException(); var result = x.Result; result.ThrowOnError(); var data = result.Data; var count = data.GetInt(); var list = new List <ClassInfo>(); while (count > 0) { count--; var typeId = ReferenceTypeId.Read(data); var status = data.GetInt(); list.Add(new ClassInfo(typeId, signature, signature, (Jdwp.ClassStatus)status)); } return list; })); }
/// <summary> /// Read an untagged value. /// </summary> private static void WriteValue(JdwpPacket.DataReaderWriter data, Jdwp.Tag tag, object obj) { switch (tag) { //case Jdwp.Tag.Array: //case Jdwp.Tag.Object: //case Jdwp.Tag.String: //case Jdwp.Tag.Thread: //case Jdwp.Tag.ThreadGroup: //case Jdwp.Tag.ClassLoader: //case Jdwp.Tag.ClassObject: // return new ObjectId(readerWriter); case Jdwp.Tag.Byte: data.SetByte((byte)obj); break; case Jdwp.Tag.Short: case Jdwp.Tag.Char: data.SetInt16((int) obj); break; //case Jdwp.Tag.Float: // readerWriter.GetFloat(); //? // break; //case Jdwp.Tag.Double: // return readerWriter.SetDouble(); //? case Jdwp.Tag.Int: data.SetInt((int)obj); break; case Jdwp.Tag.Long: data.SetLong((long) obj); break; case Jdwp.Tag.Boolean: data.SetBoolean((bool)obj); break; default: throw new ArgumentException("unsupported tag " + tag); } }
/// <summary> /// Write the modifier to the writer of a packet. /// In this method the kind byte is written override to write additional data. /// </summary> internal override void WriteTo(JdwpPacket.DataReaderWriter writer) { base.WriteTo(writer); classId.WriteTo(writer); fieldId.WriteTo(writer); }
/// <summary> /// Read a tagged value. /// </summary> public Value(JdwpPacket.DataReaderWriter readerWriter) { Tag = (Jdwp.Tag) readerWriter.GetByte(); ValueObject = ReadUntaggedValue(readerWriter, Tag); }
/// <summary> /// Write the modifier to the writer of a packet. /// In this method the kind byte is written override to write additional data. /// </summary> internal override void WriteTo(JdwpPacket.DataReaderWriter writer) { base.WriteTo(writer); instanceId.WriteTo(writer); }
/// <summary> /// Write queued packets /// </summary> private void WriteLoop() { var myThread = Thread.CurrentThread; var errorCount = 0; while ((writeThread == myThread)) { // Too many errors or disconnected? if ((errorCount > MaxWriteErrors) || !tcpClient.Connected) { Disconnect.Fire(this); return; } JdwpPacket packet = null; lock (writeQueueLock) { if ((writeQueue.Count == 0) || (state == States.AwaitingHandshake)) { // Signal all waiters Monitor.PulseAll(writeQueueLock); // Now wait ourselves for new packets Monitor.Wait(writeQueueLock); } else { packet = writeQueue.Dequeue(); } } // Disconnected? if (!tcpClient.Connected) { Disconnect.Fire(this); return; } if ((packet != null) && (writeThread == myThread)) { var attempt = 0; var succeeded = false; while ((attempt < WriteAttempts) && !succeeded) { try { attempt++; DLog.Debug(DContext.DebuggerLibJdwpConnection, "Write {0}", packet); packet.WriteTo(tcpClient.GetStream()); succeeded = true; errorCount = Math.Max(errorCount - 1, 0); } catch { } } if (!succeeded) { errorCount++; } } } }
/// <summary> /// Default ctor /// </summary> internal DataReaderWriter(JdwpPacket packet, int offset) { this.packet = packet; this.Offset = offset; }
/// <summary> /// Resume the execution of the application running in the target VM. /// </summary> public Task ResumeAsync() { var conn = ConnectionOrError; return(conn.SendAsync(JdwpPacket.CreateCommand(conn, Nr, 9, 0))); }
/// <summary> /// Create a command packet. /// </summary> public static JdwpPacket CreateCommand(IJdwpServerInfo serverInfo, int commandSet, int command, int dataLength, Action<JdwpPacket> initialize = null) { var data = new byte[HeaderLength + dataLength]; var packet = new JdwpPacket(serverInfo, data, 0) { CommandSet = commandSet, Command = command, Length = data.Length }; if (initialize != null) { initialize(packet); } return packet; }
/// <summary> /// Write the modifier to the writer of a packet. /// In this method the kind byte is written override to write additional data. /// </summary> internal override void WriteTo(JdwpPacket.DataReaderWriter writer) { base.WriteTo(writer); location.WriteTo(writer); }
/// <summary> /// Write the modifier to the writer of a packet. /// In this method the kind byte is written override to write additional data. /// </summary> internal override void WriteTo(JdwpPacket.DataReaderWriter writer) { base.WriteTo(writer); writer.SetInt(count); }
/// <summary> /// Write the modifier to the writer of a packet. /// In this method the kind byte is written override to write additional data. /// </summary> internal override void WriteTo(JdwpPacket.DataReaderWriter writer) { base.WriteTo(writer); threadId.WriteTo(writer); writer.SetInt((int) stepSize); writer.SetInt((int) stepDepth); }
/// <summary> /// writes slot and value. /// </summary> /// <param name="data"></param> public void Write(JdwpPacket.DataReaderWriter data) { data.SetInt(Slot); WriteValue(data); }
/// <summary> /// writes only the value, without the slot. /// </summary> /// <param name="data"></param> public void WriteValue(JdwpPacket.DataReaderWriter data) { data.SetByte((byte)Tag); WriteValue(data, Tag, Value); }
private void HandleCompositeCommand(JdwpPacket packet) { var data = packet.Data; var suspendPolicy = (Jdwp.SuspendPolicy) data.GetByte(); var count = data.GetInt(); for (var i = 0; i < count; i++) { var eventKind = (Jdwp.EventKind) data.GetByte(); JdwpEvent evt; switch (eventKind) { case Jdwp.EventKind.VmInit: evt = new VmStart(data); break; case Jdwp.EventKind.SingleStep: evt = new SingleStep(data); break; case Jdwp.EventKind.BreakPoint: evt = new Breakpoint(data); break; case Jdwp.EventKind.MethodEntry: evt = new MethodEntry(data); break; case Jdwp.EventKind.MethodExit: evt = new MethodExit(data); break; case Jdwp.EventKind.Exception: evt = new Exception(data); break; case Jdwp.EventKind.ThreadStart: evt = new ThreadStart(data); break; case Jdwp.EventKind.ThreadEnd: evt = new ThreadDeath(data); break; case Jdwp.EventKind.ClassPrepare: evt = new ClassPrepare(data); break; case Jdwp.EventKind.ClassUnload: evt = new ClassUnload(data); break; case Jdwp.EventKind.FieldAccess: evt = new FieldAccess(data); break; case Jdwp.EventKind.FieldModification: evt = new FieldModification(data); break; case Jdwp.EventKind.VmDeath: evt = new VmDeath(data); break; default: throw new ArgumentException("Unknown event kind in compositive command " + (int)eventKind); } DLog.Debug(DContext.DebuggerLibDebugger, "JDWP event {0} {1}", eventKind, evt); Task.Factory.StartNew(() => { evt.Accept(compositeCommandProcessor, suspendPolicy); }).ContinueWith(task => { DLog.Error(DContext.DebuggerLibJdwpConnection, "HandleCompositeCommand: Internal failure on event processing. SuspendPolicy was {1}; IsCancelled={0}. Exception={1}", suspendPolicy, task.IsCanceled, task.Exception); if (suspendPolicy != Jdwp.SuspendPolicy.None) { // we should better resume the VM, as the command handler may have failed to do so. if(Connected) VirtualMachine.ResumeAsync(); } }, TaskContinuationOptions.NotOnRanToCompletion); } }
/// <summary> /// Write the modifier to the writer of a packet. /// In this method the kind byte is written override to write additional data. /// </summary> internal override void WriteTo(JdwpPacket.DataReaderWriter writer) { base.WriteTo(writer); exceptionClassId.WriteTo(writer); writer.SetBoolean(caught); writer.SetBoolean(uncaught); }
/// <summary> /// Default ctor /// </summary> internal DataReaderWriter(JdwpPacket packet, int offset) { this.packet = packet; this._offset = offset; }
/// <summary> /// Write the modifier to the writer of a packet. /// In this method the kind byte is written override to write additional data. /// </summary> internal override void WriteTo(JdwpPacket.DataReaderWriter writer) { base.WriteTo(writer); threadId.WriteTo(writer); }
/// <summary> /// Read an untagged value. /// </summary> public Value(JdwpPacket.DataReaderWriter readerWriter, Jdwp.Tag tag) { Tag = tag; ValueObject = ReadUntaggedValue(readerWriter, tag); }
/// <summary> /// Write the modifier to the writer of a packet. /// In this method the kind byte is written override to write additional data. /// </summary> internal override void WriteTo(JdwpPacket.DataReaderWriter writer) { base.WriteTo(writer); writer.SetString(classPattern); }
/// <summary> /// Default ctor /// </summary> internal DataReaderWriter(JdwpPacket packet, int offset) : base(packet, offset) { }
/// <summary> /// Write the modifier to the writer of a packet. /// In this method the kind byte is written override to write additional data. /// </summary> internal virtual void WriteTo(JdwpPacket.DataReaderWriter writer) { writer.SetByte((byte) kind); }