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); }
// 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); }
// 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); }
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; }
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()); }
/// <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); }
/// <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); }
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); }
/// <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); }
// 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); }
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); }
//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); }
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(); } }
private MINIDUMP_EXCEPTION_STREAM GetExceptionStream() { DumpPointer pStream = GetStream(MINIDUMP_STREAM_TYPE.ExceptionStream); return(new MINIDUMP_EXCEPTION_STREAM(pStream)); }
/// <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)); }