Source code of Windows XP (NT5)
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.

265 lines
6.7 KiB

  1. /*
  2. * dbg.c - Main Module of DBG DLL.
  3. *
  4. * BobDay 13-Jan-1992 Created
  5. * Neilsa 13-Mar-1997 Moved guts to dbgdll
  6. *
  7. */
  8. #include <nt.h>
  9. #include <ntrtl.h>
  10. #include <nturtl.h>
  11. #include <windows.h>
  12. #include <stdio.h>
  13. #include <string.h>
  14. #include <mvdm.h>
  15. #include <bop.h>
  16. #include <softpc.h>
  17. #include <dbgexp.h>
  18. #include <dbgsvc.h>
  19. #include <vdmdbg.h>
  20. #include <dbginfo.h>
  21. #include <vdm.h>
  22. BOOL (WINAPI *pfnDbgInit)(ULONG, ULONG, PVOID);
  23. BOOL (WINAPI *pfnDbgIsDebuggee)(VOID);
  24. VOID (WINAPI *pfnDbgDispatch)(VOID);
  25. VOID (WINAPI *pfnDbgDosAppStart)(WORD, WORD);
  26. VOID (WINAPI *pfnDbgSegmentNotice)(WORD, WORD, WORD, WORD, LPSTR, LPSTR, DWORD);
  27. VOID (WINAPI *pfnDbgTraceEvent)(PVDM_TRACEINFO, WORD, WORD, DWORD);
  28. BOOL (WINAPI *pfnDbgFault)(ULONG);
  29. BOOL (WINAPI *pfnDbgBPInt)(VOID);
  30. BOOL (WINAPI *pfnDbgTraceInt)(VOID);
  31. VOID (WINAPI *pfnDbgNotifyNewTask)(LPVOID, UINT);
  32. VOID (WINAPI *pfnDbgNotifyRemoteThreadAddress)(LPVOID, DWORD);
  33. VOID (WINAPI *pfnDbgNotifyDebugged)(BOOL);
  34. #ifdef i386
  35. BYTE nt_cpu_info;
  36. #else
  37. extern ULONG Start_of_M_area;
  38. extern BYTE nt_cpu_info;
  39. #define IntelBase Start_of_M_area
  40. //
  41. // This field is used to hold values destined for NTVDMSTATE (at 714)
  42. // Initially, we set it to INITIAL_VDM_TIB_FLAGS just for clarity, since it
  43. // will really only be turned on or off once we look to see if a debugger
  44. // is attached. This way, if you examine it when you first attach with a
  45. // debugger, it will be consistent with the default.
  46. //
  47. ULONG InitialVdmTibFlags = INITIAL_VDM_TIB_FLAGS;
  48. VDM_TRACEINFO TraceInfo;
  49. PVDM_TRACEINFO pVdmTraceInfo = &TraceInfo;
  50. #endif
  51. BOOL bDbgInitCalled = FALSE;
  52. BOOL bDbgDebuggerLoaded = FALSE;
  53. ULONG InitialVdmDbgFlags = 0;
  54. /* DBGInit - DBG Initialiazation routine.
  55. *
  56. * This routine is called during ntvdm initialization from host\src.
  57. * It is responsible for loading ntvdmd.dll, if vdm debugging is required.
  58. */
  59. BOOL DBGInit (int argc, char *argv[])
  60. {
  61. HANDLE hmodDBG;
  62. // Indicate to VdmDbgAttach that we have gotten far enough into
  63. // the ntvdm boot that memory layout is valid.
  64. bDbgInitCalled = TRUE;
  65. //LATER Decide to load this on a registry switch
  66. if (!bDbgDebuggerLoaded) {
  67. if ( (hmodDBG = LoadLibrary("NTVDMD.DLL")) == (HANDLE)NULL ) {
  68. #if DBG
  69. OutputDebugString("NTVDM: error loading ntvdmd.dll\n");
  70. #endif
  71. return FALSE;
  72. } else {
  73. //
  74. // pfnDbgDispatch is special in that we always want to call it
  75. // even if no debugger is attached.
  76. //
  77. pfnDbgDispatch = (VOID (WINAPI *)(VOID)) GetProcAddress( hmodDBG, "xxxDbgDispatch" );
  78. }
  79. }
  80. return TRUE;
  81. }
  82. /* VdmDbgAttach
  83. *
  84. * This routine is called from NTVDMD.DLL. It is potentially called
  85. * at any time, but specifically we are looking to run some code when:
  86. * 1) the ntvdm has "matured", and
  87. * 2) a debugger is attached
  88. *
  89. * The ntvdm has "matured" when it is initialized sufficiently to determine
  90. * for example where the start of VDM memory is (on risc platforms).
  91. *
  92. */
  93. VOID
  94. VdmDbgAttach(
  95. VOID
  96. )
  97. {
  98. if (bDbgInitCalled) {
  99. HANDLE hmodDBG;
  100. hmodDBG = GetModuleHandle("NTVDMD.DLL");
  101. if ( hmodDBG == (HANDLE)NULL ) {
  102. return;
  103. }
  104. pfnDbgInit = (BOOL (WINAPI *)(ULONG, ULONG, PVOID)) GetProcAddress( hmodDBG, "xxxDbgInit" );
  105. pfnDbgIsDebuggee = (BOOL (WINAPI *)(VOID)) GetProcAddress( hmodDBG, "xxxDbgIsDebuggee" );
  106. pfnDbgDosAppStart = (VOID (WINAPI *)(WORD, WORD)) GetProcAddress( hmodDBG, "xxxDbgDosAppStart" );
  107. pfnDbgSegmentNotice = (VOID (WINAPI *)(WORD, WORD, WORD, WORD, LPSTR, LPSTR, DWORD)) GetProcAddress( hmodDBG, "xxxDbgSegmentNotice" );
  108. pfnDbgTraceEvent = (VOID (WINAPI *)(PVDM_TRACEINFO, WORD, WORD, DWORD)) GetProcAddress( hmodDBG, "xxxDbgTraceEvent" );
  109. pfnDbgFault = (BOOL (WINAPI *)(ULONG)) GetProcAddress( hmodDBG, "xxxDbgFault" );
  110. pfnDbgBPInt = (BOOL (WINAPI *)(VOID)) GetProcAddress( hmodDBG, "xxxDbgBPInt" );
  111. pfnDbgTraceInt = (BOOL (WINAPI *)(VOID)) GetProcAddress( hmodDBG, "xxxDbgTraceInt" );
  112. pfnDbgNotifyNewTask = (VOID (WINAPI *)(LPVOID, UINT)) GetProcAddress( hmodDBG, "xxxDbgNotifyNewTask" );
  113. pfnDbgNotifyRemoteThreadAddress = (VOID (WINAPI *)(LPVOID, DWORD)) GetProcAddress( hmodDBG, "xxxDbgNotifyRemoteThreadAddress" );
  114. pfnDbgNotifyDebugged= (VOID (WINAPI *)(BOOL)) GetProcAddress( hmodDBG, "xxxDbgNotifyDebugged" );
  115. //
  116. // DBGinit has already been called. Do an init, and send
  117. // symbol notifications
  118. //
  119. if (pfnDbgInit &&
  120. (bDbgDebuggerLoaded = (*pfnDbgInit)(IntelBase + FIXED_NTVDMSTATE_LINEAR,
  121. InitialVdmDbgFlags,
  122. &nt_cpu_info))) {
  123. //LATER: send symbol notifications
  124. }
  125. }
  126. }
  127. VOID
  128. DBGNotifyNewTask(
  129. LPVOID lpvNTFrame,
  130. UINT uFrameSize
  131. )
  132. {
  133. if (pfnDbgNotifyNewTask) {
  134. (*pfnDbgNotifyNewTask)(lpvNTFrame, uFrameSize);
  135. }
  136. }
  137. VOID
  138. DBGNotifyRemoteThreadAddress(
  139. LPVOID lpAddress,
  140. DWORD lpBlock
  141. )
  142. {
  143. if (pfnDbgNotifyRemoteThreadAddress) {
  144. (*pfnDbgNotifyRemoteThreadAddress)(lpAddress, lpBlock);
  145. }
  146. }
  147. VOID DBGNotifyDebugged(
  148. BOOL fNewDebugged
  149. )
  150. {
  151. if (pfnDbgNotifyDebugged) {
  152. (*pfnDbgNotifyDebugged)(fNewDebugged);
  153. }
  154. }
  155. BOOL DbgTraceInt(VOID)
  156. {
  157. BOOL bRet = FALSE;
  158. if (pfnDbgTraceInt) {
  159. bRet = (*pfnDbgTraceInt)();
  160. }
  161. return bRet;
  162. }
  163. BOOL DbgFault(ULONG value)
  164. {
  165. BOOL bRet = FALSE;
  166. if (pfnDbgFault) {
  167. bRet = (*pfnDbgFault)(value);
  168. }
  169. return bRet;
  170. }
  171. BOOL
  172. DbgIsDebuggee(
  173. void
  174. )
  175. {
  176. if (pfnDbgIsDebuggee) {
  177. return (*pfnDbgIsDebuggee)();
  178. }
  179. return FALSE;
  180. }
  181. VOID
  182. DbgSegmentNotice(
  183. WORD wType,
  184. WORD wModuleSeg,
  185. WORD wLoadSeg,
  186. WORD wNewSeg,
  187. LPSTR lpModuleName,
  188. LPSTR lpModulePath,
  189. DWORD dwImageLen
  190. )
  191. {
  192. if (pfnDbgSegmentNotice) {
  193. (*pfnDbgSegmentNotice)(wType, wModuleSeg, wLoadSeg, wNewSeg,
  194. lpModuleName, lpModulePath, dwImageLen);
  195. }
  196. }
  197. VOID
  198. DbgDosAppStart(
  199. WORD wCS,
  200. WORD wIP
  201. )
  202. {
  203. if (pfnDbgDosAppStart) {
  204. (*pfnDbgDosAppStart)(wCS, wIP);
  205. }
  206. }
  207. void DBGDispatch()
  208. {
  209. if (pfnDbgDispatch) {
  210. (*pfnDbgDispatch)();
  211. }
  212. }
  213. BOOL DbgBPInt()
  214. {
  215. BOOL bRet = FALSE;
  216. if (pfnDbgBPInt) {
  217. bRet = (*pfnDbgBPInt)();
  218. }
  219. return bRet;
  220. }
  221. VOID
  222. VdmTraceEvent(
  223. USHORT Type,
  224. USHORT wData,
  225. ULONG lData
  226. )
  227. {
  228. if (pfnDbgTraceEvent &&
  229. (*(ULONG *)(IntelBase+FIXED_NTVDMSTATE_LINEAR) & VDM_TRACE_HISTORY)) {
  230. PVDM_TIB VdmTib = NtCurrentTeb()->Vdm;
  231. (*pfnDbgTraceEvent)(&((*VdmTib).TraceInfo), Type, wData, lData);
  232. }
  233. }