Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

148 lines
3.2 KiB

  1. #include <assert.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <memory.h>
  5. #include <nt.h>
  6. #include <ntrtl.h>
  7. #include <nturtl.h>
  8. #include <ctype.h>
  9. #include <stdio.h>
  10. #include <windows.h>
  11. #include "view.h"
  12. #include "thread.h"
  13. #include "dump.h"
  14. #include "memory.h"
  15. #include "clevel.h"
  16. FIXUPRETURN g_fnFixupReturn[1];
  17. DWORD g_dwCallArray[2];
  18. BOOL
  19. PushCaller(PVOID ptfInfo,
  20. PVOID pEsp)
  21. {
  22. PTHREADFAULT ptFault = (PTHREADFAULT)ptfInfo;
  23. PCALLRETSTUB pCallStub = 0;
  24. PCALLERINFO pCallerTemp = 0;
  25. //
  26. // Allocate a unique return stub for this call
  27. //
  28. pCallStub = AllocateReturnStub(ptfInfo);
  29. if (0 == pCallStub) {
  30. return FALSE;
  31. }
  32. //
  33. // Allocate caller data for the restore
  34. //
  35. pCallerTemp = AllocMem(sizeof(CALLERINFO));
  36. if (0 == pCallerTemp) {
  37. return FALSE;
  38. }
  39. pCallerTemp->dwIdentifier = ptFault->dwCallMarker;
  40. pCallerTemp->dwCallLevel = ptFault->dwCallLevel;
  41. pCallerTemp->pReturn = (PVOID)(*(DWORD *)pEsp);
  42. pCallerTemp->pCallRetStub = pCallStub;
  43. pCallerTemp->pNextChain = 0;
  44. //
  45. // Increment the call count
  46. //
  47. ptFault->dwCallLevel++;
  48. //
  49. // Replace stack return value with the custom return stub
  50. //
  51. *(DWORD *)pEsp = (DWORD)pCallStub;
  52. //
  53. // Finally, chain up the return info to the rest of them
  54. //
  55. if (ptFault->pCallStackList) {
  56. pCallerTemp->pNextChain = ptFault->pCallStackList;
  57. ptFault->pCallStackList = pCallerTemp;
  58. }
  59. else {
  60. ptFault->pCallStackList = pCallerTemp;
  61. }
  62. return TRUE;
  63. }
  64. PCALLRETSTUB
  65. AllocateReturnStub(PVOID ptfInfo)
  66. {
  67. PCALLRETSTUB pRetStub = 0;
  68. PTHREADFAULT ptFault = (PTHREADFAULT)ptfInfo;
  69. pRetStub = AllocMem(sizeof(CALLRETSTUB));
  70. if (0 == pRetStub) {
  71. return 0;
  72. }
  73. //
  74. // Increment the return marker
  75. //
  76. ptFault->dwCallMarker++;
  77. //
  78. // Initialize the stub asm
  79. //
  80. pRetStub->PUSHDWORD[0] = 0x68; //push xxxxxxxx (68 dword)
  81. *(DWORD *)(&(pRetStub->PUSHDWORD[1])) = ptFault->dwCallMarker;
  82. pRetStub->JMPDWORD[0] = 0xff; //jmp dword ptr [xxxxxxxx] (ff 25 dword address)
  83. pRetStub->JMPDWORD[1] = 0x25;
  84. *(DWORD *)(&(pRetStub->JMPDWORD[2])) = (DWORD)&(g_dwCallArray[1]);
  85. return pRetStub;
  86. }
  87. PVOID
  88. PopCaller(DWORD dwIdentifier)
  89. {
  90. PTHREADFAULT pThreadFault = 0;
  91. PCALLERINFO pCallerTemp;
  92. PCALLERINFO pCallerPrev = 0;
  93. PVOID pReturn = 0;
  94. pThreadFault = GetProfilerThreadData();
  95. //
  96. // Find the entry in the caller list
  97. //
  98. pCallerTemp = (PCALLERINFO)pThreadFault->pCallStackList;
  99. while(pCallerTemp) {
  100. if (pCallerTemp->dwIdentifier == dwIdentifier) {
  101. break;
  102. }
  103. pCallerPrev = pCallerTemp;
  104. pCallerTemp = pCallerTemp->pNextChain;
  105. }
  106. //
  107. // Yank the entry from the list
  108. //
  109. if (0 == pCallerPrev) {
  110. pThreadFault->pCallStackList = pCallerTemp->pNextChain;
  111. }
  112. else {
  113. pCallerPrev->pNextChain = pCallerTemp->pNextChain;
  114. }
  115. //
  116. // Restore call level for the thread
  117. //
  118. pReturn = pCallerTemp->pReturn;
  119. pThreadFault->dwCallLevel = pCallerTemp->dwCallLevel;
  120. //
  121. // Cleanup the allocations
  122. //
  123. FreeMem(pCallerTemp->pCallRetStub);
  124. FreeMem(pCallerTemp);
  125. return pReturn;
  126. }