windows-nt/Source/XPSP1/NT/base/tools/kdexts2/trap.cpp
2020-09-26 16:20:57 +08:00

391 lines
9.1 KiB
C++

/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
trap.c
Abstract:
WinDbg Extension Api
Revision History:
--*/
#include "precomp.h"
#include "i386.h"
#include "ia64.h"
#pragma hdrstop
extern ULONG64 STeip, STebp, STesp;
extern ULONG64 ThreadLastDump;
DECLARE_API( callback )
/*++
Routine Description:
Arguments:
args -
Return Value:
None
--*/
{
ULONG64 Address;
ULONG Flags;
ULONG result;
ULONG64 Thread;
ULONG64 prevCallout ;
INT calloutNum ;
INT whichCallout ;
ULONG64 InitialStack;
ULONG64 TrFr;
ULONG dwProcessor=0;
GetCurrentProcessor(Client, &dwProcessor, NULL);
Address = 0;
whichCallout = 0 ;
if (GetExpressionEx(args, &Address, &args)) {
if (!sscanf(args, "%ld", &whichCallout)) {
whichCallout = 0;
}
}
if (Address == 0) {
GetCurrentThreadAddr((USHORT)dwProcessor, &Address);
}
if (!DumpThreadEx(dwProcessor, "", Address, 0, Client))
return E_INVALIDARG;
GetFieldValue(Address, "ETHREAD", "Tcb.InitialStack", InitialStack);
/*
* now try and grab the contents of the stack
*/
if (GetFieldValue(InitialStack, "KCALLOUT_FRAME", "TrFr", TrFr)) {
dprintf("%08p: Unable to get callout frame\n", InitialStack);
return E_INVALIDARG;
}
if (TargetMachine == IMAGE_FILE_MACHINE_I386) {
/*
* Save eip, esp, ebp for quick backtrace from this callback in case
* they gave us a bogus callout frame.
*/
GetFieldValue(InitialStack, "KCALLOUT_FRAME", "Ret", STeip);
STesp = (ULONG) InitialStack ;
GetFieldValue(InitialStack, "KCALLOUT_FRAME", "Ebp", STebp);
}
/*
* Print the callout chain
*/
calloutNum = 0 ;
prevCallout = InitialStack ;
if (TargetMachine == IMAGE_FILE_MACHINE_I386) {
dprintf("Callout# ebp esp eip trapframe\n") ;
} else {
dprintf("Callout# esp trapframe\n") ;
}
while (prevCallout) {
if (TargetMachine == IMAGE_FILE_MACHINE_I386) {
ULONG Ret, Ebp;
GetFieldValue(prevCallout, "KCALLOUT_FRAME", "Ebp", Ebp);
GetFieldValue(prevCallout, "KCALLOUT_FRAME", "Ret", Ret);
dprintf(" %3d %08lx %08p %08lx %08lx",
calloutNum, Ebp, prevCallout,
Ret, TrFr) ;
if (calloutNum == whichCallout) {
STeip = Ret ;
STesp = (ULONG) prevCallout ;
STebp = Ebp ;
dprintf(" <-- !kb\n") ;
}
else
dprintf("\n") ;
} else {
dprintf(" %3d %08p %08lx",
calloutNum, prevCallout, TrFr) ;
}
/*
* advance to the next callout and try to read it
*/
calloutNum++ ;
GetFieldValue(prevCallout, "KCALLOUT_FRAME", "CbStk", prevCallout);
if (GetFieldValue(prevCallout, "KCALLOUT_FRAME", "TrFr", TrFr)) {
dprintf("%08p: Unable to get callout frame\n", prevCallout);
return E_INVALIDARG;
}
}
dprintf("\n") ;
if (calloutNum <= whichCallout) {
dprintf("#(%ld) is out of range. Frame #0 selected.\n", calloutNum) ;
}
return S_OK;
}
DECLARE_API( kb )
/*++
--*/
{
dprintf("\n");
dprintf(" \"!kb\" is no longer necessary as using \"kb\" after a \".cxr\" or \".trap\"\n");
dprintf(" command will give you the stack for the faulting thread.\n");
dprintf("\n");
dprintf(" Type \"!cxr\" or \"!trap\" for more help on this.\n");
dprintf("\n");
return S_OK;
}
DECLARE_API( kv )
/*++
--*/
{
dprintf("\n");
dprintf(" \"!kv\" is no longer necessary as using \"kv\" after a \".cxr\" or \".trap\"\n");
dprintf(" command will give you the stack for the faulting thread.\n");
dprintf("\n");
dprintf(" Type \"!cxr\" or \"!trap\" for more help on this.\n");
dprintf("\n");
return S_OK;
}
#define HIGH(x) ((ULONG) ((x>>32) & 0xFFFFFFFF))
#define LOW(x) ((ULONG) (x & 0xFFFFFFFF))
VOID
DisplayFullEmRegField(
ULONG64 EmRegValue,
EM_REG_FIELD EmRegFields[],
ULONG Field
)
{
dprintf( "\n %3.3s : %I64x : %-s",
EmRegFields[Field].SubName,
(EmRegValue >> EmRegFields[Field].Shift) & ((1 << EmRegFields[Field].Length) - 1),
EmRegFields[Field].Name
);
return;
} // DisplayFullEmRegField()
VOID
DisplayFullEmReg(
IN ULONG64 Val,
IN EM_REG_FIELD EmRegFields[],
IN DISPLAY_MODE DisplayMode
)
{
ULONG i, j;
i = j = 0;
if ( DisplayMode >= DISPLAY_MAX ) {
while( j < EM_REG_BITS ) {
DisplayFullEmRegField( Val, EmRegFields, i );
j += EmRegFields[i].Length;
i++;
}
}
else {
while( j < EM_REG_BITS ) {
if ( !strstr(EmRegFields[i].Name, "reserved" ) &&
!strstr(EmRegFields[i].Name, "ignored" ) ) {
DisplayFullEmRegField( Val, EmRegFields, i );
}
j += EmRegFields[i].Length;
i++;
}
}
dprintf("\n");
return;
} // DisplayFullEmReg()
#if 0
//
// ISR codes for General Exceptions: ISR{7:4}
//
#define ISR_ILLEGAL_OP 0 // Illegal operation fault
#define ISR_PRIV_OP 1 // Privileged operation fault
#define ISR_PRIV_REG 2 // Privileged register fault
#define ISR_RESVD_REG 3 // Reserved register/field fault
#define ISR_ILLEGAL_ISA 4 // Disabled instruction set transition fault
#define ISR_ILLEGAL_HAZARD 8 // Illegal hazard fault
//
// ISR codes for Nat Consumption Faults: ISR{7:4}
//
#define ISR_NAT_REG 1 // Nat Register Consumption fault
#define ISR_NAT_PAGE 2 // Nat Page Consumption fault
//
// For Traps ISR{4:0}
//
// FP trap
#define ISR_FP_TRAP 0
// Lower privilege transfer trap
#define ISR_LP_TRAP 1
// Taken branch trap
#define ISR_TB_TRAP 2
// Single step trap
#define ISR_SS_TRAP 3
// Unimplemented instruction address trap
#define ISR_UI_TRAP 4
ISR Settings for Non-Access Instructions
Instruction ISR fields
code{3:0} na r w
tpa 0 1 0 0
fc 1 1 1 0
probe 2 1 0 or 1 a 0 or 1 a
tak 3 1 0 0
lfetch, lfetch.fault 4 1 1 0
probe.fault 5 1 0 or 1 a 0 or 1 a
a. Sets r or w or both to 1 depending on the probe form.
#endif // 0
EM_REG_FIELD EmIsrFields[] = {
{ "code", "interruption Code" , 0x10, 0 }, // 0-15
{ "vector", "IA32 exception vector number" , 0x8, 16 }, // 16-23
{ "rv", "reserved0", 0x8, 24 }, // 24-31
{ "x", "eXecute exception", 0x1, 32 }, // 32
{ "w", "Write exception", 0x1, 33 }, // 33
{ "r", "Read exception", 0x1, 34 }, // 34
{ "na", "Non-Access exception", 0x1, 35 }, // 35
{ "sp", "Speculative load exception", 0x1, 36 }, // 36
{ "rs", "Register Stack", 0x1, 37 }, // 37
{ "ir", "Invalid Register frame", 0x1, 38 }, // 38
{ "ni", "Nested Interruption", 0x1, 39 }, // 39
{ "so", "IA32 Supervisor Override", 0x1, 40 }, // 40
{ "ei", "Exception IA64 Instruction", 0x2, 41 }, // 41-42
{ "ed", "Exception Deferral", 0x1, 43 }, // 43
{ "rv", "reserved1", 0x14, 44 } // 44-63
};
VOID
DisplayIsrIA64(
IN const PCHAR Header,
IN EM_ISR EmIsr,
IN DISPLAY_MODE DisplayMode
)
{
dprintf("%s", Header ? Header : "" );
if ( DisplayMode >= DISPLAY_MED ) {
DisplayFullEmReg( EM_ISRToULong64(EmIsr), EmIsrFields, DisplayMode );
}
else {
dprintf(
"ed ei so ni ir rs sp na r w x vector code\n\t\t "
"%1I64x %1I64x %1I64x %1I64x %1I64x %1I64x %1I64x %1I64x %1I64x %1I64x %1I64x %I64x %I64x\n",
EmIsr.ed,
EmIsr.ei,
EmIsr.so,
EmIsr.ni,
EmIsr.ir,
EmIsr.rs,
EmIsr.sp,
EmIsr.na,
EmIsr.r,
EmIsr.w,
EmIsr.x,
EmIsr.vector,
EmIsr.code
);
}
return;
} // DisplayIsrIA64()
DECLARE_API( isr )
/*++
Routine Description:
Arguments:
args -
Return Value:
None
--*/
{
ULONG64 isrValue;
ULONG result;
ULONG flags = 0;
char *header;
if (!GetExpressionEx(args,&isrValue, &args)) {
dprintf("USAGE: !isr 0xValue [display_mode:0,1,2]\n");
dprintf("USAGE: !isr @isr [display_mode:0,1,2]\n");
return E_INVALIDARG;
} else {
flags = (ULONG) GetExpression(args);
}
header = (flags > DISPLAY_MIN) ? NULL : "\tisr:\t";
if (TargetMachine != IMAGE_FILE_MACHINE_IA64)
{
dprintf("!isr not implemented for this architecture.\n");
}
else
{
DisplayIsrIA64( header, ULong64ToEM_ISR(isrValue), (DISPLAY_MODE) flags );
}
return S_OK;
} // !isr