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