Example #1
0
        public static void ExecuteDbgEngCommand(this DataTarget target, string command, CommandExecutionContext context)
        {
            IDebugControl6 control = (IDebugControl6)target.DebuggerInterface;
            int            hr      = control.ExecuteWide(
                DEBUG_OUTCTL.THIS_CLIENT, command, DEBUG_EXECUTE.DEFAULT);

            if (HR.Failed(hr))
            {
                context.WriteErrorLine("Command execution failed with hr = {0:x8}", hr);
            }
        }
Example #2
0
            private string GetModuleName(IXCLRDataModule module)
            {
                StringBuilder name = new StringBuilder(MaxNameSize);
                uint          nameLen;

                if (HR.Failed(module.GetName((uint)name.Capacity, out nameLen, name)))
                {
                    return(null);
                }

                return(name.ToString());
            }
Example #3
0
            private bool FailedUnlessOnCLR2DAC(int hr)
            {
                // For CLR v2 DAC, if the return HRESULT is random garbage, ignore the error.
                // This happens because of a source-level bug in the DAC that returns an
                // uninitialized stack variable. This was confirmed by a Microsoft engineer.
                if (_isOnCLRv2)
                {
                    return(false);
                }

                return(HR.Failed(hr));
            }
        private DataTarget CreateDbgEngDataTargetImpl()
        {
            if (String.IsNullOrEmpty(DumpFile))
            {
                throw new InvalidOperationException("DbgEng targets can be created only for dump files at this point.");
            }

            var target = DataTarget.LoadCrashDump(DumpFile, CrashDumpReader.DbgEng);

            target.AppendSymbolPath(SymbolPath);

            var outputCallbacks       = new OutputCallbacks(this);
            msos_IDebugClient5 client = (msos_IDebugClient5)target.DebuggerInterface;

            HR.Verify(client.SetOutputCallbacksWide(outputCallbacks));

            return(target);
        }
Example #5
0
            private void ProcessStackWalk(uint osThreadId)
            {
                IXCLRDataProcess ixclrDataProcess = _context.Runtime.DacInterface;

                object tmp;

                HR.Verify(ixclrDataProcess.GetTaskByOSThreadID(osThreadId, out tmp));

                IXCLRDataTask task = (IXCLRDataTask)tmp;

                HR.Verify(task.CreateStackWalk(0xf /*all flags*/, out tmp));

                IXCLRDataStackWalk stackWalk = (IXCLRDataStackWalk)tmp;

                while (HR.S_OK == stackWalk.Next())
                {
                    ProcessFrame(stackWalk);
                }
            }
Example #6
0
            public void Fill(IDebugAdvanced2 debugAdvanced)
            {
                int size = Marshal.SizeOf(typeof(DEBUG_THREAD_BASIC_INFORMATION));

                byte[] buffer = new byte[size];
                if (HR.Failed(debugAdvanced.GetSystemObjectInformation(
                                  DEBUG_SYSOBJINFO.THREAD_BASIC_INFORMATION, 0, EngineThreadId, buffer, buffer.Length, out size)))
                {
                    return;
                }

                var gch = GCHandle.Alloc(buffer, GCHandleType.Pinned);

                try
                {
                    var threadBasicInformation = (DEBUG_THREAD_BASIC_INFORMATION)
                                                 Marshal.PtrToStructure(gch.AddrOfPinnedObject(), typeof(DEBUG_THREAD_BASIC_INFORMATION));
                    if ((threadBasicInformation.Valid & DEBUG_TBINFO.AFFINITY) != 0)
                    {
                        Affinity = threadBasicInformation.Affinity;
                    }
                    if ((threadBasicInformation.Valid & DEBUG_TBINFO.PRIORITY_CLASS) != 0)
                    {
                        PriorityClass = threadBasicInformation.PriorityClass;
                    }
                    if ((threadBasicInformation.Valid & DEBUG_TBINFO.PRIORITY) != 0)
                    {
                        Priority = threadBasicInformation.Priority;
                    }
                    if ((threadBasicInformation.Valid & DEBUG_TBINFO.TIMES) != 0)
                    {
                        CreateTime = threadBasicInformation.CreateTime;
                        KernelTime = threadBasicInformation.KernelTime;
                        UserTime   = threadBasicInformation.UserTime;
                    }
                }
                finally
                {
                    gch.Free();
                }
            }
