예제 #1
0
        public MINIDUMP_EXCEPTION_STREAM(DumpPointer dump)
        {
            uint offset = 0;

            ThreadId    = dump.PtrToStructureAdjustOffset <uint>(ref offset);
            __alignment = dump.PtrToStructureAdjustOffset <uint>(ref offset);

            ExceptionRecord = new MINIDUMP_EXCEPTION();

            ExceptionRecord.ExceptionCode     = dump.PtrToStructureAdjustOffset <uint>(ref offset);
            ExceptionRecord.ExceptionFlags    = dump.PtrToStructureAdjustOffset <uint>(ref offset);
            ExceptionRecord.ExceptionRecord   = dump.PtrToStructureAdjustOffset <ulong>(ref offset);
            ExceptionRecord.ExceptionAddress  = dump.PtrToStructureAdjustOffset <ulong>(ref offset);
            ExceptionRecord.NumberParameters  = dump.PtrToStructureAdjustOffset <uint>(ref offset);
            ExceptionRecord.__unusedAlignment = dump.PtrToStructureAdjustOffset <uint>(ref offset);

            if (ExceptionRecord.ExceptionInformation.Length != DumpNative.EXCEPTION_MAXIMUM_PARAMETERS)
            {
                throw new ClrDiagnosticsException(
                          "Crash dump error: Expected to find " + DumpNative.EXCEPTION_MAXIMUM_PARAMETERS +
                          " exception params, but found " +
                          ExceptionRecord.ExceptionInformation.Length + " instead.",
                          ClrDiagnosticsExceptionKind.CrashDumpError);
            }

            for (int i = 0; i < DumpNative.EXCEPTION_MAXIMUM_PARAMETERS; i++)
            {
                ExceptionRecord.ExceptionInformation[i] = dump.PtrToStructureAdjustOffset <ulong>(ref offset);
            }

            ThreadContext.DataSize  = dump.PtrToStructureAdjustOffset <uint>(ref offset);
            ThreadContext.Rva.Value = dump.PtrToStructureAdjustOffset <uint>(ref offset);
        }
예제 #2
0
        // Internal helper to get the list of modules
        private MINIDUMP_MODULE_LIST GetModuleList()
        {
            EnsureValid();
            DumpPointer          pStream = GetStream(MINIDUMP_STREAM_TYPE.ModuleListStream);
            MINIDUMP_MODULE_LIST list    = new MINIDUMP_MODULE_LIST(pStream);

            return(list);
        }
예제 #3
0
        // Get a DumpPointer from a MINIDUMP_LOCATION_DESCRIPTOR
        protected internal DumpPointer TranslateDescriptor(MINIDUMP_LOCATION_DESCRIPTOR location)
        {
            // A Location has both an RVA and Size. If we just TranslateRVA, then that would be a
            // DumpPointer associated with a larger size (to the end of the dump-file).
            DumpPointer p = TranslateRVA(location.Rva);

            p.Shrink(location.DataSize);
            return(p);
        }
예제 #4
0
        protected MinidumpArray(DumpPointer streamPointer, MINIDUMP_STREAM_TYPE streamType)
        {
            if (streamType != MINIDUMP_STREAM_TYPE.ModuleListStream &&
                streamType != MINIDUMP_STREAM_TYPE.ThreadListStream &&
                streamType != MINIDUMP_STREAM_TYPE.ThreadExListStream)
            {
                throw new ClrDiagnosticsException("MinidumpArray does not support this stream type.", ClrDiagnosticsExceptionKind.CrashDumpError);
            }

            _streamPointer = streamPointer;
        }
예제 #5
0
        internal uint ReadDwordUnsafe(ulong addr)
        {
            int chunkIndex = _memoryChunks.GetChunkContainingAddress(addr);

            if (chunkIndex == -1)
            {
                return(0);
            }

            DumpPointer chunk  = TranslateRVA(_memoryChunks.RVA((uint)chunkIndex));
            ulong       offset = addr - _memoryChunks.StartAddress((uint)chunkIndex);

            return(chunk.Adjust(offset).GetDword());
        }
