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.
1233 lines
28 KiB
1233 lines
28 KiB
/*++
|
|
|
|
Copyright (c) 1992 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
emdp3.c
|
|
|
|
Abstract:
|
|
|
|
This file contains the some of the machine independent portions of the
|
|
execution model. The machine dependent portions are in other files.
|
|
|
|
Author:
|
|
|
|
Kent Forschmiedt (kentf) 11-8-93
|
|
|
|
Environment:
|
|
|
|
Win32 -- User
|
|
|
|
Notes:
|
|
|
|
The orginal source for this came from the CodeView group.
|
|
|
|
--*/
|
|
|
|
extern RD Rgrd[];
|
|
extern const unsigned CRgrd;
|
|
extern struct RGFD Rgfd[];
|
|
extern const unsigned CRgfd;
|
|
|
|
//
|
|
// This list is only used when there is no DM present. Whenever an
|
|
// hpid is created, the real list is obtained from the DM and stored
|
|
// in a list bound to the hprc.
|
|
//
|
|
static EXCEPTION_DESCRIPTION DefaultExceptionList[] = {
|
|
{EXCEPTION_ACCESS_VIOLATION, efdStop, "Access Violation"},
|
|
{EXCEPTION_DATATYPE_MISALIGNMENT, efdStop, "Data Misalignment"},
|
|
{EXCEPTION_ARRAY_BOUNDS_EXCEEDED, efdStop, "Array Bounds Exceeded"},
|
|
{EXCEPTION_FLT_DENORMAL_OPERAND, efdStop, "FP Denormal Operand"},
|
|
{EXCEPTION_FLT_DIVIDE_BY_ZERO, efdStop, "FP Divide by Zero"},
|
|
{EXCEPTION_FLT_INEXACT_RESULT, efdStop, "FP Inexact Result"},
|
|
{EXCEPTION_FLT_INVALID_OPERATION, efdStop, "FP Invalid Operation"},
|
|
{EXCEPTION_FLT_OVERFLOW, efdStop, "FP Overflow"},
|
|
{EXCEPTION_FLT_STACK_CHECK, efdStop, "FP Stack Check"},
|
|
{EXCEPTION_FLT_UNDERFLOW, efdStop, "FP Underflow"},
|
|
{EXCEPTION_INT_DIVIDE_BY_ZERO, efdStop, "Int Divide by zero"},
|
|
{EXCEPTION_INT_OVERFLOW, efdStop, "Int Overflow"},
|
|
{EXCEPTION_PRIV_INSTRUCTION, efdStop, "Insufficient Privilege"},
|
|
{EXCEPTION_IN_PAGE_ERROR, efdStop, "I/O Error in Paging"},
|
|
{EXCEPTION_ILLEGAL_INSTRUCTION, efdStop, "Illegal Instruction"},
|
|
{EXCEPTION_NONCONTINUABLE_EXCEPTION,efdStop, "Noncontinuable Exception"},
|
|
{EXCEPTION_STACK_OVERFLOW, efdStop, "Stack Overflow"},
|
|
{EXCEPTION_INVALID_DISPOSITION, efdStop, "Invalid Disposition"},
|
|
{RPC_S_OUT_OF_RESOURCES, efdNotify, "RPC Out Of Resources"},
|
|
{RPC_S_SERVER_UNAVAILABLE, efdNotify, "RPC Server Unavailable"},
|
|
{RPC_S_SERVER_TOO_BUSY, efdNotify, "RPC Server Too Busy"},
|
|
{DBG_CONTROL_C, efdStop, "Control-C break"},
|
|
{0xE06d7363, efdNotify, "Microsoft C++ EH Exception"},
|
|
{(DWORD)STATUS_NO_MEMORY, efdStop, "No Memory"},
|
|
{(DWORD)NULL, efdStop, "Unknown"},
|
|
};
|
|
|
|
|
|
XOSD
|
|
HandleBreakpoints(
|
|
HPID hpid,
|
|
DWORD wValue,
|
|
LONG lValue
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
LPBPS lpbps = (LPBPS) lValue;
|
|
LPDBB lpdbb = malloc(sizeof(DBB) + wValue);
|
|
|
|
// let the DM handle everything?
|
|
lpdbb->hpid = hpid;
|
|
lpdbb->htid = NULL;
|
|
lpdbb->dmf = dmfBreakpoint;
|
|
memcpy(lpdbb->rgbVar, lpbps, wValue);
|
|
CallTL ( tlfRequest, hpid, sizeof ( DBB ) + wValue, (LPVOID)lpdbb );
|
|
if (LpDmMsg->xosdRet == xosdNone) {
|
|
memcpy(DwNotification(lpbps),
|
|
DwNotification( (LPBPS)(LpDmMsg->rgb) ),
|
|
lpbps->cbpis * sizeof(DWORD));
|
|
}
|
|
return LpDmMsg->xosdRet;
|
|
}
|
|
|
|
|
|
XOSD
|
|
Go (
|
|
HPID hpid,
|
|
HTID htid,
|
|
LPEXOP lpexop
|
|
)
|
|
{
|
|
UpdateChild ( hpid, htid, dmfGo );
|
|
return SendRequestX(dmfGo, hpid, htid, sizeof(EXOP), lpexop);
|
|
}
|
|
|
|
#if 0
|
|
|
|
XOSD
|
|
ReturnStep (
|
|
HPID hpid,
|
|
HTID htid,
|
|
LPEXOP lpexop
|
|
)
|
|
{
|
|
HTHD hthd;
|
|
HPRC hprc = ValidHprcFromHpid(hpid);
|
|
RTRNSTP rtrnstp;
|
|
XOSD xosd = xosdNone;
|
|
HTID vhtid = htid;
|
|
|
|
if (!hprc) {
|
|
return xosdInvalidProc;
|
|
}
|
|
if ( (hthd = HthdFromHtid(hprc, htid)) == hthdInvalid || hthd == NULL ) {
|
|
return xosdInvalidThread;
|
|
}
|
|
rtrnstp.exop = *lpexop;
|
|
if ((((DWORD)htid) & 1) == 0) {
|
|
xosd = DoGetFrame( hpid, vhtid, 1, (DWORD)&vhtid );
|
|
}
|
|
if ( xosd == xosdNone ) {
|
|
xosd = DoGetFrame( hpid, vhtid, 1, (DWORD)&vhtid );
|
|
if ( xosd == xosdNone ) {
|
|
xosd = GetAddr( hpid, vhtid, adrPC, &(rtrnstp.addrRA) );
|
|
}
|
|
}
|
|
if ( xosd != xosdNone ) {
|
|
return( xosd );
|
|
}
|
|
return SendRequestX ( dmfReturnStep, hpid, htid, sizeof(rtrnstp), &rtrnstp);
|
|
|
|
}
|
|
#endif
|
|
|
|
|
|
XOSD
|
|
ThreadStatus (
|
|
HPID hpid,
|
|
HTID htid,
|
|
LPTST lptst
|
|
)
|
|
{
|
|
XOSD xosd = SendRequest ( dmfThreadStatus, hpid, htid );
|
|
if (xosd == xosdNone) {
|
|
xosd = LpDmMsg->xosdRet;
|
|
}
|
|
if (xosd == xosdNone) {
|
|
memcpy(lptst, LpDmMsg->rgb, sizeof(TST));
|
|
}
|
|
return xosd;
|
|
}
|
|
|
|
|
|
XOSD
|
|
ProcessStatus(
|
|
HPID hpid,
|
|
LPPST lppst
|
|
)
|
|
{
|
|
XOSD xosd;
|
|
xosd = SendRequest(dmfProcessStatus, hpid, NULL );
|
|
if (xosd == xosdNone) {
|
|
xosd = LpDmMsg->xosdRet;
|
|
}
|
|
if (xosd == xosdNone) {
|
|
memcpy(lppst, LpDmMsg->rgb, sizeof(PST));
|
|
}
|
|
return xosd;
|
|
}
|
|
|
|
#ifdef OSDEBUG4
|
|
|
|
|
|
XOSD
|
|
Freeze (
|
|
HPID hpid,
|
|
HTID htid
|
|
)
|
|
{
|
|
HTHD hthd;
|
|
HPRC hprc = ValidHprcFromHpid(hpid);
|
|
if (!hprc) {
|
|
return xosdBadProcess;
|
|
}
|
|
if ( (hthd = HthdFromHtid(hprc, htid)) == hthdInvalid || hthd == NULL ) {
|
|
return xosdBadThread;
|
|
}
|
|
|
|
SendRequest ( dmfFreeze, hpid, htid);
|
|
|
|
return LpDmMsg->xosdRet;
|
|
}
|
|
|
|
|
|
XOSD
|
|
Thaw (
|
|
HPID hpid,
|
|
HTID htid
|
|
)
|
|
{
|
|
HTHD hthd;
|
|
HPRC hprc = ValidHprcFromHpid(hpid);
|
|
if (!hprc) {
|
|
return xosdBadProcess;
|
|
}
|
|
if ( (hthd = HthdFromHtid(hprc, htid)) == hthdInvalid || hthd == NULL ) {
|
|
return xosdBadThread;
|
|
}
|
|
|
|
SendRequest ( dmfResume, hpid, htid);
|
|
|
|
return LpDmMsg->xosdRet;
|
|
}
|
|
|
|
#endif
|
|
|
|
XOSD
|
|
DebugMetric (
|
|
HPID hpid,
|
|
HTID htid,
|
|
MTRC mtrc,
|
|
LPLONG lpl
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
The debugger queries this function to find out the size of OS and machine
|
|
dependent values, e.g. the size of a process ID.
|
|
|
|
Arguments:
|
|
|
|
hpid
|
|
|
|
htid
|
|
|
|
mtrc - metric identifier
|
|
|
|
lpl - answer buffer
|
|
|
|
Return Value:
|
|
|
|
xosdNone if the request succeeded, xosd error code otherwise.
|
|
|
|
--*/
|
|
{
|
|
HPRC hprc;
|
|
LPPRC lpprc = NULL;
|
|
XOSD xosd = xosdNone;
|
|
|
|
hprc = HprcFromHpid(hpid);
|
|
|
|
if (hprc) {
|
|
|
|
lpprc = LLLock( hprc );
|
|
assert( lpprc );
|
|
|
|
switch ( mtrc ) {
|
|
|
|
default:
|
|
break;
|
|
|
|
//
|
|
// Invalidate cache for some items:
|
|
//
|
|
case mtrcProcessorType:
|
|
case mtrcProcessorLevel:
|
|
case mtrcOSVersion:
|
|
lpprc->fDmiCache = FALSE;
|
|
|
|
case mtrcEndian:
|
|
case mtrcThreads:
|
|
case mtrcAsync:
|
|
case mtrcAsyncStop:
|
|
case mtrcBreakPoints:
|
|
case mtrcReturnStep:
|
|
case mtrcRemote:
|
|
if (!lpprc->fDmiCache) {
|
|
xosd = SendRequest ( dmfGetDmInfo, hpid, htid );
|
|
if (xosd == xosdNone) {
|
|
memcpy(&lpprc->dmi, LpDmMsg->rgb, sizeof(DMINFO));
|
|
lpprc->fDmiCache = TRUE;
|
|
}
|
|
}
|
|
break;
|
|
|
|
}
|
|
|
|
if (xosd != xosdNone) {
|
|
LLUnlock( hprc );
|
|
return xosd;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
switch ( mtrc ) {
|
|
|
|
default:
|
|
assert(FALSE);
|
|
xosd = xosdInvalidParameter;
|
|
break;
|
|
|
|
case mtrcProcessorType:
|
|
|
|
assert(lpprc);
|
|
*lpl = lpprc->dmi.Processor.Type;
|
|
break;
|
|
|
|
case mtrcProcessorLevel:
|
|
|
|
assert(lpprc);
|
|
*lpl = lpprc->dmi.Processor.Level;
|
|
break;
|
|
|
|
case mtrcEndian:
|
|
|
|
assert(lpprc);
|
|
*lpl = lpprc->dmi.Processor.Endian;
|
|
break;
|
|
|
|
case mtrcThreads:
|
|
|
|
assert(lpprc);
|
|
*lpl = lpprc->dmi.fHasThreads;
|
|
break;
|
|
|
|
case mtrcCRegs:
|
|
|
|
*lpl = CRgrd;
|
|
break;
|
|
|
|
case mtrcCFlags:
|
|
|
|
*lpl = CRgfd;
|
|
break;
|
|
|
|
case mtrcExtRegs:
|
|
|
|
assert(0 && "do something with this");
|
|
break;
|
|
|
|
case mtrcExtFP:
|
|
|
|
assert(0 && "do something with this");
|
|
break;
|
|
|
|
case mtrcExtMMU:
|
|
|
|
assert(0 && "do something with this");
|
|
break;
|
|
|
|
case mtrcExceptionHandling:
|
|
|
|
*( (LPDWORD) lpl) = TRUE;
|
|
break;
|
|
|
|
case mtrcAssembler:
|
|
|
|
#if defined(TARGET_i386)
|
|
*( (LPDWORD) lpl) = TRUE;
|
|
#elif defined(TARGET_PPC)
|
|
*( (LPDWORD) lpl) = FALSE;
|
|
#elif defined(TARGET_MIPS)
|
|
*( (LPDWORD) lpl) = FALSE;
|
|
#elif defined(TARGET_ALPHA)
|
|
*( (LPDWORD) lpl) = TRUE;
|
|
#else
|
|
#error "Unknown CPU type"
|
|
#endif
|
|
break;
|
|
|
|
case mtrcAsync:
|
|
|
|
assert(lpprc);
|
|
*lpl = lpprc->dmi.fAsync;
|
|
break;
|
|
|
|
case mtrcAsyncStop:
|
|
|
|
assert(lpprc);
|
|
*lpl = lpprc->dmi.fAsyncStop;
|
|
break;
|
|
|
|
case mtrcBreakPoints:
|
|
|
|
assert(lpprc);
|
|
//
|
|
// Message BPs are implemented in the EM
|
|
// on top of the exec BP implemented by the DM.
|
|
//
|
|
*lpl = lpprc->dmi.Breakpoints |
|
|
bptsMessage |
|
|
bptsMClass;
|
|
break;
|
|
|
|
case mtrcReturnStep:
|
|
|
|
assert(lpprc);
|
|
*lpl = lpprc->dmi.fReturnStep;
|
|
break;
|
|
|
|
case mtrcShowDebuggee:
|
|
|
|
*lpl = FALSE;
|
|
break;
|
|
|
|
case mtrcHardSoftMode:
|
|
|
|
*lpl = FALSE;
|
|
break;
|
|
|
|
case mtrcRemote:
|
|
|
|
assert(lpprc);
|
|
*lpl = lpprc->dmi.fRemote;
|
|
break;
|
|
|
|
case mtrcOleRpc:
|
|
|
|
*lpl = FALSE;
|
|
break;
|
|
|
|
case mtrcNativeDebugger:
|
|
|
|
*lpl = FALSE;
|
|
break;
|
|
|
|
case mtrcOSVersion:
|
|
|
|
*lpl = MAKELONG( lpprc->dmi.MinorVersion, lpprc->dmi.MajorVersion );
|
|
break;
|
|
|
|
case mtrcMultInstances:
|
|
|
|
*(BOOL*) lpl = TRUE;
|
|
break;
|
|
}
|
|
|
|
LLUnlock( hprc );
|
|
|
|
return xosdNone;
|
|
}
|
|
|
|
|
|
|
|
XOSD
|
|
FakeGetExceptionState(
|
|
EXCEPTION_CONTROL exc,
|
|
LPEXCEPTION_DESCRIPTION lpexd
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Handle the GetExceptionState call when there is no DM connected.
|
|
|
|
Arguments:
|
|
|
|
exc - Supplies exfFirst, exfSpecified or exfNext
|
|
|
|
lpexd - Returns EXCEPTION_DESCRIPTION record
|
|
|
|
Return Value:
|
|
|
|
xosdNone except when exc is exfNext and lpexd->dwExceptionCode
|
|
was not in the list.
|
|
|
|
--*/
|
|
{
|
|
DWORD dwT;
|
|
int i;
|
|
|
|
if (exc == exfFirst) {
|
|
*lpexd = DefaultExceptionList[0];
|
|
return xosdNone;
|
|
}
|
|
|
|
for (i = 0; DefaultExceptionList[i].dwExceptionCode != 0; i++) {
|
|
if (DefaultExceptionList[i].dwExceptionCode == lpexd->dwExceptionCode) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (exc == exfSpecified) {
|
|
dwT = lpexd->dwExceptionCode;
|
|
*lpexd = DefaultExceptionList[i];
|
|
lpexd->dwExceptionCode = dwT;
|
|
return xosdNone;
|
|
}
|
|
|
|
if (DefaultExceptionList[i].dwExceptionCode != 0) {
|
|
*lpexd = DefaultExceptionList[++i];
|
|
return xosdNone;
|
|
}
|
|
|
|
return xosdInvalidParameter;
|
|
}
|
|
|
|
|
|
XOSD
|
|
GetExceptionState(
|
|
HPID hpid,
|
|
HTID htid,
|
|
EXCEPTION_CONTROL exc,
|
|
LPEXCEPTION_DESCRIPTION lpexd
|
|
)
|
|
{
|
|
HPRC hprc;
|
|
LPPRC lpprc;
|
|
XOSD xosd = xosdNone;
|
|
HEXD hexd;
|
|
|
|
if (!hpid) {
|
|
return FakeGetExceptionState(exc, lpexd);
|
|
}
|
|
|
|
hprc = HprcFromHpid( hpid );
|
|
assert(hprc);
|
|
lpprc = LLLock(hprc);
|
|
|
|
switch (exc) {
|
|
|
|
default:
|
|
assert( 0 && "Invalid arg to em!GetExceptionState" );
|
|
xosd = xosdInvalidParameter;
|
|
break;
|
|
|
|
case exfFirst:
|
|
|
|
hexd = LLNext( lpprc->llexc, NULL );
|
|
if (!hexd) {
|
|
// get the default exception record
|
|
DWORD dwT = 0;
|
|
hexd = LLFind( lpprc->llexc, NULL, &dwT, 0 );
|
|
}
|
|
if (!hexd) {
|
|
memset(lpexd, 0, sizeof(EXCEPTION_DESCRIPTION));
|
|
}
|
|
else {
|
|
*lpexd = *(LPEXCEPTION_DESCRIPTION)LLLock(hexd);
|
|
LLUnlock(hexd);
|
|
}
|
|
break;
|
|
|
|
|
|
case exfSpecified:
|
|
|
|
hexd = LLFind( lpprc->llexc, NULL, &lpexd->dwExceptionCode, 0 );
|
|
if (!hexd) {
|
|
// get the default exception record
|
|
DWORD dwT = 0;
|
|
hexd = LLFind( lpprc->llexc, NULL, &dwT, 0 );
|
|
}
|
|
if (!hexd) {
|
|
memset(lpexd, 0, sizeof(EXCEPTION_DESCRIPTION));
|
|
xosd = xosdInvalidParameter;
|
|
}
|
|
else {
|
|
*lpexd = *(LPEXCEPTION_DESCRIPTION)LLLock(hexd);
|
|
LLUnlock(hexd);
|
|
}
|
|
break;
|
|
|
|
|
|
case exfNext:
|
|
|
|
hexd = LLFind( lpprc->llexc, NULL, &lpexd->dwExceptionCode, 0 );
|
|
if (!hexd) {
|
|
//
|
|
// origin must exist
|
|
//
|
|
xosd = xosdInvalidParameter;
|
|
} else {
|
|
//
|
|
// but the next one need not
|
|
//
|
|
hexd = LLNext( lpprc->llexc, hexd );
|
|
if (!hexd) {
|
|
memset(lpexd, 0, sizeof(EXCEPTION_DESCRIPTION));
|
|
xosd = xosdEndOfStack;
|
|
} else {
|
|
*lpexd = *(LPEXCEPTION_DESCRIPTION)LLLock(hexd);
|
|
LLUnlock(hexd);
|
|
}
|
|
}
|
|
break;
|
|
|
|
}
|
|
|
|
LLUnlock(hprc);
|
|
return xosd;
|
|
}
|
|
|
|
|
|
XOSD
|
|
SetExceptionState(
|
|
HPID hpid,
|
|
HTID htid,
|
|
LPEXCEPTION_DESCRIPTION lpexd
|
|
)
|
|
{
|
|
HPRC hprc = HprcFromHpid( hpid );
|
|
HLLI llexc;
|
|
HEXD hexd;
|
|
|
|
assert(lpexd->efd == efdIgnore ||
|
|
lpexd->efd == efdNotify ||
|
|
lpexd->efd == efdCommand ||
|
|
lpexd->efd == efdStop);
|
|
|
|
if (!hprc) {
|
|
return xosdInvalidProc;
|
|
}
|
|
|
|
llexc = ((LPPRC)LLLock(hprc))->llexc;
|
|
LLUnlock(hprc);
|
|
|
|
hexd = LLFind( llexc, NULL, &lpexd->dwExceptionCode, 0 );
|
|
|
|
if (!hexd) {
|
|
hexd = LLCreate( llexc );
|
|
if (!hexd) {
|
|
return xosdOutOfMemory;
|
|
}
|
|
LLAdd( llexc, hexd );
|
|
}
|
|
|
|
*(LPEXCEPTION_DESCRIPTION)LLLock(hexd) = *lpexd;
|
|
LLUnlock(hexd);
|
|
|
|
return SendRequestX( dmfSetExceptionState, hpid, htid,
|
|
sizeof(EXCEPTION_DESCRIPTION), lpexd);
|
|
}
|
|
|
|
#ifdef OSDEBUG4
|
|
|
|
XOSD
|
|
GetMemoryInfo(
|
|
HPID hpid,
|
|
HTID htid,
|
|
LPMEMINFO lpmi
|
|
)
|
|
{
|
|
PMEMORY_BASIC_INFORMATION lpmbi;
|
|
ADDR addr;
|
|
XOSD xosd = xosdNone;
|
|
|
|
Unreferenced(htid);
|
|
|
|
addr = lpmi->addr;
|
|
|
|
if (ADDR_IS_LI(addr)) {
|
|
xosd = FixupAddr(hpid, &addr);
|
|
}
|
|
|
|
if (xosd == xosdNone) {
|
|
xosd = SendRequestX( dmfVirtualQuery, hpid, 0, sizeof(ADDR),
|
|
(LPVOID)&addr );
|
|
}
|
|
|
|
if (xosd == xosdNone) {
|
|
lpmbi = (PMEMORY_BASIC_INFORMATION) LpDmMsg->rgb;
|
|
lpmi->addrAllocBase = addr;
|
|
lpmi->addrAllocBase.addr.off = (UOFF32)lpmbi->AllocationBase;
|
|
lpmi->uRegionSize = (UOFF32)lpmbi->RegionSize;
|
|
lpmi->dwProtect = lpmbi->Protect;
|
|
lpmi->dwState = lpmbi->State;
|
|
lpmi->dwType = lpmbi->Type;
|
|
}
|
|
|
|
return xosd;
|
|
}
|
|
|
|
|
|
XOSD
|
|
FreezeThread(
|
|
HPID hpid,
|
|
HTID htid,
|
|
BOOL fFreeze
|
|
)
|
|
{
|
|
HTHD hthd;
|
|
HPRC hprc = ValidHprcFromHpid(hpid);
|
|
if (!hprc) {
|
|
return xosdBadProcess;
|
|
}
|
|
if ( (hthd = HthdFromHtid(hprc, htid)) == hthdInvalid || hthd == NULL ) {
|
|
return xosdBadThread;
|
|
}
|
|
|
|
if (fFreeze) {
|
|
SendRequest ( dmfFreeze, hpid, htid);
|
|
} else {
|
|
SendRequest ( dmfResume, hpid, htid);
|
|
}
|
|
|
|
return LpDmMsg->xosdRet;
|
|
}
|
|
|
|
|
|
|
|
#define FreeModuleList(m) free(m)
|
|
#define ModuleListCount(m) ((m)->Count)
|
|
#define FirstModuleEntry(m) ((LPMODULE_ENTRY)((m)+1))
|
|
#define NextModuleEntry(e) ((e)+1)
|
|
#define NthModuleEntry(m,n) (FirstModuleEntry(m)+(n))
|
|
|
|
#define ModuleEntryFlat(e) ((e)->Flat)
|
|
#define ModuleEntryReal(e) ((e)->Real)
|
|
#define ModuleEntrySegment(e) ((e)->Segment)
|
|
#define ModuleEntrySelector(e) ((e)->Selector)
|
|
#define ModuleEntryBase(e) ((e)->Base)
|
|
#define ModuleEntryLimit(e) ((e)->Limit)
|
|
#define ModuleEntryType(e) ((e)->Type)
|
|
#define ModuleEntrySectionCount(e) ((e)->SectionCount)
|
|
#define ModuleEntryName(e) ((e)->Name)
|
|
|
|
|
|
XOSD
|
|
GetModuleList(
|
|
HPID hpid,
|
|
HTID htid,
|
|
LPSTR lpModuleName,
|
|
LPMODULE_LIST FAR * lplpModuleList
|
|
)
|
|
{
|
|
XOSD xosd = xosdNone;
|
|
HLLI llmdi;
|
|
HMDI hmdi;
|
|
LPMDI lpmdi;
|
|
DWORD Count;
|
|
LPMODULE_LIST ModList;
|
|
LPMODULE_LIST TmpList;
|
|
LPMODULE_ENTRY Entry;
|
|
LDT_ENTRY Ldt;
|
|
DWORD MaxSize;
|
|
DWORD Delta;
|
|
DWORD i;
|
|
SEGMENT Selector;
|
|
DWORD Base;
|
|
DWORD Limit;
|
|
OBJD *ObjD;
|
|
char *p;
|
|
char WantedName[ MAX_PATH ];
|
|
char WantedExt[ MAX_PATH ];
|
|
char ModName[ MAX_PATH ];
|
|
char ModExt[ MAX_PATH ];
|
|
char Name[ MAX_PATH ];
|
|
|
|
*WantedName = '\0';
|
|
*WantedExt = '\0';
|
|
|
|
if ( !lplpModuleList ) {
|
|
xosd = xosdInvalidParameter;
|
|
goto Done;
|
|
}
|
|
|
|
*lplpModuleList = NULL;
|
|
|
|
llmdi = LlmdiFromHprc( HprcFromHpid ( hpid ));
|
|
|
|
if ( !llmdi ) {
|
|
xosd = xosdBadProcess;
|
|
goto Done;
|
|
}
|
|
|
|
|
|
//
|
|
// Estimate the list size, to minimize the calls to realloc.
|
|
//
|
|
if ( lpModuleName ) {
|
|
|
|
Count = 20;
|
|
_splitpath( lpModuleName, NULL, NULL, WantedName, WantedExt );
|
|
|
|
} else {
|
|
|
|
hmdi = hmdiNull;
|
|
Count = 0;
|
|
|
|
while ( (hmdi = LLNext( llmdi, hmdi )) != hmdiNull ) {
|
|
lpmdi = LLLock( hmdi );
|
|
Count += lpmdi->fFlatMode ? 1 : lpmdi->cobj;
|
|
LLUnlock( hmdi );
|
|
}
|
|
}
|
|
|
|
//
|
|
// Allocate the list
|
|
//
|
|
MaxSize = sizeof(MODULE_LIST) + Count * sizeof(MODULE_ENTRY);
|
|
|
|
ModList = MHAlloc( MaxSize );
|
|
|
|
if ( !ModList ) {
|
|
xosd = xosdOutOfMemory;
|
|
goto Done;
|
|
}
|
|
|
|
//
|
|
// Build the list
|
|
//
|
|
Count = 0;
|
|
|
|
for ( hmdi = NULL; (hmdi = LLNext( llmdi, hmdi )); LLUnlock( hmdi ) ) {
|
|
|
|
lpmdi = LLLock( hmdi );
|
|
|
|
//
|
|
// Get the module name
|
|
//
|
|
p = (*(lpmdi->lszName) == '|') ? lpmdi->lszName+1 : lpmdi->lszName;
|
|
strcpy( Name, p );
|
|
p = strchr( Name, '|' );
|
|
if ( p ) {
|
|
*p = '\0';
|
|
}
|
|
|
|
if ( lpModuleName ) {
|
|
|
|
//
|
|
// Add if base name matches
|
|
//
|
|
_splitpath( Name, NULL, NULL, ModName, ModExt );
|
|
|
|
if (_stricmp(WantedName, ModName) || _stricmp(WantedExt, ModExt) ) {
|
|
continue;
|
|
}
|
|
}
|
|
|
|
Delta = lpmdi->fFlatMode ? 1 : lpmdi->cobj;
|
|
|
|
//
|
|
// Reallocate buffer if necessary
|
|
//
|
|
if ( (Count + Delta) * sizeof(MODULE_ENTRY) > MaxSize ) {
|
|
|
|
MaxSize += Delta * sizeof(MODULE_ENTRY);
|
|
TmpList = realloc( ModList, MaxSize );
|
|
if ( !TmpList ) {
|
|
FreeModuleList(ModList);
|
|
xosd = xosdOutOfMemory;
|
|
break;
|
|
}
|
|
|
|
ModList = TmpList;
|
|
}
|
|
|
|
//
|
|
// have buffer, fill it up
|
|
//
|
|
if ( lpmdi->fFlatMode ) {
|
|
|
|
Entry = NthModuleEntry(ModList,Count);
|
|
|
|
ModuleEntryFlat(Entry) = TRUE;
|
|
ModuleEntrySegment(Entry) = 0;
|
|
ModuleEntrySelector(Entry) = 0;
|
|
ModuleEntryBase(Entry) = lpmdi->lpBaseOfDll;
|
|
ModuleEntryLimit(Entry) = 0;
|
|
ModuleEntryType(Entry) = 0;
|
|
ModuleEntrySectionCount(Entry) = lpmdi->cobj;
|
|
strcpy(ModuleEntryName(Entry), Name);
|
|
|
|
Count++;
|
|
|
|
} else {
|
|
|
|
for ( i=0, ObjD = lpmdi->rgobjd; i < Delta; i++, ObjD++ ) {
|
|
|
|
if ( ObjD->wSel ) {
|
|
|
|
Selector = ObjD->wSel;
|
|
|
|
Entry = NthModuleEntry(ModList,Count);
|
|
|
|
ModuleEntrySegment(Entry) = i+1;
|
|
ModuleEntrySelector(Entry) = Selector;
|
|
ModuleEntryType(Entry) = 0;
|
|
ModuleEntrySectionCount(Entry) = 0;
|
|
|
|
strcpy(ModuleEntryName(Entry), Name);
|
|
|
|
if ( lpmdi->fRealMode ) {
|
|
|
|
xosd = xosdNone;
|
|
|
|
ModuleEntryFlat(Entry) = FALSE;
|
|
ModuleEntryReal(Entry) = TRUE;
|
|
ModuleEntryBase(Entry) = 0xBAD00BAD;
|
|
ModuleEntryLimit(Entry) = 0xBAD00BAD;
|
|
|
|
Count++;
|
|
|
|
} else {
|
|
|
|
xosd = SendRequestX( dmfQuerySelector,
|
|
hpid,
|
|
NULL,
|
|
sizeof(SEGMENT),
|
|
&Selector );
|
|
|
|
if (xosd == xosdNone) {
|
|
|
|
|
|
_fmemcpy( &Ldt, LpDmMsg->rgb, sizeof(Ldt));
|
|
|
|
Base = (Ldt.HighWord.Bits.BaseHi << 0x18) |
|
|
(Ldt.HighWord.Bits.BaseMid << 0x10) |
|
|
Ldt.BaseLow;
|
|
|
|
Limit = (Ldt.HighWord.Bits.LimitHi << 0x10) |
|
|
Ldt.LimitLow;
|
|
|
|
ModuleEntryFlat(Entry) = FALSE;
|
|
ModuleEntryReal(Entry) = FALSE;
|
|
ModuleEntryBase(Entry) = Base;
|
|
ModuleEntryLimit(Entry) = Limit;
|
|
|
|
Count++;
|
|
|
|
} else {
|
|
|
|
xosd = xosdNone;
|
|
|
|
ModuleEntryFlat(Entry) = FALSE;
|
|
ModuleEntryReal(Entry) = FALSE;
|
|
ModuleEntryBase(Entry) = 0xBAD00BAD;
|
|
ModuleEntryLimit(Entry) = 0xBAD00BAD;
|
|
Count++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (hmdi) {
|
|
LLUnlock(hmdi);
|
|
}
|
|
|
|
ModuleListCount(ModList) = Count;
|
|
*lplpModuleList = ModList;
|
|
|
|
Done:
|
|
return xosd;
|
|
}
|
|
|
|
|
|
XOSD
|
|
DoContinue(
|
|
HPID hpid
|
|
)
|
|
{
|
|
LPPRC lpprc;
|
|
HPRC hprc = HprcFromHpid(hpid);
|
|
XOSD xosd = xosdUnknown;
|
|
BYTE b = 1;
|
|
|
|
assert(hprc);
|
|
|
|
lpprc = LLLock(hprc);
|
|
|
|
if (lpprc->fLoadingModule) {
|
|
|
|
lpprc->fRunning = TRUE;
|
|
lpprc->fLoadingModule = FALSE;
|
|
CallTL ( tlfReply, hpid, 1, &b );
|
|
xosd = xosdNone;
|
|
|
|
} else if (lpprc->fUnloadingModule) {
|
|
|
|
lpprc->fRunning = TRUE;
|
|
lpprc->fUnloadingModule = FALSE;
|
|
CallTL ( tlfReply, hpid, 1, &b );
|
|
xosd = xosdNone;
|
|
}
|
|
|
|
LLUnlock(hprc);
|
|
|
|
return xosd;
|
|
}
|
|
|
|
|
|
XOSD
|
|
DoCustomCommand(
|
|
HPID hpid,
|
|
HTID htid,
|
|
DWORD wValue,
|
|
LPSSS lpsss
|
|
)
|
|
{
|
|
LPSTR lpsz = lpsss->rgbData;
|
|
LPSTR p;
|
|
XOSD xosd;
|
|
char cmd[256];
|
|
|
|
//
|
|
// parse the command from the command line
|
|
//
|
|
p = cmd;
|
|
while (*lpsz && !isspace(*lpsz)) {
|
|
*p++ = *lpsz++;
|
|
}
|
|
*p = '\0';
|
|
|
|
//
|
|
// this is where you would _stricmp() for your custom em command
|
|
// otherwise it is passed to the dm
|
|
//
|
|
|
|
return SendRequestX( dmfSystemService, hpid, htid, wValue, (LPVOID) lpsss );
|
|
|
|
//
|
|
// this is what would be executed if you have a custom em command
|
|
// instead of the above sendrequest()
|
|
//
|
|
|
|
#if 0
|
|
strcpy( lpiol->rgbVar, lpsz );
|
|
xosd = IoctlCmd(hpid, htid, wValue, lpiol);
|
|
|
|
return xosd;
|
|
#endif
|
|
} /* DoCustomCommand */
|
|
|
|
|
|
|
|
|
|
XOSD
|
|
SystemService(
|
|
HPID hpid,
|
|
HTID htid,
|
|
DWORD wValue,
|
|
LPSSS lpsss
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function examines SystemService requests (escapes) and deals
|
|
with those which the EM knows about. All others are passed on to
|
|
the DM for later processing.
|
|
|
|
Arguments:
|
|
|
|
argument-name - Supplies | Returns description of argument.
|
|
.
|
|
.
|
|
|
|
Return Value:
|
|
|
|
return-value - Description of conditions needed to return value. - or -
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
XOSD xosd;
|
|
DWORD dw;
|
|
HPRC hprc;
|
|
HTHD hthd;
|
|
LPTHD lpthd;
|
|
|
|
switch( lpsss-> ssvc ) {
|
|
|
|
case ssvcGetStackFrame:
|
|
hprc = HprcFromHpid( hpid );
|
|
hthd = HthdFromHtid ( hprc, htid );
|
|
assert(hthd);
|
|
lpthd = LLLock(hthd);
|
|
_fmemcpy(lpsss->rgbData, &lpthd->StackFrame, sizeof(STACKFRAME));
|
|
lpsss->cbReturned = sizeof(STACKFRAME);
|
|
xosd = xosdNone;
|
|
break;
|
|
|
|
case ssvcGetThreadContext:
|
|
xosd = SendRequest ( dmfReadReg, hpid, htid );
|
|
if (xosd == xosdNone) {
|
|
xosd = LpDmMsg->xosdRet;
|
|
dw = min(lpsss->cbSend, sizeof(CONTEXT));
|
|
_fmemcpy (lpsss->rgbData, LpDmMsg->rgb, dw);
|
|
lpsss->cbReturned = dw;
|
|
}
|
|
break;
|
|
|
|
case ssvcSetThreadContext:
|
|
xosd = SendRequestX( dmfWriteReg, hpid, htid, lpsss->cbSend,
|
|
lpsss->rgbData );
|
|
break;
|
|
|
|
case ssvcGetProcessHandle:
|
|
case ssvcGetThreadHandle:
|
|
xosd = SendRequestX(dmfSystemService,hpid, htid, wValue, (LPVOID)lpsss);
|
|
if (xosd == xosdNone) {
|
|
xosd = LpDmMsg->xosdRet;
|
|
dw = min(lpsss->cbSend, sizeof(HANDLE));
|
|
_fmemcpy (lpsss->rgbData, LpDmMsg->rgb, dw);
|
|
lpsss->cbReturned = dw;
|
|
}
|
|
break;
|
|
|
|
|
|
case ssvcCustomCommand:
|
|
xosd = DoCustomCommand(hpid, htid, wValue, lpsss);
|
|
break;
|
|
|
|
case ssvcGetPrompt:
|
|
xosd = SendRequestX(dmfSystemService, hpid, htid, wValue, (LPVOID)lpsss);
|
|
if (xosd == xosdNone) {
|
|
xosd = LpDmMsg->xosdRet;
|
|
lpsss->cbReturned = ((LPPROMPTMSG)((LPSSS)LpDmMsg->rgb))->len + sizeof(PROMPTMSG);
|
|
if (lpsss->cbReturned) {
|
|
_fmemcpy((LPVOID)lpsss->rgbData,
|
|
LpDmMsg->rgb,
|
|
lpsss->cbReturned);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case ssvcGeneric:
|
|
xosd = SendRequestX(dmfSystemService,hpid,htid,wValue,(LPVOID)lpsss);
|
|
if (xosd == xosdNone) {
|
|
xosd = LpDmMsg->xosdRet;
|
|
lpsss->cbReturned = *((LPDWORD)LpDmMsg->rgb);
|
|
if (lpsss->cbReturned) {
|
|
_fmemcpy ( (LPVOID)lpsss->rgbData,
|
|
LpDmMsg->rgb + sizeof(DWORD),
|
|
lpsss->cbReturned);
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
xosd = SendRequestX(dmfSystemService,hpid,htid,wValue,(LPVOID)lpsss);
|
|
break;
|
|
}
|
|
|
|
return xosd;
|
|
|
|
}
|
|
#endif // OSDEBUG4
|
|
|
|
XOSD
|
|
RangeStep (
|
|
HPID hpid,
|
|
HTID htid,
|
|
LPRSS lprss
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function is called to implement range steps in the EM. A range
|
|
step is defined as step all instructions as long as the program counter
|
|
remains within the starting and ending addresses.
|
|
|
|
Arguments:
|
|
|
|
hpid - Supplies the handle of the process to be stepped
|
|
htid - Supplies the handle of thread to be stepped
|
|
|
|
Return Value:
|
|
|
|
XOSD error code
|
|
|
|
--*/
|
|
|
|
{
|
|
XOSD xosd = xosdNone;
|
|
RST rst = {0};
|
|
|
|
UpdateChild ( hpid, htid, dmfRangeStep );
|
|
|
|
rst.fStepOver = lprss->lpExop->fStepOver;
|
|
rst.fAllThreads = !lprss->lpExop->fSingleThread;
|
|
rst.fInitialBP = lprss->lpExop->fInitialBP;
|
|
rst.offStart = lprss->lpaddrMin->addr.off;
|
|
rst.offEnd = lprss->lpaddrMax->addr.off;
|
|
|
|
return SendRequestX (
|
|
dmfRangeStep,
|
|
hpid,
|
|
htid,
|
|
sizeof ( RST ),
|
|
&rst
|
|
);
|
|
|
|
} /* RangeStep() */
|
|
|
|
XOSD
|
|
SingleStep (
|
|
HPID hpid,
|
|
HTID htid,
|
|
LPEXOP lpexop
|
|
)
|
|
{
|
|
assert ( hpid != NULL );
|
|
assert ( htid != NULL );
|
|
|
|
UpdateChild ( hpid, htid, dmfSingleStep );
|
|
|
|
return SendRequestX (
|
|
dmfSingleStep,
|
|
hpid,
|
|
htid,
|
|
sizeof(EXOP),
|
|
lpexop
|
|
);
|
|
}
|
|
|