Example #7
0
        private ulong GetStacksSize(DataTarget target)
        {
            // Find all the TEBs and then sum StackBase - StackLimit for all of them.
            // This gives us the committed size for each thread, but we don't have the
            // reserved size (which is the actual address space consumed). Theoretically,
            // we could get it from enumerating the memory region adjacent to the committed
            // pages and the guard page that follows. Also, for WoW64 threads, we are only
            // reporting the x86 stack (the x64 stack doesn't live in the 4GB address space
            // anyway, so it's not that relevant).

            IDebugSystemObjects sysObjects = (IDebugSystemObjects)target.DebuggerInterface;
            uint numThreads;

            HR.Verify(sysObjects.GetNumberThreads(out numThreads));

            ulong totalCommit = 0;

            for (uint i = 0; i < numThreads; ++i)
            {
                HR.Verify(sysObjects.SetCurrentThreadId(i));

                ulong tebAddress;
                HR.Verify(sysObjects.GetCurrentThreadTeb(out tebAddress));

                int    read;
                byte[] teb = new byte[IntPtr.Size * 3]; // ExceptionList, StackBase, StackLimit
                if (target.ReadProcessMemory(tebAddress, teb, teb.Length, out read) &&
                    read == teb.Length)
                {
                    ulong stackBase  = AddressFromBytes(teb, IntPtr.Size);
                    ulong stackLimit = AddressFromBytes(teb, IntPtr.Size * 2);
                    totalCommit = stackBase - stackLimit;
                }
            }

            return(totalCommit);
        }
Example #8
0
        private DataTarget CreateDbgEngDataTargetImpl()
        {
            if (String.IsNullOrEmpty(DumpFile))
            {
                throw new InvalidOperationException("DbgEng targets can be created only for dump files at this point.");
            }

            var target = DataTarget.LoadCrashDump(DumpFile, CrashDumpReader.DbgEng);

            target.SymbolLocator.SymbolPath = SymbolPath;
            ((IDebugSymbols)target.DebuggerInterface).SetSymbolPath(SymbolPath);
            if (DisplayDiagnosticInformation)
            {
                ((IDebugControl)target.DebuggerInterface).Execute(DEBUG_OUTCTL.NOT_LOGGED, "!sym noisy", DEBUG_EXECUTE.NOT_LOGGED);
            }
            ((IDebugControl)target.DebuggerInterface).Execute(DEBUG_OUTCTL.NOT_LOGGED, ".reload", DEBUG_EXECUTE.NOT_LOGGED);

            var           outputCallbacks = new OutputCallbacks(this);
            IDebugClient5 client          = (IDebugClient5)target.DebuggerInterface;

            HR.Verify(client.SetOutputCallbacksWide(outputCallbacks));

            return(target);
        }
