DUMP.C
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:10k
源码类别:

Windows编程

开发平台:

Visual C++

  1. /*++
  2. Copyright (c) 1993  Microsoft Corporation
  3. Module Name:
  4.     dump.c
  5. Abstract:
  6.     This file implements the crash dump code.
  7. Author:
  8.     Wesley Witt (wesw) 27-Jan-1995
  9. Environment:
  10.     User Mode
  11. --*/
  12. #include <windows.h>
  13. #include <stdlib.h>
  14. #include <stdio.h>
  15. #include <string.h>
  16. #include <stddef.h>
  17. #include <crash.h>
  18. #include "drwatson.h"
  19. #include "proto.h"
  20. #include "messages.h"
  21. #include "resource.h"
  22. #define MEM_SIZE (64*1024)
  23. //
  24. // these are here only so that we can link
  25. // with crashlib.  they are only referenced
  26. // when reading a kernel mode crash dump
  27. //
  28. DWORD KiProcessors;
  29. DWORD KiPcrBaseAddress;
  30. //
  31. // private data structure use for communcating
  32. // crash dump data to the callback function
  33. //
  34. typedef struct _CRASH_DUMP_INFO {
  35.     PDEBUGPACKET                dp;
  36.     EXCEPTION_DEBUG_INFO        *ExceptionInfo;
  37.     DWORD                       MemoryCount;
  38.     DWORD                       Address;
  39.     PUCHAR                      MemoryData;
  40.     MEMORY_BASIC_INFORMATION    mbi;
  41.     BOOL                        MbiOffset;
  42.     ULONG                       MbiRemaining;
  43.     PTHREADCONTEXT              ptctx;
  44.     IMAGEHLP_MODULE             mi;
  45.     PCRASH_MODULE               CrashModule;
  46. } CRASH_DUMP_INFO, *PCRASH_DUMP_INFO;
  47. LPSTR
  48. ExpandPath(
  49.     LPSTR lpPath
  50.     );
  51. DWORD
  52. GetTeb(
  53.     HANDLE hTread
  54.     );
  55. BOOL
  56. CrashDumpCallback(
  57.     DWORD               DataType,
  58.     PVOID               *DumpData,
  59.     LPDWORD             DumpDataLength,
  60.     PCRASH_DUMP_INFO    CrashdumpInfo
  61.     )
  62. /*++
  63. Routine Description:
  64.     This function is the callback used by crashlib.
  65.     Its purpose is to provide data to DmpCreateUserDump()
  66.     for writting to the crashdump file.
  67. Arguments:
  68.     DataType        - requested data type
  69.     DumpData        - pointer to a pointer to the data
  70.     DumpDataLength  - pointer to the data length
  71.     CrashdumpInfo   - DrWatson private data
  72. Return Value:
  73.     TRUE    - continue calling back for the requested data type
  74.     FALSE   - stop calling back and go on to the next data type
  75. --*/
  76. {
  77.     DWORD   cb;
  78.     switch( DataType ) {
  79.         case DMP_DEBUG_EVENT:
  80.             *DumpData = &CrashdumpInfo->dp->DebugEvent;
  81.             *DumpDataLength = sizeof(DEBUG_EVENT);
  82.             break;
  83.         case DMP_THREAD_STATE:
  84.             {
  85.                 static CRASH_THREAD CrashThread;
  86.                 PTHREADCONTEXT  ptctx;
  87.                 PLIST_ENTRY     ListEntry;
  88.                 *DumpData = &CrashThread;
  89.                 if (CrashdumpInfo->ptctx == NULL) {
  90.                     ListEntry = CrashdumpInfo->dp->ThreadList.Flink;
  91.                 } else {
  92.                     ListEntry = CrashdumpInfo->ptctx->ThreadList.Flink;
  93.                 }
  94.                 if (ListEntry == &CrashdumpInfo->dp->ThreadList) {
  95.                     CrashdumpInfo->ptctx = NULL;
  96.                     return FALSE;
  97.                 }
  98.                 ptctx =
  99.                 CrashdumpInfo->ptctx = CONTAINING_RECORD(ListEntry, THREADCONTEXT, ThreadList);
  100.                 ZeroMemory(&CrashThread, sizeof(CrashThread));
  101.                 CrashThread.ThreadId = ptctx->dwThreadId;
  102.                 CrashThread.SuspendCount = SuspendThread(ptctx->hThread);
  103.                 if (CrashThread.SuspendCount != (DWORD)-1) {
  104.                     ResumeThread(ptctx->hThread);
  105.                 }
  106.                 CrashThread.PriorityClass = GetPriorityClass(CrashdumpInfo->dp->hProcess);
  107.                 CrashThread.Priority = GetThreadPriority(ptctx->hThread);
  108.                 CrashThread.Teb = GetTeb(ptctx->hThread);
  109.                 *DumpDataLength = sizeof(CRASH_THREAD);
  110.             }
  111.             break;
  112.         case DMP_MEMORY_BASIC_INFORMATION:
  113.             while( TRUE ) {
  114.                 CrashdumpInfo->Address += CrashdumpInfo->mbi.RegionSize;
  115.                 if (!VirtualQueryEx(
  116.                         CrashdumpInfo->dp->hProcess,
  117.                         (LPVOID)CrashdumpInfo->Address,
  118.                         &CrashdumpInfo->mbi,
  119.                         sizeof(MEMORY_BASIC_INFORMATION) )) {
  120.                     return FALSE;
  121.                 }
  122.                 if ((CrashdumpInfo->mbi.AllocationProtect & PAGE_GUARD) ||
  123.                     (CrashdumpInfo->mbi.AllocationProtect & PAGE_NOACCESS)) {
  124.                     continue;
  125.                 }
  126.                 if ((CrashdumpInfo->mbi.State & MEM_FREE) ||
  127.                     (CrashdumpInfo->mbi.State & MEM_RESERVE)) {
  128.                     continue;
  129.                 }
  130.                 break;
  131.             }
  132.             *DumpData = &CrashdumpInfo->mbi;
  133.             *DumpDataLength = sizeof(MEMORY_BASIC_INFORMATION);
  134.             break;
  135.         case DMP_THREAD_CONTEXT:
  136.             {
  137.                 PLIST_ENTRY     ListEntry;
  138.                 if (CrashdumpInfo->ptctx == NULL) {
  139.                     ListEntry = CrashdumpInfo->dp->ThreadList.Flink;
  140.                 } else {
  141.                     ListEntry = CrashdumpInfo->ptctx->ThreadList.Flink;
  142.                 }
  143.                 if (ListEntry == &CrashdumpInfo->dp->ThreadList) {
  144.                     CrashdumpInfo->ptctx = NULL;
  145.                     return FALSE;
  146.                 }
  147.                 CrashdumpInfo->ptctx = CONTAINING_RECORD(ListEntry, THREADCONTEXT, ThreadList);
  148.                 *DumpData = &CrashdumpInfo->ptctx->context;
  149.                 *DumpDataLength = sizeof(CONTEXT);
  150.             }
  151.             break;
  152.         case DMP_MODULE:
  153.             if (CrashdumpInfo->mi.BaseOfImage == 0) {
  154.                 return FALSE;
  155.             }
  156.             CrashdumpInfo->CrashModule->BaseOfImage = CrashdumpInfo->mi.BaseOfImage;
  157.             CrashdumpInfo->CrashModule->SizeOfImage = CrashdumpInfo->mi.ImageSize;
  158.             CrashdumpInfo->CrashModule->ImageNameLength = strlen(CrashdumpInfo->mi.ImageName) + 1;
  159.             strcpy( CrashdumpInfo->CrashModule->ImageName, CrashdumpInfo->mi.ImageName );
  160.             *DumpData = CrashdumpInfo->CrashModule;
  161.             *DumpDataLength = sizeof(CRASH_MODULE) + CrashdumpInfo->CrashModule->ImageNameLength;
  162.             if (!SymGetModuleInfo( CrashdumpInfo->dp->hProcess, (DWORD)-1, &CrashdumpInfo->mi )) {
  163.                 CrashdumpInfo->mi.BaseOfImage = 0;
  164.             }
  165.             break;
  166.         case DMP_MEMORY_DATA:
  167.             if (!CrashdumpInfo->MemoryCount) {
  168.                 CrashdumpInfo->Address = 0;
  169.                 CrashdumpInfo->MbiOffset = 0;
  170.                 CrashdumpInfo->MbiRemaining = 0;
  171.                 ZeroMemory( &CrashdumpInfo->mbi, sizeof(MEMORY_BASIC_INFORMATION) );
  172.                 CrashdumpInfo->MemoryData = VirtualAlloc(
  173.                     NULL,
  174.                     MEM_SIZE,
  175.                     MEM_COMMIT,
  176.                     PAGE_READWRITE
  177.                     );
  178.             }
  179.             if (!CrashdumpInfo->MbiRemaining) {
  180.                 while( TRUE ) {
  181.                     CrashdumpInfo->Address += CrashdumpInfo->mbi.RegionSize;
  182.                     if (!VirtualQueryEx(
  183.                             CrashdumpInfo->dp->hProcess,
  184.                             (LPVOID)CrashdumpInfo->Address,
  185.                             &CrashdumpInfo->mbi,
  186.                             sizeof(MEMORY_BASIC_INFORMATION) )) {
  187.                         if (CrashdumpInfo->MemoryData) {
  188.                             VirtualFree( CrashdumpInfo->MemoryData, MEM_SIZE, MEM_RELEASE );
  189.                         }
  190.                         return FALSE;
  191.                     }
  192.                     if ((CrashdumpInfo->mbi.Protect & PAGE_GUARD) ||
  193.                         (CrashdumpInfo->mbi.Protect & PAGE_NOACCESS)) {
  194.                         continue;
  195.                     }
  196.                     if ((CrashdumpInfo->mbi.State & MEM_FREE) ||
  197.                         (CrashdumpInfo->mbi.State & MEM_RESERVE)) {
  198.                         continue;
  199.                     }
  200.                     CrashdumpInfo->MbiOffset = 0;
  201.                     CrashdumpInfo->MbiRemaining = CrashdumpInfo->mbi.RegionSize;
  202.                     CrashdumpInfo->MemoryCount += 1;
  203.                     break;
  204.                 }
  205.             }
  206.             *DumpDataLength = min( CrashdumpInfo->MbiRemaining, MEM_SIZE );
  207.             CrashdumpInfo->MbiRemaining -= *DumpDataLength;
  208.             ReadProcessMemory(
  209.                 CrashdumpInfo->dp->hProcess,
  210.                 (PUCHAR)((ULONG)CrashdumpInfo->mbi.BaseAddress + (ULONG)CrashdumpInfo->MbiOffset),
  211.                 CrashdumpInfo->MemoryData,
  212.                 *DumpDataLength,
  213.                 &cb
  214.                 );
  215.             *DumpData = CrashdumpInfo->MemoryData;
  216.             CrashdumpInfo->MbiOffset += *DumpDataLength;
  217.             break;
  218.     }
  219.     return TRUE;
  220. }
  221. BOOL
  222. CreateDumpFile(
  223.     PDEBUGPACKET            dp,
  224.     LPEXCEPTION_DEBUG_INFO  ed
  225.     )
  226. /*++
  227. Routine Description:
  228.     This function creates a crash dump file.
  229. Arguments:
  230.     dp              - debug packet for current process
  231.     ed              - exception data
  232. Return Value:
  233.     TRUE    - Crash dump was created
  234.     FALSE   - Crash dump was NOT created
  235. --*/
  236. {
  237.     CRASH_DUMP_INFO     CrashdumpInfo;
  238.     LPSTR               p;
  239.     ZeroMemory( &CrashdumpInfo, sizeof(CRASH_DUMP_INFO) );
  240.     CrashdumpInfo.dp = dp;
  241.     CrashdumpInfo.ExceptionInfo = ed;
  242.     CrashdumpInfo.ptctx = NULL;
  243.     //
  244.     // Get first entry in module list
  245.     //
  246.     SymGetModuleInfo( dp->hProcess, (DWORD)0, &CrashdumpInfo.mi );
  247.     CrashdumpInfo.CrashModule = LocalAlloc( LPTR, 4096 );
  248.     p = ExpandPath( dp->options.szCrashDump );
  249.     if (!p) {
  250.         return FALSE;
  251.     }
  252.     DmpCreateUserDump( p, CrashDumpCallback, &CrashdumpInfo );
  253.     free( p );
  254.     LocalFree( CrashdumpInfo.CrashModule );
  255.     return TRUE;
  256. }