324 lines
9.4 KiB
C
324 lines
9.4 KiB
C
|
/*++
|
||
|
|
||
|
Copyright (c) 1993 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
dump.c
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
This file implements the crash dump code.
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Wesley Witt (wesw) 27-Jan-1995
|
||
|
|
||
|
Environment:
|
||
|
|
||
|
User Mode
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#include <windows.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <stdio.h>
|
||
|
#include <string.h>
|
||
|
#include <stddef.h>
|
||
|
#include <crash.h>
|
||
|
|
||
|
#include "drwatson.h"
|
||
|
#include "proto.h"
|
||
|
#include "messages.h"
|
||
|
#include "resource.h"
|
||
|
|
||
|
|
||
|
#define MEM_SIZE (64*1024)
|
||
|
|
||
|
|
||
|
//
|
||
|
// these are here only so that we can link
|
||
|
// with crashlib. they are only referenced
|
||
|
// when reading a kernel mode crash dump
|
||
|
//
|
||
|
DWORD KiProcessors;
|
||
|
DWORD KiPcrBaseAddress;
|
||
|
|
||
|
//
|
||
|
// private data structure use for communcating
|
||
|
// crash dump data to the callback function
|
||
|
//
|
||
|
typedef struct _CRASH_DUMP_INFO {
|
||
|
PDEBUGPACKET dp;
|
||
|
EXCEPTION_DEBUG_INFO *ExceptionInfo;
|
||
|
DWORD MemoryCount;
|
||
|
DWORD Address;
|
||
|
PUCHAR MemoryData;
|
||
|
MEMORY_BASIC_INFORMATION mbi;
|
||
|
BOOL MbiOffset;
|
||
|
ULONG MbiRemaining;
|
||
|
PTHREADCONTEXT ptctx;
|
||
|
IMAGEHLP_MODULE mi;
|
||
|
PCRASH_MODULE CrashModule;
|
||
|
} CRASH_DUMP_INFO, *PCRASH_DUMP_INFO;
|
||
|
|
||
|
LPSTR
|
||
|
ExpandPath(
|
||
|
LPSTR lpPath
|
||
|
);
|
||
|
|
||
|
DWORD
|
||
|
GetTeb(
|
||
|
HANDLE hTread
|
||
|
);
|
||
|
|
||
|
BOOL
|
||
|
CrashDumpCallback(
|
||
|
DWORD DataType,
|
||
|
PVOID *DumpData,
|
||
|
LPDWORD DumpDataLength,
|
||
|
PCRASH_DUMP_INFO CrashdumpInfo
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This function is the callback used by crashlib.
|
||
|
Its purpose is to provide data to DmpCreateUserDump()
|
||
|
for writting to the crashdump file.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
DataType - requested data type
|
||
|
DumpData - pointer to a pointer to the data
|
||
|
DumpDataLength - pointer to the data length
|
||
|
CrashdumpInfo - DrWatson private data
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
TRUE - continue calling back for the requested data type
|
||
|
FALSE - stop calling back and go on to the next data type
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
DWORD cb;
|
||
|
|
||
|
switch( DataType ) {
|
||
|
case DMP_DEBUG_EVENT:
|
||
|
*DumpData = &CrashdumpInfo->dp->DebugEvent;
|
||
|
*DumpDataLength = sizeof(DEBUG_EVENT);
|
||
|
break;
|
||
|
|
||
|
case DMP_THREAD_STATE:
|
||
|
{
|
||
|
static CRASH_THREAD CrashThread;
|
||
|
PTHREADCONTEXT ptctx;
|
||
|
PLIST_ENTRY ListEntry;
|
||
|
|
||
|
*DumpData = &CrashThread;
|
||
|
|
||
|
if (CrashdumpInfo->ptctx == NULL) {
|
||
|
ListEntry = CrashdumpInfo->dp->ThreadList.Flink;
|
||
|
} else {
|
||
|
ListEntry = CrashdumpInfo->ptctx->ThreadList.Flink;
|
||
|
}
|
||
|
|
||
|
if (ListEntry == &CrashdumpInfo->dp->ThreadList) {
|
||
|
CrashdumpInfo->ptctx = NULL;
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
ptctx =
|
||
|
CrashdumpInfo->ptctx = CONTAINING_RECORD(ListEntry, THREADCONTEXT, ThreadList);
|
||
|
|
||
|
ZeroMemory(&CrashThread, sizeof(CrashThread));
|
||
|
|
||
|
CrashThread.ThreadId = ptctx->dwThreadId;
|
||
|
CrashThread.SuspendCount = SuspendThread(ptctx->hThread);
|
||
|
if (CrashThread.SuspendCount != (DWORD)-1) {
|
||
|
ResumeThread(ptctx->hThread);
|
||
|
}
|
||
|
CrashThread.PriorityClass = GetPriorityClass(CrashdumpInfo->dp->hProcess);
|
||
|
CrashThread.Priority = GetThreadPriority(ptctx->hThread);
|
||
|
CrashThread.Teb = GetTeb(ptctx->hThread);
|
||
|
|
||
|
*DumpDataLength = sizeof(CRASH_THREAD);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case DMP_MEMORY_BASIC_INFORMATION:
|
||
|
while( TRUE ) {
|
||
|
CrashdumpInfo->Address += CrashdumpInfo->mbi.RegionSize;
|
||
|
if (!VirtualQueryEx(
|
||
|
CrashdumpInfo->dp->hProcess,
|
||
|
(LPVOID)CrashdumpInfo->Address,
|
||
|
&CrashdumpInfo->mbi,
|
||
|
sizeof(MEMORY_BASIC_INFORMATION) )) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
if ((CrashdumpInfo->mbi.AllocationProtect & PAGE_GUARD) ||
|
||
|
(CrashdumpInfo->mbi.AllocationProtect & PAGE_NOACCESS)) {
|
||
|
continue;
|
||
|
}
|
||
|
if ((CrashdumpInfo->mbi.State & MEM_FREE) ||
|
||
|
(CrashdumpInfo->mbi.State & MEM_RESERVE)) {
|
||
|
continue;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
*DumpData = &CrashdumpInfo->mbi;
|
||
|
*DumpDataLength = sizeof(MEMORY_BASIC_INFORMATION);
|
||
|
break;
|
||
|
|
||
|
case DMP_THREAD_CONTEXT:
|
||
|
{
|
||
|
PLIST_ENTRY ListEntry;
|
||
|
|
||
|
if (CrashdumpInfo->ptctx == NULL) {
|
||
|
ListEntry = CrashdumpInfo->dp->ThreadList.Flink;
|
||
|
} else {
|
||
|
ListEntry = CrashdumpInfo->ptctx->ThreadList.Flink;
|
||
|
}
|
||
|
|
||
|
if (ListEntry == &CrashdumpInfo->dp->ThreadList) {
|
||
|
CrashdumpInfo->ptctx = NULL;
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
CrashdumpInfo->ptctx = CONTAINING_RECORD(ListEntry, THREADCONTEXT, ThreadList);
|
||
|
|
||
|
*DumpData = &CrashdumpInfo->ptctx->context;
|
||
|
*DumpDataLength = sizeof(CONTEXT);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case DMP_MODULE:
|
||
|
if (CrashdumpInfo->mi.BaseOfImage == 0) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
CrashdumpInfo->CrashModule->BaseOfImage = CrashdumpInfo->mi.BaseOfImage;
|
||
|
CrashdumpInfo->CrashModule->SizeOfImage = CrashdumpInfo->mi.ImageSize;
|
||
|
CrashdumpInfo->CrashModule->ImageNameLength = strlen(CrashdumpInfo->mi.ImageName) + 1;
|
||
|
strcpy( CrashdumpInfo->CrashModule->ImageName, CrashdumpInfo->mi.ImageName );
|
||
|
*DumpData = CrashdumpInfo->CrashModule;
|
||
|
*DumpDataLength = sizeof(CRASH_MODULE) + CrashdumpInfo->CrashModule->ImageNameLength;
|
||
|
if (!SymGetModuleInfo( CrashdumpInfo->dp->hProcess, (DWORD)-1, &CrashdumpInfo->mi )) {
|
||
|
CrashdumpInfo->mi.BaseOfImage = 0;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case DMP_MEMORY_DATA:
|
||
|
if (!CrashdumpInfo->MemoryCount) {
|
||
|
CrashdumpInfo->Address = 0;
|
||
|
CrashdumpInfo->MbiOffset = 0;
|
||
|
CrashdumpInfo->MbiRemaining = 0;
|
||
|
ZeroMemory( &CrashdumpInfo->mbi, sizeof(MEMORY_BASIC_INFORMATION) );
|
||
|
CrashdumpInfo->MemoryData = VirtualAlloc(
|
||
|
NULL,
|
||
|
MEM_SIZE,
|
||
|
MEM_COMMIT,
|
||
|
PAGE_READWRITE
|
||
|
);
|
||
|
}
|
||
|
if (!CrashdumpInfo->MbiRemaining) {
|
||
|
while( TRUE ) {
|
||
|
CrashdumpInfo->Address += CrashdumpInfo->mbi.RegionSize;
|
||
|
if (!VirtualQueryEx(
|
||
|
CrashdumpInfo->dp->hProcess,
|
||
|
(LPVOID)CrashdumpInfo->Address,
|
||
|
&CrashdumpInfo->mbi,
|
||
|
sizeof(MEMORY_BASIC_INFORMATION) )) {
|
||
|
if (CrashdumpInfo->MemoryData) {
|
||
|
VirtualFree( CrashdumpInfo->MemoryData, MEM_SIZE, MEM_RELEASE );
|
||
|
}
|
||
|
return FALSE;
|
||
|
}
|
||
|
if ((CrashdumpInfo->mbi.AllocationProtect & PAGE_GUARD) ||
|
||
|
(CrashdumpInfo->mbi.AllocationProtect & PAGE_NOACCESS)) {
|
||
|
continue;
|
||
|
}
|
||
|
if ((CrashdumpInfo->mbi.State & MEM_FREE) ||
|
||
|
(CrashdumpInfo->mbi.State & MEM_RESERVE)) {
|
||
|
continue;
|
||
|
}
|
||
|
CrashdumpInfo->MbiOffset = 0;
|
||
|
CrashdumpInfo->MbiRemaining = CrashdumpInfo->mbi.RegionSize;
|
||
|
CrashdumpInfo->MemoryCount += 1;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
*DumpDataLength = min( CrashdumpInfo->MbiRemaining, MEM_SIZE );
|
||
|
CrashdumpInfo->MbiRemaining -= *DumpDataLength;
|
||
|
ReadProcessMemory(
|
||
|
CrashdumpInfo->dp->hProcess,
|
||
|
(PUCHAR)((ULONG)CrashdumpInfo->mbi.BaseAddress + (ULONG)CrashdumpInfo->MbiOffset),
|
||
|
CrashdumpInfo->MemoryData,
|
||
|
*DumpDataLength,
|
||
|
&cb
|
||
|
);
|
||
|
*DumpData = CrashdumpInfo->MemoryData;
|
||
|
CrashdumpInfo->MbiOffset += *DumpDataLength;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
CreateDumpFile(
|
||
|
PDEBUGPACKET dp,
|
||
|
LPEXCEPTION_DEBUG_INFO ed
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This function creates a crash dump file.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
dp - debug packet for current process
|
||
|
|
||
|
ed - exception data
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
TRUE - Crash dump was created
|
||
|
FALSE - Crash dump was NOT created
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
CRASH_DUMP_INFO CrashdumpInfo;
|
||
|
LPSTR p;
|
||
|
|
||
|
|
||
|
ZeroMemory( &CrashdumpInfo, sizeof(CRASH_DUMP_INFO) );
|
||
|
|
||
|
CrashdumpInfo.dp = dp;
|
||
|
CrashdumpInfo.ExceptionInfo = ed;
|
||
|
CrashdumpInfo.ptctx = NULL;
|
||
|
//
|
||
|
// Get first entry in module list
|
||
|
//
|
||
|
SymGetModuleInfo( dp->hProcess, (DWORD)0, &CrashdumpInfo.mi );
|
||
|
CrashdumpInfo.CrashModule = LocalAlloc( LPTR, 4096 );
|
||
|
|
||
|
p = ExpandPath( dp->options.szCrashDump );
|
||
|
if (!p) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
DmpCreateUserDump( p, CrashDumpCallback, &CrashdumpInfo );
|
||
|
|
||
|
free( p );
|
||
|
|
||
|
LocalFree( CrashdumpInfo.CrashModule );
|
||
|
|
||
|
return TRUE;
|
||
|
}
|