|
|
/*++
Copyright(c) 1999 Microsoft Corporation
Module Name:
triage.c
Abstract:
Triage dump support.
Author:
Matthew D. Hendel (math) 20-Jan-1999
Comments:
Do not merge this file with some other file. By leaving it in it's own compiland, we avoid having to link with all the other random variables in crashlib.
--*/
#include "iomgr.h"
#include "dumpctl.h"
#include <nt.h>
#include <ntrtl.h>
#include <windef.h>
#include <stdio.h>
#include <malloc.h>
#include <triage.h>
#include <ntverp.h>
#ifndef NtBuildNumber
# if DBG
# define NtBuildNumber (VER_PRODUCTBUILD | 0xC0000000)
# else
# define NtBuildNumber (VER_PRODUCTBUILD | 0xF0000000)
# endif
#endif
//
// NOTE: Pages sizes copied from ntos\inc. These must be kept in sync with
// global header files.
//
#define PAGE_SIZE_I386 0x1000
#define PAGE_SIZE_ALPHA 0x2000
#define PAGE_SIZE_IA64 0x2000
ULONG TriageImagePageSize = -1;
BOOLEAN TriagepVerifyDump( IN LPVOID TriageDumpBlock );
ULONG TriagepGetPageSize( ULONG Architecture );
PTRIAGE_DUMP TriagepGetTriagePointer( IN PVOID TriageDumpBlock );
#ifdef ALLOC_PRAGMA
#pragma alloc_text (INIT, TriagepVerifyDump)
#pragma alloc_text (INIT, TriagepGetPageSize)
#pragma alloc_text (INIT, TriagepGetTriagePointer)
#pragma alloc_text (INIT, TriageGetVersion)
#pragma alloc_text (INIT, TriageGetDriverCount)
#pragma alloc_text (INIT, TriageGetContext)
#pragma alloc_text (INIT, TriageGetExceptionRecord)
#pragma alloc_text (INIT, TriageGetBugcheckData)
#pragma alloc_text (INIT, TriageGetDriverEntry)
#endif
//++
//
// PULONG
// IndexByUlong(
// PVOID Pointer,
// ULONG Index
// )
//
// Routine Description:
//
// Return the address Index ULONGs into Pointer. That is,
// Index * sizeof (ULONG) bytes into Pointer.
//
// Arguments:
//
// Pointer - Start of region.
//
// Index - Number of ULONGs to index into.
//
// Return Value:
//
// PULONG representing the pointer described above.
//
//--
#define IndexByUlong(Pointer,Index) (&(((ULONG*) (Pointer)) [Index]))
//++
//
// PBYTE
// IndexByByte(
// PVOID Pointer,
// ULONG Index
// )
//
// Routine Description:
//
// Return the address Index BYTEs into Pointer. That is,
// Index * sizeof (BYTE) bytes into Pointer.
//
// Arguments:
//
// Pointer - Start of region.
//
// Index - Number of BYTEs to index into.
//
// Return Value:
//
// PBYTE representing the pointer described above.
//
//--
#define IndexByByte(Pointer, Index) (&(((BYTE*) (Pointer)) [Index]))
ULONG TriagepGetPageSize( ULONG Architecture ) { switch (Architecture) {
case IMAGE_FILE_MACHINE_I386: return PAGE_SIZE_I386;
case IMAGE_FILE_MACHINE_ALPHA: return PAGE_SIZE_ALPHA;
case IMAGE_FILE_MACHINE_IA64: return PAGE_SIZE_IA64;
default: return -1; } }
BOOLEAN TriagepVerifyDump( IN LPVOID TriageDumpBlock ) { BOOLEAN Succ = FALSE; PMEMORY_DUMP MemoryDump = NULL;
if (!TriageDumpBlock) { return FALSE; }
MemoryDump = (PMEMORY_DUMP) TriageDumpBlock;
try {
if (MemoryDump->Header.ValidDump != 'PMUD' || MemoryDump->Header.Signature != 'EGAP' || TriagepGetPageSize (MemoryDump->Header.MachineImageType) == -1) {
Succ = FALSE; leave; }
TriageImagePageSize = TriagepGetPageSize (MemoryDump->Header.MachineImageType);
if ( MemoryDump->Header.DumpType != DUMP_TYPE_TRIAGE || *(ULONG*)IndexByByte (MemoryDump, MemoryDump->Triage.SizeOfDump - sizeof (DWORD)) != TRIAGE_DUMP_VALID ) {
Succ = FALSE; leave; }
// else
Succ = TRUE; }
except (EXCEPTION_EXECUTE_HANDLER) {
Succ = FALSE; }
return Succ; }
PTRIAGE_DUMP TriagepGetTriagePointer( IN PVOID TriageDumpBlock ) { ASSERT (TriageImagePageSize != -1); ASSERT (TriagepVerifyDump (TriageDumpBlock));
return (PTRIAGE_DUMP) IndexByByte (TriageDumpBlock, TriageImagePageSize); }
NTSTATUS TriageGetVersion( IN LPVOID TriageDumpBlock, OUT ULONG * MajorVersion, OUT ULONG * MinorVersion, OUT ULONG * ServicePackBuild ) { PTRIAGE_DUMP TriageDump; PDUMP_HEADER DumpHeader;
if (!TriagepVerifyDump (TriageDumpBlock)) { return STATUS_INVALID_PARAMETER; }
TriageDump = TriagepGetTriagePointer (TriageDumpBlock);
if (!TriageDump) { return STATUS_INVALID_PARAMETER; }
DumpHeader = (PDUMP_HEADER) TriageDumpBlock;
if (MajorVersion) { *MajorVersion = DumpHeader->MajorVersion; }
if (MinorVersion) { *MinorVersion = DumpHeader->MinorVersion; }
if (ServicePackBuild) { *ServicePackBuild = TriageDump->ServicePackBuild; }
return STATUS_SUCCESS; }
NTSTATUS TriageGetDriverCount( IN LPVOID TriageDumpBlock, OUT ULONG * DriverCount ) { PTRIAGE_DUMP TriageDump;
if (!TriagepVerifyDump (TriageDumpBlock)) { return STATUS_INVALID_PARAMETER; }
TriageDump = TriagepGetTriagePointer (TriageDumpBlock);
if (!TriageDump) { return STATUS_INVALID_PARAMETER; }
*DriverCount = TriageDump->DriverCount;
return STATUS_SUCCESS; }
#if 0
NTSTATUS TriageGetContext( IN LPVOID TriageDumpBlock, OUT LPVOID Context, IN ULONG SizeInBytes ) { PTRIAGE_DUMP TriageDump;
if (!TriagepVerifyDump (TriageDumpBlock)) { return STATUS_INVALID_PARAMETER; }
TriageDump = TriagepGetTriagePointer (TriageDumpBlock);
if (!TriageDump) { return STATUS_INVALID_PARAMETER; }
//
// Copy the CONTEXT record.
//
if (SizeInBytes == -1) { SizeInBytes = sizeof (CONTEXT); }
RtlCopyMemory (Context, IndexByUlong (TriageDumpBlock, TriageDump->ContextOffset), SizeInBytes );
return STATUS_SUCCESS; }
NTSTATUS TriageGetExceptionRecord( IN LPVOID TriageDumpBlock, OUT EXCEPTION_RECORD * ExceptionRecord ) { PTRIAGE_DUMP TriageDump;
if (!TriagepVerifyDump (TriageDumpBlock)) { return STATUS_INVALID_PARAMETER; }
TriageDump = TriagepGetTriagePointer (TriageDumpBlock);
if (!TriageDump) { return STATUS_INVALID_PARAMETER; }
RtlCopyMemory (ExceptionRecord, IndexByUlong (TriageDumpBlock, TriageDump->ExceptionOffset), sizeof (*ExceptionRecord) );
return STATUS_SUCCESS; } #endif
LOGICAL TriageActUpon( IN PVOID TriageDumpBlock ) { PTRIAGE_DUMP TriageDump;
if (!TriagepVerifyDump (TriageDumpBlock)) { return FALSE; }
TriageDump = TriagepGetTriagePointer (TriageDumpBlock);
if (!TriageDump) { return FALSE; }
if ((TriageDump->TriageOptions & DCB_TRIAGE_DUMP_ACT_UPON_ENABLED) == 0) { return FALSE; }
return TRUE; }
NTSTATUS TriageGetBugcheckData( IN LPVOID TriageDumpBlock, OUT ULONG * BugCheckCode, OUT UINT_PTR * BugCheckParam1, OUT UINT_PTR * BugCheckParam2, OUT UINT_PTR * BugCheckParam3, OUT UINT_PTR * BugCheckParam4 ) { PDUMP_HEADER DumpHeader;
if (!TriagepVerifyDump (TriageDumpBlock)) { return STATUS_INVALID_PARAMETER; }
DumpHeader = (PDUMP_HEADER) TriageDumpBlock;
*BugCheckCode = DumpHeader->BugCheckCode; *BugCheckParam1 = DumpHeader->BugCheckParameter1; *BugCheckParam2 = DumpHeader->BugCheckParameter2; *BugCheckParam3 = DumpHeader->BugCheckParameter3; *BugCheckParam4 = DumpHeader->BugCheckParameter4;
return STATUS_SUCCESS; }
PKLDR_DATA_TABLE_ENTRY TriageGetLoaderEntry( IN PVOID TriageDumpBlock, IN ULONG ModuleIndex )
/*++
Routine Description:
This function retrieves a loaded module list entry.
Arguments:
TriageDumpBlock - Supplies the triage dump to reference.
ModuleIndex - Supplies the driver index number to locate.
Return Value:
A pointer to a loader data table entry if one is available, NULL if not.
Environment:
Kernel mode, APC_LEVEL or below. Phase 0 only.
N.B. This function is for use by memory management ONLY.
--*/
{ PDUMP_STRING DriverName; PDUMP_DRIVER_ENTRY DriverList; PTRIAGE_DUMP TriageDump; PKLDR_DATA_TABLE_ENTRY DataTableEntry;
if (!TriagepVerifyDump (TriageDumpBlock)) { return NULL; }
TriageDump = TriagepGetTriagePointer (TriageDumpBlock);
if (ModuleIndex >= TriageDump->DriverCount) { return NULL; }
DriverList = (PDUMP_DRIVER_ENTRY) IndexByByte (TriageDumpBlock, TriageDump->DriverListOffset);
DataTableEntry = (PKLDR_DATA_TABLE_ENTRY) (&DriverList[ModuleIndex].LdrEntry);
//
// Repoint the module driver name into the triage buffer.
//
DriverName = (PDUMP_STRING) IndexByByte (TriageDumpBlock, DriverList [ ModuleIndex ].DriverNameOffset);
DataTableEntry->BaseDllName.Length = (USHORT) (DriverName->Length * sizeof (WCHAR)); DataTableEntry->BaseDllName.MaximumLength = DataTableEntry->BaseDllName.Length; DataTableEntry->BaseDllName.Buffer = DriverName->Buffer;
return DataTableEntry; }
PVOID TriageGetMmInformation( IN PVOID TriageDumpBlock )
/*++
Routine Description:
This function retrieves a loaded module list entry.
Arguments:
TriageDumpBlock - Supplies the triage dump to reference.
Return Value:
A pointer to an opaque Mm information structure.
Environment:
Kernel mode, APC_LEVEL or below. Phase 0 only.
N.B. This function is for use by memory management ONLY.
--*/
{ PTRIAGE_DUMP TriageDump;
if (!TriagepVerifyDump (TriageDumpBlock)) { return NULL; }
TriageDump = TriagepGetTriagePointer (TriageDumpBlock);
if (!TriageDump) { return NULL; }
return (PVOID)IndexByByte (TriageDumpBlock, TriageDump->MmOffset); }
|