예제 #6
0
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="path">filename to open dump file</param>
        public DumpReader(string path)
        {
            _file = File.OpenRead(path);
            long length = _file.Length;

            // The dump file may be many megabytes large, so we don't want to
            // read it all at once. Instead, doing a mapping.
            _fileMapping = CreateFileMapping(_file.SafeFileHandle, IntPtr.Zero, PageProtection.Readonly, 0, 0, null);

            if (_fileMapping.IsInvalid)
            {
                int error = Marshal.GetHRForLastWin32Error();
                Marshal.ThrowExceptionForHR(error, new IntPtr(-1));
            }

            _view = MapViewOfFile(_fileMapping, WindowsFunctions.NativeMethods.FILE_MAP_READ, 0, 0, IntPtr.Zero);
            if (_view.IsInvalid)
            {
                int error = Marshal.GetHRForLastWin32Error();
                Marshal.ThrowExceptionForHR(error, new IntPtr(-1));
            }

            _base = DumpPointer.DangerousMakeDumpPointer(_view.BaseAddress, (uint)length);

            //
            // Cache stuff
            //

            DumpPointer pStream;

            // System info.
            pStream = GetStream(MINIDUMP_STREAM_TYPE.SystemInfoStream);
            _info   = pStream.PtrToStructure <MINIDUMP_SYSTEM_INFO>();

            // Memory64ListStream is present in MinidumpWithFullMemory.
            if (TryGetStream(MINIDUMP_STREAM_TYPE.Memory64ListStream, out pStream))
            {
                _memoryChunks = new MinidumpMemoryChunks(pStream, MINIDUMP_STREAM_TYPE.Memory64ListStream);
            }
            else
            {
                // MiniDumpNormal doesn't have a Memory64ListStream, it has a MemoryListStream.
                pStream       = GetStream(MINIDUMP_STREAM_TYPE.MemoryListStream);
                _memoryChunks = new MinidumpMemoryChunks(pStream, MINIDUMP_STREAM_TYPE.MemoryListStream);
            }

            _mappedFileMemory = new LoadedFileMemoryLookups();
            IsMinidump        = DumpNative.IsMiniDump(_view.BaseAddress);
        }
예제 #7
0
        /// <summary>
        /// Get a DumpPointer for the given stream. That can then be used to further decode the stream.
        /// </summary>
        /// <param name="type">type of stream to lookup</param>
        /// <param name="stream">DumpPointer refering into the stream. </param>
        /// <returns>True if stream was succesfully retrived</returns>
        private bool TryGetStream(MINIDUMP_STREAM_TYPE type, out DumpPointer stream)
        {
            EnsureValid();

            bool fOk = DumpNative.MiniDumpReadDumpStream(_view.BaseAddress, type, out IntPtr pStream, out uint cbStreamSize);

            if (!fOk || IntPtr.Zero == pStream || cbStreamSize < 1)
            {
                stream = default;
                return(false);
            }

            stream = DumpPointer.DangerousMakeDumpPointer(pStream, cbStreamSize);
            return(true);
        }
예제 #8
0
        public virtual int ReadPartialMemory(ulong targetRequestStart, byte[] destinationBuffer, int bytesRequested)
        {
            EnsureValid();

            if (bytesRequested <= 0)
            {
                return(0);
            }

            if (bytesRequested > destinationBuffer.Length)
            {
                bytesRequested = destinationBuffer.Length;
            }

            int bytesRead = 0;

            do
            {
                int chunkIndex = _memoryChunks.GetChunkContainingAddress(targetRequestStart + (uint)bytesRead);
                if (chunkIndex == -1)
                {
                    break;
                }

                DumpPointer pointerCurrentChunk = TranslateRVA(_memoryChunks.RVA((uint)chunkIndex));
                ulong       startAddr           = targetRequestStart + (uint)bytesRead - _memoryChunks.StartAddress((uint)chunkIndex);
                ulong       bytesAvailable      = _memoryChunks.Size((uint)chunkIndex) - startAddr;

                Debug.Assert(bytesRequested >= bytesRead);
                int bytesToCopy = bytesRequested - bytesRead;
                if (bytesAvailable < (uint)bytesToCopy)
                {
                    bytesToCopy = (int)bytesAvailable;
                }

                Debug.Assert(bytesToCopy > 0);
                if (bytesToCopy == 0)
                {
                    break;
                }

                pointerCurrentChunk.Adjust(startAddr).Copy(destinationBuffer, bytesRead, bytesToCopy);
                bytesRead += bytesToCopy;
            } while (bytesRead < bytesRequested);

            return(bytesRead);
        }
예제 #9
0
        /// <summary>
        /// Gets a MINIDUMP_STRING at the given DumpPointer as an System.String.
        /// </summary>
        /// <param name="ptr">DumpPointer to a MINIDUMP_STRING</param>
        /// <returns>
        /// System.String representing contents of MINIDUMP_STRING at the given location
        /// in the dump
        /// </returns>
        protected internal string GetString(DumpPointer ptr)
        {
            EnsureValid();

            // Minidump string is defined as:
            // typedef struct _MINIDUMP_STRING {
            //   ULONG32 Length;         // Length in bytes of the string
            //    WCHAR   Buffer [0];     // Variable size buffer
            // } MINIDUMP_STRING, *PMINIDUMP_STRING;
            int lengthBytes = ptr.ReadInt32();

            ptr = ptr.Adjust(4); // move past the Length field

            int    lengthChars = lengthBytes / 2;
            string s           = ptr.ReadAsUnicodeString(lengthChars);

            return(s);
        }
