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.

406 lines
11 KiB

  1. //+----------------------------------------------------------------------------
  2. //
  3. // File: slist.c
  4. //
  5. // Module: Debugger extension DLL
  6. //
  7. // Synopsis: !slist debugger extension for ntsd and kd. Dumps the SLIST
  8. // header and then walks the SLIST displaying the address of
  9. // each node on the list.
  10. //
  11. // Copyright (C) 2001 Microsoft Corporation
  12. //
  13. // Created: 14 Nov 2001 Scott Gasch (sgasch)
  14. //
  15. //+----------------------------------------------------------------------------
  16. #include "precomp.h"
  17. #include "ntrtl.h"
  18. #include <string.h>
  19. #pragma hdrstop
  20. #define ARRAY_COUNT(x) (sizeof(x) / sizeof((x)[0]))
  21. CHAR *g_szNodeType = NULL;
  22. ULONG64 g_uOffset = 0;
  23. ULONG64 g_uSlistHead = 0;
  24. ULONG g_uPtrSize = 0;
  25. //+----------------------------------------------------------------------------
  26. //
  27. // Function: DisplaySlistHelp
  28. //
  29. // Synopsis: Display a simple usage message
  30. //
  31. // Arguments: void
  32. //
  33. // Returns: void
  34. //
  35. //+----------------------------------------------------------------------------
  36. void
  37. DisplaySlistHelp(void)
  38. {
  39. dprintf("!slist <address> [symbol [offset]]\n\n"
  40. "Dump the slist with header at address. If symbol and offset are\n"
  41. "present, assume each node on the SLIST is of type symbol and that\n"
  42. "the SLIST pointer is at offset in the struct.\n\n"
  43. "Examples:\n"
  44. " !slist 80543ea8\n"
  45. " !slist myprog!SlistHeader myprog!NODE 0\n");
  46. }
  47. //+----------------------------------------------------------------------------
  48. //
  49. // Function: DumpSlistHeader
  50. //
  51. // Synopsis: Given the address of the SLIST header, dump it.
  52. //
  53. // Arguments: ULONG64 u64AddrSlistHeader -- addr of SLIST_HEADER in debugee mem
  54. //
  55. // Returns: void
  56. //
  57. //+----------------------------------------------------------------------------
  58. void
  59. DumpSlistHeader(void)
  60. {
  61. ULONG uOffset; // field offset within the struct
  62. dprintf("SLIST HEADER:\n");
  63. if (InitTypeRead(g_uSlistHead,
  64. nt!_SLIST_HEADER))
  65. {
  66. dprintf("Unable to read type nt!_SLIST_HEADER at %p\n",
  67. g_uSlistHead);
  68. dprintf("Please check your symbols and sympath.\n");
  69. return;
  70. }
  71. //
  72. // Depending on the type of machine we are debugging, dump the proper
  73. // SLIST_HEADER structure. Note this must change is the definition of
  74. // SLIST_HEADER changes in ntrtl.h.
  75. //
  76. if ((TargetMachine == IMAGE_FILE_MACHINE_IA64) ||
  77. (TargetMachine == IMAGE_FILE_MACHINE_AMD64))
  78. {
  79. GetFieldOffset ("nt!_SLIST_HEADER", "Alignment", &uOffset);
  80. dprintf(" +0x%03x Alignment : %I64x\n",
  81. uOffset, ReadField(Alignment));
  82. dprintf(" +0x%03x (Depth) : %x\n",
  83. uOffset, ReadField(Alignment) & 0xFFFF);
  84. GetFieldOffset ("nt!_SLIST_HEADER", "Region", &uOffset);
  85. dprintf(" +0x%03x Region : %I64x\n",
  86. uOffset, ReadField(Region));
  87. }
  88. else
  89. {
  90. GetFieldOffset ("nt!_SLIST_HEADER", "Alignment", &uOffset);
  91. dprintf(" +0x%03x Alignment : %I64x\n",
  92. uOffset, ReadField(Alignment));
  93. GetFieldOffset ("nt!_SLIST_HEADER", "Next", &uOffset);
  94. dprintf(" +0x%03x Next : %I64x\n",
  95. uOffset, ReadField(Next));
  96. GetFieldOffset ("nt!_SLIST_HEADER", "Depth", &uOffset);
  97. dprintf(" +0x%03x Depth : %I64x\n",
  98. uOffset, ReadField(Depth));
  99. GetFieldOffset ("nt!_SLIST_HEADER", "Sequence", &uOffset);
  100. dprintf(" +0x%03x Sequence : %I64x\n",
  101. uOffset, ReadField(Sequence));
  102. }
  103. }
  104. //+----------------------------------------------------------------------------
  105. //
  106. // Function: DumpSlist
  107. //
  108. // Synopsis: Walk and display the SLIST.
  109. //
  110. // Arguments: ULONG64 pHeader -- addr of SLIST_HEADER in debugee mem
  111. //
  112. // Returns: void
  113. //
  114. //+----------------------------------------------------------------------------
  115. void
  116. DumpSlist(void)
  117. {
  118. ULONG uError; // result of ReadPointer operations
  119. ULONG64 pCurrent; // ptr to current item
  120. ULONG64 pNext; // ptr to next item
  121. ULONG64 u64Head; // first item scratch var
  122. ULONG64 u64Region; // region info for ia64 headers
  123. SYM_DUMP_PARAM SymDump;
  124. ULONG x;
  125. //
  126. // Determine the address of the first node on the list.
  127. //
  128. if ((TargetMachine == IMAGE_FILE_MACHINE_IA64) ||
  129. (TargetMachine == IMAGE_FILE_MACHINE_AMD64))
  130. {
  131. //
  132. // For ia64, getting the first node involves some work. It's
  133. // made up of some bits from the Alignment part of the header
  134. // and a few bits from the Region part of the header.
  135. //
  136. // First read the Alignment part in.
  137. //
  138. uError = ReadPointer(g_uSlistHead, &u64Head);
  139. if (!uError)
  140. {
  141. dprintf("Can't read memory at %p, error %x\n",
  142. g_uSlistHead, uError);
  143. return;
  144. }
  145. //
  146. // Now read the Region part in, 8 bytes later.
  147. //
  148. uError = ReadPointer(g_uSlistHead + 8, &u64Region);
  149. if (!uError)
  150. {
  151. dprintf("Can't read memory at %p, error %x\n",
  152. (g_uSlistHead + 8), uError);
  153. return;
  154. }
  155. //
  156. // Note to self:
  157. //
  158. // 25 == SLIST_ADR_BITS_START
  159. // 4 == SLIST_ADR_ALIGMENT
  160. //
  161. // See base\ntos\rtl\ia64\slist.s
  162. //
  163. pCurrent = ((u64Head >> 25) << 4);
  164. pCurrent += u64Region;
  165. }
  166. else
  167. {
  168. //
  169. // For x86 this is easy, the pointer is sitting in the first 4
  170. // bytes of the Header.
  171. //
  172. uError = ReadPointer(g_uSlistHead, &u64Head);
  173. if (!uError)
  174. {
  175. dprintf("Can't read memory at %p, error %x\n",
  176. g_uSlistHead, uError);
  177. return;
  178. }
  179. pCurrent = u64Head;
  180. }
  181. dprintf("\nSLIST CONTENTS:\n");
  182. //
  183. // Walk until NULL termination
  184. //
  185. while((ULONG64)0 != pCurrent)
  186. {
  187. //
  188. // Be responsive to ^C, allow dump of SLIST to be aborted
  189. //
  190. if (TRUE == CheckControlC())
  191. {
  192. return;
  193. }
  194. //
  195. // Dump this one
  196. //
  197. if (NULL == g_szNodeType)
  198. {
  199. dprintf("%p ", pCurrent);
  200. for (x = 0;
  201. x < 4;
  202. x++)
  203. {
  204. uError = ReadPointer(pCurrent + (x * g_uPtrSize), &pNext);
  205. if (!uError)
  206. {
  207. dprintf("Can't read memory at address %p, error %x\n",
  208. pCurrent + (x * g_uPtrSize), uError);
  209. pNext = 0;
  210. } else
  211. {
  212. if (g_uPtrSize == 4)
  213. {
  214. dprintf("%08x ", pNext);
  215. }
  216. else
  217. {
  218. dprintf("%08x%08x ",
  219. (pNext & 0xFFFFFFFF00000000) >> 32,
  220. pNext & 0x00000000FFFFFFFF);
  221. if (x == 1) dprintf("\n ");
  222. }
  223. }
  224. }
  225. dprintf("\n");
  226. }
  227. else
  228. {
  229. dprintf("%p\n",
  230. (pCurrent - g_uOffset));
  231. SymDump.size = sizeof(SYM_DUMP_PARAM);
  232. SymDump.sName = (PUCHAR)g_szNodeType;
  233. SymDump.Options = 0;
  234. SymDump.addr = pCurrent - g_uOffset;
  235. SymDump.listLink = NULL;
  236. SymDump.Context = NULL;
  237. SymDump.CallbackRoutine = NULL;
  238. SymDump.nFields = 0;
  239. SymDump.Fields = NULL;
  240. Ioctl(IG_DUMP_SYMBOL_INFO, &SymDump, SymDump.size);
  241. }
  242. //
  243. // Get the next one
  244. //
  245. uError = ReadPointer(pCurrent, &pNext);
  246. if (!uError)
  247. {
  248. dprintf("Can't read memory at %p, error %x\n",
  249. pCurrent, uError);
  250. return;
  251. }
  252. pCurrent = pNext;
  253. }
  254. }
  255. //+----------------------------------------------------------------------------
  256. //
  257. // Function: slist
  258. //
  259. // Synopsis: Entry point for !slist
  260. //
  261. // Arguments: Arguments to command in char *args
  262. //
  263. // Returns: S_OK
  264. //
  265. //+----------------------------------------------------------------------------
  266. DECLARE_API(slist)
  267. {
  268. SLIST_HEADER sSlistHeader;
  269. ULONG64 u64AddrSlistHeader = 0;
  270. BOOL fSuccess;
  271. CHAR *pArgs = NULL;
  272. CHAR *pDelims = " \t";
  273. CHAR *pToken;
  274. DWORD dwNumTokens = 0;
  275. INIT_API();
  276. //
  277. // Reset params from last time we ran.
  278. //
  279. g_uSlistHead = 0;
  280. if (NULL != g_szNodeType)
  281. {
  282. free(g_szNodeType);
  283. g_szNodeType = NULL;
  284. }
  285. g_uOffset = 0;
  286. if ((TargetMachine == IMAGE_FILE_MACHINE_IA64) ||
  287. (TargetMachine == IMAGE_FILE_MACHINE_AMD64))
  288. {
  289. g_uPtrSize = 8;
  290. }
  291. else
  292. {
  293. g_uPtrSize = 4;
  294. }
  295. //
  296. // Parse our arguments
  297. //
  298. pArgs = _strdup(args);
  299. if (NULL == pArgs)
  300. {
  301. dprintf("Debugger machine out of memory!\n");
  302. goto Done;
  303. }
  304. pToken = strtok(pArgs, pDelims);
  305. while (NULL != pToken)
  306. {
  307. dwNumTokens++;
  308. if ((!strncmp(pToken, "-help", 5)) ||
  309. (!strncmp(pToken, "-?", 2)) ||
  310. (!strncmp(pToken, "/help", 5)) ||
  311. (!strncmp(pToken, "/?", 2)))
  312. {
  313. DisplaySlistHelp();
  314. goto Done;
  315. }
  316. else
  317. {
  318. if (0 == g_uSlistHead)
  319. {
  320. g_uSlistHead = GetExpression(pToken);
  321. }
  322. else if (NULL == g_szNodeType)
  323. {
  324. g_szNodeType = _strdup(pToken);
  325. if (NULL == g_szNodeType)
  326. {
  327. dprintf("Debugger machine out of memory!\n");
  328. goto Done;
  329. }
  330. }
  331. else
  332. {
  333. g_uOffset = GetExpression(pToken);
  334. }
  335. }
  336. pToken = strtok(NULL, pDelims);
  337. }
  338. //
  339. // If they called with no commandline, give them the help.
  340. //
  341. if (0 == dwNumTokens)
  342. {
  343. DisplaySlistHelp();
  344. goto Done;
  345. }
  346. //
  347. // Dump the slist header
  348. //
  349. DumpSlistHeader();
  350. //
  351. // Walk the slist
  352. //
  353. DumpSlist();
  354. Done:
  355. g_uSlistHead = 0;
  356. if (NULL != g_szNodeType)
  357. {
  358. free(g_szNodeType);
  359. g_szNodeType = NULL;
  360. }
  361. g_uOffset = 0;
  362. g_uPtrSize = 0;
  363. if (NULL != pArgs)
  364. {
  365. free(pArgs);
  366. }
  367. EXIT_API();
  368. return(S_OK);
  369. }