266 lines
6.7 KiB
C
266 lines
6.7 KiB
C
|
/*
|
||
|
* dbg.c - Main Module of DBG DLL.
|
||
|
*
|
||
|
* BobDay 13-Jan-1992 Created
|
||
|
* Neilsa 13-Mar-1997 Moved guts to dbgdll
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
#include <nt.h>
|
||
|
#include <ntrtl.h>
|
||
|
#include <nturtl.h>
|
||
|
#include <windows.h>
|
||
|
#include <stdio.h>
|
||
|
#include <string.h>
|
||
|
#include <mvdm.h>
|
||
|
#include <bop.h>
|
||
|
#include <softpc.h>
|
||
|
#include <dbgexp.h>
|
||
|
#include <dbgsvc.h>
|
||
|
#include <vdmdbg.h>
|
||
|
#include <dbginfo.h>
|
||
|
#include <vdm.h>
|
||
|
|
||
|
BOOL (WINAPI *pfnDbgInit)(ULONG, ULONG, PVOID);
|
||
|
BOOL (WINAPI *pfnDbgIsDebuggee)(VOID);
|
||
|
VOID (WINAPI *pfnDbgDispatch)(VOID);
|
||
|
VOID (WINAPI *pfnDbgDosAppStart)(WORD, WORD);
|
||
|
VOID (WINAPI *pfnDbgSegmentNotice)(WORD, WORD, WORD, WORD, LPSTR, LPSTR, DWORD);
|
||
|
VOID (WINAPI *pfnDbgTraceEvent)(PVDM_TRACEINFO, WORD, WORD, DWORD);
|
||
|
BOOL (WINAPI *pfnDbgFault)(ULONG);
|
||
|
BOOL (WINAPI *pfnDbgBPInt)(VOID);
|
||
|
BOOL (WINAPI *pfnDbgTraceInt)(VOID);
|
||
|
VOID (WINAPI *pfnDbgNotifyNewTask)(LPVOID, UINT);
|
||
|
VOID (WINAPI *pfnDbgNotifyRemoteThreadAddress)(LPVOID, DWORD);
|
||
|
VOID (WINAPI *pfnDbgNotifyDebugged)(BOOL);
|
||
|
|
||
|
#ifdef i386
|
||
|
BYTE nt_cpu_info;
|
||
|
#else
|
||
|
extern ULONG Start_of_M_area;
|
||
|
extern BYTE nt_cpu_info;
|
||
|
#define IntelBase Start_of_M_area
|
||
|
//
|
||
|
// This field is used to hold values destined for NTVDMSTATE (at 714)
|
||
|
// Initially, we set it to INITIAL_VDM_TIB_FLAGS just for clarity, since it
|
||
|
// will really only be turned on or off once we look to see if a debugger
|
||
|
// is attached. This way, if you examine it when you first attach with a
|
||
|
// debugger, it will be consistent with the default.
|
||
|
//
|
||
|
ULONG InitialVdmTibFlags = INITIAL_VDM_TIB_FLAGS;
|
||
|
|
||
|
VDM_TRACEINFO TraceInfo;
|
||
|
PVDM_TRACEINFO pVdmTraceInfo = &TraceInfo;
|
||
|
#endif
|
||
|
|
||
|
BOOL bDbgInitCalled = FALSE;
|
||
|
BOOL bDbgDebuggerLoaded = FALSE;
|
||
|
|
||
|
ULONG InitialVdmDbgFlags = 0;
|
||
|
|
||
|
/* DBGInit - DBG Initialiazation routine.
|
||
|
*
|
||
|
* This routine is called during ntvdm initialization from host\src.
|
||
|
* It is responsible for loading ntvdmd.dll, if vdm debugging is required.
|
||
|
*/
|
||
|
|
||
|
BOOL DBGInit (int argc, char *argv[])
|
||
|
{
|
||
|
HANDLE hmodDBG;
|
||
|
|
||
|
// Indicate to VdmDbgAttach that we have gotten far enough into
|
||
|
// the ntvdm boot that memory layout is valid.
|
||
|
bDbgInitCalled = TRUE;
|
||
|
|
||
|
//LATER Decide to load this on a registry switch
|
||
|
if (!bDbgDebuggerLoaded) {
|
||
|
if ( (hmodDBG = LoadLibrary("NTVDMD.DLL")) == (HANDLE)NULL ) {
|
||
|
#if DBG
|
||
|
OutputDebugString("NTVDM: error loading ntvdmd.dll\n");
|
||
|
#endif
|
||
|
return FALSE;
|
||
|
} else {
|
||
|
//
|
||
|
// pfnDbgDispatch is special in that we always want to call it
|
||
|
// even if no debugger is attached.
|
||
|
//
|
||
|
pfnDbgDispatch = (VOID (WINAPI *)(VOID)) GetProcAddress( hmodDBG, "xxxDbgDispatch" );
|
||
|
}
|
||
|
}
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* VdmDbgAttach
|
||
|
*
|
||
|
* This routine is called from NTVDMD.DLL. It is potentially called
|
||
|
* at any time, but specifically we are looking to run some code when:
|
||
|
|
||
|
* 1) the ntvdm has "matured", and
|
||
|
* 2) a debugger is attached
|
||
|
*
|
||
|
* The ntvdm has "matured" when it is initialized sufficiently to determine
|
||
|
* for example where the start of VDM memory is (on risc platforms).
|
||
|
*
|
||
|
*/
|
||
|
VOID
|
||
|
VdmDbgAttach(
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
if (bDbgInitCalled) {
|
||
|
HANDLE hmodDBG;
|
||
|
hmodDBG = GetModuleHandle("NTVDMD.DLL");
|
||
|
|
||
|
if ( hmodDBG == (HANDLE)NULL ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
pfnDbgInit = (BOOL (WINAPI *)(ULONG, ULONG, PVOID)) GetProcAddress( hmodDBG, "xxxDbgInit" );
|
||
|
pfnDbgIsDebuggee = (BOOL (WINAPI *)(VOID)) GetProcAddress( hmodDBG, "xxxDbgIsDebuggee" );
|
||
|
pfnDbgDosAppStart = (VOID (WINAPI *)(WORD, WORD)) GetProcAddress( hmodDBG, "xxxDbgDosAppStart" );
|
||
|
pfnDbgSegmentNotice = (VOID (WINAPI *)(WORD, WORD, WORD, WORD, LPSTR, LPSTR, DWORD)) GetProcAddress( hmodDBG, "xxxDbgSegmentNotice" );
|
||
|
pfnDbgTraceEvent = (VOID (WINAPI *)(PVDM_TRACEINFO, WORD, WORD, DWORD)) GetProcAddress( hmodDBG, "xxxDbgTraceEvent" );
|
||
|
pfnDbgFault = (BOOL (WINAPI *)(ULONG)) GetProcAddress( hmodDBG, "xxxDbgFault" );
|
||
|
pfnDbgBPInt = (BOOL (WINAPI *)(VOID)) GetProcAddress( hmodDBG, "xxxDbgBPInt" );
|
||
|
pfnDbgTraceInt = (BOOL (WINAPI *)(VOID)) GetProcAddress( hmodDBG, "xxxDbgTraceInt" );
|
||
|
pfnDbgNotifyNewTask = (VOID (WINAPI *)(LPVOID, UINT)) GetProcAddress( hmodDBG, "xxxDbgNotifyNewTask" );
|
||
|
pfnDbgNotifyRemoteThreadAddress = (VOID (WINAPI *)(LPVOID, DWORD)) GetProcAddress( hmodDBG, "xxxDbgNotifyRemoteThreadAddress" );
|
||
|
pfnDbgNotifyDebugged= (VOID (WINAPI *)(BOOL)) GetProcAddress( hmodDBG, "xxxDbgNotifyDebugged" );
|
||
|
//
|
||
|
// DBGinit has already been called. Do an init, and send
|
||
|
// symbol notifications
|
||
|
//
|
||
|
if (pfnDbgInit &&
|
||
|
(bDbgDebuggerLoaded = (*pfnDbgInit)(IntelBase + FIXED_NTVDMSTATE_LINEAR,
|
||
|
InitialVdmDbgFlags,
|
||
|
&nt_cpu_info))) {
|
||
|
//LATER: send symbol notifications
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
DBGNotifyNewTask(
|
||
|
LPVOID lpvNTFrame,
|
||
|
UINT uFrameSize
|
||
|
)
|
||
|
{
|
||
|
if (pfnDbgNotifyNewTask) {
|
||
|
(*pfnDbgNotifyNewTask)(lpvNTFrame, uFrameSize);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
DBGNotifyRemoteThreadAddress(
|
||
|
LPVOID lpAddress,
|
||
|
DWORD lpBlock
|
||
|
)
|
||
|
{
|
||
|
if (pfnDbgNotifyRemoteThreadAddress) {
|
||
|
(*pfnDbgNotifyRemoteThreadAddress)(lpAddress, lpBlock);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
VOID DBGNotifyDebugged(
|
||
|
BOOL fNewDebugged
|
||
|
)
|
||
|
{
|
||
|
if (pfnDbgNotifyDebugged) {
|
||
|
(*pfnDbgNotifyDebugged)(fNewDebugged);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
BOOL DbgTraceInt(VOID)
|
||
|
{
|
||
|
BOOL bRet = FALSE;
|
||
|
if (pfnDbgTraceInt) {
|
||
|
bRet = (*pfnDbgTraceInt)();
|
||
|
}
|
||
|
return bRet;
|
||
|
}
|
||
|
|
||
|
BOOL DbgFault(ULONG value)
|
||
|
{
|
||
|
BOOL bRet = FALSE;
|
||
|
if (pfnDbgFault) {
|
||
|
bRet = (*pfnDbgFault)(value);
|
||
|
}
|
||
|
return bRet;
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
DbgIsDebuggee(
|
||
|
void
|
||
|
)
|
||
|
{
|
||
|
if (pfnDbgIsDebuggee) {
|
||
|
return (*pfnDbgIsDebuggee)();
|
||
|
}
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
DbgSegmentNotice(
|
||
|
WORD wType,
|
||
|
WORD wModuleSeg,
|
||
|
WORD wLoadSeg,
|
||
|
WORD wNewSeg,
|
||
|
LPSTR lpModuleName,
|
||
|
LPSTR lpModulePath,
|
||
|
DWORD dwImageLen
|
||
|
)
|
||
|
{
|
||
|
if (pfnDbgSegmentNotice) {
|
||
|
(*pfnDbgSegmentNotice)(wType, wModuleSeg, wLoadSeg, wNewSeg,
|
||
|
lpModuleName, lpModulePath, dwImageLen);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
DbgDosAppStart(
|
||
|
WORD wCS,
|
||
|
WORD wIP
|
||
|
)
|
||
|
{
|
||
|
if (pfnDbgDosAppStart) {
|
||
|
(*pfnDbgDosAppStart)(wCS, wIP);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void DBGDispatch()
|
||
|
{
|
||
|
if (pfnDbgDispatch) {
|
||
|
(*pfnDbgDispatch)();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
BOOL DbgBPInt()
|
||
|
{
|
||
|
BOOL bRet = FALSE;
|
||
|
if (pfnDbgBPInt) {
|
||
|
bRet = (*pfnDbgBPInt)();
|
||
|
}
|
||
|
return bRet;
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
VdmTraceEvent(
|
||
|
USHORT Type,
|
||
|
USHORT wData,
|
||
|
ULONG lData
|
||
|
)
|
||
|
{
|
||
|
|
||
|
if (pfnDbgTraceEvent &&
|
||
|
(*(ULONG *)(IntelBase+FIXED_NTVDMSTATE_LINEAR) & VDM_TRACE_HISTORY)) {
|
||
|
|
||
|
PVDM_TIB VdmTib = NtCurrentTeb()->Vdm;
|
||
|
|
||
|
(*pfnDbgTraceEvent)(&((*VdmTib).TraceInfo), Type, wData, lData);
|
||
|
}
|
||
|
}
|