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.

818 lines
19 KiB

  1. #include <windows.h>
  2. #include <stdio.h>
  3. #include "view.h"
  4. #include "except.h"
  5. #include "disasm.h"
  6. #include "dump.h"
  7. #include "profiler.h"
  8. #include "memory.h"
  9. #include "filter.h"
  10. static PVIEWCHAIN *ppViewHead = 0;
  11. static CRITICAL_SECTION viewCritSec;
  12. static CRITICAL_SECTION mapCritSec;
  13. static PTAGGEDADDRESS pTagHead = 0;
  14. static PBRANCHADDRESS pBranchHead = 0;
  15. BOOL
  16. InitializeViewData(VOID)
  17. {
  18. InitializeCriticalSection(&viewCritSec);
  19. InitializeCriticalSection(&mapCritSec);
  20. //
  21. // Allocate hashing data
  22. //
  23. ppViewHead = (PVIEWCHAIN *)AllocMem(sizeof(PVIEWCHAIN) * (MAX_MAP_SIZE >> MAP_STRIDE_BITS));
  24. if (0 == ppViewHead) {
  25. return FALSE;
  26. }
  27. return TRUE;
  28. }
  29. PVIEWCHAIN
  30. AddViewToMonitor(DWORD dwAddress,
  31. BPType bpType)
  32. {
  33. PVIEWCHAIN pView;
  34. DWORD dwHash;
  35. //
  36. // If address is higher than the map size, fail it
  37. //
  38. if (dwAddress >= MAX_MAP_SIZE) {
  39. return 0;
  40. }
  41. //
  42. // This occurs when a call tries to map over an existing trace breakpoint
  43. //
  44. if (*(BYTE *)dwAddress == X86_BREAKPOINT) {
  45. return 0;
  46. }
  47. //
  48. // Check if we're filtering this address
  49. //
  50. if (TRUE == IsAddressFiltered(dwAddress)) {
  51. return 0;
  52. }
  53. //
  54. // Allocate a chain entry
  55. //
  56. pView = AllocMem(sizeof(VIEWCHAIN));
  57. if (0 == pView) {
  58. return 0;
  59. }
  60. pView->bMapped = FALSE;
  61. pView->bTraced = FALSE;
  62. pView->dwAddress = dwAddress;
  63. pView->dwMapExtreme = dwAddress;
  64. pView->jByteReplaced = *(BYTE *)dwAddress;
  65. pView->bpType = bpType;
  66. //
  67. // Set a breakpoint at the top of the code
  68. //
  69. WRITEBYTE(dwAddress, X86_BREAKPOINT);
  70. EnterCriticalSection(&viewCritSec);
  71. //
  72. // Add view point to monitor list
  73. //
  74. dwHash = dwAddress >> MAP_STRIDE_BITS;
  75. if (0 == ppViewHead[dwHash]) {
  76. ppViewHead[dwHash] = pView;
  77. }
  78. else {
  79. //
  80. // Chain to head
  81. //
  82. pView->pNext = ppViewHead[dwHash];
  83. ppViewHead[dwHash] = pView;
  84. }
  85. LeaveCriticalSection(&viewCritSec);
  86. return pView;
  87. }
  88. PVIEWCHAIN
  89. RestoreAddressFromView(DWORD dwAddress,
  90. BOOL bResetData)
  91. {
  92. BOOL bResult = FALSE;
  93. PVIEWCHAIN pTemp;
  94. EnterCriticalSection(&viewCritSec);
  95. pTemp = ppViewHead[dwAddress >> MAP_STRIDE_BITS];
  96. while (pTemp) {
  97. //
  98. // Is this our entry
  99. //
  100. if (dwAddress == pTemp->dwAddress) {
  101. //
  102. // Set a breakpoint at the top of the code
  103. //
  104. if (TRUE == bResetData) {
  105. WRITEBYTE(dwAddress, pTemp->jByteReplaced);
  106. }
  107. else {
  108. WRITEBYTE(dwAddress, X86_BREAKPOINT);
  109. }
  110. //
  111. // Return with modified data
  112. //
  113. break;
  114. }
  115. pTemp = pTemp->pNext;
  116. }
  117. LeaveCriticalSection(&viewCritSec);
  118. return pTemp;
  119. }
  120. PVIEWCHAIN
  121. FindView(DWORD dwAddress) {
  122. PVIEWCHAIN pTemp;
  123. if (dwAddress >= MAX_MAP_SIZE) {
  124. return 0;
  125. }
  126. EnterCriticalSection(&viewCritSec);
  127. pTemp = ppViewHead[dwAddress >> MAP_STRIDE_BITS];
  128. while (pTemp) {
  129. //
  130. // See if address is mapped
  131. //
  132. if (dwAddress == pTemp->dwAddress) {
  133. LeaveCriticalSection(&viewCritSec);
  134. return pTemp;
  135. }
  136. pTemp = pTemp->pNext;
  137. }
  138. LeaveCriticalSection(&viewCritSec);
  139. return 0;
  140. }
  141. BOOL
  142. MapCode(PVIEWCHAIN pvMap) {
  143. BOOL bResult;
  144. DWORD dwCurrent;
  145. DWORD *pdwAddress;
  146. DWORD *pdwTemp;
  147. PCHAR pCode;
  148. PVIEWCHAIN pvTemp;
  149. DWORD dwLength;
  150. DWORD dwJumpEIP;
  151. LONG lOffset;
  152. DWORD dwInsLength;
  153. DWORD dwTemp;
  154. BYTE tempCode[32];
  155. BYTE jOperand;
  156. DWORD dwProfileEnd = 0;
  157. CHAR szBuffer[MAX_PATH];
  158. //
  159. // Map termination through all conditionals
  160. //
  161. dwCurrent = pvMap->dwAddress;
  162. //
  163. // Take the mapping lock
  164. //
  165. LockMapper();
  166. //
  167. // Forward scan through code to find termination
  168. //
  169. while(1) {
  170. strncpy(tempCode, (PCHAR)dwCurrent, 32);
  171. //
  172. // Make sure the instruction is unmodified
  173. //
  174. if (tempCode[0] == (BYTE)X86_BREAKPOINT) {
  175. //
  176. // Rebuild instruction without breakpoints
  177. //
  178. pvTemp = FindView(dwCurrent);
  179. if (pvTemp) {
  180. //
  181. // Replace the bytes if we have a match
  182. //
  183. tempCode[0] = pvTemp->jByteReplaced;
  184. }
  185. }
  186. //
  187. // Calculate instruction length
  188. //
  189. dwInsLength = GetInstructionLengthFromAddress((PVOID)tempCode);
  190. //
  191. // Follow a forward trace through jumps to the ret
  192. //
  193. if ((tempCode[0] >= (BYTE)0x70) && (tempCode[0] <= (BYTE)0x7f)) {
  194. //
  195. // Update the end of the region marker
  196. //
  197. if (dwCurrent > dwProfileEnd) {
  198. dwProfileEnd = dwCurrent;
  199. }
  200. //
  201. // Relative branch
  202. //
  203. dwJumpEIP = (dwCurrent + 2 + (CHAR)(tempCode[1]));
  204. //
  205. // Mark this branch as executed
  206. //
  207. bResult = AddTaggedAddress(dwCurrent);
  208. if (FALSE == bResult) {
  209. return FALSE;
  210. }
  211. if (dwJumpEIP > dwCurrent) {
  212. //
  213. // Push the opposite branch
  214. //
  215. bResult = PushBranch(dwCurrent + dwInsLength);
  216. if (FALSE == bResult) {
  217. return FALSE;
  218. }
  219. dwCurrent = dwJumpEIP;
  220. }
  221. else {
  222. //
  223. // Push the opposite branch
  224. //
  225. bResult = PushBranch(dwJumpEIP);
  226. if (FALSE == bResult) {
  227. return FALSE;
  228. }
  229. dwCurrent += dwInsLength;
  230. }
  231. continue;
  232. }
  233. if (tempCode[0] == (BYTE)0x0f) {
  234. if ((tempCode[1] >= (BYTE)0x80) && (tempCode[1] <= (BYTE)0x8f)) {
  235. //
  236. // Update the end of the region marker
  237. //
  238. if (dwCurrent > dwProfileEnd) {
  239. dwProfileEnd = dwCurrent;
  240. }
  241. //
  242. // Relative branch
  243. //
  244. dwJumpEIP = (dwCurrent + 6 + *(LONG *)(&(tempCode[2])));
  245. //
  246. // Mark this branch as executed
  247. //
  248. bResult = AddTaggedAddress(dwCurrent);
  249. if (FALSE == bResult) {
  250. return FALSE;
  251. }
  252. if (dwJumpEIP > dwCurrent) {
  253. //
  254. // Push the opposite branch
  255. //
  256. bResult = PushBranch(dwCurrent + dwInsLength);
  257. if (FALSE == bResult) {
  258. return FALSE;
  259. }
  260. dwCurrent = dwJumpEIP;
  261. }
  262. else {
  263. //
  264. // Push the opposite branch
  265. //
  266. bResult = PushBranch(dwJumpEIP);
  267. if (FALSE == bResult) {
  268. return FALSE;
  269. }
  270. dwCurrent += dwInsLength;
  271. }
  272. continue;
  273. }
  274. }
  275. if (tempCode[0] == (BYTE)0xe3) {
  276. //
  277. // Update the end of the region marker
  278. //
  279. if (dwCurrent > dwProfileEnd) {
  280. dwProfileEnd = dwCurrent;
  281. }
  282. //
  283. // Relative branch
  284. //
  285. dwJumpEIP = (dwCurrent + 2 + (CHAR)(tempCode[1]));
  286. //
  287. // Mark this branch as executed
  288. //
  289. bResult = AddTaggedAddress(dwCurrent);
  290. if (FALSE == bResult) {
  291. return FALSE;
  292. }
  293. if (dwJumpEIP > dwCurrent) {
  294. //
  295. // Push the opposite branch
  296. //
  297. bResult = PushBranch(dwCurrent + dwInsLength);
  298. if (FALSE == bResult) {
  299. return FALSE;
  300. }
  301. dwCurrent = dwJumpEIP;
  302. }
  303. else {
  304. //
  305. // Push the opposite branch
  306. //
  307. bResult = PushBranch(dwJumpEIP);
  308. if (FALSE == bResult) {
  309. return FALSE;
  310. }
  311. dwCurrent += dwInsLength;
  312. }
  313. continue;
  314. }
  315. if (tempCode[0] == (BYTE)0xeb) {
  316. //
  317. // Update the end of the region marker
  318. //
  319. if (dwCurrent > dwProfileEnd) {
  320. dwProfileEnd = dwCurrent;
  321. }
  322. //
  323. // Jump relative
  324. //
  325. dwJumpEIP = (dwCurrent + 2 + (CHAR)(tempCode[1]));
  326. //
  327. // Mark this branch as executed
  328. //
  329. bResult = AddTaggedAddress(dwCurrent);
  330. if (FALSE == bResult) {
  331. return FALSE;
  332. }
  333. //
  334. // Jmp must always be followed
  335. //
  336. dwCurrent = dwJumpEIP;
  337. continue;
  338. }
  339. if (tempCode[0] == (BYTE)0xe9) {
  340. //
  341. // Update the end of the region marker
  342. //
  343. if (dwCurrent > dwProfileEnd) {
  344. dwProfileEnd = dwCurrent;
  345. }
  346. //
  347. // Jump relative
  348. //
  349. dwJumpEIP = (dwCurrent + 5 + *(LONG *)(&(tempCode[1])));
  350. //
  351. // Mark this branch as executed
  352. //
  353. bResult = AddTaggedAddress(dwCurrent);
  354. if (FALSE == bResult) {
  355. return FALSE;
  356. }
  357. //
  358. // Jump must always be followed
  359. //
  360. dwCurrent = dwJumpEIP;
  361. continue;
  362. }
  363. //
  364. // Probe for calls and jumps
  365. //
  366. if (tempCode[0] == (BYTE)0xff) {
  367. //
  368. // Tests for whether this is a call or not
  369. //
  370. jOperand = (tempCode[1] >> 3) & 7;
  371. if ((jOperand == 2) ||
  372. (jOperand == 3) ||
  373. (jOperand == 4) ||
  374. (jOperand == 5)) {
  375. //
  376. // Update the end of the region marker
  377. //
  378. if (dwCurrent > dwProfileEnd) {
  379. dwProfileEnd = dwCurrent;
  380. }
  381. //
  382. // Add our mapping breakpoint with the appropriate type
  383. //
  384. if ((jOperand == 2) ||
  385. (jOperand == 3)) {
  386. pvTemp = AddViewToMonitor(dwCurrent,
  387. Call);
  388. if (pvTemp) {
  389. pvTemp->bMapped = TRUE;
  390. }
  391. }
  392. else {
  393. //
  394. // These kinds of jumps are always a break (there's no way to forward trace them)
  395. //
  396. pvTemp = AddViewToMonitor(dwCurrent,
  397. Jump);
  398. if (pvTemp) {
  399. pvTemp->bMapped = TRUE;
  400. }
  401. else {
  402. //
  403. // Special case for mapping breakpoints which really are just jumps
  404. //
  405. pvTemp = FindView(dwCurrent);
  406. if (pvTemp) {
  407. pvTemp->bMapped = TRUE;
  408. pvTemp->bpType = Jump;
  409. }
  410. }
  411. //
  412. // Mark this branch as executed
  413. //
  414. bResult = AddTaggedAddress(dwCurrent);
  415. if (FALSE == bResult) {
  416. return FALSE;
  417. }
  418. //
  419. // Dump the tree
  420. //
  421. dwTemp = PopBranch();
  422. if (dwTemp) {
  423. dwCurrent = dwTemp;
  424. continue;
  425. }
  426. break;
  427. }
  428. }
  429. }
  430. if (tempCode[0] == (BYTE)0xe8) {
  431. //
  432. // Update the end of the region marker
  433. //
  434. if (dwCurrent > dwProfileEnd) {
  435. dwProfileEnd = dwCurrent;
  436. }
  437. //
  438. // Add this top call to the view
  439. //
  440. pvTemp = AddViewToMonitor(dwCurrent,
  441. Call);
  442. if (pvTemp) {
  443. pvTemp->bMapped = TRUE;
  444. }
  445. }
  446. if (tempCode[0] == (BYTE)0x9a) {
  447. //
  448. // Update the end of the region marker
  449. //
  450. if (dwCurrent > dwProfileEnd) {
  451. dwProfileEnd = dwCurrent;
  452. }
  453. //
  454. // Add this top call to the view
  455. //
  456. pvTemp = AddViewToMonitor(dwCurrent,
  457. Call);
  458. if (pvTemp) {
  459. pvTemp->bMapped = TRUE;
  460. }
  461. }
  462. if (tempCode[0] == (BYTE)0xea) {
  463. //
  464. // Update the end of the region marker
  465. //
  466. if (dwCurrent > dwProfileEnd) {
  467. dwProfileEnd = dwCurrent;
  468. }
  469. //
  470. // Absolute far jumps are a terminating condition - flush all branches
  471. //
  472. pvTemp = AddViewToMonitor(dwCurrent,
  473. Jump);
  474. if (pvTemp) {
  475. pvTemp->bMapped = TRUE;
  476. }
  477. //
  478. // Mark this branch as executed
  479. //
  480. bResult = AddTaggedAddress(dwCurrent);
  481. if (FALSE == bResult) {
  482. return FALSE;
  483. }
  484. //
  485. // Dump the tree
  486. //
  487. dwTemp = PopBranch();
  488. if (dwTemp) {
  489. dwCurrent = dwTemp;
  490. continue;
  491. }
  492. break;
  493. }
  494. if (*(WORD *)(&(tempCode[0])) == 0xffff) {
  495. //
  496. // Update the end of the region marker
  497. //
  498. if (dwCurrent > dwProfileEnd) {
  499. dwProfileEnd = dwCurrent;
  500. }
  501. //
  502. // This is also a trace path terminator - see if we need to trace more conditions
  503. //
  504. dwTemp = PopBranch();
  505. if (dwTemp) {
  506. //
  507. // We have a branch to follow
  508. //
  509. dwCurrent = dwTemp;
  510. continue;
  511. }
  512. //
  513. // Update the end of the address range
  514. //
  515. break;
  516. }
  517. if (tempCode[0] == (BYTE)0xc3) {
  518. //
  519. // This is also a trace path terminator - see if we need to trace more conditions
  520. //
  521. if (dwCurrent > dwProfileEnd) {
  522. dwProfileEnd = dwCurrent;
  523. }
  524. dwTemp = PopBranch();
  525. if (dwTemp) {
  526. //
  527. // We have a branch to follow
  528. //
  529. dwCurrent = dwTemp;
  530. continue;
  531. }
  532. break;
  533. }
  534. if (tempCode[0] == (BYTE)0xc2) {
  535. //
  536. // This is also a trace path terminator - see if we need to trace more conditions
  537. //
  538. if (dwCurrent > dwProfileEnd) {
  539. dwProfileEnd = dwCurrent;
  540. }
  541. dwTemp = PopBranch();
  542. if (dwTemp) {
  543. //
  544. // We have a branch to follow
  545. //
  546. dwCurrent = dwTemp;
  547. continue;
  548. }
  549. break;
  550. }
  551. dwCurrent += dwInsLength;
  552. }
  553. if (dwProfileEnd) {
  554. pvMap->dwMapExtreme = dwProfileEnd;
  555. }
  556. else {
  557. pvMap->dwMapExtreme = dwCurrent;
  558. }
  559. bResult = WriteMapInfo(pvMap->dwAddress,
  560. pvMap->dwMapExtreme);
  561. if (!bResult) {
  562. return FALSE;
  563. }
  564. //
  565. // Restore the code we've whacked around
  566. //
  567. bResult = RestoreTaggedAddresses();
  568. if (FALSE == bResult) {
  569. return FALSE;
  570. }
  571. //
  572. // Assert if this _ever_ happens
  573. //
  574. if (pBranchHead != 0) {
  575. Sleep(20000);
  576. _asm int 3
  577. }
  578. //
  579. // We're mapped
  580. //
  581. pvMap->bMapped = TRUE;
  582. //
  583. // Release the mapping lock
  584. //
  585. UnlockMapper();
  586. return TRUE;
  587. }
  588. //
  589. // Trace helpers
  590. //
  591. BOOL
  592. AddTaggedAddress(DWORD dwAddress)
  593. {
  594. PTAGGEDADDRESS pTagTemp;
  595. DWORD dwTempAddress;
  596. //
  597. // Make sure we haven't addressed this tag
  598. //
  599. if (*(WORD *)dwAddress == 0xFFFF) {
  600. //
  601. // No need since it's already tagged
  602. //
  603. return TRUE;
  604. }
  605. //
  606. // Store off the bytes we are tagging
  607. //
  608. pTagTemp = AllocMem(sizeof(TAGGEDADDRESS));
  609. if (0 == pTagTemp) {
  610. return FALSE;
  611. }
  612. pTagTemp->dwAddress = dwAddress;
  613. pTagTemp->wBytesReplaced = *(WORD *)dwAddress;
  614. //
  615. // Chain the entry
  616. //
  617. if (0 == pTagHead) {
  618. pTagHead = pTagTemp;
  619. }
  620. else {
  621. pTagTemp->pNext = pTagHead;
  622. pTagHead = pTagTemp;
  623. }
  624. //
  625. // Mark this branch as executed
  626. //
  627. WRITEWORD(dwAddress, 0xFFFF);
  628. return TRUE;
  629. }
  630. BOOL
  631. RestoreTaggedAddresses(VOID)
  632. {
  633. PTAGGEDADDRESS pTagTemp;
  634. PTAGGEDADDRESS pTagTemp2;
  635. //
  636. // Walk the tag list and replace the marked branches with their original bytes
  637. //
  638. pTagTemp = pTagHead;
  639. while(pTagTemp) {
  640. //
  641. // Dirty up the code now so the branches can auto terminate
  642. //
  643. WRITEWORD(pTagTemp->dwAddress, pTagTemp->wBytesReplaced);
  644. pTagTemp2 = pTagTemp;
  645. pTagTemp = pTagTemp->pNext;
  646. //
  647. // Dump the old allocated memory
  648. //
  649. FreeMem(pTagTemp2);
  650. }
  651. pTagHead = 0;
  652. return TRUE;
  653. }
  654. BOOL
  655. PushBranch(DWORD dwAddress)
  656. {
  657. PBRANCHADDRESS pBranchTemp;
  658. pBranchTemp = AllocMem(sizeof(BRANCHADDRESS));
  659. if (0 == pBranchTemp) {
  660. return FALSE;
  661. }
  662. pBranchTemp->dwAddress = dwAddress;
  663. if (0 == pBranchHead) {
  664. pBranchHead = pBranchTemp;
  665. }
  666. else {
  667. pBranchTemp->pNext = pBranchHead;
  668. pBranchHead = pBranchTemp;
  669. }
  670. return TRUE;
  671. }
  672. DWORD
  673. PopBranch(VOID)
  674. {
  675. PBRANCHADDRESS pBranchTemp;
  676. DWORD dwAddress = 0;
  677. pBranchTemp = pBranchHead;
  678. if (0 == pBranchTemp) {
  679. return 0;
  680. }
  681. dwAddress = pBranchTemp->dwAddress;
  682. pBranchHead = pBranchHead->pNext;
  683. FreeMem(pBranchTemp);
  684. return dwAddress;
  685. }
  686. VOID
  687. LockMapper(VOID)
  688. {
  689. EnterCriticalSection(&mapCritSec);
  690. }
  691. VOID
  692. UnlockMapper(VOID)
  693. {
  694. LeaveCriticalSection(&mapCritSec);
  695. }