private static unsafe void GenerateErrorReportForDump(LowLevelList <byte[]> serializedExceptions) { checked { int loadedModuleCount = RuntimeAugments.GetLoadedOSModules(null); int cbModuleHandles = sizeof(System.IntPtr) * loadedModuleCount; int cbFinalBuffer = sizeof(ERROR_REPORT_BUFFER_HEADER) + sizeof(SERIALIZED_ERROR_REPORT_HEADER) + cbModuleHandles; for (int i = 0; i < serializedExceptions.Count; i++) { cbFinalBuffer += serializedExceptions[i].Length; } byte[] finalBuffer = new byte[cbFinalBuffer]; fixed(byte *pBuffer = &finalBuffer[0]) { byte *pCursor = pBuffer; int cbRemaining = cbFinalBuffer; ERROR_REPORT_BUFFER_HEADER *pDacHeader = (ERROR_REPORT_BUFFER_HEADER *)pCursor; pDacHeader->WriteHeader(cbFinalBuffer); pCursor += sizeof(ERROR_REPORT_BUFFER_HEADER); cbRemaining -= sizeof(ERROR_REPORT_BUFFER_HEADER); SERIALIZED_ERROR_REPORT_HEADER *pPayloadHeader = (SERIALIZED_ERROR_REPORT_HEADER *)pCursor; pPayloadHeader->WriteHeader(serializedExceptions.Count, loadedModuleCount); pCursor += sizeof(SERIALIZED_ERROR_REPORT_HEADER); cbRemaining -= sizeof(SERIALIZED_ERROR_REPORT_HEADER); // copy the serialized exceptions to report buffer for (int i = 0; i < serializedExceptions.Count; i++) { int cbChunk = serializedExceptions[i].Length; PInvokeMarshal.CopyToNative(serializedExceptions[i], 0, (IntPtr)pCursor, cbChunk); cbRemaining -= cbChunk; pCursor += cbChunk; } // copy the module-handle array to report buffer IntPtr[] loadedModuleHandles = new IntPtr[loadedModuleCount]; RuntimeAugments.GetLoadedOSModules(loadedModuleHandles); PInvokeMarshal.CopyToNative(loadedModuleHandles, 0, (IntPtr)pCursor, loadedModuleHandles.Length); cbRemaining -= cbModuleHandles; pCursor += cbModuleHandles; Debug.Assert(cbRemaining == 0); } UpdateErrorReportBuffer(finalBuffer); } }
/// <summary> /// Locate and lazily load debug info for the native app module overlapping given /// virtual address. /// </summary> /// <param name="ip">Instruction pointer address (code address for the lookup)</param> /// <param name="rva">Output VA relative to module base</param> private static IDiaSession GetDiaSession(IntPtr ip, out int rva) { if (ip == IntPtr.Zero) { rva = -1; return(null); } IntPtr moduleBase = RuntimeAugments.GetOSModuleFromPointer(ip); if (moduleBase == IntPtr.Zero) { rva = -1; return(null); } rva = (int)(ip.ToInt64() - moduleBase.ToInt64()); if (s_loadedModules == null) { // Lazily create the parallel arrays s_loadedModules and s_perModuleDebugInfo int moduleCount = RuntimeAugments.GetLoadedOSModules(null); s_loadedModules = new IntPtr[moduleCount]; s_perModuleDebugInfo = new IDiaSession[moduleCount]; // Actually read the module addresses into the array RuntimeAugments.GetLoadedOSModules(s_loadedModules); } // Locate module index based on base address int moduleIndex = s_loadedModules.Length; do { if (--moduleIndex < 0) { return(null); } }while(s_loadedModules[moduleIndex] != moduleBase); IDiaSession diaSession = s_perModuleDebugInfo[moduleIndex]; if (diaSession != null) { return(diaSession); } string modulePath = RuntimeAugments.TryGetFullPathToApplicationModule(moduleBase); if (modulePath == null) { return(null); } int indexOfLastDot = modulePath.LastIndexOf('.'); if (indexOfLastDot == -1) { return(null); } IDiaDataSource diaDataSource = GetDiaDataSource(); if (diaDataSource == null) { return(null); } // Look for .pdb next to .exe / dll - if it's not there, bail. String pdbPath = modulePath.Substring(0, indexOfLastDot) + ".pdb"; int hr = diaDataSource.LoadDataFromPdb(pdbPath); if (hr != S_OK) { return(null); } hr = diaDataSource.OpenSession(out diaSession); if (hr != S_OK) { return(null); } s_perModuleDebugInfo[moduleIndex] = diaSession; return(diaSession); }