public async Task<IEnumerable<object>> Execute(OperationModel model, CancellationToken token, object customeParameter)
        {
            //TODO: add support of local variables
            return await DebuggerSession.Instance.ExecuteOperation(() =>
            {
                var result = new List<ClrStackDump>();
                foreach (var thread in DebuggerSession.Instance.Runtime.Threads)
                {
                    if (token.IsCancellationRequested)
                        break;
                
                    var stackDetails = new ClrStackDump();
                    stackDetails.StackFrames = new List<object>();
                    stackDetails.StackObjects = new List<object>();
                    foreach (var stackFrame in thread.StackTrace)
                    {
                        stackDetails.StackBase = thread.StackBase;
                        stackDetails.StackLimit = thread.StackLimit;
                        stackDetails.Exception = thread.CurrentException;
                        stackDetails.OSThreadID = thread.IsAlive ? thread.OSThreadId.ToString() : "XXX";
                        stackDetails.ManagedThreadId = thread.ManagedThreadId;
                        stackDetails.StackFrames.Add(
                        new
                        {
                            StackPointer = stackFrame.StackPointer,
                            InstructionPointer = stackFrame.InstructionPointer,
                            DisplayString = stackFrame.DisplayString,
                            //FileAndLine = source != null ? source.FilePath + ": " + source.LineNumber : "",
                            Method = stackFrame.Method
                        });
                    }

                    // We'll need heap data to find objects on the stack.
                    ClrHeap heap = DebuggerSession.Instance.Runtime.GetHeap();
                    var pointerSize = DebuggerSession.Instance.Runtime.PointerSize;
                    // Walk each pointer aligned address on the stack.  Note that StackBase/StackLimit
                    // is exactly what they are in the TEB.  This means StackBase > StackLimit on AMD64.
                    ulong start = thread.StackBase;
                    ulong stop = thread.StackLimit;

                    // We'll walk these in pointer order.
                    if (start > stop)
                    {
                        ulong tmp = start;
                        start = stop;
                        stop = tmp;
                    }

                    // Walk each pointer aligned address.  Ptr is a stack address.
                    for (ulong ptr = start; ptr <= stop; ptr += (ulong)pointerSize)
                    {
                        // Read the value of this pointer.  If we fail to read the memory, break.  The
                        // stack region should be in the crash dump.
                        ulong obj;
                        if (!DebuggerSession.Instance.Runtime.ReadPointer(ptr, out obj))
                            break;

                        // We check to see if this address is a valid object by simply calling
                        // GetObjectType.  If that returns null, it's not an object.
                        ClrType type = heap.GetObjectType(obj);
                        if (type == null)
                            continue;

                        // Don't print out free objects as there tends to be a lot of them on
                        // the stack.
                        if (type.IsFree) continue;

                        stackDetails.StackObjects.Add(
                            new
                            {
                                Address = ptr,
                                Object = obj,
                                Name = type.Name,
                                Value = new ClrObject(obj, type).Fields.Value
                            });
                    }
                    result.Add(stackDetails);
                }
                return result;
            });
        }
示例#2
0
        public async Task <IEnumerable <object> > Execute(OperationModel model, CancellationToken token, object customeParameter)
        {
            //TODO: add support of local variables
            return(await DebuggerSession.Instance.ExecuteOperation(() =>
            {
                var result = new List <ClrStackDump>();
                foreach (var thread in DebuggerSession.Instance.Runtime.Threads)
                {
                    if (token.IsCancellationRequested)
                    {
                        break;
                    }

                    var stackDetails = new ClrStackDump();
                    stackDetails.StackFrames = new List <object>();
                    stackDetails.StackObjects = new List <object>();
                    foreach (var stackFrame in thread.StackTrace)
                    {
                        stackDetails.StackBase = thread.StackBase;
                        stackDetails.StackLimit = thread.StackLimit;
                        stackDetails.Exception = thread.CurrentException;
                        stackDetails.OSThreadID = thread.IsAlive ? thread.OSThreadId.ToString() : "XXX";
                        stackDetails.ManagedThreadId = thread.ManagedThreadId;
                        stackDetails.StackFrames.Add(
                            new
                        {
                            StackPointer = stackFrame.StackPointer,
                            InstructionPointer = stackFrame.InstructionPointer,
                            DisplayString = stackFrame.DisplayString,
                            //FileAndLine = source != null ? source.FilePath + ": " + source.LineNumber : "",
                            Method = stackFrame.Method
                        });
                    }

                    ClrHeap heap = DebuggerSession.Instance.Runtime.GetHeap();
                    var pointerSize = DebuggerSession.Instance.Runtime.PointerSize;

                    // address of TEB (thread execution block) + pointer size
                    ulong start = thread.StackBase;
                    // address of TEB (thread execution block) + pointer size * 2
                    ulong stop = thread.StackLimit;

                    // We'll walk these in pointer order.
                    if (start > stop)
                    {
                        ulong tmp = start;
                        start = stop;
                        stop = tmp;
                    }

                    // ptr is a stack address.
                    for (ulong ptr = start; ptr <= stop; ptr += (ulong)pointerSize)
                    {
                        HashSet <ulong> stackObjects = new HashSet <ulong>();

                        // fail to read the memory
                        if (!heap.ReadPointer(ptr, out ulong obj))
                        {
                            break;
                        }

                        // the object added already
                        if (!stackObjects.Add(obj))
                        {
                            continue;
                        }

                        // not an object
                        ClrType type = heap.GetObjectType(obj);
                        if (type == null)
                        {
                            continue;
                        }

                        // free space
                        if (type.IsFree)
                        {
                            continue;
                        }

                        // All good, add it
                        stackDetails.StackObjects.Add(
                            new
                        {
                            Address = ptr,
                            Object = obj,
                            Name = type.Name,
                            Value = new ClrObject(obj, type).Fields.Value
                        });
                    }
                    result.Add(stackDetails);
                }
                return result;
            }));
        }