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.

155 lines
4.2 KiB

  1. /***************************************************************************
  2. * STACK1.C
  3. *
  4. * Code to support stack tracing on task stacks.
  5. *
  6. ***************************************************************************/
  7. #include "toolpriv.h"
  8. #include <newexe.h>
  9. #include <string.h>
  10. /* ----- Function prototypes ----- */
  11. NOEXPORT void StackTraceInfo(
  12. STACKTRACEENTRY FAR *lpStack);
  13. /* ----- Functions ----- */
  14. /* StackTraceFirst
  15. * Starts a task stack trace by returning information about the
  16. * first frame on the task's stack.
  17. */
  18. BOOL TOOLHELPAPI StackTraceFirst(
  19. STACKTRACEENTRY FAR *lpStackTrace,
  20. HANDLE hTDB)
  21. {
  22. /* Check the version number and verify proper installation */
  23. if (!wLibInstalled || !lpStackTrace ||
  24. lpStackTrace->dwSize != sizeof (STACKTRACEENTRY))
  25. return FALSE;
  26. /* Get the first value */
  27. if (!(StackFrameFirst(lpStackTrace, hTDB)))
  28. return FALSE;
  29. /* Get module and segment number information */
  30. StackTraceInfo(lpStackTrace);
  31. return TRUE;
  32. }
  33. /* StackTraceCSIPFirst
  34. * Traces the stack of an arbitrary CS:IP. All parameters must be
  35. * given, and once started, the StackTraceNext function can be used
  36. * to trace the remainder of the stack
  37. */
  38. BOOL TOOLHELPAPI StackTraceCSIPFirst(
  39. STACKTRACEENTRY FAR *lpStack,
  40. WORD wSS,
  41. WORD wCS,
  42. WORD wIP,
  43. WORD wBP)
  44. {
  45. /* Check the version number and verify proper installation */
  46. if (!wLibInstalled || !lpStack ||
  47. lpStack->dwSize != sizeof (STACKTRACEENTRY))
  48. return FALSE;
  49. /* Get the user information */
  50. lpStack->wSS = wSS;
  51. lpStack->wCS = wCS;
  52. lpStack->wIP = wIP;
  53. lpStack->wBP = wBP;
  54. /* Get module and segment number information */
  55. StackTraceInfo(lpStack);
  56. /* Set the hTask to the current task as we are in the current task
  57. * context. The CS may not be owned by this task, but at least
  58. * we put a reasonable value in there.
  59. */
  60. lpStack->hTask = GetCurrentTask();
  61. return TRUE;
  62. }
  63. /* StackTraceNext
  64. * Continues a stack trace by returning information about the next
  65. * frame on the task's stack.
  66. * structure.
  67. */
  68. BOOL TOOLHELPAPI StackTraceNext(
  69. STACKTRACEENTRY FAR *lpStackTrace)
  70. {
  71. /* Check the version number and verify proper installation */
  72. if (!wLibInstalled || !lpStackTrace ||
  73. lpStackTrace->dwSize != sizeof (STACKTRACEENTRY))
  74. return FALSE;
  75. /* Get information about this frame */
  76. if (!StackFrameNext(lpStackTrace))
  77. return FALSE;
  78. /* Get module and segment number information */
  79. StackTraceInfo(lpStackTrace);
  80. return TRUE;
  81. }
  82. /* ----- Helper functions ----- */
  83. /* StackTraceInfo
  84. * Gets module and segment number info about the given entry
  85. */
  86. NOEXPORT void StackTraceInfo(
  87. STACKTRACEENTRY FAR *lpStack)
  88. {
  89. GLOBALENTRY GlobalEntry;
  90. struct new_exe FAR *lpNewExe;
  91. struct new_seg1 FAR *lpSeg;
  92. WORD i;
  93. /* If we have a NULL CS, this is a NEAR frame. Just return because we
  94. * assume the user hasn't trashed the structure. The module and seg
  95. * info will be the same as the last time
  96. */
  97. if (!lpStack->wCS)
  98. return;
  99. /* Get information about the code segment block */
  100. GlobalEntry.dwSize = sizeof (GLOBALENTRY);
  101. if (!GlobalEntryHandle(&GlobalEntry, lpStack->wCS))
  102. return;
  103. /* The owner of all code segments is the hModule */
  104. lpStack->hModule = GlobalEntry.hOwner;
  105. /* To find the segment number, we look in the EXE header and count the
  106. * listed segments till we find this one
  107. */
  108. /* Get a pointer to the EXE Header module */
  109. lpNewExe = MAKEFARPTR(HelperHandleToSel(lpStack->hModule), 0);
  110. /* Make sure this is a EXE Header segment */
  111. if (lpNewExe->ne_magic != NEMAGIC)
  112. return;
  113. /* Get the list of segments and go for it */
  114. lpSeg = MAKEFARPTR(HIWORD((DWORD)lpNewExe), lpNewExe->ne_segtab);
  115. for (i = 0 ; i < lpNewExe->ne_cseg ; ++i, ++lpSeg)
  116. if (HelperHandleToSel(lpSeg->ns_handle) == lpStack->wCS)
  117. break;
  118. if (i == lpNewExe->ne_cseg)
  119. return;
  120. /* Save the segment number (seg numbers start at one) */
  121. lpStack->wSegment = i + 1;
  122. }