Example #1
0
 /// <summary>
 /// Default ctor
 /// </summary>
 public EventStepModifier(ThreadId threadId, Jdwp.StepSize stepSize, Jdwp.StepDepth stepDepth)
     : base(10)
 {
     this.threadId  = threadId;
     this.stepSize  = stepSize;
     this.stepDepth = stepDepth;
 }
            /// <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>
            // 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>
            /// 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>
            /// 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>
            /// 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>
            /// 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;
                }));
            }
Example #8
0
 protected override DalvikThread CreateThread(Dot42.DebuggerLib.ThreadId id)
 {
     return(new DebugThread(id, this));
 }
Example #9
0
 /// <summary>
 /// Default ctor
 /// </summary>
 public EventThreadOnlyModifier(ThreadId threadId)
     : base(3)
 {
     this.threadId = threadId;
 }