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