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.
4293 lines
112 KiB
4293 lines
112 KiB
/*++
|
|
|
|
Copyright (c) 1993 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
Osdebug.c
|
|
|
|
Abstract:
|
|
|
|
This module implements the OSDebug API used by WinDBG.
|
|
|
|
Author:
|
|
|
|
Kent D. Forschmiedt (kentf) 06-Jul-1993
|
|
James L. Schaad (jimsch)
|
|
David W. Gray (davidgra) 15-Oct-1990
|
|
|
|
Environment:
|
|
|
|
Win32, User Mode
|
|
|
|
--*/
|
|
|
|
#include "windows.h"
|
|
#include "memory.h"
|
|
#include "defs.h"
|
|
|
|
#include "mm.h"
|
|
#include "ll.h"
|
|
#include "lb.h"
|
|
|
|
#include "tl.h"
|
|
#include "od.h"
|
|
#include "od2.h"
|
|
#include "osdem.h"
|
|
|
|
#include "mhhpt.h"
|
|
#include "cchpt.h"
|
|
#include "lbhpt.h"
|
|
#include "llhpt.h"
|
|
|
|
#include "osassert.h"
|
|
#include <string.h>
|
|
#include "dbgver.h"
|
|
|
|
|
|
extern AVS Avs;
|
|
static LPDBF lpdbf;
|
|
|
|
static HLLI llpid;
|
|
static HLLI llem;
|
|
static HLLI lltl = 0;
|
|
|
|
#define CEXM_MDL_native 0x20
|
|
|
|
XOSD OSDDoCallBack ( UINT, HPID, HTID, UINT, UINT, LONG );
|
|
XOSD OSDDoCallBackToEM ( EMF, HPID, HTID, UINT, LONG );
|
|
XOSD CreateProc ( LPFNSVC, HEM, HTL, LPHPID );
|
|
XOSD CreateThd ( HPID, HTID, LPHTID );
|
|
|
|
XOSD CallEM ( EMF, HPID, HTID, DWORD, LPV );
|
|
XOSD CallTL ( TLF, HPID, DWORD, LPV );
|
|
|
|
XOSD PASCAL LOADDS EMCallBackDB ( DBC, HPID, HTID, DWORD, DWORD, LPV );
|
|
XOSD PASCAL LOADDS EMCallBackTL ( TLF, HPID, DWORD, LPV );
|
|
XOSD PASCAL LOADDS EMCallBackNT ( EMF, HPID, HTID, DWORD, LPV );
|
|
XOSD PASCAL LOADDS EMCallBackEM ( EMF, HPID, HTID, DWORD, DWORD, LPV );
|
|
|
|
XOSD PASCAL LOADDS TLCallBack ( HPID, UINT, LPV );
|
|
|
|
static EMCB emcb = {
|
|
EMCallBackDB,
|
|
EMCallBackTL,
|
|
EMCallBackNT,
|
|
EMCallBackEM
|
|
};
|
|
|
|
static CRITICAL_SECTION CallbackCriticalSection;
|
|
|
|
|
|
|
|
|
|
XOSD PASCAL
|
|
OSDInit (
|
|
LPDBF lpdbfT
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Initialize the internal structures for osdebug.
|
|
Register the debugger services callback vector.
|
|
|
|
Use list manager to create the three global lists used by osdebug.
|
|
These are the list of processes ( llpid ), the list of transport
|
|
layers ( lltl ), and the list of execution models ( llem ).
|
|
|
|
Registering the debugger services with osdebug is just an
|
|
assignment of a pointer to the function structure.
|
|
|
|
If this function fails, it is catastrophic. No cleanup of
|
|
partially allocated data is attempted.
|
|
|
|
Arguments:
|
|
|
|
lpdbfT - Supplies the debugger services structure
|
|
|
|
Return Value:
|
|
|
|
xosdNone - Function succeeded
|
|
|
|
xosdOutOfMemory - List manager was unable to allocate room
|
|
for its root structures.
|
|
|
|
--*/
|
|
{
|
|
XOSD xosd = xosdNone;
|
|
|
|
assert ( lpdbfT != NULL );
|
|
|
|
InitializeCriticalSection( &CallbackCriticalSection );
|
|
|
|
lpdbf = lpdbfT;
|
|
|
|
llpid = LLInit (sizeof ( PIDS ), llfNull, ODPDKill, (LPFNFCMPNODE) NULL );
|
|
lltl = LLInit ( sizeof ( TLS ), llfNull, TLKill, (LPFNFCMPNODE) NULL );
|
|
llem = LLInit ( sizeof ( EMS ), llfNull, EMKill, (LPFNFCMPNODE) NULL );
|
|
|
|
if ( llpid == 0 || lltl == 0 || llem == 0 ) {
|
|
xosd = xosdOutOfMemory;
|
|
}
|
|
|
|
return xosd;
|
|
}
|
|
|
|
|
|
|
|
XOSD PASCAL
|
|
OSDTerm(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Deallocate resources used by OSD. At present, this only destroys
|
|
critical sections used by osdebug.
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
xosd - always xosdNone
|
|
|
|
--*/
|
|
{
|
|
DeleteCriticalSection( &CallbackCriticalSection );
|
|
return xosdNone;
|
|
}
|
|
|
|
|
|
|
|
XOSD PASCAL
|
|
OSDCreatePID (
|
|
LPFNSVC lpfnsvc,
|
|
HEM hem,
|
|
HTL htl,
|
|
LPHPID lphpid
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Create the structures associated with a process
|
|
|
|
Create the osdebug pid structure and add it to the list of processes
|
|
( llpid ). Notify the native execution model ( hem ) and the
|
|
transport layer ( htl ) of the new process.
|
|
|
|
When connecting to a remote transport layer, check the version
|
|
signature to verify that the components are compatible.
|
|
|
|
Arguments:
|
|
|
|
lpfnsvc - Supplies a pointer to the debugger callback function.
|
|
|
|
hem - Supplies a handle to the native execution model.
|
|
|
|
htl - Supplies a handle to the transport layer.
|
|
|
|
lszEMData - Supplies a string that specifies init data for the
|
|
process required by the execution model.
|
|
|
|
lszTLData - Supplies a string that specifies init data for the
|
|
process required by the transport layer.
|
|
|
|
lphpid - Returns the handle to the pid that is generated.
|
|
|
|
Return Value:
|
|
|
|
xosdOutOfMemory - The List manager was unable to allocate
|
|
memory for the structures to be created.
|
|
|
|
Any error values that may be generated by the transport
|
|
layer or execution model initialization of a process.
|
|
|
|
--*/
|
|
{
|
|
/* *
|
|
* Use the list manager to create a process structure and add it to *
|
|
* the process list ( llpid ). *
|
|
* *
|
|
* Initialize the fields of the process structure. *
|
|
* *
|
|
* Call the execution model service function for the native execution *
|
|
* model with the emfCreatePid command and the initialization string *
|
|
* ( lszEMData ). *
|
|
* *
|
|
* Call the transport layer service function for the process's *
|
|
* transport layer with the tlfCreatePid command and the *
|
|
* initialization string ( lszTLData ). */
|
|
|
|
HEM hodem;
|
|
HPID oldhpid;
|
|
|
|
HPID hpid;
|
|
LPEM lpem;
|
|
LPTL lptl;
|
|
XOSD xosd = xosdNone;
|
|
|
|
assert ( lpfnsvc != NULL );
|
|
assert ( hem != hemNull );
|
|
assert ( htl != htlNull );
|
|
assert ( lphpid != NULL );
|
|
assert ( llpid != 0 );
|
|
|
|
// Create and initialize the process structure and add to llpid
|
|
|
|
xosd = CreateProc ( lpfnsvc, hem, htl, &hpid );
|
|
if (xosd != xosdNone) {
|
|
return xosd;
|
|
}
|
|
|
|
// Notify the transport layer of the new process
|
|
|
|
lptl = LLLock ( htl );
|
|
xosd = CallTL ( tlfConnect, hpid, 0, NULL );
|
|
LLUnlock ( htl );
|
|
|
|
if (xosd != xosdNone) {
|
|
// remove hpid from the lists of hpids in llem
|
|
for (hodem = LLNext((HLLI) llem, (HLLE)hmemNull ); hodem; hodem = LLNext( (HLLI)llem, (HLLE)hodem )) {
|
|
|
|
lpem = LLLock ( hodem );
|
|
if ( oldhpid = (HPID)LLFind ( lpem->llhpid, 0, &hpid, 0L ) ) {
|
|
LLDelete ( lpem->llhpid, (HLLE)oldhpid );
|
|
}
|
|
LLUnlock ( hodem );
|
|
}
|
|
LLUnlock ( hodem );
|
|
LLDelete ( llpid, (HLLE)hpid );
|
|
return xosd;
|
|
}
|
|
|
|
// Notify the native execution model of the new process
|
|
|
|
lpem = LLLock ( hem );
|
|
xosd = lpem->emfunc( emfConnect, hpid, htidNull, 0, 0);
|
|
|
|
if (xosd != xosdNone) {
|
|
goto err;
|
|
}
|
|
|
|
xosd = lpem->emfunc (emfCreatePid, hpid, htidNull, 0, (LONG) NULL);
|
|
|
|
err:
|
|
LLUnlock ( hem );
|
|
|
|
if (xosd != xosdNone) {
|
|
CallTL(tlfDisconnect, hpid, 0, NULL);
|
|
LLDelete ( llpid, (HLLE)hpid );
|
|
return xosd;
|
|
}
|
|
|
|
*lphpid = hpid;
|
|
|
|
return xosd;
|
|
}
|
|
|
|
|
|
XOSD PASCAL
|
|
OSDDisconnect(
|
|
HPID hpid,
|
|
HTID htid
|
|
)
|
|
{
|
|
if (!hpid) {
|
|
return xosdUnknown;
|
|
}
|
|
|
|
return CallTL( tlfDisconnect, hpid, (DWORD)htid, NULL );
|
|
}
|
|
|
|
|
|
XOSD PASCAL
|
|
OSDDestroyPID (
|
|
HPID hpid
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Destroy the structures associated with a process
|
|
|
|
Delete the osdebug pid structure from the list of processes
|
|
( llpid ). Notify the native execution model ( hem ) and the
|
|
transport layer ( htl ) that it's been deleted.
|
|
|
|
Arguments:
|
|
|
|
hpid - Supplies the process to destroy.
|
|
|
|
Return Value:
|
|
|
|
xosdInvalidProc - The hpid given was invalid.
|
|
|
|
Any error values that may be generated by the transport
|
|
layer or execution model during destruction of a process.
|
|
|
|
--*/
|
|
{
|
|
|
|
/***************************************************************************
|
|
* *
|
|
* Call the execution model service functions to let them know that *
|
|
* this hpid is being destroyed. *
|
|
* *
|
|
* Use the list manager to delete the process structure from the *
|
|
* process list ( llpid ). *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
XOSD xosd;
|
|
HEM hodem;
|
|
LPEM lpem;
|
|
HPID oldhpid;
|
|
LPPID lppid;
|
|
HTL htl, htlT;
|
|
|
|
xosd = CallEM ( emfDestroyPid, hpid, htidNull, 0, 0 );
|
|
|
|
if (xosd == xosdNone) {
|
|
|
|
lppid = LLLock((HLLE)hpid);
|
|
htl = lppid->htl;
|
|
LLUnlock((HLLE)hpid);
|
|
|
|
oldhpid = NULL;
|
|
while (oldhpid = (HPID)LLNext((HLLI)llpid, (HLLE)oldhpid) ) {
|
|
if (oldhpid != hpid) {
|
|
lppid = LLLock((HLLE)oldhpid);
|
|
htlT = lppid->htl;
|
|
LLUnlock((HLLE)oldhpid);
|
|
if (htlT == htl) {
|
|
htl = 0;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (htl) {
|
|
// if nobody else is using it, tell TL to disconnect
|
|
xosd = CallEM ( emfDisconnect, hpid, 0, 0, 0 );
|
|
xosd = CallTL ( tlfDisconnect, hpid, 0, NULL );
|
|
}
|
|
|
|
// remove hpid from the lists of hpids in llem
|
|
for (hodem = LLNext( (HLLI)llem, (HLLE)hmemNull ); hodem; hodem = LLNext( (HLLI)llem, (HLLE)hodem )) {
|
|
|
|
lpem = LLLock ( (HLLE)hodem );
|
|
if ( oldhpid = (HPID)LLFind ( lpem->llhpid, 0, &hpid, 0L ) ) {
|
|
LLDelete ( lpem->llhpid, (HLLE)oldhpid );
|
|
}
|
|
LLUnlock ( (HLLE)hodem );
|
|
}
|
|
|
|
LLDelete ( llpid, (HLLE)hpid );
|
|
}
|
|
|
|
return xosd;
|
|
|
|
}
|
|
|
|
|
|
|
|
XOSD PASCAL
|
|
OSDDestroyTID(
|
|
HTID htid
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Companion for OSDDestroyPID(); unhooks and deletes an htid.
|
|
There is less to this than destroying a PID: the EM has to be
|
|
notified, but the TL does not.
|
|
|
|
Arguments:
|
|
|
|
htid - osdebug htid
|
|
|
|
Return Value:
|
|
|
|
xosdNone, xosdInvalidProc, xosdInvalidThread
|
|
|
|
--*/
|
|
{
|
|
LPTID lptid;
|
|
HPID hpid;
|
|
LPPID lppid;
|
|
XOSD xosd;
|
|
|
|
lptid = LLLock((HLLE) htid );
|
|
if (!lptid) {
|
|
return xosdInvalidThread;
|
|
}
|
|
hpid = lptid->hpid;
|
|
LLUnlock((HLLE) htid );
|
|
|
|
xosd = CallEM ( emfDestroyTid, hpid, htid, 0, 0 );
|
|
|
|
lppid = LLLock ( (HLLE)hpid );
|
|
if (!lppid) {
|
|
return xosdInvalidProc;
|
|
}
|
|
LLDelete ( lppid->lltid, (HLLE)htid );
|
|
LLUnlock ( (HLLE)hpid );
|
|
|
|
return xosdNone;
|
|
}
|
|
|
|
|
|
XOSD PASCAL
|
|
OSDPtrace (
|
|
OSD osd,
|
|
UINT wValue,
|
|
LPV lpData,
|
|
HPID hpid,
|
|
HTID htid
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Provide ptrace-type functionality. This just passes the parameters
|
|
to the EM service function.
|
|
|
|
Arguments:
|
|
|
|
osd - Supplies OSD index of requested service
|
|
|
|
wValue - Supplies function-dependent data
|
|
|
|
lpData - Supplies and/or Returns function dependent data
|
|
|
|
hpid - Supplies handle to process structure
|
|
|
|
htid - Supplies handle to thread structure
|
|
|
|
Return Value:
|
|
|
|
xosd value as returned by the EM service function.
|
|
|
|
--*/
|
|
{
|
|
return CallEM ( (EMF) osd, hpid, htid, wValue, lpData );
|
|
}
|
|
|
|
|
|
|
|
XOSD PASCAL
|
|
OSDIoctl (
|
|
HPID hpid,
|
|
HTID htid,
|
|
UINT wFunction,
|
|
UINT cbData,
|
|
LPV lpData
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Provide OS specific functionality. Calls the EM service function,
|
|
requesting the emfIOCTL service.
|
|
|
|
Arguments:
|
|
|
|
hpid - Supplies handle to the process to perform the operation
|
|
on. Some IOCTLs may not apply to a process, but the hpid
|
|
is required to provide the hook to the EM and TL.
|
|
|
|
htid - Supplies optional thread structure
|
|
|
|
wFunction - Supplies the IOCTL function index
|
|
|
|
cbData - Supplies the number of bytes in the data packet
|
|
|
|
lpData - Supplies and returns data. Use of this field depends on
|
|
the IOCTL.
|
|
|
|
Return Value:
|
|
|
|
xosd return value is supplied by the IOCTL function.
|
|
|
|
--*/
|
|
{
|
|
|
|
XOSD xosd = xosdNone;
|
|
LPIOL lpiol = MHAlloc ( sizeof ( IOL ) + cbData );
|
|
|
|
if ( lpiol == NULL ) return xosdOutOfMemory;
|
|
|
|
lpiol->wFunction = wFunction;
|
|
_fmemcpy ( lpiol->rgbVar, lpData, cbData );
|
|
|
|
xosd = CallEM ((EMF) emfIOCTL, hpid, htid, sizeof ( IOL ) + cbData, (LPV) lpiol );
|
|
|
|
_fmemcpy ( lpData, lpiol->rgbVar, cbData );
|
|
|
|
MHFree ( lpiol );
|
|
|
|
return xosd;
|
|
|
|
}
|
|
|
|
|
|
XOSD PASCAL
|
|
OSDProgramLoad (
|
|
HPID hpid,
|
|
LSZ lszCmdLine,
|
|
LSZ lszDebugger,
|
|
ULONG ulFlags
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Send a program load request to the EM. If the process is created,
|
|
the shell will be notified of a new process creation.
|
|
|
|
Arguments:
|
|
|
|
hpid - Supplies the process the process handle that binds to the
|
|
EM and TL. This is not neccessarily the hpid that will
|
|
correspond to the new process.
|
|
|
|
lszCmdLine - Supplies the command line that specifies the child program
|
|
and its arguments.
|
|
|
|
lszDebugger - Supplies the name of the debugger to the EM. This is
|
|
provided mainly so that the DM can print the debugger's
|
|
name in error messages.
|
|
|
|
ulFlags - Supplies flags that are passed to the EM. The following
|
|
flags are defined; any or none may be supported by any
|
|
EM/DM pair:
|
|
|
|
ulfMultiProcess - children of the new process will
|
|
be debugged.
|
|
|
|
ulfMinimizeApp - New process will be iconic
|
|
|
|
ulfNoActivate - New process will not receive focus
|
|
|
|
ulfInheritHandles - New app will inherit handles
|
|
from debugger. This is useful
|
|
when debugging an app which inherits
|
|
handles from its parent.
|
|
|
|
ulfDebugRegisters
|
|
|
|
ulfDisableNMI
|
|
|
|
ulfForceNMI
|
|
|
|
ulfDisableIBM
|
|
|
|
ulfForceIBM
|
|
|
|
Return Value:
|
|
|
|
If OSDProgramLoad cannot allocate a buffer to copy the arguements
|
|
into, it will return xosdOutOfMemory. Other xosd failure codes may be
|
|
returned from the EM, such as xosdFileNotFound, xosdAccessDenied.
|
|
|
|
--*/
|
|
{
|
|
XOSD xosd = xosdNone;
|
|
LPPRL lpprl;
|
|
UINT cchCmd;
|
|
|
|
assert ( hpid != NULL );
|
|
assert ( lszCmdLine != NULL );
|
|
|
|
(void)CallEM ( emfSetMulti,
|
|
hpid,
|
|
htidNull,
|
|
( ulFlags & ulfMultiProcess ) != 0,
|
|
NULL
|
|
);
|
|
|
|
(void)CallEM ( emfDebugger,
|
|
hpid,
|
|
htidNull,
|
|
_fstrlen ( lszDebugger ) + 1,
|
|
lszDebugger
|
|
);
|
|
|
|
|
|
cchCmd = _fstrlen( lszCmdLine ) + 1;
|
|
lpprl = (LPPRL)MHAlloc ( sizeof ( PRL ) + cchCmd );
|
|
if ( lpprl == NULL ) {
|
|
|
|
xosd = xosdOutOfMemory;
|
|
|
|
} else {
|
|
|
|
lpprl->cbCmdLine = cchCmd;
|
|
lpprl->ulChildFlags = ulFlags;
|
|
_fmemcpy( lpprl->lszCmdLine, lszCmdLine, cchCmd );
|
|
|
|
xosd = CallEM ( emfProgramLoad,
|
|
hpid,
|
|
htidNull,
|
|
sizeof( PRL ) + cchCmd,
|
|
lpprl
|
|
);
|
|
|
|
MHFree ( lpprl );
|
|
}
|
|
|
|
return xosd;
|
|
}
|
|
|
|
|
|
XOSD PASCAL
|
|
OSDAddEM (
|
|
EMFUNC emfunc,
|
|
LPDBF lpdbf,
|
|
LPHEM lphem,
|
|
EMTYPE emtype
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Create and initialize an execution model associated with the
|
|
service function EMFunc and add it to the list of osdebug's
|
|
available execution models ( llem ).
|
|
|
|
Arguments:
|
|
|
|
emfunc - Supplies a pointer to the execution model service function
|
|
to be associated with the execution model that is being
|
|
created.
|
|
|
|
lpdbf - Supplies a pointer to the debugger services structure that
|
|
will be registered with the execution model being created.
|
|
|
|
lphem - Returns the execution model handle.
|
|
|
|
emtype - Supplies the type of EM; emNative or emNonNative.
|
|
|
|
Return Value:
|
|
|
|
xosdNone - Success.
|
|
|
|
xosdOutOfMemory - List manager was unable to allocate em or
|
|
add it to the execution model list ( llem ).
|
|
|
|
Other xosd failure codes may be returned from the new EM while
|
|
it is being initialized.
|
|
|
|
--*/
|
|
{
|
|
/***************************************************************************
|
|
* IMPLEMENTATION: *
|
|
* *
|
|
* Use list manager to create an execution model handle and add it *
|
|
* to the execution model list ( llem ). *
|
|
* *
|
|
* Call the execution model service function ( lpfnsvcEM ) to *
|
|
* initialize the execution model and to register the debugger *
|
|
* service functions ( lpdbf ). *
|
|
* *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
HEM hem;
|
|
HEM hemm = 0;
|
|
LPEM lpem;
|
|
LPEM lpemm;
|
|
XOSD xosd = xosdNone;
|
|
UINT wModel;
|
|
|
|
assert ( emfunc != NULL );
|
|
assert ( lpdbf != NULL );
|
|
assert ( lphem != NULL );
|
|
|
|
hem = LLCreate ( llem );
|
|
if ( hem == hemNull ) {
|
|
return xosdOutOfMemory;
|
|
}
|
|
|
|
if ( emtype == emNative ) {
|
|
|
|
// native inserted at the tail of the list
|
|
LLAdd ( llem, hem );
|
|
}
|
|
else {
|
|
|
|
// non-native inserted at head of list
|
|
LLAddHead ( llem, hem );
|
|
}
|
|
|
|
lpem = LLLock ( hem );
|
|
lpem->emfunc = emfunc;
|
|
lpem->emtype = emtype;
|
|
lpem->llhpid = LLInit ( sizeof ( HPID ), llfNull, NULL, EMHpidCmp );
|
|
if ( lpem->llhpid == 0 ) {
|
|
xosd = xosdOutOfMemory;
|
|
}
|
|
|
|
xosd = emfunc ( emfRegisterDBF, NULL, htidNull, 0, (LONG) lpdbf );
|
|
if (xosd != xosdNone) {
|
|
return xosd;
|
|
}
|
|
|
|
xosd = emfunc ( emfInit, NULL, htidNull, 0, (LONG) (LPV) &emcb );
|
|
if (xosd != xosdNone) {
|
|
return xosd;
|
|
}
|
|
|
|
xosd = emfunc ( emfGetModel, NULL, htidNull, 0, (LONG) (LPV) &wModel );
|
|
if (xosd != xosdNone) {
|
|
return xosd;
|
|
}
|
|
|
|
while ( hemm = LLNext ( llem, hemm ) ) {
|
|
lpemm = LLLock ( hemm );
|
|
if ( lpemm->model == wModel ) {
|
|
|
|
// this is an error, cannot add the same model twice
|
|
LLUnlock ( hemm );
|
|
LLUnlock ( hem );
|
|
return xosdInvalidEM;
|
|
}
|
|
LLUnlock ( hemm );
|
|
}
|
|
|
|
lpem->model = wModel;
|
|
|
|
LLUnlock ( hem );
|
|
|
|
*lphem = hem;
|
|
|
|
return xosd;
|
|
}
|
|
|
|
|
|
XOSD PASCAL
|
|
OSDDeleteEM (
|
|
HEM hem
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Remove the execution model (hem) from os debug's list of available
|
|
execution models ( llem ).
|
|
|
|
Arguments:
|
|
|
|
hem - Supplies handle to EM which is being removed
|
|
|
|
Return Value:
|
|
|
|
xosdNone - Success.
|
|
|
|
xosdInvalidEM - The execution model handle ( hem ) is invalid.
|
|
|
|
xosdEMInUse - The execution model is still being used by some pid.
|
|
OSDDiscardEM must be called on all of the pids using
|
|
this particular em before OSDDeleteEM can be called
|
|
without error.
|
|
|
|
--*/
|
|
{
|
|
/***************************************************************************
|
|
* IMPLEMENTATION: *
|
|
* *
|
|
* Check the list of pids using this execution model. If it is zero *
|
|
* indicating that no pids are using it, then call the list manager *
|
|
* to delete it from the list of available execution models ( llem ). *
|
|
* *
|
|
***************************************************************************/
|
|
XOSD xosd = xosdNone;
|
|
LPEM lpem;
|
|
|
|
assert ( hem != hemNull );
|
|
|
|
lpem = LLLock ( hem );
|
|
|
|
if ( LLSize ( lpem->llhpid ) != 0 ) {
|
|
|
|
LLUnlock ( hem );
|
|
xosd = xosdEMInUse;
|
|
|
|
} else {
|
|
|
|
// Tell the EM and DM that they're about to be discarded
|
|
(lpem->emfunc) ( emfUnInit, NULL, htidNull, 0, 0 );
|
|
|
|
LLUnlock ( hem );
|
|
|
|
if ( !LLDelete ( llem, (HLLE)hem ) ) {
|
|
xosd = xosdInvalidEM;
|
|
}
|
|
}
|
|
|
|
return xosd;
|
|
}
|
|
|
|
|
|
XOSD PASCAL
|
|
OSDDeinitTL(
|
|
TLFUNC tlfunc
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Tell the transport to clean up. This should be called if the
|
|
OSDInitTL succeeds, but the OSDAddTL fails. This sends a
|
|
tlfGlobalDestroy message to the transport layer.
|
|
|
|
Arguments:
|
|
|
|
tlfunc - Supplies the TL service function
|
|
|
|
Return Value:
|
|
|
|
xosd status returned by the TL.
|
|
|
|
--*/
|
|
{
|
|
XOSD xosd;
|
|
|
|
xosd = tlfunc(tlfGlobalDestroy, NULL, 0, (LONG)0);
|
|
return(xosd);
|
|
}
|
|
|
|
|
|
XOSD PASCAL
|
|
OSDInitTL(
|
|
TLFUNC tlfunc,
|
|
LPDBF lpdbf
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Initialize a transport layer. Send a pointer to a table of
|
|
debugger service functions to the TL, then tell it to initialize.
|
|
|
|
Arguments:
|
|
|
|
tlfunc - Supplies the address of the TL service function
|
|
|
|
lpdbf - Supplies the table of debugger service functions
|
|
|
|
Return Value:
|
|
|
|
Return status is supplied by the TL.
|
|
xosdNone if initialization succeeds, an xosd failure code if not.
|
|
|
|
--*/
|
|
{
|
|
XOSD xosd = xosdNone;
|
|
|
|
xosd = tlfunc ( tlfRegisterDBF, NULL, 0, (LONG) lpdbf );
|
|
if (xosd != xosdNone) {
|
|
return xosd;
|
|
}
|
|
|
|
xosd = tlfunc ( tlfGlobalInit, NULL, 0, (LONG) TLCallBack );
|
|
return xosd;
|
|
}
|
|
|
|
|
|
|
|
#if 0
|
|
XOSD PASCAL OSDTLGetInfo( TLFUNC tlfunc, LPGIS lpgis, UINT wLen) {
|
|
XOSD xosd = xosdNone;
|
|
|
|
xosd = tlfunc ( tlfGetInfo, NULL, wLen, (LONG) lpgis );
|
|
return xosd;
|
|
}
|
|
|
|
XOSD PASCAL OSDTLSetup( TLFUNC tlfunc, LSZ lszInit, UINT wLen, LPV lpv) {
|
|
XOSD xosd = xosdNone;
|
|
|
|
xosd = tlfunc ( tlfSetUIStruct, NULL, 0, (LONG) lpv );
|
|
if (xosd != xosdNone) {
|
|
return xosd;
|
|
}
|
|
|
|
xosd = tlfunc ( tlfSetup, NULL, wLen, (LONG) lszInit );
|
|
return xosd;
|
|
}
|
|
|
|
|
|
#endif // 0
|
|
|
|
XOSD PASCAL
|
|
OSDAddTL (
|
|
TLFUNC tlfunc,
|
|
LPHTL lphtl,
|
|
LPCH lpchInit
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Create and initialize a transport layer associated with the
|
|
service function lpfnsvcTL and add it to the list of osdebug's
|
|
available transport layers ( lltl ).
|
|
|
|
Arguments:
|
|
|
|
tlfunc - Supplies pointer to the transport layer service function
|
|
to be associated with the transport layer that is being
|
|
created.
|
|
|
|
lpdbf - Supplies pointer to the debugger services structure that
|
|
will be registered with the transport layer being created.
|
|
|
|
lphtl - Returns the transport layer handle.
|
|
|
|
Return Value:
|
|
|
|
xosdNone - Success.
|
|
|
|
xosdOutOfMemory - List manager was unable to allocate TL
|
|
or add it to the transport layer list ( lltl ).
|
|
|
|
Other xosd failure codes may be returned by the transport layer
|
|
if its initialization fails.
|
|
|
|
--*/
|
|
{
|
|
/***************************************************************************
|
|
* *
|
|
* IMPLEMENTATION: *
|
|
* *
|
|
* Use list manager to create a transport layer handle and add it *
|
|
* to the transport layer list ( lltl ). *
|
|
* *
|
|
* Call the transport layer service function ( lpfnsvcTL ) to *
|
|
* initialize the transport layer and to register the debugger *
|
|
* service functions ( lpdbf ). *
|
|
* *
|
|
***************************************************************************/
|
|
HTL htl;
|
|
LPTL lptl;
|
|
XOSD xosd = xosdNone;
|
|
AVS RemoteAvs;
|
|
|
|
assert ( tlfunc != NULL );
|
|
assert ( lpdbf != NULL );
|
|
assert ( lphtl != NULL );
|
|
|
|
htl = LLCreate ( lltl );
|
|
if ( htl == htlNull ) {
|
|
|
|
xosd = xosdOutOfMemory;
|
|
|
|
} else {
|
|
|
|
LLAdd ( lltl, htl );
|
|
|
|
lptl = LLLock ( htl );
|
|
|
|
lptl->tlfunc = tlfunc;
|
|
lptl->llpid = LLInit ( sizeof ( HPID ), llfNull, NULL, NULL );
|
|
if ( lptl->llpid == 0 ) {
|
|
xosd = xosdOutOfMemory;
|
|
}
|
|
|
|
if (xosd == xosdNone) {
|
|
xosd = tlfunc ( tlfInit, NULL, 0, (LONG) lpchInit );
|
|
}
|
|
|
|
if (xosd == xosdNone) {
|
|
xosd = tlfunc ( tlfConnect, NULL, 0, 0 );
|
|
}
|
|
|
|
if (xosd == xosdNone) {
|
|
xosd = tlfunc(tlfGetVersion, NULL, sizeof(Avs), (LONG)&RemoteAvs);
|
|
switch (xosd) {
|
|
case xosdNone:
|
|
// got version info for remote side of transport...
|
|
// verify it.
|
|
if (Avs.rlvt != RemoteAvs.rlvt ||
|
|
Avs.iApiVer != RemoteAvs.iApiVer) {
|
|
xosd = xosdBadRemoteVersion; // bogus version
|
|
}
|
|
*(MPT *)lpchInit = RemoteAvs.mpt;
|
|
break;
|
|
|
|
case xosdNotRemote:
|
|
// local transport, don't need to check ver
|
|
*(MPT *)lpchInit = RemoteAvs.mpt;
|
|
xosd = xosdNone;
|
|
break;
|
|
|
|
case xosdBadRemoteVersion:
|
|
default:
|
|
break; // pass error back after cleaning up
|
|
}
|
|
|
|
if (xosd != xosdNone) {
|
|
// version check failed, disconnect tl
|
|
// hpid cleanup is handled below
|
|
tlfunc( tlfDisconnect, NULL, 0, 0 );
|
|
}
|
|
}
|
|
|
|
LLUnlock ( htl );
|
|
|
|
if (xosd == xosdNone) {
|
|
*lphtl = htl;
|
|
} else {
|
|
LLDelete(lltl, (HLLE)htl);
|
|
}
|
|
|
|
}
|
|
return xosd;
|
|
}
|
|
|
|
|
|
|
|
XOSD PASCAL
|
|
OSDDeleteTL (
|
|
HTL htl
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Remove the transport layer (htl) from os debug's list of available
|
|
transport layers ( lltl ).
|
|
|
|
Arguments:
|
|
|
|
htl - A transport layer that has previously been returned by
|
|
OSDAddTL.
|
|
|
|
Return Value:
|
|
|
|
xosdNone - Success.
|
|
|
|
xosdTLInUse - The transport layer is still being used by
|
|
some pid. OSDDiscardTL must be called on all of the
|
|
pids using this particular em before OSDDeleteTL can
|
|
be called without error.
|
|
|
|
xosdInvalidTL - The transport layer handle ( htl ) is invalid.
|
|
|
|
--*/
|
|
{
|
|
/***************************************************************************
|
|
* *
|
|
* IMPLEMENTATION: *
|
|
* *
|
|
* Check the list of pids using this transport layer. If it is zero *
|
|
* indicating that no pids are using it, then call the list manager *
|
|
* to delete it from the list of available transport layers ( lltl ). *
|
|
* *
|
|
***************************************************************************/
|
|
XOSD xosd = xosdNone;
|
|
LPTL lptl;
|
|
|
|
assert ( htl != htlNull );
|
|
|
|
lptl = LLLock ( htl );
|
|
if ( LLSize ( lptl->llpid ) != 0 ) {
|
|
|
|
LLUnlock ( htl );
|
|
xosd = xosdTLInUse;
|
|
|
|
} else {
|
|
|
|
(*lptl->tlfunc)(tlfDestroy, NULL, 0, 0);
|
|
(*lptl->tlfunc)(tlfGlobalDestroy, NULL, 0, 0);
|
|
|
|
LLUnlock ( htl );
|
|
|
|
if ( !LLDelete ( lltl, (HLLE)htl ) ) {
|
|
xosd = xosdInvalidTL;
|
|
}
|
|
}
|
|
|
|
return xosd;
|
|
}
|
|
|
|
|
|
XOSD PASCAL
|
|
OSDGetAddr (
|
|
HPID hpid,
|
|
HTID htid,
|
|
ADR adr,
|
|
LPADDR lpaddr
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
To get one of the special addresses in a process/thread which
|
|
the EM can supply.
|
|
|
|
Arguments:
|
|
|
|
hpid - The process
|
|
|
|
htid - The thread
|
|
|
|
adr - The address to get. One of the following.
|
|
|
|
adrCurrent - The the current address for the thread.
|
|
This is used to specify breakpoint
|
|
addresses, etc.
|
|
|
|
adrPC - The program counter of the thread.
|
|
|
|
adrBase - The frame base address of the thread.
|
|
|
|
adrStack - The current stack pointer of the thread.
|
|
|
|
adrData - The data area for the thread/process
|
|
|
|
adrBaseProlog - The frame base address will be fixed up as
|
|
if the prolog code of the existing function
|
|
were already executed. This requires that
|
|
the address passed in be the start of the
|
|
function.
|
|
|
|
adrTlsBase - The base of the thread local storage area.
|
|
|
|
lpaddr - Returns the requested address.
|
|
|
|
Return Value:
|
|
|
|
xosdNone - Success
|
|
|
|
Any error that may be generated by the emfGetAddr function
|
|
of the execution model associated with hpid:htid.
|
|
|
|
--*/
|
|
{
|
|
assert ( lpaddr != NULL );
|
|
|
|
if ( htid == htidNull && adr != adrCurrent ) {
|
|
_fmemset ( lpaddr, 0, sizeof ( ADDR ) );
|
|
return xosdNone;
|
|
}
|
|
else {
|
|
return CallEM ( emfGetAddr, hpid, htid, adr, lpaddr );
|
|
}
|
|
|
|
}
|
|
|
|
|
|
XOSD PASCAL
|
|
OSDIsStackSetup (
|
|
HPID hpid,
|
|
HTID htid,
|
|
LPADDR lpaddr
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Find out if the thread's stack is set up for the function
|
|
at the address supplied. Returns FALSE if the thread's PC
|
|
is in the function prolog.
|
|
|
|
The address must point to a function prolog, and the thread's
|
|
PC must be in that function, or this API's behaviour is undefined.
|
|
|
|
Arguments:
|
|
|
|
hpid - Supplies process
|
|
|
|
htid - Supplies thread
|
|
|
|
lpaddr - Supplies address of the beginning of a function.
|
|
|
|
Return Value:
|
|
|
|
xosdNone - Stack isn't setup
|
|
|
|
xosdContinue - The Stack is setup
|
|
|
|
--*/
|
|
{
|
|
assert ( lpaddr != NULL )
|
|
|
|
if ( htid == htidNull ) {
|
|
_fmemset ( lpaddr, 0, sizeof ( ADDR ) );
|
|
return xosdNone;
|
|
}
|
|
else {
|
|
return CallEM ( emfIsStackSetup, hpid, htid, 0, lpaddr );
|
|
}
|
|
}
|
|
|
|
|
|
XOSD PASCAL
|
|
OSDSetAddr (
|
|
HPID hpid,
|
|
HTID htid,
|
|
ADR adr,
|
|
LPADDR lpaddr
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Sets one of the addresses associated with a thread.
|
|
|
|
Arguments:
|
|
|
|
hpid - Supplies process
|
|
|
|
htid - Supplies thread
|
|
|
|
adr - Supplies id of the address to set, and may be
|
|
one of the following:
|
|
|
|
adrCurrent - The current address for the thread.
|
|
This is used to specify breakpoint
|
|
addresses, etc.
|
|
|
|
adrPC - The program counter of the thread.
|
|
|
|
adrBase - The frame base address of the thread.
|
|
|
|
adrStack - The current stack pointer of the thread.
|
|
|
|
adrData - The data area for the thread/process
|
|
|
|
adrBaseProlog - N/A ( can't be set )
|
|
|
|
adrTlsBase - N/A ( can't be set )
|
|
|
|
lpaddr - Supplies the address to set the hpid:htid with
|
|
|
|
Return Value:
|
|
|
|
xosdNone - Success.
|
|
|
|
Any error that may be generated by the emfSetAddr function
|
|
of the execution model associated with hpid:htid.
|
|
|
|
--*/
|
|
{
|
|
assert ( lpaddr != NULL );
|
|
|
|
if ( htid == htidNull && adr != adrCurrent ) {
|
|
return xosdInvalidThread;
|
|
}
|
|
else {
|
|
return CallEM ( emfSetAddr, hpid, htid, adr, lpaddr );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
XOSD PASCAL
|
|
OSDReadReg (
|
|
HPID hpid,
|
|
HTID htid,
|
|
UINT wIndex,
|
|
LPV lpv
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Read a register in a debuggee thread
|
|
|
|
Arguments:
|
|
|
|
hpid - Supplies process
|
|
|
|
htid - Supplies thread
|
|
|
|
wIndex - Supplies register index
|
|
|
|
lpv - Returns register value
|
|
|
|
Return Value:
|
|
|
|
xosdNone - Success
|
|
|
|
The EM may return an xosd failure status if wIndex is invalid
|
|
or for other reasons.
|
|
|
|
--*/
|
|
{
|
|
assert ( lpv != NULL );
|
|
return CallEM ( emfGetReg, hpid, htid, wIndex, lpv );
|
|
}
|
|
|
|
|
|
XOSD PASCAL
|
|
OSDWriteReg (
|
|
HPID hpid,
|
|
HTID htid,
|
|
UINT wIndex,
|
|
LPV lpv
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Write a register in a debuggee thread
|
|
|
|
Arguments:
|
|
|
|
hpid - Supplies process
|
|
|
|
htid - Supplies thread
|
|
|
|
wIndex - Supplies register index
|
|
|
|
lpv - Supplies register value
|
|
|
|
Return Value:
|
|
|
|
xosdNone - Success
|
|
|
|
The EM may return an xosd failure status if wIndex is invalid
|
|
or for other reasons.
|
|
|
|
--*/
|
|
{
|
|
return CallEM ( emfSetReg, hpid, htid, wIndex, lpv );
|
|
}
|
|
|
|
|
|
XOSD PASCAL
|
|
OSDSetFrameContext (
|
|
HPID hpid,
|
|
HTID htid,
|
|
UINT wIndex,
|
|
LPV lpv
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Specify which frame to use to get context information in the EM
|
|
|
|
Arguments:
|
|
|
|
hpid - The process
|
|
|
|
htid - The thread
|
|
|
|
wIndex - The frame number; Current is 0; caller is 1, etc.
|
|
|
|
Return Value:
|
|
|
|
xosdNone - Success
|
|
|
|
Any error that may be generated by the emfSetFrameContext
|
|
of the execution model associated with hpid:htid.
|
|
|
|
--*/
|
|
{
|
|
return CallEM ( emfSetFrameContext, hpid, htid, wIndex, lpv );
|
|
}
|
|
|
|
|
|
|
|
XOSD PASCAL
|
|
OSDFrameReadReg (
|
|
HPID hpid,
|
|
HTID htid,
|
|
UINT wIndex,
|
|
LPV lpv
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Read the register specified by wIndex in the register set
|
|
specified by hpid:htid, and the frame which was set by a prior
|
|
call to OSDSetFrameContext.
|
|
|
|
Arguments:
|
|
|
|
hpid - Supplies process
|
|
|
|
htid - Supplies thread
|
|
|
|
wIndex - Supplies register index
|
|
|
|
lpv - Returns register value
|
|
|
|
Return Value:
|
|
|
|
xosdNone - Success
|
|
|
|
Any error that may be generated by the emfFrameRegValue
|
|
function of the execution model associated with hpid:htid.
|
|
|
|
--*/
|
|
{
|
|
assert ( lpv != NULL );
|
|
return CallEM ( emfFrameRegValue, hpid, htid, wIndex, lpv );
|
|
}
|
|
|
|
|
|
XOSD PASCAL
|
|
OSDFrameWriteReg (
|
|
HPID hpid,
|
|
HTID htid,
|
|
UINT wIndex,
|
|
LPV lpv
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Write the register specified by wIndex in the register set
|
|
specified by hpid:htid, and the frame which was set by a prior
|
|
call to OSDSetFrameContext.
|
|
|
|
Arguments:
|
|
|
|
hpid - Supplies process
|
|
|
|
htid - Supplies thread
|
|
|
|
wIndex - Supplies register index
|
|
|
|
lpv - Supplies register value
|
|
|
|
Return Value:
|
|
|
|
xosdNone - Success
|
|
|
|
Any error that may be generated by the emfFrameSetReg function
|
|
of the execution model associated with hpid:htid.
|
|
|
|
--*/
|
|
{
|
|
return CallEM ( emfFrameSetReg, hpid, htid, wIndex, lpv );
|
|
}
|
|
|
|
|
|
|
|
XOSD PASCAL
|
|
OSDReadFlag (
|
|
HPID hpid,
|
|
HTID htid,
|
|
UINT wIndex,
|
|
LPV lpv
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Read the flag specified by wIndex in the processor flag set
|
|
for hpid:htid pair.
|
|
|
|
Arguments:
|
|
|
|
hpid - Supplies process
|
|
|
|
htid - Supplies thread
|
|
|
|
wIndex - Supplies register index
|
|
|
|
lpv - Returns value
|
|
|
|
Return Value:
|
|
|
|
xosdNone - Success
|
|
|
|
Any error that may be generated by the emfGetFlag function
|
|
of the execution model associated with hpid:htid.
|
|
|
|
--*/
|
|
{
|
|
assert ( lpv != NULL );
|
|
return CallEM ( emfGetFlag, hpid, htid, wIndex, lpv );
|
|
}
|
|
|
|
|
|
XOSD PASCAL
|
|
OSDWriteFlag (
|
|
HPID hpid,
|
|
HTID htid,
|
|
UINT wIndex,
|
|
LPV lpv
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Write the flag specified by wIndex in the processor flag set
|
|
for hpid:htid pair.
|
|
|
|
Arguments:
|
|
|
|
hpid - Supplies process
|
|
|
|
htid - Supplies thread
|
|
|
|
wIndex - Supplies register index
|
|
|
|
lpv - Supplies new value
|
|
|
|
Return Value:
|
|
|
|
xosdNone - Success
|
|
|
|
Any error that may be generated by the emfSetFlag function
|
|
of the execution model associated with hpid:htid.
|
|
|
|
--*/
|
|
{
|
|
return CallEM ( emfSetFlag, hpid, htid, wIndex, lpv );
|
|
}
|
|
|
|
|
|
|
|
XOSD PASCAL
|
|
OSDProgramFree (
|
|
HPID hpid
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Terminate and unload the program being debugged in process hpid.
|
|
This does not guarantee termination of child processes.
|
|
|
|
Arguments:
|
|
|
|
hpid - Supplies the process to kill
|
|
|
|
Return Value:
|
|
|
|
xosdNone - Success
|
|
|
|
Any error that can be generated by emfProgramFree
|
|
|
|
--*/
|
|
{
|
|
assert ( hpid != NULL);
|
|
return CallEM ( emfProgramFree, hpid, htidNull, 0, NULL );
|
|
}
|
|
|
|
#if 0
|
|
|
|
/**** OSDGETCURRENTEM - Get the execution model for hpid:htid ****
|
|
* *
|
|
* PURPOSE: *
|
|
* *
|
|
* To get the handle for the current execution model associated *
|
|
* with hpid:htid. *
|
|
* *
|
|
* *
|
|
* INPUTS: *
|
|
* *
|
|
* hpid - The process *
|
|
* htid - The thread *
|
|
* lphem - A far pointer to the location to stuff the handle to *
|
|
* the execution model. *
|
|
* *
|
|
* OUTPUTS: *
|
|
* *
|
|
* Return Value - *
|
|
* *
|
|
* xosdNone - Success *
|
|
* xosdInvalidEM - No valid execution model for this hpid:htid *
|
|
* *
|
|
* *lphem - A handle to the current execution model for hpid:htid. *
|
|
* *
|
|
* IMPLEMENTATION: *
|
|
* *
|
|
* Look up the execution model field in the structure reference by *
|
|
* htid and stuff it into *lphem. *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
XOSD PASCAL OSDGetCurrentEM ( HPID hpid, HTID htid, LPHEM lphem ) {
|
|
LPPID lppid;
|
|
HIND hodem = hmemNull;
|
|
LPEMP lpemp;
|
|
LPEM lpem;
|
|
|
|
Unreferenced( htid );
|
|
|
|
assert ( lphem != NULL );
|
|
|
|
lppid = LLLock ( hpid );
|
|
if ( lppid == NULL ) {
|
|
return xosdInvalidEM;
|
|
}
|
|
if ( lppid->lastmodel == CEXM_MDL_native ) {
|
|
lpemp = LLLock ( lppid->hempNative );
|
|
*lphem = lpemp->hem;
|
|
LLUnlock ( lppid->hempNative );
|
|
}
|
|
else {
|
|
while ( hodem = LLNext ( llem, hodem ) ) {
|
|
lpem = LLLock ( hodem );
|
|
if ( lpem->model == lppid->lastmodel ) {
|
|
*lphem = hodem;
|
|
}
|
|
LLUnlock ( hodem );
|
|
}
|
|
}
|
|
LLUnlock ( hpid );
|
|
return xosdNone;
|
|
}
|
|
|
|
|
|
/**** OSDNATIVEONLY - Force the use of only the native em for hpid:htid ****
|
|
* *
|
|
* PURPOSE: *
|
|
* *
|
|
* To allow the debugger to force the use of the native em even where *
|
|
* there is non-native code (ie pcode) *
|
|
* *
|
|
* INPUTS: *
|
|
* *
|
|
* hpid - The process *
|
|
* htid - The thread *
|
|
* fNat - true to set native only, false to return to normal mode *
|
|
* of handling multiple em's *
|
|
* *
|
|
* OUTPUTS: *
|
|
* *
|
|
* Return Value - *
|
|
* *
|
|
* xosdNone - Success *
|
|
* *
|
|
* IMPLEMENTATION: *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
XOSD PASCAL OSDNativeOnly ( HPID hpid, HTID htid, BOOL fNat ) {
|
|
HEMP hemp;
|
|
HEMP hempTmp = hemNull;
|
|
XOSD xosd = xosdNone;
|
|
LPEMP lpemp;
|
|
LPPID lppid;
|
|
|
|
assert ( hpid != NULL );
|
|
|
|
lppid = LLLock ( hpid );
|
|
|
|
if ( lppid->fNative == fNat ) {
|
|
LLUnlock((HLLE)hpid);
|
|
return xosd;
|
|
}
|
|
else if ( fNat ) {
|
|
|
|
// get the native em
|
|
hemp = lppid->hempNative;
|
|
|
|
// tell all of the non-native models to disconnect, cleanup or whatever
|
|
// they need to do
|
|
while ( ( hempTmp = LLNext ( lppid->llemp, hempTmp ) ) && hempTmp != hemp ) {
|
|
lpemp = LLLock ( hempTmp );
|
|
xosd = (lpemp->emfunc) ( emfDetach, hpid, htid, 0, (LONG) 0 );
|
|
LLUnlock ( hempTmp );
|
|
}
|
|
|
|
// we then move the native em to the head of the list, forcing it to be called
|
|
// first, until fNative is reset
|
|
LLRemove ( lppid->llemp, hemp );
|
|
LLAddHead ( lppid->llemp, hemp );
|
|
|
|
// if current model used to be non-native, send notification
|
|
if ( lppid->lastmodel != CEXM_MDL_native ) {
|
|
OSDDoCallBack ( dbcEmChange, hpid, htid, lppid->lastmodel, CEXM_MDL_native, (LONG) 0 );
|
|
lppid->lastmodel = CEXM_MDL_native;
|
|
}
|
|
|
|
// finally, set our global flag to true
|
|
lppid->fNative = fNat;
|
|
}
|
|
else {
|
|
|
|
// put the native em back at the end of the list
|
|
hemp = lppid->hempNative;
|
|
LLRemove ( lppid->llemp, hemp );
|
|
LLAdd ( lppid->llemp, hemp );
|
|
|
|
// tell all of the non-native models that they can re-connect
|
|
xosd = xosdPunt;
|
|
while ( ( hempTmp = LLNext ( lppid->llemp, hempTmp ) ) && hempTmp != hemp &&
|
|
xosd == xosdPunt) {
|
|
|
|
WORD wModel;
|
|
|
|
lpemp = LLLock ( hempTmp );
|
|
xosd = (lpemp->emfunc) ( emfAttach, hpid, htid, 0, (LONG) (LPV) &wModel );
|
|
if ( xosd == xosdNone ) {
|
|
|
|
// send a dbcEmChange notification
|
|
OSDDoCallBack ( dbcEmChange, hpid, htid, lppid->lastmodel, wModel, (LONG) 0 );
|
|
lppid->lastmodel = wModel;
|
|
}
|
|
LLUnlock ( hempTmp );
|
|
}
|
|
if ( xosd == xosdPunt ) xosd = xosdNone;
|
|
|
|
// reset our global flag to false
|
|
lppid->fNative = fNat;
|
|
}
|
|
|
|
LLUnlock ( hpid );
|
|
return xosd;
|
|
}
|
|
|
|
|
|
/**** OSDUSEEM - Add the execution model to the process' list of ems ****
|
|
* *
|
|
* PURPOSE: *
|
|
* *
|
|
* To tell osdebug that it should pass commands and callbacks for the *
|
|
* process hpid through the execution model whose handle is hem. *
|
|
* *
|
|
* INPUTS: *
|
|
* *
|
|
* hpid - The process *
|
|
* hem - A handle to the execution model *
|
|
* *
|
|
* OUTPUTS: *
|
|
* *
|
|
* Return Value - *
|
|
* *
|
|
* xosdNone - Success *
|
|
* xosdOutOfMemory - Not enough memory to create the reference *
|
|
* to the execution model in the process structure. *
|
|
* xosdInvalidEM - tried to add a native em when one was already *
|
|
* present *
|
|
* *
|
|
* IMPLEMENTATION: *
|
|
* *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
XOSD PASCAL OSDUseEM ( HPID hpid, HEM hem ) {
|
|
LPPID lppid;
|
|
HEMP hemp = hemNull;
|
|
LPEM lpem;
|
|
LPEMP lpemp;
|
|
HPID hpidem;
|
|
LPHPID lphpid;
|
|
|
|
assert ( hem != hemNull );
|
|
assert ( hpid != NULL );
|
|
|
|
// Add hem to pid's hem list
|
|
|
|
lppid = LLLock ( hpid );
|
|
|
|
while ( hemp = LLNext ( lppid->llemp, hemp ) ) {
|
|
lpemp = LLLock ( hemp );
|
|
if ( lpemp->hem == hem ) {
|
|
|
|
// this is an error, cannot add the same model twice
|
|
LLUnlock ( hemp );
|
|
LLUnlock ( hpid );
|
|
return xosdInvalidEM;
|
|
}
|
|
LLUnlock ( hemp );
|
|
}
|
|
|
|
hemp = LLCreate ( lppid->llemp );
|
|
if ( hemp == hmemNull ) {
|
|
LLUnlock ( hpid );
|
|
return xosdOutOfMemory;
|
|
}
|
|
|
|
lpem = LLLock ( hem );
|
|
if ( lpem->emtype ) {
|
|
LLAddHead ( lppid->llemp, hemp );
|
|
}
|
|
else {
|
|
// new native em
|
|
LLAdd ( lppid->llemp, hemp );
|
|
lppid->hempNative = hemp;
|
|
}
|
|
LLUnlock ( hpid );
|
|
|
|
// add hpid to hem in llem
|
|
|
|
hpidem = LLCreate ( lpem->llhpid );
|
|
if ( hpidem == hemNull ) {
|
|
return xosdOutOfMemory;
|
|
}
|
|
lphpid = LLLock ( hpidem );
|
|
|
|
// puts hpid in node
|
|
*lphpid = hpid;
|
|
|
|
LLUnlock ( hpidem );
|
|
LLUnlock ( hem );
|
|
LLAdd ( lpem->llhpid, hpidem );
|
|
|
|
return xosdNone;
|
|
}
|
|
|
|
|
|
|
|
/**** OSDDISCARDEM - Remove the execution model from the proc's list ****
|
|
* *
|
|
* PURPOSE: *
|
|
* *
|
|
* To remove the execution model whose handle is hem from the *
|
|
* process hpid's list of available execution models. *
|
|
* *
|
|
* INPUTS: *
|
|
* *
|
|
* hpid - A handle to the process *
|
|
* hem - A handle to the execution model. *
|
|
* *
|
|
* OUTPUTS: *
|
|
* *
|
|
* Return Value - *
|
|
* *
|
|
* xosdNone - Success *
|
|
* xosdInvalidEM - There is no execution model associated *
|
|
* with hem. *
|
|
* *
|
|
* IMPLEMENTATION: *
|
|
* *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
XOSD PASCAL OSDDiscardEM ( HPID hpid, HEM hem ) {
|
|
LPPID lppid;
|
|
HEM hemdis;
|
|
LPEM lpem;
|
|
HEMP hemp = hemNull;
|
|
HEMP hempdis;
|
|
LPEMP lpemp;
|
|
HPID hpiddis;
|
|
XOSD xosd = xosdNone;
|
|
|
|
assert ( hpid != NULL );
|
|
|
|
// find the hem in the lppid's list
|
|
lppid = LLLock ( hpid );
|
|
|
|
lpemp = LLLock ( lppid->hempNative );
|
|
if ( lpemp->hem == hem ) {
|
|
|
|
// trying to remove the native em
|
|
lppid->hempNative = 0;
|
|
}
|
|
LLUnlock ( lppid->hempNative );
|
|
|
|
while (hemp = LLNext ( lppid->llemp, hemp ) ) {
|
|
lpemp = LLLock ( hemp );
|
|
if ( lpemp->hem == hem ) {
|
|
hemdis = hem;
|
|
hempdis = hemp;
|
|
}
|
|
LLUnlock ( hemp );
|
|
}
|
|
if ( ! hemdis ) {
|
|
|
|
// no em found, return error
|
|
xosd = xosdInvalidEM;
|
|
}
|
|
else {
|
|
|
|
// delete the em from the hpid, then remove hpid from em in llem
|
|
LLDelete ( lppid->llemp, (HLLE)hempdis );
|
|
|
|
lpem = LLLock ( hemdis );
|
|
if ( hpiddis = LLFind ( lpem->llhpid, 0, &hpid, 0L ) ) {
|
|
LLDelete ( lpem->llhpid, (HLLE)hpiddis );
|
|
}
|
|
else {
|
|
|
|
// hpid not found: internal cosistancy error
|
|
assert ( FALSE );
|
|
}
|
|
LLUnlock ( hemdis );
|
|
}
|
|
LLUnlock ( hpid );
|
|
return xosd;
|
|
}
|
|
#endif // 0
|
|
|
|
|
|
XOSD PASCAL
|
|
OSDUnassemble (
|
|
HPID hpid,
|
|
HTID htid,
|
|
LPSDI lpsdi
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Disassemble one machine instruction. The address of the
|
|
instruction to disassemble is in the SDI structure pointed
|
|
to by lpsdi.
|
|
|
|
Arguments:
|
|
|
|
hpid - Supplies process to get data from
|
|
|
|
htid - Supplies thread
|
|
|
|
lpsdi - Supplies and Returns disassembly info
|
|
|
|
Return Value:
|
|
|
|
xosdNone for success, other xosd codes describe the reason
|
|
for failure.
|
|
|
|
When the call succeeds, lpsdi->lsz will point to a static
|
|
string containing the disassembled instruction. The SDI
|
|
structure contains ADDR fields which will contain effective
|
|
addresses computed for the instruction, and int fields which
|
|
describe the length of each of the parts of the disassembly
|
|
text, to facilitate formatting the text for display.
|
|
|
|
The addr field will be updated to point to the next instruction
|
|
in the stream.
|
|
|
|
--*/
|
|
{
|
|
assert ( lpsdi != NULL );
|
|
return CallEM ( emfUnassemble, hpid, htid, 0, lpsdi );
|
|
}
|
|
|
|
|
|
|
|
XOSD PASCAL
|
|
OSDAssemble (
|
|
HPID hpid,
|
|
HTID htid,
|
|
LPADDR lpaddr,
|
|
LSZ lsz
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Assemble an instruction into the debuggee.
|
|
|
|
Arguments:
|
|
|
|
hpid - Supplies process
|
|
|
|
htid - Supplies thread (optional?)
|
|
|
|
lpaddr - Supplies address to assemble to
|
|
|
|
lsz - Supplies instruction text
|
|
|
|
Return Value:
|
|
|
|
xosdNone for success, other xosd codes describe cause of failure.
|
|
|
|
--*/
|
|
{
|
|
XOSD xosd = xosdNone; // [00]
|
|
// [00]
|
|
(void)CallEM ( emfSetAddr, hpid, htid, adrCurrent, lpaddr ); // [00]
|
|
// [00]
|
|
xosd = CallEM ( emfAssemble, hpid, htid, 0, lsz ); // [00]
|
|
if (xosd != xosdNone) {
|
|
return xosd;
|
|
}
|
|
// [00]
|
|
(void)CallEM ( emfGetAddr, hpid, htid, adrCurrent, lpaddr ); // [00]
|
|
// [00]
|
|
return xosd; // [00]
|
|
}
|
|
|
|
#if 0
|
|
|
|
XOSD PASCAL OSDGetPrevInst (
|
|
HPID hpid,
|
|
HTID htid,
|
|
LPADDR lpaddr
|
|
) {
|
|
return CallEM ( emfGetPrevInst, hpid, htid, 0, lpaddr );
|
|
}
|
|
|
|
#endif
|
|
|
|
XOSD PASCAL
|
|
OSDGetDebugMetric (
|
|
HPID hpid,
|
|
HTID htid,
|
|
MTRC mtrc,
|
|
LPVOID lpv
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is a facility for getting various information about
|
|
the execution model associated with a process.
|
|
|
|
Arguments:
|
|
|
|
hpid - Supplies process
|
|
|
|
htid - Supplies thread (optional for some metrics)
|
|
|
|
mtrc - Supplies metric to query, see od.h
|
|
|
|
lpv - Returns requested info
|
|
|
|
Return Value:
|
|
|
|
xosdNone for success, other xosd codes describe the cause of failure.
|
|
lpv must point to a buffer of sufficient size to receive the info.
|
|
|
|
--*/
|
|
{
|
|
return CallEM ( emfMetric, hpid, htid, mtrc, lpv );
|
|
}
|
|
|
|
#if 0
|
|
|
|
|
|
/**** OSDGETOBJLENGTH - Get the length of the object containing *lpaddr ****
|
|
* *
|
|
* PURPOSE: Get the lenth of a given linear exe object *
|
|
* *
|
|
* INPUTS: *
|
|
* *
|
|
* hpid - A handle to the process. *
|
|
* htid - A handle to the thread. *
|
|
* lplBase - A pointer to a long in which to place the base address *
|
|
* lplLen - A pointer to a long in which to place the length *
|
|
* *lpaddr - An address within the object in question. *
|
|
* *
|
|
* OUTPUTS: *
|
|
* *
|
|
* Return Value - *
|
|
* *
|
|
* xosdNone - Success. *
|
|
* Any value that can be returned by the Get object length *
|
|
* of the execution model called. *
|
|
* *
|
|
* *
|
|
* *lplBase - The base address of the object. ( In a segmented *
|
|
* environment this will always be 0 ). *
|
|
* *lplLen - The length of the object. *
|
|
* *
|
|
* IMPLEMENTATION: *
|
|
* *
|
|
* Package the information in a gol ( Get Object Length ) package *
|
|
* and pass it to the most specific execution model associated *
|
|
* with the hpid:htid pair. *
|
|
* *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
XOSD PASCAL OSDGetObjLength (
|
|
HPID hpid,
|
|
HTID htid,
|
|
LPL lplBase,
|
|
LPL lplLen,
|
|
LPADDR lpaddr ) {
|
|
|
|
GOL gol;
|
|
|
|
gol.lplBase = lplBase;
|
|
gol.lplLen = lplLen;
|
|
gol.lpaddr = lpaddr;
|
|
|
|
assert ( lpaddr != NULL );
|
|
|
|
return CallEM ( emfGetObjLength, hpid, htid, 0, &gol );
|
|
}
|
|
|
|
#endif // 0
|
|
|
|
|
|
XOSD PASCAL
|
|
OSDGetMsgMap (
|
|
HPID hpid,
|
|
HTID htid,
|
|
LPMSGMAP* MsgMap
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get a pointer to MSGMAP structure for the EM associated with
|
|
hpid. This is a structure describing the window messages
|
|
supported by the EM. Not implemented for OS's without messages.
|
|
|
|
Arguments:
|
|
|
|
hpid - Supplies process
|
|
|
|
htid - Supplies thread (not used)
|
|
|
|
MsgMap - Returns pointer to MSGMAP structure
|
|
|
|
Return Value:
|
|
|
|
xosdNone for success, other xosd codes describe the cause of
|
|
failure. If a Win32 EM is associated with hpid, this always succeeds.
|
|
|
|
--*/
|
|
{
|
|
return CallEM ( emfGetMsgMap, hpid, htid, 0, MsgMap );
|
|
}
|
|
|
|
|
|
XOSD PASCAL
|
|
OSDGetModuleList (
|
|
HPID hpid,
|
|
HTID htid,
|
|
BOOL Flat,
|
|
LSZ ModuleName,
|
|
LPMODULE_LIST * ModuleList
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get the list of modules loaded in a process, or look up one
|
|
module. The returned module list contains one entry per
|
|
segment per module.
|
|
|
|
N.B. The function will look up flat or segmented modules,
|
|
but not both at the same time. This is not neccessarily
|
|
desirable behaviour.
|
|
|
|
Arguments:
|
|
|
|
hpid - Supplies process
|
|
|
|
htid - Supplies thread (not used)
|
|
|
|
Flat - Supplies TRUE to get flat modues, FALSE to
|
|
get segmented ones.
|
|
|
|
ModuleName - Supplies optional name of module to look for.
|
|
If this arg is NULL, all modules will be found.
|
|
|
|
ModuleList - Returns list of modules
|
|
|
|
Return Value:
|
|
|
|
xosdNone if successful. Other xosd codes indicate the
|
|
cause of failure.
|
|
|
|
--*/
|
|
{
|
|
MODULE_LIST_REQUEST Request;
|
|
|
|
Request.Flat = Flat;
|
|
Request.Name = ModuleName;
|
|
Request.List = ModuleList;
|
|
|
|
return CallEM ( emfGetModuleList, hpid, htid, 0, &Request );
|
|
}
|
|
|
|
#if 0
|
|
|
|
|
|
/**** OSDGetError - Get the Text of an error msg for a particular hpid/htid
|
|
*
|
|
* PURPOSE: Get the OS specific error msg for a pid and tid from the em.
|
|
* The debugger is responsible for providing a 12 byte buffer
|
|
* for lszErr, and a 256 byte buffer for lszErrText
|
|
*
|
|
* INPUTS:
|
|
*
|
|
* hpid - A handle to the process.
|
|
* htid - A handle to the thread.
|
|
* lpwErrNum - the error #
|
|
* lszErr - error # text string (ex. "DMOS001" )
|
|
* lszErrText - human readable text string (ex. "Tried to load OS2 app under Windows")
|
|
*
|
|
* OUTPUTS:
|
|
*
|
|
* Return Value -
|
|
*
|
|
* xosdNone - if msg was available
|
|
* xosdSyntax - if no msg available
|
|
*
|
|
* IMPLEMENTATION:
|
|
*
|
|
***************************************************************************/
|
|
|
|
XOSD PASCAL OSDGetError ( HPID hpid,
|
|
HTID htid,
|
|
LPW lpwErrNum,
|
|
LSZ lszErr,
|
|
LSZ lszErrText ) {
|
|
GET get;
|
|
|
|
get.lpwErrNum = lpwErrNum;
|
|
get.lszErr = lszErr;
|
|
get.lszErrText = lszErrText;
|
|
|
|
return CallEM ( emfGetError, hpid, htid, 0, &get );
|
|
}
|
|
|
|
|
|
/**** OSDGETFRAME - Get the the frame previous to the frame *lpaddr ****
|
|
* *
|
|
* PURPOSE: *
|
|
* *
|
|
* Put the frame on the stack previous to the frame specified by *
|
|
* *lpaddr into *lpaddr. *
|
|
* *
|
|
* INPUTS: *
|
|
* *
|
|
* hpid - A handle to the process. *
|
|
* htid - A handle to the thread. *
|
|
* *lpaddr - The current frame. *
|
|
* lpaddr - A pointer to the return frame address. *
|
|
* *
|
|
* OUTPUTS: *
|
|
* *
|
|
* Return Value - *
|
|
* *
|
|
* xosdNone - Success. *
|
|
* Any value that can be returned by the Get Frame Function *
|
|
* of the execution model called. *
|
|
* *
|
|
* *lpaddr - The previous frame address. *
|
|
* *
|
|
* IMPLEMENTATION: *
|
|
* *
|
|
* Send the Get Frame command to the execution model. *
|
|
* *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
XOSD PASCAL OSDGetFrame ( HPID hpid, HTID htid, LPADDR lpaddr ) {
|
|
|
|
return CallEM ( emfGetFrame, hpid, htid, 0, lpaddr );
|
|
}
|
|
|
|
|
|
/**** OSDGETRETURN - Get the return address for the frame *lpaddrFrame ****
|
|
* *
|
|
* PURPOSE: *
|
|
* *
|
|
* Put the return addres of the frame into *lpaddrPC. *
|
|
* *
|
|
* INPUTS: *
|
|
* *
|
|
* hpid - A handle to the process. *
|
|
* htid - A handle to the thread. *
|
|
* *lpaddrFrame - The current frame. *
|
|
* *lpaddrPC - The code addres of the current frame. *
|
|
* lpaddrPC - A pointer to the return address. *
|
|
* *
|
|
* OUTPUTS: *
|
|
* *
|
|
* Return Value - *
|
|
* *
|
|
* xosdNone - Success. *
|
|
* Any value that can be returned by the Get Return Function *
|
|
* of the execution model called. *
|
|
* *
|
|
* *lpaddr - The previous frame address. *
|
|
* *
|
|
* IMPLEMENTATION: *
|
|
* *
|
|
* Send the current addres of the htid to the frame. Send the *
|
|
* lpaddrPC into the execution model with the get return command. *
|
|
* *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
XOSD PASCAL OSDGetCaller (
|
|
HPID hpid,
|
|
HTID htid,
|
|
FCT fct,
|
|
LPADDR lpaddrFrame,
|
|
LPADDR lpaddrPC ) {
|
|
|
|
(void)CallEM ( emfSetAddr, hpid, htid, adrCurrent, lpaddrFrame );
|
|
|
|
return CallEM ( emfGetCaller, hpid, htid, fct, lpaddrPC );
|
|
}
|
|
|
|
|
|
/**** OSDSAVEREGS - Save the register set of the thread ****
|
|
* *
|
|
* PURPOSE: *
|
|
* *
|
|
* Save the register set of the thread htid in an allocated handle *
|
|
* that is returned in *lphmem. *
|
|
* *
|
|
* INPUTS: *
|
|
* *
|
|
* hpid - A handle to the process. *
|
|
* htid - A handle to the thread. *
|
|
* lphmem - A pointer in which to return the register buffer. *
|
|
* *
|
|
* OUTPUTS: *
|
|
* *
|
|
* Return Value - *
|
|
* *
|
|
* xosdNone - Success. *
|
|
* Any value that can be returned by the Save Register Function *
|
|
* of the execution model called. *
|
|
* *
|
|
* *lphmem - The buffer in which the registers are saved. *
|
|
* *
|
|
* IMPLEMENTATION: *
|
|
* *
|
|
* Call the execution model to save the registers. *
|
|
* *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
XOSD PASCAL OSDSaveRegs ( HPID hpid, HTID htid, LPHIND lphmem ) {
|
|
|
|
return CallEM ( emfSaveRegs, hpid, htid, 0, lphmem );
|
|
}
|
|
|
|
|
|
/**** OSDRESTORREGS - Restore the registers of the thread from hmem ****
|
|
* *
|
|
* PURPOSE: *
|
|
* *
|
|
* Restore the register set(s) of the thread htid with the values *
|
|
* save by OSDSaveRegs in hmem. *
|
|
* *
|
|
* INPUTS: *
|
|
* *
|
|
* hpid - A handle to the process. *
|
|
* htid - A handle to the thread. *
|
|
* hmem - A handle to a valid register set for the thread. *
|
|
* *
|
|
* OUTPUTS: *
|
|
* *
|
|
* Return Value - *
|
|
* *
|
|
* xosdNone - Success. *
|
|
* Any value that can be returned by the Restore Register Function*
|
|
* of the execution model called. *
|
|
* *
|
|
* IMPLEMENTATION: *
|
|
* *
|
|
* Call the execution model to restore the registers. *
|
|
* *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
XOSD PASCAL OSDRestoreRegs ( HPID hpid, HTID htid, HIND hmem ) {
|
|
|
|
return CallEM ( emfRestoreRegs, hpid, htid, 0, (LPV) hmem );
|
|
}
|
|
|
|
|
|
#ifdef KBDMON
|
|
/**** OSDKBDRECORD - turn keyboard recording on or off ****
|
|
* *
|
|
* PURPOSE: *
|
|
* *
|
|
* Call the EM to set or clear the keyboard recording flag *
|
|
* *
|
|
* INPUTS: *
|
|
* *
|
|
* hpid - A handle to the process. *
|
|
* htid - A handle to the thread. *
|
|
* fOn - new value for the flag *
|
|
* *
|
|
* OUTPUTS: *
|
|
* *
|
|
* Return Value - *
|
|
* *
|
|
* xosdNone - Success. *
|
|
* *
|
|
* IMPLEMENTATION: *
|
|
* *
|
|
* Call the execution model to set or clear the flag *
|
|
* *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
XOSD PASCAL OSDKbdRecord ( HPID hpid, HTID htid, BOOL fOn ) {
|
|
|
|
return CallEM ( emfKbdRecord, hpid, htid, fOn, NULL );
|
|
}
|
|
|
|
|
|
/**** OSDKBDPLAY - play back keyboard information ****
|
|
* *
|
|
* PURPOSE: *
|
|
* *
|
|
* Call the EM to play back keyboard string *
|
|
* *
|
|
* INPUTS: *
|
|
* *
|
|
* hpid - A handle to the process. *
|
|
* htid - A handle to the thread. *
|
|
* pszPlay - string to process *
|
|
* *
|
|
* OUTPUTS: *
|
|
* *
|
|
* Return Value - *
|
|
* *
|
|
* xosdNone - Success. *
|
|
* *
|
|
* IMPLEMENTATION: *
|
|
* *
|
|
* Call the execution model to play the string *
|
|
* *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
XOSD PASCAL OSDKbdPlay ( HPID hpid, HTID htid, LSZ lszPlay ) {
|
|
|
|
return CallEM ( emfKbdPlay, hpid, htid, 0, (LPV)lszPlay );
|
|
}
|
|
#endif // KBDMON
|
|
|
|
#endif // 0
|
|
|
|
XOSD PASCAL
|
|
OSDGetRegDesc (
|
|
HPID hpid,
|
|
HTID htid,
|
|
UINT iReg,
|
|
RD FAR * lprd
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get the internal description of what a specific register looks
|
|
like. This is provided for general UI interfaces. See the
|
|
RD structure for more info.
|
|
|
|
Arguments:
|
|
|
|
hpid - Supplies process
|
|
|
|
htid - Supplies thread (optional?)
|
|
|
|
iReg - Supplies index of register
|
|
|
|
lprd - Returns requested info in an RD structure
|
|
|
|
Return Value:
|
|
|
|
xosdNone. Results are undefined if iReg is out of range.
|
|
|
|
--*/
|
|
{
|
|
return CallEM ( emfGetRegStruct, hpid, htid, iReg, lprd );
|
|
}
|
|
|
|
|
|
XOSD PASCAL
|
|
OSDGetFlagDesc (
|
|
HPID hpid,
|
|
HTID htid,
|
|
UINT iFlag,
|
|
FD FAR * lpfd
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get the internal description of what a specific flag looks
|
|
like. This is provided for general UI interfaces.
|
|
|
|
Arguments:
|
|
|
|
hpid - Supplies process
|
|
|
|
htid - Supplies thread (unused?)
|
|
|
|
iReg - Supplies index of requested flag
|
|
|
|
lprd - Returns FD structure describing flag
|
|
|
|
Return Value:
|
|
|
|
xosdNone. If iReg is out of range, behaviour is undefined.
|
|
|
|
--*/
|
|
{
|
|
return CallEM ( emfGetFlagStruct, hpid, htid, iFlag, lpfd );
|
|
}
|
|
|
|
|
|
XOSD PASCAL
|
|
OSDRegisterEmi (
|
|
HPID hpid,
|
|
HTID htid,
|
|
HEMI hemi,
|
|
LSZ lsz
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Register an EMI and filename with the EM. This hooks up the
|
|
symbol table info for a module to the EM's representation of
|
|
the module in the process.
|
|
|
|
Arguments:
|
|
|
|
hpid - Supplies process
|
|
|
|
htid - Supplies thread (unused)
|
|
|
|
hemi - Supplies handle from SH to symbolic info
|
|
|
|
lsz - Supplies the name of the module
|
|
|
|
Return Value:
|
|
|
|
xosdNone on success. Current implementation never reports failure.
|
|
|
|
--*/
|
|
{
|
|
REMI remi;
|
|
|
|
remi.hemi = hemi;
|
|
remi.lsz = lsz;
|
|
|
|
return CallEM ( emfRegisterEmi, hpid, htid, 0, &remi );
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
* *
|
|
* Services provided for execution model and transport layer *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
XOSD PASCAL LOADDS
|
|
EMCallBackDB (
|
|
DBC dbc,
|
|
HPID hpid,
|
|
HTID htid,
|
|
DWORD wModel,
|
|
DWORD cb,
|
|
LPV lpv
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Send callback messages from an execution model to the debugger.
|
|
The messages get passed through all intervening higher-level
|
|
execution models.
|
|
|
|
If dbc is a dbco value, it creates the appropriate thread or
|
|
process and returns the hpid or htid in *lpv.
|
|
|
|
Otherwise, it calls OSDCallbackToEM to query all of the higher
|
|
level EM's associated with the process. If none of them
|
|
handled the callback, it then calls the debugger's callback
|
|
function via OSDDoCallback.
|
|
|
|
Arguments:
|
|
|
|
dbc - Supplies the callback message
|
|
|
|
hpid - Supplies handle to the process
|
|
|
|
htid - Supplies handle to the thread
|
|
|
|
wModel - Supplies index of EM initiating the callback
|
|
|
|
cb - Supplies the number of bytes pointed to by lpv
|
|
|
|
lpv - Supplies data associated with the callback,
|
|
Returns data for dbco callbacks.
|
|
|
|
Return Value:
|
|
|
|
xosdNone - Success
|
|
|
|
Any value that can be returned by the debugger or higher
|
|
level execution models.
|
|
|
|
--*/
|
|
{
|
|
XOSD xosd = xosdNone;
|
|
|
|
//
|
|
// Several threads can execute this, so we protect it with a critical
|
|
// section.
|
|
//
|
|
EnterCriticalSection( &CallbackCriticalSection );
|
|
|
|
switch ( dbc ) {
|
|
|
|
case dbcoCreateThread:
|
|
|
|
xosd = CreateThd ( hpid, htid, &htid );
|
|
*( (LPHTID) lpv) = htid;
|
|
goto Return;
|
|
//return xosd;
|
|
|
|
case dbcoNewProc: {
|
|
LPPID lppid = LLLock ( (HLLE)hpid );
|
|
HPID hpidT = hpid;
|
|
LPEMP lpemp = LLLock ( (HLLE)(lppid->hempNative) );
|
|
|
|
xosd = CreateProc (
|
|
lppid->lpfnsvcCC,
|
|
lpemp->hem,
|
|
lppid->htl,
|
|
&hpid
|
|
);
|
|
|
|
*( (LPHPID) lpv) = hpid;
|
|
LLUnlock ( (HLLE)(lppid->hempNative) );
|
|
LLUnlock ( (HLLE)hpidT );
|
|
}
|
|
goto Return;
|
|
//return xosd;
|
|
}
|
|
|
|
// hit all of the EMs with the DoCallback, a la CallEM,
|
|
// hitting the debugger last
|
|
xosd = OSDDoCallBackToEM ( dbc, hpid, htid, cb, (LONG) lpv );
|
|
|
|
// if xosd is xosdPunt then all non-native EMs punted on the notification
|
|
if ( xosd == xosdPunt ) {
|
|
xosd = OSDDoCallBack ( dbc, hpid, htid, wModel, cb, (LONG) lpv );
|
|
}
|
|
|
|
Return:
|
|
|
|
LeaveCriticalSection( &CallbackCriticalSection );
|
|
|
|
return xosd;
|
|
}
|
|
|
|
|
|
XOSD PASCAL LOADDS
|
|
EMCallBackTL (
|
|
TLF wCmd,
|
|
HPID hpid,
|
|
DWORD cb,
|
|
LPV lpv
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Send messages from the execution model (native) to the transport layer.
|
|
|
|
Arguments:
|
|
|
|
wCmd - Supplies the message
|
|
hpid - Supplies process
|
|
cb - Supplies the size of the buffer at lpv, in bytes
|
|
lpv - Supplies or Returns data specific to the command
|
|
|
|
Return Value:
|
|
|
|
xosdNone for success, TL may return other xosd codes to
|
|
describe failure.
|
|
|
|
--*/
|
|
{
|
|
return CallTL ( wCmd, hpid, cb, lpv );
|
|
}
|
|
|
|
|
|
|
|
XOSD PASCAL LOADDS
|
|
EMCallBackNT (
|
|
EMF emf,
|
|
HPID hpid,
|
|
HTID htid,
|
|
DWORD cb,
|
|
LPV lpv
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Provides native em services to higher level EMs. Sends messages
|
|
from the execution model (non-native) to the native execution model
|
|
for the process hpid.
|
|
|
|
Arguments:
|
|
|
|
emf - Supplies the execution model function number
|
|
|
|
hpid - Supplies process
|
|
|
|
htid - Supplies thread
|
|
|
|
cb - Supplies size of buffer at lpv in bytes
|
|
|
|
lpv - Supplies and Returns data for EM service
|
|
|
|
Return Value:
|
|
|
|
xosdNone - Success
|
|
|
|
xosdInvalidPID - hpid is not a handle to a process.
|
|
|
|
Any value that can be returned by the native execution model.
|
|
|
|
--*/
|
|
{
|
|
XOSD xosd = xosdNone;
|
|
LPPID lppid;
|
|
HEMP hemp;
|
|
LPEMP lpemp;
|
|
|
|
lppid = LLLock ( (HLLE)hpid );
|
|
if ( lppid == NULL ) {
|
|
return xosdInvalidPID;
|
|
}
|
|
|
|
hemp = lppid->hempNative;
|
|
LLUnlock ( (HLLE)hpid );
|
|
|
|
lpemp = LLLock ( (HLLE)hemp );
|
|
xosd = (lpemp->emfunc) ( emf, hpid, htid, cb, (LONG) lpv );
|
|
LLUnlock ( (HLLE)hemp );
|
|
|
|
return xosd;
|
|
}
|
|
|
|
|
|
XOSD PASCAL LOADDS
|
|
EMCallBackEM (
|
|
EMF emf,
|
|
HPID hpid,
|
|
HTID htid,
|
|
DWORD wModel,
|
|
DWORD cb,
|
|
LPV lpv
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Provides EM services to other EMs. Sends messages from one
|
|
non-native EM to the next EM in the chain for the process hpid.
|
|
|
|
Arguments:
|
|
|
|
emf - Supplies EM function number
|
|
|
|
hpid - Supplies handle to the process
|
|
|
|
htid - Supplies handle to the thread
|
|
|
|
wModel - Supplies EM # of calling EM
|
|
|
|
cb - Supplies size in bytes of buffer at lpv.
|
|
|
|
lpv - Supplies and Returns data for EM service
|
|
|
|
Return Value:
|
|
|
|
xosd code returned by the EM that handles the service request.
|
|
|
|
--*/
|
|
{
|
|
XOSD xosd = xosdNone;
|
|
LPPID lppid;
|
|
HEMP hemp = 0;
|
|
HEMP hempnext = 0;
|
|
LPEMP lpemp;
|
|
|
|
assert ( hpid != NULL );
|
|
|
|
//native ems can never make this callback!
|
|
assert ( wModel != CEXM_MDL_native );
|
|
|
|
lppid = LLLock ( (HLLE)hpid );
|
|
|
|
if ( lppid == NULL ) {
|
|
return xosdInvalidPID;
|
|
}
|
|
|
|
while ( hemp = LLNext ( (HLLI)(lppid->llemp), (HLLE)hemp ) ) {
|
|
lpemp = LLLock ( (HLLE)hemp );
|
|
if ( lpemp->model == wModel ) {
|
|
hempnext = LLNext ( (HLLI)(lppid->llemp), (HLLE)hemp );
|
|
break;
|
|
}
|
|
LLUnlock ( (HLLE)hemp );
|
|
}
|
|
|
|
assert ( hempnext != 0 );
|
|
|
|
lpemp = LLLock ( (HLLE)hempnext );
|
|
xosd = (lpemp->emfunc) ( emf, hpid, htid, cb, (LONG) lpv );
|
|
LLUnlock ( (HLLE)hempnext );
|
|
|
|
LLUnlock ( (HLLE)hpid );
|
|
|
|
return xosd;
|
|
}
|
|
|
|
|
|
XOSD PASCAL LOADDS
|
|
TLCallBack (
|
|
HPID hpid,
|
|
UINT cb,
|
|
LPV lpv
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Call the native execution model for the process hpid with the
|
|
package sent from the transport layer. This is how the DM
|
|
sends things to its native EM.
|
|
|
|
Arguments:
|
|
|
|
hpid - Supplies handle to the process
|
|
|
|
cb - Supplies size in bytes of the packet
|
|
|
|
lpv - Supplies the packet
|
|
|
|
Return Value:
|
|
|
|
xosdNone - Success
|
|
|
|
Any return value that can be generated by a native execution model.
|
|
|
|
--*/
|
|
{
|
|
XOSD xosd = xosdNone;
|
|
LPEMP lpemp;
|
|
LPPID lppid;
|
|
EMFUNC emfunc;
|
|
|
|
assert ( hpid != NULL );
|
|
|
|
//NOTENOTE a-kentf this probably doesn't have to Unlock before calling
|
|
lppid = LLLock ( (HLLE)hpid );
|
|
lpemp = LLLock ( (HLLE)(lppid->hempNative) );
|
|
emfunc = lpemp->emfunc;
|
|
LLUnlock ( (HLLE)(lppid->hempNative) );
|
|
LLUnlock ( (HLLE)hpid );
|
|
|
|
xosd = (*emfunc)( emfDebugPacket, hpid, htidNull, cb, (LONG) lpv );
|
|
|
|
return xosd;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
* *
|
|
* Internal Support functions *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
|
|
|
|
/**** CallEM - Call the execution model for hpid:htid ****
|
|
* *
|
|
* PURPOSE: *
|
|
* *
|
|
* This function multiplexes on the hpid and htid values to call *
|
|
* the most specific execution model possible. *
|
|
* *
|
|
* INPUTS: *
|
|
* *
|
|
* emf, wValue, lValue, lpxosd: These are all just passed through *
|
|
* to the actual execution model service function. *
|
|
* *
|
|
* hpid - This is the process that the execution model service *
|
|
* function is to handle. If it is null, the first execution *
|
|
* model that was registered with osdebug is called. *
|
|
* Hpid must not be invalid. *
|
|
* *
|
|
* htid - This is the thread that the execution model service *
|
|
* function is to handle. If it is null, the native execution *
|
|
* model for the pid is called. Htid must not be invalid. *
|
|
* *
|
|
* OUTPUTS: *
|
|
* *
|
|
* Return Value - This will return whatever the execution model *
|
|
* service function that it calls returns. *
|
|
* *
|
|
* *lpxosd - The errors returned here are those defined by the *
|
|
* execution model service function that was called. *
|
|
* *
|
|
* IMPLEMENTATION: *
|
|
* *
|
|
* Find the most specific em available. This is the current em *
|
|
* for the pid:tid if both pid & tid are non-Null, the native *
|
|
* execution model for the pid if the tid is null but the pid is *
|
|
* non-Null, or the first em installed if both pid & tid are null. *
|
|
* *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
|
|
XOSD
|
|
CallEM(
|
|
EMF emf,
|
|
HPID hpid,
|
|
HTID htid,
|
|
DWORD wValue,
|
|
LPV lpv
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
|
|
XOSD xosd = xosdNone;
|
|
HEMP hemp;
|
|
LPPID lppid;
|
|
LPEMP lpemp;
|
|
HLLI llemx;
|
|
|
|
if ( hpid == NULL ) {
|
|
|
|
// get oldest native EM.
|
|
if (llem != NULL) {
|
|
hemp = (HEMP)LLLast ( llemx = llem );
|
|
} else {
|
|
return xosdUnknown;
|
|
}
|
|
if (hemp == NULL) {
|
|
return xosdUnknown;
|
|
}
|
|
} else {
|
|
|
|
lppid = LLLock ( (HLLE)hpid );
|
|
assert ( lppid != NULL );
|
|
hemp = (HEMP)LLNext ( (llemx = lppid->llemp), NULL );
|
|
LLUnlock ( (HLLE)hpid );
|
|
|
|
}
|
|
|
|
lpemp = LLLock ( (HLLE)hemp );
|
|
if (lpemp->emfunc != NULL) {
|
|
xosd = (lpemp->emfunc)( emf, hpid, htid, wValue, (LONG) lpv );
|
|
} else {
|
|
xosd = xosdUnknown;
|
|
}
|
|
LLUnlock ( (HLLE)hemp );
|
|
|
|
if (xosd == xosdPunt) {
|
|
|
|
hemp = (HEMP)LLNext ( llemx, (HLLE)hemp );
|
|
|
|
do {
|
|
lpemp = LLLock ( (HLLE)hemp );
|
|
xosd = (lpemp->emfunc) ( emf, hpid, htid, wValue, (LONG) lpv );
|
|
LLUnlock ( (HLLE)hemp );
|
|
} while (xosd == xosdPunt &&
|
|
(hemp = (HEMP)LLNext ( llemx, (HLLE)hemp )) );
|
|
|
|
if (xosd == xosdPunt) {
|
|
xosd = xosdUnsupported;
|
|
}
|
|
}
|
|
|
|
return xosd;
|
|
}
|
|
|
|
|
|
/**** CallTL - Call the transport layer for hpid ****
|
|
* *
|
|
* PURPOSE: *
|
|
* *
|
|
* *
|
|
* INPUTS: *
|
|
* *
|
|
* tlf, htid, wValue, lpv - These are all just passed *
|
|
* through to the actual transport layer service function. *
|
|
* *
|
|
* hpid - This is the process that the transport layer service *
|
|
* function is to handle. If it is null, the first transport *
|
|
* layer that was registered with osdebug is called. *
|
|
* Hpid must not be invalid. *
|
|
* *
|
|
* OUTPUTS: *
|
|
* *
|
|
* Return Value - This will return whatever the transport layer *
|
|
* service function that it calls returns. *
|
|
* *
|
|
* *lpxosd - The errors returned here are those defined by the *
|
|
* transport layer service function that was called. *
|
|
* *
|
|
* IMPLEMENTATION: *
|
|
* *
|
|
* Find the most specific tl available. This is the transport *
|
|
* layer associated with the pid if the pid is non-Null, otherwise *
|
|
* it is the first transport layer registered with osdebug. *
|
|
* *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
XOSD
|
|
CallTL (
|
|
TLF tlf,
|
|
HPID hpid,
|
|
DWORD wValue,
|
|
LPV lpv
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Call the transport layer associated with hpid, and send it a
|
|
message and packet.
|
|
|
|
Arguments:
|
|
|
|
tlf - Supplies transport layer function number.
|
|
|
|
hpid - Supplies process.
|
|
|
|
wValue - Supplies function dependent data.
|
|
|
|
lpv - Supplies and Returns data depending on function.
|
|
|
|
Return Value:
|
|
|
|
xosd status code, as returned by the TL.
|
|
|
|
--*/
|
|
{
|
|
XOSD xosd = xosdNone;
|
|
HTL htl;
|
|
LPTL lptl;
|
|
|
|
if ( hpid == NULL ) {
|
|
htl = LLNext ( lltl, htlNull );
|
|
}
|
|
else {
|
|
LPPID lppid = LLLock ( (HLLE)hpid );
|
|
htl = lppid->htl;
|
|
LLUnlock ( (HLLE)hpid );
|
|
}
|
|
|
|
lptl = LLLock ( (HLLE)htl );
|
|
xosd = lptl->tlfunc ( tlf, hpid, wValue, (LONG) lpv );
|
|
LLUnlock ( (HLLE)htl );
|
|
|
|
return xosd;
|
|
}
|
|
|
|
|
|
|
|
/**** OSDDOCALLBACK - Call the debug client with a notification message ****
|
|
* *
|
|
* PURPOSE: *
|
|
* *
|
|
* INPUTS: *
|
|
* *
|
|
* OUTPUTS: *
|
|
* *
|
|
* IMPLEMENTATION: *
|
|
* *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
XOSD
|
|
OSDDoCallBack (
|
|
UINT wCommand,
|
|
HPID hpid,
|
|
HTID htid,
|
|
UINT wModel,
|
|
UINT wValue,
|
|
LONG lValue
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
|
|
XOSD xosd = xosdNone;
|
|
LPPID lppid;
|
|
|
|
assert ( hpid != NULL );
|
|
|
|
lppid = LLLock ( (HLLE)hpid );
|
|
switch ( wCommand ) {
|
|
case dbcBpt:
|
|
case dbcStep:
|
|
case dbcCheckBpt:
|
|
case dbcProcTerm:
|
|
case dbcThreadTerm:
|
|
case dbcException:
|
|
case dbcWatchPoint:
|
|
case dbcEntryPoint:
|
|
|
|
if ( lppid->lastmodel != wModel ) {
|
|
|
|
// model has changed, issue dbcEmChange notification
|
|
xosd = lppid->lpfnsvcCC ( dbcEmChange, hpid, htid, wModel, (LONG) 0 );
|
|
lppid->lastmodel = wModel;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
|
|
// same model as before, do nothing
|
|
break;
|
|
}
|
|
|
|
xosd = lppid->lpfnsvcCC (( USHORT ) wCommand, hpid, htid, wValue, lValue );
|
|
|
|
LLUnlock ( (HLLE)hpid );
|
|
|
|
switch ( wCommand ) {
|
|
case dbcThreadDestroy:
|
|
// The shell will call OSDDestroyTID(), instead of
|
|
// us doing it here.
|
|
break;
|
|
|
|
case dbcProcTerm:
|
|
// same here; the shell calls OSDDestroyPID() when it
|
|
// is finished using the structures.
|
|
break;
|
|
}
|
|
|
|
return xosd;
|
|
}
|
|
|
|
|
|
XOSD
|
|
OSDDoCallBackToEM (
|
|
EMF wCommand,
|
|
HPID hpid,
|
|
HTID htid,
|
|
UINT wValue,
|
|
LONG lValue
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Call all of the non-native EMs with a notification message.
|
|
|
|
Arguments:
|
|
|
|
wCommand - Supplies the message
|
|
|
|
hpid - Supplies process
|
|
|
|
htid - Supplies thread
|
|
|
|
wValue - Supplies message dependent data
|
|
|
|
lValue - Supplies message dependent data
|
|
|
|
Return Value:
|
|
|
|
An xosd status code. xosdPunt means it was not handled by any EM.
|
|
If an EM handles it, xosdNone or a failure status will be returned.
|
|
|
|
--*/
|
|
{
|
|
|
|
XOSD xosd = xosdPunt;
|
|
HEM hemp;
|
|
LPEMP lpemp;
|
|
LPPID lppid;
|
|
|
|
assert ( hpid != NULL );
|
|
|
|
// get handle to the native EM
|
|
lppid = LLLock ( (HLLE)hpid );
|
|
if ( lppid->fNative ) {
|
|
LLUnlock((HLLE) hpid );
|
|
// native only mode, return
|
|
return xosd;
|
|
}
|
|
LLUnlock ( (HLLE)hpid );
|
|
|
|
// M00BUG - this is not correct. we should be hitting the ems
|
|
// in the reverse order that they are in the list.
|
|
// This will bite us when we move to multiple nms
|
|
|
|
hemp = hemNull;
|
|
while ( xosd == xosdPunt ) {
|
|
if ( ! ( hemp = LLNext ( (HLLI)(lppid->llemp), (HLLE)hemp ) ) ) {
|
|
return xosd;
|
|
}
|
|
|
|
lpemp = LLLock ( (HLLE)hemp );
|
|
|
|
if ( lpemp->emtype == emNative ) {
|
|
LLUnlock ( (HLLE)hemp );
|
|
return xosd;
|
|
}
|
|
|
|
xosd = (lpemp->emfunc) ( wCommand, hpid, htid, wValue, lValue );
|
|
LLUnlock ( (HLLE)hemp );
|
|
}
|
|
return xosd;
|
|
}
|
|
|
|
|
|
/**** CREATEPROC - Create a process data struct and add to proc list ****
|
|
* *
|
|
* PURPOSE: *
|
|
* *
|
|
* INPUTS: *
|
|
* *
|
|
* OUTPUTS: *
|
|
* *
|
|
* IMPLEMENTATION: *
|
|
* *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
|
|
XOSD
|
|
CreateProc (
|
|
LPFNSVC lpfnsvc,
|
|
HEM hem,
|
|
HTL htl,
|
|
LPHPID lphpid
|
|
)
|
|
{
|
|
|
|
XOSD xosd = xosdNone;
|
|
HPID hpid;
|
|
LPPID lppid;
|
|
HEMP hemp;
|
|
LPEMP lpemp;
|
|
HEM hodem = hmemNull;
|
|
LPEM lpem;
|
|
HPID hpidem = hmemNull;
|
|
LPHPID lphpidt;
|
|
|
|
hpid = (HPID)LLCreate ((HLLI) llpid );
|
|
if ( hpid == NULL ) {
|
|
return xosdOutOfMemory;
|
|
}
|
|
|
|
LLAdd ( (HLLI)llpid, (HLLE)hpid );
|
|
|
|
lppid = LLLock ( (HLLE)hpid );
|
|
lppid->htl = htl;
|
|
lppid->fNative = FALSE;
|
|
lppid->lastmodel = CEXM_MDL_native;
|
|
lppid->lpfnsvcCC = lpfnsvc;
|
|
|
|
lppid->lltid = LLInit ( sizeof ( TIDS ), llfNull, NULL, NULL );
|
|
lppid->llemp = LLInit ( sizeof ( EMPS ), llfNull, EMPKill, NULL );
|
|
|
|
if ( lppid->llemp == 0 || lppid->lltid == 0 ) {
|
|
xosd == xosdOutOfMemory;
|
|
}
|
|
|
|
// create llem in lppid
|
|
|
|
while ( hodem = LLNext ( (HLLI)llem, (HLLE)hodem ) ) {
|
|
hemp = LLCreate ( (HLLI)(lppid->llemp) );
|
|
if ( hemp == hemNull ) {
|
|
return xosdOutOfMemory;
|
|
}
|
|
lpem = LLLock ( (HLLE)hodem );
|
|
lpemp = LLLock ( (HLLE)hemp );
|
|
|
|
// copy relevant info to hpid's emp
|
|
lpemp->hem = hodem;
|
|
lpemp->emfunc = lpem->emfunc;
|
|
lpemp->emtype = lpem->emtype;
|
|
if ( ! lpem->emtype && hodem == hem ) {
|
|
lppid->hempNative = hemp;
|
|
}
|
|
lpemp->model = lpem->model;
|
|
|
|
LLUnlock ( (HLLE)hemp );
|
|
LLUnlock ( (HLLE)hodem );
|
|
LLAdd ( (HLLI)(lppid->llemp), (HLLE)hemp );
|
|
}
|
|
|
|
// add the hpid to all em's list of hpids
|
|
|
|
hemp = hodem = hmemNull;
|
|
while ( hodem = LLNext ( (HLLI)llem, (HLLE)hodem ) ) {
|
|
|
|
lpem = LLLock ( (HLLE)hodem );
|
|
hpidem = (HPID)LLCreate ( (HLLI)(lpem->llhpid) );
|
|
if ( hpidem == hemNull ) {
|
|
LLUnlock((HLLE)hpid);
|
|
return xosdOutOfMemory;
|
|
}
|
|
lphpidt = LLLock ( (HLLE)hpidem );
|
|
|
|
// puts hpid in node
|
|
*lphpidt = hpid;
|
|
|
|
LLUnlock ( (HLLE)hpidem );
|
|
LLUnlock ( (HLLE)hodem );
|
|
LLAdd ( (HLLI)(lpem->llhpid), (HLLE)hpidem );
|
|
}
|
|
|
|
// clean up
|
|
|
|
LLUnlock ( (HLLE)hpid );
|
|
|
|
if (xosd == xosdNone) {
|
|
*lphpid = hpid;
|
|
}
|
|
|
|
return xosd;
|
|
}
|
|
|
|
|
|
/**** CREATETHD - Create a thread data struct & add to process ****
|
|
* *
|
|
* PURPOSE: *
|
|
* *
|
|
* INPUTS: *
|
|
* *
|
|
* OUTPUTS: *
|
|
* *
|
|
* IMPLEMENTATION: *
|
|
* *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
|
|
XOSD
|
|
CreateThd (
|
|
HPID hpid,
|
|
HTID htid,
|
|
LPHTID lphtid
|
|
)
|
|
{
|
|
HTID htidT;
|
|
LPTID lptidT;
|
|
LPPID lppid;
|
|
|
|
Unreferenced( htid );
|
|
|
|
lppid = LLLock ( (HLLE)hpid );
|
|
|
|
htidT = (HTID)LLCreate ( (HLLI)(lppid->lltid) );
|
|
if ( htidT == htidNull ) {
|
|
LLUnlock ( (HLLE)hpid );
|
|
return xosdOutOfMemory;
|
|
}
|
|
|
|
LLAdd((HLLI)(lppid->lltid), (HLLE)htidT);
|
|
|
|
lptidT = LLLock ( (HLLE)htidT );
|
|
lptidT->hpid = hpid;
|
|
|
|
LLUnlock ( (HLLE)htidT );
|
|
LLUnlock ( (HLLE)hpid );
|
|
|
|
*lphtid = htidT;
|
|
return xosdNone;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* *
|
|
* Kill and compare functions for the various lists used by osdebug *
|
|
* *
|
|
****************************************************************************/
|
|
|
|
|
|
void PASCAL LOADDS
|
|
ODPDKill (
|
|
LPV lpv
|
|
)
|
|
{
|
|
LPPID lppid = (LPPID) lpv;
|
|
|
|
LLDestroy ( lppid->llemp );
|
|
LLDestroy ( lppid->lltid );
|
|
}
|
|
|
|
|
|
void PASCAL LOADDS
|
|
EMKill (
|
|
LPV lpv
|
|
)
|
|
{
|
|
LPEM lpem = (LPEM) lpv;
|
|
|
|
LLDestroy ( lpem->llhpid );
|
|
}
|
|
|
|
|
|
void PASCAL LOADDS
|
|
EMPKill (
|
|
LPV lpv
|
|
)
|
|
{
|
|
Unreferenced( lpv );
|
|
return;
|
|
}
|
|
|
|
void PASCAL LOADDS
|
|
TLKill (
|
|
LPV lpv
|
|
)
|
|
{
|
|
LPTL lptl = (LPTL) lpv;
|
|
LLDestroy ( lptl->llpid );
|
|
}
|
|
|
|
int FAR PASCAL LOADDS
|
|
EMHpidCmp (
|
|
LPV lpv1,
|
|
LPV lpv2,
|
|
LONG lParam
|
|
)
|
|
{
|
|
Unreferenced( lParam );
|
|
|
|
if ( *( (LPHPID) lpv1) == *( (LPHPID) lpv2 ) ) {
|
|
return fCmpEQ;
|
|
} else {
|
|
return fCmpLT;
|
|
}
|
|
}
|
|
|
|
|
|
/************************************************************************/
|
|
|
|
/* Exception Handling */
|
|
|
|
/************************************************************************/
|
|
|
|
|
|
XOSD PASCAL
|
|
OSDGetExceptionState(
|
|
HPID hpid,
|
|
HTID htid,
|
|
LPEXCEPTION_DESCRIPTION lpExd,
|
|
EXCEPTION_CONTROL exf
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Given an address of an EXCEPTION_DESC filled in with the exception
|
|
code look up the code in the table and return a pointer to the
|
|
real exception info structure for that exception.
|
|
|
|
Arguments:
|
|
|
|
hpid - Supplies process
|
|
|
|
htid - Supplies thread
|
|
|
|
lpExd - A pointer to an exception structure to be filled in.
|
|
The dwExceptionCode member of this structure must be set
|
|
in order to use the exfSpecified or exfNext parmeter
|
|
|
|
exf - one of:
|
|
exfFirst
|
|
exfNext
|
|
exfSpecified
|
|
|
|
Return Value:
|
|
|
|
xosdNone - Success
|
|
|
|
--*/
|
|
{
|
|
if (hpid || !htid) {
|
|
return CallEM ( emfGetExceptionState, hpid, htid, exf, lpExd );
|
|
} else {
|
|
return (*(EMFUNC)htid)(emfGetExceptionState, NULL, NULL, exf, lpExd);
|
|
}
|
|
}
|
|
|
|
|
|
XOSD PASCAL
|
|
OSDSetExceptionState (
|
|
HPID hpid,
|
|
HTID htid,
|
|
LPEXCEPTION_DESCRIPTION lpExd
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Set the exception state for the given hpid/htid.
|
|
|
|
First implementation of this API should ignore the HTID parameter
|
|
as it is intended that it will only be able to Get/Set thread
|
|
exception states on a per process basis rather than on a per thread
|
|
basis. Should we choose in the future that there is a need to
|
|
Get/Set exception states on a per thread basis we can make use of
|
|
the HTID parameter at that time. At that time an htid of NULL would
|
|
indicate all threads.
|
|
|
|
Parameters:
|
|
|
|
hpid - Supplies process
|
|
|
|
htid - Supplies thread
|
|
|
|
lpExd - Supplies an exception structure to be Set. Should this
|
|
exception not be found in the current list of exceptions for
|
|
the given process/thread it will be added.
|
|
|
|
Return Value:
|
|
|
|
xosdNone: Success
|
|
|
|
--*/
|
|
{
|
|
return CallEM( emfSetExceptionState, hpid, htid, 0, lpExd );
|
|
}
|
|
|
|
|
|
|
|
|
|
XOSD PASCAL
|
|
OSDSetupExecute(
|
|
HPID hpid,
|
|
HTID htid,
|
|
LPHDEP lphdep
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is called to set up a thread for doing a function
|
|
evaluation. This is passed on the the EM for processing.
|
|
|
|
Arguments:
|
|
|
|
hpid - Supplies the handle to the process
|
|
|
|
htid - Supplies the handle to the thread
|
|
|
|
lphdep - Supplies a pointer to save the SAVEINFO handle at
|
|
|
|
Return Value:
|
|
|
|
XOSD error code
|
|
|
|
--*/
|
|
|
|
{
|
|
XOSD xosd;
|
|
xosd = CallEM( emfSetupExecute, hpid, htid, 0, lphdep);
|
|
|
|
return xosd;
|
|
} /* OSDSetupExecute() */
|
|
|
|
|
|
XOSD PASCAL
|
|
OSDStartExecute(
|
|
HPID hpid,
|
|
HDEP hdep,
|
|
LPADDR lpaddr,
|
|
BOOL fIgnoreEvents,
|
|
BOOL fFar
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Execute function evaluation.
|
|
|
|
Arguments:
|
|
|
|
hpid - Supplies the handle to the process
|
|
|
|
hdep - Supplies the exeute object handle
|
|
|
|
lpaddr - Supplies the address to start evaluation at
|
|
|
|
fIgnoreEvents - Supplies TRUE if sub-events are to be ignored
|
|
|
|
fFar - Supplies TRUE if this is an _far function
|
|
|
|
Return Value:
|
|
|
|
return-value - Description of conditions needed to return value. - or -
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
EXECUTE_STRUCT es;
|
|
|
|
es.addr = *lpaddr;
|
|
es.fIgnoreEvents = fIgnoreEvents;
|
|
es.fFar = fFar;
|
|
|
|
return CallEM( emfStartExecute, hpid, 0, (DWORD)hdep, &es);
|
|
} /* OSDStartExecute() */
|
|
|
|
|
|
XOSD PASCAL
|
|
OSDCleanUpExecute (
|
|
HPID hpid,
|
|
HDEP hdep
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is called to clean up a current pending function
|
|
evaluation.
|
|
|
|
Arguments:
|
|
|
|
hdep Supplies the handle to the execute object
|
|
|
|
Return Value:
|
|
|
|
XOSD error code
|
|
|
|
--*/
|
|
|
|
{
|
|
return CallEM( emfCleanUpExecute, hpid, htidNull, (DWORD)hdep, 0);
|
|
} /* OSDCleanUpExecute() */
|
|
|
|
|
|
|
|
XOSD PASCAL
|
|
OSDLoadDllAck(
|
|
HPID hpid
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is called in response to a modLoad message to inform
|
|
the DM that processing may now continue.
|
|
|
|
Arguments:
|
|
|
|
hpid - Supplies the handle to the process for the modLoad message
|
|
|
|
Return Value:
|
|
|
|
xosd error code
|
|
|
|
--*/
|
|
|
|
{
|
|
return CallEM( emfLoadDllAck, hpid, 0, 0, 0);
|
|
} /* OSDDllLoadAck */
|
|
|
|
|
|
|
|
XOSD PASCAL
|
|
OSDUnLoadDllAck(
|
|
HPID hpid,
|
|
HEXE emi,
|
|
BOOL fTellDM
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is called in response to a modLoad message to inform
|
|
the DM that processing may now continue.
|
|
|
|
Arguments:
|
|
|
|
hpid - Supplies the handle to the process for the modLoad message
|
|
|
|
emi - Supplies emi of module being unloaded.
|
|
|
|
Return Value:
|
|
|
|
xosd error code
|
|
|
|
--*/
|
|
|
|
{
|
|
return CallEM( emfUnLoadDllAck, hpid, 0, fTellDM, (LPV)emi);
|
|
}
|
|
|
|
|
|
XOSD
|
|
OSDDebugActive(
|
|
HPID hpid,
|
|
DWORD dwProcessId,
|
|
HANDLE hEventGo,
|
|
LPDWORD lpdwStatus
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Tell the EM to debug a process which is already running and not
|
|
being debugged. If this succeeds, the debugger will be notified
|
|
of a new process, very similar to the creation of a child of
|
|
a process already being debugged.
|
|
|
|
Arguments:
|
|
|
|
hpid - Supplies process to bind to the EM. If no process is
|
|
already being debugged, this will be the "root" process,
|
|
and will not yet have a real debuggee attached to it.
|
|
Otherwise, this may be any process which is bound to the
|
|
right native EM.
|
|
|
|
dwProcessId - Supplies the OS supplied process ID for the process to debug.
|
|
|
|
hEventGo - Supplies an optional event handle which the DM will signal
|
|
when the DM is ready to catch an exception in the process.
|
|
This is used when attaching to a crashed process in Win32.
|
|
|
|
lpdwStatus - Returns the error status from the DebugActiveProcess API.
|
|
|
|
Return Value:
|
|
|
|
xosdNone if the DebugActiveProcess succeeds. If it fails, the value
|
|
returned in the DWORD at lpdwStatus may be examined to learn the
|
|
cause of the failure.
|
|
|
|
--*/
|
|
{
|
|
DBG_ACTIVE_STRUCT dba;
|
|
XOSD xosd;
|
|
dba.dwProcessId = dwProcessId;
|
|
dba.hEventGo = hEventGo;
|
|
xosd = CallEM( emfDebugActive, hpid, htidNull, 0, &dba);
|
|
*lpdwStatus = dba.dwStatus;
|
|
return xosd;
|
|
}
|
|
|
|
|
|
XOSD
|
|
OSDStackWalkSetup(
|
|
HPID hpid,
|
|
HTID htid,
|
|
BOOL fInProlog,
|
|
LPSTKSTR lpstkstr
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is called to setup the stkstr structure which is used
|
|
to do a stack walk operation. After this function has been called
|
|
the current Program Counter and Frame Pointer will be set in the
|
|
stkstr as well as any flags needed for it.
|
|
|
|
Arguments:
|
|
|
|
hpid - Supplies the process handle to use
|
|
|
|
htid - Supplies the thread handle to use
|
|
|
|
fInProlog- Supplies TRUE if current address is in prolog
|
|
|
|
lpstkstr - Supplies a pointer to the Stack Walk Structure to fill-in
|
|
|
|
Return Value:
|
|
|
|
XOSD error code
|
|
|
|
--*/
|
|
|
|
{
|
|
return CallEM( emfStackWalkSetup, hpid, htid, fInProlog, lpstkstr);
|
|
|
|
} /* OSDStackWalkSetup() */
|
|
|
|
|
|
XOSD
|
|
OSDStackWalkNext(
|
|
HPID hpid,
|
|
HTID htid,
|
|
LPSTKSTR lpstkstr
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
hpid - Supplies the process handle to use
|
|
|
|
htid - Supplies the thread handle to use
|
|
|
|
lpstkstr - Supplies a pointer to the Stack Walk Structure to fill-in
|
|
|
|
Return Value:
|
|
|
|
XOSD error code
|
|
|
|
--*/
|
|
|
|
{
|
|
return CallEM( emfStackWalkNext, hpid, htid, 0, lpstkstr);
|
|
} /* OSDStackWalkNext() */
|
|
|
|
|
|
XOSD
|
|
OSDStackWalkCleanup(
|
|
HPID hpid,
|
|
HTID htid,
|
|
LPSTKSTR lpstkstr
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Tell the EM to clean up data structures used for walking stack
|
|
|
|
Arguments:
|
|
|
|
hpid - Supplies the process handle to use
|
|
|
|
htid - Supplies the thread handle to use
|
|
|
|
lpstkstr - Supplies a pointer to the Stack Walk Structure
|
|
|
|
Return Value:
|
|
|
|
XOSD error code
|
|
|
|
--*/
|
|
|
|
{
|
|
return CallEM( emfStackWalkCleanup, hpid, htid, 0, lpstkstr);
|
|
} /* OSDStackWalkCleanup() */
|
|
|
|
|
|
XOSD
|
|
OSDSetFrame(
|
|
HPID hpid,
|
|
HTID htid,
|
|
PFRAME pframe
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get a structure describing the current stack frame for a thread.
|
|
|
|
Arguments:
|
|
|
|
hpid - Supplies the process handle to use
|
|
|
|
htid - Supplies the thread handle to use
|
|
|
|
pframe - Returns FRAME structure
|
|
|
|
Return Value:
|
|
|
|
XOSD error code
|
|
|
|
--*/
|
|
|
|
{
|
|
return CallEM( emfSetFrame, hpid, htid, 0, pframe );
|
|
} /* OSDSetFrame() */
|
|
|
|
|
|
XOSD
|
|
OSDSetPath(
|
|
HPID hpid,
|
|
BOOL Set,
|
|
LSZ Path
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Sets the search path in the DM
|
|
|
|
Arguments:
|
|
|
|
hpid - Supplies process to bind EM
|
|
|
|
Set - Supplies TRUE to set new path, FALSE to turn
|
|
off path searching.
|
|
|
|
Path - Supplies search path string
|
|
|
|
Return Value:
|
|
|
|
XOSD error code
|
|
|
|
--*/
|
|
{
|
|
return CallEM( emfSetPath, hpid, 0, Set, Path );
|
|
}
|
|
|
|
|
|
/************************************************************************/
|
|
|
|
/* Breakpoints */
|
|
|
|
/************************************************************************/
|
|
|
|
|
|
XOSD PASCAL
|
|
OSDBreakpoint (
|
|
HPID hpid,
|
|
LPBPS lpbps
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
return CallEM ( emfBreakPoint, hpid, NULL, SizeofBPS(lpbps), lpbps);
|
|
}
|
|
|
|
|
|
XOSD
|
|
OSDGetPrompt(
|
|
HPID hpid,
|
|
LPPROMPTMSG lppm
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get a prompt string for command window. This provides a way
|
|
for the EM/DM pair to identify itself to the user.
|
|
|
|
Arguments:
|
|
|
|
hpid - Supplies process
|
|
|
|
lppm - Returns PROMPTMSG struct
|
|
|
|
Return Value:
|
|
|
|
XOSD error code
|
|
|
|
--*/
|
|
|
|
{
|
|
return CallEM( emfGetPrompt, hpid, 0, 0, lppm );
|
|
}
|
|
|
|
|
|
XOSD
|
|
OSDSendReply(
|
|
HPID hpid,
|
|
UINT cb,
|
|
LPVOID lpv
|
|
)
|
|
{
|
|
return CallEM( emfMiscReply, hpid, 0, cb, lpv );
|
|
}
|
|
|
|
|
|
XOSD PASCAL
|
|
OSDGetMemInfo(
|
|
HPID hpid,
|
|
LPMEMINFO lpMemInfo
|
|
)
|
|
{
|
|
return CallEM( emfGetMemInfo, hpid, 0, sizeof(MEMINFO), lpMemInfo );
|
|
}
|
|
|
|
|
|
|
|
|
|
XOSD
|
|
OSDGetFunctionInfo(
|
|
HPID hpid,
|
|
PADDR Addr,
|
|
PFUNCTION_INFO FunctionInfo
|
|
)
|
|
{
|
|
return CallEM( emfGetFunctionInfo, hpid, 0, (DWORD)Addr, FunctionInfo );
|
|
}
|
|
XOSD PASCAL
|
|
OSDGetProcessStatus (
|
|
HPID hpid,
|
|
LPPST lppst
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Returns a structure describing the process status for the given hpid.
|
|
|
|
uses emfProcessStatus
|
|
|
|
Arguments:
|
|
|
|
hpid - Supplies process
|
|
|
|
lppst - Returns process state structure
|
|
|
|
Return Value:
|
|
|
|
xosdNone: Success
|
|
|
|
--*/
|
|
{
|
|
return CallEM( emfProcessStatus, hpid, NULL, 0, lppst );
|
|
}
|
|
|
|
XOSD PASCAL
|
|
OSDGetThreadStatus (
|
|
HPID hpid,
|
|
HTID htid,
|
|
LPTST lptst
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Returns a structure describing the thread status for the given htid.
|
|
|
|
uses emfThreadStatus
|
|
|
|
Arguments:
|
|
|
|
hpid - Supplies process
|
|
|
|
htid - Supplies thread
|
|
|
|
lptst - Returns thread state structure
|
|
|
|
Return Value:
|
|
|
|
xosdNone: Success
|
|
|
|
--*/
|
|
{
|
|
return CallEM( emfThreadStatus, hpid, htid, 0, lptst );
|
|
}
|
|
|
|
/************************************************************************/
|
|
|
|
/* Target execution */
|
|
|
|
/************************************************************************/
|
|
|
|
|
|
XOSD PASCAL
|
|
OSDGo (
|
|
HPID hpid,
|
|
HTID htid,
|
|
LPEXOP lpExop
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Run the target program for the process hpid [thread htid].
|
|
|
|
uses emfGo.
|
|
|
|
Note: This is an asynchronous API.
|
|
|
|
Parameters:
|
|
|
|
hpid - Supplies process to run
|
|
|
|
htid - Supplies the thread to run
|
|
|
|
lpExop - Supplies options to control execution
|
|
|
|
Return Value:
|
|
|
|
xosdNone: Success
|
|
|
|
--*/
|
|
{
|
|
return CallEM( emfGo, hpid, htid, 0, lpExop );
|
|
}
|
|
|
|
|
|
|
|
|
|
XOSD PASCAL
|
|
OSDSingleStep (
|
|
HPID hpid,
|
|
HTID htid,
|
|
LPEXOP lpExop
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Execute a single processor instruction of the process hpid
|
|
and thread htid.
|
|
|
|
uses emfSingleStep
|
|
|
|
Note: This is an asynchronous API.
|
|
|
|
Parameters:
|
|
|
|
hpid - Supplies process
|
|
|
|
htid - Supplies thread
|
|
|
|
lpExop - Supplies options to control execution
|
|
|
|
Return Value:
|
|
|
|
xosdNone: Success
|
|
|
|
--*/
|
|
{
|
|
return CallEM( emfSingleStep, hpid, htid, 0, lpExop );
|
|
}
|
|
|
|
|
|
XOSD PASCAL
|
|
OSDRangeStep (
|
|
HPID hpid,
|
|
HTID htid,
|
|
LPADDR lpaddrMin,
|
|
LPADDR lpaddrMax,
|
|
LPEXOP lpExop
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Execute single processor instructions for hpid/htid while *lpaddrMin
|
|
<= adrPC <= *lpaddrMax.
|
|
|
|
Both of the boundary addresses are inclusive of the range.
|
|
|
|
uses emfRangeStep.
|
|
|
|
Note: This is an asynchronous API.
|
|
|
|
Parameters:
|
|
|
|
hpid - Supplies process
|
|
|
|
htid - Supplies thread
|
|
|
|
lpaddrMin - Supplies the lower boundary address
|
|
|
|
lpaddrMax - Supplies the upper boundary address
|
|
|
|
lpExop - Supplies options to control execution
|
|
|
|
Return Value:
|
|
|
|
xosdNone: Success
|
|
|
|
--*/
|
|
{
|
|
RSS rss;
|
|
rss.lpaddrMin = lpaddrMin;
|
|
rss.lpaddrMax = lpaddrMax;
|
|
rss.lpExop = lpExop;
|
|
return CallEM( emfRangeStep, hpid, htid, 0 , &rss );
|
|
}
|
|
|
|
|
|
XOSD PASCAL
|
|
OSDReturnStep (
|
|
HPID hpid,
|
|
HTID htid,
|
|
LPEXOP lpExop
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Execute the thread until it has returned to the caller.
|
|
|
|
uses emfReturnStep
|
|
|
|
Note: This is an asynchronous API.
|
|
|
|
Parameters:
|
|
|
|
hpid - Supplies process
|
|
|
|
htid - Supplies thread
|
|
|
|
lpExop - Supplies options to control execution
|
|
|
|
Return Value:
|
|
|
|
xosdNone: Success
|
|
|
|
--*/
|
|
{
|
|
return CallEM( emfReturnStep, hpid, htid, 0, lpExop );
|
|
}
|
|
|
|
|
|
XOSD PASCAL
|
|
OSDAsyncStop (
|
|
HPID hpid,
|
|
DWORD fSetFocus
|
|
)
|
|
/*++
|
|
|
|
Description:
|
|
|
|
Halt the execution of the target process hpid.
|
|
|
|
uses emfStop.
|
|
|
|
Note: This is an asynchronous API.
|
|
|
|
Parameters:
|
|
|
|
hpid - Supplies process
|
|
|
|
fSetFocus - Supplies option of changing focus to debuggee to avoid
|
|
user having to nudge debuggee into stop
|
|
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
return CallEM( emfStop, hpid, NULL, fSetFocus, 0 );
|
|
}
|
|
|
|
|
|
|