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.

3198 lines
101 KiB

  1. /*** WST.C - Working Set Tuner Data Collection Program.
  2. *
  3. *
  4. * Title:
  5. *
  6. * WST- Working Set Tuner Data Collection Program.
  7. *
  8. * Copyright (c) 1992-1994, Microsoft Corporation.
  9. * Reza Baghai.
  10. *
  11. * Description:
  12. *
  13. * The Working Set Tuner tool is organized as follows:
  14. *
  15. * o WST.c ........ Tools main body
  16. * o WST.h
  17. * o WST.def
  18. *
  19. *
  20. *
  21. * Design/Implementation Notes
  22. *
  23. * The following defines can be used to control output of all the
  24. * debugging information to the debugger via KdPrint() for the checked
  25. * builds:
  26. *
  27. * (All debugging options are undefined for free/retail builds)
  28. *
  29. * PPC
  30. * ---
  31. *
  32. * PPC experiences problems when reading symbols in CRTDLL.dll
  33. *
  34. * #ifdef INFODBG : Displays messages to indicate when data dumping/
  35. * clearing operations are completed. It has no effect
  36. * on timing. *DEFAULT*
  37. *
  38. * #ifdef SETUPDBG : Displays messages during memory management and
  39. * symbol lookup operations. It has some affect
  40. * on timing whenever a chuck of memory is committed.
  41. *
  42. * #ifdef C6 : Generate code using C6 compiler. C6 compiler
  43. * calls _mcount() as the profiling routine where as
  44. * C8 calls _penter().
  45. *
  46. *
  47. *
  48. *
  49. * Modification History:
  50. *
  51. * 92.07.28 RezaB -- Created
  52. * 94.02.08 a-honwah -- ported to MIPS and ALPHA
  53. * 98.04.28 DerrickG (mdg) -- QFE:
  54. * - use private grow-on-demand heap for Wststrdup() - large symbol count
  55. * - remove unused code associated with patching - reduce irrelevant mem usage
  56. * - modify WSP file format for large symbol count (long vs. short)
  57. * - modify TMI file write routine for arbitrary function name sizes
  58. * - added UnmapDebugInformation() to release symbols from DBGHELP
  59. * - eliminated dump for modules with no symbols
  60. * - modified WST.INI parsing code for more robust section recognition
  61. * - added MaxSnaps WST.INI entry in [Time Interval] section to control
  62. * memory allocated for snapshot data
  63. * - Modified SetSymbolSearchPath() to put current directory first in
  64. * search path per standard - see docs for SymInitialize()
  65. * - Removed unused internal version number (it's already in the .rc)
  66. *
  67. */
  68. #if DBG
  69. //
  70. // Don't do anything for the checked builds, let it be controlled from the
  71. // sources file.
  72. //
  73. #else
  74. //
  75. // Disable all debugging options.
  76. //
  77. #undef INFODBG
  78. #undef SETUPDBG
  79. #define SdPrint(_x_)
  80. #define IdPrint(_x_)
  81. #endif
  82. #ifdef SETUPDBG
  83. #define SdPrint(_x_) DbgPrint _x_
  84. #else
  85. #define SdPrint(_x_)
  86. #endif
  87. #ifdef INFODBG
  88. #define IdPrint(_x_) DbgPrint _x_
  89. #else
  90. #define IdPrint(_x_)
  91. #endif
  92. /* * * * * * * * * * * * * I N C L U D E F I L E S * * * * * * * * * * */
  93. #include <nt.h>
  94. #include <ntrtl.h>
  95. #include <nturtl.h>
  96. #include <ntcsrsrv.h>
  97. #include <stdlib.h>
  98. #include <stdio.h>
  99. #include <string.h>
  100. #include <excpt.h>
  101. #include <windows.h>
  102. #include <dbghelp.h>
  103. #include "wst.h"
  104. #include "wstexp.h"
  105. #if defined(_AMD64_)
  106. VOID
  107. penter (
  108. VOID
  109. )
  110. {
  111. return;
  112. }
  113. #endif
  114. #if defined(ALPHA) || defined(AXP64)
  115. #define REG_BUFFER_SIZE (sizeof(DWORDLONG) * 64)
  116. #elif defined(IA64)
  117. #define REG_BUFFER_SIZE sizeof(CONTEXT) / sizeof(DWORDLONG)
  118. #endif
  119. #if defined(ALPHA) || defined(IA64)
  120. //typedef double DWORDLONG; // bobw not needed in NT5
  121. void SaveAllRegs (DWORDLONG *pSaveRegs) ;
  122. void RestoreAllRegs (DWORDLONG *pSaveRegs) ;
  123. void penter(void);
  124. #endif
  125. void SetSymbolSearchPath (void);
  126. LPSTR lpSymbolSearchPath = NULL;
  127. #define NO_CALLER 10L
  128. /* * * * * * * * * * G L O B A L D E C L A R A T I O N S * * * * * * * * */
  129. /* * * * * * * * * * F U N C T I O N P R O T O T Y P E S * * * * * * * * */
  130. BOOLEAN WSTMain (IN PVOID DllHandle, ULONG Reason,
  131. IN PCONTEXT Context OPTIONAL);
  132. BOOLEAN WstDllInitializations (void);
  133. void WstRecordInfo (DWORD_PTR dwAddress, DWORD_PTR dwPrevAddress);
  134. void WstGetSymbols (PIMG pCurImg, PSZ pszImageName, PVOID pvImageBase,
  135. ULONG ulCodeLength,
  136. PIMAGE_COFF_SYMBOLS_HEADER DebugInfo);
  137. void WstDllCleanups (void);
  138. INT WstAccessXcptFilter (ULONG ulXcptNo, PEXCEPTION_POINTERS pXcptPtr);
  139. HANDLE WstInitWspFile (PIMG pImg);
  140. void WstClearBitStrings (PIMG pImg);
  141. void WstDumpData (PIMG pImg);
  142. void WstRotateWsiMem (PIMG pImg);
  143. void WstWriteTmiFile (PIMG pImg);
  144. int WstCompare (PWSP, PWSP);
  145. void WstSort (WSP wsp[], INT iLeft, INT iRight);
  146. int WstBCompare (DWORD_PTR *, PWSP);
  147. PWSP WstBSearch (DWORD_PTR dwAddr, WSP wspCur[], INT n);
  148. void WstSwap (WSP wsp[], INT i, INT j);
  149. DWORD WstDumpThread (PVOID pvArg);
  150. DWORD WstClearThread (PVOID pvArg);
  151. DWORD WstPauseThread (PVOID pvArg);
  152. void WstDataOverFlow(void);
  153. #ifdef BATCHING
  154. BOOL WstOpenBatchFile (VOID);
  155. #endif
  156. #if defined(_PPC_)
  157. //BOOL WINAPI _CRT_INIT(HINSTANCE, DWORD, LPVOID);
  158. #endif
  159. /* * * * * * * * * * * G L O B A L V A R I A B L E S * * * * * * * * * */
  160. HANDLE hWspSec;
  161. PULONG pulShared;
  162. HANDLE hSharedSec;
  163. HANDLE hWstHeap = NULL; // mdg 4/98 for private heap
  164. IMG aImg [MAX_IMAGES];
  165. int iImgCnt;
  166. HANDLE hGlobalSem;
  167. HANDLE hLocalSem;
  168. HANDLE hDoneEvent;
  169. HANDLE hDumpEvent;
  170. HANDLE hClearEvent;
  171. HANDLE hPauseEvent;
  172. HANDLE hDumpThread;
  173. HANDLE hClearThread;
  174. HANDLE hPauseThread;
  175. DWORD DumpClientId;
  176. DWORD ClearClientId;
  177. DWORD PauseClientId;
  178. PSZ pszBaseAppImageName;
  179. PSZ pszFullAppImageName;
  180. WSTSTATE WstState = NOT_STARTED;
  181. char achPatchBuffer [PATCHFILESZ+1] = "???";
  182. PULONG pulWsiBits;
  183. PULONG pulWspBits;
  184. PULONG pulCurWsiBits;
  185. static UINT uiTimeSegs= 0;
  186. ULONG ulSegSize;
  187. ULONG ulMaxSnapULONGs = (MAX_SNAPS_DFLT + 31) / 32; // mdg 98/3
  188. ULONG ulSnaps = 0L;
  189. ULONG ulBitCount = 0L;
  190. LARGE_INTEGER liStart;
  191. int iTimeInterval = 0; // mdg 98/3
  192. BOOL fInThread = FALSE;
  193. ULONG ulThdStackSize = 16*PAGE_SIZE;
  194. BOOL fPatchImage = FALSE;
  195. SECURITY_DESCRIPTOR SecDescriptor;
  196. LARGE_INTEGER liOverhead = {0L, 0L};
  197. #ifdef BATCHING
  198. HANDLE hBatchFile;
  199. BOOL fBatch = TRUE;
  200. #endif
  201. /* * * * * * E X P O R T E D G L O B A L V A R I A B L E S * * * * * */
  202. /* none */
  203. /****************************** W S T M a i n *******************************
  204. *
  205. * WSTMain () -
  206. * This is the DLL entry routine. It performs
  207. * DLL's initializations and cleanup.
  208. *
  209. * ENTRY -none-
  210. *
  211. * EXIT -none-
  212. *
  213. * RETURN TRUE if successful
  214. * FALSE otherwise.
  215. *
  216. * WARNING:
  217. * -none-
  218. *
  219. * COMMENT:
  220. * -none-
  221. *
  222. */
  223. BOOLEAN WSTMain (IN PVOID DllHandle,
  224. ULONG Reason,
  225. IN PCONTEXT Context OPTIONAL)
  226. {
  227. DllHandle; // avoid compiler warnings
  228. Context; // avoid compiler warnings
  229. if (Reason == DLL_PROCESS_ATTACH) {
  230. //
  231. // Initialize the DLL data
  232. //
  233. #if defined(_PPC_LIBC)
  234. if (!_CRT_INIT(DllHandle, Reason, Context))
  235. return(FALSE);
  236. #endif
  237. KdPrint (("WST: DLL_PROCESS_ATTACH\n"));
  238. WstDllInitializations ();
  239. } else if (Reason == DLL_PROCESS_DETACH) {
  240. //
  241. // Cleanup time
  242. //
  243. #if defined(_PPC_LIBC)
  244. if (!_CRT_INIT(DllHandle, Reason, Context))
  245. return(FALSE);
  246. #endif
  247. KdPrint (("WST: DLL_PROCESS_DETACH\n"));
  248. WstDllCleanups ();
  249. }
  250. #if defined(DBG)
  251. else {
  252. KdPrint (("WST: DLL_PROCESS_??\n")); // mdg 98/3
  253. }
  254. #endif // DBG
  255. return (TRUE);
  256. } /* WSTMain() */
  257. /****************** W s t s t r d u p ****************************
  258. *
  259. * Wststrdup () -
  260. * Allocate a memory and then duplicate a string
  261. * It is here because we don't want to use strdup in crtdll.dll
  262. *
  263. * ENTRY LPSTR
  264. *
  265. * EXIT LPSTR
  266. *
  267. * RETURN NULL if failed
  268. * LPSTR is success
  269. *
  270. * WARNING:
  271. * -none-
  272. *
  273. * COMMENT:
  274. * -none-
  275. *
  276. */
  277. LPSTR Wststrdup (LPTSTR lpInput)
  278. // No NULL return ever - throws exception if low on memory
  279. {
  280. size_t StringLen;
  281. LPSTR lpOutput;
  282. #if defined(DBG)
  283. if (NULL == lpInput) {
  284. KdPrint (("WST: Wststrdup() - NULL pointer\n")); // mdg 98/3
  285. return NULL;
  286. }
  287. #endif
  288. if (NULL == hWstHeap) {
  289. hWstHeap = HeapCreate( HEAP_GENERATE_EXCEPTIONS, 1, 0 ); // Create min size growable heap
  290. }
  291. StringLen = strlen( lpInput ) + 1;
  292. lpOutput = HeapAlloc( hWstHeap, HEAP_GENERATE_EXCEPTIONS, StringLen );
  293. if (lpOutput)
  294. CopyMemory( lpOutput, lpInput, StringLen );
  295. return lpOutput;
  296. }
  297. /****************** W s t D l l I n i t i a l i z a t i o n s ***************
  298. *
  299. * WstDllInitializations () -
  300. * Performs the following initializations:
  301. *
  302. * o Create LOCAL semaphore (not named)
  303. * o Create/Open global storage for WST data
  304. * o Locate all the executables/DLLs in the address and
  305. * grab all the symbols
  306. * o Sort the symbol list
  307. * o Set the profiling flag to TRUE
  308. *
  309. *
  310. * ENTRY -none-
  311. *
  312. * EXIT -none-
  313. *
  314. * RETURN TRUE if successful
  315. * FALSE otherwise.
  316. *
  317. * WARNING:
  318. * -none-
  319. *
  320. * COMMENT:
  321. * -none-
  322. *
  323. */
  324. BOOLEAN WstDllInitializations ()
  325. {
  326. DWORD_PTR dwAddr = 0L;
  327. DWORD dwPrevAddr = 0L;
  328. ANSI_STRING ObjName;
  329. UNICODE_STRING UnicodeName;
  330. OBJECT_ATTRIBUTES ObjAttributes;
  331. PLDR_DATA_TABLE_ENTRY LdrDataTableEntry;
  332. PPEB Peb;
  333. PSZ ImageName;
  334. PLIST_ENTRY Next;
  335. ULONG ExportSize;
  336. PIMAGE_EXPORT_DIRECTORY ExportDirectory;
  337. STRING ImageStringName;
  338. LARGE_INTEGER AllocationSize;
  339. SIZE_T ulViewSize;
  340. LARGE_INTEGER liOffset = {0L, 0L};
  341. HANDLE hIniFile;
  342. NTSTATUS Status;
  343. IO_STATUS_BLOCK iostatus;
  344. char achTmpImageName [32];
  345. PCHAR pchPatchExes = "";
  346. PCHAR pchPatchImports = "";
  347. PCHAR pchPatchCallers = "";
  348. PCHAR pchTimeInterval = "";
  349. PVOID ImageBase;
  350. ULONG CodeLength;
  351. LARGE_INTEGER liFreq;
  352. PIMG pImg;
  353. PIMAGE_NT_HEADERS pImageNtHeader;
  354. TCHAR atchProfObjsName[160] = PROFOBJSNAME;
  355. PTEB pteb = NtCurrentTeb();
  356. LARGE_INTEGER liStartTicks;
  357. LARGE_INTEGER liEndTicks;
  358. ULONG ulElapsed;
  359. PCHAR pchEntry;
  360. int i; // To match "->iSymCnt"
  361. #ifndef _WIN64
  362. PIMAGE_DEBUG_INFORMATION pImageDbgInfo = NULL;
  363. #endif
  364. /*
  365. ***
  366. */
  367. SetSymbolSearchPath();
  368. // Create public share security descriptor for all the named objects
  369. //
  370. Status = RtlCreateSecurityDescriptor (
  371. &SecDescriptor,
  372. SECURITY_DESCRIPTOR_REVISION1
  373. );
  374. if (!NT_SUCCESS(Status)) {
  375. KdPrint (("WST: WstDllInitializations() - "
  376. "RtlCreateSecurityDescriptor failed - 0x%lx\n", Status)); // mdg 98/3
  377. return (FALSE);
  378. }
  379. Status = RtlSetDaclSecurityDescriptor (
  380. &SecDescriptor, // SecurityDescriptor
  381. TRUE, // DaclPresent
  382. NULL, // Dacl
  383. FALSE // DaclDefaulted
  384. );
  385. if (!NT_SUCCESS(Status)) {
  386. KdPrint (("WST: WstDllInitializations() - "
  387. "RtlSetDaclSecurityDescriptor failed - 0x%lx\n", Status)); // mdg 98/3
  388. return (FALSE);
  389. }
  390. /*
  391. ***
  392. */
  393. // Initialization for GLOBAL semaphore creation (named)
  394. //
  395. RtlInitString (&ObjName, GLOBALSEMNAME);
  396. Status = RtlAnsiStringToUnicodeString (&UnicodeName, &ObjName, TRUE);
  397. if (!NT_SUCCESS(Status)) {
  398. KdPrint (("WST: WstDllInitializations() - "
  399. "RtlAnsiStringToUnicodeString failed - 0x%lx\n", Status));
  400. return (FALSE);
  401. }
  402. InitializeObjectAttributes (&ObjAttributes,
  403. &UnicodeName,
  404. OBJ_OPENIF | OBJ_CASE_INSENSITIVE,
  405. NULL,
  406. &SecDescriptor);
  407. // Create GLOBAL semaphore
  408. //
  409. Status = NtCreateSemaphore (&hGlobalSem,
  410. SEMAPHORE_QUERY_STATE |
  411. SEMAPHORE_MODIFY_STATE |
  412. SYNCHRONIZE,
  413. &ObjAttributes,
  414. 1L,
  415. 1L);
  416. RtlFreeUnicodeString (&UnicodeName); // HWC 11/93
  417. if (!NT_SUCCESS(Status)) {
  418. KdPrint (("WST: WstDllInitializations() - "
  419. "GLOBAL semaphore creation failed - 0x%lx\n", Status)); // mdg 98/3
  420. return (FALSE);
  421. }
  422. /*
  423. ***
  424. */
  425. // Create LOCAL semaphore (not named - only for this process context)
  426. //
  427. Status = NtCreateSemaphore (&hLocalSem,
  428. SEMAPHORE_QUERY_STATE |
  429. SEMAPHORE_MODIFY_STATE |
  430. SYNCHRONIZE,
  431. NULL,
  432. 1L,
  433. 1L);
  434. if (!NT_SUCCESS(Status)) {
  435. KdPrint (("WST: WstDllInitializations() - "
  436. "LOCAL semaphore creation failed - 0x%lx\n", // mdg 98/3
  437. Status));
  438. return (FALSE);
  439. }
  440. /*
  441. ***
  442. */
  443. // Initialize for allocating shared memory
  444. //
  445. RtlInitString(&ObjName, SHAREDNAME);
  446. Status = RtlAnsiStringToUnicodeString(&UnicodeName, &ObjName, TRUE);
  447. if (!NT_SUCCESS(Status)) {
  448. KdPrint (("WST: WstDllInitializations() - "
  449. "RtlAnsiStringToUnicodeString() failed - 0x%lx\n", Status));
  450. return (FALSE);
  451. }
  452. InitializeObjectAttributes(&ObjAttributes,
  453. &UnicodeName,
  454. OBJ_OPENIF | OBJ_CASE_INSENSITIVE,
  455. NULL,
  456. &SecDescriptor);
  457. AllocationSize.HighPart = 0;
  458. AllocationSize.LowPart = PAGE_SIZE;
  459. // Create a read-write section
  460. //
  461. Status = NtCreateSection(&hSharedSec,
  462. SECTION_MAP_READ | SECTION_MAP_WRITE,
  463. &ObjAttributes,
  464. &AllocationSize,
  465. PAGE_READWRITE,
  466. SEC_RESERVE,
  467. NULL);
  468. RtlFreeUnicodeString (&UnicodeName); // HWC 11/93
  469. if (!NT_SUCCESS(Status)) {
  470. KdPrint (("WST: WstDllInitializations() - "
  471. "NtCreateSection() failed - 0x%lx\n", Status));
  472. return (FALSE);
  473. }
  474. ulViewSize = AllocationSize.LowPart;
  475. pulShared = NULL;
  476. // Map the section - commit all
  477. //
  478. Status = NtMapViewOfSection (hSharedSec,
  479. NtCurrentProcess(),
  480. (PVOID *)&pulShared,
  481. 0L,
  482. PAGE_SIZE,
  483. NULL,
  484. &ulViewSize,
  485. ViewUnmap,
  486. 0L,
  487. PAGE_READWRITE);
  488. if (!NT_SUCCESS(Status)) {
  489. KdPrint (("WST: WstDllInitializations() - "
  490. "NtMapViewOfSection() failed - 0x%lx\n", Status));
  491. return (FALSE);
  492. }
  493. *pulShared = 0L;
  494. /*
  495. ***
  496. */
  497. hIniFile = CreateFile (
  498. WSTINIFILE, // The filename
  499. GENERIC_READ, // Desired access
  500. FILE_SHARE_READ, // Shared Access
  501. NULL, // Security Access
  502. OPEN_EXISTING, // Read share access
  503. FILE_ATTRIBUTE_NORMAL, // Open option
  504. NULL); // No template file
  505. if (hIniFile == INVALID_HANDLE_VALUE) {
  506. KdPrint (("WST: WstDllInitializations() - "
  507. "Error openning %s - 0x%lx\n", WSTINIFILE, GetLastError()));
  508. return (FALSE);
  509. }
  510. Status = NtReadFile(hIniFile, // DLL patch file handle
  511. 0L, // Event - optional
  512. NULL, // Completion routine - optional
  513. NULL, // Completion routine argument - optional
  514. &iostatus, // Completion status
  515. (PVOID)achPatchBuffer, // Buffer to receive data
  516. PATCHFILESZ, // Bytes to read
  517. &liOffset, // Byte offset - optional
  518. 0L); // Target process - optional
  519. if (!NT_SUCCESS(Status)) {
  520. KdPrint (("WST: WstDllInitializations() - "
  521. "Error reading %s - 0x%lx\n", WSTINIFILE, Status));
  522. return (FALSE);
  523. } else if (iostatus.Information >= PATCHFILESZ) {
  524. KdPrint (("WST: WstDllInitializations() - "
  525. "initialization file buffer too small (%lu)\n", PATCHFILESZ));
  526. return (FALSE);
  527. } else {
  528. achPatchBuffer [iostatus.Information] = '\0';
  529. _strupr (achPatchBuffer);
  530. // Allow for headers to appear in any order in .INI or be absent
  531. pchPatchExes = strstr( achPatchBuffer, PATCHEXELIST );
  532. pchPatchImports = strstr( achPatchBuffer, PATCHIMPORTLIST );
  533. pchTimeInterval = strstr( achPatchBuffer, TIMEINTERVALIST );
  534. if (pchPatchExes != NULL) {
  535. if (pchPatchExes > achPatchBuffer)
  536. *(pchPatchExes - 1) = '\0';
  537. } else {
  538. pchPatchExes = "";
  539. }
  540. if (pchPatchImports != NULL) {
  541. if (pchPatchImports > achPatchBuffer)
  542. *(pchPatchImports - 1) = '\0';
  543. } else {
  544. pchPatchImports = "";
  545. }
  546. if (pchTimeInterval != NULL) {
  547. const char * pSnapsEntry = strstr( pchTimeInterval, MAX_SNAPS_ENTRY );
  548. if (pchTimeInterval > achPatchBuffer)
  549. *(pchTimeInterval - 1) = '\0';
  550. if (pSnapsEntry) {
  551. long lSnapsEntry =
  552. atol( pSnapsEntry + sizeof( MAX_SNAPS_ENTRY ) - 1 );
  553. if (lSnapsEntry > 0)
  554. ulMaxSnapULONGs = (lSnapsEntry + 31) / 32;
  555. }
  556. } else {
  557. pchTimeInterval = "";
  558. }
  559. }
  560. NtClose (hIniFile);
  561. SdPrint (("WST: WstDllInitializations() - Patching info:\n"));
  562. SdPrint (("WST: -- %s\n", pchPatchExes));
  563. SdPrint (("WST: -- %s\n", pchPatchImports));
  564. SdPrint (("WST: -- %s\n", pchTimeInterval));
  565. /*
  566. ***
  567. */
  568. // Initialize for allocating global storage for WSPs
  569. //
  570. _ui64toa ((ULONG64)pteb->ClientId.UniqueProcess, atchProfObjsName+75, 10);
  571. _ui64toa ((ULONG64)pteb->ClientId.UniqueThread, atchProfObjsName+105, 10);
  572. strcat (atchProfObjsName, atchProfObjsName+75);
  573. strcat (atchProfObjsName, atchProfObjsName+105);
  574. SdPrint (("WST: WstDllInitializations() - %s\n", atchProfObjsName));
  575. RtlInitString(&ObjName, atchProfObjsName);
  576. Status = RtlAnsiStringToUnicodeString(&UnicodeName, &ObjName, TRUE);
  577. if (!NT_SUCCESS(Status)) {
  578. KdPrint (("WST: WstDllInitializations() - "
  579. "RtlAnsiStringToUnicodeString() failed - 0x%lx\n", Status));
  580. return (FALSE);
  581. }
  582. InitializeObjectAttributes (&ObjAttributes,
  583. &UnicodeName,
  584. OBJ_OPENIF | OBJ_CASE_INSENSITIVE,
  585. NULL,
  586. &SecDescriptor);
  587. AllocationSize.HighPart = 0;
  588. AllocationSize.LowPart = MEMSIZE;
  589. // Create a read-write section
  590. //
  591. Status =NtCreateSection(&hWspSec,
  592. SECTION_MAP_READ | SECTION_MAP_WRITE,
  593. &ObjAttributes,
  594. &AllocationSize,
  595. PAGE_READWRITE,
  596. SEC_RESERVE,
  597. NULL);
  598. RtlFreeUnicodeString (&UnicodeName); // HWC 11/93
  599. if (!NT_SUCCESS(Status)) {
  600. KdPrint (("WST: WstDllInitializations() - "
  601. "NtCreateSection() failed - 0x%lx\n", Status));
  602. return (FALSE);
  603. }
  604. ulViewSize = AllocationSize.LowPart;
  605. pImg = &aImg[0];
  606. pImg->pWsp = NULL;
  607. // Map the section - commit the first 4 * COMMIT_SIZE pages
  608. //
  609. Status = NtMapViewOfSection(hWspSec,
  610. NtCurrentProcess(),
  611. (PVOID *)&(pImg->pWsp),
  612. 0L,
  613. COMMIT_SIZE * 4,
  614. NULL,
  615. &ulViewSize,
  616. ViewUnmap,
  617. 0L,
  618. PAGE_READWRITE);
  619. if (!NT_SUCCESS(Status)) {
  620. KdPrint (("WST: WstDllInitializations() - "
  621. "NtMapViewOfSection() failed - 0x%lx\n", Status));
  622. return (FALSE);
  623. }
  624. try /* EXCEPT - to handle access violation exception. */ {
  625. //
  626. // Locate all the executables/DLLs in the address and get their symbols
  627. //
  628. BOOL fTuneApp = FALSE; // Set if whole app is to be tuned
  629. iImgCnt = 0;
  630. Peb = NtCurrentPeb();
  631. Next = Peb->Ldr->InMemoryOrderModuleList.Flink;
  632. for (; Next != &Peb->Ldr->InMemoryOrderModuleList; Next = Next->Flink) {
  633. IdPrint (("WST: WstDllInitializations() - Walking module chain: 0x%lx\n", Next));
  634. LdrDataTableEntry =
  635. (PLDR_DATA_TABLE_ENTRY)
  636. (CONTAINING_RECORD(Next,LDR_DATA_TABLE_ENTRY,InMemoryOrderLinks));
  637. ImageBase = LdrDataTableEntry->DllBase;
  638. if ( Peb->ImageBaseAddress == ImageBase ) {
  639. RtlUnicodeStringToAnsiString (&ImageStringName,
  640. &LdrDataTableEntry->BaseDllName,
  641. TRUE);
  642. ImageName = ImageStringName.Buffer;
  643. pszBaseAppImageName = ImageStringName.Buffer;
  644. RtlUnicodeStringToAnsiString (&ImageStringName,
  645. &LdrDataTableEntry->FullDllName,
  646. TRUE);
  647. pszFullAppImageName = ImageStringName.Buffer;
  648. //
  649. // Skip the object directory name (if any)
  650. //
  651. if ( (pszFullAppImageName = strchr(pszFullAppImageName, ':')) ) {
  652. pszFullAppImageName--;
  653. } else {
  654. pszFullAppImageName = pszBaseAppImageName;
  655. }
  656. IdPrint (("WST: WstDllInitializations() - FullAppImageName: %s\n", pszFullAppImageName));
  657. } else {
  658. ExportDirectory =
  659. (PIMAGE_EXPORT_DIRECTORY)RtlImageDirectoryEntryToData (
  660. ImageBase,
  661. TRUE,
  662. IMAGE_DIRECTORY_ENTRY_EXPORT,
  663. &ExportSize);
  664. ImageName = (PSZ)((ULONG_PTR)ImageBase + ExportDirectory->Name);
  665. IdPrint (("WST: WstDllInitializations() - ImageName: %s\n", ImageName));
  666. }
  667. pImageNtHeader = RtlImageNtHeader (ImageBase);
  668. _strupr (strcpy (achTmpImageName, ImageName));
  669. pchEntry = strstr (pchPatchExes, achTmpImageName);
  670. if (pchEntry) {
  671. if (*(pchEntry-1) == ';') {
  672. pchEntry = NULL;
  673. } else if ( Peb->ImageBaseAddress == ImageBase )
  674. fTuneApp = TRUE;
  675. }
  676. if ( strcmp (achTmpImageName, WSTDLL) && (pchEntry || fTuneApp) ) {
  677. if ( !fPatchImage )
  678. fPatchImage = TRUE;
  679. //
  680. // Locate the code range.
  681. //
  682. pImg->pszName = Wststrdup (ImageName);
  683. pImg->ulCodeStart = 0L;
  684. pImg->ulCodeEnd = 0L;
  685. pImg->iSymCnt = 0;
  686. #ifndef _WIN64
  687. pImageDbgInfo = MapDebugInformation (0L,
  688. ImageName,
  689. lpSymbolSearchPath,
  690. (DWORD)ImageBase);
  691. if (pImageDbgInfo == NULL) {
  692. IdPrint (("WST: WstDllInitializations() - "
  693. "No symbols for %s\n", ImageName));
  694. } else if ( pImageDbgInfo->CoffSymbols == NULL ) {
  695. IdPrint (("WST: WstDllInitializations() - "
  696. "No coff symbols for %s\n", ImageName));
  697. } else {
  698. PIMAGE_COFF_SYMBOLS_HEADER DebugInfo;
  699. DebugInfo = pImageDbgInfo->CoffSymbols;
  700. if (DebugInfo->LvaToFirstSymbol == 0L) {
  701. IdPrint (("WST: WstDllInitializations() - "
  702. "Virtual Address to coff symbols not set for %s\n",
  703. ImageName));
  704. } else {
  705. CodeLength = (DebugInfo->RvaToLastByteOfCode -
  706. DebugInfo->RvaToFirstByteOfCode) - 1;
  707. pImg->ulCodeStart = (ULONG)ImageBase +
  708. DebugInfo->RvaToFirstByteOfCode;
  709. pImg->ulCodeEnd = pImg->ulCodeStart + CodeLength;
  710. IdPrint(( "WST: WstDllInitializations() - %ul total symbols\n", DebugInfo->NumberOfSymbols ));
  711. WstGetSymbols (pImg, ImageName, ImageBase, CodeLength,
  712. DebugInfo);
  713. }
  714. // mdg 98/3
  715. // Must release debug information - should not stay around cluttering up memory!
  716. if (!UnmapDebugInformation( pImageDbgInfo ))
  717. KdPrint(("WST: WstDllInitializations() - failure in UnmapDebugInformation()\n"));
  718. pImageDbgInfo = NULL;
  719. } // if pImageDbgInfo->CoffSymbols != NULL
  720. #endif // _WIN64
  721. IdPrint (("WST: WstDllInitializations() - @ 0x%08lx "
  722. "image #%d = %s; %d symbols extracted\n", (ULONG)ImageBase, iImgCnt,
  723. ImageName, pImg->iSymCnt));
  724. pImg->pWsp[pImg->iSymCnt].pszSymbol = UNKNOWN_SYM;
  725. pImg->pWsp[pImg->iSymCnt].ulFuncAddr = UNKNOWN_ADDR;
  726. pImg->pWsp[pImg->iSymCnt].ulBitString = 0; // mdg 98/3
  727. pImg->pWsp[pImg->iSymCnt].ulCodeLength = 0; // mdg 98/3
  728. (pImg->iSymCnt)++;
  729. //
  730. // Set wsi.
  731. //
  732. pImg->pulWsi = pImg->pulWsiNxt = (PULONG)
  733. (pImg->pWsp + pImg->iSymCnt);
  734. RtlZeroMemory (pImg->pulWsi,
  735. pImg->iSymCnt * ulMaxSnapULONGs * sizeof(ULONG));
  736. //
  737. // Set wsp.
  738. //
  739. pImg->pulWsp = (PULONG)(pImg->pulWsi +
  740. (pImg->iSymCnt * ulMaxSnapULONGs));
  741. RtlZeroMemory (pImg->pulWsp,
  742. pImg->iSymCnt * ulMaxSnapULONGs * sizeof(ULONG));
  743. //
  744. // Sort wsp & set code lengths
  745. //
  746. WstSort (pImg->pWsp, 0, pImg->iSymCnt-1);
  747. //
  748. // Last symbol length is set to be the same as length of
  749. // (n-1)th symbol or remaining code length of module
  750. //
  751. i = pImg->iSymCnt - 1; // mdg 98/3 (assert pImg->iSymCnt is at least 1)
  752. if (i--) { // Test count & set index to top symbol
  753. pImg->pWsp[i].ulCodeLength = (ULONG)(
  754. i ? pImg->pWsp[i].ulFuncAddr - pImg->pWsp[i - 1].ulFuncAddr
  755. : pImg->ulCodeEnd + 1 - pImg->pWsp[i].ulFuncAddr);
  756. while (i-- > 0) { // Enumerate symbols & set index
  757. pImg->pWsp[i].ulCodeLength = (ULONG)(pImg->pWsp[i+1].ulFuncAddr -
  758. pImg->pWsp[i].ulFuncAddr);
  759. }
  760. }
  761. //
  762. // Setup next pWsp
  763. //
  764. (pImg+1)->pWsp = (PWSP)(pImg->pulWsp +
  765. (pImg->iSymCnt * ulMaxSnapULONGs));
  766. iImgCnt++;
  767. pImg++;
  768. if (iImgCnt == MAX_IMAGES) {
  769. KdPrint(("WST: WstDllInitialization() - Not enough "
  770. "space allocated for all images\n"));
  771. return (FALSE);
  772. }
  773. }
  774. } // if (Next != &Peb->Ldr->InMemoryOrderModuleList)
  775. } // try
  776. //
  777. // + : transfer control to the handler (EXCEPTION_EXECUTE_HANDLER)
  778. // 0 : continue search (EXCEPTION_CONTINUE_SEARCH)
  779. // - : dismiss exception & continue (EXCEPTION_CONTINUE_EXECUTION)
  780. //
  781. except ( WstAccessXcptFilter (GetExceptionCode(), GetExceptionInformation()) )
  782. {
  783. //
  784. // Should never get here since filter never returns
  785. // EXCEPTION_EXECUTE_HANDLER.
  786. //
  787. KdPrint (("WST: WstDllInitializations() - *LOGIC ERROR* - "
  788. "Inside the EXCEPT: (xcpt=0x%lx)\n", GetExceptionCode()));
  789. }
  790. /*
  791. ***
  792. */
  793. //
  794. // Get the frequency
  795. //
  796. NtQueryPerformanceCounter (&liStart, &liFreq);
  797. if (strlen(pchTimeInterval) > (sizeof(TIMEINTERVALIST)+1)) // mdg 98/3
  798. iTimeInterval = atoi (pchTimeInterval+sizeof(TIMEINTERVALIST)+1);
  799. if ( iTimeInterval == 0 ) {
  800. //
  801. // Use the default value
  802. //
  803. iTimeInterval = TIMESEG;
  804. }
  805. ulSegSize = iTimeInterval * (liFreq.LowPart / 1000);
  806. #ifdef BATCHING
  807. fBatch = WstOpenBatchFile();
  808. #endif
  809. SdPrint (("WST: Time interval: Millisecs=%d Ticks=%lu\n",
  810. iTimeInterval, ulSegSize));
  811. if (fPatchImage) {
  812. // Initialization for DONE event creation
  813. //
  814. RtlInitString (&ObjName, DONEEVENTNAME);
  815. Status = RtlAnsiStringToUnicodeString (&UnicodeName, &ObjName, TRUE);
  816. if (!NT_SUCCESS(Status)) {
  817. KdPrint (("WST: WstDllInitializations() - "
  818. "RtlAnsiStringToUnicodeString failed - 0x%lx\n", Status));
  819. return (FALSE);
  820. }
  821. InitializeObjectAttributes (&ObjAttributes,
  822. &UnicodeName,
  823. OBJ_OPENIF | OBJ_CASE_INSENSITIVE,
  824. NULL,
  825. &SecDescriptor);
  826. // Create DONE event
  827. //
  828. Status = NtCreateEvent (&hDoneEvent,
  829. EVENT_QUERY_STATE |
  830. EVENT_MODIFY_STATE |
  831. SYNCHRONIZE,
  832. &ObjAttributes,
  833. NotificationEvent,
  834. TRUE);
  835. RtlFreeUnicodeString (&UnicodeName); // HWC 11/93
  836. if (!NT_SUCCESS(Status)) {
  837. KdPrint (("WST: WstDllInitializations() - "
  838. "DONE event creation failed - 0x%lx\n", Status)); // mdg 98/3
  839. return (FALSE);
  840. }
  841. // Initialization for DUMP event creation
  842. //
  843. RtlInitString (&ObjName, DUMPEVENTNAME);
  844. Status = RtlAnsiStringToUnicodeString (&UnicodeName, &ObjName, TRUE);
  845. if (!NT_SUCCESS(Status)) {
  846. KdPrint (("WST: WstDllInitializations() - "
  847. "RtlAnsiStringToUnicodeString failed - 0x%lx\n", Status));
  848. return (FALSE);
  849. }
  850. InitializeObjectAttributes (&ObjAttributes,
  851. &UnicodeName,
  852. OBJ_OPENIF | OBJ_CASE_INSENSITIVE,
  853. NULL,
  854. &SecDescriptor);
  855. // Create DUMP event
  856. //
  857. Status = NtCreateEvent (&hDumpEvent,
  858. EVENT_QUERY_STATE |
  859. EVENT_MODIFY_STATE |
  860. SYNCHRONIZE,
  861. &ObjAttributes,
  862. NotificationEvent,
  863. FALSE);
  864. RtlFreeUnicodeString (&UnicodeName); // HWC 11/93
  865. if (!NT_SUCCESS(Status)) {
  866. KdPrint (("WST: WstDllInitializations() - "
  867. "DUMP event creation failed - 0x%lx\n", Status)); // mdg 98/3
  868. return (FALSE);
  869. }
  870. // Initialization for CLEAR event creation
  871. //
  872. RtlInitString (&ObjName, CLEAREVENTNAME);
  873. Status = RtlAnsiStringToUnicodeString (&UnicodeName, &ObjName, TRUE);
  874. if (!NT_SUCCESS(Status)) {
  875. KdPrint (("WST: WstDllInitializations() - "
  876. "RtlAnsiStringToUnicodeString failed - 0x%lx\n", Status));
  877. return (FALSE);
  878. }
  879. InitializeObjectAttributes (&ObjAttributes,
  880. &UnicodeName,
  881. OBJ_OPENIF | OBJ_CASE_INSENSITIVE,
  882. NULL,
  883. &SecDescriptor);
  884. // Create CLEAR event
  885. //
  886. Status = NtCreateEvent (&hClearEvent,
  887. EVENT_QUERY_STATE |
  888. EVENT_MODIFY_STATE |
  889. SYNCHRONIZE,
  890. &ObjAttributes,
  891. NotificationEvent,
  892. FALSE);
  893. RtlFreeUnicodeString (&UnicodeName); // HWC 11/93
  894. if (!NT_SUCCESS(Status)) {
  895. KdPrint (("WST: WstDllInitializations() - "
  896. "CLEAR event creation failed - 0x%lx\n", Status)); // mdg 98/3
  897. return (FALSE);
  898. }
  899. // Initialization for PAUSE event creation
  900. //
  901. RtlInitString (&ObjName, PAUSEEVENTNAME);
  902. Status = RtlAnsiStringToUnicodeString (&UnicodeName, &ObjName, TRUE);
  903. if (!NT_SUCCESS(Status)) {
  904. KdPrint (("WST: WstDllInitializations() - "
  905. "RtlAnsiStringToUnicodeString failed - 0x%lx\n", Status));
  906. return (FALSE);
  907. }
  908. InitializeObjectAttributes (&ObjAttributes,
  909. &UnicodeName,
  910. OBJ_OPENIF | OBJ_CASE_INSENSITIVE,
  911. NULL,
  912. &SecDescriptor);
  913. // Create PAUSE event
  914. //
  915. Status = NtCreateEvent (&hPauseEvent,
  916. EVENT_QUERY_STATE |
  917. EVENT_MODIFY_STATE |
  918. SYNCHRONIZE,
  919. &ObjAttributes,
  920. NotificationEvent,
  921. FALSE);
  922. RtlFreeUnicodeString (&UnicodeName); // HWC 11/93
  923. if (!NT_SUCCESS(Status)) {
  924. KdPrint (("WST: WstDllInitializations() - "
  925. "PAUSE event creation failed - 0x%lx\n", Status)); // mdg 98/3
  926. return (FALSE);
  927. }
  928. //
  929. // Calculate excess overhead for WstRecordInfo
  930. //
  931. liOverhead.HighPart = 0L;
  932. liOverhead.LowPart = 0xFFFFFFFF;
  933. for (i=0; i < NUM_ITERATIONS; i++) {
  934. NtQueryPerformanceCounter (&liStartTicks, NULL);
  935. //
  936. WSTUSAGE(NtCurrentTeb()) = 0L;
  937. #ifdef i386
  938. _asm
  939. {
  940. push edi
  941. mov edi, dword ptr [ebp+4]
  942. mov dwAddr, edi
  943. mov edi, dword ptr [ebp+8]
  944. mov dwPrevAddr, edi
  945. pop edi
  946. }
  947. #endif
  948. #if defined(ALPHA) || defined(IA64)
  949. {
  950. PULONG pulAddr;
  951. DWORDLONG SaveRegisters [REG_BUFFER_SIZE] ;
  952. SaveAllRegs (SaveRegisters);
  953. pulAddr = (PULONG) dwAddr;
  954. pulAddr -= 1;
  955. RestoreAllRegs (SaveRegisters);
  956. }
  957. #elif defined(_X86_)
  958. SaveAllRegs ();
  959. RestoreAllRegs ();
  960. #endif
  961. WSTUSAGE(NtCurrentTeb()) = 0L;
  962. Status = NtWaitForSingleObject (hLocalSem, FALSE, NULL);
  963. if (!NT_SUCCESS(Status)) {
  964. KdPrint (("WST: WstDllInitilizations() - "
  965. "Wait for LOCAL semaphore failed - 0x%lx\n", Status));
  966. }
  967. liStart.QuadPart = liStart.QuadPart - liStart.QuadPart ;
  968. liStart.QuadPart = liStart.QuadPart + liStart.QuadPart ;
  969. liStart.QuadPart = liStart.QuadPart + liStart.QuadPart ;
  970. Status = NtReleaseSemaphore (hLocalSem, 1, NULL);
  971. if (!NT_SUCCESS(Status)) {
  972. KdPrint (("WST: WstDllInitializations() - "
  973. "Error releasing LOCAL semaphore - 0x%lx\n", Status));
  974. }
  975. WSTUSAGE(NtCurrentTeb()) = 0L;
  976. //
  977. NtQueryPerformanceCounter (&liEndTicks, NULL);
  978. ulElapsed = liEndTicks.LowPart - liStartTicks.LowPart;
  979. if (ulElapsed < liOverhead.LowPart) {
  980. liOverhead.LowPart = ulElapsed;
  981. }
  982. }
  983. SdPrint (("WST: WstDllInitializations() - WstRecordInfo() overhead = %lu\n",
  984. liOverhead.LowPart));
  985. // Start monitor threads
  986. //
  987. hDumpThread = CreateThread (
  988. NULL, // no security attribute
  989. (DWORD)1024L, // initial stack size
  990. (LPTHREAD_START_ROUTINE)WstDumpThread, // thread starting address
  991. NULL, // no argument for the thread
  992. (DWORD)0, // no creation flag
  993. &DumpClientId); // address for thread id
  994. hClearThread = CreateThread (
  995. NULL, // no security attribute
  996. (DWORD)1024L, // initial stack size
  997. (LPTHREAD_START_ROUTINE)WstClearThread, // thread starting address
  998. NULL, // no argument for the thread
  999. (DWORD)0, // no creation flag
  1000. &ClearClientId); // address for thread id
  1001. hPauseThread = CreateThread (
  1002. NULL, // no security attribute
  1003. (DWORD)1024L, // initial stack size
  1004. (LPTHREAD_START_ROUTINE)WstPauseThread, // thread starting address
  1005. NULL, // no argument for the thread
  1006. (DWORD)0, // no creation flag
  1007. &PauseClientId); // address for thread id
  1008. NtQueryPerformanceCounter (&liStart, NULL);
  1009. WstState = STARTED;
  1010. }
  1011. return (TRUE);
  1012. } /* WstDllInitializations () */
  1013. /****************************** _ p e n t e r ******************************
  1014. *
  1015. * _penter() / _mcount() -
  1016. * This is the main profiling routine. This routine is called
  1017. * upon entry of each routine in the profiling DLL/EXE.
  1018. *
  1019. * ENTRY -none-
  1020. *
  1021. * EXIT -none-
  1022. *
  1023. * RETURN -none-
  1024. *
  1025. * WARNING:
  1026. * -none-
  1027. *
  1028. * COMMENT:
  1029. * Compiling apps with -Gp option trashs EAX initially.
  1030. *
  1031. */
  1032. #ifdef i386
  1033. void __cdecl _penter ()
  1034. #elif defined(ALPHA) || defined(IA64) || defined(_AMD64_)
  1035. void c_penter (ULONG_PTR dwPrevious, ULONG_PTR dwCurrent)
  1036. #endif
  1037. {
  1038. DWORD_PTR dwAddr;
  1039. DWORD_PTR dwPrevAddr;
  1040. ULONG_PTR ulInWst ;
  1041. #if defined(ALPHA) || defined(_AXP64_) || defined(IA64)
  1042. PULONG pulAddr;
  1043. DWORDLONG SaveRegisters [REG_BUFFER_SIZE];
  1044. SaveAllRegs(SaveRegisters) ;
  1045. #endif
  1046. dwAddr = 0L;
  1047. dwPrevAddr = 0L;
  1048. ulInWst = WSTUSAGE(NtCurrentTeb());
  1049. if (WstState != STARTED) {
  1050. goto Exit0;
  1051. } else if (ulInWst) {
  1052. goto Exit0;
  1053. }
  1054. //
  1055. // Put the address of the calling function into var dwAddr
  1056. //
  1057. #ifdef i386
  1058. _asm
  1059. {
  1060. push edi
  1061. mov edi, dword ptr [ebp+4]
  1062. mov dwAddr, edi
  1063. mov edi, dword ptr [ebp+8]
  1064. mov dwPrevAddr, edi
  1065. pop edi
  1066. }
  1067. #endif
  1068. #if defined(ALPHA) || defined(IA64)
  1069. dwPrevAddr = NO_CALLER;
  1070. dwAddr = dwCurrent;
  1071. // GetCaller (&dwAddr, 0x0220); // FIXFIX StackSize
  1072. // now check if we are calling from the stub we created
  1073. pulAddr = (PULONG) dwAddr;
  1074. pulAddr -= 1;
  1075. if (*(pulAddr) == 0x681b4000 &&
  1076. (*(pulAddr + 1) == 0xa75e0008) &&
  1077. (*(pulAddr + 8) == 0xfefe55aa) ) {
  1078. // get the address that we will go after the penter function
  1079. dwAddr = *(pulAddr + 4) & 0x0000ffff;
  1080. if (*(pulAddr + 5) & 0x00008000) {
  1081. // fix the address since we have to add one when
  1082. // we created our stub code
  1083. dwAddr -= 1;
  1084. }
  1085. dwAddr = dwAddr << 16;
  1086. dwAddr |= *(pulAddr + 5) & 0x0000ffff;
  1087. // get the caller to the stub
  1088. dwPrevAddr = dwPrevious;
  1089. // GetStubCaller (&dwPrevAddr, 0x0220); // FIXFIX StackSize
  1090. }
  1091. #endif
  1092. //
  1093. // Call WstRecordInfo for this API
  1094. //
  1095. #ifdef i386
  1096. SaveAllRegs ();
  1097. #endif
  1098. WstRecordInfo (dwAddr, dwPrevAddr);
  1099. #ifdef i386
  1100. RestoreAllRegs ();
  1101. #endif
  1102. Exit0:
  1103. #if defined(ALPHA) || defined(IA64)
  1104. RestoreAllRegs (SaveRegisters);
  1105. #endif
  1106. return;
  1107. } /* _penter() / _mcount()*/
  1108. void __cdecl _mcount ()
  1109. {
  1110. }
  1111. /************************* W s t R e c o r d I n f o ************************
  1112. *
  1113. * WstRecordInfo (dwAddress) -
  1114. *
  1115. * ENTRY dwAddress - Address of the routine just called
  1116. *
  1117. * EXIT -none-
  1118. *
  1119. * RETURN -none-
  1120. *
  1121. * WARNING:
  1122. * -none-
  1123. *
  1124. * COMMENT:
  1125. * -none-
  1126. *
  1127. */
  1128. void WstRecordInfo (DWORD_PTR dwAddress, DWORD_PTR dwPrevAddress)
  1129. {
  1130. NTSTATUS Status;
  1131. INT x;
  1132. INT i, iIndex;
  1133. PWSP pwspTmp;
  1134. LARGE_INTEGER liNow, liTmp;
  1135. LARGE_INTEGER liElapsed;
  1136. CHAR *pszSym;
  1137. #ifdef BATCHING
  1138. CHAR szBatchBuf[128];
  1139. DWORD dwCache;
  1140. DWORD dwHits;
  1141. DWORD dwBatch;
  1142. IO_STATUS_BLOCK ioStatus;
  1143. #endif
  1144. WSTUSAGE(NtCurrentTeb()) = 1;
  1145. //
  1146. // Wait for the semaphore object to suspend execution of other threads
  1147. //
  1148. Status = NtWaitForSingleObject (hLocalSem, FALSE, NULL);
  1149. if (!NT_SUCCESS(Status)) {
  1150. KdPrint (("WST: WstRecordInfo() - "
  1151. "Wait for LOCAL semaphore failed - 0x%lx\n", Status));
  1152. }
  1153. NtQueryPerformanceCounter(&liNow, NULL);
  1154. liElapsed.QuadPart = liNow.QuadPart - liStart.QuadPart ;
  1155. // SdPrint(("WST: WstRecordInfo() - Elapsed time: %ld\n", liElapsed.LowPart));
  1156. //
  1157. // WstBSearch is a binary find function that will return the address of
  1158. // the wsp record we want
  1159. //
  1160. // SdPrint(("WST: WstRecordInfo() - Preparing for WstBSearch of 0x%lx\n",
  1161. // dwAddress-5));
  1162. pwspTmp = NULL;
  1163. for (i=0; i<iImgCnt; i++) {
  1164. if ( (dwAddress >= aImg[i].ulCodeStart) &&
  1165. (dwAddress < aImg[i].ulCodeEnd) ) {
  1166. #ifdef i386
  1167. pwspTmp = WstBSearch(dwAddress-5, aImg[i].pWsp, aImg[i].iSymCnt);
  1168. if (!pwspTmp) {
  1169. pwspTmp = WstBSearch(UNKNOWN_ADDR, aImg[i].pWsp, aImg[i].iSymCnt);
  1170. }
  1171. #else
  1172. // the following works for both MIPS and ALPHA
  1173. pwspTmp = WstBSearch(dwAddress, aImg[i].pWsp, aImg[i].iSymCnt);
  1174. if (!pwspTmp) {
  1175. // symbol not found
  1176. pwspTmp = WstBSearch(UNKNOWN_ADDR, aImg[i].pWsp, aImg[i].iSymCnt);
  1177. }
  1178. #endif
  1179. break;
  1180. }
  1181. }
  1182. iIndex = i;
  1183. if (pwspTmp) {
  1184. pszSym = pwspTmp->pszSymbol;
  1185. pwspTmp->ulBitString |= 1;
  1186. } else {
  1187. SdPrint (("WST: WstRecordInfo() - LOGIC ERROR - Completely bogus addr = 0x%08lx\n",
  1188. dwAddress)); // We could also get here if moduled compiled with -Gh but no COFF symbols available
  1189. }
  1190. if (liElapsed.LowPart >= ulSegSize) {
  1191. SdPrint(("WST: WstRecordInfo() - ulSegSize expired; "
  1192. "Preparing to shift the BitStrings\n"));
  1193. if (ulBitCount < 31) {
  1194. for (i=0; i<iImgCnt; i++) {
  1195. for (x=0; x < aImg[i].iSymCnt ; x++ ) {
  1196. aImg[i].pWsp[x].ulBitString <<= 1;
  1197. }
  1198. }
  1199. }
  1200. liElapsed.LowPart = 0L;
  1201. ulBitCount++;
  1202. NtQueryPerformanceCounter(&liStart, NULL);
  1203. liNow = liStart;
  1204. if (ulBitCount == 32) {
  1205. SdPrint(("WST: WstRecordInfo() - Dump Bit Strings\n"));
  1206. for (i=0; i<iImgCnt; i++) {
  1207. for (x=0; x < aImg[i].iSymCnt ; x++ ) {
  1208. aImg[i].pulWsiNxt[x] = aImg[i].pWsp[x].ulBitString;
  1209. aImg[i].pWsp[x].ulBitString = 0L;
  1210. }
  1211. aImg[i].pulWsiNxt += aImg[i].iSymCnt;
  1212. }
  1213. ulSnaps++;
  1214. ulBitCount = 0;
  1215. if (ulSnaps == ulMaxSnapULONGs) {
  1216. KdPrint (("WST: WstRecordInfo() - No more space available"
  1217. " for next time snap data!\n"));
  1218. //
  1219. // Dump and clear the data
  1220. //
  1221. WstDataOverFlow();
  1222. }
  1223. }
  1224. }
  1225. #ifdef BATCHING
  1226. //
  1227. // The following code will get the current batching information
  1228. // if the DLL was compiled with the BATCHING variable set. You
  1229. // should not have this variable set if you are tuning GDI.
  1230. //
  1231. if (fBatch) {
  1232. GdiGetCsInfo(&dwHits, &dwBatch, &dwCache);
  1233. if (dwHits)
  1234. GdiResetCsInfo();
  1235. if (dwBatch == 10)
  1236. GdiResetCsInfo();
  1237. while (*(pszSym++) != '_');
  1238. sprintf(szBatchBuf, "%s:%s,%ld,%ld,%ld\n",
  1239. aImg[iIndex].pszName, pszSym, dwHits, dwBatch, dwCache);
  1240. Status = NtWriteFile(hBatchFile,
  1241. NULL,
  1242. NULL,
  1243. NULL,
  1244. &ioStatus,
  1245. szBatchBuf,
  1246. strlen(szBatchBuf),
  1247. NULL,
  1248. NULL
  1249. );
  1250. if (!NT_SUCCESS(Status)) {
  1251. KdPrint (("WST: WstRecodInfo() - "
  1252. "NtWriteFile() failed on hBatchFile - 0x%lx\n", Status));
  1253. }
  1254. }//Batching info
  1255. #endif
  1256. //
  1257. // We call NtQueryPerformanceCounter here to account for the overhead
  1258. // required for doing our work
  1259. //
  1260. NtQueryPerformanceCounter(&liTmp, NULL);
  1261. liElapsed.QuadPart = liTmp.QuadPart - liNow.QuadPart ;
  1262. liStart.QuadPart = liStart.QuadPart + liElapsed.QuadPart ;
  1263. liStart.QuadPart = liStart.QuadPart + liOverhead.QuadPart ;
  1264. //
  1265. // Release semaphore to continue execution of other threads
  1266. //
  1267. Status = NtReleaseSemaphore (hLocalSem, 1, NULL);
  1268. if (!NT_SUCCESS(Status)) {
  1269. KdPrint (("WST: WstRecordInfo () - "
  1270. "Error releasing LOCAL semaphore - 0x%lx\n", Status));
  1271. }
  1272. WSTUSAGE(NtCurrentTeb()) = 0L;
  1273. } /* WstRecordInfo () */
  1274. /******************** W s t C l e a r B i t S t r i n g *********************
  1275. *
  1276. * Function: WstClearBitStrings (pImg)
  1277. *
  1278. * Purpose: This function clears the BitString for each symbol.
  1279. *
  1280. * Parameters: pImg - Current image data structure pointer
  1281. *
  1282. * Returns: -none-
  1283. *
  1284. * History: 8-3-92 Marklea - created
  1285. *
  1286. */
  1287. void WstClearBitStrings (PIMG pImg)
  1288. {
  1289. UINT uiLshft = 0;
  1290. INT x;
  1291. //
  1292. // Since we are completed with the profile, we need to create a
  1293. // DWORD out of the balance of the bitString. We do this by left
  1294. // shifting the bitstring by difference between the bitCount and
  1295. // 32.
  1296. //
  1297. if (ulBitCount < 32) {
  1298. uiLshft =(UINT)(31 - ulBitCount);
  1299. for (x=0; x < pImg->iSymCnt; x++) {
  1300. pImg->pWsp[x].ulBitString <<= uiLshft;
  1301. pImg->pulWsiNxt[x] = pImg->pWsp[x].ulBitString;
  1302. }
  1303. pImg->pulWsiNxt += pImg->iSymCnt;
  1304. }
  1305. } /* WstClearBitStrings () */
  1306. /*********************** W s t I n i t W s p F i l e ***********************
  1307. *
  1308. * Function: WstInitWspFile (pImg)
  1309. *
  1310. * Purpose: This function will create a WSP file and dump the header
  1311. * information for the file.
  1312. *
  1313. * Parameters: pImg - Current image data structure pointer
  1314. *
  1315. * Returns: Handle to the WSP file.
  1316. *
  1317. * History: 8-3-92 Marklea - created
  1318. *
  1319. */
  1320. HANDLE WstInitWspFile (PIMG pImg)
  1321. {
  1322. CHAR szOutFile [256] = WSTROOT;
  1323. CHAR szModName [128] = {0};
  1324. PCHAR pDot;
  1325. CHAR szExt [5] = "WSP";
  1326. WSPHDR wsphdr;
  1327. DWORD dwBytesWritten;
  1328. BOOL fRet;
  1329. HANDLE hFile = INVALID_HANDLE_VALUE;
  1330. int iExt = 0;
  1331. //
  1332. // Prepare the filename path
  1333. //
  1334. strcat (szOutFile, pImg->pszName);
  1335. //
  1336. // Open the file for binary output.
  1337. //
  1338. pImg->fDumpAll = TRUE;
  1339. while (iExt < 256) {
  1340. strcpy ((strchr(szOutFile,'.'))+1, szExt);
  1341. hFile = CreateFile ( szOutFile, // WSP file handle
  1342. GENERIC_WRITE |
  1343. GENERIC_READ, // Desired access
  1344. 0L, // Read share access
  1345. NULL, // No EaBuffer
  1346. CREATE_NEW,
  1347. FILE_ATTRIBUTE_NORMAL,
  1348. 0); // EaBuffer length
  1349. if (hFile != INVALID_HANDLE_VALUE) {
  1350. IdPrint(("WST: WstInitWspFile() - WSP file name: %s\n",
  1351. szOutFile));
  1352. if (iExt != 0) {
  1353. pImg->fDumpAll = FALSE;
  1354. }
  1355. break;
  1356. }
  1357. iExt++;
  1358. sprintf (szExt, "W%02x", iExt);
  1359. }
  1360. if (iExt == 256) {
  1361. KdPrint (("WST: WstInitWspFile() - "
  1362. "Error creating %s - 0x%lx\n", szOutFile,
  1363. GetLastError()));
  1364. return (hFile);
  1365. }
  1366. //
  1367. // Fill a WSP header structure
  1368. //
  1369. strcpy(szModName, pImg->pszName);
  1370. pDot = strchr(szModName, '.');
  1371. if (pDot)
  1372. strcpy(pDot, "");
  1373. strcpy(wsphdr.chFileSignature, "WSP");
  1374. wsphdr.ulTimeStamp = 0L;
  1375. wsphdr.usId = 0;
  1376. wsphdr.ulApiCount = 0;
  1377. wsphdr.ulSetSymbols = pImg->ulSetSymbols;
  1378. wsphdr.ulModNameLen = strlen(szModName);
  1379. wsphdr.ulSegSize = (ULONG)iTimeInterval;
  1380. wsphdr.ulOffset = wsphdr.ulModNameLen + (ULONG)sizeof(WSPHDR);
  1381. wsphdr.ulSnaps = ulSnaps;
  1382. //
  1383. // Write header and module name
  1384. //
  1385. fRet = WriteFile(hFile, // Wsp file handle
  1386. (PVOID)&wsphdr, // Buffer of data
  1387. (ULONG)sizeof(WSPHDR), // Bytes to write
  1388. &dwBytesWritten, // Bytes written
  1389. NULL);
  1390. if (!fRet) {
  1391. KdPrint (("WST: WstInitWspFile() - "
  1392. "Error writing to %s - 0x%lx\n", szOutFile,
  1393. GetLastError));
  1394. return (NULL);
  1395. }
  1396. fRet = WriteFile (hFile, // Wsp file handle
  1397. (PVOID)szModName, // Buffer of data
  1398. (ULONG)strlen(szModName), // Bytes to write
  1399. &dwBytesWritten,
  1400. NULL);
  1401. if (!fRet) {
  1402. KdPrint (("WST: WstInitWspFile() - "
  1403. "Error writing to %s - 0x%lx\n", szOutFile,
  1404. GetLastError()));
  1405. return (NULL);
  1406. }
  1407. return (hFile);
  1408. } /* WstInitWspFile () */
  1409. /************************** W s t D u m p D a t a **************************
  1410. *
  1411. * Function: WstDumpData (pImg)
  1412. *
  1413. * Purpose:
  1414. *
  1415. * Parameters: pImg - Current image data structure pointer
  1416. *
  1417. * Returns: NONE
  1418. *
  1419. * History: 8-3-92 Marklea - created
  1420. *
  1421. */
  1422. void WstDumpData (PIMG pImg)
  1423. {
  1424. INT x = 0;
  1425. DWORD dwBytesWritten;
  1426. BOOL fRet;
  1427. HANDLE hWspFile;
  1428. if ( !(hWspFile = WstInitWspFile(pImg)) ) {
  1429. KdPrint (("WST: WstDumpData() - Error creating WSP file.\n"));
  1430. return;
  1431. }
  1432. //
  1433. // Write all the symbols with any bits set
  1434. //
  1435. for (x=0; x<pImg->iSymCnt; x++) {
  1436. if (pImg->pWsp[x].ulBitString) {
  1437. fRet = WriteFile(
  1438. hWspFile, // Wsp file handle
  1439. (PVOID)(pImg->pulWsp+(x*ulSnaps)), // Buffer of data
  1440. ulSnaps * sizeof(ULONG), // Bytes to write
  1441. &dwBytesWritten, // Bytes written
  1442. NULL); // Optional
  1443. if (!fRet) {
  1444. KdPrint (("WST: WstDumpData() - "
  1445. "Error writing to WSP file - 0x%lx\n",
  1446. GetLastError()));
  1447. return;
  1448. }
  1449. }
  1450. }
  1451. //
  1452. // Now write all the symbols with no bits set
  1453. //
  1454. if (pImg->fDumpAll) {
  1455. for (x=0; x<pImg->iSymCnt; x++) {
  1456. if (pImg->pWsp[x].ulBitString == 0L) {
  1457. fRet = WriteFile(
  1458. hWspFile, // Wsp file handle
  1459. (PVOID)(pImg->pulWsp+(x*ulSnaps)), // Buffer of data
  1460. ulSnaps * sizeof(ULONG), // Bytes to write
  1461. &dwBytesWritten, // Bytes written
  1462. NULL); // Optional
  1463. if (!fRet) {
  1464. KdPrint (("WST: WstDumpData() - "
  1465. "Error writing to WSP file - 0x%lx\n",
  1466. GetLastError()));
  1467. return;
  1468. }
  1469. }
  1470. }
  1471. }
  1472. fRet = CloseHandle(hWspFile);
  1473. if (!fRet) {
  1474. KdPrint (("WST: WstDumpData() - "
  1475. "Error closing %s - 0x%lx\n", "WSI file",
  1476. GetLastError()));
  1477. return;
  1478. }
  1479. } /* WstDumpData () */
  1480. /************************ W s t W r i t e T m i F i l e **********************
  1481. *
  1482. * Function: WstWriteTmiFile (pImg)
  1483. *
  1484. * Purpose: Write all the symbole info for the current image to its TMI
  1485. * file.
  1486. *
  1487. *
  1488. * Parameters: pImg - Current image data structure pointer
  1489. *
  1490. * Returns: -none-
  1491. *
  1492. * History: 8-5-92 Marklea - created
  1493. *
  1494. */
  1495. void WstWriteTmiFile (PIMG pImg)
  1496. {
  1497. CHAR szOutFile [256] = WSTROOT;
  1498. CHAR szBuffer [256];
  1499. CHAR szExt [5] = "TMI";
  1500. HANDLE hTmiFile;
  1501. INT x;
  1502. DWORD dwBytesWritten;
  1503. BOOL fRet;
  1504. int iExt = 0;
  1505. PSZ pszSymbol;
  1506. ULONG nSymbolLen;
  1507. //
  1508. // Prepare the filename path
  1509. //
  1510. strcat (szOutFile, pImg->pszName);
  1511. //
  1512. // Open the file for binary output.
  1513. //
  1514. pImg->fDumpAll = TRUE;
  1515. KdPrint (("WST: WstWriteTmiFile() - creating TMI for %s\n", szOutFile));
  1516. while (iExt < 256) {
  1517. strcpy ((strchr(szOutFile,'.'))+1, szExt);
  1518. hTmiFile = CreateFile ( szOutFile, // TMI file handle
  1519. GENERIC_WRITE |
  1520. GENERIC_READ, // Desired access
  1521. 0L, // Read share access
  1522. NULL, // No EaBuffer
  1523. CREATE_NEW,
  1524. FILE_ATTRIBUTE_NORMAL,
  1525. 0); // EaBuffer length
  1526. if (hTmiFile != INVALID_HANDLE_VALUE) {
  1527. IdPrint(("WST: WstWriteTmiFile() - TMI file name: %s\n",
  1528. szOutFile));
  1529. if (iExt != 0) {
  1530. pImg->fDumpAll = FALSE;
  1531. }
  1532. break;
  1533. }
  1534. iExt++;
  1535. sprintf (szExt, "T%02x", iExt);
  1536. }
  1537. if (iExt == 256) {
  1538. KdPrint (("WST: WstWriteTmiFile() - "
  1539. "Error creating %s - 0x%lx\n", szOutFile,
  1540. GetLastError()));
  1541. return;
  1542. }
  1543. sprintf(szBuffer, "/* %s for NT */\n"
  1544. "/* Total Symbols= %lu */\n"
  1545. "DO NOT DELETE\n"
  1546. "%d\n"
  1547. "TDFID = 0\n",
  1548. pImg->pszName,
  1549. pImg->fDumpAll ? pImg->iSymCnt : pImg->ulSetSymbols,
  1550. iTimeInterval);
  1551. //
  1552. // Write header
  1553. //
  1554. fRet = WriteFile(hTmiFile, // Tmi file handle
  1555. (PVOID)szBuffer, // Buffer of data
  1556. (ULONG)strlen(szBuffer), // Bytes to write
  1557. &dwBytesWritten, // Bytes written
  1558. NULL);
  1559. if (!fRet) {
  1560. KdPrint (("WST: WstWriteTmiFile() - "
  1561. "Error writing to %s - 0x%lx\n", szOutFile,
  1562. GetLastError));
  1563. return;
  1564. }
  1565. //
  1566. // Dump all the symbols with set bits.
  1567. //
  1568. IdPrint (("WST: WstWriteTmiFile() - Dumping set symbols...\n"));
  1569. for (x=0; x<pImg->iSymCnt ; x++) {
  1570. if (pImg->pWsp[x].ulBitString) {
  1571. pszSymbol =
  1572. (pImg->pWsp[x].pszSymbol);
  1573. nSymbolLen = strlen( pszSymbol ); // mdg 98/4
  1574. sprintf(szBuffer, "%ld 0000:%08lx 0x%lx %lu ", // mdg 98/4
  1575. (LONG)x, pImg->pWsp[x].ulFuncAddr,
  1576. pImg->pWsp[x].ulCodeLength, nSymbolLen);
  1577. //
  1578. // Write symbol line
  1579. //
  1580. fRet = WriteFile(hTmiFile, // Tmi file handle
  1581. (PVOID)szBuffer, // Buffer of data
  1582. (ULONG)strlen(szBuffer), // Bytes to write
  1583. &dwBytesWritten, // Bytes written
  1584. NULL)
  1585. && WriteFile(hTmiFile, // Tmi file handle
  1586. (PVOID)pszSymbol, // Buffer of data
  1587. nSymbolLen, // Bytes to write
  1588. &dwBytesWritten, // Bytes written
  1589. NULL)
  1590. && WriteFile(hTmiFile, // Tmi file handle
  1591. (PVOID)"\n", // Buffer of data
  1592. 1, // Bytes to write
  1593. &dwBytesWritten, // Bytes written
  1594. NULL);
  1595. if (!fRet) {
  1596. KdPrint (("WST: WstWriteTmiFile() - "
  1597. "Error writing to %s - 0x%lx\n", szOutFile,
  1598. GetLastError));
  1599. return;
  1600. }
  1601. }
  1602. }
  1603. //
  1604. // Now dump all the symbols without any bits set.
  1605. //
  1606. IdPrint (("WST: WstWriteTmiFile() - Dumping unset symbols...\n"));
  1607. if (pImg->fDumpAll) {
  1608. for (x=0; x<pImg->iSymCnt ; x++ ) {
  1609. if (!pImg->pWsp[x].ulBitString) {
  1610. pszSymbol =
  1611. (pImg->pWsp[x].pszSymbol);
  1612. nSymbolLen = strlen( pszSymbol ); // mdg 98/4
  1613. sprintf(szBuffer, "%ld 0000:%08lx 0x%lx %lu ", // mdg 98/4
  1614. (LONG)x, pImg->pWsp[x].ulFuncAddr,
  1615. pImg->pWsp[x].ulCodeLength, nSymbolLen);
  1616. //
  1617. // Write symbol line
  1618. //
  1619. fRet = WriteFile(hTmiFile, // Tmi file handle
  1620. (PVOID)szBuffer, // Buffer of data
  1621. (ULONG)strlen(szBuffer), // Bytes to write
  1622. &dwBytesWritten, // Bytes written
  1623. NULL)
  1624. && WriteFile(hTmiFile, // Tmi file handle
  1625. (PVOID)pszSymbol, // Buffer of data
  1626. nSymbolLen, // Bytes to write
  1627. &dwBytesWritten, // Bytes written
  1628. NULL)
  1629. && WriteFile(hTmiFile, // Tmi file handle
  1630. (PVOID)"\n", // Buffer of data
  1631. 1, // Bytes to write
  1632. &dwBytesWritten, // Bytes written
  1633. NULL);
  1634. if (!fRet) {
  1635. KdPrint (("WST: WstWriteTmiFile() - "
  1636. "Error writing to %s - 0x%lx\n", szOutFile,
  1637. GetLastError));
  1638. return;
  1639. }
  1640. }
  1641. }
  1642. }
  1643. fRet = CloseHandle(hTmiFile);
  1644. if (!fRet) {
  1645. KdPrint (("WST: WstWriteTmiFile() - "
  1646. "Error closing %s - 0x%lx\n", szOutFile, GetLastError()));
  1647. return;
  1648. }
  1649. } /* WstWriteTmiFile () */
  1650. /*********************** W s t R o t a t e W s i M e m ***********************
  1651. *
  1652. * Function: WstRotateWsiMem (pImg)
  1653. *
  1654. * Purpose:
  1655. *
  1656. *
  1657. * Parameters: pImg - Current image data structure pointer
  1658. *
  1659. * Returns: -none-
  1660. *
  1661. * History: 8-5-92 Marklea - created
  1662. *
  1663. */
  1664. void WstRotateWsiMem (PIMG pImg)
  1665. {
  1666. ULONG ulCurSnap;
  1667. ULONG ulOffset;
  1668. int x;
  1669. PULONG pulWsp;
  1670. pulWsp = pImg->pulWsp;
  1671. pImg->ulSetSymbols = 0;
  1672. for (x=0; x<pImg->iSymCnt; x++) {
  1673. ulOffset = 0L;
  1674. ulCurSnap = 0L;
  1675. pImg->pWsp[x].ulBitString = 0L;
  1676. while (ulCurSnap < ulSnaps) {
  1677. ulOffset = (ULONG)x + ((ULONG)pImg->iSymCnt * ulCurSnap);
  1678. *pulWsp = *(pImg->pulWsi + ulOffset);
  1679. pImg->pWsp[x].ulBitString |= (*pulWsp);
  1680. pulWsp++;
  1681. ulCurSnap++;
  1682. }
  1683. if (pImg->pWsp[x].ulBitString) {
  1684. /*
  1685. SdPrint (("WST: WstRotateWsiMem() - set: %s\n",
  1686. pImg->pWsp[x].pszSymbol));
  1687. */
  1688. (pImg->ulSetSymbols)++;
  1689. }
  1690. }
  1691. IdPrint (("WST: WstRotateWsiMem() - Number of set symbols = %lu\n",
  1692. pImg->ulSetSymbols));
  1693. } /* WstRotateWsiMwm () */
  1694. /*********************** W s t G e t S y m b o l s *************************
  1695. *
  1696. * WstGetSymbols (pCurWsp, pszImageName, pvImageBase, ulCodeLength, DebugInfo)
  1697. * This routine stores all the symbols for the current
  1698. * image into pCurWsp
  1699. *
  1700. * ENTRY upCurWsp - Pointer to current WSP structure
  1701. * pszImageName - Pointer to image name
  1702. * pvImageBase - Current image base address
  1703. * ulCodeLength - Current image code length
  1704. * DebugInfo - Pointer to the coff debug info structure
  1705. *
  1706. * EXIT -none-
  1707. *
  1708. * RETURN -none-
  1709. *
  1710. * WARNING:
  1711. * -none-
  1712. *
  1713. * COMMENT:
  1714. * -none-
  1715. *
  1716. */
  1717. #ifndef _WIN64
  1718. void WstGetSymbols (PIMG pCurImg,
  1719. PSZ pszImageName,
  1720. PVOID pvImageBase,
  1721. ULONG ulCodeLength,
  1722. PIMAGE_COFF_SYMBOLS_HEADER DebugInfo)
  1723. {
  1724. IMAGE_SYMBOL Symbol;
  1725. PIMAGE_SYMBOL SymbolEntry;
  1726. PUCHAR StringTable;
  1727. ULONG i;
  1728. char achTmp[9];
  1729. PWSP pCurWsp;
  1730. PSZ ptchSymName;
  1731. pCurWsp = pCurImg->pWsp;
  1732. achTmp[8] = '\0';
  1733. //
  1734. // Crack the COFF symbol table
  1735. //
  1736. SymbolEntry = (PIMAGE_SYMBOL)
  1737. ((ULONG)DebugInfo + DebugInfo->LvaToFirstSymbol);
  1738. StringTable = (PUCHAR)((ULONG)DebugInfo + DebugInfo->LvaToFirstSymbol +
  1739. DebugInfo->NumberOfSymbols * (ULONG)IMAGE_SIZEOF_SYMBOL);
  1740. //
  1741. // Loop through all symbols in the symbol table.
  1742. //
  1743. for (i = 0; i < DebugInfo->NumberOfSymbols; i++) {
  1744. //
  1745. // Skip thru aux symbols..
  1746. //
  1747. RtlMoveMemory (&Symbol, SymbolEntry, IMAGE_SIZEOF_SYMBOL);
  1748. if (Symbol.SectionNumber == 1) { //code section
  1749. if (ISFCN( Symbol.Type )) { // mdg 98/3 Also picks up WEAK_EXTERNAL functions
  1750. //
  1751. // This symbol is within the code.
  1752. //
  1753. pCurImg->iSymCnt++;
  1754. pCurWsp->ulBitString = 0L;
  1755. pCurWsp->ulFuncAddr = Symbol.Value + (ULONG)pvImageBase;
  1756. if (Symbol.N.Name.Short) {
  1757. strncpy (achTmp, (PSZ)&(Symbol.N.Name.Short), 8);
  1758. #ifdef i386
  1759. // only need to strip leading underscore for i386.
  1760. // mips and alpha are ok.
  1761. if (achTmp[0] == '_') {
  1762. pCurWsp->pszSymbol = Wststrdup (&achTmp[1]);
  1763. } else {
  1764. pCurWsp->pszSymbol = Wststrdup (achTmp);
  1765. }
  1766. #else
  1767. pCurWsp->pszSymbol = Wststrdup (achTmp);
  1768. #endif
  1769. } else {
  1770. ptchSymName = (PSZ)&StringTable[Symbol.N.Name.Long];
  1771. #ifdef i386
  1772. // only need to strip leading underscore for i386.
  1773. // mips and alpha are ok.
  1774. if (*ptchSymName == '_') {
  1775. ptchSymName++;
  1776. }
  1777. #endif
  1778. pCurWsp->pszSymbol = Wststrdup (ptchSymName);
  1779. }
  1780. // IdPrint(( "WST: WstGetSymbols() - 0x%lx = %s\n", pCurWsp->ulFuncAddr, pCurWsp->pszSymbol ));
  1781. pCurWsp++;
  1782. }
  1783. }
  1784. SymbolEntry = (PIMAGE_SYMBOL)((ULONG)SymbolEntry + IMAGE_SIZEOF_SYMBOL);
  1785. }
  1786. } /* WstGetSymbols () */
  1787. #endif
  1788. /*********************** W s t D l l C l e a n u p s ***********************
  1789. *
  1790. * WstDllCleanups () -
  1791. * Dumps the end data, closes all semaphores and events, and
  1792. * closes DUMP, CLEAR & PAUSE thread handles.
  1793. *
  1794. * ENTRY -none-
  1795. *
  1796. * EXIT -none-
  1797. *
  1798. * RETURN -none-
  1799. *
  1800. * WARNING:
  1801. * -none-
  1802. *
  1803. * COMMENT:
  1804. * -none-
  1805. *
  1806. */
  1807. void WstDllCleanups ()
  1808. {
  1809. NTSTATUS Status;
  1810. int i;
  1811. if (WstState != NOT_STARTED) {
  1812. WstState = STOPPED;
  1813. IdPrint(("WST: WstDllCleanups() - Outputting data...\n")); // mdg 98/3
  1814. if (ulBitCount != 0L) {
  1815. ulSnaps++;
  1816. }
  1817. //
  1818. // Get the GLOBAL semaphore.. (valid accross all process contexts)
  1819. //
  1820. Status = NtWaitForSingleObject (hGlobalSem, FALSE, NULL);
  1821. if (!NT_SUCCESS(Status)) {
  1822. KdPrint (("WST: WstDllCleanups() - "
  1823. "ERROR - Wait for GLOBAL semaphore failed - 0x%lx\n",
  1824. Status));
  1825. }
  1826. for (i=0; i<iImgCnt; i++) {
  1827. if (aImg[i].iSymCnt > 1) { // Don't dump modules w/o symbols (the 1 is UNKNOWN) mdg 98/4
  1828. WstClearBitStrings (&aImg[i]);
  1829. WstRotateWsiMem (&aImg[i]);
  1830. WstDumpData (&aImg[i]);
  1831. WstWriteTmiFile (&aImg[i]);
  1832. }
  1833. }
  1834. //
  1835. // Release the GLOBAL semaphore so other processes can dump data
  1836. //
  1837. Status = NtReleaseSemaphore (hGlobalSem, 1, NULL);
  1838. if (!NT_SUCCESS(Status)) {
  1839. KdPrint (("WST: WstDllCleanups() - "
  1840. "Error releasing GLOBAL semaphore - 0x%lx\n", Status));
  1841. }
  1842. IdPrint(("WST: WstDllCleanups() - ...Done.\n"));
  1843. }
  1844. if (fInThread) {
  1845. (*pulShared)--;
  1846. fInThread = FALSE;
  1847. if ( (int)*pulShared <= 0L ) {
  1848. Status = NtSetEvent (hDoneEvent, NULL);
  1849. if (!NT_SUCCESS(Status)) {
  1850. KdPrint (("WST: WstDllCleanups() - "
  1851. "ERROR - Setting DONE event failed - 0x%lx\n", Status));
  1852. }
  1853. }
  1854. }
  1855. // Unmap and close shared block section
  1856. //
  1857. Status = NtUnmapViewOfSection (NtCurrentProcess(), (PVOID)pulShared);
  1858. if (!NT_SUCCESS(Status)) {
  1859. KdPrint (("WST: WstDllCleanups() - "
  1860. "ERROR - NtUnmapViewOfSection() - 0x%lx\n", Status));
  1861. }
  1862. Status = NtClose(hSharedSec);
  1863. if (!NT_SUCCESS(Status)) {
  1864. KdPrint (("WST: WstDllCleanups() - "
  1865. "ERROR - NtClose() - 0x%lx\n", Status));
  1866. }
  1867. // Unmap and close WSP section
  1868. //
  1869. Status = NtUnmapViewOfSection (NtCurrentProcess(), (PVOID)aImg[0].pWsp);
  1870. if (!NT_SUCCESS(Status)) {
  1871. KdPrint (("WST: WstDllCleanups() - "
  1872. "ERROR - NtUnmapViewOfSection() - 0x%lx\n", Status));
  1873. }
  1874. Status = NtClose(hWspSec);
  1875. if (!NT_SUCCESS(Status)) {
  1876. KdPrint (("WST: WstDllCleanups() - "
  1877. "ERROR - NtClose() - 0x%lx\n", Status));
  1878. }
  1879. // Free private heap
  1880. //
  1881. if (NULL != hWstHeap) {
  1882. if (!HeapDestroy( hWstHeap )) { // Eliminate private heap & allocations
  1883. KdPrint (("WST: WstDllCleanups() -"
  1884. "ERROR - HeapDestroy() - 0x%lx\n", GetLastError()));
  1885. }
  1886. }
  1887. // Close GLOBAL semaphore
  1888. //
  1889. Status = NtClose (hGlobalSem);
  1890. if (!NT_SUCCESS(Status)) {
  1891. KdPrint (("WST: WstDllCleanups() - "
  1892. "ERROR - Could not close the GLOBAL semaphore - 0x%lx\n",
  1893. Status));
  1894. }
  1895. //
  1896. // Close LOCAL semaphore
  1897. //
  1898. Status = NtClose (hLocalSem);
  1899. if (!NT_SUCCESS(Status)) {
  1900. KdPrint (("WST: WstDllCleanups() - "
  1901. "ERROR - Could not close the LOCAL semaphore - 0x%lx\n",
  1902. Status));
  1903. }
  1904. if (fPatchImage) {
  1905. //
  1906. // Close all events
  1907. //
  1908. NtClose (hDoneEvent);
  1909. NtClose (hDumpEvent);
  1910. NtClose (hClearEvent);
  1911. NtClose (hPauseEvent);
  1912. //
  1913. // Close thread handles - threads are terminated during DLL detaching
  1914. // process.
  1915. //
  1916. CloseHandle (hDumpThread);
  1917. CloseHandle (hClearThread);
  1918. CloseHandle (hPauseThread);
  1919. }
  1920. } /* WstDllCleanups () */
  1921. /******************* W s t A c c e s s X c p t F i l t e r ******************
  1922. *
  1923. * WstAccessXcptFilter (ulXcptNo, pXcptInfoPtr) -
  1924. * Commits COMMIT_SIZE more pages of memory if exception is access
  1925. * violation.
  1926. *
  1927. * ENTRY ulXcptNo - exception number
  1928. * pXcptInfoPtr - exception report record info pointer
  1929. *
  1930. * EXIT -none-
  1931. *
  1932. * RETURN EXCEPTIONR_CONTINUE_EXECUTION : if access violation exception
  1933. * and mem committed successfully
  1934. * EXCEPTION_CONTINUE_SEARCH : if non-access violation exception
  1935. * or cannot commit more memory
  1936. * WARNING:
  1937. * -none-
  1938. *
  1939. * COMMENT:
  1940. * -none-
  1941. *
  1942. */
  1943. INT WstAccessXcptFilter (ULONG ulXcptNo, PEXCEPTION_POINTERS pXcptPtr)
  1944. {
  1945. NTSTATUS Status;
  1946. SIZE_T ulSize = COMMIT_SIZE;
  1947. PVOID pvMem = (PVOID)pXcptPtr->ExceptionRecord->ExceptionInformation[1];
  1948. if (ulXcptNo != EXCEPTION_ACCESS_VIOLATION) {
  1949. return (EXCEPTION_CONTINUE_SEARCH);
  1950. } else {
  1951. Status = NtAllocateVirtualMemory (NtCurrentProcess(),
  1952. &pvMem,
  1953. 0L,
  1954. &ulSize,
  1955. MEM_COMMIT,
  1956. PAGE_READWRITE);
  1957. if (!NT_SUCCESS(Status)) {
  1958. KdPrint (("WST: WstAccessXcptFilter() - "
  1959. "Error committing more memory @ 0x%08lx - 0x%08lx "
  1960. "- TEB=0x%08lx\n", pvMem, Status, NtCurrentTeb()));
  1961. return (EXCEPTION_CONTINUE_SEARCH);
  1962. } else {
  1963. SdPrint (("WST: WstAccessXcptFilter() - "
  1964. "Committed %d more pages @ 0x%08lx - TEB=0x%08lx\n",
  1965. COMMIT_SIZE/PAGE_SIZE, pvMem, NtCurrentTeb()));
  1966. }
  1967. return (EXCEPTION_CONTINUE_EXECUTION);
  1968. }
  1969. } /* WstAccessXcptFilter () */
  1970. /*****************************************************************************/
  1971. /******* S O R T / S E A R C H U T I L I T Y F U N C T I O N S *********/
  1972. /*****************************************************************************/
  1973. /************************* W s t C o m p a r e *****************************
  1974. *
  1975. * Function: WstCompare(PVOID val1,PVOID val2)
  1976. *
  1977. * Purpose: Compare values for qsort
  1978. *
  1979. *
  1980. * Parameters: PVOID
  1981. *
  1982. * Returns: -1 if val1 < val2
  1983. * 1 if val1 > val2
  1984. * 0 if val1 == val2
  1985. *
  1986. * History: 8-3-92 Marklea - created
  1987. *
  1988. */
  1989. int WstCompare (PWSP val1, PWSP val2)
  1990. {
  1991. return (val1->ulFuncAddr < val2->ulFuncAddr ? -1:
  1992. val1->ulFuncAddr == val2->ulFuncAddr ? 0:
  1993. 1);
  1994. } /* WstComapre () */
  1995. /*********************** W s t B C o m p a r e ********************************
  1996. *
  1997. * Function: WstBCompare(PDWORD pdwVal1, PVOID val2)
  1998. *
  1999. * Purpose: Compare values for Binary search
  2000. *
  2001. *
  2002. * Parameters: PVOID
  2003. *
  2004. * Returns: -1 if val1 < val2
  2005. * 1 if val1 > val2
  2006. * 0 if val1 == val2
  2007. *
  2008. * History: 8-3-92 Marklea - created
  2009. *
  2010. */
  2011. int WstBCompare (DWORD_PTR *pdwVal1, PWSP val2)
  2012. {
  2013. #if defined(_X86_)
  2014. return (*pdwVal1 < val2->ulFuncAddr ? -1:
  2015. *pdwVal1 == val2->ulFuncAddr ? 0:
  2016. 1);
  2017. #elif defined(ALPHA) || defined(IA64) || defined(_AMD64_)
  2018. int dwCompareCode = 0;
  2019. if (*pdwVal1 < val2->ulFuncAddr) {
  2020. dwCompareCode = -1;
  2021. } else if (*pdwVal1 >= val2->ulFuncAddr + val2->ulCodeLength) {
  2022. dwCompareCode = 1;
  2023. }
  2024. return (dwCompareCode);
  2025. #endif
  2026. } /* WstBCompare () */
  2027. /*********************** W s t S o r t **************************************
  2028. *
  2029. * Function: WstSort(WSP wsp[], INT iLeft, INT iRight)
  2030. *
  2031. * Purpose: Sort WSP array for binary search
  2032. *
  2033. *
  2034. * Parameters: wsp[] Pointer to WSP array
  2035. * iLeft Left most index value for array
  2036. * iRight Rightmost index value for array
  2037. *
  2038. * Returns: NONE
  2039. *
  2040. * History: 8-4-92 Marklea - created
  2041. *
  2042. */
  2043. void WstSort (WSP wsp[], INT iLeft, INT iRight)
  2044. {
  2045. INT i, iLast;
  2046. if (iLeft >= iRight) {
  2047. return;
  2048. }
  2049. WstSwap(wsp, iLeft, (iLeft + iRight)/2);
  2050. iLast = iLeft;
  2051. for (i=iLeft+1; i <= iRight ; i++ ) {
  2052. if (WstCompare(&wsp[i], &wsp[iLeft]) < 0) {
  2053. if (!wsp[i].ulFuncAddr) {
  2054. SdPrint(("WST: WstSort() - Error in symbol list ulFuncAddr: "
  2055. "0x%lx [%d]\n", wsp[i].ulFuncAddr, i));
  2056. }
  2057. WstSwap(wsp, ++iLast, i);
  2058. }
  2059. }
  2060. WstSwap(wsp, iLeft, iLast);
  2061. WstSort(wsp, iLeft, iLast-1);
  2062. WstSort(wsp, iLast+1, iRight);
  2063. } /* WstSort () */
  2064. /*********************** W s t S w a p **************************************
  2065. *
  2066. * Function: WstSwap(WSP wsp[], INT i, INT j)
  2067. *
  2068. * Purpose: Helper function for WstSort to swap WSP array values
  2069. *
  2070. *
  2071. * Parameters: wsp[] Pointer to WSP array
  2072. * i index value to swap to
  2073. * i index value to swap from
  2074. *
  2075. * Returns: NONE
  2076. *
  2077. * History: 8-4-92 Marklea - created
  2078. *
  2079. */
  2080. void WstSwap (WSP wsp[], INT i, INT j)
  2081. {
  2082. WSP wspTmp;
  2083. wspTmp = wsp[i];
  2084. wsp[i] = wsp[j];
  2085. wsp[j] = wspTmp;
  2086. } /* WstSwap () */
  2087. /*********************** W s t B S e a r c h *******************************
  2088. *
  2089. * Function: WstBSearch(DWORD dwAddr, WSP wspCur[], INT n)
  2090. *
  2091. * Purpose: Binary search function for finding a match in the WSP array
  2092. *
  2093. *
  2094. * Parameters: dwAddr Address of calling function
  2095. * wspCur[]Pointer to WSP containg value to match with dwAddr
  2096. * n Number of elements in WSP array
  2097. *
  2098. * Returns: PWSP Pointer to matching WSP
  2099. *
  2100. * History: 8-5-92 Marklea - created
  2101. *
  2102. */
  2103. PWSP WstBSearch (DWORD_PTR dwAddr, WSP wspCur[], INT n)
  2104. {
  2105. int i;
  2106. ULONG ulHigh = n;
  2107. ULONG ulLow = 0;
  2108. ULONG ulMid;
  2109. while (ulLow < ulHigh) {
  2110. ulMid = ulLow + (ulHigh - ulLow) /2;
  2111. if ((i = WstBCompare(&dwAddr, &wspCur[ulMid])) < 0) {
  2112. ulHigh = ulMid;
  2113. } else if (i > 0) {
  2114. ulLow = ulMid + 1;
  2115. } else {
  2116. return (&wspCur[ulMid]);
  2117. }
  2118. }
  2119. return (NULL);
  2120. } /* WstBSearch () */
  2121. /************************** W s t D u m p t h r e a d ***********************
  2122. *
  2123. * WstDumpThread (pvArg) -
  2124. * This routine is executed as the DUMP notification thread.
  2125. * It will wait on an event before calling the dump routine.
  2126. *
  2127. * ENTRY pvArg - thread's single argument
  2128. *
  2129. * EXIT -none-
  2130. *
  2131. * RETURN 0
  2132. *
  2133. * WARNING:
  2134. * -none-
  2135. *
  2136. * COMMENT:
  2137. * Leaves profiling turned off.
  2138. *
  2139. */
  2140. #if _MSC_FULL_VER >= 13008827
  2141. #pragma warning(push)
  2142. #pragma warning(disable:4715) // Not all control paths return (due to infinite loop)
  2143. #endif
  2144. DWORD WstDumpThread (PVOID pvArg)
  2145. {
  2146. NTSTATUS Status;
  2147. int i;
  2148. pvArg; // prevent compiler warnings
  2149. SdPrint (("WST: WstDumpThread() started.. TEB=0x%lx\n", NtCurrentTeb()));
  2150. for (;;) {
  2151. //
  2152. // Wait for the DUMP event..
  2153. //
  2154. Status = NtWaitForSingleObject (hDumpEvent, FALSE, NULL);
  2155. if (!NT_SUCCESS(Status)) {
  2156. KdPrint (("WST: WstDumpThread() - "
  2157. "ERROR - Wait for DUMP event failed - 0x%lx\n", Status));
  2158. }
  2159. Status = NtResetEvent (hDoneEvent, NULL);
  2160. if (!NT_SUCCESS(Status)) {
  2161. KdPrint (("WST: WstDumpThread() - "
  2162. "ERROR - Resetting DONE event failed - 0x%lx\n", Status));
  2163. }
  2164. fInThread = TRUE;
  2165. (*pulShared)++;
  2166. if (WstState != NOT_STARTED) {
  2167. IdPrint (("WST: Profiling stopped & DUMPing data... \n"));
  2168. // Stop profiling
  2169. //
  2170. WstState = NOT_STARTED;
  2171. // Dump the data
  2172. //
  2173. if (ulBitCount != 0L) {
  2174. ulSnaps++;
  2175. }
  2176. //
  2177. // Get the GLOBAL semaphore.. (valid accross all process contexts)
  2178. //
  2179. Status = NtWaitForSingleObject (hGlobalSem, FALSE, NULL);
  2180. if (!NT_SUCCESS(Status)) {
  2181. KdPrint (("WST: WstDumpThread() - "
  2182. "ERROR - Wait for GLOBAL semaphore failed - 0x%lx\n",
  2183. Status));
  2184. }
  2185. for (i=0; i<iImgCnt; i++) {
  2186. if (aImg[i].iSymCnt > 1) { // Don't dump modules w/o symbols (the 1 is UNKNOWN) mdg 98/4
  2187. WstClearBitStrings (&aImg[i]);
  2188. WstRotateWsiMem (&aImg[i]);
  2189. WstDumpData (&aImg[i]);
  2190. WstWriteTmiFile (&aImg[i]);
  2191. }
  2192. }
  2193. //
  2194. // Release the GLOBAL semaphore so other processes can dump data
  2195. //
  2196. Status = NtReleaseSemaphore (hGlobalSem, 1, NULL);
  2197. if (!NT_SUCCESS(Status)) {
  2198. KdPrint (("WST: WstDumpThread() - "
  2199. "Error releasing GLOBAL semaphore - 0x%lx\n", Status));
  2200. }
  2201. IdPrint (("WST: ...data DUMPed & profiling stopped.\n"));
  2202. }
  2203. (*pulShared)--;
  2204. if ( *pulShared == 0L ) {
  2205. Status = NtSetEvent (hDoneEvent, NULL);
  2206. if (!NT_SUCCESS(Status)) {
  2207. KdPrint (("WST: WstDumpThread() - "
  2208. "ERROR - Setting DONE event failed - 0x%lx\n",
  2209. Status));
  2210. }
  2211. }
  2212. fInThread = FALSE;
  2213. }
  2214. return 0;
  2215. } /* WstDumpThread () */
  2216. /************************ W s t C l e a r T h r e a d ***********************
  2217. *
  2218. * WstClearThread (hNotifyEvent) -
  2219. * This routine is executed as the CLEAR notification thread.
  2220. * It will wait on an event before calling the clear routine
  2221. * and restarting profiling.
  2222. *
  2223. * ENTRY pvArg - thread's single argument
  2224. *
  2225. * EXIT -none-
  2226. *
  2227. * RETURN -none-
  2228. *
  2229. * WARNING:
  2230. * -none-
  2231. *
  2232. * COMMENT:
  2233. * -none-
  2234. *
  2235. */
  2236. DWORD WstClearThread (PVOID pvArg)
  2237. {
  2238. NTSTATUS Status;
  2239. int i;
  2240. pvArg; // prevent compiler warnings
  2241. SdPrint (("WST: WstClearThread() started.. TEB=0x%lx\n", NtCurrentTeb()));
  2242. for (;;) {
  2243. //
  2244. // Wait for the CLEAR event..
  2245. //
  2246. Status = NtWaitForSingleObject (hClearEvent, FALSE, NULL);
  2247. if (!NT_SUCCESS(Status)) {
  2248. KdPrint (("WST: WstClearThread() - "
  2249. "Wait for CLEAR event failed - 0x%lx\n", Status));
  2250. }
  2251. Status = NtResetEvent (hDoneEvent, NULL);
  2252. if (!NT_SUCCESS(Status)) {
  2253. KdPrint (("WST: WstClearThread() - "
  2254. "ERROR - Resetting DONE event failed - 0x%lx\n", Status));
  2255. }
  2256. fInThread = TRUE;
  2257. (*pulShared)++;
  2258. IdPrint (("WST: Profiling stopped & CLEARing data...\n"));
  2259. // Stop profiling while clearing data
  2260. //
  2261. WstState = STOPPED;
  2262. // Clear WST info
  2263. //
  2264. ulBitCount = 0L;
  2265. ulSnaps = 0L;
  2266. for (i=0; i<iImgCnt; i++) {
  2267. aImg[i].pulWsiNxt = aImg[i].pulWsi;
  2268. RtlZeroMemory (aImg[i].pulWsi,
  2269. aImg[i].iSymCnt * ulMaxSnapULONGs * sizeof(ULONG));
  2270. RtlZeroMemory (aImg[i].pulWsp,
  2271. aImg[i].iSymCnt * ulMaxSnapULONGs * sizeof(ULONG));
  2272. }
  2273. NtQueryPerformanceCounter (&liStart, NULL);
  2274. // Resume profiling
  2275. //
  2276. WstState = STARTED;
  2277. IdPrint (("WST: ...data is CLEARed & profiling restarted.\n"));
  2278. (*pulShared)--;
  2279. if ( *pulShared == 0L ) {
  2280. Status = NtSetEvent (hDoneEvent, NULL);
  2281. if (!NT_SUCCESS(Status)) {
  2282. KdPrint (("WST: WstClearThread() - "
  2283. "ERROR - Setting DONE event failed - 0x%lx\n",
  2284. Status));
  2285. }
  2286. }
  2287. fInThread = FALSE;
  2288. }
  2289. return 0;
  2290. } /* WstClearThread () */
  2291. /************************ W s t P a u s e T h r e a d ***********************
  2292. *
  2293. * WstPauseThread (hNotifyEvent) -
  2294. * This routine is executed as the PAUSE notification thread.
  2295. * It will wait on an event before pausing the profiling.
  2296. *
  2297. * ENTRY pvArg - thread's single argument
  2298. *
  2299. * EXIT -none-
  2300. *
  2301. * RETURN -none-
  2302. *
  2303. * WARNING:
  2304. * -none-
  2305. *
  2306. * COMMENT:
  2307. * -none-
  2308. *
  2309. */
  2310. DWORD WstPauseThread (PVOID pvArg)
  2311. {
  2312. NTSTATUS Status;
  2313. pvArg; // prevent compiler warnings
  2314. SdPrint (("WST: WstPauseThread() started.. TEB=0x%lx\n", NtCurrentTeb()));
  2315. for (;;) {
  2316. //
  2317. // Wait for the PASUE event..
  2318. //
  2319. Status = NtWaitForSingleObject (hPauseEvent, FALSE, NULL);
  2320. if (!NT_SUCCESS(Status)) {
  2321. KdPrint (("WST: WstPauseThread() - "
  2322. "Wait for PAUSE event failed - 0x%lx\n", Status));
  2323. }
  2324. Status = NtResetEvent (hDoneEvent, NULL);
  2325. if (!NT_SUCCESS(Status)) {
  2326. KdPrint (("WST: WstPauseThread() - "
  2327. "ERROR - Resetting DONE event failed - 0x%lx\n", Status));
  2328. }
  2329. fInThread = TRUE;
  2330. (*pulShared)++;
  2331. if (WstState == STARTED) {
  2332. //
  2333. // Stop profiling
  2334. //
  2335. WstState = STOPPED;
  2336. IdPrint (("WST: Profiling stopped.\n"));
  2337. }
  2338. (*pulShared)--;
  2339. if ( *pulShared == 0L ) {
  2340. Status = NtSetEvent (hDoneEvent, NULL);
  2341. if (!NT_SUCCESS(Status)) {
  2342. KdPrint (("WST: WstPauseThread() - "
  2343. "ERROR - Setting DONE event failed - 0x%lx\n",
  2344. Status));
  2345. }
  2346. }
  2347. fInThread = FALSE;
  2348. }
  2349. return 0;
  2350. } /* WstPauseThread () */
  2351. #if _MSC_FULL_VER >= 13008827
  2352. #pragma warning(pop)
  2353. #endif
  2354. /*********************** W s t D a t a O v e r F l o w **********************
  2355. *
  2356. * WstDataOverFlow () -
  2357. * This routine is called upon lack of space for storing next
  2358. * time snap data. It dumps and then clears the WST data.
  2359. *
  2360. * ENTRY -none-
  2361. *
  2362. * EXIT -none-
  2363. *
  2364. * RETURN -none-
  2365. *
  2366. * WARNING:
  2367. * -none-
  2368. *
  2369. * COMMENT:
  2370. * -none-
  2371. *
  2372. */
  2373. void WstDataOverFlow(void)
  2374. {
  2375. NTSTATUS Status;
  2376. //
  2377. // Dump data
  2378. //
  2379. Status = NtResetEvent (hDoneEvent, NULL);
  2380. if (!NT_SUCCESS(Status)) {
  2381. KdPrint (("WST: WstDataOverFlow() - "
  2382. "ERROR - Resetting DONE event failed - 0x%lx\n", Status));
  2383. }
  2384. Status = NtPulseEvent (hDumpEvent, NULL);
  2385. if (!NT_SUCCESS(Status)) {
  2386. KdPrint (("WST: WstDataOverFlow() - NtPulseEvent() "
  2387. "failed for DUMP event - %lx\n", Status));
  2388. }
  2389. Status = NtWaitForSingleObject (hDoneEvent, FALSE, NULL);
  2390. if (!NT_SUCCESS(Status)) {
  2391. KdPrint (("WST: WstDataOverFlow() - NtWaitForSingleObject() "
  2392. "failed for DONE event - %lx\n", Status));
  2393. }
  2394. //
  2395. // Clear data
  2396. //
  2397. Status = NtResetEvent (hDoneEvent, NULL);
  2398. if (!NT_SUCCESS(Status)) {
  2399. KdPrint (("WST: WstDataOverFlow() - "
  2400. "ERROR - Resetting DONE event failed - 0x%lx\n", Status));
  2401. }
  2402. Status = NtPulseEvent (hClearEvent, NULL);
  2403. if (!NT_SUCCESS(Status)) {
  2404. KdPrint (("WST: WstDataOverFlow() - NtPulseEvent() "
  2405. "failed for CLEAR event - %lx\n", Status));
  2406. }
  2407. //
  2408. // Wait for the DONE event..
  2409. //
  2410. Status = NtWaitForSingleObject (hDoneEvent, FALSE, NULL);
  2411. if (!NT_SUCCESS(Status)) {
  2412. KdPrint (("WST: WstDataOverFlow() - NtWaitForSingleObject() "
  2413. "failed for DONE event - %lx\n", Status));
  2414. }
  2415. } /* WstDataOverFlow() */
  2416. #ifdef BATCHING
  2417. BOOL WstOpenBatchFile(VOID)
  2418. {
  2419. NTSTATUS Status;
  2420. ANSI_STRING ObjName;
  2421. UNICODE_STRING UnicodeName;
  2422. OBJECT_ATTRIBUTES ObjAttributes;
  2423. IO_STATUS_BLOCK iostatus;
  2424. RtlInitString(&ObjName, "\\Device\\Harddisk0\\Partition1\\wst\\BATCH.TXT");
  2425. Status = RtlAnsiStringToUnicodeString(&UnicodeName, &ObjName, TRUE);
  2426. if (!NT_SUCCESS(Status)) {
  2427. KdPrint (("WST: WstOpenBatchFile() - "
  2428. "RtlAnsiStringToUnicodeString() failed - 0x%lx\n", Status));
  2429. return (FALSE);
  2430. }
  2431. InitializeObjectAttributes (&ObjAttributes,
  2432. &UnicodeName,
  2433. OBJ_CASE_INSENSITIVE,
  2434. NULL,
  2435. &SecDescriptor);
  2436. Status = NtCreateFile(&hBatchFile,
  2437. GENERIC_WRITE | SYNCHRONIZE, // Desired access
  2438. &ObjAttributes, // Object attributes
  2439. &iostatus, // Completion status
  2440. NULL,
  2441. FILE_ATTRIBUTE_NORMAL,
  2442. FILE_SHARE_WRITE,
  2443. FILE_OVERWRITE_IF,
  2444. FILE_SEQUENTIAL_ONLY | // Open option
  2445. FILE_SYNCHRONOUS_IO_NONALERT,
  2446. NULL,
  2447. 0L);
  2448. RtlFreeUnicodeString (&UnicodeName); // HWC 11/93
  2449. if (!NT_SUCCESS(Status)) {
  2450. KdPrint (("WST: WstOpenBatchFile() - "
  2451. "NtCreateFile() failed - 0x%lx\n", Status));
  2452. return (FALSE);
  2453. }
  2454. return(TRUE);
  2455. } /* WstOpenBatchFile () */
  2456. #endif
  2457. /******************* S e t S y m b o l S e a r c h P a t h ******************
  2458. *
  2459. * SetSymbolSearchPath ()
  2460. * Return complete search path for symbols files (.dbg)
  2461. *
  2462. * ENTRY -none-
  2463. *
  2464. * EXIT -none-
  2465. *
  2466. * RETURN -none-
  2467. *
  2468. * WARNING:
  2469. * -none-
  2470. *
  2471. * COMMENT:
  2472. * "lpSymbolSearchPath" global LPSTR variable will point to the
  2473. * search path.
  2474. */
  2475. #define FilePathLen 256
  2476. void SetSymbolSearchPath (void)
  2477. {
  2478. CHAR SymPath[FilePathLen];
  2479. CHAR AltSymPath[FilePathLen];
  2480. CHAR SysRootPath[FilePathLen];
  2481. LPSTR lpSymPathEnv=SymPath;
  2482. LPSTR lpAltSymPathEnv=AltSymPath;
  2483. LPSTR lpSystemRootEnv=SysRootPath;
  2484. ULONG cbSymPath;
  2485. DWORD dw;
  2486. HANDLE hMemoryHandle;
  2487. SymPath[0] = AltSymPath[0] = SysRootPath[0] = '\0';
  2488. cbSymPath = 18;
  2489. if (GetEnvironmentVariable("_NT_SYMBOL_PATH", SymPath, sizeof(SymPath))) {
  2490. cbSymPath += strlen(lpSymPathEnv) + 1;
  2491. }
  2492. if (GetEnvironmentVariable("_NT_ALT_SYMBOL_PATH", AltSymPath, sizeof(AltSymPath))) {
  2493. cbSymPath += strlen(lpAltSymPathEnv) + 1;
  2494. }
  2495. if (GetEnvironmentVariable("SystemRoot", SysRootPath, sizeof(SysRootPath))) {
  2496. cbSymPath += strlen(lpSystemRootEnv) + 1;
  2497. }
  2498. hMemoryHandle = GlobalAlloc (GHND, cbSymPath+1);
  2499. if (!hMemoryHandle) {
  2500. return;
  2501. }
  2502. lpSymbolSearchPath = GlobalLock (hMemoryHandle);
  2503. if (!lpSymbolSearchPath) {
  2504. GlobalFree( hMemoryHandle ); // mdg 98/3
  2505. return;
  2506. }
  2507. strcat(lpSymbolSearchPath,".");
  2508. if (*lpAltSymPathEnv) {
  2509. dw = GetFileAttributes(lpAltSymPathEnv);
  2510. if ( dw != 0xffffffff && dw & FILE_ATTRIBUTE_DIRECTORY ) {
  2511. strcat(lpSymbolSearchPath,";");
  2512. strcat(lpSymbolSearchPath,lpAltSymPathEnv);
  2513. }
  2514. }
  2515. if (*lpSymPathEnv) {
  2516. dw = GetFileAttributes(lpSymPathEnv);
  2517. if ( dw != 0xffffffff && dw & FILE_ATTRIBUTE_DIRECTORY ) {
  2518. strcat(lpSymbolSearchPath,";");
  2519. strcat(lpSymbolSearchPath,lpSymPathEnv);
  2520. }
  2521. }
  2522. if (*lpSystemRootEnv) {
  2523. dw = GetFileAttributes(lpSystemRootEnv);
  2524. if ( dw != 0xffffffff && dw & FILE_ATTRIBUTE_DIRECTORY ) {
  2525. strcat(lpSymbolSearchPath,";");
  2526. strcat(lpSymbolSearchPath,lpSystemRootEnv);
  2527. }
  2528. }
  2529. } /* SetSymbolSearchPath () */
  2530. #ifdef i386
  2531. //+-------------------------------------------------------------------------
  2532. //
  2533. // Function: SaveAllRegs
  2534. //
  2535. // Synopsis: Save all regs.
  2536. //
  2537. // Arguments: nothing
  2538. //
  2539. // Returns: none
  2540. //
  2541. //--------------------------------------------------------------------------
  2542. Naked void SaveAllRegs(void)
  2543. {
  2544. _asm
  2545. {
  2546. push ebp
  2547. mov ebp,esp ; Remember where we are during this stuff
  2548. ; ebp = Original esp - 4
  2549. push eax ; Save all regs that we think we might
  2550. push ebx ; destroy
  2551. push ecx
  2552. push edx
  2553. push esi
  2554. push edi
  2555. pushfd
  2556. push ds
  2557. push es
  2558. push ss
  2559. push fs
  2560. push gs
  2561. mov eax,[ebp+4] ; Grab Return Address
  2562. push eax ; Put Return Address on Stack so we can RET
  2563. mov ebp,[ebp+0] ; Restore original ebp
  2564. //
  2565. // This is how the stack looks like before the RET statement
  2566. //
  2567. // +-----------+
  2568. // | Ret Addr | + 3ch CurrentEBP + 4
  2569. // +-----------+
  2570. // | Org ebp | + 38h CurrentEBP + 0
  2571. // +-----------+
  2572. // | eax | + 34h
  2573. // +-----------+
  2574. // | ebx | + 30h
  2575. // +-----------+
  2576. // | ecx | + 2ch
  2577. // +-----------+
  2578. // | edx | + 24h
  2579. // +-----------+
  2580. // | esi | + 20h
  2581. // +-----------+
  2582. // | edi | + 1ch
  2583. // +-----------+
  2584. // | eflags | + 18h
  2585. // +-----------+
  2586. // | ds | + 14h
  2587. // +-----------+
  2588. // | es | + 10h
  2589. // +-----------+
  2590. // | ss | + ch
  2591. // +-----------+
  2592. // | fs | + 8h
  2593. // +-----------+
  2594. // | gs | + 4h
  2595. // +-----------+
  2596. // | Ret Addr | ESP + 0h
  2597. // +-----------+
  2598. ret
  2599. }
  2600. }
  2601. //+-------------------------------------------------------------------------
  2602. //
  2603. // Function: RestoreAllRegs
  2604. //
  2605. // Synopsis: restore all regs
  2606. //
  2607. // Arguments: nothing
  2608. //
  2609. // Returns: none
  2610. //
  2611. //--------------------------------------------------------------------------
  2612. Naked void RestoreAllRegs(void)
  2613. {
  2614. _asm
  2615. {
  2616. //
  2617. // This is how the stack looks like upon entering this routine
  2618. //
  2619. // +-----------+
  2620. // | Ret Addr | + 38h [ RetAddr for SaveAllRegs() ]
  2621. // +-----------+
  2622. // | Org ebp | + 34h
  2623. // +-----------+
  2624. // | eax | + 30h
  2625. // +-----------+
  2626. // | ebx | + 2Ch
  2627. // +-----------+
  2628. // | ecx | + 28h
  2629. // +-----------+
  2630. // | edx | + 24h
  2631. // +-----------+
  2632. // | esi | + 20h
  2633. // +-----------+
  2634. // | edi | + 1Ch
  2635. // +-----------+
  2636. // | eflags | + 18h
  2637. // +-----------+
  2638. // | ds | + 14h
  2639. // +-----------+
  2640. // | es | + 10h
  2641. // +-----------+
  2642. // | ss | + Ch
  2643. // +-----------+
  2644. // | fs | + 8h
  2645. // +-----------+
  2646. // | gs | + 4h
  2647. // +-----------+
  2648. // | Ret EIP | ESP + 0h [ RetAddr for RestoreAllRegs() ]
  2649. // +-----------+
  2650. //
  2651. push ebp ; Save a temporary copy of original BP
  2652. mov ebp,esp ; BP = Original SP + 4
  2653. //
  2654. // This is how the stack looks like NOW!
  2655. //
  2656. // +-----------+
  2657. // | Ret Addr | + 3Ch [ RetAddr for SaveAllRegs() ]
  2658. // +-----------+
  2659. // | Org ebp | + 38h [ EBP before SaveAllRegs() ]
  2660. // +-----------+
  2661. // | eax | + 34h
  2662. // +-----------+
  2663. // | ebx | + 30h
  2664. // +-----------+
  2665. // | ecx | + 2Ch
  2666. // +-----------+
  2667. // | edx | + 28h
  2668. // +-----------+
  2669. // | esi | + 24h
  2670. // +-----------+
  2671. // | edi | + 20h
  2672. // +-----------+
  2673. // | eflags | + 1Ch
  2674. // +-----------+
  2675. // | ds | + 18h
  2676. // +-----------+
  2677. // | es | + 14h
  2678. // +-----------+
  2679. // | ss | + 10h
  2680. // +-----------+
  2681. // | fs | + Ch
  2682. // +-----------+
  2683. // | gs | + 8h
  2684. // +-----------+
  2685. // | Ret EIP | ESP + 4h [ RetAddr for RestoreAllRegs() ]
  2686. // +-----------+
  2687. // | EBP | ESP + 0h or EBP + 0h
  2688. // +-----------+
  2689. //
  2690. pop eax ; Get Original EBP
  2691. mov [ebp+38h],eax ; Put it in the original EBP place
  2692. ; This EBP is the EBP before calling
  2693. ; RestoreAllRegs()
  2694. pop eax ; Get ret address forRestoreAllRegs ()
  2695. mov [ebp+3Ch],eax ; Put Return Address on Stack
  2696. pop gs ; Restore all regs
  2697. pop fs
  2698. pop ss
  2699. pop es
  2700. pop ds
  2701. popfd
  2702. pop edi
  2703. pop esi
  2704. pop edx
  2705. pop ecx
  2706. pop ebx
  2707. pop eax
  2708. pop ebp
  2709. ret
  2710. }
  2711. }
  2712. #endif