/// <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;
                }));
            }
Exemple #2
0
            /// <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>
            /// 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;
                }));
            }
            /// <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>
            /// 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>
            // 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();
                }));
            }
Exemple #7
0
            /// <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 "&lt;init&gt;"), the initialization method (identified with the name "&lt;clinit&gt;") 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;
                }));
            }
Exemple #8
0
            /// <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>
            /// 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();
                }));
            }
Exemple #12
0
            /// <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();
            }
Exemple #13
0
            /// <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>
            /// 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 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>
            /// 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 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);
            }));
        }
Exemple #19
0
            /// <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();
                }));
            }
Exemple #23
0
            /// <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;
                }));
            }
Exemple #24
0
            /// <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)));
            }