예제 #10
0
        // Since a MemoryListStream makes no guarantees that there aren't duplicate, overlapping, or wholly contained
        // memory regions, we need to handle that.  For the purposes of this code, we presume all memory regions
        // in the dump that cover a given VA have the correct (duplicate) contents.
        protected uint ReadPartialMemoryInternal(
            ulong targetRequestStart,
            IntPtr destinationBuffer,
            uint destinationBufferSizeInBytes,
            uint startIndex)
        {
            EnsureValid();

            if (destinationBufferSizeInBytes == 0)
            {
                return(0);
            }

            uint bytesRead = 0;

            do
            {
                int chunkIndex = _memoryChunks.GetChunkContainingAddress(targetRequestStart + bytesRead);
                if (chunkIndex == -1)
                {
                    break;
                }

                DumpPointer pointerCurrentChunk = TranslateRVA(_memoryChunks.RVA((uint)chunkIndex));
                uint        idxStart            = (uint)(targetRequestStart + bytesRead - _memoryChunks.StartAddress((uint)chunkIndex));
                uint        bytesAvailable      = (uint)_memoryChunks.Size((uint)chunkIndex) - idxStart;
                uint        bytesNeeded         = destinationBufferSizeInBytes - bytesRead;
                uint        bytesToCopy         = Math.Min(bytesAvailable, bytesNeeded);

                Debug.Assert(bytesToCopy > 0);
                if (bytesToCopy == 0)
                {
                    break;
                }

                IntPtr dest     = new IntPtr(destinationBuffer.ToInt64() + bytesRead);
                uint   destSize = destinationBufferSizeInBytes - bytesRead;
                pointerCurrentChunk.Adjust(idxStart).Copy(dest, destSize, bytesToCopy);
                bytesRead += bytesToCopy;
            } while (bytesRead < destinationBufferSizeInBytes);

            return(bytesRead);
        }
예제 #11
0
        internal void GetThreadContext(MINIDUMP_LOCATION_DESCRIPTOR loc, IntPtr buffer, int sizeBufferBytes)
        {
            if (loc.IsNull)
            {
                throw new ClrDiagnosticsException("Context not present", ClrDiagnosticsExceptionKind.CrashDumpError);
            }

            DumpPointer pContext    = TranslateDescriptor(loc);
            int         sizeContext = (int)loc.DataSize;

            if (sizeBufferBytes < sizeContext)
            {
                // Context size doesn't match
                throw new ClrDiagnosticsException(
                          "Context size mismatch. Expected = 0x" + sizeBufferBytes.ToString("x") + ", Size in dump = 0x" + sizeContext.ToString("x"),
                          ClrDiagnosticsExceptionKind.CrashDumpError);
            }

            // Now copy from dump into buffer.
            pContext.Copy(buffer, (uint)sizeContext);
        }
예제 #12
0
        //todo

        /*
         * public NativeContext ExceptionStreamThreadContext()
         * {
         *  NativeMethods.MINIDUMP_EXCEPTION_STREAM es = GetExceptionStream();
         *  return GetThreadContext(es.ThreadContext);
         * }
         */

        /// <summary>
        /// Lookup the first module in the target with a matching.
        /// </summary>
        /// <param name="nameModule">The name can either be a matching full name, or just shortname</param>
        /// <returns>The first DumpModule that has a matching name. </returns>
        public DumpModule LookupModule(string nameModule)
        {
            MINIDUMP_MODULE_LIST list = GetModuleList();
            uint num = list.Count;

            for (uint i = 0; i < num; i++)
            {
                MINIDUMP_MODULE module = list.GetElement(i);
                RVA             rva    = module.ModuleNameRva;

                DumpPointer ptr = TranslateRVA(rva);

                string name = GetString(ptr);
                if (nameModule == name ||
                    name.EndsWith(nameModule))
                {
                    return(new DumpModule(this, module));
                }
            }

            return(null);
        }
예제 #13
0
        public MinidumpMemoryChunks(DumpPointer rawStream, MINIDUMP_STREAM_TYPE type)
        {
            Count         = 0;
            _memory64List = null;
            _memoryList   = null;
            _listType     = MINIDUMP_STREAM_TYPE.UnusedStream;

            if (type != MINIDUMP_STREAM_TYPE.MemoryListStream &&
                type != MINIDUMP_STREAM_TYPE.Memory64ListStream)
            {
                throw new ClrDiagnosticsException("Type must be either MemoryListStream or Memory64ListStream", ClrDiagnosticsExceptionKind.CrashDumpError);
            }

            _listType   = type;
            _dumpStream = rawStream;
            if (MINIDUMP_STREAM_TYPE.Memory64ListStream == type)
            {
                InitFromMemory64List();
            }
            else
            {
                InitFromMemoryList();
            }
        }
예제 #14
0
        private MINIDUMP_EXCEPTION_STREAM GetExceptionStream()
        {
            DumpPointer pStream = GetStream(MINIDUMP_STREAM_TYPE.ExceptionStream);

            return(new MINIDUMP_EXCEPTION_STREAM(pStream));
        }
예제 #15
0
        /// <summary>
        /// Gets a MINIDUMP_STRING at the given RVA as an System.String.
        /// </summary>
        /// <param name="rva">RVA of MINIDUMP_STRING</param>
        /// <returns>System.String representing contents of MINIDUMP_STRING at the given RVA</returns>
        protected internal string GetString(RVA rva)
        {
            DumpPointer p = TranslateRVA(rva);

            return(GetString(p));
        }