/* * dbg.c - Main Module of DBG DLL. * * BobDay 13-Jan-1992 Created * Neilsa 13-Mar-1997 Moved guts to dbgdll * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include 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); } }