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.

1869 lines
58 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // Top-level command parsing.
  4. //
  5. // Copyright (C) Microsoft Corporation, 1990-2002.
  6. //
  7. //----------------------------------------------------------------------------
  8. #include "ntsdp.hpp"
  9. // Set if registers should be displayed by default in OutCurInfo.
  10. BOOL g_OciOutputRegs;
  11. ULONG g_DefaultStackTraceDepth = 20;
  12. BOOL g_EchoEventTimestamps;
  13. BOOL g_SwitchedProcs;
  14. // Last command executed.
  15. CHAR g_LastCommand[MAX_COMMAND];
  16. // State variables for top-level command processing.
  17. PSTR g_CommandStart; // Start of command buffer.
  18. PSTR g_CurCmd; // Current pointer in command buffer.
  19. ULONG g_PromptLength = 8; // Size of prompt string.
  20. ADDR g_UnasmDefault; // Default unassembly address.
  21. ADDR g_AssemDefault; // Default assembly address.
  22. ULONG g_DefaultRadix = 16; // Default number base.
  23. CHAR g_SymbolSuffix = 'n'; // Suffix to add to symbol if search
  24. // failure - 'n'-none 'a'-'w'-append.
  25. CHAR g_CmdState = 'i'; // State of present command processing
  26. // 'i'-init; 'g'-go; 't'-trace
  27. // 'p'-step; 'c'-cmd; 'b'-branch trace.
  28. int g_RedoCount = 0;
  29. PWSTR g_StartProcessDir;
  30. BOOL
  31. ChangeSymPath(PCSTR Args,
  32. BOOL Append,
  33. OUT PSTR PathRet,
  34. ULONG PathRetChars)
  35. {
  36. TargetInfo* Target;
  37. ProcessInfo* Process;
  38. if (Args != NULL)
  39. {
  40. while (*Args == ' ' || *Args == '\t')
  41. {
  42. Args++;
  43. }
  44. }
  45. if (Args != NULL && *Args)
  46. {
  47. if (ChangePath(&g_SymbolSearchPath, Args, Append,
  48. DEBUG_CSS_PATHS) != S_OK)
  49. {
  50. return FALSE;
  51. }
  52. ForAllLayersToProcess()
  53. {
  54. SymSetSearchPath(Process->m_SymHandle, g_SymbolSearchPath);
  55. }
  56. }
  57. if (PathRet)
  58. {
  59. CopyString(PathRet, g_SymbolSearchPath, PathRetChars);
  60. }
  61. else
  62. {
  63. dprintf("Symbol search path is: %s\n", g_SymbolSearchPath);
  64. CheckPath(g_SymbolSearchPath);
  65. }
  66. return TRUE;
  67. }
  68. void
  69. CallBugCheckExtension(DebugClient* Client)
  70. {
  71. HRESULT Status = E_FAIL;
  72. if (Client == NULL)
  73. {
  74. Client = FindExtClient();
  75. }
  76. if (Client != NULL)
  77. {
  78. char ExtName[32];
  79. // Extension name has to be in writable memory as it
  80. // gets lower-cased.
  81. strcpy(ExtName, "Analyze");
  82. // See if any existing extension DLLs are interested
  83. // in analyzing this bugcheck.
  84. CallAnyExtension(Client, NULL, ExtName, "",
  85. FALSE, FALSE, &Status);
  86. }
  87. if (Status != S_OK)
  88. {
  89. if (Client == NULL)
  90. {
  91. WarnOut("WARNING: Unable to locate a client for "
  92. "bugcheck analysis\n");
  93. }
  94. dprintf("*******************************************************************************\n");
  95. dprintf("* *\n");
  96. dprintf("* Bugcheck Analysis *\n");
  97. dprintf("* *\n");
  98. dprintf("*******************************************************************************\n");
  99. Execute(Client, ".bugcheck", DEBUG_EXECUTE_DEFAULT);
  100. dprintf("\n");
  101. Execute(Client, "kb", DEBUG_EXECUTE_DEFAULT);
  102. dprintf("\n");
  103. }
  104. }
  105. void
  106. HandleBPWithStatus(void)
  107. {
  108. ULONG Status = (ULONG)g_EventMachine->GetArgReg();
  109. switch(Status)
  110. {
  111. case DBG_STATUS_CONTROL_C:
  112. case DBG_STATUS_SYSRQ:
  113. if ((g_EngOptions & DEBUG_ENGOPT_IGNORE_DBGHELP_VERSION) == 0 &&
  114. !g_QuietMode)
  115. {
  116. dprintf("*******************************************************************************\n");
  117. dprintf("* *\n");
  118. if (Status == DBG_STATUS_SYSRQ)
  119. {
  120. dprintf("* You are seeing this message because you pressed the SysRq/PrintScreen *\n");
  121. dprintf("* key on your test machine's keyboard. *\n");
  122. }
  123. if (Status == DBG_STATUS_DEBUG_CONTROL)
  124. {
  125. dprintf("* You are seeing this message because you typed in .breakin from ntsd. *\n");
  126. }
  127. if (Status == DBG_STATUS_CONTROL_C)
  128. {
  129. dprintf("* You are seeing this message because you pressed either *\n");
  130. dprintf("* CTRL+C (if you run kd.exe) or, *\n");
  131. dprintf("* CTRL+BREAK (if you run WinDBG), *\n");
  132. dprintf("* on your debugger machine's keyboard. *\n");
  133. }
  134. dprintf("* *\n");
  135. dprintf("* THIS IS NOT A BUG OR A SYSTEM CRASH *\n");
  136. dprintf("* *\n");
  137. dprintf("* If you did not intend to break into the debugger, press the \"g\" key, then *\n");
  138. dprintf("* press the \"Enter\" key now. This message might immediately reappear. If it *\n");
  139. dprintf("* does, press \"g\" and \"Enter\" again. *\n");
  140. dprintf("* *\n");
  141. dprintf("*******************************************************************************\n");
  142. }
  143. break;
  144. case DBG_STATUS_BUGCHECK_FIRST:
  145. ErrOut("\nA fatal system error has occurred.\n");
  146. ErrOut("Debugger entered on first try; "
  147. "Bugcheck callbacks have not been invoked.\n");
  148. // Fall through.
  149. case DBG_STATUS_BUGCHECK_SECOND:
  150. ErrOut("\nA fatal system error has occurred.\n\n");
  151. CallBugCheckExtension(NULL);
  152. break;
  153. case DBG_STATUS_FATAL:
  154. // hals call KeEnterDebugger when they panic.
  155. break;
  156. }
  157. }
  158. #define MAX_PROMPT 32
  159. HRESULT
  160. GetPromptText(PSTR Buffer, ULONG BufferSize, PULONG TextSize)
  161. {
  162. char Prompt[MAX_PROMPT];
  163. PSTR Text = Prompt;
  164. if (g_NumberTargets > 1)
  165. {
  166. *Text++ = '|';
  167. *Text++ = '|';
  168. if (g_Target)
  169. {
  170. sprintf(Text, "%1ld:", g_Target->m_UserId);
  171. Text += strlen(Text);
  172. }
  173. else
  174. {
  175. *Text++ = '?';
  176. *Text++ = ':';
  177. }
  178. }
  179. if (IS_LOCAL_KERNEL_TARGET(g_Target))
  180. {
  181. strcpy(Text, "lkd");
  182. Text += 3;
  183. }
  184. else if (IS_KERNEL_TARGET(g_Target))
  185. {
  186. if (g_X86InVm86)
  187. {
  188. strcpy(Text, "vm");
  189. Text += 2;
  190. }
  191. else if (g_X86InCode16)
  192. {
  193. strcpy(Text, "16");
  194. Text += 2;
  195. }
  196. else if (g_Target &&
  197. g_Target->m_MachineType == IMAGE_FILE_MACHINE_AMD64 &&
  198. !g_Amd64InCode64)
  199. {
  200. strcpy(Text, "32");
  201. Text += 2;
  202. }
  203. if (g_Target == NULL ||
  204. g_Process == NULL ||
  205. g_Thread == NULL ||
  206. ((IS_KERNEL_FULL_DUMP(g_Target) ||
  207. IS_KERNEL_SUMMARY_DUMP(g_Target)) &&
  208. g_Target->m_KdDebuggerData.KiProcessorBlock == 0))
  209. {
  210. strcpy(Text, "?: kd");
  211. Text += 5;
  212. }
  213. else if (g_Target->m_NumProcessors > 1)
  214. {
  215. sprintf(Text, "%d: kd", CURRENT_PROC);
  216. Text += strlen(Text);
  217. }
  218. else
  219. {
  220. strcpy(Text, "kd");
  221. Text += 2;
  222. }
  223. }
  224. else if (IS_USER_TARGET(g_Target))
  225. {
  226. if (g_Process)
  227. {
  228. sprintf(Text, "%1ld:", g_Process->m_UserId);
  229. Text += strlen(Text);
  230. }
  231. else
  232. {
  233. *Text++ = '?';
  234. *Text++ = ':';
  235. }
  236. if (g_Thread)
  237. {
  238. sprintf(Text, "%03ld", g_Thread->m_UserId);
  239. Text += strlen(Text);
  240. }
  241. else
  242. {
  243. strcpy(Text, "???");
  244. Text += 3;
  245. }
  246. }
  247. else
  248. {
  249. strcpy(Text, "NoTarget");
  250. Text += 8;
  251. }
  252. if (g_Machine && g_Target &&
  253. g_Machine->m_ExecTypes[0] != g_Target->m_MachineType)
  254. {
  255. *Text++ = ':';
  256. strcpy(Text, g_Machine->m_AbbrevName);
  257. Text += strlen(Text);
  258. }
  259. *Text++ = '>';
  260. *Text = 0;
  261. return FillStringBuffer(Prompt, (ULONG)(Text - Prompt) + 1,
  262. Buffer, BufferSize, TextSize);
  263. }
  264. void
  265. OutputPrompt(PCSTR Format, va_list Args)
  266. {
  267. char Prompt[MAX_PROMPT];
  268. GetPromptText(Prompt, sizeof(Prompt), NULL);
  269. g_PromptLength = strlen(Prompt);
  270. MaskOut(DEBUG_OUTPUT_PROMPT, "%s", Prompt);
  271. // Include space after >.
  272. g_PromptLength++;
  273. if (Format != NULL)
  274. {
  275. MaskOutVa(DEBUG_OUTPUT_PROMPT, Format, Args, TRUE);
  276. }
  277. }
  278. DWORD
  279. CommandExceptionFilter(PEXCEPTION_POINTERS Info)
  280. {
  281. if (Info->ExceptionRecord->ExceptionCode >=
  282. (COMMAND_EXCEPTION_BASE + OVERFLOW) &&
  283. Info->ExceptionRecord->ExceptionCode
  284. <= (COMMAND_EXCEPTION_BASE + UNIMPLEMENT))
  285. {
  286. // This is a legitimate command error code exception.
  287. return EXCEPTION_EXECUTE_HANDLER;
  288. }
  289. else
  290. {
  291. // This is some other exception that the command
  292. // filter isn't supposed to handle.
  293. ErrOut("Non-command exception %X at %s in command filter\n",
  294. Info->ExceptionRecord->ExceptionCode,
  295. FormatAddr64((ULONG64)Info->ExceptionRecord->ExceptionAddress));
  296. return EXCEPTION_CONTINUE_SEARCH;
  297. }
  298. }
  299. void
  300. ParseLoadModules(void)
  301. {
  302. ImageInfo* Image;
  303. PSTR Pattern;
  304. CHAR Save;
  305. BOOL AnyMatched = FALSE;
  306. if (!g_Process)
  307. {
  308. error(BADPROCESS);
  309. }
  310. Pattern =
  311. StringValue(STRV_SPACE_IS_SEPARATOR | STRV_TRIM_TRAILING_SPACE |
  312. STRV_ESCAPED_CHARACTERS, &Save);
  313. _strupr(Pattern);
  314. for (Image = g_Process->m_ImageHead; Image; Image = Image->m_Next)
  315. {
  316. if (MatchPattern(Image->m_ModuleName, Pattern))
  317. {
  318. IMAGEHLP_MODULE64 ModInfo;
  319. AnyMatched = TRUE;
  320. ModInfo.SizeOfStruct = sizeof(ModInfo);
  321. if (!SymGetModuleInfo64(g_Process->m_SymHandle,
  322. Image->m_BaseOfImage, &ModInfo) ||
  323. ModInfo.SymType == SymDeferred)
  324. {
  325. if (!SymLoadModule64(g_Process->m_SymHandle,
  326. NULL, NULL, NULL,
  327. Image->m_BaseOfImage, 0))
  328. {
  329. ErrOut("Symbol load for %s failed\n", Image->m_ModuleName);
  330. }
  331. else
  332. {
  333. dprintf("Symbols loaded for %s\n", Image->m_ModuleName);
  334. }
  335. }
  336. else
  337. {
  338. dprintf("Symbols already loaded for %s\n",
  339. Image->m_ModuleName);
  340. }
  341. }
  342. if (CheckUserInterrupt())
  343. {
  344. break;
  345. }
  346. }
  347. if (!AnyMatched)
  348. {
  349. WarnOut("No modules matched '%s'\n", Pattern);
  350. }
  351. *g_CurCmd = Save;
  352. }
  353. void
  354. ParseProcessorCommands(void)
  355. {
  356. ULONG Proc;
  357. PSTR Start = g_CurCmd;
  358. if (!g_Target)
  359. {
  360. error(BADSYSTEM);
  361. }
  362. Proc = 0;
  363. while (*g_CurCmd >= '0' && *g_CurCmd <= '9')
  364. {
  365. Proc = Proc * 10 + (*g_CurCmd - '0');
  366. g_CurCmd++;
  367. }
  368. if (Start == g_CurCmd)
  369. {
  370. // No digits.
  371. error(SYNTAX);
  372. }
  373. if (*g_CurCmd == 's')
  374. {
  375. g_CurCmd++;
  376. }
  377. if (Proc < g_Target->m_NumProcessors)
  378. {
  379. if (Proc != g_Target->m_RegContextProcessor)
  380. {
  381. if (g_Target->SwitchProcessors(Proc) == S_OK)
  382. {
  383. ResetCurrentScope();
  384. }
  385. }
  386. }
  387. else
  388. {
  389. ErrOut("%d is not a valid processor number\n", Proc);
  390. }
  391. }
  392. void
  393. SetSuffix(void)
  394. {
  395. char Ch;
  396. Ch = PeekChar();
  397. Ch = (UCHAR)tolower(Ch);
  398. if (Ch == ';' || Ch == '\0')
  399. {
  400. if (g_SymbolSuffix == 'n')
  401. {
  402. dprintf("n - no suffix\n");
  403. }
  404. else if (g_SymbolSuffix == 'a')
  405. {
  406. dprintf("a - ascii\n");
  407. }
  408. else
  409. {
  410. dprintf("w - wide\n");
  411. }
  412. }
  413. else if (Ch == 'n' || Ch == 'a' || Ch == 'w')
  414. {
  415. g_SymbolSuffix = Ch;
  416. g_CurCmd++;
  417. }
  418. else
  419. {
  420. error(SYNTAX);
  421. }
  422. }
  423. void
  424. OutputVersionInformation(DebugClient* Client)
  425. {
  426. DBH_DIAVERSION DiaVer;
  427. //
  428. // Print out the connection options if we are doing live debugging.
  429. //
  430. if (g_Target)
  431. {
  432. char Buf[2 * MAX_PATH];
  433. g_Target->GetDescription(Buf, sizeof(Buf), NULL);
  434. dprintf("%s\n", Buf);
  435. }
  436. dprintf("command line: '%s' Debugger Process 0x%X \n",
  437. GetCommandLine(), GetCurrentProcessId());
  438. dprintf(ENGINE_MOD_NAME ": ");
  439. OutputModuleIdInfo(NULL, ENGINE_DLL_NAME, NULL);
  440. CheckForStaleBinary(ENGINE_DLL_NAME, TRUE);
  441. dprintf("dbghelp: ");
  442. OutputModuleIdInfo(NULL, "dbghelp.dll", NULL);
  443. DiaVer.function = dbhDiaVersion;
  444. DiaVer.sizeofstruct = sizeof(DiaVer);
  445. if (dbghelp(NULL, &DiaVer))
  446. {
  447. dprintf(" DIA version: %d\n", DiaVer.ver);
  448. }
  449. // Dump information about the IA64 support DLLs if they're
  450. // loaded. Don't bother forcing them to load.
  451. if (GetModuleHandle("decem.dll") != NULL)
  452. {
  453. dprintf("decem: ");
  454. OutputModuleIdInfo(NULL, "decem.dll", NULL);
  455. }
  456. OutputExtensions(Client, TRUE);
  457. if (g_Wow64exts != NULL)
  458. {
  459. dprintf("WOW64 extensions loaded\n");
  460. }
  461. }
  462. void
  463. ParseStackTrace(PULONG TraceFlags,
  464. PULONG64 Frame,
  465. PULONG64 Stack,
  466. PULONG64 Instr,
  467. PULONG Count,
  468. PULONG PtrDef)
  469. {
  470. char Ch;
  471. ADDR Addr;
  472. Ch = PeekChar();
  473. *TraceFlags =
  474. DEBUG_STACK_COLUMN_NAMES |
  475. DEBUG_STACK_FRAME_ADDRESSES |
  476. DEBUG_STACK_SOURCE_LINE;
  477. if (tolower(Ch) == 'b')
  478. {
  479. g_CurCmd++;
  480. *TraceFlags |= DEBUG_STACK_ARGUMENTS;
  481. }
  482. else if (tolower(Ch) == 'v')
  483. {
  484. g_CurCmd++;
  485. *TraceFlags |=
  486. DEBUG_STACK_ARGUMENTS |
  487. DEBUG_STACK_FUNCTION_INFO |
  488. DEBUG_STACK_NONVOLATILE_REGISTERS;
  489. }
  490. else if (tolower(Ch) == 'd')
  491. {
  492. g_CurCmd++;
  493. *TraceFlags = RAW_STACK_DUMP;
  494. }
  495. else if (tolower(Ch) == 'p')
  496. {
  497. g_CurCmd++;
  498. *TraceFlags |= DEBUG_STACK_PARAMETERS;
  499. }
  500. Ch = PeekChar();
  501. if (tolower(Ch) == 'n')
  502. {
  503. if (*TraceFlags == RAW_STACK_DUMP)
  504. {
  505. error(SYNTAX);
  506. }
  507. g_CurCmd++;
  508. Ch = PeekChar();
  509. *TraceFlags |= DEBUG_STACK_FRAME_NUMBERS;
  510. }
  511. if (tolower(Ch) == 'f')
  512. {
  513. if (*TraceFlags == RAW_STACK_DUMP)
  514. {
  515. error(SYNTAX);
  516. }
  517. g_CurCmd++;
  518. Ch = PeekChar();
  519. *TraceFlags |= DEBUG_STACK_FRAME_MEMORY_USAGE;
  520. }
  521. if (Ch == 'L')
  522. {
  523. if (*TraceFlags == RAW_STACK_DUMP)
  524. {
  525. error(SYNTAX);
  526. }
  527. g_CurCmd++;
  528. Ch = PeekChar();
  529. *TraceFlags &= ~DEBUG_STACK_SOURCE_LINE;
  530. }
  531. if (!PeekChar() && GetCurrentScopeContext())
  532. {
  533. dprintf(" *** Stack trace for last set context - "
  534. ".thread/.cxr resets it\n");
  535. }
  536. *PtrDef = STACK_ALL_DEFAULT;
  537. *Frame = 0;
  538. *Stack = 0;
  539. *Instr = 0;
  540. if (g_Machine->m_ExecTypes[0] == IMAGE_FILE_MACHINE_I386)
  541. {
  542. *Instr = g_Machine->GetReg64(X86_EIP);
  543. *PtrDef &= ~STACK_INSTR_DEFAULT;
  544. }
  545. if (PeekChar() == '=')
  546. {
  547. g_CurCmd++;
  548. GetAddrExpression(SEGREG_STACK, &Addr);
  549. *Frame = Flat(Addr);
  550. *PtrDef &= ~STACK_FRAME_DEFAULT;
  551. }
  552. else if (g_Machine->m_ExecTypes[0] == IMAGE_FILE_MACHINE_I386)
  553. {
  554. g_Machine->GetFP(&Addr);
  555. *Frame = Flat(Addr);
  556. *PtrDef &= ~STACK_FRAME_DEFAULT;
  557. }
  558. *Count = g_DefaultStackTraceDepth;
  559. if (g_Machine->m_ExecTypes[0] == IMAGE_FILE_MACHINE_I386 &&
  560. (Ch = PeekChar()) != '\0' && Ch != ';')
  561. {
  562. //
  563. // If only one more value it's the count
  564. //
  565. *Count = (ULONG)GetExpression();
  566. if ((Ch = PeekChar()) != '\0' && Ch != ';')
  567. {
  568. //
  569. // More than one value, set extra value for special
  570. // FPO backtrace.
  571. //
  572. *Instr = GetExpression();
  573. *Stack = EXTEND64(*Count);
  574. *PtrDef &= ~(STACK_INSTR_DEFAULT | STACK_STACK_DEFAULT);
  575. *Count = g_DefaultStackTraceDepth;
  576. }
  577. }
  578. if ((Ch = PeekChar()) != '\0' && Ch != ';')
  579. {
  580. *Count = (ULONG)GetExpression();
  581. if ((LONG)*Count < 1)
  582. {
  583. g_CurCmd++;
  584. error(SYNTAX);
  585. }
  586. }
  587. if (*Count >= 0x10000)
  588. {
  589. ErrOut("Requested number of stack frames (0x%x) is too large! "
  590. "The maximum number is 0xffff.\n", *Count);
  591. error(BADRANGE);
  592. }
  593. }
  594. void
  595. CmdHelp(void)
  596. {
  597. char Buf[16];
  598. // Commands available on all platforms and in all modes.
  599. dprintf("\nOpen debugger.chm for complete debugger documentation\n\n");
  600. dprintf("A [<address>] - assemble\n");
  601. dprintf("BC[<bp>] - clear breakpoint(s)\n");
  602. dprintf("BD[<bp>] - disable breakpoint(s)\n");
  603. dprintf("BE[<bp>] - enable breakpoint(s)\n");
  604. dprintf("BL - list breakpoints\n");
  605. dprintf("[thread]BP[#] <address> - set breakpoint\n");
  606. dprintf("C <range> <address> [passes] [command] - compare\n");
  607. dprintf("D[type][<range>] - dump memory\n");
  608. dprintf("DL[B] <address> <maxcount> <size> - dump linked list\n");
  609. dprintf("#[processor] DT [-n|y] [[mod!]name] [[-n|y]fields]\n");
  610. dprintf(" [address] [-l list] [-a[]|c|i|o|r[#]|v] - \n");
  611. dprintf(" dump using type information\n");
  612. dprintf("E[type] <address> [<list>] - enter\n");
  613. dprintf("F <range> <list> - fill\n");
  614. dprintf("[thread]G [=<address> [<address>...]] - go\n");
  615. dprintf("[thread]GH [=<address> [<address>...]] - "
  616. "go with exception handled\n");
  617. dprintf("[thread]GN [=<address> [<address>...]] - "
  618. "go with exception not handled\n");
  619. dprintf("J<expr> [']cmd1['];[']cmd2['] - conditional execution\n");
  620. dprintf("[thread|processor]K[B] <count> - stacktrace\n");
  621. dprintf("KD [<count>] - stack trace with raw data\n");
  622. dprintf("[thread|processor] KV [ <count> | =<reg> ] - "
  623. "stacktrace with FPO data\n");
  624. dprintf("L{+|-}[l|o|s|t|*] - Control source options\n");
  625. dprintf("LD [<module>] - refresh module information\n");
  626. dprintf("LM[k|l|u|v] - list modules\n");
  627. dprintf("LN <expr> - list nearest symbols\n");
  628. dprintf("LS[.] [<first>][,<count>] - List source file lines\n");
  629. dprintf("LSA <addr>[,<first>][,<count>] - "
  630. "List source file lines at addr\n");
  631. dprintf("LSC - Show current source file and line\n");
  632. dprintf("LSF[-] <file> - Load or unload a source file for browsing\n");
  633. dprintf("M <range> <address> - move\n");
  634. dprintf("N [<radix>] - set / show radix\n");
  635. dprintf("[thread]P[R] [=<addr>] [<value>] - program step\n");
  636. dprintf("Q - quit\n");
  637. dprintf("\n");
  638. GetInput("Hit Enter...", Buf, DIMA(Buf) - 1, GETIN_DEFAULT);
  639. dprintf("\n");
  640. dprintf("[thread|processor]R[F][L][M <expr>] [[<reg> [= <expr>]]] - "
  641. "reg/flag\n");
  642. dprintf("Rm[?] [<expr>] - Control prompt register output mask\n");
  643. dprintf("S <range> <list> - search\n");
  644. dprintf("SQ[e|d] - set quiet mode\n");
  645. dprintf("SS <n | a | w> - set symbol suffix\n");
  646. dprintf("SX [{e|d|i|n} [-c \"Cmd1\"] [-c2 \"Cmd2\"] [-h] "
  647. "{Exception|Event|*}] - event filter\n");
  648. dprintf("[thread]T[R] [=<address>] [<expr>] - trace\n");
  649. dprintf("U [<range>] - unassemble\n");
  650. dprintf("vercommand - show the debuggee command line\n");
  651. dprintf("version - show debuggee and debugger version\n");
  652. dprintf("vertarget - show debuggee version\n");
  653. dprintf("X [<*|module>!]<*|symbol> - view symbols\n");
  654. dprintf("<commands>; [processor] z(<expression>) - do while true\n");
  655. dprintf("~ - list threads status\n");
  656. dprintf("~#s - set default thread\n");
  657. dprintf("~[.|#|*|ddd]f - freeze thread\n");
  658. dprintf("~[.|#|*|ddd]u - unfreeze thread\n");
  659. dprintf("~[.|#|ddd]k[expr] - backtrace stack\n");
  660. dprintf("| - list processes status\n");
  661. dprintf("|#s - set default process\n");
  662. dprintf("|#<command> - default process override\n");
  663. dprintf("? <expr> - display expression\n");
  664. dprintf("? - command help\n");
  665. dprintf("#<string> [address] - search for a string in the dissasembly\n");
  666. dprintf("$< <filename> - take input from a command file\n");
  667. dprintf("<Enter> - repeat previous command\n");
  668. dprintf("; - command separator\n");
  669. dprintf("*|$ - comment mark\n");
  670. dprintf("\n");
  671. GetInput("Hit Enter...", Buf, DIMA(Buf) - 1, GETIN_DEFAULT);
  672. dprintf("\n");
  673. dprintf("<expr> unary ops: + - not by wo dwo qwo poi hi low\n");
  674. dprintf(" binary ops: + - * / mod(%%) and(&) xor(^) or(|)\n");
  675. dprintf(" comparisons: == (=) < > !=\n");
  676. dprintf(" operands: number in current radix, "
  677. "public symbol, <reg>\n");
  678. dprintf("<type> : b (byte), w (word), d[s] "
  679. "(doubleword [with symbols]),\n");
  680. dprintf(" a (ascii), c (dword and Char), u (unicode), l (list)\n");
  681. dprintf(" f (float), D (double), s|S (ascii/unicode string)\n");
  682. dprintf(" q (quadword)\n");
  683. dprintf("<pattern> : [(nt | <dll-name>)!]<var-name> "
  684. "(<var-name> can include ? and *)\n");
  685. dprintf("<event> : ct, et, ld, av, cc "
  686. "(see documentation for full list)\n");
  687. dprintf("<radix> : 8, 10, 16\n");
  688. dprintf("<reg> : $u0-$u9, $ea, $exp, $ra, $p\n");
  689. dprintf("<addr> : %%<32-bit address>\n");
  690. dprintf("<range> : <address> <address>\n");
  691. dprintf(" : <address> L <count>\n");
  692. dprintf("<list> : <byte> [<byte> ...]\n");
  693. if (IS_KERNEL_TARGET(g_Target))
  694. {
  695. dprintf("\n");
  696. dprintf("Kernel-mode options:\n");
  697. dprintf("~<processor>s - change current processor\n");
  698. dprintf("I<b|w|d> <port> - read I/O port\n");
  699. dprintf("O<b|w|d> <port> <expr> - write I/O\n");
  700. dprintf("RDMSR <MSR> - read MSR\n");
  701. dprintf("SO [<options>] - set kernel debugging options\n");
  702. dprintf("UX [<address>] - disassemble X86 BIOS code\n");
  703. dprintf("WRMSR <MSR> - write MSR\n");
  704. dprintf(".cache [size] - set vmem cache size\n");
  705. dprintf(".reboot - reboot target machine\n");
  706. }
  707. switch(g_Machine->m_ExecTypes[0])
  708. {
  709. case IMAGE_FILE_MACHINE_I386:
  710. dprintf("\n");
  711. dprintf("x86 options:\n");
  712. dprintf("BA[#] <e|r|w|i><1|2|4> <addr> - addr bp\n");
  713. dprintf("DG <selector> - dump selector\n");
  714. dprintf("KB = <base> <stack> <ip> - stacktrace from specific state\n");
  715. dprintf("<reg> : [e]ax, [e]bx, [e]cx, [e]dx, [e]si, [e]di, "
  716. "[e]bp, [e]sp, [e]ip, [e]fl,\n");
  717. dprintf(" al, ah, bl, bh, cl, ch, dl, dh, "
  718. "cs, ds, es, fs, gs, ss\n");
  719. dprintf(" dr0, dr1, dr2, dr3, dr6, dr7\n");
  720. if (IS_KERNEL_TARGET(g_Target))
  721. {
  722. dprintf(" cr0, cr2, cr3, cr4\n");
  723. dprintf(" gdtr, gdtl, idtr, idtl, tr, ldtr\n");
  724. }
  725. else
  726. {
  727. dprintf(" fpcw, fpsw, fptw, st0-st7, mm0-mm7\n");
  728. }
  729. dprintf(" xmm0-xmm7\n");
  730. dprintf("<flag> : iopl, of, df, if, tf, sf, zf, af, pf, cf\n");
  731. dprintf("<addr> : #<16-bit protect-mode [seg:]address>,\n");
  732. dprintf(" &<V86-mode [seg:]address>\n");
  733. break;
  734. case IMAGE_FILE_MACHINE_IA64:
  735. dprintf("\n");
  736. dprintf("IA64 options:\n");
  737. dprintf("BA[#] <r|w><1|2|4|8> <addr> - addr bp\n");
  738. dprintf("<reg> : r2-r31, f2-f127, gp, sp, intnats, preds, brrp, brs0-brs4, brt0, brt1,\n");
  739. dprintf(" dbi0-dbi7, dbd0-dbd7, kpfc0-kpfc7, kpfd0-kpfd7, h16-h31, unat, lc, ec,\n");
  740. dprintf(" ccv, dcr, pfs, bsp, bspstore, rsc, rnat, ipsr, iip, ifs, kr0-kr7, itc,\n");
  741. dprintf(" itm, iva, pta, isr, ifa, itir, iipa, iim, iha, lid, ivr, tpr, eoi,\n");
  742. dprintf(" irr0-irr3, itv, pmv, lrr0, lrr1, cmcv, rr0-rr7, pkr0-pkr15, tri0-tri7,\n");
  743. dprintf(" trd0-trd7\n");
  744. break;
  745. case IMAGE_FILE_MACHINE_AMD64:
  746. dprintf("\n");
  747. dprintf("x86-64 options:\n");
  748. dprintf("BA[#] <e|r|w|i><1|2|4> <addr> - addr bp\n");
  749. dprintf("DG <selector> - dump selector\n");
  750. dprintf("KB = <base> <stack> <ip> - stacktrace from specific state\n");
  751. dprintf("<reg> : [r|e]ax, [r|e]bx, [r|e]cx, [r|e]dx, [r|e]si, [r|e]di, "
  752. "[r|e]bp, [r|e]sp, [r|e]ip, [e]fl,\n");
  753. dprintf(" r8-r15 with b/w/d subregisters\n");
  754. dprintf(" al, ah, bl, bh, cl, ch, dl, dh, "
  755. "cs, ds, es, fs, gs, ss\n");
  756. dprintf(" sil, dil, bpl, spl\n");
  757. dprintf(" dr0, dr1, dr2, dr3, dr6, dr7\n");
  758. if (IS_KERNEL_TARGET(g_Target))
  759. {
  760. dprintf(" cr0, cr2, cr3, cr4\n");
  761. dprintf(" gdtr, gdtl, idtr, idtl, tr, ldtr\n");
  762. }
  763. else
  764. {
  765. dprintf(" fpcw, fpsw, fptw, st0-st7, mm0-mm7\n");
  766. }
  767. dprintf(" xmm0-xmm15\n");
  768. dprintf("<flag> : iopl, of, df, if, tf, sf, zf, af, pf, cf\n");
  769. dprintf("<addr> : #<16-bit protect-mode [seg:]address>,\n");
  770. dprintf(" &<V86-mode [seg:]address>\n");
  771. break;
  772. }
  773. dprintf("\nOpen debugger.chm for complete debugger documentation\n\n");
  774. }
  775. /*** ProcessCommands - high-level command processor
  776. *
  777. * Purpose:
  778. * If no command string remains, the user is prompted to
  779. * input one. Once input, this routine parses the string
  780. * into commands and their operands. Error checking is done
  781. * on both commands and operands. Multiple commands may be
  782. * input by separating them with semicolons. Once a command
  783. * is parsefd, the appropriate routine (type fnXXXXX) is called
  784. * to execute the command.
  785. *
  786. * Input:
  787. * g_CurCmd = pointer to the next command in the string
  788. *
  789. * Output:
  790. * None.
  791. *
  792. * Exceptions:
  793. * error exit: SYNTAX - command type or operand error
  794. * normal exit: termination on 'q' command
  795. *
  796. *************************************************************************/
  797. HRESULT
  798. ProcessCommands(DebugClient* Client, BOOL Nested)
  799. {
  800. char Ch;
  801. ADDR Addr1;
  802. ADDR Addr2;
  803. ULONG64 Value1;
  804. ULONG64 Value2;
  805. ULONG Count;
  806. PSTR SavedCurCmd;
  807. ProcessInfo* ProcessPrevious = NULL;
  808. BOOL ParseProcess = FALSE;
  809. HRESULT Status = S_FALSE;
  810. PCROSS_PLATFORM_CONTEXT ScopeContext;
  811. DEBUG_SCOPE_STATE SaveCurrCtxtState;
  812. ContextSave* PushContext;
  813. PSTR Scan, Start;
  814. if (g_Process == NULL ||
  815. g_Thread == NULL)
  816. {
  817. WarnOut("WARNING: The debugger does not have a current "
  818. "process or thread\n");
  819. WarnOut("WARNING: Many commands will not work\n");
  820. }
  821. if (!Nested)
  822. {
  823. g_SwitchedProcs = FALSE;
  824. }
  825. do
  826. {
  827. Ch = *g_CurCmd++;
  828. if (Ch == '\0' ||
  829. (Ch == ';' && (g_EngStatus & ENG_STATUS_USER_INTERRUPT)))
  830. {
  831. if (!Nested)
  832. {
  833. g_EngStatus &= ~ENG_STATUS_USER_INTERRUPT;
  834. g_BreakpointsSuspended = FALSE;
  835. }
  836. Status = S_OK;
  837. // Back up to terminating character in
  838. // case command processing is reentered without
  839. // resetting things.
  840. g_CurCmd--;
  841. break;
  842. }
  843. EVALUATE:
  844. while (Ch == ' ' || Ch == '\t' || Ch == '\r' || Ch == '\n' ||
  845. Ch == ';')
  846. {
  847. Ch = *g_CurCmd++;
  848. }
  849. if (IS_KERNEL_TARGET(g_Target))
  850. {
  851. if (g_Target &&
  852. g_Target->m_NumProcessors > MAXIMUM_PROCS)
  853. {
  854. WarnOut("WARNING: Number of processors corrupted - using 1\n");
  855. g_Target->m_NumProcessors = 1;
  856. }
  857. if (Ch >= '0' && Ch <= '9')
  858. {
  859. if (IS_KERNEL_TRIAGE_DUMP(g_Target))
  860. {
  861. ErrOut("Can't switch processors on a Triage dump\n");
  862. error(SYNTAX);
  863. }
  864. Value1 = 0;
  865. SavedCurCmd = g_CurCmd;
  866. while (Ch >= '0' && Ch <= '9')
  867. {
  868. Value1 = Value1 * 10 + (Ch - '0');
  869. Ch = *SavedCurCmd++;
  870. }
  871. Ch = (char)tolower(Ch);
  872. if (Ch == 'r' || Ch == 'k' || Ch == 'z' ||
  873. (Ch == 'd' && tolower(*SavedCurCmd) == 't'))
  874. {
  875. if (g_Target && Value1 < g_Target->m_NumProcessors)
  876. {
  877. if (Value1 != g_Target->m_RegContextProcessor)
  878. {
  879. SaveSetCurrentProcessorThread(g_Target,
  880. (ULONG)Value1);
  881. g_SwitchedProcs = TRUE;
  882. }
  883. }
  884. else
  885. {
  886. error(BADRANGE);
  887. }
  888. }
  889. else
  890. {
  891. error(SYNTAX);
  892. }
  893. g_CurCmd = SavedCurCmd;
  894. }
  895. }
  896. g_PrefixSymbols = FALSE;
  897. switch (Ch = (char)tolower(Ch))
  898. {
  899. case '?':
  900. if ((Ch = PeekChar()) == '\0' || Ch == ';')
  901. {
  902. CmdHelp();
  903. }
  904. else if (*g_CurCmd == '?')
  905. {
  906. TypedData Result;
  907. EvalExpression* Eval;
  908. g_CurCmd++;
  909. Eval = GetEvaluator(DEBUG_EXPR_CPLUSPLUS, FALSE);
  910. Eval->EvalCurrent(&Result);
  911. ReleaseEvaluator(Eval);
  912. Result.OutputTypeAndValue();
  913. }
  914. else
  915. {
  916. DotFormats(NULL, Client);
  917. }
  918. break;
  919. case '$':
  920. if ( *g_CurCmd++ == '<')
  921. {
  922. if ((Status =
  923. ExecuteCommandFile(Client, (PCSTR)g_CurCmd,
  924. DEBUG_EXECUTE_ECHO)) != S_OK)
  925. {
  926. ErrOut("Command file execution failed, %s\n "
  927. "\"%s\"\n", FormatStatusCode(Status),
  928. FormatStatus(Status));
  929. }
  930. }
  931. *g_CurCmd = 0;
  932. break;
  933. case '~':
  934. if (IS_USER_TARGET(g_Target))
  935. {
  936. if (Nested)
  937. {
  938. ErrOut("Ignoring recursive thread command\n");
  939. break;
  940. }
  941. ParseThreadCmds(Client);
  942. }
  943. else
  944. {
  945. ParseProcessorCommands();
  946. }
  947. break;
  948. case '|':
  949. if (*g_CurCmd == '|')
  950. {
  951. g_CurCmd++;
  952. ParseSystemCommands();
  953. break;
  954. }
  955. if (IS_KERNEL_TARGET(g_Target))
  956. {
  957. break;
  958. }
  959. if (!ParseProcess)
  960. {
  961. ParseProcess = TRUE;
  962. ProcessPrevious = g_Process;
  963. }
  964. ParseProcessCmds();
  965. if (!*g_CurCmd)
  966. {
  967. ParseProcess = FALSE;
  968. }
  969. else
  970. {
  971. Ch = *g_CurCmd++;
  972. goto EVALUATE;
  973. }
  974. break;
  975. case '.':
  976. SavedCurCmd = g_CurCmd;
  977. if (!DotCommand(Client, FALSE))
  978. {
  979. g_CurCmd = SavedCurCmd;
  980. ParseBangCmd(Client, TRUE);
  981. }
  982. break;
  983. case '!':
  984. SavedCurCmd = g_CurCmd;
  985. if (!DotCommand(Client, TRUE))
  986. {
  987. g_CurCmd = SavedCurCmd;
  988. ParseBangCmd(Client, FALSE);
  989. }
  990. break;
  991. case '*':
  992. while (*g_CurCmd != '\0')
  993. {
  994. g_CurCmd++;
  995. }
  996. break;
  997. case '#':
  998. ParseInstrGrep();
  999. break;
  1000. case 'a':
  1001. //
  1002. // Alias command or just default to pre-existing
  1003. // assemble command.
  1004. //
  1005. Ch = *g_CurCmd++;
  1006. switch (tolower(Ch))
  1007. {
  1008. // Alias list
  1009. case 'l':
  1010. ListAliases();
  1011. break;
  1012. // Alias set
  1013. case 's':
  1014. ParseSetAlias();
  1015. break;
  1016. // Alias delete
  1017. case 'd':
  1018. ParseDeleteAlias();
  1019. break;
  1020. // Pre-existing assemble command
  1021. default:
  1022. g_CurCmd--;
  1023. ParseAssemble();
  1024. break;
  1025. }
  1026. break;
  1027. case 'b':
  1028. Ch = *g_CurCmd++;
  1029. Ch = (char)tolower(Ch);
  1030. if (!g_Target || !g_Target->m_DynamicEvents)
  1031. {
  1032. error(TARGETNOTSUP);
  1033. }
  1034. switch(Ch)
  1035. {
  1036. case 'p':
  1037. case 'u':
  1038. case 'a':
  1039. case 'i':
  1040. case 'w':
  1041. case 'm':
  1042. ParseBpCmd(Client, Ch, NULL);
  1043. break;
  1044. case 'c':
  1045. case 'd':
  1046. case 'e':
  1047. Value1 = GetIdList(TRUE);
  1048. ChangeBreakpointState(Client, g_Process,
  1049. (ULONG)Value1, Ch);
  1050. break;
  1051. case 'l':
  1052. if (PeekChar() != ';' && *g_CurCmd)
  1053. {
  1054. Value1 = GetIdList(TRUE);
  1055. }
  1056. else
  1057. {
  1058. Value1 = ALL_ID_LIST;
  1059. }
  1060. ListBreakpoints(Client, g_Process, (ULONG)Value1);
  1061. break;
  1062. default:
  1063. error(SYNTAX);
  1064. break;
  1065. }
  1066. break;
  1067. case 'c':
  1068. GetRange(&Addr1, &Value2, 1, SEGREG_DATA,
  1069. DEFAULT_RANGE_LIMIT);
  1070. GetAddrExpression(SEGREG_DATA, &Addr2);
  1071. CompareTargetMemory(&Addr1, (ULONG)Value2, &Addr2);
  1072. break;
  1073. case 'd':
  1074. ParseDumpCommand();
  1075. break;
  1076. case 'e':
  1077. ParseEnterCommand();
  1078. break;
  1079. case 'f':
  1080. ParseFillMemory();
  1081. break;
  1082. case 'g':
  1083. ParseGoCmd(NULL, FALSE);
  1084. break;
  1085. case 'i':
  1086. Ch = (char)tolower(*g_CurCmd);
  1087. g_CurCmd++;
  1088. if (Ch != 'b' && Ch != 'w' && Ch != 'd')
  1089. {
  1090. error(SYNTAX);
  1091. }
  1092. if (IS_USER_TARGET(g_Target) || IS_DUMP_TARGET(g_Target))
  1093. {
  1094. error(SESSIONNOTSUP);
  1095. }
  1096. InputIo((ULONG)GetExpression(), Ch);
  1097. break;
  1098. case 'j':
  1099. if (GetExpression())
  1100. {
  1101. Scan = g_CurCmd;
  1102. // Find a semicolon or a quote
  1103. while (*Scan && *Scan != ';' && *Scan != '\'')
  1104. {
  1105. Scan++;
  1106. }
  1107. if (*Scan == ';')
  1108. {
  1109. *Scan = 0;
  1110. }
  1111. else if (*Scan)
  1112. {
  1113. *Scan = ' ';
  1114. // Find the closing quote
  1115. while (*Scan && *Scan != '\'')
  1116. {
  1117. Scan++;
  1118. }
  1119. *Scan = 0;
  1120. }
  1121. }
  1122. else
  1123. {
  1124. Start = Scan = g_CurCmd;
  1125. // Find a semicolon or a quote
  1126. while (*Scan && *Scan != ';' && *Scan != '\'')
  1127. {
  1128. Scan++;
  1129. }
  1130. if (*Scan == ';')
  1131. {
  1132. Start = ++Scan;
  1133. }
  1134. else if (*Scan)
  1135. {
  1136. Scan++;
  1137. while (*Scan && *Scan++ != '\'')
  1138. {
  1139. // Empty.
  1140. }
  1141. while (*Scan && (*Scan == ';' || *Scan == ' '))
  1142. {
  1143. Scan++;
  1144. }
  1145. Start = Scan;
  1146. }
  1147. while (*Scan && *Scan != ';' && *Scan != '\'')
  1148. {
  1149. Scan++;
  1150. }
  1151. if (*Scan == ';')
  1152. {
  1153. *Scan = 0;
  1154. }
  1155. else if (*Scan)
  1156. {
  1157. *Scan = ' ';
  1158. // Find the closing quote
  1159. while (*Scan && *Scan != '\'')
  1160. {
  1161. Scan++;
  1162. }
  1163. *Scan = 0;
  1164. }
  1165. g_CurCmd = Start;
  1166. }
  1167. Ch = *g_CurCmd++;
  1168. goto EVALUATE;
  1169. case 'k':
  1170. if (IS_LOCAL_KERNEL_TARGET(g_Target))
  1171. {
  1172. error(SESSIONNOTSUP);
  1173. }
  1174. if (!IS_CUR_CONTEXT_ACCESSIBLE())
  1175. {
  1176. error(BADTHREAD);
  1177. }
  1178. SaveCurrCtxtState = g_ScopeBuffer.State;
  1179. if (g_SwitchedProcs)
  1180. {
  1181. g_ScopeBuffer.State = ScopeDefault;
  1182. }
  1183. if (ScopeContext = GetCurrentScopeContext())
  1184. {
  1185. PushContext = g_Machine->PushContext(ScopeContext);
  1186. }
  1187. __try
  1188. {
  1189. ULONG64 Frame, Stack, Instr;
  1190. ULONG PtrDef;
  1191. ULONG TraceFlags;
  1192. Count = g_DefaultStackTraceDepth;
  1193. ParseStackTrace(&TraceFlags, &Frame, &Stack, &Instr,
  1194. &Count, &PtrDef);
  1195. DoStackTrace(Client, Frame, Stack, Instr, PtrDef,
  1196. Count, TraceFlags);
  1197. }
  1198. __except(CommandExceptionFilter(GetExceptionInformation()))
  1199. {
  1200. // Stop command processing.
  1201. *g_CurCmd = 0;
  1202. }
  1203. if (ScopeContext)
  1204. {
  1205. g_Machine->PopContext(PushContext);
  1206. }
  1207. if (g_SwitchedProcs)
  1208. {
  1209. RestoreCurrentProcessorThread(g_Target);
  1210. g_SwitchedProcs = FALSE;
  1211. g_ScopeBuffer.State = SaveCurrCtxtState;
  1212. }
  1213. break;
  1214. case 'l':
  1215. Ch = (char)tolower(*g_CurCmd);
  1216. if (Ch == 'n')
  1217. {
  1218. g_CurCmd++;
  1219. if (!g_Machine || !g_Process)
  1220. {
  1221. error(BADTHREAD);
  1222. }
  1223. if ((Ch = PeekChar()) != '\0' && Ch != ';')
  1224. {
  1225. GetAddrExpression(SEGREG_CODE, &Addr1);
  1226. }
  1227. else
  1228. {
  1229. ScopeContext = GetCurrentScopeContext();
  1230. if (ScopeContext)
  1231. {
  1232. PushContext = g_Machine->PushContext(ScopeContext);
  1233. }
  1234. g_Machine->GetPC(&Addr1);
  1235. if (ScopeContext)
  1236. {
  1237. g_Machine->PopContext(PushContext);
  1238. }
  1239. }
  1240. ListNearSymbols(Flat(Addr1));
  1241. }
  1242. else if (Ch == '+' || Ch == '-')
  1243. {
  1244. g_CurCmd++;
  1245. ParseSrcOptCmd(Ch);
  1246. }
  1247. else if (Ch == 's')
  1248. {
  1249. g_CurCmd++;
  1250. Ch = (char)tolower(*g_CurCmd);
  1251. if (Ch == 'f')
  1252. {
  1253. g_CurCmd++;
  1254. ParseSrcLoadCmd();
  1255. }
  1256. else if (Ch == 'p')
  1257. {
  1258. g_CurCmd++;
  1259. ParseOciSrcCmd();
  1260. }
  1261. else
  1262. {
  1263. ParseSrcListCmd(Ch);
  1264. }
  1265. }
  1266. else if (Ch == 'm')
  1267. {
  1268. ParseDumpModuleTable();
  1269. }
  1270. else if (Ch == 'd')
  1271. {
  1272. g_CurCmd++;
  1273. ParseLoadModules();
  1274. }
  1275. else
  1276. {
  1277. error(SYNTAX);
  1278. }
  1279. break;
  1280. case 'm':
  1281. GetRange(&Addr1, &Value2, 1, SEGREG_DATA,
  1282. DEFAULT_RANGE_LIMIT);
  1283. GetAddrExpression(SEGREG_DATA, &Addr2);
  1284. MoveTargetMemory(&Addr1, (ULONG)Value2, &Addr2);
  1285. break;
  1286. case 'n':
  1287. if ((Ch = PeekChar()) != '\0' && Ch != ';')
  1288. {
  1289. if (Ch == '8')
  1290. {
  1291. g_CurCmd++;
  1292. g_DefaultRadix = 8;
  1293. }
  1294. else if (Ch == '1')
  1295. {
  1296. Ch = *++g_CurCmd;
  1297. if (Ch == '0' || Ch == '6')
  1298. {
  1299. g_CurCmd++;
  1300. g_DefaultRadix = 10 + Ch - '0';
  1301. }
  1302. else
  1303. {
  1304. error(SYNTAX);
  1305. }
  1306. }
  1307. else
  1308. {
  1309. error(SYNTAX);
  1310. }
  1311. NotifyChangeEngineState(DEBUG_CES_RADIX, g_DefaultRadix,
  1312. TRUE);
  1313. }
  1314. dprintf("base is %ld\n", g_DefaultRadix);
  1315. break;
  1316. case 'o':
  1317. Ch = (char)tolower(*g_CurCmd);
  1318. g_CurCmd++;
  1319. if (Ch == 'b')
  1320. {
  1321. Value2 = 1;
  1322. }
  1323. else if (Ch == 'w')
  1324. {
  1325. Value2 = 2;
  1326. }
  1327. else if (Ch == 'd')
  1328. {
  1329. Value2 = 4;
  1330. }
  1331. else
  1332. {
  1333. error(SYNTAX);
  1334. }
  1335. if (IS_USER_TARGET(g_Target) || IS_DUMP_TARGET(g_Target))
  1336. {
  1337. error(SESSIONNOTSUP);
  1338. }
  1339. Value1 = GetExpression();
  1340. Value2 = HexValue((ULONG)Value2);
  1341. OutputIo((ULONG)Value1, (ULONG)Value2, Ch);
  1342. break;
  1343. case 'w':
  1344. case 'p':
  1345. case 't':
  1346. if (IS_KERNEL_TARGET(g_Target))
  1347. {
  1348. if (Ch == 'w' &&
  1349. tolower(g_CurCmd[0]) == 'r' &&
  1350. tolower(g_CurCmd[1]) == 'm' &&
  1351. tolower(g_CurCmd[2]) == 's' &&
  1352. tolower(g_CurCmd[3]) == 'r')
  1353. {
  1354. g_CurCmd +=4;
  1355. Value1 = GetExpression();
  1356. if (g_Target->WriteMsr((ULONG)Value1,
  1357. HexValue(8)) != S_OK)
  1358. {
  1359. ErrOut ("no such msr\n");
  1360. }
  1361. break;
  1362. }
  1363. }
  1364. ParseStepTrace(NULL, FALSE, Ch);
  1365. break;
  1366. case 'q':
  1367. char QuitArgument;
  1368. BOOL ForceQuit;
  1369. ForceQuit = FALSE;
  1370. QuitArgument = (char)tolower(PeekChar());
  1371. if (QuitArgument == 'q')
  1372. {
  1373. ForceQuit = TRUE;
  1374. g_CurCmd++;
  1375. QuitArgument = (char)tolower(PeekChar());
  1376. }
  1377. if ((IS_LIVE_USER_TARGET(g_Target) && QuitArgument == 'd') ||
  1378. QuitArgument == 'k')
  1379. {
  1380. g_CurCmd++;
  1381. }
  1382. if (PeekChar() != 0)
  1383. {
  1384. error(SYNTAX);
  1385. }
  1386. if (!ForceQuit &&
  1387. Client != NULL &&
  1388. (Client->m_Flags & CLIENT_REMOTE))
  1389. {
  1390. ErrOut("Exit a remote ntsd/cdb client "
  1391. "with Ctrl-b<enter>.\n"
  1392. "Exit a remote windbg client "
  1393. "with File.Exit (Alt-F4).\n"
  1394. "If you really want the server "
  1395. "to quit use 'qq'.\n");
  1396. break;
  1397. }
  1398. // Detach if requested.
  1399. if (QuitArgument == 'd')
  1400. {
  1401. DBG_ASSERT(IS_LIVE_USER_TARGET(g_Target));
  1402. // If detach isn't supported warn the user
  1403. // and abort the quit.
  1404. if (((LiveUserTargetInfo*)g_Target)->m_Services->
  1405. DetachProcess(0) != S_OK)
  1406. {
  1407. ErrOut("The system doesn't support detach\n");
  1408. break;
  1409. }
  1410. if (g_SessionThread &&
  1411. GetCurrentThreadId() != g_SessionThread)
  1412. {
  1413. ErrOut("Detach can only be done by the server\n");
  1414. break;
  1415. }
  1416. HRESULT DetachStatus;
  1417. if (FAILED(DetachStatus = DetachProcesses()))
  1418. {
  1419. ErrOut("Detach failed, 0x%X\n", DetachStatus);
  1420. }
  1421. }
  1422. else if ((g_GlobalProcOptions &
  1423. DEBUG_PROCESS_DETACH_ON_EXIT) ||
  1424. (g_Target &&
  1425. (g_Target->m_AllProcessFlags & ENG_PROC_EXAMINED)))
  1426. {
  1427. HRESULT PrepareStatus;
  1428. if (g_SymOptions & SYMOPT_SECURE)
  1429. {
  1430. error(NOTSECURE);
  1431. }
  1432. // We need to restart the program before we
  1433. // quit so that it's put back in a running state.
  1434. PrepareStatus = PrepareForSeparation();
  1435. if (PrepareStatus != S_OK)
  1436. {
  1437. ErrOut("Unable to prepare for detach, %s\n \"%s\"",
  1438. FormatStatusCode(PrepareStatus),
  1439. FormatStatus(PrepareStatus));
  1440. break;
  1441. }
  1442. }
  1443. dprintf("quit:\n");
  1444. // Force engine into a no-debuggee state
  1445. // to indicate quit.
  1446. g_CmdState = 'q';
  1447. g_EngStatus |= ENG_STATUS_STOP_SESSION;
  1448. NotifyChangeEngineState(DEBUG_CES_EXECUTION_STATUS,
  1449. DEBUG_STATUS_NO_DEBUGGEE, TRUE);
  1450. break;
  1451. case 'r':
  1452. if (IS_KERNEL_TARGET(g_Target))
  1453. {
  1454. if (tolower(g_CurCmd[0]) == 'd' &&
  1455. tolower(g_CurCmd[1]) == 'm' &&
  1456. tolower(g_CurCmd[2]) == 's' &&
  1457. tolower(g_CurCmd[3]) == 'r')
  1458. {
  1459. g_CurCmd +=4;
  1460. Value1 = GetExpression();
  1461. if (g_Target->ReadMsr((ULONG)Value1, &Value2) == S_OK)
  1462. {
  1463. dprintf("msr[%x] = %08x:%08x\n",
  1464. (ULONG)Value1, (ULONG)(Value2 >> 32),
  1465. (ULONG)Value2);
  1466. }
  1467. else
  1468. {
  1469. ErrOut("no such msr\n");
  1470. }
  1471. break;
  1472. }
  1473. }
  1474. if (ScopeContext = GetCurrentScopeContext())
  1475. {
  1476. dprintf("Last set context:\n");
  1477. PushContext = g_Machine->PushContext(ScopeContext);
  1478. }
  1479. __try
  1480. {
  1481. ParseRegCmd();
  1482. }
  1483. __except(CommandExceptionFilter(GetExceptionInformation()))
  1484. {
  1485. // Stop command processing.
  1486. *g_CurCmd = 0;
  1487. }
  1488. if (ScopeContext)
  1489. {
  1490. g_Machine->PopContext(PushContext);
  1491. }
  1492. if (g_SwitchedProcs)
  1493. {
  1494. RestoreCurrentProcessorThread(g_Target);
  1495. g_SwitchedProcs = FALSE;
  1496. }
  1497. break;
  1498. case 's':
  1499. Ch = (char)tolower(*g_CurCmd);
  1500. if (Ch == 's')
  1501. {
  1502. g_CurCmd++;
  1503. SetSuffix();
  1504. }
  1505. else if (Ch == 'q')
  1506. {
  1507. g_CurCmd++;
  1508. Ch = (char)tolower(*g_CurCmd);
  1509. if (Ch == 'e')
  1510. {
  1511. g_QuietMode = TRUE;
  1512. g_CurCmd++;
  1513. }
  1514. else if (Ch == 'd')
  1515. {
  1516. g_QuietMode = FALSE;
  1517. g_CurCmd++;
  1518. }
  1519. else
  1520. {
  1521. g_QuietMode = !g_QuietMode;
  1522. }
  1523. dprintf("Quiet mode is %s\n", g_QuietMode ? "ON" : "OFF");
  1524. }
  1525. else if (Ch == 'x')
  1526. {
  1527. g_CurCmd++;
  1528. ParseSetEventFilter(Client);
  1529. }
  1530. else if (IS_KERNEL_TARGET(g_Target) && Ch == 'o')
  1531. {
  1532. Scan = ++g_CurCmd;
  1533. while ((*Scan != '\0') && (*Scan != ';'))
  1534. {
  1535. Scan++;
  1536. }
  1537. Ch = *Scan;
  1538. *Scan = '\0';
  1539. ReadDebugOptions(FALSE, (*g_CurCmd == '\0' ?
  1540. NULL : g_CurCmd));
  1541. *Scan = Ch;
  1542. g_CurCmd = Scan;
  1543. }
  1544. else
  1545. {
  1546. // s, s-w, s-d, s-q.
  1547. ParseSearchMemory();
  1548. }
  1549. break;
  1550. case 'u':
  1551. ParseUnassemble();
  1552. break;
  1553. case 'v':
  1554. Scan = g_CurCmd;
  1555. while (*Scan && !isspace(*Scan) && *Scan != ';')
  1556. {
  1557. Scan++;
  1558. }
  1559. Count = (ULONG)(Scan - g_CurCmd);
  1560. if (Count == 8 &&
  1561. _memicmp(g_CurCmd, "ertarget", Count) == 0)
  1562. {
  1563. g_CurCmd = Scan;
  1564. g_Target->OutputVersion();
  1565. }
  1566. else if (Count == 6 &&
  1567. _memicmp(g_CurCmd, "ersion", Count) == 0)
  1568. {
  1569. g_CurCmd = Scan;
  1570. // Print target version, then debugger version.
  1571. g_Target->OutputVersion();
  1572. OutputVersionInformation(Client);
  1573. }
  1574. else if (Count == 9 &&
  1575. _memicmp(g_CurCmd, "ercommand", Count) == 0)
  1576. {
  1577. g_CurCmd = Scan;
  1578. dprintf("command line: '%s'\n", GetCommandLine());
  1579. }
  1580. else
  1581. {
  1582. error(SYNTAX);
  1583. }
  1584. break;
  1585. case 'x':
  1586. ParseExamine();
  1587. break;
  1588. case ';':
  1589. case '\0':
  1590. g_CurCmd--;
  1591. break;
  1592. case 'z':
  1593. // Works like do{ cmds }while(Cond);
  1594. // Eg. p;z(eax<2);
  1595. if (CheckUserInterrupt())
  1596. {
  1597. // Eat the expression also to prevent
  1598. // spurious extra character errors.
  1599. GetExpression();
  1600. g_RedoCount = 0;
  1601. break;
  1602. }
  1603. if (GetExpression())
  1604. {
  1605. g_CurCmd = g_CommandStart;
  1606. ++g_RedoCount;
  1607. dprintf("redo [%d] %s\n", g_RedoCount, g_CurCmd );
  1608. FlushCallbacks();
  1609. Ch = *g_CurCmd++;
  1610. goto EVALUATE;
  1611. }
  1612. else
  1613. {
  1614. g_RedoCount = 0;
  1615. }
  1616. break;
  1617. default:
  1618. error(SYNTAX);
  1619. break;
  1620. }
  1621. do
  1622. {
  1623. Ch = *g_CurCmd++;
  1624. } while (Ch == ' ' || Ch == '\t' || Ch == '\n' || Ch == '\r');
  1625. if (Ch != ';' && Ch != '\0')
  1626. {
  1627. error(EXTRACHARS);
  1628. }
  1629. g_CurCmd--;
  1630. }
  1631. while (g_CmdState == 'c');
  1632. if (Status == S_FALSE)
  1633. {
  1634. Scan = g_CurCmd;
  1635. // We switched to a non-'c' cmdState so the
  1636. // loop was exited. Check and see if we're
  1637. // also at the end of the command as that will
  1638. // take precedence in what the return value is.
  1639. while (*Scan == ' ' || *Scan == '\t' || *Scan == ';')
  1640. {
  1641. Scan++;
  1642. }
  1643. Status = *Scan ? S_FALSE : S_OK;
  1644. }
  1645. g_EngStatus &= ~ENG_STATUS_USER_INTERRUPT;
  1646. return Status;
  1647. }
  1648. HRESULT
  1649. ProcessCommandsAndCatch(DebugClient* Client)
  1650. {
  1651. HRESULT Status;
  1652. __try
  1653. {
  1654. Status = ProcessCommands(Client, FALSE);
  1655. }
  1656. __except(CommandExceptionFilter(GetExceptionInformation()))
  1657. {
  1658. g_CurCmd = g_CommandStart;
  1659. *g_CurCmd = '\0';
  1660. g_LastCommand[0] = '\0';
  1661. Status = HR_PROCESS_EXCEPTION;
  1662. g_EngStatus &= ~ENG_STATUS_USER_INTERRUPT;
  1663. }
  1664. return Status;
  1665. }