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.

260 lines
5.5 KiB

  1. /*++
  2. Copyright (c) 1990 - 1994 Microsoft Corporation
  3. All rights reserved
  4. Module Name:
  5. dbgspl.c
  6. Abstract:
  7. Debugging tools for Argus
  8. Author:
  9. Krishna Ganugapati (KrishnaG) 28-December-1994
  10. Revision History:
  11. KrishnaG: Created: 28-December-1994
  12. To do:
  13. --*/
  14. #define NOMINMAX
  15. #include <nt.h>
  16. #include <ntrtl.h>
  17. #include <nturtl.h>
  18. #include <windows.h>
  19. #include <stdlib.h>
  20. #include <math.h>
  21. #include <ntsdexts.h>
  22. #include "dbglocal.h"
  23. typedef void (*PNTSD_OUTPUT_ROUTINE)(char *, ...);
  24. //+---------------------------------------------------------------------------
  25. //
  26. // Function: DumpVtbl
  27. //
  28. // Synopsis: Dumps a vtbl to the debugger
  29. //
  30. // Effects: Given a pointer to a vtbl, output the name of the vtbl, and
  31. // its contents to the debugger.
  32. //
  33. // Arguments: [pvtbl] -- Address of vtbl
  34. // [pszCommand] -- Symbolic expression for pvtbl
  35. //
  36. // History: 8-07-94 kevinro Created
  37. // 12-28-94 krishnaG swiped from the Ole project
  38. //
  39. //----------------------------------------------------------------------------
  40. BOOL
  41. DumpVtbl(
  42. HANDLE hCurrentProcess,
  43. HANDLE hCurrentThread,
  44. DWORD dwCurrentPc,
  45. PNTSD_EXTENSION_APIS lpExtensionApis,
  46. LPSTR lpArgumentString,
  47. PVOID pvtbl
  48. )
  49. {
  50. DWORD dwVtblOffset;
  51. char achNextSymbol[256];
  52. DWORD dwIndex;
  53. DWORD dwVtblEntry;
  54. if (pvtbl == 0)
  55. {
  56. // Can't handle objects at zero
  57. // ntsdPrintf("%s has a vtbl pointer of NULL\n", pszCommand);
  58. return 0;
  59. }
  60. if ((DWORD)pvtbl == 0xdededede)
  61. {
  62. // Can't handle objects at zero
  63. // ntsdPrintf("%s may be deleted memory. pvtbl==0xdededede\n",pszCommand);
  64. return 0;
  65. }
  66. //
  67. // This value points at the VTBL. Find a symbol for the VTBL
  68. //
  69. ntsdGetSymbol((LPVOID)pvtbl,(UCHAR *)achNextSymbol,(LPDWORD)&dwVtblOffset);
  70. //
  71. // If the dwVtblOffset is not zero, then we are pointing into the table.
  72. // This could mean multiple inheritance. We could be tricky, and try to
  73. // determine the vtbl by backing up here. Maybe later
  74. //
  75. if (dwVtblOffset != 0){
  76. ntsdPrintf("Closest Previous symbol is %s at 0x%x (offset -0x%x)\n",
  77. achNextSymbol,
  78. (DWORD)pvtbl - dwVtblOffset,
  79. dwVtblOffset);
  80. return 0;
  81. }
  82. ntsdPrintf("0x%08x -->\t %s\n",pvtbl,achNextSymbol);
  83. //
  84. // vtbl entries should always point at functions. Therefore, we should
  85. // always have a displacement of zero. To check for the end of the table
  86. // we will reevaluate the vtbl pointer. If the offset isn't what we
  87. // expected, then we are done.
  88. //
  89. for (dwIndex = 0 ; dwIndex < 4096 ; dwIndex += 4)
  90. {
  91. ntsdGetSymbol((LPVOID)((DWORD)pvtbl+dwIndex),
  92. (UCHAR *)achNextSymbol,
  93. (LPDWORD)&dwVtblOffset);
  94. if (dwVtblOffset != dwIndex){
  95. //
  96. // May have moved on to another vtable
  97. //
  98. #if DBG
  99. ntsdPrintf("?? %s + %x\n",achNextSymbol,dwVtblOffset);
  100. ntsdPrintf("Moved to another table?\n");
  101. #endif
  102. return 0;
  103. }
  104. movemem(
  105. (LPVOID)((DWORD)(pvtbl)+dwIndex),
  106. (PVOID)&dwVtblEntry,
  107. sizeof(dwVtblEntry)
  108. );
  109. //
  110. // If the function is at zero, then must be at end of table
  111. //
  112. if (dwVtblEntry == 0) {
  113. #if DBG
  114. ntsdPrintf("dwVtblEntry is zero. Must be end of table\n");
  115. return 0;
  116. #endif
  117. }
  118. // Now, determine the symbol for the entry in the vtbl
  119. ntsdGetSymbol((LPVOID)dwVtblEntry,
  120. (UCHAR *)achNextSymbol,
  121. (LPDWORD)&dwVtblOffset);
  122. // If it doesn't point to the start of a routine, then it
  123. // probably isn't part of the vtbl
  124. if (dwVtblOffset != 0)
  125. {
  126. #if DBG
  127. ntsdPrintf("?? %s + %x\n",achNextSymbol,dwVtblOffset);
  128. ntsdPrintf("Doesn't point to function?\n");
  129. #endif
  130. return 0;
  131. }
  132. ntsdPrintf(" 0x%08x\t %s\n",dwVtblEntry,achNextSymbol);
  133. }
  134. ntsdPrintf("Wow, there were at least 1024 entries in the table!\n");
  135. return(TRUE);
  136. }
  137. void
  138. vtbl(
  139. HANDLE hCurrentProcess,
  140. HANDLE hCurrentThread,
  141. DWORD dwCurrentPc,
  142. PNTSD_EXTENSION_APIS lpExtensionApis,
  143. LPSTR lpArgumentString
  144. )
  145. {
  146. PVOID pvtbl;
  147. //
  148. // Evalute the first pointer. This is a pointer to the table
  149. //
  150. pvtbl = (PVOID) ntsdGetExpr(lpArgumentString);
  151. DumpVtbl(
  152. hCurrentProcess,
  153. hCurrentThread,
  154. dwCurrentPc,
  155. lpExtensionApis,
  156. lpArgumentString,
  157. pvtbl
  158. );
  159. }
  160. BOOL dp(
  161. HANDLE hCurrentProcess,
  162. HANDLE hCurrentThread,
  163. DWORD dwCurrentPc,
  164. PNTSD_EXTENSION_APIS lpExtensionApis,
  165. LPSTR lpArgumentString)
  166. {
  167. PNTSD_OUTPUT_ROUTINE Print;
  168. PNTSD_GET_EXPRESSION EvalExpression;
  169. PNTSD_GET_SYMBOL GetSymbol;
  170. DWORD dwAddress = 0;
  171. BOOL bThereAreOptions = TRUE;
  172. Print = lpExtensionApis->lpOutputRoutine;
  173. EvalExpression = lpExtensionApis->lpGetExpressionRoutine;
  174. GetSymbol = lpExtensionApis->lpGetSymbolRoutine;
  175. while (bThereAreOptions) {
  176. while (isspace(*lpArgumentString)) {
  177. lpArgumentString++;
  178. }
  179. switch (*lpArgumentString) {
  180. default: // go get the address because there's nothing else
  181. bThereAreOptions = FALSE;
  182. break;
  183. }
  184. }
  185. if (*lpArgumentString != 0) {
  186. dwAddress = EvalValue(&lpArgumentString, EvalExpression, Print);
  187. }else {
  188. Print("Usage: !argexts.dp <addr of object>\n");
  189. return(TRUE);
  190. }
  191. //
  192. // Now dump out the object
  193. //
  194. return TRUE;
  195. }