Example #9
0
            private void FillValue(ArgumentOrLocal argOrLocal, IXCLRDataValue value)
            {
                object tmp;

                ulong size;

                if (HR.Failed(value.GetSize(out size)))
                {
                    size = 0; // When the value is unavailable, GetSize fails; consider it 0
                }
                argOrLocal.Size = size;

                bool probablyReferenceType = false;
                int  getTypeHr             = value.GetType(out tmp);

                if (getTypeHr == HR.S_FALSE)
                {
                    // For reference types, GetType returns S_FALSE and we need to call GetAssociatedType
                    // to retrieve the type that the reference points to.
                    getTypeHr             = value.GetAssociatedType(out tmp);
                    probablyReferenceType = (getTypeHr == HR.S_OK);
                }

                if (getTypeHr != HR.S_OK)
                {
                    return;
                }

                IXCLRDataTypeInstance typeInstance = (IXCLRDataTypeInstance)tmp;
                StringBuilder         typeName     = new StringBuilder(MaxNameSize);
                uint typeNameLen;

                if (FailedUnlessOnCLR2DAC(typeInstance.GetName(0 /*CLRDATA_GETNAME_DEFAULT*/, (uint)typeName.Capacity, out typeNameLen, typeName)))
                {
                    return;
                }

                argOrLocal.StaticTypeName = typeName.ToString();
                argOrLocal.ClrType        = _context.Heap.GetTypeByName(argOrLocal.StaticTypeName);

                // If the value is unavailable, we're done here.
                if (size == 0)
                {
                    return;
                }

                FillLocation(argOrLocal, value);

                argOrLocal.Value = new byte[size];
                uint dataSize;

                if (HR.Failed(value.GetBytes((uint)argOrLocal.Value.Length, out dataSize, argOrLocal.Value)))
                {
                    argOrLocal.Value = null;
                }

                // If the type is an array type (e.g. System.Byte[]), or a pointer type
                // (e.g. System.Byte*), or a by-ref type (e.g. System.Byte&), ClrHeap.GetTypeByName
                // will never return a good value. This is only a problem with variables that
                // are either ref types and null (and then we can't get the type name from
                // the object itself), variables that are pointers, and variables that are
                // by-ref types. Here's the plan:
                //  1) If the variable is a ref type and is null, we don't care about the
                //     ClrType being correct anyway. We report the type returned by GetName
                //     above, and report the value as null.
                //  2) If the value is a by-ref type or a pointer type, IXCLRDataValue::GetFlags
                //     can detect it. Then, we keep the ClrType null (because ClrMD doesn't have
                //     a representation for pointer types or by-ref types), but we read the
                //     value anyway by dereferencing the pointer. According to the comments in
                //     xclrdata.idl, IXCLRDataValue::GetAssociatedValue is supposed to return the
                //     pointed-to value, but it doesn't (it only works for references).

                uint             vf;
                CLRDataValueFlag valueFlags = CLRDataValueFlag.Invalid;

                if (HR.S_OK == value.GetFlags(out vf))
                {
                    valueFlags = (CLRDataValueFlag)vf;
                }

                // * Pointers are identified as CLRDATA_VALUE_IS_POINTER.
                // * By-refs are identified as CLRDATA_VALUE_DEFAULT regardless of referenced type.
                bool byRefOrPointerType =
                    (valueFlags & CLRDataValueFlag.CLRDATA_VALUE_IS_POINTER) != 0 ||
                    (valueFlags == CLRDataValueFlag.CLRDATA_VALUE_DEFAULT /* it is 0 */);

                if (byRefOrPointerType)
                {
                    // By-refs to pointers are identified as CLRDATA_VALUE_DEFAULT with target UInt64,
                    // which makes them undistinguishable from 'ref ulong', unfortunately. But if the
                    // type name reported didn't include the &, we know that's what it is.
                    if (argOrLocal.StaticTypeName == "System.UInt64")
                    {
                        argOrLocal.ClrType        = null; // We don't really know what the type is
                        argOrLocal.StaticTypeName = "UNKNOWN*&";
                    }

                    if (argOrLocal.Value != null)
                    {
                        ulong ptrValue = RawBytesToAddress(argOrLocal.Value);

                        ulong potentialReference;
                        if (_context.Runtime.ReadPointer(ptrValue, out potentialReference) &&
                            (argOrLocal.ClrType = _context.Heap.GetObjectType(potentialReference)) != null)
                        {
                            // If the type was resolved, then this was the address of a heap object.
                            // In that case, we're done and we have a type.
                            argOrLocal.ObjectAddress = potentialReference;
                        }
                        else
                        {
                            // Otherwise, this address is the address of a value type. We don't know
                            // which type, because IXCLRDataValue::GetAssociatedType doesn't return anything
                            // useful when the value is a pointer or by-ref. But we can try to remove
                            // the * or & from the type name, and then try to figure out what the target
                            // type is.
                            string noRefNoPtrTypeName = argOrLocal.StaticTypeName.TrimEnd('&', '*');
                            if ((argOrLocal.ClrType = _context.Heap.GetTypeByName(noRefNoPtrTypeName))
                                != null)
                            {
                                argOrLocal.Location = ptrValue;
                            }
                        }
                    }
                }

                if (argOrLocal.ClrType == null)
                {
                    // If the type is an inner type, IXCLRDataTypeInstance::GetName reports only
                    // the inner part of the type. This isn't enough for ClrHeap.GetTypeByName,
                    // so we have yet another option in that case -- searching by metadata token.
                    TryGetTypeByMetadataToken(argOrLocal, typeInstance);

                    // If we had a pointer or by-ref type and didn't know what it was, we now do,
                    // so we can store its location and have it displayed.
                    if (byRefOrPointerType && argOrLocal.ClrType != null)
                    {
                        argOrLocal.Location = RawBytesToAddress(argOrLocal.Value);
                    }
                }

                if (!byRefOrPointerType && (probablyReferenceType || argOrLocal.IsReferenceType))
                {
                    argOrLocal.ObjectAddress = RawBytesToAddress(argOrLocal.Value);
                    // The type assigned here can be different from the previous value,
                    // because the static and dynamic type of the argument could differ.
                    // If the object reference is null or invalid, it could also be null --
                    // so we keep the previous type if it was already available.
                    argOrLocal.ClrType =
                        _context.Heap.GetObjectType(argOrLocal.ObjectAddress) ?? argOrLocal.ClrType;
                }
            }
