1386 lines
44 KiB
C
1386 lines
44 KiB
C
/*** ntreg.c - processor-specific register structures
|
||
*
|
||
* Copyright <C> 1990, Microsoft Corporation
|
||
*
|
||
* Purpose:
|
||
* Structures used to parse and access register and flag
|
||
* fields.
|
||
*
|
||
* Revision History:
|
||
*
|
||
* [-] 01-Jul-1990 Richk Created.
|
||
*
|
||
*************************************************************************/
|
||
|
||
#include <conio.h>
|
||
#include <string.h>
|
||
#include "ntsdp.h"
|
||
#include "86reg.h"
|
||
#if defined(KERNEL) && defined(i386)
|
||
#include <ntos.h>
|
||
#endif
|
||
|
||
#if defined(KERNEL) && defined(i386)
|
||
#include <ntos.h>
|
||
extern USHORT NtsdCurrentProcessor;
|
||
extern ULONG NumberProcessors;
|
||
extern BOOLEAN fSetGlobalDataBrkpts;
|
||
extern BOOLEAN fSwitched;
|
||
USHORT PreviousProcessor;
|
||
VDMCONTEXT SavedRegisterContext;
|
||
extern BOOLEAN KdVerbose; // from ntsym.c
|
||
#define fVerboseOutput KdVerbose
|
||
#endif
|
||
|
||
#define DPRINT(str) if (fVerboseOutput) dprintf str
|
||
|
||
|
||
extern ADDR EAaddr[2]; // from module ntdis.c
|
||
extern ulong EXPRLastExpression; // from module ntexpr.c
|
||
extern ulong EXPRLastDump; // from module ntcmd.c
|
||
extern BOOLEAN STtrace; // from module ntcmd.c
|
||
extern ULONG STeip, STebp, STesp; // from module ntcmd.c
|
||
extern int fControlC;
|
||
|
||
extern PUCHAR UserRegs[10];
|
||
|
||
BOOLEAN X86fDelayInstruction(void);
|
||
void X86OutputHelp(void);
|
||
#if defined(KERNEL) && defined(i386)
|
||
BOOLEAN fTraceFlag;
|
||
void InitFirCache(ULONG, PUCHAR);
|
||
void SaveProcessorState(void);
|
||
void RestoreProcessorState(void);
|
||
BOOLEAN X86GetTraceFlag(void);
|
||
extern NTSTATUS TaskGate2TrapFrame(USHORT, PKTRAP_FRAME, PULONG);
|
||
extern NTSTATUS ReadTrapFrame(ULONG, PKTRAP_FRAME);
|
||
extern DbgKdInitVirtualCacheEntry (ULONG, ULONG, PUCHAR);
|
||
#endif
|
||
ULONG GetDregValue(ULONG);
|
||
void SetDregValue(ULONG, ULONG);
|
||
void X86ClearTraceFlag(void);
|
||
void X86SetTraceFlag(void);
|
||
|
||
PUCHAR X86RegNameFromIndex(ULONG);
|
||
|
||
extern PUCHAR pchCommand; // current pointer in command buffer
|
||
|
||
#if defined(KERNEL) && defined(i386)
|
||
KSPECIAL_REGISTERS SpecialRegContext, SavedSpecialRegContext;
|
||
ULONG TerseLevel = 1;
|
||
#endif
|
||
|
||
ULONG VDMcbBrkptLength = 1L;
|
||
ULONG VDMtrapInstr = 0xcc;
|
||
#if !defined(KERNEL) && defined(i386)
|
||
ULONG VDMContextType = VDMCONTEXT_CONTROL | VDMCONTEXT_INTEGER | VDMCONTEXT_SEGMENTS
|
||
| VDMCONTEXT_DEBUG_REGISTERS;
|
||
#else
|
||
ULONG VDMContextType = VDMCONTEXT_CONTROL | VDMCONTEXT_INTEGER | VDMCONTEXT_SEGMENTS;
|
||
#endif
|
||
|
||
#if defined(KERNEL) && defined(i386)
|
||
ULONG contextState, SavedContextState;
|
||
#define CONTEXTNONE 5 // no context
|
||
#define CONTEXTFIR 0 // only unchanged FIR in context
|
||
#define CONTEXTVALID 1 // full, but unchanged context
|
||
#define CONTEXTDIRTY 2 // full, but changed context
|
||
#define CONTEXTSHORT 3 // short context loaded (unchanged)
|
||
#define CONTEXTHALF 4 // half context loaded
|
||
|
||
|
||
UCHAR FullContextPresent[] = { FALSE, TRUE, TRUE, FALSE, FALSE };
|
||
#endif
|
||
|
||
char szGsReg[] = "gs";
|
||
char szFsReg[] = "fs";
|
||
char szEsReg[] = "es";
|
||
char szDsReg[] = "ds";
|
||
char szEdiReg[] = "edi";
|
||
char szEsiReg[] = "esi";
|
||
char szEbxReg[] = "ebx";
|
||
char szEdxReg[] = "edx";
|
||
char szEcxReg[] = "ecx";
|
||
char szEaxReg[] = "eax";
|
||
char szEbpReg[] = "ebp";
|
||
char szEipReg[] = "eip";
|
||
char szCsReg[] = "cs";
|
||
char szEflReg[] = "efl";
|
||
char szEspReg[] = "esp";
|
||
char szSsReg[] = "ss";
|
||
#if defined(KERNEL) && defined(i386)
|
||
char szCr0Reg[] = "cr0";
|
||
char szCr2Reg[] = "cr2";
|
||
char szCr3Reg[] = "cr3";
|
||
char szCr4Reg[] = "cr4";
|
||
char szDr0Reg[] = "dr0";
|
||
char szDr1Reg[] = "dr1";
|
||
char szDr2Reg[] = "dr2";
|
||
char szDr3Reg[] = "dr3";
|
||
char szDr6Reg[] = "dr6";
|
||
char szDr7Reg[] = "dr7";
|
||
char szGdtrReg[] = "gdtr";
|
||
char szGdtlReg[] = "gdtl";
|
||
char szIdtrReg[] = "idtr";
|
||
char szIdtlReg[] = "idtl";
|
||
char szTrReg[] = "tr";
|
||
char szLdtrReg[] = "ldtr";
|
||
#endif
|
||
char szDiReg[] = "di";
|
||
char szSiReg[] = "si";
|
||
char szBxReg[] = "bx";
|
||
char szDxReg[] = "dx";
|
||
char szCxReg[] = "cx";
|
||
char szAxReg[] = "ax";
|
||
char szBpReg[] = "bp";
|
||
char szIpReg[] = "ip";
|
||
char szFlReg[] = "fl";
|
||
char szSpReg[] = "sp";
|
||
char szBlReg[] = "bl";
|
||
char szDlReg[] = "dl";
|
||
char szClReg[] = "cl";
|
||
char szAlReg[] = "al";
|
||
char szBhReg[] = "bh";
|
||
char szDhReg[] = "dh";
|
||
char szChReg[] = "ch";
|
||
char szAhReg[] = "ah";
|
||
char szIoplFlag[] = "iopl";
|
||
char szFlagOf[] = "of";
|
||
char szFlagDf[] = "df";
|
||
char szFlagIf[] = "if";
|
||
char szFlagTf[] = "tf";
|
||
char szFlagSf[] = "sf";
|
||
char szFlagZf[] = "zf";
|
||
char szFlagAf[] = "af";
|
||
char szFlagPf[] = "pf";
|
||
char szFlagCf[] = "cf";
|
||
char szFlagVip[] = "vip";
|
||
char szFlagVif[] = "vif";
|
||
|
||
extern char szEaPReg[];
|
||
extern char szExpPReg[];
|
||
extern char szRaPReg[];
|
||
extern char szPPReg[];
|
||
extern char szU0Preg[];
|
||
extern char szU1Preg[];
|
||
extern char szU2Preg[];
|
||
extern char szU3Preg[];
|
||
extern char szU4Preg[];
|
||
extern char szU5Preg[];
|
||
extern char szU6Preg[];
|
||
extern char szU7Preg[];
|
||
extern char szU8Preg[];
|
||
extern char szU9Preg[];
|
||
|
||
struct Reg regname[] = {
|
||
{ szGsReg, REGGS },
|
||
{ szFsReg, REGFS },
|
||
{ szEsReg, REGES },
|
||
{ szDsReg, REGDS },
|
||
{ szEdiReg, REGEDI },
|
||
{ szEsiReg, REGESI },
|
||
{ szEbxReg, REGEBX },
|
||
{ szEdxReg, REGEDX },
|
||
{ szEcxReg, REGECX },
|
||
{ szEaxReg, REGEAX },
|
||
{ szEbpReg, REGEBP },
|
||
{ szEipReg, REGEIP },
|
||
{ szCsReg, REGCS },
|
||
{ szEflReg, REGEFL },
|
||
{ szEspReg, REGESP },
|
||
{ szSsReg, REGSS },
|
||
#if defined(KERNEL) && defined(i386)
|
||
{ szCr0Reg, REGCR0 },
|
||
{ szCr2Reg, REGCR2 },
|
||
{ szCr3Reg, REGCR3 },
|
||
{ szCr4Reg, REGCR4 },
|
||
{ szDr0Reg, REGDR0 },
|
||
{ szDr1Reg, REGDR1 },
|
||
{ szDr2Reg, REGDR2 },
|
||
{ szDr3Reg, REGDR3 },
|
||
{ szDr6Reg, REGDR6 },
|
||
{ szDr7Reg, REGDR7 },
|
||
{ szGdtrReg, REGGDTR },
|
||
{ szGdtlReg, REGGDTL },
|
||
{ szIdtrReg, REGIDTR },
|
||
{ szIdtlReg, REGIDTL },
|
||
{ szTrReg, REGTR },
|
||
{ szLdtrReg, REGLDTR },
|
||
#endif
|
||
{ szDiReg, REGDI },
|
||
{ szSiReg, REGSI },
|
||
{ szBxReg, REGBX },
|
||
{ szDxReg, REGDX },
|
||
{ szCxReg, REGCX },
|
||
{ szAxReg, REGAX },
|
||
{ szBpReg, REGBP },
|
||
{ szIpReg, REGIP },
|
||
{ szFlReg, REGFL },
|
||
{ szSpReg, REGSP },
|
||
{ szBlReg, REGBL },
|
||
{ szDlReg, REGDL },
|
||
{ szClReg, REGCL },
|
||
{ szAlReg, REGAL },
|
||
{ szBhReg, REGBH },
|
||
{ szDhReg, REGDH },
|
||
{ szChReg, REGCH },
|
||
{ szAhReg, REGAH },
|
||
{ szIoplFlag, FLAGIOPL },
|
||
{ szFlagOf, FLAGOF },
|
||
{ szFlagDf, FLAGDF },
|
||
{ szFlagIf, FLAGIF },
|
||
{ szFlagTf, FLAGTF },
|
||
{ szFlagSf, FLAGSF },
|
||
{ szFlagZf, FLAGZF },
|
||
{ szFlagAf, FLAGAF },
|
||
{ szFlagPf, FLAGPF },
|
||
{ szFlagCf, FLAGCF },
|
||
{ szFlagVip, FLAGVIP },
|
||
{ szFlagVif, FLAGVIF },
|
||
{ szEaPReg, PREGEA },
|
||
{ szExpPReg, PREGEXP },
|
||
{ szRaPReg, PREGRA },
|
||
{ szPPReg, PREGP },
|
||
{ szU0Preg, PREGU0 },
|
||
{ szU1Preg, PREGU1 },
|
||
{ szU2Preg, PREGU2 },
|
||
{ szU3Preg, PREGU3 },
|
||
{ szU4Preg, PREGU4 },
|
||
{ szU5Preg, PREGU5 },
|
||
{ szU6Preg, PREGU6 },
|
||
{ szU7Preg, PREGU7 },
|
||
{ szU8Preg, PREGU8 },
|
||
{ szU9Preg, PREGU9 },
|
||
};
|
||
|
||
#define REGNAMESIZE (sizeof(regname) / sizeof(struct Reg))
|
||
|
||
struct SubReg X86subregname[] = {
|
||
{ REGEDI, 0, 0xffff }, // DI register
|
||
{ REGESI, 0, 0xffff }, // SI register
|
||
{ REGEBX, 0, 0xffff }, // BX register
|
||
{ REGEDX, 0, 0xffff }, // DX register
|
||
{ REGECX, 0, 0xffff }, // CX register
|
||
{ REGEAX, 0, 0xffff }, // AX register
|
||
{ REGEBP, 0, 0xffff }, // BP register
|
||
{ REGEIP, 0, 0xffff }, // IP register
|
||
{ REGEFL, 0, 0xffff }, // FL register
|
||
{ REGESP, 0, 0xffff }, // SP register
|
||
{ REGEBX, 0, 0xff }, // BL register
|
||
{ REGEDX, 0, 0xff }, // DL register
|
||
{ REGECX, 0, 0xff }, // CL register
|
||
{ REGEAX, 0, 0xff }, // AL register
|
||
{ REGEBX, 8, 0xff }, // BH register
|
||
{ REGEDX, 8, 0xff }, // DH register
|
||
{ REGECX, 8, 0xff }, // CH register
|
||
{ REGEAX, 8, 0xff }, // AH register
|
||
{ REGEFL, 12, 3 }, // IOPL level value
|
||
{ REGEFL, 11, 1 }, // OF (overflow flag)
|
||
{ REGEFL, 10, 1 }, // DF (direction flag)
|
||
{ REGEFL, 9, 1 }, // IF (interrupt enable flag)
|
||
{ REGEFL, 8, 1 }, // TF (trace flag)
|
||
{ REGEFL, 7, 1 }, // SF (sign flag)
|
||
{ REGEFL, 6, 1 }, // ZF (zero flag)
|
||
{ REGEFL, 4, 1 }, // AF (aux carry flag)
|
||
{ REGEFL, 2, 1 }, // PF (parity flag)
|
||
{ REGEFL, 0, 1 }, // CF (carry flag)
|
||
{ REGEFL, 20, 1 }, // VIP (virtual interrupt pending)
|
||
{ REGEFL, 19, 1 } // VIF (virtual interrupt flag)
|
||
};
|
||
|
||
/*** X86GetRegFlagValue - get register or flag value
|
||
*
|
||
* Purpose:
|
||
* Return the value of the specified register or flag.
|
||
* This routine calls X86GetRegValue to get the register
|
||
* value and shifts and masks appropriately to extract a
|
||
* flag value.
|
||
*
|
||
* Input:
|
||
* regnum - register or flag specification
|
||
*
|
||
* Returns:
|
||
* Value of register or flag.
|
||
*
|
||
*************************************************************************/
|
||
|
||
ULONG
|
||
X86GetRegFlagValue (
|
||
ULONG regnum
|
||
)
|
||
{
|
||
ULONG value;
|
||
|
||
if (regnum < FLAGBASE) {
|
||
value = X86GetRegValue(regnum);
|
||
} else {
|
||
regnum -= FLAGBASE;
|
||
value = X86GetRegValue(X86subregname[regnum].regindex);
|
||
value = (value >> X86subregname[regnum].shift) & X86subregname[regnum].mask;
|
||
}
|
||
return value;
|
||
}
|
||
|
||
/*** X86GetRegValue - get register value
|
||
*
|
||
* Purpose:
|
||
* Returns the value of the register from the processor
|
||
* context structure.
|
||
*
|
||
* Input:
|
||
* regnum - register specification
|
||
*
|
||
* Returns:
|
||
* value of the register from the context structure
|
||
*
|
||
*************************************************************************/
|
||
|
||
ULONG
|
||
X86GetRegValue (
|
||
ULONG regnum
|
||
)
|
||
{
|
||
#if defined(KERNEL) && defined(i386)
|
||
ULONG cBytesRead;
|
||
NTSTATUS NtStatus;
|
||
|
||
//fprintf (stdout, "X86GetRegValue %d\n", regnum);
|
||
switch (contextState) {
|
||
case CONTEXTFIR:
|
||
switch (regnum) {
|
||
case REGEIP: return VDMRegisterContext.Eip;
|
||
case REGDR6: return SpecialRegContext.KernelDr6;
|
||
case REGDR7: return SpecialRegContext.KernelDr7;
|
||
}
|
||
|
||
//
|
||
// Requested register was not in CONTEXTFIR - go get the next
|
||
// context level. (we skip CONTEXTSMALL since that's the only
|
||
// api we have)
|
||
//
|
||
|
||
if (!DbgGetThreadContext(NtsdCurrentProcessor, &VDMRegisterContext)) {
|
||
dprintf("DbgKdGetContext failed\n");
|
||
exit(1);
|
||
}
|
||
|
||
contextState = CONTEXTHALF;
|
||
|
||
// Fallthrough!
|
||
case CONTEXTSHORT:
|
||
switch (regnum) {
|
||
case REGCS: return VDMRegisterContext.SegCs;
|
||
case REGDS: return VDMRegisterContext.SegDs;
|
||
case REGES: return VDMRegisterContext.SegEs;
|
||
case REGFS: return VDMRegisterContext.SegFs;
|
||
case REGEIP: return VDMRegisterContext.Eip;
|
||
case REGEFL: return VDMRegisterContext.EFlags;
|
||
case REGDR6: return SpecialRegContext.KernelDr6;
|
||
case REGDR7: return SpecialRegContext.KernelDr7;
|
||
}
|
||
|
||
//
|
||
// Requested register was not in CONTEXTSHORT - go get the next
|
||
// context level.
|
||
//
|
||
|
||
case CONTEXTNONE:
|
||
if (contextState < CONTEXTHALF || contextState == CONTEXTNONE) {
|
||
if (!DbgGetThreadContext(NtsdCurrentProcessor, &VDMRegisterContext)) {
|
||
dprintf("DbgKdGetContext failed\n");
|
||
exit(1);
|
||
}
|
||
contextState = CONTEXTHALF;
|
||
}
|
||
|
||
// Fallthrough!
|
||
case CONTEXTHALF:
|
||
switch (regnum) {
|
||
case REGCS: return VDMRegisterContext.SegCs;
|
||
case REGDS: return VDMRegisterContext.SegDs;
|
||
case REGES: return VDMRegisterContext.SegEs;
|
||
case REGFS: return VDMRegisterContext.SegFs;
|
||
case REGEIP: return VDMRegisterContext.Eip;
|
||
case REGEFL: return VDMRegisterContext.EFlags;
|
||
case REGDR6: return SpecialRegContext.KernelDr6;
|
||
case REGDR7: return SpecialRegContext.KernelDr7;
|
||
|
||
case REGGS: return VDMRegisterContext.SegGs;
|
||
case REGSS: return VDMRegisterContext.SegSs;
|
||
case REGEDI: return VDMRegisterContext.Edi;
|
||
case REGESI: return VDMRegisterContext.Esi;
|
||
case REGEBX: return VDMRegisterContext.Ebx;
|
||
case REGEDX: return VDMRegisterContext.Edx;
|
||
case REGECX: return VDMRegisterContext.Ecx;
|
||
case REGEAX: return VDMRegisterContext.Eax;
|
||
case REGEBP: return VDMRegisterContext.Ebp;
|
||
case REGESP: return VDMRegisterContext.Esp;
|
||
|
||
}
|
||
|
||
//
|
||
// The requested register is not in our current context, load up
|
||
// a complete context
|
||
//
|
||
|
||
NtStatus = DbgKdReadControlSpace(NtsdCurrentProcessor,
|
||
(PVOID)sizeof(CONTEXT),
|
||
(PVOID)&SpecialRegContext,
|
||
sizeof(KSPECIAL_REGISTERS),
|
||
&cBytesRead);
|
||
if (!NT_SUCCESS(NtStatus) ||
|
||
cBytesRead != sizeof(KSPECIAL_REGISTERS)) {
|
||
dprintf("DbgKdReadControlSpace failed\n");
|
||
exit(1);
|
||
}
|
||
|
||
contextState = CONTEXTVALID;
|
||
}
|
||
|
||
//
|
||
// We must have a complete context...
|
||
//
|
||
|
||
#endif
|
||
switch (regnum) {
|
||
case REGGS:
|
||
return VDMRegisterContext.SegGs;
|
||
case REGFS:
|
||
return VDMRegisterContext.SegFs;
|
||
case REGES:
|
||
return VDMRegisterContext.SegEs;
|
||
case REGDS:
|
||
return VDMRegisterContext.SegDs;
|
||
case REGEDI:
|
||
return VDMRegisterContext.Edi;
|
||
case REGESI:
|
||
return VDMRegisterContext.Esi;
|
||
case REGSI:
|
||
return(VDMRegisterContext.Esi & 0xffff);
|
||
case REGDI:
|
||
return(VDMRegisterContext.Edi & 0xffff);
|
||
case REGEBX:
|
||
return VDMRegisterContext.Ebx;
|
||
case REGEDX:
|
||
return VDMRegisterContext.Edx;
|
||
case REGECX:
|
||
return VDMRegisterContext.Ecx;
|
||
case REGEAX:
|
||
return VDMRegisterContext.Eax;
|
||
case REGEBP:
|
||
return VDMRegisterContext.Ebp;
|
||
case REGEIP:
|
||
return VDMRegisterContext.Eip;
|
||
case REGCS:
|
||
return VDMRegisterContext.SegCs;
|
||
case REGEFL:
|
||
return VDMRegisterContext.EFlags;
|
||
case REGESP:
|
||
return VDMRegisterContext.Esp;
|
||
case REGSS:
|
||
return VDMRegisterContext.SegSs;
|
||
case PREGEA:
|
||
return EAaddr[0].flat;
|
||
case PREGEXP:
|
||
return EXPRLastExpression;
|
||
case PREGRA: {
|
||
ADDR stackBP;
|
||
struct {
|
||
ULONG oldBP;
|
||
ULONG retAddr;
|
||
} stackRead;
|
||
FormAddress(&stackBP, (ULONG)X86GetRegValue(REGSS), (ULONG)X86GetRegValue(REGEBP));
|
||
GetMemString(&stackBP, (PUCHAR)&stackRead, sizeof(stackRead));
|
||
return stackRead.retAddr;
|
||
}
|
||
case PREGP:
|
||
return EXPRLastDump;
|
||
case PREGU0:
|
||
case PREGU1:
|
||
case PREGU2:
|
||
case PREGU3:
|
||
case PREGU4:
|
||
case PREGU5:
|
||
case PREGU6:
|
||
case PREGU7:
|
||
case PREGU8:
|
||
case PREGU9:
|
||
return (ULONG)UserRegs[regnum - PREGU0];
|
||
|
||
#if defined(KERNEL) && defined(i386)
|
||
case REGCR0:
|
||
return SpecialRegContext.Cr0;
|
||
case REGCR2:
|
||
return SpecialRegContext.Cr2;
|
||
case REGCR3:
|
||
return SpecialRegContext.Cr3;
|
||
case REGCR4:
|
||
return SpecialRegContext.Cr4;
|
||
case REGDR0:
|
||
return SpecialRegContext.KernelDr0;
|
||
case REGDR1:
|
||
return SpecialRegContext.KernelDr1;
|
||
case REGDR2:
|
||
return SpecialRegContext.KernelDr2;
|
||
case REGDR3:
|
||
return SpecialRegContext.KernelDr3;
|
||
case REGDR6:
|
||
return SpecialRegContext.KernelDr6;
|
||
case REGDR7:
|
||
return SpecialRegContext.KernelDr7;
|
||
case REGGDTR:
|
||
return SpecialRegContext.Gdtr.Base;
|
||
case REGGDTL:
|
||
return (ULONG)SpecialRegContext.Gdtr.Limit;
|
||
case REGIDTR:
|
||
return SpecialRegContext.Idtr.Base;
|
||
case REGIDTL:
|
||
return (ULONG)SpecialRegContext.Idtr.Limit;
|
||
case REGTR:
|
||
return (ULONG)SpecialRegContext.Tr;
|
||
case REGLDTR:
|
||
return (ULONG)SpecialRegContext.Ldtr;
|
||
#endif
|
||
|
||
#if !defined(KERNEL) && defined(i386)
|
||
case REGDR0:
|
||
return VDMRegisterContext.Dr0;
|
||
case REGDR1:
|
||
return VDMRegisterContext.Dr1;
|
||
case REGDR2:
|
||
return VDMRegisterContext.Dr2;
|
||
case REGDR3:
|
||
return VDMRegisterContext.Dr3;
|
||
case REGDR6:
|
||
return VDMRegisterContext.Dr6;
|
||
case REGDR7:
|
||
return VDMRegisterContext.Dr7;
|
||
#endif
|
||
default:
|
||
dprintf("X86GetRegValue: unknown register %lx requested\n",regnum);
|
||
return((ULONG)-1);
|
||
}
|
||
}
|
||
|
||
/*** X86SetRegFlagValue - set register or flag value
|
||
*
|
||
* Purpose:
|
||
* Set the value of the specified register or flag.
|
||
* This routine calls X86SetRegValue to set the register
|
||
* value and shifts and masks appropriately to set a
|
||
* flag value.
|
||
*
|
||
* Input:
|
||
* regnum - register or flag specification
|
||
* regvalue - new register or flag value
|
||
*
|
||
* Output:
|
||
* None.
|
||
*
|
||
* Exceptions:
|
||
* error exit: OVERFLOW - value too large for flag
|
||
*
|
||
* Notes:
|
||
*
|
||
*************************************************************************/
|
||
|
||
void X86SetRegFlagValue (ULONG regnum, ULONG regvalue)
|
||
{
|
||
ULONG regindex;
|
||
ULONG newvalue;
|
||
PUCHAR szValue;
|
||
ULONG index;
|
||
|
||
if (regnum >= PREGU0 && regnum <= PREGU9) {
|
||
szValue = (PUCHAR)regvalue;
|
||
index = 0L;
|
||
|
||
while (szValue[index] >= ' ')
|
||
index++;
|
||
szValue[index] = 0;
|
||
if (szValue = UserRegs[regnum - PREGU0])
|
||
free(szValue);
|
||
szValue = UserRegs[regnum - PREGU0] =
|
||
malloc(strlen((PUCHAR)regvalue) + 1);
|
||
if (szValue)
|
||
strcpy(szValue, (PUCHAR)regvalue);
|
||
}
|
||
|
||
else if (regnum < PREGBASE)
|
||
X86SetRegValue(regnum, regvalue);
|
||
else if (regnum >= FLAGBASE) {
|
||
regnum -= FLAGBASE;
|
||
if (regvalue > X86subregname[regnum].mask)
|
||
error(OVERFLOW);
|
||
regindex = X86subregname[regnum].regindex;
|
||
newvalue = X86GetRegValue(regindex) &
|
||
(~(X86subregname[regnum].mask << X86subregname[regnum].shift)) |
|
||
(regvalue << X86subregname[regnum].shift);
|
||
X86SetRegValue(regindex, newvalue);
|
||
}
|
||
}
|
||
|
||
/*** X86SetRegValue - set register value
|
||
*
|
||
* Purpose:
|
||
* Set the value of the register in the processor context
|
||
* structure.
|
||
*
|
||
* Input:
|
||
* regnum - register specification
|
||
* regvalue - new value to set the register
|
||
*
|
||
* Output:
|
||
* None.
|
||
*
|
||
*************************************************************************/
|
||
|
||
void X86SetRegValue (ULONG regnum, ULONG regvalue)
|
||
{
|
||
#if defined(KERNEL) && defined(i386)
|
||
ULONG cBytesRead;
|
||
NTSTATUS NtStatus;
|
||
|
||
if ((regnum == REGEIP && regvalue != VDMRegisterContext.Eip)
|
||
|| (regnum != REGEIP && regnum != REGDR7)) {
|
||
|
||
if (!FullContextPresent[contextState]) {
|
||
if (!DbgGetThreadContext(NtsdCurrentProcessor, &VDMRegisterContext)) {
|
||
dprintf("DbgKdGetContext failed\n");
|
||
exit(1);
|
||
}
|
||
|
||
NtStatus = DbgKdReadControlSpace(NtsdCurrentProcessor,
|
||
(PVOID)sizeof(CONTEXT),
|
||
(PVOID)&SpecialRegContext,
|
||
sizeof(KSPECIAL_REGISTERS),
|
||
&cBytesRead);
|
||
if (!NT_SUCCESS(NtStatus) ||
|
||
cBytesRead != sizeof(KSPECIAL_REGISTERS)) {
|
||
dprintf("DbgKdReadControlSpace failed\n");
|
||
exit(1);
|
||
}
|
||
}
|
||
|
||
contextState = CONTEXTDIRTY;
|
||
}
|
||
#endif
|
||
switch (regnum) {
|
||
case REGGS:
|
||
VDMRegisterContext.SegGs = regvalue;
|
||
break;
|
||
case REGFS:
|
||
VDMRegisterContext.SegFs = regvalue;
|
||
break;
|
||
case REGES:
|
||
VDMRegisterContext.SegEs = regvalue;
|
||
break;
|
||
case REGDS:
|
||
VDMRegisterContext.SegDs = regvalue;
|
||
break;
|
||
case REGEDI:
|
||
VDMRegisterContext.Edi = regvalue;
|
||
break;
|
||
case REGESI:
|
||
VDMRegisterContext.Esi = regvalue;
|
||
break;
|
||
case REGEBX:
|
||
VDMRegisterContext.Ebx = regvalue;
|
||
break;
|
||
case REGEDX:
|
||
VDMRegisterContext.Edx = regvalue;
|
||
break;
|
||
case REGECX:
|
||
VDMRegisterContext.Ecx = regvalue;
|
||
break;
|
||
case REGEAX:
|
||
VDMRegisterContext.Eax = regvalue;
|
||
break;
|
||
case REGEBP:
|
||
VDMRegisterContext.Ebp = regvalue;
|
||
break;
|
||
case REGEIP:
|
||
VDMRegisterContext.Eip = regvalue;
|
||
|
||
break;
|
||
case REGCS:
|
||
VDMRegisterContext.SegCs = regvalue;
|
||
break;
|
||
case REGEFL:
|
||
#if defined(KERNEL) && defined(i386)
|
||
VDMRegisterContext.EFlags = regvalue & ~0x100; // leave TF clear
|
||
#else
|
||
VDMRegisterContext.EFlags = regvalue; // allow TF set
|
||
#endif
|
||
break;
|
||
case REGESP:
|
||
VDMRegisterContext.Esp = regvalue;
|
||
break;
|
||
case REGSS:
|
||
VDMRegisterContext.SegSs = regvalue;
|
||
break;
|
||
#if defined(KERNEL) && defined(i386)
|
||
case REGCR0:
|
||
SpecialRegContext.Cr0 = regvalue;
|
||
break;
|
||
case REGCR2:
|
||
SpecialRegContext.Cr2 = regvalue;
|
||
break;
|
||
case REGCR3:
|
||
SpecialRegContext.Cr3 = regvalue;
|
||
break;
|
||
case REGCR4:
|
||
SpecialRegContext.Cr4 = regvalue;
|
||
break;
|
||
case REGDR0:
|
||
SpecialRegContext.KernelDr0 = regvalue;
|
||
break;
|
||
case REGDR1:
|
||
SpecialRegContext.KernelDr1 = regvalue;
|
||
break;
|
||
case REGDR2:
|
||
SpecialRegContext.KernelDr2 = regvalue;
|
||
break;
|
||
case REGDR3:
|
||
SpecialRegContext.KernelDr3 = regvalue;
|
||
break;
|
||
case REGDR6:
|
||
SpecialRegContext.KernelDr6 = regvalue;
|
||
break;
|
||
case REGDR7:
|
||
SpecialRegContext.KernelDr7 = regvalue;
|
||
break;
|
||
case REGGDTR:
|
||
SpecialRegContext.Gdtr.Base = regvalue;
|
||
break;
|
||
case REGGDTL:
|
||
SpecialRegContext.Gdtr.Limit = (USHORT)regvalue;
|
||
break;
|
||
case REGIDTR:
|
||
SpecialRegContext.Idtr.Base = regvalue;
|
||
break;
|
||
case REGIDTL:
|
||
SpecialRegContext.Idtr.Limit = (USHORT)regvalue;
|
||
break;
|
||
case REGTR:
|
||
SpecialRegContext.Tr = (USHORT)regvalue;
|
||
break;
|
||
case REGLDTR:
|
||
SpecialRegContext.Ldtr = (USHORT)regvalue;
|
||
break;
|
||
#endif
|
||
|
||
#if !defined(KERNEL) && defined(i386)
|
||
case REGDR0:
|
||
VDMRegisterContext.Dr0 = regvalue;
|
||
break;
|
||
case REGDR1:
|
||
VDMRegisterContext.Dr1 = regvalue;
|
||
break;
|
||
case REGDR2:
|
||
VDMRegisterContext.Dr2 = regvalue;
|
||
break;
|
||
case REGDR3:
|
||
VDMRegisterContext.Dr3 = regvalue;
|
||
break;
|
||
case REGDR6:
|
||
VDMRegisterContext.Dr6 = regvalue;
|
||
break;
|
||
case REGDR7:
|
||
VDMRegisterContext.Dr7 = regvalue;
|
||
break;
|
||
#endif
|
||
default:
|
||
dprintf("X86SetRegValue: unknown register %lx requested\n",regnum);
|
||
}
|
||
}
|
||
|
||
/*** X86GetRegName - get register name
|
||
*
|
||
* Purpose:
|
||
* Parse a register name from the current command line position.
|
||
* If successful, return the register index value, else return -1.
|
||
*
|
||
* Input:
|
||
* pchCommand - present command string position
|
||
*
|
||
* Returns:
|
||
* register or flag index if found, else -1
|
||
*
|
||
*************************************************************************/
|
||
|
||
ULONG X86GetRegName (void)
|
||
{
|
||
char szregname[8];
|
||
char ch;
|
||
int count = 0;
|
||
|
||
ch = (char)tolower(*pchCommand); pchCommand++;
|
||
while (ch >= 'a' && ch <= 'z' || ch >= '0' && ch <= '9' || ch == '$') {
|
||
if (count == 7)
|
||
return (ULONG)-1;
|
||
szregname[count++] = ch;
|
||
ch = (char)tolower(*pchCommand); pchCommand++;
|
||
}
|
||
szregname[count] = '\0';
|
||
pchCommand--;
|
||
return X86GetRegString(szregname);
|
||
}
|
||
|
||
ULONG X86GetRegString (PUCHAR pszString)
|
||
{
|
||
ULONG count;
|
||
|
||
for (count = 0; count < REGNAMESIZE; count++)
|
||
if (!strcmp(pszString, regname[count].psz))
|
||
return regname[count].value;
|
||
return (ULONG)-1;
|
||
}
|
||
|
||
void X86GetRegPCValue (PADDR Address)
|
||
{
|
||
|
||
Off(*Address) = X86GetRegValue(REGEIP);
|
||
|
||
#ifdef MULTIMODE
|
||
if (VM86(X86GetRegValue(REGEFL))) {
|
||
Address->type = ADDR_V86;
|
||
Address->seg = (USHORT)X86GetRegValue(REGCS);
|
||
ComputeFlatAddress(Address, NULL);
|
||
}
|
||
else {
|
||
DESCRIPTOR_TABLE_ENTRY desc;
|
||
static USHORT MainCodeSeg = 0;
|
||
ULONG base;
|
||
|
||
Address->seg = (USHORT)(desc.Selector = X86GetRegValue(REGCS));
|
||
#ifdef i386
|
||
DbgKdLookupSelector(NtsdCurrentProcessor, &desc);
|
||
Address->type = desc.Descriptor.HighWord.Bits.Default_Big
|
||
? ADDR_1632 : ADDR_16;
|
||
if ( Address->type == ADDR_1632 ) {
|
||
if ( MainCodeSeg == 0 ) {
|
||
base = ((ULONG)desc.Descriptor.HighWord.Bytes.BaseHi << 24)
|
||
+ ((ULONG)desc.Descriptor.HighWord.Bytes.BaseMid << 16)
|
||
+ ((ULONG)desc.Descriptor.BaseLow);
|
||
if ( base == 0 ) {
|
||
MainCodeSeg = Address->seg;
|
||
}
|
||
}
|
||
if ( Address->seg == MainCodeSeg ) {
|
||
Address->type = ADDR_32;
|
||
}
|
||
}
|
||
#else
|
||
Address->type = ADDR_16;
|
||
#endif
|
||
ComputeFlatAddress(Address, &desc);
|
||
}
|
||
#endif
|
||
return;
|
||
}
|
||
|
||
PADDR X86GetRegFPValue (void)
|
||
{
|
||
static ADDR addrFP;
|
||
|
||
Off(addrFP) = X86GetRegValue(REGEBP);
|
||
|
||
#ifdef MULTIMODE
|
||
if (VM86(X86GetRegValue(REGEFL))) {
|
||
addrFP.type = ADDR_V86;
|
||
addrFP.seg = (USHORT)X86GetRegValue(REGSS);
|
||
ComputeFlatAddress(&addrFP, NULL);
|
||
}
|
||
else {
|
||
DESCRIPTOR_TABLE_ENTRY desc;
|
||
addrFP.seg = (USHORT)(desc.Selector = X86GetRegValue(REGSS));
|
||
#ifdef i386
|
||
DbgKdLookupSelector(NtsdCurrentProcessor, &desc);
|
||
addrFP.type = desc.Descriptor.HighWord.Bits.Default_Big
|
||
? ADDR_32 : ADDR_16;
|
||
#else
|
||
addrFP.type = ADDR_16;
|
||
#endif
|
||
ComputeFlatAddress(&addrFP, &desc);
|
||
}
|
||
#endif
|
||
return &addrFP;
|
||
}
|
||
|
||
void X86SetRegPCValue (PADDR paddr)
|
||
{
|
||
// We set the EIP to the offset (the non-translated value),
|
||
// because we may not be in "flat" mode !!!
|
||
|
||
X86SetRegValue(REGEIP, Off(*paddr));
|
||
}
|
||
|
||
/*** X86OutputAllRegs - output all registers and present instruction
|
||
*
|
||
* Purpose:
|
||
* To output the current register state of the processor.
|
||
* All integer registers are output as well as processor status
|
||
* registers. Important flag fields are also output separately.
|
||
*
|
||
* Input:
|
||
* fTerseReg - (kernel only) - if set, do not output all control
|
||
* register, just the more commonly useful ones.
|
||
*
|
||
* Output:
|
||
* None.
|
||
*
|
||
*************************************************************************/
|
||
|
||
void X86OutputAllRegs(void)
|
||
{
|
||
dprintf("eax=%08lx ebx=%08lx ecx=%08lx edx=%08lx esi=%08lx edi=%08lx\n",
|
||
X86GetRegValue(REGEAX),
|
||
X86GetRegValue(REGEBX),
|
||
X86GetRegValue(REGECX),
|
||
X86GetRegValue(REGEDX),
|
||
X86GetRegValue(REGESI),
|
||
X86GetRegValue(REGEDI));
|
||
|
||
dprintf("eip=%08lx esp=%08lx ebp=%08lx iopl=%1lx "
|
||
"%s %s %s %s %s %s %s %s %s %s\n",
|
||
X86GetRegValue(REGEIP),
|
||
X86GetRegValue(REGESP),
|
||
X86GetRegValue(REGEBP),
|
||
X86GetRegFlagValue(FLAGIOPL),
|
||
X86GetRegFlagValue(FLAGVIP) ? "vip" : " ",
|
||
X86GetRegFlagValue(FLAGVIF) ? "vif" : " ",
|
||
X86GetRegFlagValue(FLAGOF) ? "ov" : "nv",
|
||
X86GetRegFlagValue(FLAGDF) ? "dn" : "up",
|
||
X86GetRegFlagValue(FLAGIF) ? "ei" : "di",
|
||
X86GetRegFlagValue(FLAGSF) ? "ng" : "pl",
|
||
X86GetRegFlagValue(FLAGZF) ? "zr" : "nz",
|
||
X86GetRegFlagValue(FLAGAF) ? "ac" : "na",
|
||
X86GetRegFlagValue(FLAGPF) ? "po" : "pe",
|
||
X86GetRegFlagValue(FLAGCF) ? "cy" : "nc");
|
||
#if defined(KERNEL) && defined(i386)
|
||
if (TerseLevel >= 3)
|
||
return ;
|
||
#endif
|
||
dprintf("cs=%04lx ss=%04lx ds=%04lx es=%04lx fs=%04lx gs=%04lx"
|
||
" efl=%08lx\n",
|
||
X86GetRegValue(REGCS),
|
||
X86GetRegValue(REGSS),
|
||
X86GetRegValue(REGDS),
|
||
X86GetRegValue(REGES),
|
||
X86GetRegValue(REGFS),
|
||
X86GetRegValue(REGGS),
|
||
X86GetRegFlagValue(REGEFL));
|
||
#if defined(KERNEL) && defined(i386)
|
||
if (TerseLevel >= 2)
|
||
return ;
|
||
|
||
dprintf("cr0=%08lx cr2=%08lx cr3=%08lx",
|
||
X86GetRegValue(REGCR0),
|
||
X86GetRegValue(REGCR2),
|
||
X86GetRegValue(REGCR3));
|
||
|
||
if (TerseLevel >= 1) {
|
||
dprintf("\n");
|
||
return ;
|
||
}
|
||
|
||
dprintf(" dr0=%08lx dr1=%08lx dr2=%08lx\n",
|
||
X86GetRegValue(REGDR0),
|
||
X86GetRegValue(REGDR1),
|
||
X86GetRegValue(REGDR2));
|
||
dprintf("dr3=%08lx dr6=%08lx dr7=%08lx cr4=%08lx\n",
|
||
X86GetRegValue(REGDR3),
|
||
X86GetRegValue(REGDR6),
|
||
X86GetRegValue(REGDR7),
|
||
X86GetRegValue(REGCR4));
|
||
dprintf("gdtr=%08lx gdtl=%04lx idtr=%08lx idtl=%04lx "
|
||
"tr=%04lx ldtr=%04x\n",
|
||
X86GetRegValue(REGGDTR),
|
||
X86GetRegValue(REGGDTL),
|
||
X86GetRegValue(REGIDTR),
|
||
X86GetRegValue(REGIDTL),
|
||
X86GetRegValue(REGTR),
|
||
X86GetRegValue(REGLDTR));
|
||
#endif
|
||
}
|
||
|
||
|
||
/*** X86OutputOneReg - output one register value
|
||
*
|
||
* Purpose:
|
||
* Function for the "r <regname>" command.
|
||
*
|
||
* Output the value for the specified register or flag.
|
||
*
|
||
* Input:
|
||
* regnum - register or flag specification
|
||
*
|
||
* Output:
|
||
* None.
|
||
*
|
||
*************************************************************************/
|
||
|
||
VOID
|
||
X86OutputOneReg(
|
||
ULONG regnum
|
||
)
|
||
{
|
||
ULONG value;
|
||
|
||
value = X86GetRegFlagValue(regnum);
|
||
if (regnum < FLAGBASE) {
|
||
dprintf("%08lx\n", value);
|
||
} else{
|
||
dprintf("%lx\n", value);
|
||
}
|
||
}
|
||
|
||
BOOLEAN X86fDelayInstruction (void)
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
/*** X86OutputHelp - output help text
|
||
*
|
||
* Purpose:
|
||
* To output a one-page summary help text.
|
||
*
|
||
* Input:
|
||
* None.
|
||
*
|
||
* Output:
|
||
* None.
|
||
*
|
||
*************************************************************************/
|
||
|
||
void X86OutputHelp (void)
|
||
{
|
||
#if defined(KERNEL) && defined(i386)
|
||
dprintf("A [<address>] - assemble N [<radix>] - set / show radix\n");
|
||
dprintf("BA[#] <e|r|w|i><1|2|4> <addr> - addr bp P[R] [=<addr>] [<value>] - program step\n");
|
||
dprintf("BC[<bp>] - clear breakpoint(s) Q - quit\n");
|
||
dprintf("BD[<bp>] - disable breakpoint(s) R[T] [[<reg> [= <value>]]] - reg/flag\n");
|
||
dprintf("BE[<bp>] - enable breakpoint(s) #R[T] - multiprocessor register dump\n");
|
||
dprintf("BL[<bp>] - list breakpoint(s) S <range> <list> - search\n");
|
||
dprintf("BP[#] <address> - set breakpoint\n");
|
||
dprintf("C <range> <address> - compare SS <n | a | w> - set symbol suffix\n");
|
||
dprintf("D[type][<range>] - dump memory T[R] [=<address>] [<value>] - trace\n");
|
||
dprintf("E[type] <address> [<list>] - enter U [<range>] - unassemble\n");
|
||
dprintf("F <range> <list> - fill V [<range>] - view source lines\n");
|
||
dprintf("G [=<address> [<address>...]] - go X [<*|module>!]<*|symbol> - view symbols\n");
|
||
dprintf("J<expr> [']cmd1['];[']cmd2['] - conditional execution\n");
|
||
dprintf("K[B] <count> - stacktrace .logappend [<file>] - append to log file\n");
|
||
dprintf("LN <expr> - list near .logclose - close log file\n");
|
||
dprintf("M <range> <address> - move .logopen [<file>] - open new log file\n");
|
||
dprintf("O<type> <port> <value> - write I/O \n");
|
||
dprintf("~ - list threads status ~#s - set default thread\n");
|
||
dprintf("~[.|#|*|ddd]f - freeze thread ~[.|#|ddd]k[value] - backtrace stack\n");
|
||
dprintf("| - list processes status |#s - set default process\n");
|
||
dprintf("|#<command> - default process override\n");
|
||
dprintf("? <expr> - display expression\n");
|
||
dprintf("#<string> [address] - search for a string in the dissasembly\n");
|
||
dprintf("$< <filename> - take input from a command file\n");
|
||
dprintf("\n");
|
||
dprintf("<expr> ops: + - * / not by wo dw poi mod(%) and(&) xor(^) or(|) hi low\n");
|
||
dprintf(" operands: number in current radix, public symbol, <reg>\n");
|
||
dprintf("<type> : B (byte), W (word), D (doubleword), A (ascii)\n");
|
||
dprintf(" C <dwordandChar>, U (unicode), L (list)\n");
|
||
dprintf("<pattern> : [(nt | <dll-name>)!]<var-name> (<var-name> can include ? and *)\n");
|
||
dprintf("<radix> : 8, 10, 16\n");
|
||
dprintf("<reg> : [e]ax, [e]bx, [e]cx, [e]dx, [e]si, [e]di, [e]bp, [e]sp, [e]ip, [e]fl,\n");
|
||
dprintf(" al, ah, bl, bh, cl, ch, dl, ch, cs, ds, es, fs, gs, ss\n");
|
||
dprintf(" cr0, cr2, cr3, cr4, dr0, dr1, dr2, dr3, dr6, dr7\n");
|
||
dprintf(" gdtr, gdtl, idtr, idtl, tr, ldtr, $u0-$u9, $ea, $exp, $ra, $p\n");
|
||
dprintf("<flag> : iopl, of, df, if, tf, sf, zf, af, pf, cf\n");
|
||
dprintf("<addr> : %<32-bit address>, #<16-bit protect-mode [seg:]address>,\n");
|
||
dprintf(" &<V86-mode [seg:]address>\n");
|
||
#else
|
||
dprintf("A [<address>] - assemble O<type> <port> <value> - write I/O\n");
|
||
dprintf("BA[#] <e|r|w><1|2|4> <addr> - addr bp P[R] [=<addr>] [<value>] - program step\n");
|
||
dprintf("BC[<bp>] - clear breakpoint(s) Q - quit\n");
|
||
dprintf("BD[<bp>] - disable breakpoint(s) R[T] [[<reg> [= <value>]]] - reg/flag\n");
|
||
dprintf("BE[<bp>] - enable breakpoint(s) #R[T] - multiprocessor register dump\n");
|
||
dprintf("BL[<bp>] - list breakpoint(s) S <range> <list> - search\n");
|
||
dprintf("BP[#] <address> - set breakpoint\n");
|
||
dprintf("C <range> <address> - compare SS <n | a | w> - set symbol suffix\n");
|
||
dprintf("D[type][<range>] - dump memory T[R] [=<address>] [<value>] - trace\n");
|
||
dprintf("E[type] <address> [<list>] - enter U [<range>] - unassemble\n");
|
||
dprintf("F <range> <list> - fill V [<range>] - view source lines\n");
|
||
dprintf("G [=<address> [<address>...]] - go X [<*|module>!]<*|symbol> - view symbols\n");
|
||
dprintf("I<type> <port> - read I/O port .cache [size] - set vmem cache size\n");
|
||
dprintf("J<expr> [']cmd1['];[']cmd2['] - conditional execution\n");
|
||
dprintf("K[B] <count> - stacktrace .logappend [<file>] - append to log file\n");
|
||
dprintf("LN <expr> - list near .logclose - close log file\n");
|
||
dprintf("M <range> <address> - move .logopen [<file>] - open new log file\n");
|
||
dprintf("N [<radix>] - set / show radix .reboot - reboot target machine\n");
|
||
dprintf("? <expr> - display expression \n");
|
||
dprintf("#<string> [address] - search for a string in the dissasembly\n");
|
||
dprintf("$< <filename> - take input from a command file\n");
|
||
dprintf("\n");
|
||
dprintf("<expr> ops: + - * / not by wo dw poi mod(%) and(&) xor(^) or(|) hi low\n");
|
||
dprintf(" operands: number in current radix, public symbol, <reg>\n");
|
||
dprintf("<type> : B (byte), W (word), D (doubleword), A (ascii)\n");
|
||
dprintf(" U (unicode), L (list), O (object)\n");
|
||
dprintf("<pattern> : [(nt | <dll-name>)!]<var-name> (<var-name> can include ? and *)\n");
|
||
dprintf("<radix> : 8, 10, 16\n");
|
||
dprintf("<reg> : [e]ax, [e]bx, [e]cx, [e]dx, [e]si, [e]di, [e]bp, [e]sp, [e]ip, [e]fl,\n");
|
||
dprintf(" al, ah, bl, bh, cl, ch, dl, ch, cs, ds, es, fs, gs, ss\n");
|
||
dprintf(" cr0, cr2, cr3, cr4, dr0, dr1, dr2, dr3, dr6, dr7\n");
|
||
dprintf(" gdtr, gdtl, idtr, idtl, tr, ldtr, $u0-$u9, $ea, $exp, $ra, $p\n");
|
||
dprintf("<flag> : iopl, of, df, if, tf, sf, zf, af, pf, cf\n");
|
||
dprintf("<addr> : %<32-bit address>, #<16-bit protect-mode [seg:]address>,\n");
|
||
dprintf(" &<V86-mode [seg:]address>\n");
|
||
#endif
|
||
}
|
||
|
||
#if defined(KERNEL) && defined(i386)
|
||
BOOLEAN X86GetTraceFlag (void)
|
||
{
|
||
return fTraceFlag;
|
||
}
|
||
#endif
|
||
|
||
void X86ClearTraceFlag (void)
|
||
{
|
||
#if defined(KERNEL) && defined(i386)
|
||
fTraceFlag = FALSE;
|
||
#else
|
||
X86SetRegFlagValue(FLAGTF, 0);
|
||
#endif
|
||
}
|
||
|
||
void X86SetTraceFlag (void)
|
||
{
|
||
#if defined(KERNEL) && defined(i386)
|
||
fTraceFlag = TRUE;
|
||
#else
|
||
X86SetRegFlagValue(FLAGTF, 1);
|
||
#endif
|
||
}
|
||
|
||
#if defined(KERNEL) && defined(i386)
|
||
/*** GetRegContext - return register context pointer
|
||
*
|
||
* Purpose:
|
||
* Return the pointer to the current register context.
|
||
* For kernel debugging, ensure the context is read.
|
||
*
|
||
* Input:
|
||
* None.
|
||
*
|
||
* Returns:
|
||
* Pointer to the context.
|
||
*
|
||
*************************************************************************/
|
||
|
||
PCONTEXT GetRegContext (void)
|
||
{
|
||
|
||
if (contextState == CONTEXTFIR) {
|
||
if (!DbgGetThreadContext(NtsdCurrentProcessor, &RegisterContext)) {
|
||
dprintf("DbgKdGetContext failed\n");
|
||
exit(1);
|
||
}
|
||
contextState = CONTEXTVALID;
|
||
}
|
||
return &RegisterContext;
|
||
}
|
||
|
||
void ChangeKdRegContext(ULONG pcValue, PDBGKD_CONTROL_REPORT pCtlReport)
|
||
{
|
||
ULONG cBytesWritten;
|
||
ULONG cBytesRead;
|
||
USHORT Processor;
|
||
NTSTATUS NtStatus;
|
||
|
||
if (pcValue) { // initial context
|
||
contextState = CONTEXTFIR;
|
||
VDMRegisterContext.Eip = pcValue;
|
||
SpecialRegContext.KernelDr6 = pCtlReport->Dr6;
|
||
SpecialRegContext.KernelDr7 = pCtlReport->Dr7;
|
||
|
||
if (pCtlReport->ReportFlags & REPORT_INCLUDES_SEGS) {
|
||
//
|
||
// This is for backwards compatibility - older kernels
|
||
// won't pass these registers in the report record.
|
||
//
|
||
|
||
contextState = CONTEXTSHORT;
|
||
VDMRegisterContext.SegCs = pCtlReport->SegCs;
|
||
VDMRegisterContext.SegDs = pCtlReport->SegDs;
|
||
VDMRegisterContext.SegEs = pCtlReport->SegEs;
|
||
VDMRegisterContext.SegFs = pCtlReport->SegFs;
|
||
VDMRegisterContext.EFlags = pCtlReport->EFlags;
|
||
}
|
||
|
||
} else if (contextState == CONTEXTDIRTY) { // write final context
|
||
if (!DbgSetThreadContext(NtsdCurrentProcessor, &VDMRegisterContext)) {
|
||
dprintf("DbgKdSetContext failed\n");
|
||
exit(1);
|
||
}
|
||
|
||
NtStatus = DbgKdWriteControlSpace(NtsdCurrentProcessor,
|
||
(PVOID)sizeof(CONTEXT),
|
||
(PVOID)&SpecialRegContext,
|
||
sizeof(KSPECIAL_REGISTERS),
|
||
&cBytesWritten);
|
||
if (!NT_SUCCESS(NtStatus) ||
|
||
cBytesWritten != sizeof(KSPECIAL_REGISTERS)) {
|
||
dprintf("DbgKdWriteControlSpace failed\n");
|
||
exit(1);
|
||
}
|
||
|
||
if (fSetGlobalDataBrkpts && NumberProcessors > 1) {
|
||
for ( Processor = 0; Processor < NumberProcessors; Processor++) {
|
||
if (Processor != NtsdCurrentProcessor) {
|
||
NtStatus = DbgKdReadControlSpace((USHORT)Processor,
|
||
(PVOID)sizeof(CONTEXT),
|
||
(PVOID)&SavedSpecialRegContext,
|
||
sizeof(KSPECIAL_REGISTERS),
|
||
&cBytesRead);
|
||
if (!NT_SUCCESS(NtStatus) ||
|
||
cBytesRead != sizeof(KSPECIAL_REGISTERS)) {
|
||
dprintf("DbgKdReadControlSpace failed\n");
|
||
exit(1);
|
||
}
|
||
|
||
memcpy(&SavedSpecialRegContext.KernelDr0,
|
||
&SpecialRegContext.KernelDr0, 6 * sizeof(ULONG));
|
||
|
||
NtStatus = DbgKdWriteControlSpace((USHORT)Processor,
|
||
(PVOID)sizeof(CONTEXT),
|
||
(PVOID)&SavedSpecialRegContext,
|
||
sizeof(KSPECIAL_REGISTERS),
|
||
&cBytesWritten);
|
||
if (!NT_SUCCESS(NtStatus) ||
|
||
cBytesWritten != sizeof(KSPECIAL_REGISTERS)) {
|
||
dprintf("DbgKdWriteControlSpace failed\n");
|
||
exit(1);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
}
|
||
#endif
|
||
|
||
#if defined(KERNEL) && defined(i386)
|
||
void InitFirCache (ULONG count, PUCHAR pstream)
|
||
{
|
||
//
|
||
// If we are in anything but 32-bit flat mode, then don't init cache
|
||
//
|
||
|
||
if (!fVm86 && !f16pm) {
|
||
DbgKdInitVirtualCacheEntry (X86GetRegValue(REGEIP), count, pstream);
|
||
}
|
||
}
|
||
#endif
|
||
|
||
ULONG
|
||
GetDregValue (
|
||
ULONG index
|
||
)
|
||
{
|
||
if (index < 4) {
|
||
index += REGDR0;
|
||
} else {
|
||
index += REGDR6 - 6;
|
||
}
|
||
return X86GetRegValue(index);
|
||
}
|
||
|
||
VOID
|
||
SetDregValue (
|
||
ULONG index,
|
||
ULONG value
|
||
)
|
||
{
|
||
if (index < 4) {
|
||
index += REGDR0;
|
||
} else {
|
||
index += REGDR6 - 6;
|
||
}
|
||
X86SetRegValue(index, value);
|
||
}
|
||
|
||
#if defined(KERNEL) && defined(i386)
|
||
void SaveProcessorState(void)
|
||
{
|
||
PreviousProcessor = NtsdCurrentProcessor;
|
||
SavedRegisterContext = VDMRegisterContext;
|
||
SavedSpecialRegContext = SpecialRegContext;
|
||
SavedContextState = contextState;
|
||
contextState = CONTEXTNONE;
|
||
}
|
||
|
||
void RestoreProcessorState(void)
|
||
{
|
||
NtsdCurrentProcessor = PreviousProcessor;
|
||
VDMRegisterContext = SavedRegisterContext;
|
||
SpecialRegContext = SavedSpecialRegContext;
|
||
contextState = SavedContextState;
|
||
}
|
||
#endif
|
||
|
||
|
||
#ifdef i386
|
||
ULONGLONG STGetRegValue (ULONG regnum)
|
||
{
|
||
if (!STtrace) {
|
||
return X86GetRegValue(regnum);
|
||
}
|
||
|
||
switch (regnum) {
|
||
case REGEBP: return STebp;
|
||
case REGESP: return STesp;
|
||
default:
|
||
DPRINT(("%s: bad regnum\n",DebuggerName));
|
||
break;
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
#endif
|
||
|
||
PUCHAR X86RegNameFromIndex (ULONG index)
|
||
{
|
||
ULONG count;
|
||
|
||
for (count = 0; count < REGNAMESIZE; count++)
|
||
if (regname[count].value == index)
|
||
return regname[count].psz;
|
||
return NULL;
|
||
}
|
||
|
||
#if defined(i386)
|
||
BOOL
|
||
DbgGetThreadContext(
|
||
THREADORPROCESSOR TorP,
|
||
PCONTEXT Context
|
||
)
|
||
{
|
||
#ifdef KERNEL
|
||
return NT_SUCCESS(DbgKdGetContext(TorP, Context));
|
||
#else // KERNEL
|
||
return GetThreadContext(TorP, Context);
|
||
#endif // KERNEL
|
||
}
|
||
|
||
|
||
BOOL
|
||
DbgSetThreadContext(
|
||
THREADORPROCESSOR TorP,
|
||
PCONTEXT Context
|
||
)
|
||
{
|
||
#ifdef KERNEL
|
||
return NT_SUCCESS(DbgKdSetContext(TorP, Context));
|
||
#else // KERNEL
|
||
return SetThreadContext(TorP, Context);
|
||
#endif // KERNEL
|
||
}
|
||
#endif // i386
|