ReactOS  0.4.15-dev-1629-g9aa73da
kdb_cli.c
Go to the documentation of this file.
1 /*
2  * ReactOS kernel
3  * Copyright (C) 2005 ReactOS Team
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  */
19 /*
20  * PROJECT: ReactOS kernel
21  * FILE: ntoskrnl/kdbg/kdb_cli.c
22  * PURPOSE: Kernel debugger command line interface
23  * PROGRAMMER: Gregor Anich (blight@blight.eu.org)
24  * Hervé Poussineau
25  * UPDATE HISTORY:
26  * Created 16/01/2005
27  */
28 
29 /* INCLUDES ******************************************************************/
30 
31 #include <ntoskrnl.h>
32 
33 #define NDEBUG
34 #include <debug.h>
35 
36 /* DEFINES *******************************************************************/
37 
38 #define KEY_BS 8
39 #define KEY_ESC 27
40 #define KEY_DEL 127
41 
42 #define KEY_SCAN_UP 72
43 #define KEY_SCAN_DOWN 80
44 
45 /* Scan codes of keyboard keys: */
46 #define KEYSC_END 0x004f
47 #define KEYSC_PAGEUP 0x0049
48 #define KEYSC_PAGEDOWN 0x0051
49 #define KEYSC_HOME 0x0047
50 #define KEYSC_ARROWUP 0x0048
51 
52 #define KDB_ENTER_CONDITION_TO_STRING(cond) \
53  ((cond) == KdbDoNotEnter ? "never" : \
54  ((cond) == KdbEnterAlways ? "always" : \
55  ((cond) == KdbEnterFromKmode ? "kmode" : "umode")))
56 
57 #define KDB_ACCESS_TYPE_TO_STRING(type) \
58  ((type) == KdbAccessRead ? "read" : \
59  ((type) == KdbAccessWrite ? "write" : \
60  ((type) == KdbAccessReadWrite ? "rdwr" : "exec")))
61 
62 #define NPX_STATE_TO_STRING(state) \
63  ((state) == NPX_STATE_LOADED ? "Loaded" : \
64  ((state) == NPX_STATE_NOT_LOADED ? "Not loaded" : "Unknown"))
65 
66 /* PROTOTYPES ****************************************************************/
67 
68 static BOOLEAN KdbpCmdEvalExpression(ULONG Argc, PCHAR Argv[]);
69 static BOOLEAN KdbpCmdDisassembleX(ULONG Argc, PCHAR Argv[]);
70 static BOOLEAN KdbpCmdRegs(ULONG Argc, PCHAR Argv[]);
71 static BOOLEAN KdbpCmdBackTrace(ULONG Argc, PCHAR Argv[]);
72 
73 static BOOLEAN KdbpCmdContinue(ULONG Argc, PCHAR Argv[]);
74 static BOOLEAN KdbpCmdStep(ULONG Argc, PCHAR Argv[]);
75 static BOOLEAN KdbpCmdBreakPointList(ULONG Argc, PCHAR Argv[]);
77 static BOOLEAN KdbpCmdBreakPoint(ULONG Argc, PCHAR Argv[]);
78 
79 static BOOLEAN KdbpCmdThread(ULONG Argc, PCHAR Argv[]);
80 static BOOLEAN KdbpCmdProc(ULONG Argc, PCHAR Argv[]);
81 
82 static BOOLEAN KdbpCmdMod(ULONG Argc, PCHAR Argv[]);
83 static BOOLEAN KdbpCmdGdtLdtIdt(ULONG Argc, PCHAR Argv[]);
84 static BOOLEAN KdbpCmdPcr(ULONG Argc, PCHAR Argv[]);
85 static BOOLEAN KdbpCmdTss(ULONG Argc, PCHAR Argv[]);
86 
87 static BOOLEAN KdbpCmdBugCheck(ULONG Argc, PCHAR Argv[]);
88 static BOOLEAN KdbpCmdReboot(ULONG Argc, PCHAR Argv[]);
89 static BOOLEAN KdbpCmdFilter(ULONG Argc, PCHAR Argv[]);
90 static BOOLEAN KdbpCmdSet(ULONG Argc, PCHAR Argv[]);
91 static BOOLEAN KdbpCmdHelp(ULONG Argc, PCHAR Argv[]);
92 static BOOLEAN KdbpCmdDmesg(ULONG Argc, PCHAR Argv[]);
93 
94 BOOLEAN ExpKdbgExtPool(ULONG Argc, PCHAR Argv[]);
99 BOOLEAN ExpKdbgExtIrpFind(ULONG Argc, PCHAR Argv[]);
100 BOOLEAN ExpKdbgExtHandle(ULONG Argc, PCHAR Argv[]);
101 
102 #ifdef __ROS_DWARF__
103 static BOOLEAN KdbpCmdPrintStruct(ULONG Argc, PCHAR Argv[]);
104 #endif
105 
106 /* GLOBALS *******************************************************************/
107 
108 typedef
109 BOOLEAN
111  IN PCHAR Command,
112  IN ULONG Argc,
113  IN PCH Argv[]);
114 
116 static BOOLEAN KdbUseIntelSyntax = FALSE; /* Set to TRUE for intel syntax */
117 static BOOLEAN KdbBreakOnModuleLoad = FALSE; /* Set to TRUE to break into KDB when a module is loaded */
118 
119 static CHAR KdbCommandHistoryBuffer[2048]; /* Command history string ringbuffer */
120 static PCHAR KdbCommandHistory[sizeof(KdbCommandHistoryBuffer) / 8] = { NULL }; /* Command history ringbuffer */
123 
130 
131 PCHAR KdbInitFileBuffer = NULL; /* Buffer where KDBinit file is loaded into during initialization */
133 
134 /* Vars for dmesg */
135 /* defined in ../kd/kdio.c, declare here: */
136 extern volatile BOOLEAN KdbpIsInDmesgMode;
137 extern const ULONG KdpDmesgBufferSize;
138 extern PCHAR KdpDmesgBuffer;
139 extern volatile ULONG KdpDmesgCurrentPosition;
140 extern volatile ULONG KdpDmesgFreeBytes;
141 extern volatile ULONG KdbDmesgTotalWritten;
142 
144 
145 //
146 // Debug Filter Component Table
147 //
148 #define KD_DEBUG_PRINT_FILTER(Name) \
149  { #Name, DPFLTR_##Name##_ID }
150 
151 static struct
152 {
155 }
156 ComponentTable[] =
157 {
158 //
159 // Default components
160 //
161  { "WIN2000", MAXULONG },
163 //
164 // Standard components
165 //
167  KD_DEBUG_PRINT_FILTER(SMSS),
169  KD_DEBUG_PRINT_FILTER(NTFS),
170  KD_DEBUG_PRINT_FILTER(FSTUB),
171  KD_DEBUG_PRINT_FILTER(CRASHDUMP),
172  KD_DEBUG_PRINT_FILTER(CDAUDIO),
173  KD_DEBUG_PRINT_FILTER(CDROM),
174  KD_DEBUG_PRINT_FILTER(CLASSPNP),
175  KD_DEBUG_PRINT_FILTER(DISK),
176  KD_DEBUG_PRINT_FILTER(REDBOOK),
177  KD_DEBUG_PRINT_FILTER(STORPROP),
178  KD_DEBUG_PRINT_FILTER(SCSIPORT),
179  KD_DEBUG_PRINT_FILTER(SCSIMINIPORT),
180  KD_DEBUG_PRINT_FILTER(CONFIG),
181  KD_DEBUG_PRINT_FILTER(I8042PRT),
182  KD_DEBUG_PRINT_FILTER(SERMOUSE),
183  KD_DEBUG_PRINT_FILTER(LSERMOUS),
184  KD_DEBUG_PRINT_FILTER(KBDHID),
185  KD_DEBUG_PRINT_FILTER(MOUHID),
186  KD_DEBUG_PRINT_FILTER(KBDCLASS),
187  KD_DEBUG_PRINT_FILTER(MOUCLASS),
188  KD_DEBUG_PRINT_FILTER(TWOTRACK),
189  KD_DEBUG_PRINT_FILTER(WMILIB),
190  KD_DEBUG_PRINT_FILTER(ACPI),
191  KD_DEBUG_PRINT_FILTER(AMLI),
192  KD_DEBUG_PRINT_FILTER(HALIA64),
193  KD_DEBUG_PRINT_FILTER(VIDEO),
194  KD_DEBUG_PRINT_FILTER(SVCHOST),
195  KD_DEBUG_PRINT_FILTER(VIDEOPRT),
196  KD_DEBUG_PRINT_FILTER(TCPIP),
197  KD_DEBUG_PRINT_FILTER(DMSYNTH),
198  KD_DEBUG_PRINT_FILTER(NTOSPNP),
199  KD_DEBUG_PRINT_FILTER(FASTFAT),
200  KD_DEBUG_PRINT_FILTER(SAMSS),
201  KD_DEBUG_PRINT_FILTER(PNPMGR),
202  KD_DEBUG_PRINT_FILTER(NETAPI),
203  KD_DEBUG_PRINT_FILTER(SCSERVER),
204  KD_DEBUG_PRINT_FILTER(SCCLIENT),
205  KD_DEBUG_PRINT_FILTER(SERIAL),
206  KD_DEBUG_PRINT_FILTER(SERENUM),
207  KD_DEBUG_PRINT_FILTER(UHCD),
208  KD_DEBUG_PRINT_FILTER(RPCPROXY),
209  KD_DEBUG_PRINT_FILTER(AUTOCHK),
210  KD_DEBUG_PRINT_FILTER(DCOMSS),
211  KD_DEBUG_PRINT_FILTER(UNIMODEM),
213  KD_DEBUG_PRINT_FILTER(FLTMGR),
214  KD_DEBUG_PRINT_FILTER(WMICORE),
215  KD_DEBUG_PRINT_FILTER(BURNENG),
216  KD_DEBUG_PRINT_FILTER(IMAPI),
218  KD_DEBUG_PRINT_FILTER(FUSION),
219  KD_DEBUG_PRINT_FILTER(IDLETASK),
220  KD_DEBUG_PRINT_FILTER(SOFTPCI),
221  KD_DEBUG_PRINT_FILTER(TAPE),
222  KD_DEBUG_PRINT_FILTER(MCHGR),
223  KD_DEBUG_PRINT_FILTER(IDEP),
224  KD_DEBUG_PRINT_FILTER(PCIIDE),
225  KD_DEBUG_PRINT_FILTER(FLOPPY),
227  KD_DEBUG_PRINT_FILTER(TERMSRV),
228  KD_DEBUG_PRINT_FILTER(W32TIME),
229  KD_DEBUG_PRINT_FILTER(PREFETCHER),
230  KD_DEBUG_PRINT_FILTER(RSFILTER),
231  KD_DEBUG_PRINT_FILTER(FCPORT),
233  KD_DEBUG_PRINT_FILTER(DMIO),
234  KD_DEBUG_PRINT_FILTER(DMCONFIG),
235  KD_DEBUG_PRINT_FILTER(DMADMIN),
236  KD_DEBUG_PRINT_FILTER(WSOCKTRANSPORT),
238  KD_DEBUG_PRINT_FILTER(PNPMEM),
239  KD_DEBUG_PRINT_FILTER(PROCESSOR),
240  KD_DEBUG_PRINT_FILTER(DMSERVER),
242  KD_DEBUG_PRINT_FILTER(INFINIBAND),
243  KD_DEBUG_PRINT_FILTER(IHVDRIVER),
244  KD_DEBUG_PRINT_FILTER(IHVVIDEO),
245  KD_DEBUG_PRINT_FILTER(IHVAUDIO),
246  KD_DEBUG_PRINT_FILTER(IHVNETWORK),
247  KD_DEBUG_PRINT_FILTER(IHVSTREAMING),
248  KD_DEBUG_PRINT_FILTER(IHVBUS),
250  KD_DEBUG_PRINT_FILTER(RTLTHREADPOOL),
252  KD_DEBUG_PRINT_FILTER(TCPIP6),
253  KD_DEBUG_PRINT_FILTER(ISAPNP),
254  KD_DEBUG_PRINT_FILTER(SHPC),
255  KD_DEBUG_PRINT_FILTER(STORPORT),
256  KD_DEBUG_PRINT_FILTER(STORMINIPORT),
257  KD_DEBUG_PRINT_FILTER(PRINTSPOOLER),
258  KD_DEBUG_PRINT_FILTER(VSSDYNDISK),
259  KD_DEBUG_PRINT_FILTER(VERIFIER),
261  KD_DEBUG_PRINT_FILTER(VDSBAS),
262  KD_DEBUG_PRINT_FILTER(VDSDYN), // Specified in Vista+
263  KD_DEBUG_PRINT_FILTER(VDSDYNDR),
264  KD_DEBUG_PRINT_FILTER(VDSLDR), // Specified in Vista+
265  KD_DEBUG_PRINT_FILTER(VDSUTIL),
266  KD_DEBUG_PRINT_FILTER(DFRGIFC),
268  KD_DEBUG_PRINT_FILTER(DFSC),
269  KD_DEBUG_PRINT_FILTER(WOW64),
270 //
271 // Components specified in Vista+, some of which we also use in ReactOS
272 //
273  KD_DEBUG_PRINT_FILTER(ALPC),
275  KD_DEBUG_PRINT_FILTER(PERFLIB),
277  KD_DEBUG_PRINT_FILTER(IOSTRESS),
279  KD_DEBUG_PRINT_FILTER(WHEA),
280  KD_DEBUG_PRINT_FILTER(USERGDI),
281  KD_DEBUG_PRINT_FILTER(MMCSS),
283  KD_DEBUG_PRINT_FILTER(THREADORDER),
284  KD_DEBUG_PRINT_FILTER(ENVIRON),
287  KD_DEBUG_PRINT_FILTER(FVEVOL),
288  KD_DEBUG_PRINT_FILTER(NDIS),
289  KD_DEBUG_PRINT_FILTER(NVCTRACE),
290  KD_DEBUG_PRINT_FILTER(LUAFV),
291  KD_DEBUG_PRINT_FILTER(APPCOMPAT),
292  KD_DEBUG_PRINT_FILTER(USBSTOR),
293  KD_DEBUG_PRINT_FILTER(SBP2PORT),
295  KD_DEBUG_PRINT_FILTER(CACHEMGR),
296  KD_DEBUG_PRINT_FILTER(MOUNTMGR),
299  KD_DEBUG_PRINT_FILTER(KSECDD),
300  KD_DEBUG_PRINT_FILTER(FLTREGRESS),
301  KD_DEBUG_PRINT_FILTER(MPIO),
302  KD_DEBUG_PRINT_FILTER(MSDSM),
303  KD_DEBUG_PRINT_FILTER(UDFS),
304  KD_DEBUG_PRINT_FILTER(PSHED),
305  KD_DEBUG_PRINT_FILTER(STORVSP),
306  KD_DEBUG_PRINT_FILTER(LSASS),
307  KD_DEBUG_PRINT_FILTER(SSPICLI),
309  KD_DEBUG_PRINT_FILTER(EXFAT),
310  KD_DEBUG_PRINT_FILTER(FILETRACE),
311  KD_DEBUG_PRINT_FILTER(XSAVE),
313  KD_DEBUG_PRINT_FILTER(DRIVEEXTENDER),
314 //
315 // Components specified in Windows 8
316 //
317  KD_DEBUG_PRINT_FILTER(POWER),
318  KD_DEBUG_PRINT_FILTER(CRASHDUMPXHCI),
319  KD_DEBUG_PRINT_FILTER(GPIO),
320  KD_DEBUG_PRINT_FILTER(REFS),
322 //
323 // Components specified in Windows 10
324 //
325  KD_DEBUG_PRINT_FILTER(CAPIMG),
326  KD_DEBUG_PRINT_FILTER(VPCI),
327  KD_DEBUG_PRINT_FILTER(STORAGECLASSMEMORY),
328  KD_DEBUG_PRINT_FILTER(FSLIB),
329 };
330 #undef KD_DEBUG_PRINT_FILTER
331 
332 //
333 // Command Table
334 //
335 static const struct
336 {
337  PCHAR Name;
340  BOOLEAN (*Fn)(ULONG Argc, PCHAR Argv[]);
341 } KdbDebuggerCommands[] = {
342  /* Data */
343  { NULL, NULL, "Data", NULL },
344  { "?", "? expression", "Evaluate expression.", KdbpCmdEvalExpression },
345  { "disasm", "disasm [address] [L count]", "Disassemble count instructions at address.", KdbpCmdDisassembleX },
346  { "x", "x [address] [L count]", "Display count dwords, starting at address.", KdbpCmdDisassembleX },
347  { "regs", "regs", "Display general purpose registers.", KdbpCmdRegs },
348  { "sregs", "sregs", "Display status registers.", KdbpCmdRegs },
349  { "dregs", "dregs", "Display debug registers.", KdbpCmdRegs },
350  { "bt", "bt [*frameaddr|thread id]", "Prints current backtrace or from given frame address.", KdbpCmdBackTrace },
351 #ifdef __ROS_DWARF__
352  { "dt", "dt [mod] [type] [addr]", "Print a struct. The address is optional.", KdbpCmdPrintStruct },
353 #endif
354 
355  /* Flow control */
356  { NULL, NULL, "Flow control", NULL },
357  { "cont", "cont", "Continue execution (leave debugger).", KdbpCmdContinue },
358  { "step", "step [count]", "Execute single instructions, stepping into interrupts.", KdbpCmdStep },
359  { "next", "next [count]", "Execute single instructions, skipping calls and reps.", KdbpCmdStep },
360  { "bl", "bl", "List breakpoints.", KdbpCmdBreakPointList },
361  { "be", "be [breakpoint]", "Enable breakpoint.", KdbpCmdEnableDisableClearBreakPoint },
362  { "bd", "bd [breakpoint]", "Disable breakpoint.", KdbpCmdEnableDisableClearBreakPoint },
363  { "bc", "bc [breakpoint]", "Clear breakpoint.", KdbpCmdEnableDisableClearBreakPoint },
364  { "bpx", "bpx [address] [IF condition]", "Set software execution breakpoint at address.", KdbpCmdBreakPoint },
365  { "bpm", "bpm [r|w|rw|x] [byte|word|dword] [address] [IF condition]", "Set memory breakpoint at address.", KdbpCmdBreakPoint },
366 
367  /* Process/Thread */
368  { NULL, NULL, "Process/Thread", NULL },
369  { "thread", "thread [list[ pid]|[attach ]tid]", "List threads in current or specified process, display thread with given id or attach to thread.", KdbpCmdThread },
370  { "proc", "proc [list|[attach ]pid]", "List processes, display process with given id or attach to process.", KdbpCmdProc },
371 
372  /* System information */
373  { NULL, NULL, "System info", NULL },
374  { "mod", "mod [address]", "List all modules or the one containing address.", KdbpCmdMod },
375  { "gdt", "gdt", "Display the global descriptor table.", KdbpCmdGdtLdtIdt },
376  { "ldt", "ldt", "Display the local descriptor table.", KdbpCmdGdtLdtIdt },
377  { "idt", "idt", "Display the interrupt descriptor table.", KdbpCmdGdtLdtIdt },
378  { "pcr", "pcr", "Display the processor control region.", KdbpCmdPcr },
379  { "tss", "tss [selector|*descaddr]", "Display the current task state segment, or the one specified by its selector number or descriptor address.", KdbpCmdTss },
380 
381  /* Others */
382  { NULL, NULL, "Others", NULL },
383  { "bugcheck", "bugcheck", "Bugchecks the system.", KdbpCmdBugCheck },
384  { "reboot", "reboot", "Reboots the system.", KdbpCmdReboot},
385  { "filter", "filter [error|warning|trace|info|level]+|-[componentname|default]", "Enable/disable debug channels.", KdbpCmdFilter },
386  { "set", "set [var] [value]", "Sets var to value or displays value of var.", KdbpCmdSet },
387  { "dmesg", "dmesg", "Display debug messages on screen, with navigation on pages.", KdbpCmdDmesg },
388  { "kmsg", "kmsg", "Kernel dmesg. Alias for dmesg.", KdbpCmdDmesg },
389  { "help", "help", "Display help screen.", KdbpCmdHelp },
390  { "!pool", "!pool [Address [Flags]]", "Display information about pool allocations.", ExpKdbgExtPool },
391  { "!poolused", "!poolused [Flags [Tag]]", "Display pool usage.", ExpKdbgExtPoolUsed },
392  { "!poolfind", "!poolfind Tag [Pool]", "Search for pool tag allocations.", ExpKdbgExtPoolFind },
393  { "!filecache", "!filecache", "Display cache usage.", ExpKdbgExtFileCache },
394  { "!defwrites", "!defwrites", "Display cache write values.", ExpKdbgExtDefWrites },
395  { "!irpfind", "!irpfind [Pool [startaddress [criteria data]]]", "Lists IRPs potentially matching criteria.", ExpKdbgExtIrpFind },
396  { "!handle", "!handle [Handle]", "Displays info about handles.", ExpKdbgExtHandle },
397 };
398 
399 /* FUNCTIONS *****************************************************************/
400 
413 static BOOLEAN
416  IN LONG ErrOffset,
418 {
419  static CHAR ErrMsgBuffer[130] = "^ ";
420  LONG ExpressionErrOffset = -1;
421  PCHAR ErrMsg = ErrMsgBuffer;
422  BOOLEAN Ok;
423 
425  &ExpressionErrOffset, ErrMsgBuffer + 2);
426  if (!Ok)
427  {
428  if (ExpressionErrOffset >= 0)
429  ExpressionErrOffset += ErrOffset;
430  else
431  ErrMsg += 2;
432 
433  KdbpPrint("%*s%s\n", ExpressionErrOffset, "", ErrMsg);
434  }
435 
436  return Ok;
437 }
438 
439 BOOLEAN
440 NTAPI
442  IN PCHAR pszNum,
443  OUT ULONG_PTR *pulValue)
444 {
445  char *endptr;
446 
447  /* Skip optional '0x' prefix */
448  if ((pszNum[0] == '0') && ((pszNum[1] == 'x') || (pszNum[1] == 'X')))
449  pszNum += 2;
450 
451  /* Make a number from the string (hex) */
452  *pulValue = strtoul(pszNum, &endptr, 16);
453 
454  return (*endptr == '\0');
455 }
456 
459 static BOOLEAN
461  ULONG Argc,
462  PCHAR Argv[])
463 {
464  ULONG i, len;
465  ULONGLONG Result = 0;
466  ULONG ul;
467  LONG l = 0;
468  BOOLEAN Ok;
469 
470  if (Argc < 2)
471  {
472  KdbpPrint("?: Argument required\n");
473  return TRUE;
474  }
475 
476  /* Put the arguments back together */
477  Argc--;
478  for (i = 1; i < Argc; i++)
479  {
480  len = strlen(Argv[i]);
481  Argv[i][len] = ' ';
482  }
483 
484  /* Evaluate the expression */
485  Ok = KdbpEvaluateExpression(Argv[1], KdbPromptString.Length + (Argv[1]-Argv[0]), &Result);
486  if (Ok)
487  {
488  if (Result > 0x00000000ffffffffLL)
489  {
490  if (Result & 0x8000000000000000LL)
491  KdbpPrint("0x%016I64x %20I64u %20I64d\n", Result, Result, Result);
492  else
493  KdbpPrint("0x%016I64x %20I64u\n", Result, Result);
494  }
495  else
496  {
497  ul = (ULONG)Result;
498 
499  if (ul <= 0xff && ul >= 0x80)
500  l = (LONG)((CHAR)ul);
501  else if (ul <= 0xffff && ul >= 0x8000)
502  l = (LONG)((SHORT)ul);
503  else
504  l = (LONG)ul;
505 
506  if (l < 0)
507  KdbpPrint("0x%08lx %10lu %10ld\n", ul, ul, l);
508  else
509  KdbpPrint("0x%08lx %10lu\n", ul, ul);
510  }
511  }
512 
513  return TRUE;
514 }
515 
516 #ifdef __ROS_DWARF__
517 
520 static VOID
521 KdbpPrintStructInternal
523  PCHAR Indent,
524  BOOLEAN DoRead,
526  PROSSYM_AGGREGATE Aggregate)
527 {
528  ULONG i;
531  ULONG IndentLen = strlen(Indent);
532  ROSSYM_AGGREGATE MemberAggregate = {0 };
533 
534  for (i = 0; i < Aggregate->NumElements; i++) {
535  Member = &Aggregate->Elements[i];
536  KdbpPrint("%s%p+%x: %s", Indent, ((PCHAR)BaseAddress) + Member->BaseOffset, Member->Size, Member->Name ? Member->Name : "<anoymous>");
537  if (DoRead) {
538  if (!strcmp(Member->Type, "_UNICODE_STRING")) {
539  KdbpPrint("\"%wZ\"\n", ((PCHAR)BaseAddress) + Member->BaseOffset);
540  continue;
541  } else if (!strcmp(Member->Type, "PUNICODE_STRING")) {
542  KdbpPrint("\"%wZ\"\n", *(((PUNICODE_STRING*)((PCHAR)BaseAddress) + Member->BaseOffset)));
543  continue;
544  }
545  switch (Member->Size) {
546  case 1:
547  case 2:
548  case 4:
549  case 8: {
550  Result = 0;
551  if (NT_SUCCESS(KdbpSafeReadMemory(&Result, ((PCHAR)BaseAddress) + Member->BaseOffset, Member->Size))) {
552  if (Member->Bits) {
553  Result >>= Member->FirstBit;
554  Result &= ((1 << Member->Bits) - 1);
555  }
556  KdbpPrint(" %lx\n", Result);
557  }
558  else goto readfail;
559  break;
560  }
561  default: {
562  if (Member->Size < 8) {
563  if (NT_SUCCESS(KdbpSafeReadMemory(&Result, ((PCHAR)BaseAddress) + Member->BaseOffset, Member->Size))) {
564  ULONG j;
565  for (j = 0; j < Member->Size; j++) {
566  KdbpPrint(" %02x", (int)(Result & 0xff));
567  Result >>= 8;
568  }
569  } else goto readfail;
570  } else {
571  KdbpPrint(" %s @ %p {\n", Member->Type, ((PCHAR)BaseAddress) + Member->BaseOffset);
572  Indent[IndentLen] = ' ';
573  if (RosSymAggregate(Info, Member->Type, &MemberAggregate)) {
574  KdbpPrintStructInternal(Info, Indent, DoRead, ((PCHAR)BaseAddress) + Member->BaseOffset, &MemberAggregate);
575  RosSymFreeAggregate(&MemberAggregate);
576  }
577  Indent[IndentLen] = 0;
578  KdbpPrint("%s}\n", Indent);
579  } break;
580  }
581  }
582  } else {
583  readfail:
584  if (Member->Size <= 8) {
585  KdbpPrint(" ??\n");
586  } else {
587  KdbpPrint(" %s @ %x {\n", Member->Type, Member->BaseOffset);
588  Indent[IndentLen] = ' ';
589  if (RosSymAggregate(Info, Member->Type, &MemberAggregate)) {
590  KdbpPrintStructInternal(Info, Indent, DoRead, BaseAddress, &MemberAggregate);
591  RosSymFreeAggregate(&MemberAggregate);
592  }
593  Indent[IndentLen] = 0;
594  KdbpPrint("%s}\n", Indent);
595  }
596  }
597  }
598 }
599 
601 
602 static BOOLEAN
603 KdbpCmdPrintStruct(
604  ULONG Argc,
605  PCHAR Argv[])
606 {
607  ULONG i;
608  ULONGLONG Result = 0;
609  PVOID BaseAddress = 0;
610  ROSSYM_AGGREGATE Aggregate = {0};
611  UNICODE_STRING ModName = {0};
612  ANSI_STRING AnsiName = {0};
613  CHAR Indent[100] = {0};
615 
616  if (Argc < 3) goto end;
617  AnsiName.Length = AnsiName.MaximumLength = strlen(Argv[1]);
618  AnsiName.Buffer = Argv[1];
619  RtlAnsiStringToUnicodeString(&ModName, &AnsiName, TRUE);
620  Info = KdbpSymFindCachedFile(&ModName);
621 
622  if (!Info || !RosSymAggregate(Info, Argv[2], &Aggregate)) {
623  DPRINT1("Could not get aggregate\n");
624  goto end;
625  }
626 
627  // Get an argument for location if it was given
628  if (Argc > 3) {
629  ULONG len;
630  PCHAR ArgStart = Argv[3];
631  DPRINT1("Trying to get expression\n");
632  for (i = 3; i < Argc - 1; i++)
633  {
634  len = strlen(Argv[i]);
635  Argv[i][len] = ' ';
636  }
637 
638  /* Evaluate the expression */
639  DPRINT1("Arg: %s\n", ArgStart);
640  if (KdbpEvaluateExpression(ArgStart, strlen(ArgStart), &Result)) {
642  DPRINT1("BaseAddress: %p\n", BaseAddress);
643  }
644  }
645  DPRINT1("BaseAddress %p\n", BaseAddress);
646  KdbpPrintStructInternal(Info, Indent, !!BaseAddress, BaseAddress, &Aggregate);
647 end:
648  RosSymFreeAggregate(&Aggregate);
649  RtlFreeUnicodeString(&ModName);
650  return TRUE;
651 }
652 #endif
653 
662 static BOOLEAN
664  IN PCSTR ComponentName,
666 {
667  ULONG i;
668 
669  for (i = 0; i < RTL_NUMBER_OF(ComponentTable); i++)
670  {
671  if (_stricmp(ComponentName, ComponentTable[i].Name) == 0)
672  {
674  return TRUE;
675  }
676  }
677 
678  return FALSE;
679 }
680 
683 static BOOLEAN
685  ULONG Argc,
686  PCHAR Argv[])
687 {
689  ULONG set = DPFLTR_MASK, clear = DPFLTR_MASK;
690  PCHAR pend;
691  PCSTR opt, p;
692 
693  static struct
694  {
695  PCSTR Name;
696  ULONG Level;
697  }
698  debug_classes[] =
699  {
700  { "error", 1 << DPFLTR_ERROR_LEVEL },
701  { "warning", 1 << DPFLTR_WARNING_LEVEL },
702  { "trace", 1 << DPFLTR_TRACE_LEVEL },
703  { "info", 1 << DPFLTR_INFO_LEVEL },
704  };
705 
706  if (Argc <= 1)
707  {
708  /* Display the list of available debug filter components */
709  KdbpPrint("REMARKS:\n"
710  "- The 'WIN2000' system-wide debug filter component is used for DbgPrint()\n"
711  " messages without Component ID and Level.\n"
712  "- The 'DEFAULT' debug filter component is used for DbgPrint() messages with\n"
713  " an unknown Component ID.\n\n");
714  KdbpPrint("The list of debug filter components currently available on your system is:\n\n");
715  KdbpPrint(" Component Name Component ID\n"
716  " ================== ================\n");
717  for (i = 0; i < RTL_NUMBER_OF(ComponentTable); i++)
718  {
719  KdbpPrint("%20s 0x%08lx\n", ComponentTable[i].Name, ComponentTable[i].Id);
720  }
721  return TRUE;
722  }
723 
724  for (i = 1; i < Argc; i++)
725  {
726  opt = Argv[i];
727  p = opt + strcspn(opt, "+-");
728  if (!p[0]) p = opt; /* Assume it's a debug channel name */
729 
730  if (p > opt)
731  {
732  for (j = 0; j < RTL_NUMBER_OF(debug_classes); j++)
733  {
735  if (len != (p - opt))
736  continue;
737  if (_strnicmp(opt, debug_classes[j].Name, len) == 0) /* Found it */
738  {
739  if (*p == '+')
740  set |= debug_classes[j].Level;
741  else
742  clear |= debug_classes[j].Level;
743  break;
744  }
745  }
746  if (j == RTL_NUMBER_OF(debug_classes))
747  {
748  Level = strtoul(opt, &pend, 0);
749  if (pend != p)
750  {
751  KdbpPrint("filter: bad class name '%.*s'\n", p - opt, opt);
752  continue;
753  }
754  if (*p == '+')
755  set |= Level;
756  else
757  clear |= Level;
758  }
759  }
760  else
761  {
762  if (*p == '-')
763  clear = MAXULONG;
764  else
765  set = MAXULONG;
766  }
767  if (*p == '+' || *p == '-')
768  p++;
769 
771  {
772  KdbpPrint("filter: '%s' is not a valid component name!\n", p);
773  return TRUE;
774  }
775 
776  /* Get current mask value */
779  }
780 
781  return TRUE;
782 }
783 
787 static BOOLEAN
789  ULONG Argc,
790  PCHAR Argv[])
791 {
792  ULONG Count;
793  ULONG ul;
794  INT i;
795  ULONGLONG Result = 0;
797  LONG InstLen;
798 
799  if (Argv[0][0] == 'x') /* display memory */
800  Count = 16;
801  else /* disassemble */
802  Count = 10;
803 
804  if (Argc >= 2)
805  {
806  /* Check for [L count] part */
807  ul = 0;
808  if (strcmp(Argv[Argc-2], "L") == 0)
809  {
810  ul = strtoul(Argv[Argc-1], NULL, 0);
811  if (ul > 0)
812  {
813  Count = ul;
814  Argc -= 2;
815  }
816  }
817  else if (Argv[Argc-1][0] == 'L')
818  {
819  ul = strtoul(Argv[Argc-1] + 1, NULL, 0);
820  if (ul > 0)
821  {
822  Count = ul;
823  Argc--;
824  }
825  }
826 
827  /* Put the remaining arguments back together */
828  Argc--;
829  for (ul = 1; ul < Argc; ul++)
830  {
831  Argv[ul][strlen(Argv[ul])] = ' ';
832  }
833  Argc++;
834  }
835 
836  /* Evaluate the expression */
837  if (Argc > 1)
838  {
839  if (!KdbpEvaluateExpression(Argv[1], KdbPromptString.Length + (Argv[1]-Argv[0]), &Result))
840  return TRUE;
841 
842  if (Result > (ULONGLONG)(~((ULONG_PTR)0)))
843  KdbpPrint("Warning: Address %I64x is beeing truncated\n",Result);
844 
846  }
847  else if (Argv[0][0] == 'x')
848  {
849  KdbpPrint("x: Address argument required.\n");
850  return TRUE;
851  }
852 
853  if (Argv[0][0] == 'x')
854  {
855  /* Display dwords */
856  ul = 0;
857 
858  while (Count > 0)
859  {
861  KdbpPrint("<%08x>:", Address);
862  else
863  KdbpPrint(":");
864 
865  i = min(4, Count);
866  Count -= i;
867 
868  while (--i >= 0)
869  {
870  if (!NT_SUCCESS(KdbpSafeReadMemory(&ul, (PVOID)Address, sizeof(ul))))
871  KdbpPrint(" ????????");
872  else
873  KdbpPrint(" %08x", ul);
874 
875  Address += sizeof(ul);
876  }
877 
878  KdbpPrint("\n");
879  }
880  }
881  else
882  {
883  /* Disassemble */
884  while (Count-- > 0)
885  {
887  KdbpPrint("<%08x>: ", Address);
888  else
889  KdbpPrint(": ");
890 
892  if (InstLen < 0)
893  {
894  KdbpPrint("<INVALID>\n");
895  return TRUE;
896  }
897 
898  KdbpPrint("\n");
899  Address += InstLen;
900  }
901  }
902 
903  return TRUE;
904 }
905 
908 static BOOLEAN
910  ULONG Argc,
911  PCHAR Argv[])
912 {
914  INT i;
915  static const PCHAR EflagsBits[32] = { " CF", NULL, " PF", " BIT3", " AF", " BIT5",
916  " ZF", " SF", " TF", " IF", " DF", " OF",
917  NULL, NULL, " NT", " BIT15", " RF", " VF",
918  " AC", " VIF", " VIP", " ID", " BIT22",
919  " BIT23", " BIT24", " BIT25", " BIT26",
920  " BIT27", " BIT28", " BIT29", " BIT30",
921  " BIT31" };
922 
923  if (Argv[0][0] == 'r') /* regs */
924  {
925  KdbpPrint("CS:EIP 0x%04x:0x%08x\n"
926  "SS:ESP 0x%04x:0x%08x\n"
927  " EAX 0x%08x EBX 0x%08x\n"
928  " ECX 0x%08x EDX 0x%08x\n"
929  " ESI 0x%08x EDI 0x%08x\n"
930  " EBP 0x%08x\n",
931  Context->SegCs & 0xFFFF, Context->Eip,
932  Context->SegSs, Context->Esp,
933  Context->Eax, Context->Ebx,
934  Context->Ecx, Context->Edx,
935  Context->Esi, Context->Edi,
936  Context->Ebp);
937 
938  /* Display the EFlags */
939  KdbpPrint("EFLAGS 0x%08x ", Context->EFlags);
940  for (i = 0; i < 32; i++)
941  {
942  if (i == 1)
943  {
944  if ((Context->EFlags & (1 << 1)) == 0)
945  KdbpPrint(" !BIT1");
946  }
947  else if (i == 12)
948  {
949  KdbpPrint(" IOPL%d", (Context->EFlags >> 12) & 3);
950  }
951  else if (i == 13)
952  {
953  }
954  else if ((Context->EFlags & (1 << i)) != 0)
955  {
956  KdbpPrint(EflagsBits[i]);
957  }
958  }
959  KdbpPrint("\n");
960  }
961  else if (Argv[0][0] == 's') /* sregs */
962  {
963  KdbpPrint("CS 0x%04x Index 0x%04x %cDT RPL%d\n",
964  Context->SegCs & 0xffff, (Context->SegCs & 0xffff) >> 3,
965  (Context->SegCs & (1 << 2)) ? 'L' : 'G', Context->SegCs & 3);
966  KdbpPrint("DS 0x%04x Index 0x%04x %cDT RPL%d\n",
967  Context->SegDs, Context->SegDs >> 3, (Context->SegDs & (1 << 2)) ? 'L' : 'G', Context->SegDs & 3);
968  KdbpPrint("ES 0x%04x Index 0x%04x %cDT RPL%d\n",
969  Context->SegEs, Context->SegEs >> 3, (Context->SegEs & (1 << 2)) ? 'L' : 'G', Context->SegEs & 3);
970  KdbpPrint("FS 0x%04x Index 0x%04x %cDT RPL%d\n",
971  Context->SegFs, Context->SegFs >> 3, (Context->SegFs & (1 << 2)) ? 'L' : 'G', Context->SegFs & 3);
972  KdbpPrint("GS 0x%04x Index 0x%04x %cDT RPL%d\n",
973  Context->SegGs, Context->SegGs >> 3, (Context->SegGs & (1 << 2)) ? 'L' : 'G', Context->SegGs & 3);
974  KdbpPrint("SS 0x%04x Index 0x%04x %cDT RPL%d\n",
975  Context->SegSs, Context->SegSs >> 3, (Context->SegSs & (1 << 2)) ? 'L' : 'G', Context->SegSs & 3);
976  }
977  else /* dregs */
978  {
979  ASSERT(Argv[0][0] == 'd');
980  KdbpPrint("DR0 0x%08x\n"
981  "DR1 0x%08x\n"
982  "DR2 0x%08x\n"
983  "DR3 0x%08x\n"
984  "DR6 0x%08x\n"
985  "DR7 0x%08x\n",
986  Context->Dr0, Context->Dr1, Context->Dr2, Context->Dr3,
987  Context->Dr6, Context->Dr7);
988  }
989 
990  return TRUE;
991 }
992 
993 static PKTSS
995  IN USHORT TssSelector,
996  OUT PULONG pType OPTIONAL,
997  IN PKDESCRIPTOR pGdtr OPTIONAL)
998 {
999  KDESCRIPTOR Gdtr;
1000  KGDTENTRY Desc;
1001  PKTSS Tss;
1002 
1003  /* Retrieve the Global Descriptor Table (user-provided or system) */
1004  if (pGdtr)
1005  Gdtr = *pGdtr;
1006  else
1007  Ke386GetGlobalDescriptorTable(&Gdtr.Limit);
1008 
1009  /* Check limits */
1010  if ((TssSelector & (sizeof(KGDTENTRY) - 1)) ||
1011  (TssSelector < sizeof(KGDTENTRY)) ||
1012  (TssSelector + sizeof(KGDTENTRY) - 1 > Gdtr.Limit))
1013  {
1014  return NULL;
1015  }
1016 
1017  /* Retrieve the descriptor */
1018  if (!NT_SUCCESS(KdbpSafeReadMemory(&Desc,
1019  (PVOID)(Gdtr.Base + TssSelector),
1020  sizeof(KGDTENTRY))))
1021  {
1022  return NULL;
1023  }
1024 
1025  /* Check for TSS32(Avl) or TSS32(Busy) */
1026  if (Desc.HighWord.Bits.Type != 9 && Desc.HighWord.Bits.Type != 11)
1027  {
1028  return NULL;
1029  }
1030  if (pType) *pType = Desc.HighWord.Bits.Type;
1031 
1032  Tss = (PKTSS)(ULONG_PTR)(Desc.BaseLow |
1033  Desc.HighWord.Bytes.BaseMid << 16 |
1034  Desc.HighWord.Bytes.BaseHi << 24);
1035 
1036  return Tss;
1037 }
1038 
1041  IN USHORT TssSelector,
1042  IN PKTSS Tss)
1043 {
1044  USHORT Backlink;
1045 
1046  if (!Tss)
1047  return FALSE;
1048 
1049  /* Retrieve the TSS Backlink */
1050  if (!NT_SUCCESS(KdbpSafeReadMemory(&Backlink,
1051  (PVOID)&Tss->Backlink,
1052  sizeof(USHORT))))
1053  {
1054  return FALSE;
1055  }
1056 
1057  return (Backlink != 0 && Backlink != TssSelector);
1058 }
1059 
1060 static BOOLEAN
1063  OUT PUSHORT TssSelector,
1064  IN OUT PKTSS* pTss,
1065  IN PKDESCRIPTOR pGdtr)
1066 {
1067  ULONG_PTR Eip, Ebp;
1068  USHORT Backlink;
1069  PKTSS Tss = *pTss;
1070 
1071  /* Retrieve the TSS Backlink */
1072  if (!NT_SUCCESS(KdbpSafeReadMemory(&Backlink,
1073  (PVOID)&Tss->Backlink,
1074  sizeof(USHORT))))
1075  {
1076  return FALSE;
1077  }
1078 
1079  /* Retrieve the parent TSS */
1080  Tss = KdbpRetrieveTss(Backlink, NULL, pGdtr);
1081  if (!Tss)
1082  return FALSE;
1083 
1084  if (!NT_SUCCESS(KdbpSafeReadMemory(&Eip,
1085  (PVOID)&Tss->Eip,
1086  sizeof(ULONG_PTR))))
1087  {
1088  return FALSE;
1089  }
1090 
1091  if (!NT_SUCCESS(KdbpSafeReadMemory(&Ebp,
1092  (PVOID)&Tss->Ebp,
1093  sizeof(ULONG_PTR))))
1094  {
1095  return FALSE;
1096  }
1097 
1098  /* Return the parent TSS and its trap frame */
1099  *TssSelector = Backlink;
1100  *pTss = Tss;
1101  Context->Eip = Eip;
1102  Context->Ebp = Ebp;
1103  return TRUE;
1104 }
1105 
1108 static BOOLEAN
1110  ULONG Argc,
1111  PCHAR Argv[])
1112 {
1113  ULONG ul;
1114  ULONGLONG Result = 0;
1116  ULONG_PTR Frame = Context.Ebp;
1118  KDESCRIPTOR Gdtr;
1119  USHORT TssSelector;
1120  PKTSS Tss;
1121 
1122  if (Argc >= 2)
1123  {
1124  /* Check for [L count] part */
1125  ul = 0;
1126  if (strcmp(Argv[Argc-2], "L") == 0)
1127  {
1128  ul = strtoul(Argv[Argc-1], NULL, 0);
1129  if (ul > 0)
1130  {
1131  Argc -= 2;
1132  }
1133  }
1134  else if (Argv[Argc-1][0] == 'L')
1135  {
1136  ul = strtoul(Argv[Argc-1] + 1, NULL, 0);
1137  if (ul > 0)
1138  {
1139  Argc--;
1140  }
1141  }
1142 
1143  /* Put the remaining arguments back together */
1144  Argc--;
1145  for (ul = 1; ul < Argc; ul++)
1146  {
1147  Argv[ul][strlen(Argv[ul])] = ' ';
1148  }
1149  Argc++;
1150  }
1151 
1152  /* Check if a Frame Address or Thread ID is given */
1153  if (Argc > 1)
1154  {
1155  if (Argv[1][0] == '*')
1156  {
1157  Argv[1]++;
1158 
1159  /* Evaluate the expression */
1160  if (!KdbpEvaluateExpression(Argv[1], KdbPromptString.Length + (Argv[1]-Argv[0]), &Result))
1161  return TRUE;
1162 
1163  if (Result > (ULONGLONG)(~((ULONG_PTR)0)))
1164  KdbpPrint("Warning: Address %I64x is beeing truncated\n", Result);
1165 
1166  Frame = (ULONG_PTR)Result;
1167  }
1168  else
1169  {
1170  KdbpPrint("Thread backtrace not supported yet!\n");
1171  return TRUE;
1172  }
1173  }
1174 
1175  /* Retrieve the Global Descriptor Table */
1176  Ke386GetGlobalDescriptorTable(&Gdtr.Limit);
1177 
1178  /* Retrieve the current (active) TSS */
1179  TssSelector = Ke386GetTr();
1180  Tss = KdbpRetrieveTss(TssSelector, NULL, &Gdtr);
1181  if (KdbpIsNestedTss(TssSelector, Tss))
1182  {
1183  /* Display the active TSS if it is nested */
1184  KdbpPrint("[Active TSS 0x%04x @ 0x%p]\n", TssSelector, Tss);
1185  }
1186 
1187  /* If no Frame Address or Thread ID was given, try printing the function at EIP */
1188  if (Argc <= 1)
1189  {
1190  KdbpPrint("Eip:\n");
1191  if (!KdbSymPrintAddress((PVOID)Context.Eip, &Context))
1192  KdbpPrint("<%08x>\n", Context.Eip);
1193  else
1194  KdbpPrint("\n");
1195  }
1196 
1197  /* Walk through the frames */
1198  KdbpPrint("Frames:\n");
1199  for (;;)
1200  {
1201  BOOLEAN GotNextFrame;
1202 
1203  if (Frame == 0)
1204  goto CheckForParentTSS;
1205 
1206  Address = 0;
1207  if (!NT_SUCCESS(KdbpSafeReadMemory(&Address, (PVOID)(Frame + sizeof(ULONG_PTR)), sizeof(ULONG_PTR))))
1208  {
1209  KdbpPrint("Couldn't access memory at 0x%p!\n", Frame + sizeof(ULONG_PTR));
1210  goto CheckForParentTSS;
1211  }
1212 
1213  if (Address == 0)
1214  goto CheckForParentTSS;
1215 
1216  GotNextFrame = NT_SUCCESS(KdbpSafeReadMemory(&Frame, (PVOID)Frame, sizeof(ULONG_PTR)));
1217  if (GotNextFrame)
1218  Context.Ebp = Frame;
1219  // else
1220  // Frame = 0;
1221 
1222  /* Print the location of the call instruction (assumed 5 bytes length) */
1223  if (!KdbSymPrintAddress((PVOID)(Address - 5), &Context))
1224  KdbpPrint("<%08x>\n", Address);
1225  else
1226  KdbpPrint("\n");
1227 
1228  if (KdbOutputAborted)
1229  break;
1230 
1231  if (!GotNextFrame)
1232  {
1233  KdbpPrint("Couldn't access memory at 0x%p!\n", Frame);
1234  goto CheckForParentTSS; // break;
1235  }
1236 
1237  continue;
1238 
1239 CheckForParentTSS:
1240  /*
1241  * We have ended the stack walking for the current (active) TSS.
1242  * Check whether this TSS was nested, and if so switch to its parent
1243  * and walk its stack.
1244  */
1245  if (!KdbpIsNestedTss(TssSelector, Tss))
1246  break; // The TSS is not nested, we stop there.
1247 
1248  GotNextFrame = KdbpContextFromPrevTss(&Context, &TssSelector, &Tss, &Gdtr);
1249  if (!GotNextFrame)
1250  {
1251  KdbpPrint("Couldn't access parent TSS 0x%04x\n", Tss->Backlink);
1252  break; // Cannot retrieve the parent TSS, we stop there.
1253  }
1254  Address = Context.Eip;
1255  Frame = Context.Ebp;
1256 
1257  KdbpPrint("[Parent TSS 0x%04x @ 0x%p]\n", TssSelector, Tss);
1258 
1260  KdbpPrint("<%08x>\n", Address);
1261  else
1262  KdbpPrint("\n");
1263  }
1264 
1265  return TRUE;
1266 }
1267 
1270 static BOOLEAN
1272  ULONG Argc,
1273  PCHAR Argv[])
1274 {
1275  /* Exit the main loop */
1276  return FALSE;
1277 }
1278 
1281 static BOOLEAN
1283  ULONG Argc,
1284  PCHAR Argv[])
1285 {
1286  ULONG Count = 1;
1287 
1288  if (Argc > 1)
1289  {
1290  Count = strtoul(Argv[1], NULL, 0);
1291  if (Count == 0)
1292  {
1293  KdbpPrint("%s: Integer argument required\n", Argv[0]);
1294  return TRUE;
1295  }
1296  }
1297 
1298  if (Argv[0][0] == 'n')
1300  else
1302 
1303  /* Set the number of single steps and return to the interrupted code. */
1305 
1306  return FALSE;
1307 }
1308 
1311 static BOOLEAN
1313  ULONG Argc,
1314  PCHAR Argv[])
1315 {
1316  LONG l;
1317  ULONG_PTR Address = 0;
1319  KDB_ACCESS_TYPE AccessType = 0;
1320  UCHAR Size = 0;
1321  UCHAR DebugReg = 0;
1322  BOOLEAN Enabled = FALSE;
1323  BOOLEAN Global = FALSE;
1325  PCHAR str1, str2, ConditionExpr, GlobalOrLocal;
1326  CHAR Buffer[20];
1327 
1329  if (l < 0)
1330  {
1331  KdbpPrint("No breakpoints.\n");
1332  return TRUE;
1333  }
1334 
1335  KdbpPrint("Breakpoints:\n");
1336  do
1337  {
1338  if (!KdbpGetBreakPointInfo(l, &Address, &Type, &Size, &AccessType, &DebugReg,
1339  &Enabled, &Global, &Process, &ConditionExpr))
1340  {
1341  continue;
1342  }
1343 
1344  if (l == KdbLastBreakPointNr)
1345  {
1346  str1 = "\x1b[1m*";
1347  str2 = "\x1b[0m";
1348  }
1349  else
1350  {
1351  str1 = " ";
1352  str2 = "";
1353  }
1354 
1355  if (Global)
1356  {
1357  GlobalOrLocal = " global";
1358  }
1359  else
1360  {
1361  GlobalOrLocal = Buffer;
1362  sprintf(Buffer, " PID 0x%08lx",
1363  (ULONG)(Process ? Process->UniqueProcessId : INVALID_HANDLE_VALUE));
1364  }
1365 
1367  {
1368  KdbpPrint(" %s%03d BPX 0x%08x%s%s%s%s%s\n",
1369  str1, l, Address,
1370  Enabled ? "" : " disabled",
1371  GlobalOrLocal,
1372  ConditionExpr ? " IF " : "",
1373  ConditionExpr ? ConditionExpr : "",
1374  str2);
1375  }
1376  else if (Type == KdbBreakPointHardware)
1377  {
1378  if (!Enabled)
1379  {
1380  KdbpPrint(" %s%03d BPM 0x%08x %-5s %-5s disabled%s%s%s%s\n", str1, l, Address,
1381  KDB_ACCESS_TYPE_TO_STRING(AccessType),
1382  Size == 1 ? "byte" : (Size == 2 ? "word" : "dword"),
1383  GlobalOrLocal,
1384  ConditionExpr ? " IF " : "",
1385  ConditionExpr ? ConditionExpr : "",
1386  str2);
1387  }
1388  else
1389  {
1390  KdbpPrint(" %s%03d BPM 0x%08x %-5s %-5s DR%d%s%s%s%s\n", str1, l, Address,
1391  KDB_ACCESS_TYPE_TO_STRING(AccessType),
1392  Size == 1 ? "byte" : (Size == 2 ? "word" : "dword"),
1393  DebugReg,
1394  GlobalOrLocal,
1395  ConditionExpr ? " IF " : "",
1396  ConditionExpr ? ConditionExpr : "",
1397  str2);
1398  }
1399  }
1400  }
1401  while ((l = KdbpGetNextBreakPointNr(l+1)) >= 0);
1402 
1403  return TRUE;
1404 }
1405 
1408 static BOOLEAN
1410  ULONG Argc,
1411  PCHAR Argv[])
1412 {
1413  PCHAR pend;
1414  ULONG BreakPointNr;
1415 
1416  if (Argc < 2)
1417  {
1418  KdbpPrint("%s: argument required\n", Argv[0]);
1419  return TRUE;
1420  }
1421 
1422  pend = Argv[1];
1423  BreakPointNr = strtoul(Argv[1], &pend, 0);
1424  if (pend == Argv[1] || *pend != '\0')
1425  {
1426  KdbpPrint("%s: integer argument required\n", Argv[0]);
1427  return TRUE;
1428  }
1429 
1430  if (Argv[0][1] == 'e') /* enable */
1431  {
1432  KdbpEnableBreakPoint(BreakPointNr, NULL);
1433  }
1434  else if (Argv [0][1] == 'd') /* disable */
1435  {
1436  KdbpDisableBreakPoint(BreakPointNr, NULL);
1437  }
1438  else /* clear */
1439  {
1440  ASSERT(Argv[0][1] == 'c');
1441  KdbpDeleteBreakPoint(BreakPointNr, NULL);
1442  }
1443 
1444  return TRUE;
1445 }
1446 
1449 static BOOLEAN
1451 {
1452  ULONGLONG Result = 0;
1455  UCHAR Size = 0;
1456  KDB_ACCESS_TYPE AccessType = 0;
1457  ULONG AddressArgIndex, i;
1458  LONG ConditionArgIndex;
1459  BOOLEAN Global = TRUE;
1460 
1461  if (Argv[0][2] == 'x') /* software breakpoint */
1462  {
1463  if (Argc < 2)
1464  {
1465  KdbpPrint("bpx: Address argument required.\n");
1466  return TRUE;
1467  }
1468 
1469  AddressArgIndex = 1;
1471  }
1472  else /* memory breakpoint */
1473  {
1474  ASSERT(Argv[0][2] == 'm');
1475 
1476  if (Argc < 2)
1477  {
1478  KdbpPrint("bpm: Access type argument required (one of r, w, rw, x)\n");
1479  return TRUE;
1480  }
1481 
1482  if (_stricmp(Argv[1], "x") == 0)
1483  AccessType = KdbAccessExec;
1484  else if (_stricmp(Argv[1], "r") == 0)
1485  AccessType = KdbAccessRead;
1486  else if (_stricmp(Argv[1], "w") == 0)
1487  AccessType = KdbAccessWrite;
1488  else if (_stricmp(Argv[1], "rw") == 0)
1489  AccessType = KdbAccessReadWrite;
1490  else
1491  {
1492  KdbpPrint("bpm: Unknown access type '%s'\n", Argv[1]);
1493  return TRUE;
1494  }
1495 
1496  if (Argc < 3)
1497  {
1498  KdbpPrint("bpm: %s argument required.\n", AccessType == KdbAccessExec ? "Address" : "Memory size");
1499  return TRUE;
1500  }
1501 
1502  AddressArgIndex = 3;
1503  if (_stricmp(Argv[2], "byte") == 0)
1504  Size = 1;
1505  else if (_stricmp(Argv[2], "word") == 0)
1506  Size = 2;
1507  else if (_stricmp(Argv[2], "dword") == 0)
1508  Size = 4;
1509  else if (AccessType == KdbAccessExec)
1510  {
1511  Size = 1;
1512  AddressArgIndex--;
1513  }
1514  else
1515  {
1516  KdbpPrint("bpm: Unknown memory size '%s'\n", Argv[2]);
1517  return TRUE;
1518  }
1519 
1520  if (Argc <= AddressArgIndex)
1521  {
1522  KdbpPrint("bpm: Address argument required.\n");
1523  return TRUE;
1524  }
1525 
1527  }
1528 
1529  /* Put the arguments back together */
1530  ConditionArgIndex = -1;
1531  for (i = AddressArgIndex; i < (Argc-1); i++)
1532  {
1533  if (strcmp(Argv[i+1], "IF") == 0) /* IF found */
1534  {
1535  ConditionArgIndex = i + 2;
1536  if ((ULONG)ConditionArgIndex >= Argc)
1537  {
1538  KdbpPrint("%s: IF requires condition expression.\n", Argv[0]);
1539  return TRUE;
1540  }
1541 
1542  for (i = ConditionArgIndex; i < (Argc-1); i++)
1543  Argv[i][strlen(Argv[i])] = ' ';
1544 
1545  break;
1546  }
1547 
1548  Argv[i][strlen(Argv[i])] = ' ';
1549  }
1550 
1551  /* Evaluate the address expression */
1552  if (!KdbpEvaluateExpression(Argv[AddressArgIndex],
1553  KdbPromptString.Length + (Argv[AddressArgIndex]-Argv[0]),
1554  &Result))
1555  {
1556  return TRUE;
1557  }
1558 
1559  if (Result > (ULONGLONG)(~((ULONG_PTR)0)))
1560  KdbpPrint("%s: Warning: Address %I64x is beeing truncated\n", Argv[0],Result);
1561 
1563 
1564  KdbpInsertBreakPoint(Address, Type, Size, AccessType,
1565  (ConditionArgIndex < 0) ? NULL : Argv[ConditionArgIndex],
1566  Global, NULL);
1567 
1568  return TRUE;
1569 }
1570 
1573 static BOOLEAN
1575  ULONG Argc,
1576  PCHAR Argv[])
1577 {
1579  PETHREAD Thread = NULL;
1581  BOOLEAN ReferencedThread = FALSE, ReferencedProcess = FALSE;
1582  PULONG Esp;
1583  PULONG Ebp;
1584  ULONG Eip;
1585  ULONG ul = 0;
1586  PCHAR State, pend, str1, str2;
1587  static const PCHAR ThreadStateToString[DeferredReady+1] =
1588  {
1589  "Initialized", "Ready", "Running",
1590  "Standby", "Terminated", "Waiting",
1591  "Transition", "DeferredReady"
1592  };
1593 
1595 
1596  if (Argc >= 2 && _stricmp(Argv[1], "list") == 0)
1597  {
1599 
1600  if (Argc >= 3)
1601  {
1602  ul = strtoul(Argv[2], &pend, 0);
1603  if (Argv[2] == pend)
1604  {
1605  KdbpPrint("thread: '%s' is not a valid process id!\n", Argv[2]);
1606  return TRUE;
1607  }
1608 
1610  {
1611  KdbpPrint("thread: Invalid process id!\n");
1612  return TRUE;
1613  }
1614 
1615  /* Remember our reference */
1616  ReferencedProcess = TRUE;
1617  }
1618 
1619  Entry = Process->ThreadListHead.Flink;
1620  if (Entry == &Process->ThreadListHead)
1621  {
1622  if (Argc >= 3)
1623  KdbpPrint("No threads in process 0x%08x!\n", ul);
1624  else
1625  KdbpPrint("No threads in current process!\n");
1626 
1627  if (ReferencedProcess)
1629 
1630  return TRUE;
1631  }
1632 
1633  KdbpPrint(" TID State Prior. Affinity EBP EIP\n");
1634  do
1635  {
1636  Thread = CONTAINING_RECORD(Entry, ETHREAD, ThreadListEntry);
1637 
1638  if (Thread == KdbCurrentThread)
1639  {
1640  str1 = "\x1b[1m*";
1641  str2 = "\x1b[0m";
1642  }
1643  else
1644  {
1645  str1 = " ";
1646  str2 = "";
1647  }
1648 
1649  if (!Thread->Tcb.InitialStack)
1650  {
1651  /* Thread has no kernel stack (probably terminated) */
1652  Esp = Ebp = NULL;
1653  Eip = 0;
1654  }
1655  else if (Thread->Tcb.TrapFrame)
1656  {
1658  Esp = (PULONG)Thread->Tcb.TrapFrame->TempEsp;
1659  else
1661 
1662  Ebp = (PULONG)Thread->Tcb.TrapFrame->Ebp;
1663  Eip = Thread->Tcb.TrapFrame->Eip;
1664  }
1665  else
1666  {
1667  Esp = (PULONG)Thread->Tcb.KernelStack;
1668  Ebp = (PULONG)Esp[4];
1669  Eip = 0;
1670 
1671  if (Ebp) /* FIXME: Should we attach to the process to read Ebp[1]? */
1672  KdbpSafeReadMemory(&Eip, Ebp + 1, sizeof(Eip));
1673  }
1674 
1675  if (Thread->Tcb.State < (DeferredReady + 1))
1676  State = ThreadStateToString[Thread->Tcb.State];
1677  else
1678  State = "Unknown";
1679 
1680  KdbpPrint(" %s0x%08x %-11s %3d 0x%08x 0x%08x 0x%08x%s\n",
1681  str1,
1683  State,
1684  Thread->Tcb.Priority,
1685  Thread->Tcb.Affinity,
1686  Ebp,
1687  Eip,
1688  str2);
1689 
1690  Entry = Entry->Flink;
1691  }
1692  while (Entry != &Process->ThreadListHead);
1693 
1694  /* Release our reference, if any */
1695  if (ReferencedProcess)
1697  }
1698  else if (Argc >= 2 && _stricmp(Argv[1], "attach") == 0)
1699  {
1700  if (Argc < 3)
1701  {
1702  KdbpPrint("thread attach: thread id argument required!\n");
1703  return TRUE;
1704  }
1705 
1706  ul = strtoul(Argv[2], &pend, 0);
1707  if (Argv[2] == pend)
1708  {
1709  KdbpPrint("thread attach: '%s' is not a valid thread id!\n", Argv[2]);
1710  return TRUE;
1711  }
1712 
1713  if (!KdbpAttachToThread((PVOID)ul))
1714  {
1715  return TRUE;
1716  }
1717 
1718  KdbpPrint("Attached to thread 0x%08x.\n", ul);
1719  }
1720  else
1721  {
1723 
1724  if (Argc >= 2)
1725  {
1726  ul = strtoul(Argv[1], &pend, 0);
1727  if (Argv[1] == pend)
1728  {
1729  KdbpPrint("thread: '%s' is not a valid thread id!\n", Argv[1]);
1730  return TRUE;
1731  }
1732 
1734  {
1735  KdbpPrint("thread: Invalid thread id!\n");
1736  return TRUE;
1737  }
1738 
1739  /* Remember our reference */
1740  ReferencedThread = TRUE;
1741  }
1742 
1743  if (Thread->Tcb.State < (DeferredReady + 1))
1744  State = ThreadStateToString[Thread->Tcb.State];
1745  else
1746  State = "Unknown";
1747 
1748  KdbpPrint("%s"
1749  " TID: 0x%08x\n"
1750  " State: %s (0x%x)\n"
1751  " Priority: %d\n"
1752  " Affinity: 0x%08x\n"
1753  " Initial Stack: 0x%08x\n"
1754  " Stack Limit: 0x%08x\n"
1755  " Stack Base: 0x%08x\n"
1756  " Kernel Stack: 0x%08x\n"
1757  " Trap Frame: 0x%08x\n"
1758  " NPX State: %s (0x%x)\n",
1759  (Argc < 2) ? "Current Thread:\n" : "",
1761  State, Thread->Tcb.State,
1762  Thread->Tcb.Priority,
1763  Thread->Tcb.Affinity,
1766  Thread->Tcb.StackBase,
1768  Thread->Tcb.TrapFrame,
1770 
1771  /* Release our reference if we had one */
1772  if (ReferencedThread)
1774  }
1775 
1776  return TRUE;
1777 }
1778 
1781 static BOOLEAN
1783  ULONG Argc,
1784  PCHAR Argv[])
1785 {
1788  BOOLEAN ReferencedProcess = FALSE;
1789  PCHAR State, pend, str1, str2;
1790  ULONG ul;
1792 
1793  if (Argc >= 2 && _stricmp(Argv[1], "list") == 0)
1794  {
1796  if (!Entry || Entry == &PsActiveProcessHead)
1797  {
1798  KdbpPrint("No processes in the system!\n");
1799  return TRUE;
1800  }
1801 
1802  KdbpPrint(" PID State Filename\n");
1803  do
1804  {
1805  Process = CONTAINING_RECORD(Entry, EPROCESS, ActiveProcessLinks);
1806 
1807  if (Process == KdbCurrentProcess)
1808  {
1809  str1 = "\x1b[1m*";
1810  str2 = "\x1b[0m";
1811  }
1812  else
1813  {
1814  str1 = " ";
1815  str2 = "";
1816  }
1817 
1818  State = ((Process->Pcb.State == ProcessInMemory) ? "In Memory" :
1819  ((Process->Pcb.State == ProcessOutOfMemory) ? "Out of Memory" : "In Transition"));
1820 
1821  KdbpPrint(" %s0x%08x %-10s %s%s\n",
1822  str1,
1823  Process->UniqueProcessId,
1824  State,
1825  Process->ImageFileName,
1826  str2);
1827 
1828  Entry = Entry->Flink;
1829  }
1830  while(Entry != &PsActiveProcessHead);
1831  }
1832  else if (Argc >= 2 && _stricmp(Argv[1], "attach") == 0)
1833  {
1834  if (Argc < 3)
1835  {
1836  KdbpPrint("process attach: process id argument required!\n");
1837  return TRUE;
1838  }
1839 
1840  ul = strtoul(Argv[2], &pend, 0);
1841  if (Argv[2] == pend)
1842  {
1843  KdbpPrint("process attach: '%s' is not a valid process id!\n", Argv[2]);
1844  return TRUE;
1845  }
1846 
1847  if (!KdbpAttachToProcess((PVOID)ul))
1848  {
1849  return TRUE;
1850  }
1851 
1852  KdbpPrint("Attached to process 0x%08x, thread 0x%08x.\n", (ULONG)ul,
1854  }
1855  else
1856  {
1858 
1859  if (Argc >= 2)
1860  {
1861  ul = strtoul(Argv[1], &pend, 0);
1862  if (Argv[1] == pend)
1863  {
1864  KdbpPrint("proc: '%s' is not a valid process id!\n", Argv[1]);
1865  return TRUE;
1866  }
1867 
1869  {
1870  KdbpPrint("proc: Invalid process id!\n");
1871  return TRUE;
1872  }
1873 
1874  /* Remember our reference */
1875  ReferencedProcess = TRUE;
1876  }
1877 
1878  State = ((Process->Pcb.State == ProcessInMemory) ? "In Memory" :
1879  ((Process->Pcb.State == ProcessOutOfMemory) ? "Out of Memory" : "In Transition"));
1880  KdbpPrint("%s"
1881  " PID: 0x%08x\n"
1882  " State: %s (0x%x)\n"
1883  " Image Filename: %s\n",
1884  (Argc < 2) ? "Current process:\n" : "",
1885  Process->UniqueProcessId,
1886  State, Process->Pcb.State,
1887  Process->ImageFileName);
1888 
1889  /* Release our reference, if any */
1890  if (ReferencedProcess)
1892  }
1893 
1894  return TRUE;
1895 }
1896 
1899 static BOOLEAN
1901  ULONG Argc,
1902  PCHAR Argv[])
1903 {
1904  ULONGLONG Result = 0;
1906  PLDR_DATA_TABLE_ENTRY LdrEntry;
1907  BOOLEAN DisplayOnlyOneModule = FALSE;
1908  INT i = 0;
1909 
1910  if (Argc >= 2)
1911  {
1912  /* Put the arguments back together */
1913  Argc--;
1914  while (--Argc >= 1)
1915  Argv[Argc][strlen(Argv[Argc])] = ' ';
1916 
1917  /* Evaluate the expression */
1918  if (!KdbpEvaluateExpression(Argv[1], KdbPromptString.Length + (Argv[1]-Argv[0]), &Result))
1919  {
1920  return TRUE;
1921  }
1922 
1923  if (Result > (ULONGLONG)(~((ULONG_PTR)0)))
1924  KdbpPrint("%s: Warning: Address %I64x is beeing truncated\n", Argv[0],Result);
1925 
1927 
1928  if (!KdbpSymFindModule((PVOID)Address, NULL, -1, &LdrEntry))
1929  {
1930  KdbpPrint("No module containing address 0x%p found!\n", Address);
1931  return TRUE;
1932  }
1933 
1934  DisplayOnlyOneModule = TRUE;
1935  }
1936  else
1937  {
1938  if (!KdbpSymFindModule(NULL, NULL, 0, &LdrEntry))
1939  {
1940  ULONG_PTR ntoskrnlBase = ((ULONG_PTR)KdbpCmdMod) & 0xfff00000;
1941  KdbpPrint(" Base Size Name\n");
1942  KdbpPrint(" %08x %08x %s\n", ntoskrnlBase, 0, "ntoskrnl.exe");
1943  return TRUE;
1944  }
1945 
1946  i = 1;
1947  }
1948 
1949  KdbpPrint(" Base Size Name\n");
1950  for (;;)
1951  {
1952  KdbpPrint(" %08x %08x %wZ\n", LdrEntry->DllBase, LdrEntry->SizeOfImage, &LdrEntry->BaseDllName);
1953 
1954  if(DisplayOnlyOneModule || !KdbpSymFindModule(NULL, NULL, i++, &LdrEntry))
1955  break;
1956  }
1957 
1958  return TRUE;
1959 }
1960 
1963 static BOOLEAN
1965  ULONG Argc,
1966  PCHAR Argv[])
1967 {
1968  KDESCRIPTOR Reg;
1969  ULONG SegDesc[2];
1970  ULONG SegBase;
1971  ULONG SegLimit;
1972  PCHAR SegType;
1973  USHORT SegSel;
1974  UCHAR Type, Dpl;
1975  INT i;
1976  ULONG ul;
1977 
1978  if (Argv[0][0] == 'i')
1979  {
1980  /* Read IDTR */
1981  __sidt(&Reg.Limit);
1982 
1983  if (Reg.Limit < 7)
1984  {
1985  KdbpPrint("Interrupt descriptor table is empty.\n");
1986  return TRUE;
1987  }
1988 
1989  KdbpPrint("IDT Base: 0x%08x Limit: 0x%04x\n", Reg.Base, Reg.Limit);
1990  KdbpPrint(" Idx Type Seg. Sel. Offset DPL\n");
1991 
1992  for (i = 0; (i + sizeof(SegDesc) - 1) <= Reg.Limit; i += 8)
1993  {
1994  if (!NT_SUCCESS(KdbpSafeReadMemory(SegDesc, (PVOID)(Reg.Base + i), sizeof(SegDesc))))
1995  {
1996  KdbpPrint("Couldn't access memory at 0x%08x!\n", Reg.Base + i);
1997  return TRUE;
1998  }
1999 
2000  Dpl = ((SegDesc[1] >> 13) & 3);
2001  if ((SegDesc[1] & 0x1f00) == 0x0500) /* Task gate */
2002  SegType = "TASKGATE";
2003  else if ((SegDesc[1] & 0x1fe0) == 0x0e00) /* 32 bit Interrupt gate */
2004  SegType = "INTGATE32";
2005  else if ((SegDesc[1] & 0x1fe0) == 0x0600) /* 16 bit Interrupt gate */
2006  SegType = "INTGATE16";
2007  else if ((SegDesc[1] & 0x1fe0) == 0x0f00) /* 32 bit Trap gate */
2008  SegType = "TRAPGATE32";
2009  else if ((SegDesc[1] & 0x1fe0) == 0x0700) /* 16 bit Trap gate */
2010  SegType = "TRAPGATE16";
2011  else
2012  SegType = "UNKNOWN";
2013 
2014  if ((SegDesc[1] & (1 << 15)) == 0) /* not present */
2015  {
2016  KdbpPrint(" %03d %-10s [NP] [NP] %02d\n",
2017  i / 8, SegType, Dpl);
2018  }
2019  else if ((SegDesc[1] & 0x1f00) == 0x0500) /* Task gate */
2020  {
2021  SegSel = SegDesc[0] >> 16;
2022  KdbpPrint(" %03d %-10s 0x%04x %02d\n",
2023  i / 8, SegType, SegSel, Dpl);
2024  }
2025  else
2026  {
2027  SegSel = SegDesc[0] >> 16;
2028  SegBase = (SegDesc[1] & 0xffff0000) | (SegDesc[0] & 0x0000ffff);
2029  KdbpPrint(" %03d %-10s 0x%04x 0x%08x %02d\n",
2030  i / 8, SegType, SegSel, SegBase, Dpl);
2031  }
2032  }
2033  }
2034  else
2035  {
2036  ul = 0;
2037 
2038  if (Argv[0][0] == 'g')
2039  {
2040  /* Read GDTR */
2041  Ke386GetGlobalDescriptorTable(&Reg.Limit);
2042  i = 8;
2043  }
2044  else
2045  {
2046  ASSERT(Argv[0][0] == 'l');
2047 
2048  /* Read LDTR */
2049  Reg.Limit = Ke386GetLocalDescriptorTable();
2050  Reg.Base = 0;
2051  i = 0;
2052  ul = 1 << 2;
2053  }
2054 
2055  if (Reg.Limit < 7)
2056  {
2057  KdbpPrint("%s descriptor table is empty.\n",
2058  Argv[0][0] == 'g' ? "Global" : "Local");
2059  return TRUE;
2060  }
2061 
2062  KdbpPrint("%cDT Base: 0x%08x Limit: 0x%04x\n",
2063  Argv[0][0] == 'g' ? 'G' : 'L', Reg.Base, Reg.Limit);
2064  KdbpPrint(" Idx Sel. Type Base Limit DPL Attribs\n");
2065 
2066  for (; (i + sizeof(SegDesc) - 1) <= Reg.Limit; i += 8)
2067  {
2068  if (!NT_SUCCESS(KdbpSafeReadMemory(SegDesc, (PVOID)(Reg.Base + i), sizeof(SegDesc))))
2069  {
2070  KdbpPrint("Couldn't access memory at 0x%08x!\n", Reg.Base + i);
2071  return TRUE;
2072  }
2073 
2074  Dpl = ((SegDesc[1] >> 13) & 3);
2075  Type = ((SegDesc[1] >> 8) & 0xf);
2076 
2077  SegBase = SegDesc[0] >> 16;
2078  SegBase |= (SegDesc[1] & 0xff) << 16;
2079  SegBase |= SegDesc[1] & 0xff000000;
2080  SegLimit = SegDesc[0] & 0x0000ffff;
2081  SegLimit |= (SegDesc[1] >> 16) & 0xf;
2082 
2083  if ((SegDesc[1] & (1 << 23)) != 0)
2084  {
2085  SegLimit *= 4096;
2086  SegLimit += 4095;
2087  }
2088  else
2089  {
2090  SegLimit++;
2091  }
2092 
2093  if ((SegDesc[1] & (1 << 12)) == 0) /* System segment */
2094  {
2095  switch (Type)
2096  {
2097  case 1: SegType = "TSS16(Avl)"; break;
2098  case 2: SegType = "LDT"; break;
2099  case 3: SegType = "TSS16(Busy)"; break;
2100  case 4: SegType = "CALLGATE16"; break;
2101  case 5: SegType = "TASKGATE"; break;
2102  case 6: SegType = "INTGATE16"; break;
2103  case 7: SegType = "TRAPGATE16"; break;
2104  case 9: SegType = "TSS32(Avl)"; break;
2105  case 11: SegType = "TSS32(Busy)"; break;
2106  case 12: SegType = "CALLGATE32"; break;
2107  case 14: SegType = "INTGATE32"; break;
2108  case 15: SegType = "TRAPGATE32"; break;
2109  default: SegType = "UNKNOWN"; break;
2110  }
2111 
2112  if (!(Type >= 1 && Type <= 3) &&
2113  Type != 9 && Type != 11)
2114  {
2115  SegBase = 0;
2116  SegLimit = 0;
2117  }
2118  }
2119  else if ((SegDesc[1] & (1 << 11)) == 0) /* Data segment */
2120  {
2121  if ((SegDesc[1] & (1 << 22)) != 0)
2122  SegType = "DATA32";
2123  else
2124  SegType = "DATA16";
2125  }
2126  else /* Code segment */
2127  {
2128  if ((SegDesc[1] & (1 << 22)) != 0)
2129  SegType = "CODE32";
2130  else
2131  SegType = "CODE16";
2132  }
2133 
2134  if ((SegDesc[1] & (1 << 15)) == 0) /* Not present */
2135  {
2136  KdbpPrint(" %03d 0x%04x %-11s [NP] [NP] %02d NP\n",
2137  i / 8, i | Dpl | ul, SegType, Dpl);
2138  }
2139  else
2140  {
2141  KdbpPrint(" %03d 0x%04x %-11s 0x%08x 0x%08x %02d ",
2142  i / 8, i | Dpl | ul, SegType, SegBase, SegLimit, Dpl);
2143 
2144  if ((SegDesc[1] & (1 << 12)) == 0) /* System segment */
2145  {
2146  /* FIXME: Display system segment */
2147  }
2148  else if ((SegDesc[1] & (1 << 11)) == 0) /* Data segment */
2149  {
2150  if ((SegDesc[1] & (1 << 10)) != 0) /* Expand-down */
2151  KdbpPrint(" E");
2152 
2153  KdbpPrint((SegDesc[1] & (1 << 9)) ? " R/W" : " R");
2154 
2155  if ((SegDesc[1] & (1 << 8)) != 0)
2156  KdbpPrint(" A");
2157  }
2158  else /* Code segment */
2159  {
2160  if ((SegDesc[1] & (1 << 10)) != 0) /* Conforming */
2161  KdbpPrint(" C");
2162 
2163  KdbpPrint((SegDesc[1] & (1 << 9)) ? " R/X" : " X");
2164 
2165  if ((SegDesc[1] & (1 << 8)) != 0)
2166  KdbpPrint(" A");
2167  }
2168 
2169  if ((SegDesc[1] & (1 << 20)) != 0)
2170  KdbpPrint(" AVL");
2171 
2172  KdbpPrint("\n");
2173  }
2174  }
2175  }
2176 
2177  return TRUE;
2178 }
2179 
2182 static BOOLEAN
2184  ULONG Argc,
2185  PCHAR Argv[])
2186 {
2187  PKIPCR Pcr = (PKIPCR)KeGetPcr();
2188 
2189  KdbpPrint("Current PCR is at 0x%p.\n", Pcr);
2190  KdbpPrint(" Tib.ExceptionList: 0x%08x\n"
2191  " Tib.StackBase: 0x%08x\n"
2192  " Tib.StackLimit: 0x%08x\n"
2193  " Tib.SubSystemTib: 0x%08x\n"
2194  " Tib.FiberData/Version: 0x%08x\n"
2195  " Tib.ArbitraryUserPointer: 0x%08x\n"
2196  " Tib.Self: 0x%08x\n"
2197  " SelfPcr: 0x%08x\n"
2198  " PCRCB: 0x%08x\n"
2199  " Irql: 0x%02x\n"
2200  " IRR: 0x%08x\n"
2201  " IrrActive: 0x%08x\n"
2202  " IDR: 0x%08x\n"
2203  " KdVersionBlock: 0x%08x\n"
2204  " IDT: 0x%08x\n"
2205  " GDT: 0x%08x\n"
2206  " TSS: 0x%08x\n"
2207  " MajorVersion: 0x%04x\n"
2208  " MinorVersion: 0x%04x\n"
2209  " SetMember: 0x%08x\n"
2210  " StallScaleFactor: 0x%08x\n"
2211  " Number: 0x%02x\n"
2212  " L2CacheAssociativity: 0x%02x\n"
2213  " VdmAlert: 0x%08x\n"
2214  " L2CacheSize: 0x%08x\n"
2215  " InterruptMode: 0x%08x\n",
2218  Pcr->NtTib.Self, Pcr->SelfPcr, Pcr->Prcb, Pcr->Irql, Pcr->IRR, Pcr->IrrActive,
2219  Pcr->IDR, Pcr->KdVersionBlock, Pcr->IDT, Pcr->GDT, Pcr->TSS,
2220  Pcr->MajorVersion, Pcr->MinorVersion, Pcr->SetMember, Pcr->StallScaleFactor,
2222  Pcr->VdmAlert, Pcr->SecondLevelCacheSize, Pcr->InterruptMode);
2223 
2224  return TRUE;
2225 }
2226 
2229 static BOOLEAN
2231  ULONG Argc,
2232  PCHAR Argv[])
2233 {
2234  USHORT TssSelector;
2235  PKTSS Tss = NULL;
2236 
2237  if (Argc >= 2)
2238  {
2239  /*
2240  * Specified TSS via its selector [selector] or descriptor address [*descaddr].
2241  * Note that we ignore any other argument values.
2242  */
2243  PCHAR Param, pszNext;
2244  ULONG ulValue;
2245 
2246  Param = Argv[1];
2247  if (Argv[1][0] == '*')
2248  ++Param;
2249 
2250  ulValue = strtoul(Param, &pszNext, 0);
2251  if (pszNext && *pszNext)
2252  {
2253  KdbpPrint("Invalid TSS specification.\n");
2254  return TRUE;
2255  }
2256 
2257  if (Argv[1][0] == '*')
2258  {
2259  /* Descriptor specified */
2260  TssSelector = 0; // Unknown selector!
2261  // TODO: Room for improvement: Find the TSS descriptor
2262  // in the GDT so as to validate it.
2263  Tss = (PKTSS)(ULONG_PTR)ulValue;
2264  if (!Tss)
2265  {
2266  KdbpPrint("Invalid 32-bit TSS descriptor.\n");
2267  return TRUE;
2268  }
2269  }
2270  else
2271  {
2272  /* Selector specified, retrive the corresponding TSS */
2273  TssSelector = (USHORT)ulValue;
2274  Tss = KdbpRetrieveTss(TssSelector, NULL, NULL);
2275  if (!Tss)
2276  {
2277  KdbpPrint("Invalid 32-bit TSS selector.\n");
2278  return TRUE;
2279  }
2280  }
2281  }
2282 
2283  if (!Tss)
2284  {
2285  /* If no TSS was specified, use the current TSS descriptor */
2286  TssSelector = Ke386GetTr();
2287  Tss = KeGetPcr()->TSS;
2288  // NOTE: If everything works OK, Tss is the current TSS corresponding to the TR selector.
2289  }
2290 
2291  KdbpPrint("%s TSS 0x%04x is at 0x%p.\n",
2292  (Tss == KeGetPcr()->TSS) ? "Current" : "Specified", TssSelector, Tss);
2293  KdbpPrint(" Backlink: 0x%04x\n"
2294  " Ss0:Esp0: 0x%04x:0x%08x\n"
2295  // NOTE: Ss1:Esp1 and Ss2:Esp2: are in the NotUsed1 field.
2296  " CR3: 0x%08x\n"
2297  " EFlags: 0x%08x\n"
2298  " Eax: 0x%08x\n"
2299  " Ebx: 0x%08x\n"
2300  " Ecx: 0x%08x\n"
2301  " Edx: 0x%08x\n"
2302  " Esi: 0x%08x\n"
2303  " Edi: 0x%08x\n"
2304  " Eip: 0x%08x\n"
2305  " Esp: 0x%08x\n"
2306  " Ebp: 0x%08x\n"
2307  " Cs: 0x%04x\n"
2308  " Ss: 0x%04x\n"
2309  " Ds: 0x%04x\n"
2310  " Es: 0x%04x\n"
2311  " Fs: 0x%04x\n"
2312  " Gs: 0x%04x\n"
2313  " LDT: 0x%04x\n"
2314  " Flags: 0x%04x\n"
2315  " IoMapBase: 0x%04x\n",
2316  Tss->Backlink, Tss->Ss0, Tss->Esp0, Tss->CR3, Tss->EFlags,
2317  Tss->Eax, Tss->Ebx, Tss->Ecx, Tss->Edx, Tss->Esi, Tss->Edi,
2318  Tss->Eip, Tss->Esp, Tss->Ebp,
2319  Tss->Cs, Tss->Ss, Tss->Ds, Tss->Es, Tss->Fs, Tss->Gs,
2320  Tss->LDT, Tss->Flags, Tss->IoMapBase);
2321 
2322  return TRUE;
2323 }
2324 
2327 static BOOLEAN
2329  ULONG Argc,
2330  PCHAR Argv[])
2331 {
2332  /* Set the flag and quit looping */
2334  return FALSE;
2335 }
2336 
2337 static BOOLEAN
2339  ULONG Argc,
2340  PCHAR Argv[])
2341 {
2342  /* Reboot immediately (we do not return) */
2344  return FALSE;
2345 }
2346 
2347 
2348 VOID
2349 KdbpPager(
2350  IN PCHAR Buffer,
2351  IN ULONG BufLength);
2352 
2358 static BOOLEAN
2360  ULONG Argc,
2361  PCHAR Argv[])
2362 {
2363  ULONG beg, end;
2364 
2365  KdbpIsInDmesgMode = TRUE; /* Toggle logging flag */
2366  if (!KdpDmesgBuffer)
2367  {
2368  KdbpPrint("Dmesg: error, buffer is not allocated! /DEBUGPORT=SCREEN kernel param required for dmesg.\n");
2369  return TRUE;
2370  }
2371 
2372  KdbpPrint("*** Dmesg *** TotalWritten=%lu, BufferSize=%lu, CurrentPosition=%lu\n",
2374 
2375  /* Pass data to the pager */
2378 
2379  /* No roll-overs, and overwritten=lost bytes */
2381  {
2382  /* Show buffer (KdpDmesgBuffer + beg, num) */
2384  }
2385  else
2386  {
2387  /* Show 2 buffers: (KdpDmesgBuffer + beg, KdpDmesgBufferSize - beg)
2388  * and: (KdpDmesgBuffer, end) */
2390  KdbpPrint("*** Dmesg: buffer rollup ***\n");
2392  }
2393  KdbpPrint("*** Dmesg: end of output ***\n");
2394 
2395  KdbpIsInDmesgMode = FALSE; /* Toggle logging flag */
2396 
2397  return TRUE;
2398 }
2399 
2402 static BOOLEAN
2404  ULONG Argc,
2405  PCHAR Argv[])
2406 {
2407  LONG l;
2408  BOOLEAN First;
2409  PCHAR pend = 0;
2410  KDB_ENTER_CONDITION ConditionFirst = KdbDoNotEnter;
2411  KDB_ENTER_CONDITION ConditionLast = KdbDoNotEnter;
2412 
2413  static const PCHAR ExceptionNames[21] =
2414  {
2415  "ZERODEVIDE", "DEBUGTRAP", "NMI", "INT3", "OVERFLOW", "BOUND", "INVALIDOP",
2416  "NOMATHCOP", "DOUBLEFAULT", "RESERVED(9)", "INVALIDTSS", "SEGMENTNOTPRESENT",
2417  "STACKFAULT", "GPF", "PAGEFAULT", "RESERVED(15)", "MATHFAULT", "ALIGNMENTCHECK",
2418  "MACHINECHECK", "SIMDFAULT", "OTHERS"
2419  };
2420 
2421  if (Argc == 1)
2422  {
2423  KdbpPrint("Available settings:\n");
2424  KdbpPrint(" syntax [intel|at&t]\n");
2425  KdbpPrint(" condition [exception|*] [first|last] [never|always|kmode|umode]\n");
2426  KdbpPrint(" break_on_module_load [true|false]\n");
2427  }
2428  else if (strcmp(Argv[1], "syntax") == 0)
2429  {
2430  if (Argc == 2)
2431  {
2432  KdbpPrint("syntax = %s\n", KdbUseIntelSyntax ? "intel" : "at&t");
2433  }
2434  else if (Argc >= 3)
2435  {
2436  if (_stricmp(Argv[2], "intel") == 0)
2438  else if (_stricmp(Argv[2], "at&t") == 0)
2440  else
2441  KdbpPrint("Unknown syntax '%s'.\n", Argv[2]);
2442  }
2443  }
2444  else if (strcmp(Argv[1], "condition") == 0)
2445  {
2446  if (Argc == 2)
2447  {
2448  KdbpPrint("Conditions: (First) (Last)\n");
2449  for (l = 0; l < RTL_NUMBER_OF(ExceptionNames) - 1; l++)
2450  {
2451  if (!ExceptionNames[l])
2452  continue;
2453 
2454  if (!KdbpGetEnterCondition(l, TRUE, &ConditionFirst))
2455  ASSERT(FALSE);
2456 
2457  if (!KdbpGetEnterCondition(l, FALSE, &ConditionLast))
2458  ASSERT(FALSE);
2459 
2460  KdbpPrint(" #%02d %-20s %-8s %-8s\n", l, ExceptionNames[l],
2461  KDB_ENTER_CONDITION_TO_STRING(ConditionFirst),
2462  KDB_ENTER_CONDITION_TO_STRING(ConditionLast));
2463  }
2464 
2465  ASSERT(l == (RTL_NUMBER_OF(ExceptionNames) - 1));
2466  KdbpPrint(" %-20s %-8s %-8s\n", ExceptionNames[l],
2467  KDB_ENTER_CONDITION_TO_STRING(ConditionFirst),
2468  KDB_ENTER_CONDITION_TO_STRING(ConditionLast));
2469  }
2470  else
2471  {
2472  if (Argc >= 5 && strcmp(Argv[2], "*") == 0) /* Allow * only when setting condition */
2473  {
2474  l = -1;
2475  }
2476  else
2477  {
2478  l = strtoul(Argv[2], &pend, 0);
2479 
2480  if (Argv[2] == pend)
2481  {
2482  for (l = 0; l < RTL_NUMBER_OF(ExceptionNames); l++)
2483  {
2484  if (!ExceptionNames[l])
2485  continue;
2486 
2487  if (_stricmp(ExceptionNames[l], Argv[2]) == 0)
2488  break;
2489  }
2490  }
2491 
2492  if (l >= RTL_NUMBER_OF(ExceptionNames))
2493  {
2494  KdbpPrint("Unknown exception '%s'.\n", Argv[2]);
2495  return TRUE;
2496  }
2497  }
2498 
2499  if (Argc > 4)
2500  {
2501  if (_stricmp(Argv[3], "first") == 0)
2502  First = TRUE;
2503  else if (_stricmp(Argv[3], "last") == 0)
2504  First = FALSE;
2505  else
2506  {
2507  KdbpPrint("set condition: second argument must be 'first' or 'last'\n");
2508  return TRUE;
2509  }
2510 
2511  if (_stricmp(Argv[4], "never") == 0)
2512  ConditionFirst = KdbDoNotEnter;
2513  else if (_stricmp(Argv[4], "always") == 0)
2514  ConditionFirst = KdbEnterAlways;
2515  else if (_stricmp(Argv[4], "umode") == 0)
2516  ConditionFirst = KdbEnterFromUmode;
2517  else if (_stricmp(Argv[4], "kmode") == 0)
2518  ConditionFirst = KdbEnterFromKmode;
2519  else
2520  {
2521  KdbpPrint("set condition: third argument must be 'never', 'always', 'umode' or 'kmode'\n");
2522  return TRUE;
2523  }
2524 
2525  if (!KdbpSetEnterCondition(l, First, ConditionFirst))
2526  {
2527  if (l >= 0)
2528  KdbpPrint("Couldn't change condition for exception #%02d\n", l);
2529  else
2530  KdbpPrint("Couldn't change condition for all exceptions\n", l);
2531  }
2532  }
2533  else /* Argc >= 3 */
2534  {
2535  if (!KdbpGetEnterCondition(l, TRUE, &ConditionFirst))
2536  ASSERT(FALSE);
2537 
2538  if (!KdbpGetEnterCondition(l, FALSE, &ConditionLast))
2539  ASSERT(FALSE);
2540 
2541  if (l < (RTL_NUMBER_OF(ExceptionNames) - 1))
2542  {
2543  KdbpPrint("Condition for exception #%02d (%s): FirstChance %s LastChance %s\n",
2544  l, ExceptionNames[l],
2545  KDB_ENTER_CONDITION_TO_STRING(ConditionFirst),
2546  KDB_ENTER_CONDITION_TO_STRING(ConditionLast));
2547  }
2548  else
2549  {
2550  KdbpPrint("Condition for all other exceptions: FirstChance %s LastChance %s\n",
2551  KDB_ENTER_CONDITION_TO_STRING(ConditionFirst),
2552  KDB_ENTER_CONDITION_TO_STRING(ConditionLast));
2553  }
2554  }
2555  }
2556  }
2557  else if (strcmp(Argv[1], "break_on_module_load") == 0)
2558  {
2559  if (Argc == 2)
2560  KdbpPrint("break_on_module_load = %s\n", KdbBreakOnModuleLoad ? "enabled" : "disabled");
2561  else if (Argc >= 3)
2562  {
2563  if (_stricmp(Argv[2], "enable") == 0 || _stricmp(Argv[2], "enabled") == 0 || _stricmp(Argv[2], "true") == 0)
2565  else if (_stricmp(Argv[2], "disable") == 0 || _stricmp(Argv[2], "disabled") == 0 || _stricmp(Argv[2], "false") == 0)
2567  else
2568  KdbpPrint("Unknown setting '%s'.\n", Argv[2]);
2569  }
2570  }
2571  else
2572  {
2573  KdbpPrint("Unknown setting '%s'.\n", Argv[1]);
2574  }
2575 
2576  return TRUE;
2577 }
2578 
2581 static BOOLEAN
2583  ULONG Argc,
2584  PCHAR Argv[])
2585 {
2586  ULONG i;
2587 
2588  KdbpPrint("Kernel debugger commands:\n");
2589  for (i = 0; i < RTL_NUMBER_OF(KdbDebuggerCommands); i++)
2590  {
2591  if (!KdbDebuggerCommands[i].Syntax) /* Command group */
2592  {
2593  if (i > 0)
2594  KdbpPrint("\n");
2595 
2596  KdbpPrint("\x1b[7m* %s:\x1b[0m\n", KdbDebuggerCommands[i].Help);
2597  continue;
2598  }
2599 
2600  KdbpPrint(" %-20s - %s\n",
2603  }
2604 
2605  return TRUE;
2606 }
2607 
2617 VOID
2619  IN PCHAR Format,
2620  IN ... OPTIONAL)
2621 {
2622  static CHAR Buffer[4096];
2623  static BOOLEAN TerminalInitialized = FALSE;
2624  static BOOLEAN TerminalConnected = FALSE;
2625  static BOOLEAN TerminalReportsSize = TRUE;
2626  CHAR c = '\0';
2627  PCHAR p, p2;
2628  ULONG Length;
2629  ULONG i, j;
2630  LONG RowsPrintedByTerminal;
2631  ULONG ScanCode;
2632  va_list ap;
2633 
2634  /* Check if the user has aborted output of the current command */
2635  if (KdbOutputAborted)
2636  return;
2637 
2638  /* Initialize the terminal */
2639  if (!TerminalInitialized)
2640  {
2641  DbgPrint("\x1b[7h"); /* Enable linewrap */
2642 
2643  /* Query terminal type */
2644  /*DbgPrint("\x1b[Z");*/
2645  DbgPrint("\x05");
2646 
2647  TerminalInitialized = TRUE;
2648  Length = 0;
2649  KeStallExecutionProcessor(100000);
2650 
2651  for (;;)
2652  {
2653  c = KdbpTryGetCharSerial(5000);
2654  if (c == -1)
2655  break;
2656 
2657  Buffer[Length++] = c;
2658  if (Length >= (sizeof(Buffer) - 1))
2659  break;
2660  }
2661 
2662  Buffer[Length] = '\0';
2663  if (Length > 0)
2664  TerminalConnected = TRUE;
2665  }
2666 
2667  /* Get number of rows and columns in terminal */
2668  if ((KdbNumberOfRowsTerminal < 0) || (KdbNumberOfColsTerminal < 0) ||
2669  (KdbNumberOfRowsPrinted) == 0) /* Refresh terminal size each time when number of rows printed is 0 */
2670  {
2671  if ((KdbDebugState & KD_DEBUG_KDSERIAL) && TerminalConnected && TerminalReportsSize)
2672  {
2673  /* Try to query number of rows from terminal. A reply looks like "\x1b[8;24;80t" */
2674  TerminalReportsSize = FALSE;
2675  KeStallExecutionProcessor(100000);
2676  DbgPrint("\x1b[18t");
2677  c = KdbpTryGetCharSerial(5000);
2678 
2679  if (c == KEY_ESC)
2680  {
2681  c = KdbpTryGetCharSerial(5000);
2682  if (c == '[')
2683  {
2684  Length = 0;
2685 
2686  for (;;)
2687  {
2688  c = KdbpTryGetCharSerial(5000);
2689  if (c == -1)
2690  break;
2691 
2692  Buffer[Length++] = c;
2693  if (isalpha(c) || Length >= (sizeof(Buffer) - 1))
2694  break;
2695  }
2696 
2697  Buffer[Length] = '\0';
2698  if (Buffer[0] == '8' && Buffer[1] == ';')
2699  {
2700  for (i = 2; (i < Length) && (Buffer[i] != ';'); i++);
2701 
2702  if (Buffer[i] == ';')
2703  {
2704  Buffer[i++] = '\0';
2705 
2706  /* Number of rows is now at Buffer + 2 and number of cols at Buffer + i */
2709  TerminalReportsSize = TRUE;
2710  }
2711  }
2712  }
2713  /* Clear further characters */
2714  while ((c = KdbpTryGetCharSerial(5000)) != -1);
2715  }
2716  }
2717 
2718  if (KdbNumberOfRowsTerminal <= 0)
2719  {
2720  /* Set number of rows to the default. */
2721  KdbNumberOfRowsTerminal = 23; //24; //Mna.: 23 for SCREEN debugport
2722  }
2723  else if (KdbNumberOfColsTerminal <= 0)
2724  {
2725  /* Set number of cols to the default. */
2726  KdbNumberOfColsTerminal = 75; //80; //Mna.: 75 for SCREEN debugport
2727  }
2728  }
2729 
2730  /* Get the string */
2731  va_start(ap, Format);
2732  Length = _vsnprintf(Buffer, sizeof(Buffer) - 1, Format, ap);
2733  Buffer[Length] = '\0';
2734  va_end(ap);
2735 
2736  p = Buffer;
2737  while (p[0] != '\0')
2738  {
2739  i = strcspn(p, "\n");
2740 
2741  /* Calculate the number of lines which will be printed in the terminal
2742  * when outputting the current line
2743  */
2744  if (i > 0)
2745  RowsPrintedByTerminal = (i + KdbNumberOfColsPrinted - 1) / KdbNumberOfColsTerminal;
2746  else
2747  RowsPrintedByTerminal = 0;
2748 
2749  if (p[i] == '\n')
2750  RowsPrintedByTerminal++;
2751 
2752  /*DbgPrint("!%d!%d!%d!%d!", KdbNumberOfRowsPrinted, KdbNumberOfColsPrinted, i, RowsPrintedByTerminal);*/
2753 
2754  /* Display a prompt if we printed one screen full of text */
2755  if (KdbNumberOfRowsTerminal > 0 &&
2756  (LONG)(KdbNumberOfRowsPrinted + RowsPrintedByTerminal) >= KdbNumberOfRowsTerminal)
2757  {
2759 
2760  if (KdbNumberOfColsPrinted > 0)
2761  DbgPrint("\n");
2762 
2763  DbgPrint("--- Press q to abort, any other key to continue ---");
2764  RowsPrintedByTerminal++; /* added by Mna. */
2765 
2767  c = KdbpGetCharSerial();
2768  else
2770 
2771  if (c == '\r')
2772  {
2773  /* Try to read '\n' which might follow '\r' - if \n is not received here
2774  * it will be interpreted as "return" when the next command should be read.
2775  */
2777  c = KdbpTryGetCharSerial(5);
2778  else
2780  }
2781 
2782  DbgPrint("\n");
2783  if (c == 'q')
2784  {
2786  return;
2787  }
2788 
2791  }
2792 
2793  /* Insert a NUL after the line and print only the current line. */
2794  if (p[i] == '\n' && p[i + 1] != '\0')
2795  {
2796  c = p[i + 1];
2797  p[i + 1] = '\0';
2798  }
2799  else
2800  {
2801  c = '\0';
2802  }
2803 
2804  /* Remove escape sequences from the line if there's no terminal connected */
2805  if (!TerminalConnected)
2806  {
2807  while ((p2 = strrchr(p, '\x1b'))) /* Look for escape character */
2808  {
2809  size_t len = strlen(p2);
2810  if (p2[1] == '[')
2811  {
2812  j = 2;
2813  while (!isalpha(p2[j++]));
2814  memmove(p2, p2 + j, len + 1 - j);
2815  }
2816  else
2817  {
2818  memmove(p2, p2 + 1, len);
2819  }
2820  }
2821  }
2822 
2823  DbgPrint("%s", p);
2824 
2825  if (c != '\0')
2826  p[i + 1] = c;
2827 
2828  /* Set p to the start of the next line and
2829  * remember the number of rows/cols printed
2830  */
2831  p += i;
2832  if (p[0] == '\n')
2833  {
2834  p++;
2836  }
2837  else
2838  {
2839  ASSERT(p[0] == '\0');
2841  }
2842 
2843  KdbNumberOfRowsPrinted += RowsPrintedByTerminal;
2844  }
2845 }
2846 
2848 /*
2849  * Reverse memchr()
2850  * Find the last occurrence of 'c' in the buffer 's' of size 'n'.
2851  */
2852 void *
2853 memrchr(const void *s, int c, size_t n)
2854 {
2855  const unsigned char *cp;
2856 
2857  if (n != 0)
2858  {
2859  cp = (unsigned char *)s + n;
2860  do
2861  {
2862  if (*(--cp) == (unsigned char)c)
2863  return (void *)cp;
2864  } while (--n != 0);
2865  }
2866  return NULL;
2867 }
2868 
2880 PCHAR
2881 CountOnePageUp(PCHAR Buffer, ULONG BufLength, PCHAR pCurPos)
2882 {
2883  PCHAR p;
2884  // p0 is initial guess of Page Start
2886  PCHAR p0 = pCurPos - p0len;
2887  PCHAR prev_p = p0, p1;
2888  ULONG j;
2889 
2890  if (pCurPos < Buffer)
2891  pCurPos = Buffer;
2892  ASSERT(pCurPos <= Buffer + BufLength);
2893 
2894  p = memrchr(p0, '\n', p0len);
2895  if (NULL == p)
2896  p = p0;
2897  for (j = KdbNumberOfRowsTerminal; j--; )
2898  {
2899  int linesCnt;
2900  p1 = memrchr(p0, '\n', p-p0);
2901  prev_p = p;
2902  p = p1;
2903  if (NULL == p)
2904  {
2905  p = prev_p;
2906  if (NULL == p)
2907  p = p0;
2908  break;
2909  }
2910  linesCnt = (KdbNumberOfColsTerminal+prev_p-p-2) / KdbNumberOfColsTerminal;
2911  if (linesCnt > 1)
2912  j -= linesCnt-1;
2913  }
2914 
2915  ASSERT(p != 0);
2916  ++p;
2917  return p;
2918 }
2919 
2932 VOID
2934  IN PCHAR Buffer,
2935  IN ULONG BufLength)
2936 {
2937  static CHAR InBuffer[4096];
2938  static BOOLEAN TerminalInitialized = FALSE;
2939  static BOOLEAN TerminalConnected = FALSE;
2940  static BOOLEAN TerminalReportsSize = TRUE;
2941  CHAR c = '\0';
2942  PCHAR p, p2;
2943  ULONG Length;
2944  ULONG i, j;
2945  LONG RowsPrintedByTerminal;
2946  ULONG ScanCode;
2947 
2948  if( BufLength == 0)
2949  return;
2950 
2951  /* Check if the user has aborted output of the current command */
2952  if (KdbOutputAborted)
2953  return;
2954 
2955  /* Initialize the terminal */
2956  if (!TerminalInitialized)
2957  {
2958  DbgPrint("\x1b[7h"); /* Enable linewrap */
2959 
2960  /* Query terminal type */
2961  /*DbgPrint("\x1b[Z");*/
2962  DbgPrint("\x05");
2963 
2964  TerminalInitialized = TRUE;
2965  Length = 0;
2966  KeStallExecutionProcessor(100000);
2967 
2968  for (;;)
2969  {
2970  c = KdbpTryGetCharSerial(5000);
2971  if (c == -1)
2972  break;
2973 
2974  InBuffer[Length++] = c;
2975  if (Length >= (sizeof(InBuffer) - 1))
2976  break;
2977  }
2978 
2979  InBuffer[Length] = '\0';
2980  if (Length > 0)
2981  TerminalConnected = TRUE;
2982  }
2983 
2984  /* Get number of rows and columns in terminal */
2985  if ((KdbNumberOfRowsTerminal < 0) || (KdbNumberOfColsTerminal < 0) ||
2986  (KdbNumberOfRowsPrinted) == 0) /* Refresh terminal size each time when number of rows printed is 0 */
2987  {
2988  if ((KdbDebugState & KD_DEBUG_KDSERIAL) && TerminalConnected && TerminalReportsSize)
2989  {
2990  /* Try to query number of rows from terminal. A reply looks like "\x1b[8;24;80t" */
2991  TerminalReportsSize = FALSE;
2992  KeStallExecutionProcessor(100000);
2993  DbgPrint("\x1b[18t");
2994  c = KdbpTryGetCharSerial(5000);
2995 
2996  if (c == KEY_ESC)
2997  {
2998  c = KdbpTryGetCharSerial(5000);
2999  if (c == '[')
3000  {
3001  Length = 0;
3002 
3003  for (;;)
3004  {
3005  c = KdbpTryGetCharSerial(5000);
3006  if (c == -1)
3007  break;
3008 
3009  InBuffer[Length++] = c;
3010  if (isalpha(c) || Length >= (sizeof(InBuffer) - 1))
3011  break;
3012  }
3013 
3014  InBuffer[Length] = '\0';
3015  if (InBuffer[0] == '8' && InBuffer[1] == ';')
3016  {
3017  for (i = 2; (i < Length) && (InBuffer[i] != ';'); i++);
3018 
3019  if (Buffer[i] == ';')
3020  {
3021  Buffer[i++] = '\0';
3022 
3023  /* Number of rows is now at Buffer + 2 and number of cols at Buffer + i */
3024  KdbNumberOfRowsTerminal = strtoul(InBuffer + 2, NULL, 0);
3025  KdbNumberOfColsTerminal = strtoul(InBuffer + i, NULL, 0);
3026  TerminalReportsSize = TRUE;
3027  }
3028  }
3029  }
3030  /* Clear further characters */
3031  while ((c = KdbpTryGetCharSerial(5000)) != -1);
3032  }
3033  }
3034 
3035  if (KdbNumberOfRowsTerminal <= 0)
3036  {
3037  /* Set number of rows to the default. */
3039  }
3040  else if (KdbNumberOfColsTerminal <= 0)
3041  {
3042  /* Set number of cols to the default. */
3044  }
3045  }
3046 
3047  /* Get the string */
3048  p = Buffer;
3049 
3050  while (p[0] != '\0')
3051  {
3052  if ( p > Buffer+BufLength)
3053  {
3054  DbgPrint("Dmesg: error, p > Buffer+BufLength,d=%d", p - (Buffer+BufLength));
3055  return;
3056  }
3057  i = strcspn(p, "\n");
3058 
3059  // Are we out of buffer?
3060  if (p + i > Buffer + BufLength)
3061  // Leaving pager function:
3062  break;
3063 
3064  /* Calculate the number of lines which will be printed in the terminal
3065  * when outputting the current line.
3066  */
3067  if (i > 0)
3068  RowsPrintedByTerminal = (i + KdbNumberOfColsPrinted - 1) / KdbNumberOfColsTerminal;
3069  else
3070  RowsPrintedByTerminal = 0;
3071 
3072  if (p[i] == '\n')
3073  RowsPrintedByTerminal++;
3074 
3075  /*DbgPrint("!%d!%d!%d!%d!", KdbNumberOfRowsPrinted, KdbNumberOfColsPrinted, i, RowsPrintedByTerminal);*/
3076 
3077  /* Display a prompt if we printed one screen full of text */
3078  if (KdbNumberOfRowsTerminal > 0 &&
3079  (LONG)(KdbNumberOfRowsPrinted + RowsPrintedByTerminal) >= KdbNumberOfRowsTerminal)
3080  {
3082 
3083  if (KdbNumberOfColsPrinted > 0)
3084  DbgPrint("\n");
3085 
3086  DbgPrint("--- Press q to abort, e/End,h/Home,u/PgUp, other key/PgDn ---");
3087  RowsPrintedByTerminal++;
3088 
3090  c = KdbpGetCharSerial();
3091  else
3093 
3094  if (c == '\r')
3095  {
3096  /* Try to read '\n' which might follow '\r' - if \n is not received here
3097  * it will be interpreted as "return" when the next command should be read.
3098  */
3100  c = KdbpTryGetCharSerial(5);
3101  else
3103  }
3104 
3105  //DbgPrint("\n"); //Consize version: don't show pressed key
3106  DbgPrint(" '%c'/scan=%04x\n", c, ScanCode); // Shows pressed key
3107 
3108  if (c == 'q')
3109  {
3111  return;
3112  }
3113  if ( ScanCode == KEYSC_END || c=='e')
3114  {
3115  PCHAR pBufEnd = Buffer + BufLength;
3116  p = CountOnePageUp(Buffer, BufLength, pBufEnd);
3117  i = strcspn(p, "\n");
3118  }
3119  else if (ScanCode == KEYSC_PAGEUP || c=='u')
3120  {
3121  p = CountOnePageUp(Buffer, BufLength, p);
3122  i = strcspn(p, "\n");
3123  }
3124  else if (ScanCode == KEYSC_HOME || c=='h')
3125  {
3126  p = Buffer;
3127  i = strcspn(p, "\n");
3128  }
3129  else if (ScanCode == KEYSC_ARROWUP)
3130  {
3131  p = CountOnePageUp(Buffer, BufLength, p);
3132  i = strcspn(p, "\n");
3133  }
3134 
3137  }
3138 
3139  /* Insert a NUL after the line and print only the current line. */
3140  if (p[i] == '\n' && p[i + 1] != '\0')
3141  {
3142  c = p[i + 1];
3143  p[i + 1] = '\0';
3144  }
3145  else
3146  {
3147  c = '\0';
3148  }
3149 
3150  /* Remove escape sequences from the line if there's no terminal connected */
3151  if (!TerminalConnected)
3152  {
3153  while ((p2 = strrchr(p, '\x1b'))) /* Look for escape character */
3154  {
3155  size_t len = strlen(p2);
3156  if (p2[1] == '[')
3157  {
3158  j = 2;
3159  while (!isalpha(p2[j++]));
3160  memmove(p2, p2 + j, len + 1 - j);
3161  }
3162  else
3163  {
3164  memmove(p2, p2 + 1, len);
3165  }
3166  }
3167  }
3168 
3169  // The main printing of the current line:
3170  DbgPrint(p);
3171 
3172  // restore not null char with saved:
3173  if (c != '\0')
3174  p[i + 1] = c;
3175 
3176  /* Set p to the start of the next line and
3177  * remember the number of rows/cols printed
3178  */
3179  p += i;
3180  if (p[0] == '\n')
3181  {
3182  p++;
3184  }
3185  else
3186  {
3187  ASSERT(p[0] == '\0');
3189  }
3190 
3191  KdbNumberOfRowsPrinted += RowsPrintedByTerminal;
3192  }
3193 }
3194 
3199 static VOID
3201  IN PCHAR Command)
3202 {
3203  ULONG Length1 = strlen(Command) + 1;
3204  ULONG Length2 = 0;
3205  INT i;
3206  PCHAR Buffer;
3207 
3209 
3210  if (Length1 <= 1 ||
3213  {
3214  return;
3215  }
3216 
3217  /* Calculate Length1 and Length2 */
3221  {
3224  Length1 -= Length2;
3225  }
3226 
3227  /* Remove previous commands until there is enough space to append the new command */
3229  {
3230  if ((Length2 > 0 &&
3231  (KdbCommandHistory[i] >= Buffer ||
3233  (Length2 <= 0 &&
3234  (KdbCommandHistory[i] >= Buffer &&
3236  {
3238  }
3239 
3240  i--;
3241  if (i < 0)
3243 
3244  if (i == KdbCommandHistoryIndex)
3245  break;
3246  }
3247 
3248  /* Make sure the new command history entry is free */
3252  {
3254  }
3255 
3256  /* Append command */
3260  if (Length2 > 0)
3261  {
3263  }
3264 }
3265 
3273 static VOID
3275  OUT PCHAR Buffer,
3276  IN ULONG Size)
3277 {
3278  CHAR Key;
3279  PCHAR Orig = Buffer;
3280  ULONG ScanCode = 0;
3281  BOOLEAN EchoOn;
3282  static CHAR LastCommand[1024];
3283  static CHAR NextKey = '\0';
3284  INT CmdHistIndex = -1;
3285  INT i;
3286 
3287  EchoOn = !((KdbDebugState & KD_DEBUG_KDNOECHO) != 0);
3288 
3289  for (;;)
3290  {
3292  {
3293  Key = (NextKey == '\0') ? KdbpGetCharSerial() : NextKey;
3294  NextKey = '\0';
3295  ScanCode = 0;
3296  if (Key == KEY_ESC) /* ESC */
3297  {
3298  Key = KdbpGetCharSerial();
3299  if (Key == '[')
3300  {
3301  Key = KdbpGetCharSerial();
3302 
3303  switch (Key)
3304  {
3305  case 'A':
3307  break;
3308  case 'B':
3310  break;
3311  case 'C':
3312  break;
3313  case 'D':
3314  break;
3315  }
3316  }
3317  }
3318  }
3319  else
3320  {
3321  ScanCode = 0;
3322  Key = (NextKey == '\0') ? KdbpGetCharKeyboard(&ScanCode) : NextKey;
3323  NextKey = '\0';
3324  }
3325 
3326  if ((ULONG)(Buffer - Orig) >= (Size - 1))
3327  {
3328  /* Buffer is full, accept only newlines */
3329  if (Key != '\n')
3330  continue;
3331  }
3332 
3333  if (Key == '\r')
3334  {
3335  /* Read the next char - this is to throw away a \n which most clients should
3336  * send after \r.
3337  */
3338  KeStallExecutionProcessor(100000);
3339 
3341  NextKey = KdbpTryGetCharSerial(5);
3342  else
3343  NextKey = KdbpTryGetCharKeyboard(&ScanCode, 5);
3344 
3345  if (NextKey == '\n' || NextKey == -1) /* \n or no response at all */
3346  NextKey = '\0';
3347 
3348  KdbpPrint("\n");
3349 
3350  /*
3351  * Repeat the last command if the user presses enter. Reduces the
3352  * risk of RSI when single-stepping.
3353  */
3354  if (Buffer != Orig)
3355  {
3357  *Buffer = '\0';
3358  RtlStringCbCopyA(LastCommand, sizeof(LastCommand), Orig);
3359  }
3360  else if (KdbRepeatLastCommand)
3361  RtlStringCbCopyA(Buffer, Size, LastCommand);
3362  else
3363  *Buffer = '\0';
3364 
3365  return;
3366  }
3367  else if (Key == KEY_BS || Key == KEY_DEL)
3368  {
3369  if (Buffer > Orig)
3370  {
3371  Buffer--;
3372  *Buffer = 0;
3373 
3374  if (EchoOn)
3375  KdbpPrint("%c %c", KEY_BS, KEY_BS);
3376  else
3377  KdbpPrint(" %c", KEY_BS);
3378  }
3379  }
3380  else if (ScanCode == KEY_SCAN_UP)
3381  {
3382  BOOLEAN Print = TRUE;
3383 
3384  if (CmdHistIndex < 0)
3385  {
3386  CmdHistIndex = KdbCommandHistoryIndex;
3387  }
3388  else
3389  {
3390  i = CmdHistIndex - 1;
3391 
3392  if (i < 0)
3393  CmdHistIndex = RTL_NUMBER_OF(KdbCommandHistory) - 1;
3394 
3396  CmdHistIndex = i;
3397  else
3398  Print = FALSE;
3399  }
3400 
3401  if (Print && KdbCommandHistory[CmdHistIndex])
3402  {
3403  while (Buffer > Orig)
3404  {
3405  Buffer--;
3406  *Buffer = 0;
3407 
3408  if (EchoOn)
3409  KdbpPrint("%c %c", KEY_BS, KEY_BS);
3410  else
3411  KdbpPrint(" %c", KEY_BS);
3412  }
3413 
3414  i = min(strlen(KdbCommandHistory[CmdHistIndex]), Size - 1);
3415  memcpy(Orig, KdbCommandHistory[CmdHistIndex], i);
3416  Orig[i] = '\0';
3417  Buffer = Orig + i;
3418  KdbpPrint("%s", Orig);
3419  }
3420  }
3421  else if (ScanCode == KEY_SCAN_DOWN)
3422  {
3423  if (CmdHistIndex > 0 && CmdHistIndex != KdbCommandHistoryIndex)
3424  {
3425  i = CmdHistIndex + 1;
3427  i = 0;
3428 
3429  if (KdbCommandHistory[i])
3430  {
3431  CmdHistIndex = i;
3432  while (Buffer > Orig)
3433  {
3434  Buffer--;
3435  *Buffer = 0;
3436 
3437  if (EchoOn)
3438  KdbpPrint("%c %c", KEY_BS, KEY_BS);
3439  else
3440  KdbpPrint(" %c", KEY_BS);
3441  }
3442 
3443  i = min(strlen(KdbCommandHistory[CmdHistIndex]), Size - 1);
3444  memcpy(Orig, KdbCommandHistory[CmdHistIndex], i);
3445  Orig[i] = '\0';
3446  Buffer = Orig + i;
3447  KdbpPrint("%s", Orig);
3448  }
3449  }
3450  }
3451  else
3452  {
3453  if (EchoOn)
3454  KdbpPrint("%c", Key);
3455 
3456  *Buffer = Key;
3457  Buffer++;
3458  }
3459  }
3460 }
3461 
3462 
3463 BOOLEAN
3464 NTAPI
3466  PVOID Callback,
3467  BOOLEAN Deregister)
3468 {
3469  ULONG i;
3470 
3471  /* Loop all entries */
3472  for (i = 0; i < _countof(KdbCliCallbacks); i++)
3473  {
3474  /* Check if deregistering was requested */
3475  if (Deregister)
3476  {
3477  /* Check if this entry is the one that was registered */
3478  if (KdbCliCallbacks[i] == Callback)
3479  {
3480  /* Delete it and report success */
3481  KdbCliCallbacks[i] = NULL;
3482  return TRUE;
3483  }
3484  }
3485  else
3486  {
3487  /* Check if this entry is free */
3488  if (KdbCliCallbacks[i] == NULL)
3489  {
3490  /* Set it and and report success */
3492  return TRUE;
3493  }
3494  }
3495  }
3496 
3497  /* Unsuccessful */
3498  return FALSE;
3499 }
3500 
3510 static
3511 BOOLEAN
3513  IN PCHAR Command,
3514  IN ULONG Argc,
3515  IN PCHAR Argv[])
3516 {
3517  ULONG i;
3518 
3519  /* Loop all entries */
3520  for (i = 0; i < _countof(KdbCliCallbacks); i++)
3521  {
3522  /* Check if this entry is registered */
3523  if (KdbCliCallbacks[i])
3524  {
3525  /* Invoke the callback and check if it handled the command */
3526  if (KdbCliCallbacks[i](Command, Argc, Argv))
3527  {
3528  return TRUE;
3529  }
3530  }
3531  }
3532 
3533  /* None of the callbacks handled the command */
3534  return FALSE;
3535 }
3536 
3537 
3545 static BOOLEAN
3547  IN PCHAR Command)
3548 {
3549  ULONG i;
3550  PCHAR p;
3551  ULONG Argc;
3552  // FIXME: for what do we need a 1024 characters command line and 256 tokens?
3553  static PCHAR Argv[256];
3554  static CHAR OrigCommand[1024];
3555 
3556  RtlStringCbCopyA(OrigCommand, sizeof(OrigCommand), Command);
3557 
3558  Argc = 0;
3559  p = Command;
3560 
3561  for (;;)
3562  {
3563  while (*p == '\t' || *p == ' ')
3564  p++;
3565 
3566  if (*p == '\0')
3567  break;
3568 
3569  i = strcspn(p, "\t ");
3570  Argv[Argc++] = p;
3571  p += i;
3572  if (*p == '\0')
3573  break;
3574 
3575  *p = '\0';
3576  p++;
3577  }
3578 
3579  if (Argc < 1)
3580  return TRUE;
3581 
3582  for (i = 0; i < RTL_NUMBER_OF(KdbDebuggerCommands); i++)
3583  {
3584  if (!KdbDebuggerCommands[i].Name)
3585  continue;
3586 
3587  if (strcmp(KdbDebuggerCommands[i].Name, Argv[0]) == 0)
3588  {
3589  return KdbDebuggerCommands[i].Fn(Argc, Argv);
3590  }
3591  }
3592 
3593  /* Now invoke the registered callbacks */
3594  if (KdbpInvokeCliCallbacks(Command, Argc, Argv))
3595  {
3596  return TRUE;
3597  }
3598 
3599  KdbpPrint("Command '%s' is unknown.\n", OrigCommand);
3600  return TRUE;
3601 }
3602 
3607 VOID
3609  IN BOOLEAN EnteredOnSingleStep)
3610 {
3611  static CHAR Command[1024];
3612  BOOLEAN Continue;
3613 
3614  if (EnteredOnSingleStep)
3615  {
3617  {
3618  KdbpPrint("<%08x>", KdbCurrentTrapFrame->Eip);
3619  }
3620 
3621  KdbpPrint(": ");
3623  {
3624  KdbpPrint("<INVALID>");
3625  }
3626  KdbpPrint("\n");
3627  }
3628 
3629  /* Flush the input buffer */
3631  {
3632  while (KdbpTryGetCharSerial(1) != -1);
3633  }
3634  else
3635  {
3636  ULONG ScanCode;
3637  while (KdbpTryGetCharKeyboard(&ScanCode, 1) != -1);
3638  }
3639 
3640  /* Main loop */
3641  do
3642  {
3643  /* Reset the number of rows/cols printed */
3645 
3646  /* Print the prompt */
3647  KdbpPrint(KdbPromptString.Buffer);
3648 
3649  /* Read a command and remember it */
3650  KdbpReadCommand(Command, sizeof(Command));
3652 
3653  /* Reset the number of rows/cols printed and output aborted state */
3656 
3657  /* Call the command */
3660  }
3661  while (Continue);
3662 }
3663 
3668 VOID
3671 {
3672  if (!KdbBreakOnModuleLoad)
3673  return;
3674 
3675  KdbpPrint("Module %wZ loaded.\n", Name);
3677 }
3678 
3685 VOID
3687 {
3688  PCHAR p1, p2;
3689  INT i;
3690  CHAR c;
3691 
3692  /* Execute the commands in the init file */
3693  DPRINT("KDB: Executing KDBinit file...\n");
3694  p1 = KdbInitFileBuffer;
3695  while (p1[0] != '\0')
3696  {
3697  i = strcspn(p1, "\r\n");
3698  if (i > 0)
3699  {
3700  c = p1[i];
3701  p1[i] = '\0';
3702 
3703  /* Look for "break" command and comments */
3704  p2 = p1;
3705 
3706  while (isspace(p2[0]))
3707  p2++;
3708 
3709  if (strncmp(p2, "break", sizeof("break")-1) == 0 &&
3710  (p2[sizeof("break")-1] == '\0' || isspace(p2[sizeof("break")-1])))
3711  {
3712  /* break into the debugger */
3714  }
3715  else if (p2[0] != '#' && p2[0] != '\0') /* Ignore empty lines and comments */
3716  {
3717  KdbpDoCommand(p1);
3718  }
3719 
3720  p1[i] = c;
3721  }
3722 
3723  p1 += i;
3724  while (p1[0] == '\r' || p1[0] == '\n')
3725  p1++;
3726  }
3727  DPRINT("KDB: KDBinit executed\n");
3728 }
3729 
3734 VOID
3736 {
3737  NTSTATUS Status;
3741  FILE_STANDARD_INFORMATION FileStdInfo;
3742  HANDLE hFile = NULL;
3743  INT FileSize;
3744  PCHAR FileBuffer;
3745  ULONG OldEflags;
3746 
3747  /* Initialize the object attributes */
3748  RtlInitUnicodeString(&FileName, L"\\SystemRoot\\System32\\drivers\\etc\\KDBinit");
3750  &FileName,
3752  NULL,
3753  NULL);
3754 
3755  /* Open the file */
3757  &ObjectAttributes, &Iosb, 0,
3760  if (!NT_SUCCESS(Status))
3761  {
3762  DPRINT("Could not open \\SystemRoot\\System32\\drivers\\etc\\KDBinit (Status 0x%x)", Status);
3763  return;
3764  }
3765 
3766  /* Get the size of the file */
3767  Status = ZwQueryInformationFile(hFile, &Iosb, &FileStdInfo, sizeof(FileStdInfo),
3769  if (!NT_SUCCESS(Status))
3770  {
3771  ZwClose(hFile);
3772  DPRINT("Could not query size of \\SystemRoot\\System32\\drivers\\etc\\KDBinit (Status 0x%x)", Status);
3773  return;
3774  }
3775  FileSize = FileStdInfo.EndOfFile.u.LowPart;
3776 
3777  /* Allocate memory for the file */
3778  FileBuffer = ExAllocatePool(PagedPool, FileSize + 1); /* add 1 byte for terminating '\0' */
3779  if (!FileBuffer)
3780  {
3781  ZwClose(hFile);
3782  DPRINT("Could not allocate %d bytes for KDBinit file\n", FileSize);
3783  return;
3784  }
3785 
3786  /* Load file into memory */
3787  Status = ZwReadFile(hFile, NULL, NULL, NULL, &Iosb, FileBuffer, FileSize, NULL, NULL);
3788  ZwClose(hFile);
3789 
3791  {
3792  ExFreePool(FileBuffer);
3793  DPRINT("Could not read KDBinit file into memory (Status 0x%lx)\n", Status);
3794  return;
3795  }
3796 
3797  FileSize = min(FileSize, (INT)Iosb.Information);
3798  FileBuffer[FileSize] = '\0';
3799 
3800  /* Enter critical section */
3801  OldEflags = __readeflags();
3802  _disable();
3803 
3804  /* Interpret the init file... */
3805  KdbInitFileBuffer = FileBuffer;
3806  //KdbEnter(); // FIXME
3808 
3809  /* Leave critical section */
3810  __writeeflags(OldEflags);
3811 
3812  ExFreePool(FileBuffer);
3813 }
PCHAR KdpDmesgBuffer
Definition: kdio.c:39
BOOLEAN KdbpDeleteBreakPoint(IN LONG BreakPointNr OPTIONAL, IN OUT PKDB_BREAKPOINT BreakPoint OPTIONAL)
Deletes a breakpoint.
Definition: kdb.c:594
signed char * PCHAR
Definition: retypes.h:7
struct _NT_TIB * Self
Definition: compat.h:579
ULONG TempEsp
Definition: ketypes.h:246
#define KEY_ESC
Definition: kdb_cli.c:39
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
#define IN
Definition: typedefs.h:39
#define isspace(c)
Definition: acclib.h:69
static BOOLEAN KdbpCmdFilter(ULONG Argc, PCHAR Argv[])
Displays the list of active debug channels, or enable/disable debug channels.
Definition: kdb_cli.c:684
BOOLEAN KdbpSetEnterCondition(IN LONG ExceptionNr, IN BOOLEAN FirstChance, IN KDB_ENTER_CONDITION Condition)
Sets the first or last chance enter-condition for exception nr. ExceptionNr.
Definition: kdb.c:991
#define memmove(s1, s2, n)
Definition: mkisofs.h:881
PCWSTR Expression
static VOID KdbpReadCommand(OUT PCHAR Buffer, IN ULONG Size)
Reads a line of user-input.
Definition: kdb_cli.c:3274
UINT32 strtoul(const char *String, char **Terminator, UINT32 Base)
Definition: utclib.c:696
void * memrchr(const void *s, int c, size_t n)
Definition: kdb_cli.c:2853
static VOID KdbpCommandHistoryAppend(IN PCHAR Command)
Appends a command to the command history.
Definition: kdb_cli.c:3200
volatile BOOLEAN KdbpIsInDmesgMode
Definition: kdio.c:43
static PKDBG_CLI_ROUTINE KdbCliCallbacks[10]
Definition: kdb_cli.c:115
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
ULONG ScanCode
Definition: api.c:39
#define NPX_STATE_TO_STRING(state)
Definition: kdb_cli.c:62
BOOLEAN KdbSymPrintAddress(IN PVOID Address, IN PCONTEXT Context)
Print address...
Definition: kdb_symbols.c:156
static const struct op_mask SETUP
Definition: startup.c:427
ULONG Eip
Definition: nt_native.h:1476
#define COVERAGE(name, NAME, description, tag1, tag2, tag3, tag4)
struct _Entry Entry
Definition: kefuncs.h:627
static BOOLEAN KdbpCmdProc(ULONG Argc, PCHAR Argv[])
Lists processes or switches to another process context.
Definition: kdb_cli.c:1782
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
ULONG KdbDebugState
Definition: kdb.c:45
USHORT Fs
Definition: ketypes.h:816
#define DbgPrint
Definition: loader.c:25
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
NTSTATUS NTAPI NtSetDebugFilterState(_In_ ULONG ComponentId, _In_ ULONG Level, _In_ BOOLEAN State)
Definition: kdapi.c:2406
BOOLEAN NTAPI KdbpGetHexNumber(IN PCHAR pszNum, OUT ULONG_PTR *pulValue)
Definition: kdb_cli.c:441
ULONG IRR
Definition: ketypes.h:754
#define KdbpGetCharKeyboard(ScanCode)
Definition: kdb.h:263
static BOOLEAN KdbpEvaluateExpression(IN PCHAR Expression, IN LONG ErrOffset, OUT PULONGLONG Result)
Evaluates an expression...
Definition: kdb_cli.c:414
#define TRUE
Definition: types.h:120
static BOOLEAN KdbpCmdBreakPointList(ULONG Argc, PCHAR Argv[])
Lists breakpoints.
Definition: kdb_cli.c:1312
#define KDB_ACCESS_TYPE_TO_STRING(type)
Definition: kdb_cli.c:57
BOOLEAN KdbpAttachToThread(PVOID ThreadId)
Switches to another thread context.
Definition: kdb.c:1032
USHORT BaseLow
Definition: ketypes.h:336
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
ULONG CR3
Definition: ketypes.h:797
PEPROCESS KdbCurrentProcess
Definition: kdb.c:47
_Check_return_ _CRTIMP size_t __cdecl strcspn(_In_z_ const char *_Str, _In_z_ const char *_Control)
UCHAR SecondLevelCacheAssociativity
Definition: ketypes.h:872
#define DPFLTR_INFO_LEVEL
Definition: kdtypes.h:33
NTSTATUS NTAPI PsLookupThreadByThreadId(IN HANDLE ThreadId, OUT PETHREAD *Thread)
Definition: thread.c:643
char CHAR
Definition: xmlstorage.h:175
VOID KdbpPrint(IN PCHAR Format, IN ... OPTIONAL)
Prints the given string with printf-like formatting.
Definition: kdb_cli.c:2618
#define KEYSC_PAGEUP
Definition: kdb_cli.c:47
PCSTR Name
Definition: kdb_cli.c:153
USHORT MinorVersion
Definition: ketypes.h:877
LONG NTSTATUS
Definition: precomp.h:26
BOOLEAN RosSymAggregate(PROSSYM_INFO RosSymInfo, PCHAR Type, PROSSYM_AGGREGATE Aggregate)
Definition: find.c:137
#define KEYSC_HOME
Definition: kdb_cli.c:49
KTHREAD Tcb
Definition: pstypes.h:1045
struct _KIPCR * PKIPCR
static BOOLEAN KdbpCmdBugCheck(ULONG Argc, PCHAR Argv[])
Bugchecks the system.
Definition: kdb_cli.c:2328
ULONG NumElements
Definition: rossym.h:101
SCHAR Priority
Definition: ketypes.h:1714
GLdouble n
Definition: glext.h:7729
#define DPFLTR_MASK
Definition: kdtypes.h:34
USHORT Cs
Definition: ketypes.h:810
_In_ ULONG _In_ ULONG State
Definition: potypes.h:516
UCHAR Number
Definition: ketypes.h:766
ULONG SizeOfImage
Definition: ldrtypes.h:143
USHORT Es
Definition: ketypes.h:808
INT Length2
Definition: FsRtlDissect.c:16
#define INVALID_HANDLE_VALUE
Definition: compat.h:590
#define KD_DEBUG_PRINT_FILTER(Name)
Definition: kdb_cli.c:148
const ULONG KdpDmesgBufferSize
Definition: kdio.c:38
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:361
#define KDB_ENTER_CONDITION_TO_STRING(cond)
Definition: kdb_cli.c:52
BOOLEAN ExpKdbgExtPool(ULONG Argc, PCHAR Argv[])
PKTRAP_FRAME TrapFrame
Definition: ketypes.h:1706
#define isalpha(c)
Definition: acclib.h:74
_IRQL_requires_same_ typedef _In_ ULONG _In_ UCHAR Level
Definition: wmitypes.h:55
ULONG Id
Definition: kdb_cli.c:154
ACPI_BUFFER *RetBuffer ACPI_BUFFER *RetBuffer char ACPI_WALK_RESOURCE_CALLBACK void *Context ACPI_BUFFER *RetBuffer UINT16 ACPI_RESOURCE **ResourcePtr ACPI_GENERIC_ADDRESS *Reg UINT32 *ReturnValue UINT8 UINT8 *Slp_TypB ACPI_PHYSICAL_ADDRESS PhysicalAddress64 UINT32 UINT32 *TimeElapsed UINT32 ACPI_STATUS const char UINT32 ACPI_STATUS const char UINT32 const char const char UINT32 ComponentId
Definition: acpixf.h:1274
#define KdbpGetCharSerial()
Definition: kdb.h:267
_Check_return_ _CRTIMP _CONST_RETURN char *__cdecl strrchr(_In_z_ const char *_Str, _In_ int _Ch)
Definition: shell.h:41
USHORT Backlink
Definition: ketypes.h:791
LIST_ENTRY PsActiveProcessHead
Definition: process.c:22
NTSTATUS KdbpInsertBreakPoint(IN ULONG_PTR Address, IN KDB_BREAKPOINT_TYPE Type, IN UCHAR Size OPTIONAL, IN KDB_ACCESS_TYPE AccessType OPTIONAL, IN PCHAR ConditionExpression OPTIONAL, IN BOOLEAN Global, OUT PLONG BreakPointNr OPTIONAL)
Inserts a breakpoint into the breakpoint array.
Definition: kdb.c:473
KIRQL Irql
Definition: ketypes.h:871
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
#define _stricmp
Definition: cat.c:22
UNICODE_STRING Global
Definition: symlink.c:37
int32_t INT
Definition: typedefs.h:58
PVOID Base
Definition: ketypes.h:486
PVOID ArbitraryUserPointer
Definition: compat.h:578
static struct @1808 ComponentTable[]
#define KeGetPcr()
Definition: ke.h:26
#define DPFLTR_WARNING_LEVEL
Definition: kdtypes.h:31
static BOOLEAN KdbpCmdEnableDisableClearBreakPoint(ULONG Argc, PCHAR Argv[])
Enables, disables or clears a breakpoint.
Definition: kdb_cli.c:1409
CHAR KdbpTryGetCharSerial(ULONG Retry)
Definition: kdb_serial.c:19
CHAR KdbpTryGetCharKeyboard(PULONG ScanCode, ULONG Retry)
Definition: kdb_keyboard.c:104
USHORT LDT
Definition: ketypes.h:820
#define KEY_SCAN_DOWN
Definition: kdb_cli.c:43
void Print(USHORT Window, LPSTR p)
Definition: hardware.c:776
USHORT Limit
Definition: ketypes.h:485
static PKTSS KdbpRetrieveTss(IN USHORT TssSelector, OUT PULONG pType OPTIONAL, IN PKDESCRIPTOR pGdtr OPTIONAL)
Definition: kdb_cli.c:994
volatile ULONG KdbDmesgTotalWritten
Definition: kdio.c:42
static ULONG KdbNumberOfRowsPrinted
Definition: kdb_cli.c:124
#define STATUS_END_OF_FILE
Definition: shellext.h:67
uint32_t ULONG_PTR
Definition: typedefs.h:65
NTSTRSAFEAPI RtlStringCbCopyA(_Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest, _In_ size_t cbDest, _In_ NTSTRSAFE_PCSTR pszSrc)
Definition: ntstrsafe.h:156
_Must_inspect_result_ _In_ WDFCHILDLIST _In_ PWDF_CHILD_LIST_ITERATOR _Out_ WDFDEVICE _Inout_opt_ PWDF_CHILD_RETRIEVE_INFO Info
Definition: wdfchildlist.h:683
INT Length1
Definition: FsRtlDissect.c:15
BOOLEAN KdbpDisableBreakPoint(IN LONG BreakPointNr OPTIONAL, IN OUT PKDB_BREAKPOINT BreakPoint OPTIONAL)
Disables a breakpoint.
Definition: kdb.c:864
PVOID DllBase
Definition: btrfs_drv.h:1926
#define sprintf(buf, format,...)
Definition: sprintf.c:55
static BOOLEAN KdbpDoCommand(IN PCHAR Command)
Parses command line and executes command if found.
Definition: kdb_cli.c:3546
WCHAR First[]
Definition: FormatMessage.c:11
#define DEFAULT
Definition: ruserpass.c:31
USHORT Ds
Definition: ketypes.h:814
static BOOLEAN KdbpCmdStep(ULONG Argc, PCHAR Argv[])
Continues execution of the system/leaves KDB.
Definition: kdb_cli.c:1282
#define FILE_NO_INTERMEDIATE_BUFFERING
Definition: from_kernel.h:28
static BOOLEAN KdbpCmdContinue(ULONG Argc, PCHAR Argv[])
Continues execution of the system/leaves KDB.
Definition: kdb_cli.c:1271
ULONG Edx
Definition: ketypes.h:802
static BOOLEAN KdbpCmdMod(ULONG Argc, PCHAR Argv[])
Lists loaded modules or the one containing the specified address.
Definition: kdb_cli.c:1900
__INTRIN_INLINE uintptr_t __readeflags(void)
Definition: intrin_x86.h:1603
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define va_end(ap)
Definition: acmsvcex.h:90
#define FALSE
Definition: types.h:117
VOID KdbpCliModuleLoaded(IN PUNICODE_STRING Name)
Called when a module is loaded.
Definition: kdb_cli.c:3669
static ULONG KdbNumberOfColsPrinted
Definition: kdb_cli.c:125
long LONG
Definition: pedump.c:60
ULONG VdmAlert
Definition: ketypes.h:769
__INTRIN_INLINE void __sidt(void *Destination)
Definition: intrin_x86.h:1952
short SHORT
Definition: pedump.c:59
#define FILE_READ_DATA
Definition: nt_native.h:628
volatile ULONG KdpDmesgCurrentPosition
Definition: kdio.c:40
CHAR * PCH
Definition: ntbasedef.h:391
BOOLEAN NTAPI KdbRegisterCliCallback(PVOID Callback, BOOLEAN Deregister)
Definition: kdb_cli.c:3465
ULONG StallScaleFactor
Definition: ketypes.h:878
unsigned char BOOLEAN
ULONG SecondLevelCacheSize
Definition: ketypes.h:881
static BOOLEAN KdbRepeatLastCommand
Definition: kdb_cli.c:127
static WCHAR Address[46]
Definition: ping.c:68
unsigned char
Definition: typeof.h:29
KAFFINITY SetMember
Definition: ketypes.h:763
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:426
Definition: ketypes.h:789
PCHAR CountOnePageUp(PCHAR Buffer, ULONG BufLength, PCHAR pCurPos)
Calculate pointer position for N lines upper of current position.
Definition: kdb_cli.c:2881
char * va_list
Definition: acmsvcex.h:78
void DPRINT(...)
Definition: polytest.cpp:61
_Must_inspect_result_ _In_ WDFDEVICE _In_ ULONG _In_ ACCESS_MASK _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFKEY * Key
Definition: wdfdevice.h:2654
static BOOLEAN KdbpCmdHelp(ULONG Argc, PCHAR Argv[])
Displays help screen.
Definition: kdb_cli.c:2582
Definition: bufpool.h:45
PVOID KernelStack
Definition: ketypes.h:1607
#define KEY_BS
Definition: kdb_cli.c:38
void * PVOID
Definition: retypes.h:9
static const struct @1809 KdbDebuggerCommands[]
static BOOLEAN KdbpCmdBreakPoint(ULONG Argc, PCHAR Argv[])
Sets a software or hardware (memory) breakpoint at the given address.
Definition: kdb_cli.c:1450
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
struct _LARGE_INTEGER::@2284 u
VOID KdbpCliMainLoop(IN BOOLEAN EnteredOnSingleStep)
KDB Main Loop.
Definition: kdb_cli.c:3608
static BOOLEAN KdbpCmdSet(ULONG Argc, PCHAR Argv[])
Sets or displays a config variables value.
Definition: kdb_cli.c:2403
#define KEY_SCAN_UP
Definition: kdb_cli.c:42
BOOLEAN KdbpBugCheckRequested
Definition: kdb_cli.c:132
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
#define KEYSC_END
Definition: kdb_cli.c:46
static BOOLEAN KdbpCmdTss(ULONG Argc, PCHAR Argv[])
Displays the TSS.
Definition: kdb_cli.c:2230
PKDB_KTRAP_FRAME KdbCurrentTrapFrame
Definition: kdb.c:51
r l[0]
Definition: byte_order.h:167
Status
Definition: gdiplustypes.h:24
ULONG64 NpxState
Definition: ketypes.h:2000
PROSSYM_AGGREGATE_MEMBER Elements
Definition: rossym.h:102
USHORT MaximumLength
Definition: env_spec_w32.h:377
BOOLEAN KdbpEnableBreakPoint(IN LONG BreakPointNr OPTIONAL, IN OUT PKDB_BREAKPOINT BreakPoint OPTIONAL)
Enables a breakpoint.
Definition: kdb.c:697
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
ULONG Ebx
Definition: ketypes.h:803
struct _KTSS * TSS
Definition: ketypes.h:760
int Count
Definition: noreturn.cpp:7
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID * BaseAddress
Definition: mmfuncs.h:404
static BOOLEAN KdbOutputAborted
Definition: kdb_cli.c:126
static const char *const debug_classes[]
Definition: debug.c:51
PCHAR Syntax
Definition: kdb_cli.c:338
#define ASSERT(a)
Definition: mode.c:45
static LONG KdbCommandHistoryBufferIndex
Definition: kdb_cli.c:121
ULONG InterruptMode
Definition: ketypes.h:773
return Iosb
Definition: create.c:4402
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
USHORT Ss0
Definition: ketypes.h:794
ULONG Eip
Definition: ketypes.h:798
PVOID FiberData
Definition: compat.h:575
struct Command Command
uint64_t ULONGLONG
Definition: typedefs.h:67
static PROSSYM_INFO KdbpSymFindCachedFile(IN PUNICODE_STRING FileName)
Find cached symbol file.
Definition: kdb_symbols.c:242
#define _countof(array)
Definition: sndvol32.h:68
static BOOLEAN KdbBreakOnModuleLoad
Definition: kdb_cli.c:117
CLIENT_ID Cid
Definition: pstypes.h:1070
static BOOLEAN KdbpCmdRegs(ULONG Argc, PCHAR Argv[])
Displays CPU registers.
Definition: kdb_cli.c:909
BOOLEAN ExpKdbgExtPoolFind(ULONG Argc, PCHAR Argv[])
LONG KdbpGetNextBreakPointNr(IN ULONG Start OPTIONAL)
Gets the number of the next breakpoint >= Start.
Definition: kdb.c:377
static BOOLEAN KdbpCmdThread(ULONG Argc, PCHAR Argv[])
Lists threads or switches to another thread context.
Definition: kdb_cli.c:1574
union _KGDTENTRY::@2415 HighWord
struct _EXCEPTION_REGISTRATION_RECORD * ExceptionList
Definition: compat.h:570
static BOOLEAN KdbUseIntelSyntax
Definition: kdb_cli.c:116
#define ObDereferenceObject
Definition: obfuncs.h:203
ULONG Ecx
Definition: ketypes.h:801
struct _KGDTENTRY::@2415::@2417 Bits
const GLubyte * c
Definition: glext.h:8905
static BOOLEAN KdbpCmdReboot(ULONG Argc, PCHAR Argv[])
Definition: kdb_cli.c:2338
int strncmp(const char *String1, const char *String2, ACPI_SIZE Count)
Definition: utclib.c:534
ULONG HardwareEsp
Definition: ketypes.h:270
volatile VOID * StackLimit
Definition: ketypes.h:1597
Type
Definition: Type.h:6
static LONG KdbNumberOfRowsTerminal
Definition: kdb_cli.c:128
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
va_start(ap, x)
#define _strnicmp(_String1, _String2, _MaxCount)
Definition: compat.h:23
VOID NTAPI HalReturnToFirmware(IN FIRMWARE_REENTRY Action)
Definition: reboot.c:22
USHORT IoMapBase
Definition: ketypes.h:823
ULONG EFlags
Definition: ketypes.h:799
static BOOLEAN KdbpCmdDisassembleX(ULONG Argc, PCHAR Argv[])
Disassembles 10 instructions at eip or given address or displays 16 dwords from memory at given addre...
Definition: kdb_cli.c:788
static BOOLEAN KdbpContextFromPrevTss(IN OUT PCONTEXT Context, OUT PUSHORT TssSelector, IN OUT PKTSS *pTss, IN PKDESCRIPTOR pGdtr)
Definition: kdb_cli.c:1061
HANDLE UniqueThread
Definition: compat.h:685
GLuint GLuint end
Definition: gl.h:1545
std::wstring STRING
Definition: fontsub.cpp:33
enum _KDB_ACCESS_TYPE KDB_ACCESS_TYPE
#define PKTSS
Definition: ketypes.h:921
NTSYSAPI NTSTATUS NTAPI ZwOpenFile(_Out_ PHANDLE FileHandle, _In_ ACCESS_MASK DesiredAccess, _In_ POBJECT_ATTRIBUTES ObjectAttributes, _Out_ PIO_STATUS_BLOCK IoStatusBlock, _In_ ULONG ShareAccess, _In_ ULONG OpenOptions)
volatile int Continue
Definition: gdblib.c:102
NTSTATUS NTAPI PsLookupProcessByProcessId(IN HANDLE ProcessId, OUT PEPROCESS *Process)
Definition: process.c:919
unsigned char UCHAR
Definition: xmlstorage.h:181
static LONG KdbNumberOfColsTerminal
Definition: kdb_cli.c:129
ULONG KdbNumSingleSteps
Definition: kdb.c:43
PVOID SubSystemTib
Definition: compat.h:573
static const WCHAR L[]
Definition: oid.c:1250
KPRCB Prcb
Definition: ketypes.h:889
enum _KDB_ENTER_CONDITION KDB_ENTER_CONDITION
static BOOLEAN KdbpCmdGdtLdtIdt(ULONG Argc, PCHAR Argv[])
Displays GDT, LDT or IDT.
Definition: kdb_cli.c:1964
VOID RosSymFreeAggregate(PROSSYM_AGGREGATE Aggregate)
Definition: find.c:126
__INTRIN_INLINE void __writeeflags(uintptr_t Value)
Definition: intrin_x86.h:1598
#define ExAllocatePool(type, size)
Definition: fbtusb.h:44
#define FILE_NON_DIRECTORY_FILE
Definition: constants.h:492
Definition: btrfs_drv.h:1922
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
GLenum GLsizei len
Definition: glext.h:6722
PCHAR Help
Definition: kdb_cli.c:339
_Must_inspect_result_ _Out_ PLARGE_INTEGER FileSize
Definition: fsrtlfuncs.h:108
GLdouble s
Definition: gl.h:2039
VOID KdbpPager(IN PCHAR Buffer, IN ULONG BufLength)
Prints the given string with, page by page.
Definition: kdb_cli.c:2933
BOOLEAN KdbSingleStepOver
Definition: kdb.c:44
Definition: typedefs.h:119
BOOLEAN ExpKdbgExtPoolUsed(ULONG Argc, PCHAR Argv[])
STRING KdbPromptString
Definition: kdb_cli.c:143
#define SYNCHRONIZE
Definition: nt_native.h:61
enum _KDB_BREAKPOINT_TYPE KDB_BREAKPOINT_TYPE
_In_ HANDLE hFile
Definition: mswsock.h:90
BOOLEAN KdbpAttachToProcess(PVOID ProcessId)
Switches to another process/thread context.
Definition: kdb.c:1113
ULONG Eip
Definition: ketypes.h:267
ULONG Eax
Definition: ketypes.h:800
static BOOLEAN KdbpCmdPcr(ULONG Argc, PCHAR Argv[])
Displays the KPCR.
Definition: kdb_cli.c:2183
USHORT Ss
Definition: ketypes.h:812
#define SE
Definition: ftp_var.h:28
static BOOLEAN KdbpCmdDmesg(ULONG Argc, PCHAR Argv[])
Display debug messages on screen, with paging.
Definition: kdb_cli.c:2359
_In_ WDFINTERRUPT _In_ PFN_WDF_INTERRUPT_SYNCHRONIZE Callback
Definition: wdfinterrupt.h:456
#define MAXULONG
Definition: typedefs.h:251
ULONG PreviousPreviousMode
Definition: ketypes.h:259
PVOID StackBase
Definition: ketypes.h:1598
static LONG KdbCommandHistoryIndex
Definition: kdb_cli.c:122
ULONG_PTR SIZE_T
Definition: typedefs.h:80
BOOLEAN ExpKdbgExtIrpFind(ULONG Argc, PCHAR Argv[])
ULONG Esp
Definition: ketypes.h:804
USHORT Flags
Definition: ketypes.h:822
struct _FileName FileName
Definition: fatprocs.h:893
NTSTATUS KdbpSafeReadMemory(OUT PVOID Dest, IN PVOID Src, IN ULONG Bytes)
Definition: kdb.c:1679
BOOLEAN ExpKdbgExtFileCache(ULONG Argc, PCHAR Argv[])
BOOLEAN KdbpGetBreakPointInfo(IN ULONG BreakPointNr, OUT ULONG_PTR *Address OPTIONAL, OUT KDB_BREAKPOINT_TYPE *Type OPTIONAL, OUT UCHAR *Size OPTIONAL, OUT KDB_ACCESS_TYPE *AccessType OPTIONAL, OUT UCHAR *DebugReg OPTIONAL, OUT BOOLEAN *Enabled OPTIONAL, OUT BOOLEAN *Global OPTIONAL, OUT PEPROCESS *Process OPTIONAL, OUT PCHAR *ConditionExpression OPTIONAL)
Returns information of the specified breakpoint.
Definition: kdb.c:404
static PCHAR KdbCommandHistory[sizeof(KdbCommandHistoryBuffer)/8]
Definition: kdb_cli.c:120
PVOID KdVersionBlock
Definition: ketypes.h:885
ULONG Esp0
Definition: ketypes.h:793
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
static BOOLEAN KdbpCmdEvalExpression(ULONG Argc, PCHAR Argv[])
Evaluates an expression and displays the result.
Definition: kdb_cli.c:460
PVOID StackBase
Definition: compat.h:571
#define DPFLTR_ERROR_LEVEL
Definition: main.cpp:32
unsigned short USHORT
Definition: pedump.c:61
BOOLEAN(* Fn)(ULONG Argc, PCHAR Argv[])
Definition: kdb_cli.c:340
#define RTL_NUMBER_OF(x)
Definition: RtlRegistry.c:12
ULONG Edi
Definition: ketypes.h:807
ULONG Ebp
Definition: ketypes.h:805
PKGDTENTRY GDT
Definition: ketypes.h:759
NTSYSAPI NTSTATUS NTAPI RtlAnsiStringToUnicodeString(PUNICODE_STRING DestinationString, PANSI_STRING SourceString, BOOLEAN AllocateDestinationString)
LONG KdbLastBreakPointNr
Definition: kdb.c:42
FORCEINLINE BOOLEAN KdbpIsNestedTss(IN USHORT TssSelector, IN PKTSS Tss)
Definition: kdb_cli.c:1040
#define FORCEINLINE
Definition: wdftypes.h:67
UNICODE_STRING BaseDllName
Definition: ldrtypes.h:145
#define KEYSC_ARROWUP
Definition: kdb_cli.c:50
unsigned int * PULONG
Definition: retypes.h:1
#define min(a, b)
Definition: monoChain.cc:55
#define NULL
Definition: types.h:112
USHORT MajorVersion
Definition: ketypes.h:876
static CHAR KdbCommandHistoryBuffer[2048]
Definition: kdb_cli.c:119
#define KEY_DEL
Definition: kdb_cli.c:40
VOID KdbpCliInit(VOID)
Called when KDB is initialized.
Definition: kdb_cli.c:3735
#define _vsnprintf
Definition: xmlstorage.h:202
#define DPRINT1
Definition: precomp.h:8
#define FileStandardInformation
Definition: propsheet.cpp:61
#define FILE_SYNCHRONOUS_IO_NONALERT
Definition: from_kernel.h:31
#define SYSTEM
Definition: fatfs.h:185
BOOLEAN(NTAPI * PKDBG_CLI_ROUTINE)(IN PCHAR Command, IN ULONG Argc, IN PCH Argv[])
Definition: kdb_cli.c:110
#define DBG_STATUS_CONTROL_C
Definition: kdtypes.h:39
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219
PETHREAD KdbCurrentThread
Definition: kdb.c:49
POINT cp
Definition: magnifier.c:59
void int int ULONGLONG int va_list * ap
Definition: winesup.h:32
#define BOOLEAN
Definition: pedump.c:73
#define OUT
Definition: typedefs.h:40
__GNU_EXTENSION typedef unsigned __int64 * PULONGLONG
Definition: ntbasedef.h:383
volatile UCHAR State
Definition: ketypes.h:1721
ULONG Esi
Definition: ketypes.h:806
void __cdecl _disable(void)
Definition: intrin_arm.h:365
GROUP_AFFINITY Affinity
Definition: ketypes.h:1870
ULONG IDR
Definition: ketypes.h:756
#define c
Definition: ke_i.h:80
unsigned int ULONG
Definition: retypes.h:1
BOOLEAN ExpKdbgExtDefWrites(ULONG Argc, PCHAR Argv[])
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
ULONG IrrActive
Definition: ketypes.h:755
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define ULONG_PTR
Definition: config.h:101
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
PVOID StackLimit
Definition: compat.h:572
const char * PCSTR
Definition: typedefs.h:52
__analysis_noreturn NTSYSAPI VOID NTAPI DbgBreakPointWithStatus(_In_ ULONG Status)
BOOLEAN KdbpGetEnterCondition(IN LONG ExceptionNr, IN BOOLEAN FirstChance, OUT KDB_ENTER_CONDITION *Condition)
Gets the first or last chance enter-condition for exception nr. ExceptionNr.
Definition: kdb.c:969
NT_TIB NtTib
Definition: ketypes.h:857
GLfloat GLfloat p
Definition: glext.h:8902
LONG KdbpDisassemble(IN ULONG Address, IN ULONG IntelSyntax)
Definition: i386-dis.c:121
static BOOLEAN KdbpGetComponentId(IN PCSTR ComponentName, OUT PULONG ComponentId)
Retrieves the component ID corresponding to a given component name.
Definition: kdb_cli.c:663
struct _KGDTENTRY::@2415::@2416 Bytes
USHORT Gs
Definition: ketypes.h:818
Definition: _set.h:46
PKIDTENTRY IDT
Definition: ketypes.h:758
#define DPFLTR_TRACE_LEVEL
Definition: kdtypes.h:32
PVOID InitialStack
Definition: ketypes.h:1596
VOID KdbpCliInterpretInitFile(VOID)
This function is called by KdbEnterDebuggerException...
Definition: kdb_cli.c:3686
PCHAR KdbInitFileBuffer
Definition: kdb_cli.c:131
static BOOLEAN KdbpInvokeCliCallbacks(IN PCHAR Command, IN ULONG Argc, IN PCHAR Argv[])
Invokes registered CLI callbacks until one of them handled the Command.
Definition: kdb_cli.c:3512
unsigned short * PUSHORT
Definition: retypes.h:2
VOID NTAPI KeStallExecutionProcessor(IN ULONG MicroSeconds)
Definition: ntoskrnl.c:95
BOOLEAN KdbpSymFindModule(IN PVOID Address OPTIONAL, IN LPCWSTR Name OPTIONAL, IN INT Index OPTIONAL, OUT PLDR_DATA_TABLE_ENTRY *pLdrEntry)
Find a module...
Definition: kdb_symbols.c:84
BOOLEAN KdbpRpnEvaluateExpression(IN PCHAR Expression, IN PKDB_KTRAP_FRAME TrapFrame, OUT PULONGLONG Result, OUT PLONG ErrOffset OPTIONAL, OUT PCHAR ErrMsg OPTIONAL)
Evaluates the given expression.
Definition: kdb_expr.c:1087
volatile ULONG KdpDmesgFreeBytes
Definition: kdio.c:41
base of all file and directory entries
Definition: entries.h:82
static BOOLEAN KdbpCmdBackTrace(ULONG Argc, PCHAR Argv[])
Displays a backtrace.
Definition: kdb_cli.c:1109
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
struct _KPCR * SelfPcr
Definition: ketypes.h:751
ULONG Ebp
Definition: ketypes.h:265
Definition: heap.c:51
#define RTL_CONSTANT_STRING(s)
Definition: tunneltest.c:14
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
BOOLEAN ExpKdbgExtHandle(ULONG Argc, PCHAR Argv[])