Windows2000/private/windbg64/debugger/dm/funccall.c
2020-09-30 17:12:32 +02:00

474 lines
9.4 KiB
C

/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
funchdr.c
Abstract:
This file contians the code used for supporting function evaluation
from the expression evaluator.
Author:
Jim Schaad (jimsch) 06-04-92
Environment:
Win32 - User
--*/
#include "precomp.h"
#pragma hdrstop
SetFile()
void
NotifyFuncCall(
DEBUG_EVENT64 * lpde,
HTHDX hthd,
DWORDLONG unused,
DWORDLONG lparam
);
METHOD MthdFuncNotify = {NotifyFuncCall};
extern DMTLFUNCTYPE DmTlFunc;
extern LPDM_MSG LpDmMsg;
VOID
ProcessSetupExecuteCmd(
HPRCX hprc,
HTHDX hthd,
LPDBB lpdbb
)
/*++
Routine Description:
This function is called in response to a dmfSetupExecute request.
It will create a local Execute Object and return the handle to
the object.
Arguments:
hprc - Supplies the process handle for the operation
hthd - Supplies the thread handle for the operation
lpdbb - Supplies a pointer to possible futher information
Return Value:
None.
--*/
{
LPEXECUTE_OBJECT_DM lpeo;
Unreferenced( hprc );
DPRINT(1, ("Setup Execute"));
/*
* In order for this to be a valid operation the requested
* thread must be in a stopped state (and don't allow evaluation
* until we have hit the loader breakpoint)
*/
if ( ((hthd->tstate & ts_stopped) == 0) ||
((hthd->tstate & (ts_dead|ts_destroyed)) != 0) ||
(hprc->pstate & (ps_preEntry|ps_preStart)) ) {
LpDmMsg->xosdRet = xosdBadThread;
goto Exit;
}
lpeo = MHAlloc(sizeof(EXECUTE_OBJECT_DM));
if (lpeo == NULL) {
LpDmMsg->xosdRet = xosdOutOfMemory;
goto Exit;
}
memset(lpeo, 0, sizeof(EXECUTE_OBJECT_DM));
LpDmMsg->xosdRet = xosdNone;
*((HIND *)LpDmMsg->rgb) = (HIND) lpeo;
hthd->tstate |= ts_funceval;
hthd->cFuncEval += 1;
Exit:
Reply(sizeof(HIND), LpDmMsg, lpdbb->hpid);
return;
} /* ProcessSetupExecute() */
VOID
ProcessStartExecuteCmd(
HPRCX hprc,
HTHDX hthd,
LPDBB lpdbb
)
/*++
Routine Description:
description-of-function.
Arguments:
hprc - Supplies the process handle for the operation
hthd - Supplies the thread handle for the operation
lpdbb - Supplies a pointer to possible futher information
Return Value:
None.
--*/
{
LPEXECUTE_STRUCT lpes = (LPEXECUTE_STRUCT) (lpdbb->rgbVar);
LPEXECUTE_OBJECT_DM lpeo;
XOSD xosd;
/*
* Start by saving the information in the EXECUTE_STRUCT in
* the local Execute Object structure.
*/
lpeo = (LPEXECUTE_OBJECT_DM) lpes->hindDm;
DPRINT(1, ("Start Execute @%08x", lpes->addr.addr.off));
lpeo->addrStart = lpes->addr;
lpeo->pbpSave = AtBP(hthd);
lpeo->fIgnoreEvents = lpes->fIgnoreEvents;
lpeo->hthd = hthd;
lpeo->lpbp = SetBP(hprc, hthd, bptpExec, bpnsStop, &(lpeo->addrStart), (HPID) lpeo);
/*
* Mark a breakpoint at the current address
*/
SetBPFlag(hthd, lpeo->lpbp);
/*
* Call a machine specific fucntion to setup stacks and some
* work in the Execute Object for later use.
*/
xosd = SetupFunctionCall(lpeo, lpes);
/*
* If the set up worked successfully, the next step to to register
* an expected debug event and
* step the child.
*/
if (xosd == xosdNone) {
SingleStep(hthd, &MthdFuncNotify, FALSE, TRUE);
}
LpDmMsg->xosdRet = xosd;
Reply(0, LpDmMsg, lpdbb->hpid);
return;
} /* ProcessStartExecute() */
VOID
ProcessCleanUpExecuteCmd(
HPRCX hprc,
HTHDX hthd,
LPDBB lpdbb
)
/*++
Routine Description:
description-of-function.
Arguments:
hprc - Supplies the process handle for the operation
hthd - Supplies the thread handle for the operation
lpdbb - Supplies a pointer to possible futher information
Return Value:
None.
--*/
{
LPEXECUTE_OBJECT_DM lpeo = *(LPEXECUTE_OBJECT_DM *) (lpdbb->rgbVar);
DPRINT(1, ("Cleanup Execute"));
hthd->cFuncEval -= 1;
if (hthd->cFuncEval == 0) {
hthd->tstate &= ~ts_funceval;
}
if (lpeo->lpbp) {
RemoveBP(lpeo->lpbp);
}
/*
* This is wrong if the BP could be removed during function evaluation
*/
SetBPFlag(hthd, lpeo->pbpSave);
LpDmMsg->xosdRet = xosdNone;
Reply(0, LpDmMsg, lpdbb->hpid);
MHFree( lpeo );
return;
} /* ProcessCleanUpCmd() */
void
NotifyFuncCall(
DEBUG_EVENT64 * lpde,
HTHDX hthd,
DWORDLONG unused,
DWORDLONG lparam
)
/*++
Routine Description:
This function is called as the notifyer function for expected events
for executing of functions for the expression evaluator.
Arguments:
lpde - Supplies the pointer to the debug event exception structure
hthd - Supplies the handle to the thread of the exception
lpv - Supplies a pointer to extra data for the expectation
Return Value:
None.
--*/
{
Unreferenced( lpde );
Unreferenced( lparam );
/*
* Debug output first
*/
DEBUG_PRINT("** NotifyFuncCall **\n");
ContinueThread(hthd);
return;
} /* NotifyFuncCall() */
VOID
EvntBreakpoint(
DEBUG_EVENT64 * de,
HTHDX hthd
)
/*++
Routine Description:
This routine is called if the current thread is processing a function
evaluation and a breakpoint debug event occurs. The routine checks
to see if the desired breakpoint has been reached. If it has not
then the breakpoint will be consumed and the thread continued. If it
has then a dbcExecuteDone notification will be sent to the debugger.
Arguments:
de - Supplies a pointer to the current debug event.
hthd - Supplies the handle of the current thread
Return Value:
None.
--*/
{
LPEXECUTE_OBJECT_DM lpeo;
PBREAKPOINT lpbpp = (PBREAKPOINT) ((((DWORD_PTR)de->u.Exception.ExceptionRecord.NumberParameters) << 32) | (DWORD)de->u.Exception.ExceptionRecord.ExceptionCode);
HIND hzero = 0;
#if 0 //v-vadimp - this code is not right - third line should say ibpp = .....<<32 | ibpp, and will probably have pointer extension problems
*DWORD_PTR ibpp;
ibpp = de->u.Exception.ExceptionRecord.ExceptionCode;
ibpp = de->u.Exception.ExceptionRecord.NumberParameters << 32;
lpbpp = (PBREAKPOINT) ibpp;
#endif
de->u.Exception.ExceptionRecord.ExceptionCode = 0;
de->u.Exception.ExceptionRecord.NumberParameters = 0;
if (lpbpp) {
lpeo = (LPEXECUTE_OBJECT_DM) lpbpp->id;
} else {
lpeo = NULL;
}
DPRINT(1, ("Hit Execute Breakpoint (%08x)", lpbpp));
/*
* This may have been a recursive call. TO deal with this we need
* to check that the stack pointers are the same as when we started
* doing the function evaluation.
* If it is not ok on the stacks then merely continue. Note that this
* requires doing a single step event.
*/
if ((lpeo != NULL) && !CompareStacks(lpeo)) {
SetBPFlag(hthd, lpbpp);
#if defined(TARGET_i386) && defined(KERNEL)
DecrementIP( hthd );
#endif
DPRINT(1, (" Compare Stacks fail\n"));
SingleStep(hthd, &MthdFuncNotify, FALSE, TRUE);
} else {
DPRINT(1, (" Execute done\n"));
/*
* We really did finish so send a message to that effect
*/
DMSendDebugPacket(dbcExecuteDone,
hthd->hprc->hpid,
hthd->htid,
sizeof(HIND),
&hzero
);
}
return;
} /* EvntBreakpoint() */
VOID
EvntException(
DEBUG_EVENT64 * de,
HTHDX hthd
)
/*++
Routine Description:
description-of-function.
Arguments:
argument-name - Supplies | Returns description of argument.
.
.
Return Value:
return-value - Description of conditions needed to return value. - or -
None.
--*/
{
HIND hzero = 0;
DPRINT(1, ("Execute -- Exececption Occured\n"));
hthd->fExceptionHandled = TRUE;
DMSendDebugPacket(dbcExecuteDone,
hthd->hprc->hpid,
hthd->htid,
sizeof(HIND),
&hzero
);
return;
} /* EvntException() */
VOID
EvntExitProcess(
DEBUG_EVENT64 * de,
HTHDX hthd
)
/*++
Routine Description:
This function is called if an exit process event is called while
a function is being evaluated.
This is a pain to deal with. First the function evaluation must
be killed and then we need to do normal processing
Arguments:
de - Supplies the Exit Process Debug event
hthd - Supplies the handle to the current thread
Return Value:
None.
--*/
{
HIND hzero = 0;
DPRINT(1, ("Execute -- Exit Process Occurred\n"));
hthd->fExceptionHandled = TRUE;
DMSendDebugPacket(dbcExecuteDone,
hthd->hprc->hpid,
hthd->htid,
sizeof(HIND),
&hzero
);
ProcessExitProcessEvent(de, hthd);
return;
} /* EvntExitProcess() */