Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

524 lines
9.9 KiB

/*++
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);
}