525 lines
9.9 KiB
C
525 lines
9.9 KiB
C
|
||
/*++
|
||
|
||
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);
|
||
}
|