windows-nt/Source/XPSP1/NT/base/mvdm/dbg/dbg.c
2020-09-26 16:20:57 +08:00

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);
}
}