Leaked source code of windows server 2003
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.

680 lines
18 KiB

  1. /*++
  2. * Main module of DBG DLL.
  3. *
  4. * Copyright (c) 1997, Microsoft Corporation
  5. *
  6. * This code runs in the debuggee's process.
  7. *
  8. --*/
  9. #include <precomp.h>
  10. #pragma hdrstop
  11. BOOL InVdmDebugger = FALSE;
  12. BOOL bWantsNtsdPrompt = FALSE;
  13. ULONG ulTHHOOK = 0L; // Address registered from 16-bit world
  14. LPVOID lpRemoteAddress = NULL; // Address registered from WOW32
  15. DWORD lpRemoteBlock = 0; // Address registered from WOW32
  16. BOOL f386;
  17. DWORD VdmDbgEFLAGS;
  18. WORD DbgWowhExeHead = 0;
  19. WORD DbgWowhGlobalHeap = 0;
  20. PDWORD lpVdmState = NULL;
  21. PBYTE lpNtCpuInfo = NULL;
  22. UCHAR DbgTimerMode = VDMTI_TIMER_TICK;
  23. BOOL DbgTimerInitialized = FALSE;
  24. VOID VdmDbgAttach(VOID);
  25. BOOLEAN
  26. DbgDllInitialize(
  27. IN PVOID DllHandle,
  28. IN ULONG Reason,
  29. IN PCONTEXT Context OPTIONAL
  30. )
  31. /*
  32. * DBGDllInitialize - DBG Initialiazation routine.
  33. *
  34. */
  35. {
  36. HANDLE MyDebugPort;
  37. DWORD st;
  38. BOOL fAlreadyDebugged;
  39. UNREFERENCED_PARAMETER(Context);
  40. switch ( Reason ) {
  41. case DLL_PROCESS_ATTACH:
  42. #ifdef i386
  43. // X86 Only, get pointer to Register Context Block
  44. px86 = getIntelRegistersPointer();
  45. #endif
  46. st = NtQueryInformationProcess(
  47. NtCurrentProcess(),
  48. ProcessDebugPort,
  49. (PVOID)&MyDebugPort,
  50. sizeof(MyDebugPort),
  51. NULL );
  52. if ( NT_SUCCESS(st) ) {
  53. fDebugged = (MyDebugPort != NULL);
  54. } else {
  55. fDebugged = FALSE;
  56. }
  57. if (fDebugged) {
  58. DbgAttach();
  59. }
  60. break;
  61. case DLL_THREAD_ATTACH:
  62. //
  63. // See if the debugger is attaching. If it is, then turn on the
  64. // default of breaking into the debugger.
  65. //
  66. fAlreadyDebugged = fDebugged;
  67. st = NtQueryInformationProcess(
  68. NtCurrentProcess(),
  69. ProcessDebugPort,
  70. (PVOID)&MyDebugPort,
  71. sizeof(MyDebugPort),
  72. NULL );
  73. if ( NT_SUCCESS(st) ) {
  74. fDebugged = (MyDebugPort != NULL);
  75. } else {
  76. fDebugged = FALSE;
  77. }
  78. if (fDebugged && !fAlreadyDebugged) {
  79. DbgAttach();
  80. }
  81. break;
  82. case DLL_THREAD_DETACH:
  83. break;
  84. case DLL_PROCESS_DETACH:
  85. break;
  86. default:
  87. break;
  88. }
  89. return( TRUE );
  90. }
  91. void
  92. DbgAttach(
  93. void
  94. )
  95. /*
  96. * DbgAttach
  97. *
  98. * Called to initiate the communication with a debugger
  99. *
  100. */
  101. {
  102. //
  103. // Send DBG_ATTACH notification
  104. //
  105. DbgGetContext();
  106. SendVDMEvent(DBG_ATTACH);
  107. //
  108. // This call tells ntvdm to resync with us
  109. //
  110. VdmDbgAttach();
  111. }
  112. BOOL
  113. WINAPI
  114. xxxDbgInit(
  115. PVOID pState,
  116. ULONG InitialVdmDbgFlags,
  117. PVOID pCpuInfo
  118. )
  119. /*
  120. * DbgInit
  121. *
  122. * Called once ntvdm has completed it's initialization. Now it
  123. * is possible to compute for example the IntelMemoryBase.
  124. *
  125. */
  126. {
  127. VdmDbgTraceFlags = InitialVdmDbgFlags;
  128. lpVdmState = pState;
  129. IntelMemoryBase = (ULONG)VdmMapFlat(0, 0, VDM_V86);
  130. lpNtCpuInfo = pCpuInfo;
  131. //
  132. // turn on default debugging bits in ntvdmstate
  133. //
  134. *lpVdmState |= VDM_BREAK_DEBUGGER;
  135. #if DBG
  136. *lpVdmState |= VDM_TRACE_HISTORY;
  137. #endif
  138. if (fDebugged) {
  139. DbgGetContext();
  140. SendVDMEvent(DBG_INIT);
  141. }
  142. return TRUE;
  143. }
  144. BOOL
  145. WINAPI
  146. xxxDbgIsDebuggee(
  147. void
  148. )
  149. /*
  150. * DbgIsDebuggee
  151. *
  152. * Determines if we are being debugged
  153. *
  154. * Entry: void
  155. *
  156. * Exit: BOOL bRet - TRUE we are being debugged
  157. *
  158. */
  159. {
  160. return fDebugged;
  161. }
  162. BOOL
  163. SendVDMEvent(
  164. WORD wEventType
  165. )
  166. /* SendVDMEvent
  167. *
  168. * Sends a VDM event notification to the debugger
  169. *
  170. * Entry:
  171. *
  172. * Exit: BOOL bRet
  173. * Returns TRUE if exception was handled, FALSE otherwise
  174. *
  175. */
  176. {
  177. BOOL fResult;
  178. EventParams[0] = MAKELONG( wEventType, EventFlags );
  179. EventParams[3] = (DWORD)&viInfo;
  180. InVdmDebugger = TRUE;
  181. do {
  182. bWantsNtsdPrompt = FALSE;
  183. // Slimyness to determine whether the exception was handled or not.
  184. try {
  185. RaiseException( STATUS_VDM_EVENT,
  186. 0,
  187. 4,
  188. EventParams );
  189. fResult = TRUE;
  190. } except(EXCEPTION_EXECUTE_HANDLER) {
  191. fResult = FALSE;
  192. }
  193. //
  194. // bWantsNtsdPrompt may be changed by vdmexts
  195. //
  196. if (bWantsNtsdPrompt) {
  197. DbgBreakPoint();
  198. }
  199. } while (bWantsNtsdPrompt);
  200. InVdmDebugger = FALSE;
  201. FlushVdmBreakPoints();
  202. return( fResult );
  203. }
  204. VOID
  205. DbgGetContext(
  206. VOID
  207. )
  208. /* DbgGetContext() - Get the VDM's current context
  209. *
  210. * Most of the routines that send VDMEvents need to have a context record
  211. * associated with them. This routine is a quick way to get most of the
  212. * general registers. Redundant work is being done because AX for example
  213. * is often on the stack and as such must really be pulled from the frame.
  214. * Hopefully this is OK because it is fast.
  215. */
  216. {
  217. //
  218. // Everything defaults to 0.
  219. //
  220. RtlFillMemory( &vcContext, sizeof(VDMCONTEXT), (UCHAR)0 );
  221. RtlFillMemory( &viInfo, sizeof(VDMINTERNALINFO), (UCHAR)0 );
  222. //
  223. // Fill in the internal info structure
  224. //
  225. viInfo.dwLdtBase = (DWORD)ExpLdt;
  226. viInfo.dwIntelBase = IntelMemoryBase;
  227. viInfo.wKernelSeg = HIWORD(ulTHHOOK);
  228. viInfo.dwOffsetTHHOOK = (DWORD)(LOWORD(ulTHHOOK));
  229. viInfo.vdmContext = &vcContext;
  230. viInfo.lpRemoteAddress = lpRemoteAddress;
  231. viInfo.lpRemoteBlock = lpRemoteBlock;
  232. viInfo.f386 = f386;
  233. viInfo.lpNtvdmState = lpVdmState;
  234. viInfo.lpVdmDbgFlags = &VdmDbgTraceFlags;
  235. viInfo.lpNtCpuInfo = lpNtCpuInfo;
  236. viInfo.lpVdmBreakPoints= &VdmBreakPoints;
  237. EventFlags = 0;
  238. if(NtCurrentTeb()->Vdm) {
  239. //
  240. // Fill in the context structure
  241. //
  242. vcContext.SegEs = (ULONG)getES();
  243. vcContext.SegDs = (ULONG)getDS();
  244. vcContext.SegCs = (ULONG)getCS();
  245. vcContext.SegSs = (ULONG)getSS();
  246. vcContext.SegFs = (ULONG)getFS();
  247. vcContext.SegGs = (ULONG)getGS();
  248. vcContext.EFlags = getEFLAGS();
  249. VdmDbgEFLAGS = vcContext.EFlags; // save for vdmexts
  250. vcContext.Edi = getEDI();
  251. vcContext.Esi = getESI();
  252. vcContext.Ebx = getEBX();
  253. vcContext.Edx = getEDX();
  254. vcContext.Ecx = getECX();
  255. vcContext.Eax = getEAX();
  256. vcContext.Ebp = getEBP();
  257. vcContext.Eip = getEIP();
  258. vcContext.Esp = getESP();
  259. //
  260. // Put in special flags in event field
  261. //
  262. if (!(getMSW() & MSW_PE) || (getEFLAGS() & V86FLAGS_V86)) {
  263. EventFlags |= VDMEVENT_V86; // emulator is in real or v86 mode
  264. } else {
  265. EventFlags |= VDMEVENT_PE;
  266. if ((getMSW() & MSW_PE) && !SEGMENT_IS_BIG(vcContext.SegCs)) {
  267. EventFlags |= VDMEVENT_PM16; // emulator is in real or v86 mode
  268. }
  269. }
  270. }
  271. }
  272. void
  273. WINAPI
  274. xxxDbgDispatch()
  275. {
  276. UNALIGNED WORD *stack;
  277. WORD mode;
  278. WORD selector;
  279. WORD segment;
  280. WORD new_selector;
  281. BOOL fBPRelease;
  282. BOOL fData;
  283. LPSTR lpModuleName;
  284. LPSTR lpPathName;
  285. UCHAR fPE;
  286. PFFRAME16 pFFrame;
  287. PTFRAME16 pTFrame;
  288. PNDFRAME16 pNDFrame;
  289. PSTFRAME16 pSTFrame;
  290. WORD wFrame;
  291. fPE = ISPESET;
  292. stack = (UNALIGNED WORD *)Sim32GetVDMPointer(
  293. ((ULONG)getSS() << 16) + (ULONG)getSP(),
  294. MAX_DBG_FRAME, fPE );
  295. mode = *stack++;
  296. //
  297. // If there is no debugger, then only handle DBG_WOWINIT
  298. //
  299. if (!fDebugged && (mode != DBG_WOWINIT)) {
  300. return;
  301. }
  302. switch( mode ) {
  303. case DBG_SEGLOAD:
  304. selector = *stack++;
  305. segment = *stack++;
  306. lpModuleName = (LPSTR)Sim32GetVDMPointer(
  307. (ULONG)*stack + ((ULONG)(*(stack+1)) << 16),
  308. 0, fPE );
  309. stack += 2;
  310. lpPathName = (LPSTR)Sim32GetVDMPointer(
  311. (ULONG)*stack + ((ULONG)(*(stack+1)) << 16),
  312. 0, fPE );
  313. if ( lpPathName == NULL ) {
  314. lpPathName = "";
  315. }
  316. stack += 2;
  317. fData = (BOOL)(*stack++);
  318. SegmentLoad( lpModuleName, lpPathName, selector, segment, fData );
  319. break;
  320. case DBG_SEGMOVE:
  321. selector = *stack++;
  322. new_selector = *stack++;
  323. SegmentMove( selector, new_selector );
  324. break;
  325. case DBG_SEGFREE:
  326. fBPRelease = (BOOL)*stack++;
  327. selector = *stack++;
  328. SegmentFree( selector, fBPRelease );
  329. break;
  330. case DBG_MODFREE:
  331. lpModuleName = (LPSTR)Sim32GetVDMPointer(
  332. (ULONG)*stack + ((ULONG)(*(stack+1)) << 16),
  333. 0, fPE );
  334. stack += 2;
  335. lpPathName = (LPSTR)Sim32GetVDMPointer(
  336. (ULONG)*stack + ((ULONG)(*(stack+1)) << 16),
  337. 0, fPE );
  338. if ( lpPathName == NULL ) {
  339. lpPathName = "";
  340. }
  341. ModuleFree( lpModuleName, lpPathName );
  342. break;
  343. case DBG_GPFAULT2:
  344. wFrame = getBP() - (WORD)(FIELD_OFFSET(FFRAME16,wBP));
  345. pFFrame = (PFFRAME16)Sim32GetVDMPointer(
  346. ((ULONG)getSS() << 16) + (ULONG)wFrame,
  347. MAX_DBG_FRAME, fPE );
  348. fData = DbgGPFault2( pFFrame );
  349. setAX((WORD)fData);
  350. break;
  351. case DBG_DIVOVERFLOW:
  352. pTFrame = (PTFRAME16)Sim32GetVDMPointer(
  353. (ULONG)((ULONG)getSS() << 16) + (ULONG)getSP(),
  354. MAX_DBG_FRAME, fPE );
  355. fData = DbgDivOverflow2( pTFrame );
  356. setAX((WORD)fData);
  357. break;
  358. case DBG_DLLSTART:
  359. pNDFrame = (PNDFRAME16)Sim32GetVDMPointer(
  360. (ULONG)((ULONG)getSS() << 16) + (ULONG)getSP(),
  361. MAX_DBG_FRAME, fPE );
  362. fData = DbgDllStart( pNDFrame );
  363. setAX((WORD)fData);
  364. break;
  365. case DBG_TASKSTOP:
  366. pSTFrame = (PSTFRAME16)Sim32GetVDMPointer(
  367. (ULONG)((ULONG)getSS() << 16) + (ULONG)getSP(),
  368. MAX_DBG_FRAME, fPE );
  369. fData = DbgTaskStop( pSTFrame );
  370. break;
  371. case DBG_ATTACH:
  372. break;
  373. case DBG_TOOLHELP:
  374. ulTHHOOK = (ULONG)*stack + ((ULONG)(*(stack+1)) << 16);
  375. stack += 2;
  376. f386 = (BOOL)*stack;
  377. break;
  378. case DBG_WOWINIT:
  379. //
  380. // Pass in some data from KRNL386 so that VDMEXTS can get a
  381. // hold of them.
  382. //
  383. DbgWowhExeHead = getDX();
  384. DbgWowhGlobalHeap = getCX();
  385. break;
  386. default:
  387. setAX(0); // Event not handled
  388. break;
  389. }
  390. }
  391. VOID
  392. xxxDbgNotifyRemoteThreadAddress(
  393. LPVOID lpAddress,
  394. DWORD lpBlock
  395. ) {
  396. lpRemoteAddress = lpAddress;
  397. lpRemoteBlock = lpBlock;
  398. }
  399. VOID
  400. xxxDbgNotifyDebugged(
  401. BOOL fNewDebugged
  402. ) {
  403. fDebugged = fNewDebugged;
  404. }
  405. VOID
  406. RestoreVDMContext(
  407. VDMCONTEXT *vcContext
  408. )
  409. {
  410. setEAX(vcContext->Eax);
  411. setEBX(vcContext->Ebx);
  412. setECX(vcContext->Ecx);
  413. setEDX(vcContext->Edx);
  414. setEIP(vcContext->Eip);
  415. setESP(vcContext->Esp);
  416. setEBP(vcContext->Ebp);
  417. setEFLAGS(vcContext->EFlags);
  418. }
  419. ULONG
  420. DbgEventTime(
  421. PVDM_TRACEINFO pVdmTraceInfo
  422. )
  423. {
  424. ULONG TickCount = 0;
  425. USHORT id;
  426. ULONG CurTick;
  427. LARGE_INTEGER CurTime;
  428. LARGE_INTEGER DiffTime;
  429. #ifdef _X86_
  430. ULONG CurHigh, CurLow;
  431. #endif
  432. if (!DbgTimerInitialized) {
  433. #ifdef _X86_
  434. ULONG CpuidHigh;
  435. _asm pushad
  436. _asm mov eax, 1
  437. _asm _emit 0fh
  438. _asm _emit 0a2h // CPUID
  439. _asm mov CpuidHigh, edx
  440. _asm popad
  441. if (CpuidHigh & 0x10) {
  442. // cpu has time stamp counter
  443. DbgTimerMode = VDMTI_TIMER_PENTIUM;
  444. }
  445. #endif
  446. switch(DbgTimerMode & VDMTI_TIMER_MODE) {
  447. case VDMTI_TIMER_TICK:
  448. pVdmTraceInfo->TimeStamp.LowPart = GetTickCount();
  449. DbgTimerInitialized = TRUE;
  450. break;
  451. #ifdef _X86_
  452. case VDMTI_TIMER_PENTIUM:
  453. _asm push eax
  454. _asm push edx
  455. _asm _emit 0fh
  456. _asm _emit 031h // RDTSC
  457. _asm mov CurLow, eax
  458. _asm mov CurHigh, edx
  459. _asm pop edx
  460. _asm pop eax
  461. pVdmTraceInfo->TimeStamp.LowPart = CurLow;
  462. pVdmTraceInfo->TimeStamp.HighPart = CurHigh;
  463. DbgTimerInitialized = TRUE;
  464. break;
  465. #endif
  466. }
  467. }
  468. if (DbgTimerInitialized) {
  469. pVdmTraceInfo->Flags = (pVdmTraceInfo->Flags & ~VDMTI_TIMER_MODE) +
  470. (DbgTimerMode & VDMTI_TIMER_MODE);
  471. switch(pVdmTraceInfo->Flags & VDMTI_TIMER_MODE) {
  472. case VDMTI_TIMER_TICK:
  473. CurTick = GetTickCount();
  474. if (CurTick > pVdmTraceInfo->TimeStamp.LowPart) {
  475. TickCount = CurTick - pVdmTraceInfo->TimeStamp.LowPart;
  476. pVdmTraceInfo->TimeStamp.LowPart = CurTick;
  477. } else {
  478. TickCount = 0;
  479. }
  480. break;
  481. #ifdef _X86_
  482. case VDMTI_TIMER_PENTIUM: {
  483. _asm push eax
  484. _asm push edx
  485. _asm _emit 0fh
  486. _asm _emit 031h // RDTSC
  487. _asm mov CurLow, eax
  488. _asm mov CurHigh, edx
  489. _asm pop edx
  490. _asm pop eax
  491. CurTime.LowPart = CurLow;
  492. CurTime.HighPart = CurHigh;
  493. DiffTime.QuadPart = CurTime.QuadPart - pVdmTraceInfo->TimeStamp.QuadPart;
  494. pVdmTraceInfo->TimeStamp.QuadPart = CurTime.QuadPart;
  495. TickCount = DiffTime.LowPart;
  496. //if (DiffTime.HighPart) {
  497. // TickCount = 0xffffffff;
  498. //}
  499. break;
  500. }
  501. #endif
  502. }
  503. }
  504. return (TickCount);
  505. }
  506. #define NUM_VDM_TRACE_PAGES 8
  507. VOID
  508. WINAPI
  509. xxxDbgTraceEvent(
  510. PVDM_TRACEINFO pVdmTraceInfo,
  511. USHORT Type,
  512. USHORT wData,
  513. ULONG lData
  514. )
  515. {
  516. PVDM_TRACEENTRY pEntry;
  517. if (!(*(ULONG *)(IntelMemoryBase+FIXED_NTVDMSTATE_LINEAR) & VDM_TRACE_HISTORY)) {
  518. return;
  519. }
  520. if (!pVdmTraceInfo->pTraceTable) {
  521. pVdmTraceInfo->pTraceTable = (PVDM_TRACEENTRY) VirtualAlloc(NULL,
  522. 4096*NUM_VDM_TRACE_PAGES,
  523. MEM_COMMIT,
  524. PAGE_READWRITE);
  525. if (!pVdmTraceInfo->pTraceTable) {
  526. // couldn't allocate memory
  527. return;
  528. }
  529. pVdmTraceInfo->CurrentEntry = 0;
  530. pVdmTraceInfo->NumPages = NUM_VDM_TRACE_PAGES;
  531. pVdmTraceInfo->Flags = 0;
  532. }
  533. pEntry = &pVdmTraceInfo->pTraceTable[pVdmTraceInfo->CurrentEntry];
  534. pEntry->Type = Type;
  535. pEntry->wData = wData;
  536. pEntry->lData = lData;
  537. pEntry->Time = DbgEventTime(pVdmTraceInfo);
  538. pEntry->eax = getEAX();
  539. pEntry->ebx = getEBX();
  540. pEntry->ecx = getECX();
  541. pEntry->edx = getEDX();
  542. pEntry->esi = getESI();
  543. pEntry->edi = getEDI();
  544. pEntry->ebp = getEBP();
  545. pEntry->esp = getESP();
  546. pEntry->eip = getEIP();
  547. pEntry->eflags = getEFLAGS();
  548. pEntry->cs = getCS();
  549. pEntry->ds = getDS();
  550. pEntry->es = getES();
  551. pEntry->fs = getFS();
  552. pEntry->gs = getGS();
  553. pEntry->ss = getSS();
  554. if (++pVdmTraceInfo->CurrentEntry >=
  555. (pVdmTraceInfo->NumPages*4096/sizeof(VDM_TRACEENTRY))) {
  556. pVdmTraceInfo->CurrentEntry = 0;
  557. }
  558. }