Example #10
0
            private void ProcessFrame(IXCLRDataStackWalk stackWalk)
            {
                object tmp;

                if (HR.Failed(stackWalk.GetFrame(out tmp)))
                {
                    return;
                }

                IXCLRDataFrame frame = (IXCLRDataFrame)tmp;

                StringBuilder methodName = new StringBuilder(MaxNameSize);
                uint          methodNameLen;

                if (HR.Failed(frame.GetCodeName(0 /*default flags*/, (uint)methodName.Capacity, out methodNameLen, methodName)))
                {
                    return;
                }

                uint numArgs, numLocals;

                if (HR.Failed(frame.GetNumArguments(out numArgs)))
                {
                    numArgs = 0;
                }
                if (HR.Failed(frame.GetNumLocalVariables(out numLocals)))
                {
                    numLocals = 0;
                }

                FrameArgumentsAndLocals frameArgsLocals = new FrameArgumentsAndLocals()
                {
                    MethodName = methodName.ToString()
                };

                for (uint argIdx = 0; argIdx < numArgs; ++argIdx)
                {
                    StringBuilder argName = new StringBuilder(MaxNameSize);
                    uint          argNameLen;

                    if (FailedUnlessOnCLR2DAC(frame.GetArgumentByIndex(argIdx, out tmp, (uint)argName.Capacity, out argNameLen, argName)) ||
                        tmp == null)
                    {
                        continue;
                    }

                    var arg = new ArgumentOrLocal()
                    {
                        Name = argName.ToString()
                    };
                    FillValue(arg, (IXCLRDataValue)tmp);
                    frameArgsLocals.Arguments.Add(arg);
                }

                for (uint lclIdx = 0; lclIdx < numLocals; ++lclIdx)
                {
                    // The mscordacwks!ClrDataFrame::GetLocalVariableByIndex implementation never returns
                    // names for local variables. Need to go through metadata to get them.
                    StringBuilder dummy = new StringBuilder(2);
                    uint          lclNameLen;
                    if (FailedUnlessOnCLR2DAC(frame.GetLocalVariableByIndex(lclIdx, out tmp, (uint)dummy.Capacity, out lclNameLen, dummy)) ||
                        tmp == null)
                    {
                        continue;
                    }

                    string lclName       = dummy.ToString();
                    var    matchingFrame = _stackTrace.SingleOrDefault(f => f.DisplayString == frameArgsLocals.MethodName);
                    if (matchingFrame != null)
                    {
                        lclName = GetLocalVariableName(matchingFrame.InstructionPointer, lclIdx);
                    }

                    var lcl = new ArgumentOrLocal()
                    {
                        Name = lclName
                    };
                    FillValue(lcl, (IXCLRDataValue)tmp);
                    frameArgsLocals.LocalVariables.Add(lcl);
                }

                _results.Add(frameArgsLocals);
            }
