mirror of https://github.com/lianthony/NT4.0
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.
1802 lines
39 KiB
1802 lines
39 KiB
/**** EMDPDEV.C - Debugger end Execution Model (x86 dependent code) **
|
|
* *
|
|
* *
|
|
* Copyright <C> 1990, Microsoft Corp *
|
|
* *
|
|
* Created: October 15, 1990 by David W. Gray *
|
|
* *
|
|
* Revision History: *
|
|
* *
|
|
* Purpose: *
|
|
* *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
#include "strings.h"
|
|
|
|
|
|
DWORD ConvertOmapToSrc(LPMDI lpmdi, DWORD addr);
|
|
|
|
|
|
typedef struct _L_DOUBLE {
|
|
BYTE b[10];
|
|
} L_DOUBLE, FAR *LPL_DOUBLE;
|
|
|
|
|
|
#ifndef SMARTALIAS
|
|
void PurgeCache ( void );
|
|
#endif
|
|
|
|
#define CEXM_MDL_native 0x20
|
|
|
|
|
|
/*
|
|
** This is the description of all registers and flags contained on the
|
|
** x86 machine
|
|
*/
|
|
|
|
extern RD Rgrd[];
|
|
|
|
extern struct {
|
|
FD fd;
|
|
USHORT iShift;
|
|
} Rgfd[];
|
|
|
|
#ifdef TARGET32
|
|
#define SIZEOF_STACK_OFFSET sizeof(LONG)
|
|
#else // TARGET32
|
|
#define SIZEOF_STACK_OFFSET sizeof(WORD)
|
|
#endif // TARGET32
|
|
|
|
#ifndef OSDEBUG4
|
|
|
|
#pragma pack ( 1 )
|
|
|
|
typedef union _PLG {
|
|
|
|
struct std {
|
|
unsigned char PushBP;
|
|
unsigned short MovBPSP;
|
|
} std;
|
|
|
|
struct enter {
|
|
unsigned char C8;
|
|
unsigned short cbStack;
|
|
unsigned char cNesting;
|
|
} enter;
|
|
|
|
} PLG;
|
|
#pragma pack()
|
|
|
|
#define ENTERINS 0xC8
|
|
#define PUSHBP 0x55
|
|
#define PUSHSI 0x56
|
|
#define PUSHDI 0x57
|
|
#define MOVBPSP 0xEC8B
|
|
|
|
BOOL NEAR PASCAL IsStackSetup(
|
|
HPID hpid,
|
|
HTID htid,
|
|
LPADDR lpaddrProc
|
|
) {
|
|
BOOL rval = TRUE;
|
|
PLG plg;
|
|
UOFFSET cbInProlog;
|
|
LPTHD lpthd;
|
|
HPRC hprc = ValidHprcFromHpid(hpid);
|
|
HTHD hthd;
|
|
if (!hprc) {
|
|
return FALSE;
|
|
}
|
|
hthd = HthdFromHtid(hprc, htid);
|
|
if (!hthd) {
|
|
return FALSE;
|
|
}
|
|
lpthd = LLLock ( hthd );
|
|
|
|
lpthd->addrCurrent = *lpaddrProc;
|
|
|
|
if (ReadBuffer(hpid, htid, 0, sizeof ( PLG ), (char FAR *) &plg, NULL)) {
|
|
|
|
/* Stack is set up but is it Parents Stack?
|
|
*/
|
|
|
|
if( plg.enter.C8 == ENTERINS || plg.std.MovBPSP == MOVBPSP ) {
|
|
cbInProlog = (UOFFSET) lpthd->regs.Eip - offAddr ( *lpaddrProc );
|
|
|
|
/* Are we beyond the push bp, mov bp, sp combo or an enter?
|
|
*/
|
|
rval = cbInProlog >= 3;
|
|
}
|
|
}
|
|
|
|
LLUnlock( hthd );
|
|
return( rval );
|
|
}
|
|
#endif // OSDEBUG4
|
|
|
|
|
|
XOSD
|
|
GetAddr (
|
|
HPID hpid,
|
|
HTID htid,
|
|
ADR adr,
|
|
LPADDR lpaddr
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function will get return a specific type of address.
|
|
|
|
Arguments:
|
|
|
|
hpid - Supplies the handle to the process to retrive the address from
|
|
htid - Supplies the handle to the thread to retrieve the address from
|
|
adr - Supplies the type of address to be retrieved
|
|
lpaddr - Returns the requested address
|
|
|
|
Return Value:
|
|
|
|
XOSD error code
|
|
|
|
--*/
|
|
|
|
{
|
|
HPRC hprc;
|
|
HTHD hthd;
|
|
LPTHD lpthd = NULL;
|
|
XOSD xosd = xosdNone;
|
|
HEMI hemi = emiAddr(*lpaddr);
|
|
HMDI hmdi;
|
|
LPMDI lpmdi;
|
|
|
|
assert ( lpaddr != NULL );
|
|
assert ( hpid != hpidNull );
|
|
|
|
hprc = ValidHprcFromHpid(hpid);
|
|
if (!hprc) {
|
|
return xosdInvalidProc;
|
|
}
|
|
|
|
hthd = HthdFromHtid(hprc, htid);
|
|
|
|
if ( hthd != hthdNull ) {
|
|
lpthd = LLLock ( hthd );
|
|
}
|
|
|
|
_fmemset ( lpaddr, 0, sizeof ( ADDR ) );
|
|
|
|
switch ( adr ) {
|
|
case adrPC:
|
|
if ( lpthd && !(lpthd->drt & drtCntrlPresent) ) {
|
|
UpdateRegisters ( hprc, hthd );
|
|
}
|
|
break;
|
|
|
|
case adrBase:
|
|
case adrStack:
|
|
case adrData:
|
|
if ( lpthd && !(lpthd->drt & drtAllPresent )) {
|
|
UpdateRegisters ( hprc, hthd );
|
|
}
|
|
break;
|
|
}
|
|
|
|
switch ( adr ) {
|
|
#ifndef OSDEBUG4
|
|
case adrCurrent:
|
|
// If a non-NULL HTHD was passed in, use addrCurrent from that
|
|
// thread. Otherwise use addrCurrent from the HPRC.
|
|
|
|
if ( lpthd ) {
|
|
*lpaddr = lpthd->addrCurrent;
|
|
} else {
|
|
LPPRC lpprc = LLLock ( hprc );
|
|
|
|
*lpaddr = lpprc->addrCurrent;
|
|
|
|
LLUnlock ( hprc );
|
|
}
|
|
break;
|
|
#endif
|
|
|
|
case adrPC:
|
|
AddrInit(lpaddr, 0, (SEGMENT) lpthd->regs.SegCs,
|
|
(UOFFSET) lpthd->regs.Eip, lpthd->fFlat,
|
|
lpthd->fOff32, FALSE, lpthd->fReal)
|
|
SetEmi ( hpid, lpaddr );
|
|
break;
|
|
|
|
case adrBase:
|
|
AddrInit(lpaddr, 0, (SEGMENT) 0,
|
|
(UOFFSET) lpthd->regs.Ebp, lpthd->fFlat,
|
|
lpthd->fOff32, FALSE, lpthd->fReal)
|
|
SetEmi ( hpid, lpaddr );
|
|
break;
|
|
|
|
case adrStack:
|
|
AddrInit(lpaddr, 0, (SEGMENT) lpthd->regs.SegSs,
|
|
(UOFFSET) lpthd->regs.Esp, lpthd->fFlat,
|
|
lpthd->fOff32, FALSE, lpthd->fReal)
|
|
SetEmi ( hpid, lpaddr );
|
|
break;
|
|
|
|
case adrData:
|
|
AddrInit(lpaddr, 0, (SEGMENT) lpthd->regs.SegDs, 0,
|
|
lpthd->fFlat, lpthd->fOff32, FALSE, lpthd->fReal);
|
|
SetEmi ( hpid, lpaddr );
|
|
break;
|
|
|
|
case adrTlsBase:
|
|
/*
|
|
* If -1 then we have not gotten a value from the DM yet.
|
|
*/
|
|
|
|
assert(hemi != 0);
|
|
|
|
if (hemi == 0) {
|
|
return xosdBadAddress;
|
|
}
|
|
|
|
if (hemi != emiAddr(lpthd->addrTls)) {
|
|
hmdi = LLFind( LlmdiFromHprc( hprc ), wNull, (LPB) &hemi, emdiEMI);
|
|
assert(hmdi != 0);
|
|
|
|
if (hmdi == 0) {
|
|
return xosdBadAddress;
|
|
}
|
|
|
|
lpmdi = LLLock( hmdi );
|
|
|
|
SendRequestX( dmfQueryTlsBase, hpid, htid, sizeof(OFFSET),
|
|
&lpmdi->lpBaseOfDll);
|
|
|
|
lpthd->addrTls = *((LPADDR) LpDmMsg->rgb);
|
|
emiAddr(lpthd->addrTls) = hemi;
|
|
LLUnlock( hmdi );
|
|
|
|
}
|
|
|
|
*lpaddr = lpthd->addrTls;
|
|
emiAddr(*lpaddr) = 0;
|
|
break;
|
|
|
|
default:
|
|
assert ( FALSE );
|
|
break;
|
|
}
|
|
|
|
if ( hthd != hthdNull ) {
|
|
LLUnlock ( hthd );
|
|
}
|
|
|
|
return xosd;
|
|
} /* GetAddr() */
|
|
|
|
|
|
XOSD
|
|
SetAddr (
|
|
HPID hpid,
|
|
HTID htid,
|
|
ADR adr,
|
|
LPADDR lpaddr
|
|
)
|
|
{
|
|
HPRC hprc;
|
|
HTHD hthd;
|
|
LPTHD lpthd = NULL;
|
|
|
|
assert ( lpaddr != NULL );
|
|
assert ( hpid != hpidNull );
|
|
|
|
hprc = ValidHprcFromHpid(hpid);
|
|
if (!hprc) {
|
|
return xosdInvalidProc;
|
|
}
|
|
|
|
hthd = HthdFromHtid(hprc, htid);
|
|
|
|
|
|
if ( hthd != hthdNull ) {
|
|
lpthd = LLLock ( hthd );
|
|
}
|
|
|
|
switch ( adr ) {
|
|
case adrPC:
|
|
if ( !( lpthd->drt & drtCntrlPresent) ) {
|
|
UpdateRegisters ( hprc, hthd );
|
|
}
|
|
break;
|
|
|
|
|
|
case adrBase:
|
|
case adrStack:
|
|
case adrData:
|
|
if ( !(lpthd->drt & drtAllPresent) ) {
|
|
UpdateRegisters ( hprc, hthd );
|
|
}
|
|
break;
|
|
|
|
}
|
|
switch ( adr ) {
|
|
#ifndef OSDEBUG4
|
|
case adrCurrent:
|
|
if ( lpaddr->emi == hmemNull ) {
|
|
SetEmi ( hpid, lpaddr );
|
|
}
|
|
|
|
// If a non-NULL HTHD was passed in, use addrCurrent from that
|
|
// thread. Otherwise use addrCurrent from the HPRC.
|
|
|
|
if ( lpthd ) {
|
|
lpthd->addrCurrent = *lpaddr;
|
|
}
|
|
else {
|
|
LPPRC lpprc = LLLock ( hprc );
|
|
|
|
lpprc->addrCurrent = *lpaddr;
|
|
|
|
LLUnlock ( hprc );
|
|
}
|
|
break;
|
|
#endif
|
|
|
|
case adrPC:
|
|
lpthd->regs.SegCs = segAddr ( *lpaddr );
|
|
lpthd->regs.Eip = offAddr ( *lpaddr );
|
|
lpthd->drt |= drtCntrlDirty;
|
|
break;
|
|
|
|
case adrBase:
|
|
lpthd->regs.Ebp = offAddr ( *lpaddr );
|
|
lpthd->drt |= drtAllDirty;
|
|
break;
|
|
|
|
case adrStack:
|
|
lpthd->regs.SegSs = segAddr ( *lpaddr );
|
|
lpthd->regs.Esp = offAddr ( *lpaddr );
|
|
lpthd->drt |= drtAllDirty;
|
|
break;
|
|
|
|
case adrData:
|
|
case adrTlsBase:
|
|
default:
|
|
assert ( FALSE );
|
|
break;
|
|
}
|
|
|
|
if ( hthd != hthdNull ) {
|
|
LLUnlock ( hthd );
|
|
}
|
|
|
|
return xosdNone;
|
|
} /* SetAddr() */
|
|
|
|
|
|
XOSD
|
|
SetAddrFromCSIP (
|
|
HTHD hthd
|
|
)
|
|
{
|
|
|
|
ADDR addr = {0};
|
|
LPTHD lpthd;
|
|
|
|
assert ( hthd != hthdNull && hthd != hthdInvalid );
|
|
|
|
lpthd = LLLock ( hthd );
|
|
|
|
segAddr ( addr ) = (SEGMENT) lpthd->regs.SegCs;
|
|
offAddr ( addr ) = (UOFFSET) lpthd->regs.Eip;
|
|
emiAddr ( addr ) = 0;
|
|
SETADDRMODE ( addr );
|
|
|
|
lpthd->addrCurrent = addr;
|
|
|
|
LLUnlock ( hthd );
|
|
|
|
return xosdNone;
|
|
}
|
|
|
|
|
|
CMP
|
|
CmpAddr (
|
|
LPADDR lpaddr1,
|
|
LPADDR lpaddr2
|
|
)
|
|
{
|
|
// NOTENOTE -- segmented addresses
|
|
if ( offAddr ( *lpaddr1 ) < offAddr ( *lpaddr2 ) )
|
|
return ( fCmpLT );
|
|
else if ( offAddr ( *lpaddr1 ) > offAddr ( *lpaddr2 ) )
|
|
return ( fCmpGT );
|
|
else
|
|
return ( fCmpEQ );
|
|
}
|
|
|
|
|
|
LPV
|
|
DoGetReg(
|
|
LPCONTEXT lpregs,
|
|
DWORD ireg,
|
|
LPV lpvRegValue
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is used to extract the value of a single register from
|
|
the debuggee.
|
|
|
|
Arguments:
|
|
|
|
lpregs - Supplies pointer to the register set for the debuggee
|
|
|
|
ireg - Supplies the index of the register to be read
|
|
|
|
lpvRegValue - Supplies the buffer to place the register value in
|
|
|
|
Return Value:
|
|
|
|
return-value - lpvRegValue + size of register on sucess and NULL on
|
|
failure
|
|
--*/
|
|
|
|
{
|
|
int i;
|
|
|
|
switch ( ireg ) {
|
|
|
|
case CV_REG_AL:
|
|
*( (LPB) lpvRegValue ) = (BYTE) lpregs->Eax;
|
|
break;
|
|
|
|
case CV_REG_CL:
|
|
*( (LPB) lpvRegValue ) = (BYTE) lpregs->Ecx;
|
|
break;
|
|
|
|
case CV_REG_DL:
|
|
*( (LPB) lpvRegValue ) = (BYTE) lpregs->Edx;
|
|
break;
|
|
|
|
case CV_REG_BL:
|
|
*( (LPB) lpvRegValue ) = (BYTE) lpregs->Ebx;
|
|
break;
|
|
|
|
case CV_REG_AH:
|
|
*( (LPB) lpvRegValue ) = (BYTE) (lpregs->Eax >> 8);
|
|
break;
|
|
|
|
case CV_REG_CH:
|
|
*( (LPB) lpvRegValue ) = (BYTE) (lpregs->Ecx >> 8);
|
|
break;
|
|
|
|
case CV_REG_DH:
|
|
*( (LPB) lpvRegValue ) = (BYTE) (lpregs->Edx >> 8);
|
|
break;
|
|
|
|
case CV_REG_BH:
|
|
*( (LPB) lpvRegValue ) = (BYTE) (lpregs->Ebx >> 8);
|
|
break;
|
|
|
|
case CV_REG_AX:
|
|
*( (LPW) lpvRegValue ) = (WORD) lpregs->Eax;
|
|
break;
|
|
|
|
case CV_REG_CX:
|
|
*( (LPW) lpvRegValue ) = (WORD) lpregs->Ecx;
|
|
break;
|
|
|
|
case CV_REG_DX:
|
|
*( (LPW) lpvRegValue ) = (WORD) lpregs->Edx;
|
|
break;
|
|
|
|
case CV_REG_BX:
|
|
*( (LPW) lpvRegValue ) = (WORD) lpregs->Ebx;
|
|
break;
|
|
|
|
case CV_REG_SP:
|
|
*( (LPW) lpvRegValue ) = (WORD) lpregs->Esp;
|
|
break;
|
|
|
|
case CV_REG_BP:
|
|
*( (LPW) lpvRegValue ) = (WORD) lpregs->Ebp;
|
|
break;
|
|
|
|
case CV_REG_SI:
|
|
*( (LPW) lpvRegValue ) = (WORD) lpregs->Esi;
|
|
break;
|
|
|
|
case CV_REG_DI:
|
|
*( (LPW) lpvRegValue ) = (WORD) lpregs->Edi;
|
|
break;
|
|
|
|
case CV_REG_IP:
|
|
*( (LPW) lpvRegValue ) = (WORD) lpregs->Eip;
|
|
break;
|
|
|
|
case CV_REG_FLAGS:
|
|
*( (LPW) lpvRegValue ) = (WORD) lpregs->EFlags;
|
|
break;
|
|
|
|
case CV_REG_ES:
|
|
*( (LPW) lpvRegValue ) = (SEGMENT) lpregs->SegEs;
|
|
break;
|
|
|
|
case CV_REG_CS:
|
|
*( (LPW) lpvRegValue ) = (SEGMENT) lpregs->SegCs;
|
|
break;
|
|
|
|
case CV_REG_SS:
|
|
*( (LPW) lpvRegValue ) = (SEGMENT) lpregs->SegSs;
|
|
break;
|
|
|
|
case CV_REG_DS:
|
|
*( (LPW) lpvRegValue ) = (SEGMENT) lpregs->SegDs;
|
|
break;
|
|
|
|
case CV_REG_FS:
|
|
*( (LPW) lpvRegValue ) = (SEGMENT) lpregs->SegFs;
|
|
break;
|
|
|
|
case CV_REG_GS:
|
|
*( (LPW) lpvRegValue ) = (SEGMENT) lpregs->SegGs;
|
|
break;
|
|
|
|
case CV_REG_EAX:
|
|
*( (LPL) lpvRegValue ) = lpregs->Eax;
|
|
break;
|
|
|
|
case CV_REG_ECX:
|
|
*( (LPL) lpvRegValue ) = lpregs->Ecx;
|
|
break;
|
|
|
|
case CV_REG_EDX:
|
|
*( (LPL) lpvRegValue ) = lpregs->Edx;
|
|
break;
|
|
|
|
case CV_REG_EBX:
|
|
*( (LPL) lpvRegValue ) = lpregs->Ebx;
|
|
break;
|
|
|
|
case CV_REG_ESP:
|
|
*( (LPL) lpvRegValue ) = lpregs->Esp;
|
|
break;
|
|
|
|
case CV_REG_EBP:
|
|
*( (LPL) lpvRegValue ) = lpregs->Ebp;
|
|
break;
|
|
|
|
case CV_REG_ESI:
|
|
*( (LPL) lpvRegValue ) = lpregs->Esi;
|
|
break;
|
|
|
|
case CV_REG_EDI:
|
|
*( (LPL) lpvRegValue ) = lpregs->Edi;
|
|
break;
|
|
|
|
case CV_REG_EIP:
|
|
*( (LPL) lpvRegValue ) = lpregs->Eip;
|
|
break;
|
|
|
|
case CV_REG_EFLAGS:
|
|
*( (LPL) lpvRegValue ) = lpregs->EFlags;
|
|
break;
|
|
|
|
case CV_REG_ST0:
|
|
case CV_REG_ST1:
|
|
case CV_REG_ST2:
|
|
case CV_REG_ST3:
|
|
case CV_REG_ST4:
|
|
case CV_REG_ST5:
|
|
case CV_REG_ST6:
|
|
case CV_REG_ST7:
|
|
|
|
// i = (lpregs->FloatSave.StatusWord >> 11) & 0x7;
|
|
// i = (i + ireg - CV_REG_ST0) % 8;
|
|
|
|
i = ireg - CV_REG_ST0;
|
|
|
|
*( (LPL_DOUBLE) lpvRegValue ) =
|
|
((LPL_DOUBLE)(lpregs->FloatSave.RegisterArea))[ i ];
|
|
break;
|
|
|
|
case CV_REG_CTRL:
|
|
*( (LPL) lpvRegValue ) = lpregs->FloatSave.ControlWord;
|
|
break;
|
|
|
|
case CV_REG_STAT:
|
|
*( (LPL) lpvRegValue ) = lpregs->FloatSave.StatusWord;
|
|
break;
|
|
|
|
case CV_REG_TAG:
|
|
*( (LPL) lpvRegValue ) = lpregs->FloatSave.TagWord;
|
|
break;
|
|
|
|
case CV_REG_FPIP:
|
|
*( (LPW) lpvRegValue ) = (OFF16) lpregs->FloatSave.ErrorOffset;
|
|
break;
|
|
|
|
case CV_REG_FPEIP:
|
|
*( (LPL) lpvRegValue ) = lpregs->FloatSave.ErrorOffset;
|
|
break;
|
|
|
|
case CV_REG_FPCS:
|
|
*( (LPW) lpvRegValue ) = (SEGMENT) lpregs->FloatSave.ErrorSelector;
|
|
break;
|
|
|
|
case CV_REG_FPDO:
|
|
*( (LPL) lpvRegValue ) = (OFF16) lpregs->FloatSave.DataOffset;
|
|
break;
|
|
|
|
case CV_REG_FPEDO:
|
|
*( (LPL) lpvRegValue ) = lpregs->FloatSave.DataOffset;
|
|
break;
|
|
|
|
case CV_REG_FPDS:
|
|
*( (LPW) lpvRegValue ) = (SEGMENT) lpregs->FloatSave.DataSelector;
|
|
break;
|
|
|
|
#define lpsr ((PKSPECIAL_REGISTERS)lpregs)
|
|
case CV_REG_GDTR:
|
|
*( (LPDWORD) lpvRegValue ) = lpsr->Gdtr.Base;
|
|
break;
|
|
|
|
case CV_REG_GDTL:
|
|
*( (LPWORD) lpvRegValue ) = lpsr->Gdtr.Limit;
|
|
break;
|
|
|
|
case CV_REG_IDTR:
|
|
*( (LPDWORD) lpvRegValue ) = lpsr->Idtr.Base;
|
|
break;
|
|
|
|
case CV_REG_IDTL:
|
|
*( (LPWORD) lpvRegValue ) = lpsr->Idtr.Limit;
|
|
break;
|
|
|
|
case CV_REG_LDTR:
|
|
*( (LPWORD) lpvRegValue ) = lpsr->Ldtr;
|
|
break;
|
|
|
|
case CV_REG_TR:
|
|
*( (LPWORD) lpvRegValue ) = lpsr->Tr;
|
|
break;
|
|
|
|
case CV_REG_CR0:
|
|
*( (LPDWORD) lpvRegValue ) = lpsr->Cr0;
|
|
break;
|
|
|
|
case CV_REG_CR2:
|
|
*( (LPDWORD) lpvRegValue ) = lpsr->Cr2;
|
|
break;
|
|
|
|
case CV_REG_CR3:
|
|
*( (LPDWORD) lpvRegValue ) = lpsr->Cr3;
|
|
break;
|
|
|
|
case CV_REG_CR4:
|
|
*( (LPDWORD) lpvRegValue ) = lpsr->Cr4;
|
|
break;
|
|
#undef lpsr
|
|
|
|
case CV_REG_DR0:
|
|
*( (PULONG) lpvRegValue ) = lpregs->Dr0;
|
|
break;
|
|
|
|
case CV_REG_DR1:
|
|
*( (PULONG) lpvRegValue ) = lpregs->Dr1;
|
|
break;
|
|
|
|
case CV_REG_DR2:
|
|
*( (PULONG) lpvRegValue ) = lpregs->Dr2;
|
|
break;
|
|
|
|
case CV_REG_DR3:
|
|
*( (PULONG) lpvRegValue ) = lpregs->Dr3;
|
|
break;
|
|
|
|
case CV_REG_DR6:
|
|
*( (PULONG) lpvRegValue ) = lpregs->Dr6;
|
|
break;
|
|
|
|
case CV_REG_DR7:
|
|
*( (PULONG) lpvRegValue ) = lpregs->Dr7;
|
|
break;
|
|
|
|
}
|
|
|
|
switch ( ireg ) {
|
|
|
|
case CV_REG_AL:
|
|
case CV_REG_CL:
|
|
case CV_REG_DL:
|
|
case CV_REG_BL:
|
|
case CV_REG_AH:
|
|
case CV_REG_CH:
|
|
case CV_REG_DH:
|
|
case CV_REG_BH:
|
|
|
|
(LPB) lpvRegValue += sizeof ( BYTE );
|
|
break;
|
|
|
|
case CV_REG_AX:
|
|
case CV_REG_CX:
|
|
case CV_REG_DX:
|
|
case CV_REG_BX:
|
|
case CV_REG_SP:
|
|
case CV_REG_BP:
|
|
case CV_REG_SI:
|
|
case CV_REG_DI:
|
|
case CV_REG_IP:
|
|
case CV_REG_FLAGS:
|
|
case CV_REG_ES:
|
|
case CV_REG_CS:
|
|
case CV_REG_SS:
|
|
case CV_REG_DS:
|
|
case CV_REG_FS:
|
|
case CV_REG_GS:
|
|
case CV_REG_FPCS:
|
|
case CV_REG_FPDS:
|
|
case CV_REG_CTRL:
|
|
case CV_REG_STAT:
|
|
case CV_REG_TAG:
|
|
case CV_REG_FPIP:
|
|
case CV_REG_FPDO:
|
|
|
|
case CV_REG_GDTL:
|
|
case CV_REG_IDTL:
|
|
case CV_REG_LDTR:
|
|
case CV_REG_TR:
|
|
|
|
(LPB) lpvRegValue += sizeof ( WORD );
|
|
break;
|
|
|
|
case CV_REG_EAX:
|
|
case CV_REG_ECX:
|
|
case CV_REG_EDX:
|
|
case CV_REG_EBX:
|
|
case CV_REG_ESP:
|
|
case CV_REG_EBP:
|
|
case CV_REG_ESI:
|
|
case CV_REG_EDI:
|
|
case CV_REG_EIP:
|
|
case CV_REG_EFLAGS:
|
|
case CV_REG_FPEIP:
|
|
case CV_REG_FPEDO:
|
|
|
|
case CV_REG_CR0:
|
|
case CV_REG_CR1:
|
|
case CV_REG_CR2:
|
|
case CV_REG_CR3:
|
|
case CV_REG_CR4:
|
|
|
|
case CV_REG_DR0:
|
|
case CV_REG_DR1:
|
|
case CV_REG_DR2:
|
|
case CV_REG_DR3:
|
|
case CV_REG_DR4:
|
|
case CV_REG_DR5:
|
|
case CV_REG_DR6:
|
|
case CV_REG_DR7:
|
|
|
|
case CV_REG_GDTR:
|
|
case CV_REG_IDTR:
|
|
|
|
(LPB) lpvRegValue += sizeof ( LONG );
|
|
break;
|
|
|
|
case CV_REG_ST0:
|
|
case CV_REG_ST1:
|
|
case CV_REG_ST2:
|
|
case CV_REG_ST3:
|
|
case CV_REG_ST4:
|
|
case CV_REG_ST5:
|
|
case CV_REG_ST6:
|
|
case CV_REG_ST7:
|
|
|
|
(LPB) lpvRegValue += sizeof ( L_DOUBLE );
|
|
break;
|
|
|
|
default:
|
|
lpvRegValue = NULL;
|
|
break;
|
|
}
|
|
|
|
return lpvRegValue;
|
|
} /* DoGetReg() */
|
|
|
|
|
|
LPV
|
|
DoSetReg(
|
|
LPCONTEXT lpregs,
|
|
DWORD ireg,
|
|
LPV lpvRegValue
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is used to set a specific register in a threads
|
|
context
|
|
|
|
Arguments:
|
|
|
|
lpregs - Supplies pointer to register context for thread
|
|
ireg - Supplies the index of the register to be modified
|
|
lpvRegValue - Supplies the buffer containning the new data
|
|
|
|
Return Value:
|
|
|
|
return-value - the pointer the the next location where a register
|
|
value could be.
|
|
|
|
--*/
|
|
|
|
{
|
|
int i;
|
|
|
|
switch ( ireg ) {
|
|
|
|
case CV_REG_AL:
|
|
lpregs->Eax = (lpregs->Eax & 0xFFFFFF00) | *( (LPB) lpvRegValue );
|
|
break;
|
|
|
|
case CV_REG_CL:
|
|
lpregs->Ecx = (lpregs->Ecx & 0xFFFFFF00) | *( (LPB) lpvRegValue );
|
|
break;
|
|
|
|
case CV_REG_DL:
|
|
lpregs->Edx = (lpregs->Edx & 0xFFFFFF00) | *( (LPB) lpvRegValue );
|
|
break;
|
|
|
|
case CV_REG_BL:
|
|
lpregs->Ebx = (lpregs->Ebx & 0xFFFFFF00) | *( (LPB) lpvRegValue );
|
|
break;
|
|
|
|
case CV_REG_AH:
|
|
lpregs->Eax = (lpregs->Eax & 0xFFFF00FF) |
|
|
(((WORD) *( (LPB) lpvRegValue )) << 8);
|
|
break;
|
|
|
|
case CV_REG_CH:
|
|
lpregs->Ecx = (lpregs->Ecx & 0xFFFF00FF) |
|
|
(((WORD) *( (LPB) lpvRegValue )) << 8);
|
|
break;
|
|
|
|
case CV_REG_DH:
|
|
lpregs->Edx = (lpregs->Edx & 0xFFFF00FF) |
|
|
(((WORD) *( (LPB) lpvRegValue )) << 8);
|
|
break;
|
|
|
|
case CV_REG_BH:
|
|
lpregs->Ebx = (lpregs->Ebx & 0xFFFF00FF) |
|
|
(((WORD) *( (LPB) lpvRegValue )) << 8);
|
|
break;
|
|
|
|
case CV_REG_AX:
|
|
lpregs->Eax = (lpregs->Eax & 0xFFFF0000) | *( (LPW) lpvRegValue );
|
|
break;
|
|
|
|
case CV_REG_CX:
|
|
lpregs->Ecx = (lpregs->Ecx & 0xFFFF0000) | *( (LPW) lpvRegValue );
|
|
break;
|
|
|
|
case CV_REG_DX:
|
|
lpregs->Edx = (lpregs->Edx & 0xFFFF0000) | *( (LPW) lpvRegValue );
|
|
break;
|
|
|
|
case CV_REG_BX:
|
|
lpregs->Ebx = (lpregs->Ebx & 0xFFFF0000) | *( (LPW) lpvRegValue );
|
|
break;
|
|
|
|
case CV_REG_SP:
|
|
lpregs->Esp = (lpregs->Esp & 0xFFFF0000) | *( (LPW) lpvRegValue );
|
|
break;
|
|
|
|
case CV_REG_BP:
|
|
lpregs->Ebp = (lpregs->Ebp & 0xFFFF0000) | *( (LPW) lpvRegValue );
|
|
break;
|
|
|
|
case CV_REG_SI:
|
|
lpregs->Esi = (lpregs->Esi & 0xFFFF0000) | *( (LPW) lpvRegValue );
|
|
break;
|
|
|
|
case CV_REG_DI:
|
|
lpregs->Edi = (lpregs->Edi & 0xFFFF0000) | *( (LPW) lpvRegValue );
|
|
break;
|
|
|
|
case CV_REG_IP:
|
|
lpregs->Eip = (lpregs->Eip & 0xFFFF0000) | *( (LPW) lpvRegValue );
|
|
break;
|
|
|
|
case CV_REG_FLAGS:
|
|
lpregs->EFlags = (lpregs->EFlags & 0xFFFF0000 ) | *( (LPW) lpvRegValue );
|
|
break;
|
|
|
|
case CV_REG_ES:
|
|
lpregs->SegEs = *( (LPW) lpvRegValue );
|
|
break;
|
|
|
|
case CV_REG_CS:
|
|
lpregs->SegCs = *( (LPW) lpvRegValue );
|
|
break;
|
|
|
|
case CV_REG_SS:
|
|
lpregs->SegSs = *( (LPW) lpvRegValue );
|
|
break;
|
|
|
|
case CV_REG_DS:
|
|
lpregs->SegDs = *( (LPW) lpvRegValue );
|
|
break;
|
|
|
|
case CV_REG_FS:
|
|
lpregs->SegFs = *( (LPW) lpvRegValue );
|
|
break;
|
|
|
|
case CV_REG_GS:
|
|
lpregs->SegGs = *( (LPW) lpvRegValue );
|
|
break;
|
|
|
|
case CV_REG_EAX:
|
|
lpregs->Eax = *( (LPL) lpvRegValue );
|
|
break;
|
|
|
|
case CV_REG_ECX:
|
|
lpregs->Ecx = *( (LPL) lpvRegValue );
|
|
break;
|
|
|
|
case CV_REG_EDX:
|
|
lpregs->Edx = *( (LPL) lpvRegValue );
|
|
break;
|
|
|
|
case CV_REG_EBX:
|
|
lpregs->Ebx = *( (LPL) lpvRegValue );
|
|
break;
|
|
|
|
case CV_REG_ESP:
|
|
lpregs->Esp = *( (LPL) lpvRegValue );
|
|
break;
|
|
|
|
case CV_REG_EBP:
|
|
lpregs->Ebp = *( (LPL) lpvRegValue );
|
|
break;
|
|
|
|
case CV_REG_ESI:
|
|
lpregs->Esi = *( (LPL) lpvRegValue );
|
|
break;
|
|
|
|
case CV_REG_EDI:
|
|
lpregs->Edi = *( (LPL) lpvRegValue );
|
|
break;
|
|
|
|
case CV_REG_EIP:
|
|
lpregs->Eip = *( (LPL) lpvRegValue );
|
|
break;
|
|
|
|
case CV_REG_EFLAGS:
|
|
lpregs->EFlags = *( (LPL) lpvRegValue );
|
|
break;
|
|
|
|
case CV_REG_ST0:
|
|
case CV_REG_ST1:
|
|
case CV_REG_ST2:
|
|
case CV_REG_ST3:
|
|
case CV_REG_ST4:
|
|
case CV_REG_ST5:
|
|
case CV_REG_ST6:
|
|
case CV_REG_ST7:
|
|
// i = (lpregs->FloatSave.StatusWord >> 11) & 0x7;
|
|
// i = (i + ireg - CV_REG_ST0) % 8;
|
|
i = ireg - CV_REG_ST0;
|
|
memcpy(&lpregs->FloatSave.RegisterArea[10*(i)], lpvRegValue, 10);
|
|
break;
|
|
|
|
case CV_REG_CTRL:
|
|
lpregs->FloatSave.ControlWord = *( (LPW) lpvRegValue );
|
|
break;
|
|
|
|
case CV_REG_STAT:
|
|
lpregs->FloatSave.StatusWord = *( (LPW) lpvRegValue );
|
|
break;
|
|
|
|
case CV_REG_TAG:
|
|
lpregs->FloatSave.TagWord = *( (LPW) lpvRegValue );
|
|
break;
|
|
|
|
case CV_REG_FPIP:
|
|
lpregs->FloatSave.ErrorOffset = *( (LPW) lpvRegValue );
|
|
break;
|
|
|
|
case CV_REG_FPEIP:
|
|
lpregs->FloatSave.ErrorOffset = *( (LPL) lpvRegValue );
|
|
break;
|
|
|
|
case CV_REG_FPCS:
|
|
lpregs->FloatSave.ErrorSelector = *( (LPW) lpvRegValue );
|
|
break;
|
|
|
|
case CV_REG_FPDO:
|
|
lpregs->FloatSave.DataOffset = *( (LPW) lpvRegValue );
|
|
break;
|
|
|
|
case CV_REG_FPEDO:
|
|
lpregs->FloatSave.DataOffset = *( (LPW) lpvRegValue );
|
|
break;
|
|
|
|
case CV_REG_FPDS:
|
|
lpregs->FloatSave.DataSelector = *( (LPW) lpvRegValue );
|
|
break;
|
|
|
|
#define lpsr ((PKSPECIAL_REGISTERS)lpregs)
|
|
case CV_REG_GDTR:
|
|
lpsr->Gdtr.Base = *( (LPDWORD) lpvRegValue );
|
|
break;
|
|
|
|
case CV_REG_GDTL:
|
|
lpsr->Gdtr.Limit = *( (LPWORD) lpvRegValue );
|
|
break;
|
|
|
|
case CV_REG_IDTR:
|
|
lpsr->Idtr.Base = *( (LPDWORD) lpvRegValue );
|
|
break;
|
|
|
|
case CV_REG_IDTL:
|
|
lpsr->Idtr.Limit = *( (LPWORD) lpvRegValue );
|
|
break;
|
|
|
|
case CV_REG_LDTR:
|
|
lpsr->Ldtr = *( (LPW) lpvRegValue );
|
|
break;
|
|
|
|
case CV_REG_TR:
|
|
lpsr->Tr = *( (LPW) lpvRegValue );
|
|
break;
|
|
|
|
case CV_REG_CR0:
|
|
lpsr->Cr0 = *( (LPDWORD) lpvRegValue );
|
|
break;
|
|
|
|
case CV_REG_CR2:
|
|
lpsr->Cr2 = *( (LPDWORD) lpvRegValue );
|
|
break;
|
|
|
|
case CV_REG_CR3:
|
|
lpsr->Cr3 = *( (LPDWORD) lpvRegValue );
|
|
break;
|
|
|
|
case CV_REG_CR4:
|
|
lpsr->Cr4 = *( (LPDWORD) lpvRegValue );
|
|
break;
|
|
#undef lpsr
|
|
|
|
case CV_REG_DR0:
|
|
lpregs->Dr0 = *( (PULONG) lpvRegValue );
|
|
break;
|
|
|
|
case CV_REG_DR1:
|
|
lpregs->Dr1 = *( (PULONG) lpvRegValue );
|
|
break;
|
|
|
|
case CV_REG_DR2:
|
|
lpregs->Dr2 = *( (PULONG) lpvRegValue );
|
|
break;
|
|
|
|
case CV_REG_DR3:
|
|
lpregs->Dr3 = *( (PULONG) lpvRegValue );
|
|
break;
|
|
|
|
case CV_REG_DR6:
|
|
lpregs->Dr6 = *( (PULONG) lpvRegValue );
|
|
break;
|
|
|
|
case CV_REG_DR7:
|
|
lpregs->Dr7 = *( (PULONG) lpvRegValue );
|
|
|
|
}
|
|
|
|
|
|
switch ( ireg ) {
|
|
|
|
case CV_REG_AL:
|
|
case CV_REG_CL:
|
|
case CV_REG_DL:
|
|
case CV_REG_BL:
|
|
case CV_REG_AH:
|
|
case CV_REG_CH:
|
|
case CV_REG_DH:
|
|
case CV_REG_BH:
|
|
|
|
(LPB) lpvRegValue += sizeof ( BYTE );
|
|
break;
|
|
|
|
case CV_REG_AX:
|
|
case CV_REG_CX:
|
|
case CV_REG_DX:
|
|
case CV_REG_BX:
|
|
case CV_REG_SP:
|
|
case CV_REG_BP:
|
|
case CV_REG_SI:
|
|
case CV_REG_DI:
|
|
case CV_REG_IP:
|
|
case CV_REG_FLAGS:
|
|
case CV_REG_ES:
|
|
case CV_REG_CS:
|
|
case CV_REG_SS:
|
|
case CV_REG_DS:
|
|
case CV_REG_FS:
|
|
case CV_REG_GS:
|
|
case CV_REG_CTRL:
|
|
case CV_REG_STAT:
|
|
case CV_REG_TAG:
|
|
case CV_REG_FPIP:
|
|
case CV_REG_FPCS:
|
|
case CV_REG_FPDO:
|
|
case CV_REG_FPDS:
|
|
case CV_REG_GDTL:
|
|
case CV_REG_IDTL:
|
|
case CV_REG_LDTR:
|
|
case CV_REG_TR:
|
|
|
|
(LPB) lpvRegValue += sizeof ( WORD );
|
|
break;
|
|
|
|
case CV_REG_EAX:
|
|
case CV_REG_ECX:
|
|
case CV_REG_EDX:
|
|
case CV_REG_EBX:
|
|
case CV_REG_ESP:
|
|
case CV_REG_EBP:
|
|
case CV_REG_ESI:
|
|
case CV_REG_EDI:
|
|
case CV_REG_EIP:
|
|
case CV_REG_EFLAGS:
|
|
case CV_REG_FPEIP:
|
|
case CV_REG_FPEDO:
|
|
case CV_REG_CR0:
|
|
case CV_REG_CR1:
|
|
case CV_REG_CR2:
|
|
case CV_REG_CR3:
|
|
case CV_REG_CR4:
|
|
case CV_REG_DR0:
|
|
case CV_REG_DR1:
|
|
case CV_REG_DR2:
|
|
case CV_REG_DR3:
|
|
case CV_REG_DR4:
|
|
case CV_REG_DR5:
|
|
case CV_REG_DR6:
|
|
case CV_REG_DR7:
|
|
case CV_REG_GDTR:
|
|
case CV_REG_IDTR:
|
|
|
|
(LPB) lpvRegValue += sizeof ( LONG );
|
|
break;
|
|
|
|
case CV_REG_ST0:
|
|
case CV_REG_ST1:
|
|
case CV_REG_ST2:
|
|
case CV_REG_ST3:
|
|
case CV_REG_ST4:
|
|
case CV_REG_ST5:
|
|
case CV_REG_ST6:
|
|
case CV_REG_ST7:
|
|
|
|
(LPB) lpvRegValue += sizeof ( L_DOUBLE );
|
|
break;
|
|
|
|
default:
|
|
|
|
lpvRegValue = NULL;
|
|
break;
|
|
}
|
|
|
|
return lpvRegValue;
|
|
} /* DoSetReg() */
|
|
|
|
|
|
|
|
LPV
|
|
DoSetFrameReg(
|
|
HPID hpid,
|
|
HTID htid,
|
|
LPTHD lpthd,
|
|
PKNONVOLATILE_CONTEXT_POINTERS contextPtrs,
|
|
DWORD ireg,
|
|
LPV lpvRegValue
|
|
)
|
|
{
|
|
|
|
return DoSetReg(&lpthd->regs, ireg, lpvRegValue);
|
|
}
|
|
|
|
XOSD
|
|
GetFlagValue (
|
|
HPID hpid,
|
|
HTID htid,
|
|
DWORD iFlag,
|
|
LPV lpvRegValue
|
|
)
|
|
{
|
|
HPRC hprc;
|
|
HTHD hthd;
|
|
LPTHD lpthd;
|
|
LPCONTEXT lpregs;
|
|
LONG l;
|
|
UINT cbytes;
|
|
|
|
hprc = ValidHprcFromHpid(hpid);
|
|
if (!hprc) {
|
|
return xosdInvalidProc;
|
|
}
|
|
hthd = HthdFromHtid(hprc, htid);
|
|
|
|
assert ( hthd != hthdNull );
|
|
lpthd = LLLock( hthd );
|
|
|
|
lpregs = &lpthd->regs;
|
|
|
|
if ( !(lpthd->drt & drtAllPresent) ) {
|
|
UpdateRegisters ( hprc, hthd );
|
|
}
|
|
|
|
if (DoGetReg ( lpregs, Rgfd[iFlag].fd.hReg, &l ) == NULL) {
|
|
LLUnlock( hthd );
|
|
return xosdInvalidRegister;
|
|
}
|
|
|
|
l = l >> Rgfd[iFlag].iShift;
|
|
l &= (1 << Rgfd[iFlag].fd.cbits) - 1;
|
|
cbytes = (Rgfd[iFlag].fd.cbits <= 8) ? 1 : ((Rgfd[iFlag].fd.cbits + 15)/16 * 2);
|
|
switch (cbytes ) {
|
|
case 1:
|
|
*((BYTE FAR *) lpvRegValue) = (BYTE) l;
|
|
break;
|
|
|
|
case 2:
|
|
*((USHORT FAR *) lpvRegValue) = (USHORT) l;
|
|
break;
|
|
|
|
case 4:
|
|
*((ULONG FAR *) lpvRegValue) = (ULONG) l;
|
|
break;
|
|
|
|
default:
|
|
assert(FALSE);
|
|
|
|
break;
|
|
}
|
|
LLUnlock( hthd );
|
|
return xosdNone;
|
|
}
|
|
|
|
|
|
#ifndef OSDEBUG4
|
|
|
|
XOSD
|
|
StackWalkSetup(
|
|
HPID hpid,
|
|
HTID htid,
|
|
LPSTACKFRAME lpstkframe
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is used to setup the StackWalk Structure.
|
|
This routine will defer the processing to the dm
|
|
|
|
Arguments:
|
|
|
|
hprc - Supplies handle to process to stack walk
|
|
|
|
hthd - Supplies handle to thread to stack walk
|
|
|
|
lpstkframe - Supplies pointer the stack walk structure
|
|
|
|
Return Value:
|
|
|
|
xosd error code
|
|
|
|
--*/
|
|
|
|
{
|
|
LPTHD lpthd;
|
|
HTHD hthd;
|
|
HPRC hprc = ValidHprcFromHpid(hpid);
|
|
ADDRESS_MODE mode;
|
|
ULONG ul;
|
|
|
|
|
|
if (!hprc) {
|
|
return xosdInvalidProc;
|
|
}
|
|
|
|
hthd = HthdFromHtid(hprc, htid);
|
|
if (hthd == hthdNull) {
|
|
return xosdInvalidThread;
|
|
}
|
|
|
|
lpthd = LLLock( hthd );
|
|
|
|
assert(lpthd != NULL);
|
|
|
|
if (lpthd->drt & (drtCntrlDirty|drtAllDirty)) {
|
|
SendRequestX(dmfWriteReg, hpid, htid, sizeof(CONTEXT), &lpthd->regs);
|
|
lpthd->drt &= ~(drtCntrlDirty|drtAllDirty);
|
|
}
|
|
|
|
UpdateRegisters( hprc, hthd );
|
|
GetRegValue( hpid, htid, CV_REG_EBP, &ul);
|
|
|
|
//
|
|
// set the addressing mode
|
|
//
|
|
if (lpthd->fFlat) {
|
|
mode = AddrModeFlat;
|
|
} else
|
|
if (lpthd->fReal) {
|
|
mode = AddrModeReal;
|
|
} else
|
|
if (lpthd->fOff32) {
|
|
mode = AddrMode1632;
|
|
} else {
|
|
mode = AddrMode1616;
|
|
}
|
|
|
|
//
|
|
// setup the program counter
|
|
//
|
|
if (!lpstkframe->AddrPC.Offset) {
|
|
if (mode == AddrModeFlat) {
|
|
lpstkframe->AddrPC.Offset = lpthd->regs.Eip;
|
|
} else {
|
|
lpstkframe->AddrPC.Offset = (WORD)lpthd->regs.Eip;
|
|
}
|
|
lpstkframe->AddrPC.Segment = (WORD)lpthd->regs.SegCs;
|
|
lpstkframe->AddrPC.Mode = mode;
|
|
}
|
|
|
|
//
|
|
// setup the frame pointer
|
|
//
|
|
if (!lpstkframe->AddrFrame.Offset) {
|
|
if (mode == AddrModeFlat) {
|
|
lpstkframe->AddrFrame.Offset = lpthd->regs.Ebp;
|
|
} else {
|
|
lpstkframe->AddrFrame.Offset = (WORD)lpthd->regs.Ebp;
|
|
}
|
|
lpstkframe->AddrFrame.Segment = (WORD)lpthd->regs.SegSs;
|
|
lpstkframe->AddrFrame.Mode = mode;
|
|
}
|
|
|
|
//
|
|
// setup the stack pointer
|
|
//
|
|
if (!lpstkframe->AddrStack.Offset) {
|
|
if (mode == AddrModeFlat) {
|
|
lpstkframe->AddrStack.Offset = lpthd->regs.Esp;
|
|
} else {
|
|
lpstkframe->AddrStack.Offset = (WORD)lpthd->regs.Esp;
|
|
}
|
|
lpstkframe->AddrStack.Segment = (WORD)lpthd->regs.SegSs;
|
|
lpstkframe->AddrStack.Mode = mode;
|
|
}
|
|
|
|
LLUnlock( hthd );
|
|
|
|
if (StackWalk( IMAGE_FILE_MACHINE_I386,
|
|
hpid,
|
|
htid,
|
|
lpstkframe,
|
|
NULL,
|
|
SwReadMemory,
|
|
SwFunctionTableAccess,
|
|
SwGetModuleBase,
|
|
SwTranslateAddress
|
|
)) {
|
|
|
|
return xosdNone;
|
|
|
|
}
|
|
|
|
return xosdEndOfStack;
|
|
} /* StackWalkSetup() */
|
|
|
|
|
|
XOSD
|
|
StackWalkNext(
|
|
HPID hpid,
|
|
HTID htid,
|
|
LPSTACKFRAME lpstkframe
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function is called to move up a level in the call stack.
|
|
We defer down to the DM to do this.
|
|
|
|
Arguments:
|
|
|
|
hpid - Supplies process handle to stack walk
|
|
htid - Supplies thread handle to stack walk
|
|
lpstkframe - Supplies pointer to stack walk data
|
|
|
|
Return Value:
|
|
|
|
XOSD error code
|
|
|
|
--*/
|
|
|
|
{
|
|
if (StackWalk( IMAGE_FILE_MACHINE_I386,
|
|
hpid,
|
|
htid,
|
|
lpstkframe,
|
|
NULL,
|
|
SwReadMemory,
|
|
SwFunctionTableAccess,
|
|
SwGetModuleBase,
|
|
SwTranslateAddress
|
|
)) {
|
|
|
|
return xosdNone;
|
|
|
|
}
|
|
|
|
return xosdEndOfStack;
|
|
} /* StackWalkNext() */
|
|
|
|
#endif
|
|
|
|
PFPO_DATA
|
|
SwSearchFpoData(
|
|
DWORD key,
|
|
PFPO_DATA base,
|
|
DWORD num
|
|
)
|
|
{
|
|
PFPO_DATA lo = base;
|
|
PFPO_DATA hi = base + (num - 1);
|
|
PFPO_DATA mid;
|
|
DWORD half;
|
|
|
|
while (lo <= hi) {
|
|
if (half = num / 2) {
|
|
mid = lo + ((num & 1) ? half : (half - 1));
|
|
if ((key >= mid->ulOffStart)&&(key < (mid->ulOffStart+mid->cbProcSize))) {
|
|
return mid;
|
|
}
|
|
if (key < mid->ulOffStart) {
|
|
hi = mid - 1;
|
|
num = (num & 1) ? half : half-1;
|
|
}
|
|
else {
|
|
lo = mid + 1;
|
|
num = half;
|
|
}
|
|
}
|
|
else
|
|
if (num) {
|
|
if ((key >= lo->ulOffStart)&&(key < (lo->ulOffStart+lo->cbProcSize))) {
|
|
return lo;
|
|
}
|
|
else {
|
|
break;
|
|
}
|
|
}
|
|
else {
|
|
break;
|
|
}
|
|
}
|
|
return(NULL);
|
|
}
|
|
|
|
LPVOID
|
|
SwFunctionTableAccess(
|
|
HPID hpid,
|
|
DWORD AddrBase
|
|
)
|
|
{
|
|
HLLI hlli = 0;
|
|
HMDI hmdi = 0;
|
|
LPMDI lpmdi = 0;
|
|
DWORD off;
|
|
PFPO_DATA pFpo;
|
|
|
|
|
|
hmdi = SwGetMdi( hpid, AddrBase );
|
|
if (!hmdi) {
|
|
return NULL;
|
|
}
|
|
|
|
lpmdi = LLLock( hmdi );
|
|
|
|
if (lpmdi && lpmdi->lpDebug) {
|
|
off = ConvertOmapToSrc( lpmdi, AddrBase );
|
|
if (off) {
|
|
AddrBase = off;
|
|
}
|
|
pFpo = SwSearchFpoData( AddrBase - lpmdi->lpBaseOfDll,
|
|
lpmdi->lpDebug->lpFpo,
|
|
lpmdi->lpDebug->cRtf
|
|
);
|
|
LLUnlock( hmdi );
|
|
if (pFpo) {
|
|
return (LPVOID)pFpo;
|
|
}
|
|
} else {
|
|
LLUnlock( hmdi );
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
DWORD
|
|
SwTranslateAddress(
|
|
HPID hpid,
|
|
HTID htid,
|
|
LPADDRESS lpaddress
|
|
)
|
|
{
|
|
XOSD xosd;
|
|
ADDR addr;
|
|
BYTE buf[256];
|
|
LPIOL lpiol = (LPIOL)buf;
|
|
PIOCTLGENERIC pig = (PIOCTLGENERIC)lpiol->rgbVar;
|
|
|
|
|
|
ZeroMemory( &addr, sizeof(addr) );
|
|
addr.addr.off = lpaddress->Offset;
|
|
addr.addr.seg = lpaddress->Segment;
|
|
addr.mode.fFlat = lpaddress->Mode == AddrModeFlat;
|
|
addr.mode.fOff32 = lpaddress->Mode == AddrMode1632;
|
|
addr.mode.fReal = lpaddress->Mode == AddrModeReal;
|
|
|
|
memcpy( pig->data, &addr, sizeof(addr) );
|
|
lpiol->wFunction = ioctlGeneric;
|
|
pig->length = sizeof(addr) + 4;
|
|
pig->ioctlSubType = IG_TRANSLATE_ADDRESS;
|
|
|
|
xosd = IoctlCmd( hpid, htid, pig->length+sizeof(*pig), lpiol );
|
|
|
|
if (xosd == xosdNone) {
|
|
addr = *((LPADDR)pig->data);
|
|
|
|
lpaddress->Offset = addr.addr.off;
|
|
lpaddress->Segment = addr.addr.seg;
|
|
|
|
if (addr.mode.fFlat) {
|
|
lpaddress->Mode = AddrModeFlat;
|
|
} else
|
|
if (addr.mode.fOff32) {
|
|
lpaddress->Mode == AddrMode1632;
|
|
} else
|
|
if (addr.mode.fReal) {
|
|
lpaddress->Mode == AddrModeReal;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL
|
|
SwReadMemory(
|
|
HPID hpid,
|
|
LPCVOID lpBaseAddress,
|
|
LPVOID lpBuffer,
|
|
DWORD nSize,
|
|
LPDWORD lpNumberOfBytesRead
|
|
)
|
|
{
|
|
ADDR addr;
|
|
DWORD cb;
|
|
XOSD xosd;
|
|
BYTE buf[256];
|
|
LPIOL lpiol;
|
|
PIOCTLGENERIC pig;
|
|
PREADCONTROLSPACE prc;
|
|
|
|
|
|
if ((LONG)lpNumberOfBytesRead == -1) {
|
|
|
|
lpiol = (LPIOL)buf;
|
|
pig = (PIOCTLGENERIC)lpiol->rgbVar;
|
|
prc = (PREADCONTROLSPACE) pig->data;
|
|
|
|
prc->Processor = (USHORT)-1;
|
|
prc->Address = (DWORD)lpBaseAddress;
|
|
prc->BufLen = nSize;
|
|
|
|
lpiol->wFunction = ioctlGeneric;
|
|
pig->length = sizeof(*prc) + nSize;
|
|
pig->ioctlSubType = IG_READ_CONTROL_SPACE;
|
|
|
|
xosd = IoctlCmd( hpid, htidNull, pig->length+sizeof(*pig), lpiol );
|
|
if (xosd == xosdNone) {
|
|
memcpy( lpBuffer, prc->Buf, nSize );
|
|
return TRUE;
|
|
} else {
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
addr.addr.off = (OFFSET)lpBaseAddress;
|
|
addr.addr.seg = 0;
|
|
addr.emi = 0;
|
|
addr.mode.fFlat = TRUE;
|
|
addr.mode.fOff32 = FALSE;
|
|
addr.mode.fIsLI = FALSE;
|
|
addr.mode.fReal = FALSE;
|
|
|
|
xosd = ReadBuffer( hpid, NULL, &addr, nSize, lpBuffer, &cb );
|
|
if (xosd != xosdNone) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (lpNumberOfBytesRead) {
|
|
*lpNumberOfBytesRead = cb;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
XOSD
|
|
SetFrame(
|
|
HPID hpid,
|
|
HTID htid,
|
|
PFRAME pframe
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is used to setup the StackWalk Structure.
|
|
This routine will fill in the first stack walk structure element.
|
|
|
|
Arguments:
|
|
|
|
hprc - Supplies handle to process to stack walk in
|
|
hthd - Supplies handle to thread to stack walk in
|
|
pframe - Supplies pointer to the frame structure to fill in
|
|
|
|
Return Value:
|
|
|
|
xosd error code
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG ul;
|
|
HPRC hprc;
|
|
HTHD hthd;
|
|
LPTHD lpthd;
|
|
|
|
hprc = ValidHprcFromHpid( hpid );
|
|
if (!hprc) {
|
|
return xosdInvalidProc;
|
|
}
|
|
|
|
hthd = HthdFromHtid(hprc, htid);
|
|
if (hthd == hthdNull) {
|
|
return xosdInvalidThread;
|
|
}
|
|
|
|
lpthd = LLLock( hthd );
|
|
|
|
FrameFlat ( *pframe ) = lpthd->fFlat;
|
|
FrameOff32 ( *pframe ) = lpthd->fOff32;
|
|
FrameReal (*pframe ) = lpthd->fReal;
|
|
|
|
if (lpthd->fOff32) {
|
|
GetRegValue( hpid, htid, CV_REG_EBP, &ul);
|
|
} else {
|
|
GetRegValue( hpid, htid, CV_REG_BP, &ul);
|
|
ul &= 0xffff;
|
|
}
|
|
SetFrameBPOff ( *pframe, (UOFFSET) ul );
|
|
|
|
GetRegValue( hpid, htid, CV_REG_SS, &ul);
|
|
SetFrameBPSeg ( *pframe, (USHORT) ul);
|
|
pframe->SS = (USHORT) ul;
|
|
GetRegValue( hpid, htid, CV_REG_DS, &ul);
|
|
pframe->DS = (USHORT) ul;
|
|
pframe->PID = hpid;
|
|
pframe->TID = htid;
|
|
|
|
return xosdNone;
|
|
} /* SetFrame() */
|
|
|
|
|
|
|
|
|
|
|
|
XOSD
|
|
SetPath(
|
|
HPID hpid,
|
|
HTID htid,
|
|
BOOL Set,
|
|
LSZ Path
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Sets the search path in the DM
|
|
|
|
Arguments:
|
|
|
|
hpid - process
|
|
htid - thread
|
|
Set - set flag
|
|
Path - Path to search, PATH if null
|
|
|
|
|
|
Return Value:
|
|
|
|
xosd error code
|
|
|
|
--*/
|
|
|
|
{
|
|
char Buffer[ MAX_PATH ];
|
|
SETPTH *SetPth = (SETPTH *)&Buffer;
|
|
|
|
if ( Set ) {
|
|
|
|
SetPth->Set = TRUE;
|
|
if ( Path ) {
|
|
strcpy(SetPth->Path, Path );
|
|
} else {
|
|
SetPth->Path[0] = '\0';
|
|
}
|
|
} else {
|
|
SetPth->Set = FALSE;
|
|
SetPth->Path[0] = '\0';
|
|
}
|
|
|
|
return SendRequestX( dmfSetPath, hpid, htid, sizeof(SETPTH) + strlen(SetPth->Path), SetPth );
|
|
}
|
|
|
|
|
|
XOSD
|
|
GetFunctionInfo(
|
|
HPID hpid,
|
|
PADDR Addr,
|
|
PFUNCTION_INFO FunctionInfo
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Gets function information for a particular address.
|
|
|
|
Arguments:
|
|
|
|
hpid - process
|
|
Addr - Address
|
|
FunctionInfo - Function information
|
|
|
|
|
|
Return Value:
|
|
|
|
xosd error code
|
|
|
|
--*/
|
|
{
|
|
UNREFERENCED_PARAMETER( Addr );
|
|
UNREFERENCED_PARAMETER( FunctionInfo );
|
|
|
|
return xosdUnknown;
|
|
}
|