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.

252 lines
7.6 KiB

  1. /*-----------------------------------------------------------------------------
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module:
  4. exts.cpp
  5. Sampe file showing couple of extension examples
  6. -----------------------------------------------------------------------------*/
  7. #include "dbgexts.h"
  8. /*
  9. Sample extension to demonstrace ececuting debugger command
  10. */
  11. HRESULT CALLBACK
  12. cmdsample(PDEBUG_CLIENT Client, PCSTR args)
  13. {
  14. CHAR Input[256];
  15. INIT_API();
  16. UNREFERENCED_PARAMETER(args);
  17. //
  18. // Output a 10 frame stack
  19. //
  20. g_ExtControl->OutputStackTrace(DEBUG_OUTCTL_ALL_CLIENTS | // Flags on what to do with output
  21. DEBUG_OUTCTL_OVERRIDE_MASK |
  22. DEBUG_OUTCTL_NOT_LOGGED,
  23. NULL,
  24. 10, // number of frames to display
  25. DEBUG_STACK_FUNCTION_INFO | DEBUG_STACK_COLUMN_NAMES |
  26. DEBUG_STACK_ARGUMENTS | DEBUG_STACK_FRAME_ADDRESSES);
  27. //
  28. // Engine interface for print
  29. //
  30. g_ExtControl->Output(DEBUG_OUTCTL_ALL_CLIENTS, "\n\nDebugger module list\n");
  31. //
  32. // list all the modules by executing lm command
  33. //
  34. g_ExtControl->Execute(DEBUG_OUTCTL_ALL_CLIENTS |
  35. DEBUG_OUTCTL_OVERRIDE_MASK |
  36. DEBUG_OUTCTL_NOT_LOGGED,
  37. "lm", // Command to be executed
  38. DEBUG_EXECUTE_DEFAULT );
  39. //
  40. // Ask for user input
  41. //
  42. g_ExtControl->Output(DEBUG_OUTCTL_ALL_CLIENTS, "\n\n***User Input sample\n\nEnter Command to run : ");
  43. GetInputLine(NULL, &Input[0], sizeof(Input));
  44. g_ExtControl->Execute(DEBUG_OUTCTL_ALL_CLIENTS |
  45. DEBUG_OUTCTL_OVERRIDE_MASK |
  46. DEBUG_OUTCTL_NOT_LOGGED,
  47. Input, // Command to be executed
  48. DEBUG_EXECUTE_DEFAULT );
  49. EXIT_API();
  50. return S_OK;
  51. }
  52. /*
  53. Sample extension to read and dump a struct on target
  54. This reads the struct _EXCEPTION_RECORD which is defined as:
  55. typedef struct _EXCEPTION_RECORD {
  56. NTSTATUS ExceptionCode;
  57. ULONG ExceptionFlags;
  58. struct _EXCEPTION_RECORD *ExceptionRecord;
  59. PVOID ExceptionAddress;
  60. ULONG NumberParameters;
  61. ULONG_PTR ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];
  62. } EXCEPTION_RECORD;
  63. */
  64. HRESULT CALLBACK
  65. structsample(PDEBUG_CLIENT Client, PCSTR args)
  66. {
  67. ULONG64 Address;
  68. INIT_API();
  69. Address = GetExpression(args);
  70. DWORD Buffer[4], cb;
  71. // Read and display first 4 dwords at Address
  72. if (ReadMemory(Address, &Buffer, sizeof(Buffer), &cb) && cb == sizeof(Buffer)) {
  73. dprintf("%p: %08lx %08lx %08lx %08lx\n\n", Address,
  74. Buffer[0], Buffer[1], Buffer[2], Buffer[3]);
  75. }
  76. //
  77. // Method 1 to dump a struct
  78. //
  79. dprintf("Method 1:\n");
  80. // Inititalze type read from the Address
  81. if (InitTypeRead(Address, _EXCEPTION_RECORD) != 0) {
  82. dprintf("Error in reading _EXCEPTION_RECORD at %p", // Use %p to print pointer values
  83. Address);
  84. } else {
  85. // read and dump the fields
  86. dprintf("_EXCEPTION_RECORD @ %p\n", Address);
  87. dprintf("\tExceptionCode : %lx\n", (ULONG) ReadField(ExceptionCode));
  88. dprintf("\tExceptionAddress : %p\n", ReadField(ExceptionAddress));
  89. dprintf("\tExceptionInformation[1] : %I64lx\n", ReadField(ExceptionInformation[1]));
  90. // And so on...
  91. }
  92. //
  93. // Method 2 to read a struct
  94. //
  95. ULONG64 ExceptionInformation_1, ExceptionAddress, ExceptionCode;
  96. dprintf("\n\nMethod 2:\n");
  97. // Read and dump the fields by specifying type and address individually
  98. if (GetFieldValue(Address, "_EXCEPTION_RECORD", "ExceptionCode", ExceptionCode)) {
  99. dprintf("Error in reading _EXCEPTION_RECORD at %p\n",
  100. Address);
  101. } else {
  102. // Pointers are read as ULONG64 values
  103. GetFieldValue(Address, "_EXCEPTION_RECORD", "ExceptionAddress", ExceptionAddress);
  104. GetFieldValue(Address, "_EXCEPTION_RECORD", "ExceptionInformation[1]", ExceptionInformation_1);
  105. // And so on..
  106. dprintf("_EXCEPTION_RECORD @ %p\n", Address);
  107. dprintf("\tExceptionCode : %lx\n", ExceptionCode);
  108. dprintf("\tExceptionAddress : %p\n", ExceptionAddress);
  109. dprintf("\tExceptionInformation[1] : %I64lx\n", ExceptionInformation_1);
  110. }
  111. ULONG64 Module;
  112. ULONG i, TypeId;
  113. CHAR Name[MAX_PATH];
  114. //
  115. // To get/list field names
  116. //
  117. g_ExtSymbols->GetSymbolTypeId("_EXCEPTION_RECORD", &TypeId, &Module);
  118. dprintf("Fields of _EXCEPTION_RECORD\n");
  119. for (i=0; ;i++) {
  120. HRESULT Hr;
  121. ULONG Offset=0;
  122. Hr = g_ExtSymbols2->GetFieldName(Module, TypeId, i, Name, MAX_PATH, NULL);
  123. if (Hr == S_OK) {
  124. g_ExtSymbols->GetFieldOffset(Module, TypeId, Name, &Offset);
  125. dprintf("%lx (+%03lx) %s\n", i, Offset, Name);
  126. } else if (Hr == E_INVALIDARG) {
  127. // All Fields done
  128. break;
  129. } else {
  130. dprintf("GetFieldName Failed %lx\n", Hr);
  131. break;
  132. }
  133. }
  134. //
  135. // Get name for an enumerate
  136. //
  137. // typedef enum {
  138. // Enum1,
  139. // Enum2,
  140. // Enum3,
  141. // } TEST_ENUM;
  142. //
  143. ULONG ValueOfEnum = 0;
  144. g_ExtSymbols->GetSymbolTypeId("TEST_ENUM", &TypeId, &Module);
  145. g_ExtSymbols2->GetConstantName(Module, TypeId, ValueOfEnum, Name, MAX_PATH, NULL);
  146. dprintf("Testenum %I64lx == %s\n", ExceptionCode, Name);
  147. // This prints out, Testenum 0 == Enum1
  148. //
  149. // Read an array
  150. //
  151. // typedef struct FOO_TYPE {
  152. // ULONG Bar;
  153. // ULONG Bar2;
  154. // } FOO_TYPE;
  155. //
  156. // FOO_TYPE sampleArray[20];
  157. ULONG Bar, Bar2;
  158. CHAR TypeName[100];
  159. for (i=0; i<20; i++) {
  160. sprintf(TypeName, "sampleArray[%lx]", i);
  161. if (GetFieldValue(0, TypeName, "Bar", Bar))
  162. break;
  163. GetFieldValue(0, TypeName, "Bar2", Bar2);
  164. dprintf("%16s - Bar %2ld Bar2 %ld\n", TypeName, Bar, Bar2);
  165. }
  166. EXIT_API();
  167. return S_OK;
  168. }
  169. /*
  170. This gets called (by DebugExtensionNotify whentarget is halted and is accessible
  171. */
  172. HRESULT
  173. NotifyOnTargetAccessible(PDEBUG_CONTROL Control)
  174. {
  175. dprintf("Extension dll detected a break");
  176. if (Connected) {
  177. dprintf(" connected to ");
  178. switch (TargetMachine) {
  179. case IMAGE_FILE_MACHINE_I386:
  180. dprintf("X86");
  181. break;
  182. case IMAGE_FILE_MACHINE_IA64:
  183. dprintf("IA64");
  184. break;
  185. default:
  186. dprintf("Other");
  187. break;
  188. }
  189. }
  190. dprintf("\n");
  191. //
  192. // show the top frame and execute dv to dump the locals here and return
  193. //
  194. Control->Execute(DEBUG_OUTCTL_ALL_CLIENTS |
  195. DEBUG_OUTCTL_OVERRIDE_MASK |
  196. DEBUG_OUTCTL_NOT_LOGGED,
  197. ".frame", // Command to be executed
  198. DEBUG_EXECUTE_DEFAULT );
  199. Control->Execute(DEBUG_OUTCTL_ALL_CLIENTS |
  200. DEBUG_OUTCTL_OVERRIDE_MASK |
  201. DEBUG_OUTCTL_NOT_LOGGED,
  202. "dv", // Command to be executed
  203. DEBUG_EXECUTE_DEFAULT );
  204. return S_OK;
  205. }
  206. /*
  207. A built-in help for the extension dll
  208. */
  209. HRESULT CALLBACK
  210. help(PDEBUG_CLIENT Client, PCSTR args)
  211. {
  212. INIT_API();
  213. UNREFERENCED_PARAMETER(args);
  214. dprintf("Help for dbgexts.dll\n"
  215. " cmdsample - This does stacktrace and lists\n"
  216. " help = Shows this help\n"
  217. " structsample <addr> - This dumps a struct at given address\n"
  218. );
  219. EXIT_API();
  220. return S_OK;
  221. }