Exemplo n.º 1
0
        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);
        }