Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

1254 lines
27 KiB

/**** EMDPDEV.C - Debugger end Execution Model (ALPHA dependent code) **
* *
* *
* Copyright <C> 1993, Digital Equipment Corporation *
* Copyright <C> 1990, Microsoft Corp *
* *
* Created: January 1, 1993, Miche Baker-Harvey (mbh)
* *
* Revision History: *
* MBH - this file is a copy of the mips version, with DoSetReg, *
* DoGetReg replaced with the ALPHA equivalents, and the *
* #ifdef 0 code has been removed. *
* Taken from MIPS version dated 08-DEC-92. *
* ReTaken from MIPS version in nt353, *
* which contained no #ifdef 0 code *
* *
* *
* Purpose: *
* *
* *
***************************************************************************/
#include "precomp.h"
#pragma hdrstop
#include "strings.h"
#include "llhpt.h"
#include "mhhpt.h"
#include "lbhpt.h"
#include "osdem.h"
#include "emdm.h"
#include "emdata.h"
#include "emproto.h"
#include "osassert.h"
#include "strings.h"
#ifndef SMARTALIAS
void PurgeCache ( void );
#endif
#define CEXM_MDL_native 0x20
CONTEXT ContextSave;
/*
** This is the description of all registers and flags containned on the
** alpha machine
*/
extern RD Rgrd[];
extern struct {
FD fd;
USHORT iShift;
} Rgfd[];
#define SIZEOF_STACK_OFFSET sizeof(LONG)
BOOL NEAR PASCAL IsStackSetup(
HPID hpid,
HTID htid,
LPADDR lpaddrProc
) {
Unreferenced(hpid);
Unreferenced(htid);
Unreferenced(lpaddrProc);
return TRUE;
}
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 adrData:
if ( lpthd && !(lpthd->drt & drtAllPresent) ) {
UpdateRegisters ( hprc, hthd );
}
break;
}
switch ( adr ) {
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;
case adrPC:
AddrInit(lpaddr, 0, 0,
(UOFFSET) lpthd->regs.Fir, lpthd->fFlat,
lpthd->fOff32, FALSE, lpthd->fReal)
SetEmi ( hpid, lpaddr );
break;
case adrData:
AddrInit(lpaddr, 0, 0, 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 && !(lpthd->drt & drtCntrlPresent) ) {
UpdateRegisters ( hprc, hthd );
}
break;
case adrData:
if ( lpthd && !(lpthd->drt & drtAllPresent) ) {
UpdateRegisters ( hprc, hthd );
}
break;
}
switch ( adr ) {
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;
case adrPC:
lpthd->regs.Fir = (LONG)offAddr ( *lpaddr );
lpthd->drt |= drtCntrlDirty;
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 ) = 0;
offAddr ( addr ) = (UOFFSET) lpthd->regs.Fir;
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 );
}
//
// For DoGetReg, we push the full 64-bit value.
// The correct value is still picked up in the longword
// by the caller.
// This is written to be executable on ALPHA, MIPS and i386
//
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 success and NULL on
failure
--*/
{
PDWORDLONG RegArray;
PDWORDLONG pdwl = (PDWORDLONG)lpvRegValue;
PDWORD pdw = (PDWORD)lpvRegValue;
switch ( ireg ) {
case CV_ALPHA_IntV0 :
case CV_ALPHA_IntT0 :
case CV_ALPHA_IntT1 :
case CV_ALPHA_IntT2 :
case CV_ALPHA_IntT3 :
case CV_ALPHA_IntT4 :
case CV_ALPHA_IntT5 :
case CV_ALPHA_IntT6 :
case CV_ALPHA_IntT7 :
case CV_ALPHA_IntS0 :
case CV_ALPHA_IntS1 :
case CV_ALPHA_IntS2 :
case CV_ALPHA_IntS3 :
case CV_ALPHA_IntS4 :
case CV_ALPHA_IntS5 :
case CV_ALPHA_IntFP :
case CV_ALPHA_IntA0 :
case CV_ALPHA_IntA1 :
case CV_ALPHA_IntA2 :
case CV_ALPHA_IntA3 :
case CV_ALPHA_IntA4 :
case CV_ALPHA_IntA5 :
case CV_ALPHA_IntT8 :
case CV_ALPHA_IntT9 :
case CV_ALPHA_IntT10 :
case CV_ALPHA_IntT11 :
case CV_ALPHA_IntRA :
case CV_ALPHA_IntT12 :
case CV_ALPHA_IntAT :
case CV_ALPHA_IntGP :
case CV_ALPHA_IntSP :
case CV_ALPHA_IntZERO :
RegArray = &lpregs->IntV0;
*pdwl = RegArray[ireg - CV_ALPHA_IntV0];
lpvRegValue = (LPVOID)(pdwl + 1);
break;
case CV_ALPHA_Fir:
*pdwl = lpregs->Fir;
lpvRegValue = (LPVOID)(pdwl + 1);
break;
case CV_ALPHA_Psr:
*pdw = lpregs->Psr;
lpvRegValue = (LPVOID)(pdw + 1);
break;
case CV_ALPHA_Fpcr:
*pdwl = lpregs->Fpcr;
lpvRegValue = (LPVOID)(pdwl + 1);
break;
case CV_ALPHA_SoftFpcr:
*pdwl = lpregs->SoftFpcr;
lpvRegValue = (LPVOID)(pdwl + 1);
break;
case CV_ALPHA_FltF0 :
case CV_ALPHA_FltF1 :
case CV_ALPHA_FltF2 :
case CV_ALPHA_FltF3 :
case CV_ALPHA_FltF4 :
case CV_ALPHA_FltF5 :
case CV_ALPHA_FltF6 :
case CV_ALPHA_FltF7 :
case CV_ALPHA_FltF8 :
case CV_ALPHA_FltF9 :
case CV_ALPHA_FltF10 :
case CV_ALPHA_FltF11 :
case CV_ALPHA_FltF12 :
case CV_ALPHA_FltF13 :
case CV_ALPHA_FltF14 :
case CV_ALPHA_FltF15 :
case CV_ALPHA_FltF16 :
case CV_ALPHA_FltF17 :
case CV_ALPHA_FltF18 :
case CV_ALPHA_FltF19 :
case CV_ALPHA_FltF20 :
case CV_ALPHA_FltF21 :
case CV_ALPHA_FltF22 :
case CV_ALPHA_FltF23 :
case CV_ALPHA_FltF24 :
case CV_ALPHA_FltF25 :
case CV_ALPHA_FltF26 :
case CV_ALPHA_FltF27 :
case CV_ALPHA_FltF28 :
case CV_ALPHA_FltF29 :
case CV_ALPHA_FltF30 :
case CV_ALPHA_FltF31 :
RegArray = &lpregs->FltF0;
*pdwl = RegArray [ireg - CV_ALPHA_FltF0];
lpvRegValue = (LPVOID)(pdwl + 1);
break;
default:
assert(FALSE);
return 0;
}
return lpvRegValue;
}
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.
--*/
{
PDWORDLONG RegArray;
PDWORDLONG pdwl = (PDWORDLONG)lpvRegValue;
PDWORD pdw = (PDWORD)lpvRegValue;
switch ( ireg ) {
case CV_ALPHA_IntZERO :
return NULL;
case CV_ALPHA_IntV0 :
case CV_ALPHA_IntT0 :
case CV_ALPHA_IntT1 :
case CV_ALPHA_IntT2 :
case CV_ALPHA_IntT3 :
case CV_ALPHA_IntT4 :
case CV_ALPHA_IntT5 :
case CV_ALPHA_IntT6 :
case CV_ALPHA_IntT7 :
case CV_ALPHA_IntS0 :
case CV_ALPHA_IntS1 :
case CV_ALPHA_IntS2 :
case CV_ALPHA_IntS3 :
case CV_ALPHA_IntS4 :
case CV_ALPHA_IntS5 :
case CV_ALPHA_IntFP :
case CV_ALPHA_IntA0 :
case CV_ALPHA_IntA1 :
case CV_ALPHA_IntA2 :
case CV_ALPHA_IntA3 :
case CV_ALPHA_IntA4 :
case CV_ALPHA_IntA5 :
case CV_ALPHA_IntT8 :
case CV_ALPHA_IntT9 :
case CV_ALPHA_IntT10 :
case CV_ALPHA_IntT11 :
case CV_ALPHA_IntRA :
case CV_ALPHA_IntT12 :
case CV_ALPHA_IntAT :
case CV_ALPHA_IntGP :
case CV_ALPHA_IntSP :
RegArray = &lpregs->IntV0;
RegArray[ireg - CV_ALPHA_IntV0] = *pdwl;
lpvRegValue = (PVOID)(pdwl + 1);
break;
case CV_ALPHA_Fir:
lpregs->Fir = *pdwl;
lpvRegValue = (PVOID)(pdwl + 1);
break;
case CV_ALPHA_Psr:
lpregs->Psr = *pdw;
lpvRegValue = (PVOID)(pdw + 1);
break;
case CV_ALPHA_Fpcr:
lpregs->Fpcr = *pdwl;
lpvRegValue = (PVOID)(pdwl + 1);
break;
case CV_ALPHA_SoftFpcr:
lpregs->SoftFpcr = *pdwl;
lpvRegValue = (PVOID)(pdwl + 1);
break;
case CV_ALPHA_FltF0 :
case CV_ALPHA_FltF1 :
case CV_ALPHA_FltF2 :
case CV_ALPHA_FltF3 :
case CV_ALPHA_FltF4 :
case CV_ALPHA_FltF5 :
case CV_ALPHA_FltF6 :
case CV_ALPHA_FltF7 :
case CV_ALPHA_FltF8 :
case CV_ALPHA_FltF9 :
case CV_ALPHA_FltF10 :
case CV_ALPHA_FltF11 :
case CV_ALPHA_FltF12 :
case CV_ALPHA_FltF13 :
case CV_ALPHA_FltF14 :
case CV_ALPHA_FltF15 :
case CV_ALPHA_FltF16 :
case CV_ALPHA_FltF17 :
case CV_ALPHA_FltF18 :
case CV_ALPHA_FltF19 :
case CV_ALPHA_FltF20 :
case CV_ALPHA_FltF21 :
case CV_ALPHA_FltF22 :
case CV_ALPHA_FltF23 :
case CV_ALPHA_FltF24 :
case CV_ALPHA_FltF25 :
case CV_ALPHA_FltF26 :
case CV_ALPHA_FltF27 :
case CV_ALPHA_FltF28 :
case CV_ALPHA_FltF29 :
case CV_ALPHA_FltF30 :
case CV_ALPHA_FltF31 :
//
// Transfer the data from the caller.
// We can do this to DOUBLES because we are doing
// memory-memory copies.
//
RegArray = &lpregs->FltF0;
RegArray [ireg - CV_ALPHA_FltF0] = *pdwl;
lpvRegValue = (PVOID)(pdwl + 1);
break;
default:
assert(FALSE);
return NULL;
}
return lpvRegValue;
}
LPV
DoSetFrameReg(
HPID hpid,
HTID htid,
LPTHD lpthd,
PKNONVOLATILE_CONTEXT_POINTERS contextPtrs,
DWORD ireg,
LPV lpvRegValue
)
/*++
Routine Description:
Sets a register in an old frame; uses context pointers to do it,
which is why we can't use DoSetReg:
there's another layer of indirection
Arguments:
lpregs - Supplies pointer to pointers to the frame context
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.
--*/
{
ADDR address;
LPADDR lpaddr = &address;
XOSD xosdreturn;
switch ( ireg ) {
case CV_ALPHA_IntV0 :
case CV_ALPHA_IntT0 :
case CV_ALPHA_IntT1 :
case CV_ALPHA_IntT2 :
case CV_ALPHA_IntT3 :
case CV_ALPHA_IntT4 :
case CV_ALPHA_IntT5 :
case CV_ALPHA_IntT6 :
case CV_ALPHA_IntT7 :
case CV_ALPHA_IntS0 :
case CV_ALPHA_IntS1 :
case CV_ALPHA_IntS2 :
case CV_ALPHA_IntS3 :
case CV_ALPHA_IntS4 :
case CV_ALPHA_IntS5 :
case CV_ALPHA_IntFP :
case CV_ALPHA_IntA0 :
case CV_ALPHA_IntA1 :
case CV_ALPHA_IntA2 :
case CV_ALPHA_IntA3 :
case CV_ALPHA_IntA4 :
case CV_ALPHA_IntA5 :
case CV_ALPHA_IntT8 :
case CV_ALPHA_IntT9 :
case CV_ALPHA_IntT10 :
case CV_ALPHA_IntT11 :
case CV_ALPHA_IntRA :
case CV_ALPHA_IntT12 :
case CV_ALPHA_IntAT :
case CV_ALPHA_IntGP :
case CV_ALPHA_IntSP :
case CV_ALPHA_IntZERO :
//
// Setup the ADDR structure for where this register was saved
// on the stack for this frame.
//
AddrInit(lpaddr, 0, 0,
(UOFFSET) contextPtrs->IntegerContext[ireg - CV_ALPHA_IntV0],
lpthd->fFlat,
lpthd->fOff32, FALSE, lpthd->fReal)
SetEmi ( hpid, lpaddr );
xosdreturn = SetAddr(hpid, htid, adrCurrent, &address);
if ( xosdreturn == xosdNone ) {
xosdreturn = WriteBuffer(hpid, htid, 8, lpvRegValue);
}
break;
case CV_ALPHA_FltF0 :
case CV_ALPHA_FltF1 :
case CV_ALPHA_FltF2 :
case CV_ALPHA_FltF3 :
case CV_ALPHA_FltF4 :
case CV_ALPHA_FltF5 :
case CV_ALPHA_FltF6 :
case CV_ALPHA_FltF7 :
case CV_ALPHA_FltF8 :
case CV_ALPHA_FltF9 :
case CV_ALPHA_FltF10 :
case CV_ALPHA_FltF11 :
case CV_ALPHA_FltF12 :
case CV_ALPHA_FltF13 :
case CV_ALPHA_FltF14 :
case CV_ALPHA_FltF15 :
case CV_ALPHA_FltF16 :
case CV_ALPHA_FltF17 :
case CV_ALPHA_FltF18 :
case CV_ALPHA_FltF19 :
case CV_ALPHA_FltF20 :
case CV_ALPHA_FltF21 :
case CV_ALPHA_FltF22 :
case CV_ALPHA_FltF23 :
case CV_ALPHA_FltF24 :
case CV_ALPHA_FltF25 :
case CV_ALPHA_FltF26 :
case CV_ALPHA_FltF27 :
case CV_ALPHA_FltF28 :
case CV_ALPHA_FltF29 :
case CV_ALPHA_FltF30 :
case CV_ALPHA_FltF31 :
//
// Setup the ADDR structure for where this register was saved
// on the stack for this frame.
//
AddrInit(lpaddr, 0, 0,
(UOFFSET) contextPtrs->FloatingContext[ireg - CV_ALPHA_FltF0],
lpthd->fFlat,
lpthd->fOff32, FALSE, lpthd->fReal)
SetEmi ( hpid, lpaddr );
xosdreturn = SetAddr(hpid, htid, adrCurrent, &address);
if ( xosdreturn == xosdNone ) {
xosdreturn = WriteBuffer(hpid, htid, 8, lpvRegValue);
}
break;
default:
return NULL;
}
if ( xosdreturn == xosdNone) {
return lpvRegValue;
} else {
return NULL;
}
}
XOSD
GetFlagValue (
HPID hpid,
HTID htid,
DWORD iFlag,
LPV lpvRegValue
)
{
HPRC hprc;
HTHD hthd;
LPTHD lpthd;
LPCONTEXT lpregs;
DWORDLONG value;
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, &value ) == NULL) {
LLUnlock( hthd );
return xosdInvalidRegister;
}
value = (value >> Rgfd[iFlag].iShift) & ((1 << Rgfd[iFlag].fd.cbits) - 1);
*( (LPL) lpvRegValue) = (DWORD)value;
LLUnlock(hthd);
return xosdNone;
}
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);
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 );
ContextSave = lpthd->regs;
if (StackWalk( IMAGE_FILE_MACHINE_ALPHA,
hpid,
htid,
lpstkframe,
&ContextSave,
SwReadMemory,
SwFunctionTableAccess,
NULL,
NULL
)) {
LLUnlock( hthd );
return xosdNone;
}
LLUnlock( hthd );
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
--*/
{
LPTHD lpthd;
HTHD hthd;
HPRC hprc = ValidHprcFromHpid(hpid);
if (!hprc) {
return xosdInvalidProc;
}
hthd = HthdFromHtid(hprc, htid);
if (hthd == hthdNull) {
return xosdInvalidThread;
}
lpthd = LLLock( hthd );
assert(lpthd != NULL);
if (StackWalk( IMAGE_FILE_MACHINE_ALPHA,
hpid,
htid,
lpstkframe,
&ContextSave,
SwReadMemory,
SwFunctionTableAccess,
NULL,
NULL
)) {
LLUnlock( hthd );
return xosdNone;
}
LLUnlock( hthd );
return xosdEndOfStack;
} /* StackWalkNext() */
PIMAGE_RUNTIME_FUNCTION_ENTRY
LookupFunctionEntry (
PIMAGE_RUNTIME_FUNCTION_ENTRY FunctionTable,
DWORD NumberOfFunctions,
DWORD ControlPc
)
/*++
Routine Description:
This function searches the currently active function tables for an entry
that corresponds to the specified PC value.
Arguments:
ControlPc - Supplies the address of an instruction within the specified
function.
Return Value:
If there is no entry in the function table for the specified PC, then
NULL is returned. Otherwise, the address of the function table entry
that corresponds to the specified PC is returned.
--*/
{
PIMAGE_RUNTIME_FUNCTION_ENTRY FunctionEntry;
LONG High;
LONG Low;
LONG Middle;
//
// Initialize search indicies.
//
Low = 0;
High = NumberOfFunctions - 1;
//
// Perform binary search on the function table for a function table
// entry that subsumes the specified PC.
//
while (High >= Low) {
//
// Compute next probe index and test entry. If the specified PC
// is greater than of equal to the beginning address and less
// than the ending address of the function table entry, then
// return the address of the function table entry. Otherwise,
// continue the search.
//
Middle = (Low + High) >> 1;
FunctionEntry = &FunctionTable[Middle];
if (ControlPc < FunctionEntry->BeginAddress) {
High = Middle - 1;
} else if (ControlPc >= FunctionEntry->EndAddress) {
Low = Middle + 1;
} else {
return FunctionEntry;
}
}
//
// A function table entry for the specified PC was not found.
//
return NULL;
}
LPVOID
SwFunctionTableAccess(
HPID hpid,
DWORD AddrBase
)
{
HLLI hlli = 0;
HMDI hmdi = 0;
LPMDI lpmdi = 0;
PIMAGE_RUNTIME_FUNCTION_ENTRY rf;
hmdi = SwGetMdi( hpid, AddrBase );
if (!hmdi) {
return NULL;
}
lpmdi = LLLock( hmdi );
if (lpmdi) {
rf = LookupFunctionEntry( lpmdi->lpDebug->lpRtf,
lpmdi->lpDebug->cRtf,
AddrBase
);
LLUnlock( hmdi );
return (LPVOID)rf;
}
return NULL;
}
BOOL
SwReadMemory(
HPID hpid,
LPCVOID lpBaseAddress,
LPVOID lpBuffer,
DWORD nSize,
LPDWORD lpNumberOfBytesRead
)
{
ADDR addr;
DWORD cb;
XOSD xosd;
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 fill in the FRAME structure.
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
--*/
{
LARGE_INTEGER ul;
GetRegValue( hpid, htid, CV_ALPHA_IntSP, &ul);
FrameFlat ( *pframe ) = TRUE;
FrameOff32 ( *pframe ) = TRUE;
FrameReal (*pframe ) = FALSE;
SetFrameBPOff( *pframe, ul.LowPart );
SetFrameBPSeg( *pframe, 0);
pframe->SS = 0;
pframe->DS = 0;
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
--*/
{
XOSD xosd = xosdNone;
PIMAGE_RUNTIME_FUNCTION_ENTRY pfe;
pfe = SwFunctionTableAccess( hpid, GetAddrOff( *Addr ) );
if ( pfe ) {
AddrInit( &FunctionInfo->AddrStart, 0,0, pfe->BeginAddress,
TRUE, TRUE, FALSE, FALSE );
AddrInit( &FunctionInfo->AddrEnd, 0,0, pfe->EndAddress,
TRUE, TRUE, FALSE, FALSE );
AddrInit( &FunctionInfo->AddrPrologEnd, 0,0, (pfe->PrologEndAddress & ~0x3),
TRUE, TRUE, FALSE, FALSE );
} else {
xosd = xosdUnknown;
}
return xosd;
}