265 lines
7.9 KiB
C
265 lines
7.9 KiB
C
|
/*++
|
||
|
|
||
|
Copyright (c) 1992-1998 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
threadst.h
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
This module defines the structures and constant for describing a
|
||
|
thread's state.
|
||
|
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Dave Hastings (daveh) creation-date 20-May-1995
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#ifndef _THREADST_H_
|
||
|
#define _THREADST_H_
|
||
|
|
||
|
#define EIPLOGSIZE 32 // keep track of the last N instructions run
|
||
|
|
||
|
#define CSSIZE 512 // Size of call stack (512*8 = 2048 bytes = 1 page)
|
||
|
|
||
|
typedef union _REG32 { // definition of a 32-bit x86 register
|
||
|
struct {
|
||
|
BYTE i1;
|
||
|
BYTE hb;
|
||
|
};
|
||
|
USHORT i2;
|
||
|
ULONG i4;
|
||
|
} REG32;
|
||
|
|
||
|
#if defined(_ALPHA_)
|
||
|
typedef DWORD FPTAG; // bytes are too slow on AXP
|
||
|
#else
|
||
|
typedef BYTE FPTAG;
|
||
|
#endif
|
||
|
|
||
|
typedef struct _FPREG { // definition of an x86 floating-point register
|
||
|
union {
|
||
|
double r64;
|
||
|
DWORD rdw[2];
|
||
|
BYTE rb[8];
|
||
|
};
|
||
|
FPTAG Tag;
|
||
|
FPTAG TagSpecial;
|
||
|
} FPREG, *PFPREG;
|
||
|
|
||
|
//
|
||
|
// CALLSTACK is an optimization for CALL/RET pairs, so that an expensive
|
||
|
// NativeAddressFromEip() call can be avoided when determining the RISC
|
||
|
// address of an x86 return address.
|
||
|
//
|
||
|
typedef struct _callStack {
|
||
|
ULONG intelAddr;
|
||
|
ULONG nativeAddr;
|
||
|
} CALLSTACK, *PCALLSTACK;
|
||
|
|
||
|
// Indices into CPUSTATE.Regs[]. get_reg32() depends on EAX through
|
||
|
// EDI being contiguous and ordered the same as they are in the mod/rm and
|
||
|
// reg instruction encodings (ie. EAX=0,ECX=1,EDX=2,EBX=3,ESP=4,EBP=5,ESI=6,
|
||
|
// EDI=7)
|
||
|
#define GP_EAX 0x00
|
||
|
#define GP_ECX 0x01
|
||
|
#define GP_EDX 0x02
|
||
|
#define GP_EBX 0x03
|
||
|
#define GP_ESP 0x04
|
||
|
#define GP_EBP 0x05
|
||
|
#define GP_ESI 0x06
|
||
|
#define GP_EDI 0x07
|
||
|
|
||
|
// Segment registers. get_segreg() depends on the order.
|
||
|
#define REG_ES 0x08
|
||
|
#define REG_CS 0x09
|
||
|
#define REG_SS 0x0a
|
||
|
#define REG_DS 0x0b
|
||
|
#define REG_FS 0x0c
|
||
|
#define REG_GS 0x0d
|
||
|
|
||
|
|
||
|
// Identifiers for components of registers. get_reg16() depends on the order.
|
||
|
#define GP_AX 0x0e
|
||
|
#define GP_CX 0x0f
|
||
|
#define GP_DX 0x10
|
||
|
#define GP_BX 0x11
|
||
|
#define GP_SP 0x12
|
||
|
#define GP_BP 0x13
|
||
|
#define GP_SI 0x14
|
||
|
#define GP_DI 0x15
|
||
|
|
||
|
// PlaceOperandFragments() depends on GP_AH and beyond, and that no registers
|
||
|
// are past GP_BH.
|
||
|
#define GP_AL 0x16
|
||
|
#define GP_CL 0x17
|
||
|
#define GP_DL 0x18
|
||
|
#define GP_BL 0x19
|
||
|
#define GP_AH 0x1a
|
||
|
#define GP_CH 0x1b
|
||
|
#define GP_DH 0x1c
|
||
|
#define GP_BH 0x1d
|
||
|
|
||
|
#define NO_REG 0xffffffff
|
||
|
|
||
|
typedef struct _CPU_SUSPEND_MSG
|
||
|
{
|
||
|
// Owned by local thread
|
||
|
HANDLE StartSuspendCallEvent;
|
||
|
HANDLE EndSuspendCallEvent;
|
||
|
|
||
|
} CPU_SUSPEND_MSG, *PCPU_SUSPEND_MSG;
|
||
|
|
||
|
// all information related to a particular thread of the CPU belongs here
|
||
|
typedef struct _ThreadState {
|
||
|
|
||
|
//
|
||
|
// General-purpose and segment registers
|
||
|
// accessible as an array of REG32 or by Register Name
|
||
|
// NOTE: the name orders must match the GP_XXX defines for registers
|
||
|
//
|
||
|
union {
|
||
|
REG32 GpRegs[14];
|
||
|
struct _RegisterByName {
|
||
|
REG32 Eax;
|
||
|
REG32 Ecx;
|
||
|
REG32 Edx;
|
||
|
REG32 Ebx;
|
||
|
REG32 Esp;
|
||
|
REG32 Ebp;
|
||
|
REG32 Esi;
|
||
|
REG32 Edi;
|
||
|
REG32 Es;
|
||
|
REG32 Cs;
|
||
|
REG32 Ss;
|
||
|
REG32 Ds;
|
||
|
REG32 Fs;
|
||
|
REG32 Gs;
|
||
|
};
|
||
|
};
|
||
|
|
||
|
REG32 eipReg; // Pointer to start of current instruction (never
|
||
|
// points into the middle of an instruction)
|
||
|
|
||
|
DWORD flag_cf; // 0 = carry
|
||
|
DWORD flag_pf; // 2 = parity
|
||
|
DWORD flag_aux; // 4 = aux carry
|
||
|
DWORD flag_zf; // 6 = zero
|
||
|
DWORD flag_sf; // 7 = sign
|
||
|
DWORD flag_tf; // 8 = trap
|
||
|
DWORD flag_if; // 9 = interrupt enable
|
||
|
DWORD flag_df; // 10 = direction (1 = clear, -1 = set)
|
||
|
DWORD flag_of; // 11 = overflow
|
||
|
DWORD flag_nt; // 14 = nested task
|
||
|
DWORD flag_rf; // 16 = resume flag
|
||
|
DWORD flag_vm; // 17 = virtual mode
|
||
|
DWORD flag_ac; // 18 = alignment check
|
||
|
|
||
|
// Floating-point registers
|
||
|
FPREG FpStack[8];
|
||
|
PFPREG FpST0;
|
||
|
INT FpTop;
|
||
|
INT FpStatusC3;
|
||
|
INT FpStatusC2;
|
||
|
INT FpStatusC1;
|
||
|
INT FpStatusC0;
|
||
|
INT FpStatusSF;
|
||
|
INT FpStatusES; // Error Summary Status
|
||
|
INT FpControlInfinity;
|
||
|
INT FpControlRounding;
|
||
|
INT FpControlPrecision;
|
||
|
DWORD FpStatusExceptions;
|
||
|
DWORD FpControlMask;
|
||
|
DWORD FpEip; // EIP for the current FP instruction
|
||
|
PVOID FpData; // Effective address for current FP instruction
|
||
|
PVOID FpAddTable; // ptr to table of function pointers for FADD
|
||
|
PVOID FpSubTable; // ptr to table of function pointers for FSUB
|
||
|
PVOID FpMulTable; // ptr to table of function pointers for FMUL
|
||
|
PVOID FpDivTable; // ptr to table of function pointers for FDIV
|
||
|
|
||
|
ULONG CpuNotify;
|
||
|
|
||
|
PVOID TraceAddress; // Used by debugger extensions
|
||
|
|
||
|
DWORD fTCUnlocked; // FALSE means TC must be unlocked after exception
|
||
|
|
||
|
// SuspendThread/ResumeThread support
|
||
|
PCPU_SUSPEND_MSG SuspendMsg;
|
||
|
|
||
|
int eipLogIndex; // Index of next entry to write into in the log
|
||
|
DWORD eipLog[EIPLOGSIZE]; // log of last EIPLOGSIZE instructions run
|
||
|
|
||
|
ULONG CSIndex; // Index into the stack (offset of current location)
|
||
|
DWORD CSTimestamp;// Value of TranslationCacheTimestamp corresponding to the callstack cache
|
||
|
CALLSTACK callStack[CSSIZE]; // callstack optimization
|
||
|
|
||
|
int ErrnoVal; // CRT errno value
|
||
|
|
||
|
DWORD flag_id; // 21 = ID (CPUID present if this can be toggled)
|
||
|
|
||
|
} THREADSTATE, *PTHREADSTATE, CPUCONTEXT, *PCPUCONTEXT;
|
||
|
|
||
|
// Bit offsets in cpu->FpControlMask. Same as the x86 bit positions
|
||
|
#define FPCONTROL_IM 1 // Invalid operation
|
||
|
#define FPCONTROL_DM 2 // Denormalized operation
|
||
|
#define FPCONTROL_ZM 4 // Zero divide
|
||
|
#define FPCONTROL_OM 8 // Overflow
|
||
|
#define FPCONTROL_UM 16 // Underflow
|
||
|
#define FPCONTROL_PM 32 // Precision
|
||
|
|
||
|
// This macro allows one to access the cpu state via the local variable cpu
|
||
|
#define DECLARE_CPU \
|
||
|
PCPUCONTEXT cpu=(PCPUCONTEXT)Wow64TlsGetValue(WOW64_TLS_CPURESERVED);
|
||
|
|
||
|
//
|
||
|
// The following macros allow one to push and pop values from the
|
||
|
// call stack
|
||
|
//
|
||
|
|
||
|
#define ISTOPOF_CALLSTACK(iAddr) \
|
||
|
(cpu->callStack[(cpu->CSIndex)].intelAddr == iAddr)
|
||
|
|
||
|
#define PUSH_CALLSTACK(iAddr,nAddr) \
|
||
|
{ \
|
||
|
PCALLSTACK pCallStack; \
|
||
|
\
|
||
|
cpu->CSIndex = (cpu->CSIndex+1) % CSSIZE; \
|
||
|
pCallStack = &cpu->callStack[cpu->CSIndex]; \
|
||
|
pCallStack->intelAddr = iAddr; \
|
||
|
pCallStack->nativeAddr = nAddr; \
|
||
|
}
|
||
|
|
||
|
#define POP_CALLSTACK(iAddr,nAddr) \
|
||
|
{ \
|
||
|
PCALLSTACK pCallStack; \
|
||
|
extern ULONG TranslationCacheTimestamp; \
|
||
|
\
|
||
|
CPUASSERTMSG( \
|
||
|
(cpu->CSTimestamp == TranslationCacheTimestamp), \
|
||
|
"POP_CALLSTACK: About to return and invalid value\n"\
|
||
|
); \
|
||
|
\
|
||
|
pCallStack = &cpu->callStack[cpu->CSIndex]; \
|
||
|
if (iAddr == pCallStack->intelAddr) { \
|
||
|
nAddr = pCallStack->nativeAddr; \
|
||
|
} else { \
|
||
|
nAddr = 0; \
|
||
|
} \
|
||
|
cpu->CSIndex = (cpu->CSIndex-1) % CSSIZE; \
|
||
|
}
|
||
|
|
||
|
PCPUCONTEXT GetCpuContext (); //has been implemented in wowproxy
|
||
|
|
||
|
NTSTATUS
|
||
|
CpupSuspendCurrentThread(
|
||
|
VOID);
|
||
|
|
||
|
|
||
|
#endif //_THREADST_H_
|