Example #11
0
        public override bool Generate(CommandExecutionContext context)
        {
            _title = Path.GetFileName(context.DumpFile);
            switch (context.TargetType)
            {
            case TargetType.DumpFile:
                DumpType = "Full memory dump with heap";
                break;

            case TargetType.DumpFileNoHeap:
                DumpType = "Mini dump with no heap";
                break;

            default:
                DumpType = "Unsupported dump file type";
                break;
            }
            var target = context.NativeDbgEngTarget;
            IDebugSystemObjects2 sysObjects = (IDebugSystemObjects2)target.DebuggerInterface;
            IDebugControl2       control    = (IDebugControl2)target.DebuggerInterface;

            uint          dummy;
            StringBuilder exeName = new StringBuilder(2048);

            if (HR.Succeeded(sysObjects.GetCurrentProcessExecutableName(exeName, exeName.Capacity, out dummy)))
            {
                ExecutableName = exeName.ToString();
            }

            uint uptime;

            if (HR.Succeeded(sysObjects.GetCurrentProcessUpTime(out uptime)))
            {
                ProcessUpTimeInSeconds = uptime;
            }

            if (HR.Succeeded(control.GetCurrentSystemUpTime(out uptime)))
            {
                SystemUpTimeInSeconds = uptime;
            }

            uint time;

            if (HR.Succeeded(control.GetCurrentTimeDate(out time)))
            {
                SessionTime = DateTimeOffset.FromUnixTimeSeconds(time);
            }

            uint num;

            if (HR.Succeeded(control.GetNumberProcessors(out num)))
            {
                NumberOfProcessors = num;
            }

            uint          platformId, major, minor, servicePackNumber;
            StringBuilder servicePack = new StringBuilder(1048);
            StringBuilder build       = new StringBuilder(1048);

            if (HR.Succeeded(control.GetSystemVersion(out platformId, out major, out minor, servicePack, servicePack.Capacity, out dummy, out servicePackNumber, build, build.Capacity, out dummy)))
            {
                WindowsBuildNumber       = minor;
                WindowsServicePack       = servicePack.ToString();
                WindowsServicePackNumber = servicePackNumber;
                WindowsBuild             = build.ToString();
            }

            ClrVersions.AddRange(context.Runtime.DataTarget.ClrVersions.Select(v => v.Version.ToString()));

            if (context.Runtime.DataTarget.ClrVersions.Any(v => v.Version.Minor == 2))
            {
                Recommendations.Add(new CLRV2Detected());
            }

            return(true);
        }
Example #12
0
        public static LastEventInformation GetLastEventInformation(this DataTarget target)
        {
            var           control = (IDebugControl)target.DebuggerInterface;
            DEBUG_EVENT   eventType;
            uint          procId, threadId;
            StringBuilder description = new StringBuilder(2048);
            uint          unused;
            uint          descriptionSize;

            if (HR.Failed(control.GetLastEventInformation(
                              out eventType, out procId, out threadId,
                              IntPtr.Zero, 0, out unused,
                              description, description.Capacity, out descriptionSize)))
            {
                return(null);
            }

            var osThreadIds      = target.GetOSThreadIds();
            var eventInformation = new LastEventInformation
            {
                OSThreadId       = (int)osThreadIds[threadId],
                EventType        = eventType,
                EventDescription = description.ToString()
            };

            IDebugAdvanced2 debugAdvanced = (IDebugAdvanced2)target.DebuggerInterface;
            int             outSize;

            byte[] buffer = new byte[Marshal.SizeOf(typeof(EXCEPTION_RECORD64))];
            int    hr     = debugAdvanced.Request(DEBUG_REQUEST.TARGET_EXCEPTION_RECORD, null, 0, buffer, buffer.Length, out outSize);

            if (HR.Succeeded(hr))
            {
                GCHandle gch = GCHandle.Alloc(buffer, GCHandleType.Pinned);
                try
                {
                    eventInformation.ExceptionRecord = (EXCEPTION_RECORD64)Marshal.PtrToStructure(gch.AddrOfPinnedObject(), typeof(EXCEPTION_RECORD64));
                }
                finally
                {
                    gch.Free();
                }
            }

            buffer = new byte[Marshal.SizeOf(typeof(uint))];
            hr     = debugAdvanced.Request(DEBUG_REQUEST.TARGET_EXCEPTION_THREAD, null, 0, buffer, buffer.Length, out outSize);
            if (HR.Succeeded(hr))
            {
                // If there is a stored exception event with a thread id, use that instead
                // of what GetLastEventInformation returns, because it might be different.
                eventInformation.OSThreadId = (int)BitConverter.ToUInt32(buffer, 0);
            }

            buffer = new byte[Marshal.SizeOf(typeof(CONTEXT))];
            hr     = debugAdvanced.Request(DEBUG_REQUEST.TARGET_EXCEPTION_CONTEXT, null, 0, buffer, buffer.Length, out outSize);
            if (HR.Succeeded(hr))
            {
                var gch = GCHandle.Alloc(buffer, GCHandleType.Pinned);
                try
                {
                    eventInformation.ExceptionContext = (CONTEXT)Marshal.PtrToStructure(
                        gch.AddrOfPinnedObject(), typeof(CONTEXT));
                }
                finally
                {
                    gch.Free();
                }
            }

            return(eventInformation);
        }