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.

559 lines
14 KiB

  1. /*++
  2. Copyright (c) 1993-2000 Microsoft Corporation
  3. Module Name:
  4. exts.c
  5. Abstract:
  6. This file contains the generic routines and initialization code
  7. for the kernel debugger extensions dll.
  8. Environment:
  9. User Mode
  10. --*/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. #include <ntverp.h>
  14. //
  15. // Valid for the lifetime of the debug session.
  16. //
  17. WINDBG_EXTENSION_APIS ExtensionApis;
  18. ULONG TargetMachine;
  19. BOOL Connected;
  20. ULONG g_TargetClass;
  21. ULONG g_TargetBuild;
  22. ULONG g_Qualifier;
  23. ULONG64 g_SharedUserData;
  24. //
  25. // Valid only during an extension API call
  26. //
  27. PDEBUG_ADVANCED g_ExtAdvanced;
  28. PDEBUG_CLIENT g_ExtClient;
  29. PDEBUG_CONTROL g_ExtControl;
  30. PDEBUG_DATA_SPACES g_ExtData;
  31. PDEBUG_REGISTERS g_ExtRegisters;
  32. PDEBUG_SYMBOLS2 g_ExtSymbols;
  33. PDEBUG_SYSTEM_OBJECTS3 g_ExtSystem;
  34. #define SKIP_WSPACE(s) while (*s && (*s == ' ' || *s == '\t')) {++s;}
  35. // Queries for all debugger interfaces.
  36. extern "C" HRESULT
  37. ExtQuery(PDEBUG_CLIENT Client)
  38. {
  39. HRESULT Status;
  40. if ((Status = Client->QueryInterface(__uuidof(IDebugAdvanced),
  41. (void **)&g_ExtAdvanced)) != S_OK)
  42. {
  43. goto Fail;
  44. }
  45. if ((Status = Client->QueryInterface(__uuidof(IDebugControl),
  46. (void **)&g_ExtControl)) != S_OK)
  47. {
  48. goto Fail;
  49. }
  50. if ((Status = Client->QueryInterface(__uuidof(IDebugDataSpaces),
  51. (void **)&g_ExtData)) != S_OK)
  52. {
  53. goto Fail;
  54. }
  55. if ((Status = Client->QueryInterface(__uuidof(IDebugRegisters),
  56. (void **)&g_ExtRegisters)) != S_OK)
  57. {
  58. goto Fail;
  59. }
  60. if ((Status = Client->QueryInterface(__uuidof(IDebugSymbols2),
  61. (void **)&g_ExtSymbols)) != S_OK)
  62. {
  63. goto Fail;
  64. }
  65. if ((Status = Client->QueryInterface(__uuidof(IDebugSystemObjects),
  66. (void **)&g_ExtSystem)) != S_OK)
  67. {
  68. goto Fail;
  69. }
  70. g_ExtClient = Client;
  71. return S_OK;
  72. Fail:
  73. ExtRelease();
  74. return Status;
  75. }
  76. // Cleans up all debugger interfaces.
  77. void
  78. ExtRelease(void)
  79. {
  80. g_ExtClient = NULL;
  81. EXT_RELEASE(g_ExtAdvanced);
  82. EXT_RELEASE(g_ExtControl);
  83. EXT_RELEASE(g_ExtData);
  84. EXT_RELEASE(g_ExtRegisters);
  85. EXT_RELEASE(g_ExtSymbols);
  86. EXT_RELEASE(g_ExtSystem);
  87. }
  88. // Normal output.
  89. void __cdecl
  90. ExtOut(PCSTR Format, ...)
  91. {
  92. va_list Args;
  93. va_start(Args, Format);
  94. g_ExtControl->OutputVaList(DEBUG_OUTPUT_NORMAL, Format, Args);
  95. va_end(Args);
  96. }
  97. // Error output.
  98. void __cdecl
  99. ExtErr(PCSTR Format, ...)
  100. {
  101. va_list Args;
  102. va_start(Args, Format);
  103. g_ExtControl->OutputVaList(DEBUG_OUTPUT_ERROR, Format, Args);
  104. va_end(Args);
  105. }
  106. // Warning output.
  107. void __cdecl
  108. ExtWarn(PCSTR Format, ...)
  109. {
  110. va_list Args;
  111. va_start(Args, Format);
  112. g_ExtControl->OutputVaList(DEBUG_OUTPUT_WARNING, Format, Args);
  113. va_end(Args);
  114. }
  115. // Verbose output.
  116. void __cdecl
  117. ExtVerb(PCSTR Format, ...)
  118. {
  119. va_list Args;
  120. va_start(Args, Format);
  121. g_ExtControl->OutputVaList(DEBUG_OUTPUT_VERBOSE, Format, Args);
  122. va_end(Args);
  123. }
  124. extern "C"
  125. HRESULT
  126. CALLBACK
  127. DebugExtensionInitialize(PULONG Version, PULONG Flags)
  128. {
  129. IDebugClient *DebugClient;
  130. PDEBUG_CONTROL DebugControl;
  131. HRESULT Hr;
  132. *Version = DEBUG_EXTENSION_VERSION(1, 0);
  133. *Flags = 0;
  134. if ((Hr = DebugCreate(__uuidof(IDebugClient),
  135. (void **)&DebugClient)) != S_OK)
  136. {
  137. return Hr;
  138. }
  139. if ((Hr = DebugClient->QueryInterface(__uuidof(IDebugControl),
  140. (void **)&DebugControl)) != S_OK)
  141. {
  142. return Hr;
  143. }
  144. ExtensionApis.nSize = sizeof (ExtensionApis);
  145. if ((Hr = DebugControl->GetWindbgExtensionApis64(&ExtensionApis)) != S_OK) {
  146. return Hr;
  147. }
  148. DebugControl->Release();
  149. DebugClient->Release();
  150. return S_OK;
  151. }
  152. extern "C"
  153. void
  154. CALLBACK
  155. DebugExtensionNotify(ULONG Notify, ULONG64 Argument)
  156. {
  157. //
  158. // The first time we actually connect to a target, get the page size
  159. //
  160. if ((Notify == DEBUG_NOTIFY_SESSION_ACCESSIBLE) && (!Connected))
  161. {
  162. IDebugClient *DebugClient;
  163. PDEBUG_DATA_SPACES DebugDataSpaces;
  164. PDEBUG_CONTROL DebugControl;
  165. PDEBUG_SYSTEM_OBJECTS3 DebugSystem;
  166. HRESULT Hr;
  167. ULONG64 Page;
  168. if ((Hr = DebugCreate(__uuidof(IDebugClient),
  169. (void **)&DebugClient)) == S_OK)
  170. {
  171. //
  172. // Get the page size and PAE enable flag
  173. //
  174. if ((Hr = DebugClient->QueryInterface(__uuidof(IDebugDataSpaces),
  175. (void **)&DebugDataSpaces)) == S_OK)
  176. {
  177. if ((Hr = DebugDataSpaces->ReadDebuggerData(
  178. DEBUG_DATA_MmPageSize, &Page,
  179. sizeof(Page), NULL)) == S_OK)
  180. {
  181. PageSize = (ULONG)(ULONG_PTR)Page;
  182. }
  183. if ((Hr = DebugDataSpaces->ReadDebuggerData(
  184. DEBUG_DATA_SharedUserData, &g_SharedUserData,
  185. sizeof(Page), NULL)) != S_OK)
  186. {
  187. g_SharedUserData = (ULONG64) 0;
  188. }
  189. DebugDataSpaces->Release();
  190. }
  191. //
  192. // Get the architecture type.
  193. //
  194. if ((Hr = DebugClient->QueryInterface(__uuidof(IDebugControl),
  195. (void **)&DebugControl)) == S_OK)
  196. {
  197. ULONG Platform, MajorVer, MinorVer, SrvPack;
  198. if ((Hr = DebugControl->GetActualProcessorType(
  199. &TargetMachine)) == S_OK)
  200. {
  201. Connected = TRUE;
  202. }
  203. if ((Hr = DebugControl->GetDebuggeeType(&g_TargetClass, &g_Qualifier)) == S_OK)
  204. {
  205. }
  206. if ((Hr = DebugControl->GetSystemVersion(&Platform, &MajorVer,
  207. &MinorVer, NULL,
  208. 0, NULL,
  209. &SrvPack, NULL,
  210. 0, NULL)) == S_OK)
  211. {
  212. g_TargetBuild = MinorVer;
  213. } else
  214. {
  215. // for some reason we failed, assume target is a recent build
  216. g_TargetBuild = 3600;
  217. }
  218. DebugControl->Release();
  219. }
  220. DebugClient->Release();
  221. }
  222. }
  223. if (Notify == DEBUG_NOTIFY_SESSION_INACTIVE)
  224. {
  225. Connected = FALSE;
  226. PageSize = 0;
  227. TargetMachine = 0;
  228. }
  229. return;
  230. }
  231. extern "C"
  232. void
  233. CALLBACK
  234. DebugExtensionUninitialize(void)
  235. {
  236. return;
  237. }
  238. DllInit(
  239. HANDLE hModule,
  240. DWORD dwReason,
  241. DWORD dwReserved
  242. )
  243. {
  244. switch (dwReason) {
  245. case DLL_THREAD_ATTACH:
  246. break;
  247. case DLL_THREAD_DETACH:
  248. break;
  249. case DLL_PROCESS_DETACH:
  250. break;
  251. case DLL_PROCESS_ATTACH:
  252. break;
  253. }
  254. return TRUE;
  255. }
  256. HRESULT
  257. GetCurrentProcessor(
  258. IN PDEBUG_CLIENT Client,
  259. OPTIONAL OUT PULONG pProcessor,
  260. OPTIONAL OUT PHANDLE phCurrentThread
  261. )
  262. {
  263. PDEBUG_SYSTEM_OBJECTS DebugSystem;
  264. ULONG64 hCurrentThread;
  265. if (Client) {
  266. if (Client->QueryInterface(__uuidof(IDebugSystemObjects),
  267. (void **)&DebugSystem) != S_OK) {
  268. return E_FAIL;
  269. }
  270. DebugSystem->GetCurrentThreadHandle(&hCurrentThread);
  271. if (phCurrentThread) {
  272. *phCurrentThread = (HANDLE) hCurrentThread;
  273. }
  274. if (pProcessor) {
  275. *pProcessor = (ULONG) hCurrentThread - 1;
  276. }
  277. DebugSystem->Release();
  278. return S_OK;
  279. }
  280. if (phCurrentThread) {
  281. *phCurrentThread = NULL;
  282. }
  283. if (pProcessor) {
  284. *pProcessor = 0;
  285. }
  286. return E_FAIL;
  287. }
  288. HRESULT
  289. GetCurrentProcessName( PSTR ProcessBuffer, ULONG BufferSIze )
  290. {
  291. if (g_TargetClass == DEBUG_CLASS_USER_WINDOWS)
  292. {
  293. return g_ExtSystem->GetCurrentProcessExecutableName(ProcessBuffer, BufferSIze, NULL);
  294. }
  295. return S_FALSE;
  296. }
  297. typedef struct _LIST_TYPE_PARAMS {
  298. PCHAR Command;
  299. PCHAR CommandArgs;
  300. ULONG FieldOffset;
  301. ULONG nElement;
  302. } LIST_TYPE_PARAMS, *PLIST_TYPE_PARAMS;
  303. ULONG
  304. ListCallback(
  305. PFIELD_INFO Field,
  306. PVOID Context
  307. )
  308. {
  309. CHAR Execute[MAX_PATH];
  310. PCHAR Buffer;
  311. PLIST_TYPE_PARAMS pListParams = (PLIST_TYPE_PARAMS) Context;
  312. // Execute command
  313. sprintf(Execute,
  314. "%s %I64lx %s",
  315. pListParams->Command,
  316. Field->address,// - pListParams->FieldOffset,
  317. pListParams->CommandArgs);
  318. g_ExtControl->Execute(DEBUG_OUTCTL_AMBIENT,Execute,DEBUG_EXECUTE_DEFAULT);
  319. dprintf("\n");
  320. if (CheckControlC()) {
  321. return TRUE;
  322. }
  323. return FALSE;
  324. }
  325. /*
  326. !list [-type <Type>] [-x "<Command>"] <address>
  327. This dumps out a list starting at ginve <address>
  328. <Type> If types is specified, it'll list that particular type accoring to
  329. the given field.
  330. <Command> If specified it'll execute the command for every list element.
  331. */
  332. DECLARE_API ( list )
  333. {
  334. CHAR Command[MAX_PATH], CmdArgs[MAX_PATH];
  335. CHAR Type[MAX_PATH];
  336. CHAR Field[MAX_PATH];
  337. ULONG64 Start;
  338. ULONG i, Offset, Commandlen;
  339. ULONG64 Next, Current;
  340. LIST_TYPE_PARAMS ListParams;
  341. ZeroMemory(Type, sizeof(Type));
  342. ZeroMemory(Field, sizeof(Field));
  343. ZeroMemory(Command, sizeof(Command));
  344. CmdArgs[0] = 0;
  345. Start = 0;
  346. while (args && *args) {
  347. SKIP_WSPACE(args);
  348. if (*args == '-' || *args == '/') {
  349. ++args;
  350. if (*args == 't') {
  351. PCHAR Dot;
  352. args++;
  353. SKIP_WSPACE(args);
  354. Dot = strchr(args, '.');
  355. if (Dot) {
  356. if ((ULONG) (ULONG_PTR) (Dot-args) < sizeof(Type))
  357. {
  358. strncpy(Type, args, (ULONG) (ULONG_PTR) (Dot-args));
  359. }
  360. Dot++;
  361. i=0;
  362. while (*Dot && (i < MAX_PATH-1) && (*Dot != ' ') && (*Dot != '\t'))
  363. Field[i++] = *Dot++;
  364. args = Dot;
  365. }
  366. } else if (*args == 'x') {
  367. ++args;
  368. SKIP_WSPACE(args);
  369. i=0;
  370. if (*args == '"') {
  371. ++args;
  372. while (*args && (i < MAX_PATH-1) && (*args != '"'))
  373. Command[i++] = *args++;
  374. ++args;
  375. } else {
  376. dprintf("Invalid command specification. See !list -h\n");
  377. return E_INVALIDARG;
  378. }
  379. } else if (*args == 'a') {
  380. ++args;
  381. SKIP_WSPACE(args);
  382. i=0;
  383. if (*args == '"') {
  384. ++args;
  385. while (*args && (i < MAX_PATH-1) && (*args != '"'))
  386. CmdArgs[i++] = *args++;
  387. ++args;
  388. CmdArgs[i] = 0;
  389. } else {
  390. dprintf("Invalid command argument specification. See !list -h\n");
  391. return E_INVALIDARG;
  392. }
  393. } else if (*args == 'h' || *args == '?') {
  394. dprintf("Usage: !list -t [mod!]TYPE.Field <Start-Address>\n"
  395. " -x \"Command-for-each-element\"\n"
  396. " -a \"Command-arguments\"\n"
  397. " -h\n"
  398. "Command after -x is executed for each list element. Its first argument is\n"
  399. "list-head address and remaining arguments are specified after -a\n"
  400. "eg. !list -t MYTYPE.l.Flink -x \"dd\" -a \"l2\" 0x6bc00\n"
  401. " dumps first 2 dwords in list of MYTYPE at 0x6bc00\n\n"
  402. );
  403. return S_OK;
  404. } else {
  405. dprintf("Invalid flag -%c in !list\n", *args ? *args : ' ');
  406. return E_INVALIDARG;
  407. }
  408. } else {
  409. if (!GetExpressionEx(args, &Start, &args)) {
  410. dprintf("Invalid expression in %s\n", args);
  411. return E_FAIL;
  412. }
  413. }
  414. }
  415. Offset = 0;
  416. if (!Command[0]) {
  417. strcat(Command, "dp");
  418. }
  419. if (Type[0] && Field[0]) {
  420. if (GetFieldOffset(Type, Field, &Offset)) {
  421. dprintf("GetFieldOffset failed for %s.%s\n", Type, Field);
  422. return E_FAIL;
  423. }
  424. ListParams.Command = Command;
  425. ListParams.CommandArgs = CmdArgs;
  426. ListParams.FieldOffset = Offset;
  427. ListParams.nElement = 0;
  428. INIT_API();
  429. ListType(Type, Start, FALSE, Field, (PVOID) &ListParams, &ListCallback );
  430. EXIT_API();
  431. return S_OK;
  432. }
  433. Current = Start;
  434. Next = 0;
  435. INIT_API();
  436. while (Next != Start) {
  437. CHAR Execute[MAX_PATH];
  438. PCHAR Buffer;
  439. // Execute command
  440. sprintf(Execute, "%s %I64lx %s", Command, Current, CmdArgs);
  441. g_ExtControl->Execute(DEBUG_OUTCTL_AMBIENT,Execute,DEBUG_EXECUTE_DEFAULT);
  442. dprintf("\n");
  443. if (!ReadPointer(Current + Offset, &Next)) {
  444. dprintf("Cannot read next element at %p\n",
  445. Current + Offset);
  446. break;
  447. }
  448. if (!Next) {
  449. break;
  450. }
  451. Next -= Offset;
  452. Current = Next;
  453. if (CheckControlC()) {
  454. break;
  455. }
  456. }
  457. EXIT_API();
  458. return S_OK;
  459. }