ReactOS  0.4.13-dev-464-g6b95727
kdb_cli.c
Go to the documentation of this file.
1 /*
2  * ReactOS kernel
3  * Copyright (C) 2005 ReactOS Team
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  */
19 /*
20  * PROJECT: ReactOS kernel
21  * FILE: ntoskrnl/kdbg/kdb_cli.c
22  * PURPOSE: Kernel debugger command line interface
23  * PROGRAMMER: Gregor Anich (blight@blight.eu.org)
24  * Hervé Poussineau
25  * UPDATE HISTORY:
26  * Created 16/01/2005
27  */
28 
29 /* INCLUDES ******************************************************************/
30 
31 #include <ntoskrnl.h>
32 
33 #define NDEBUG
34 #include <debug.h>
35 
36 /* DEFINES *******************************************************************/
37 
38 #define KEY_BS 8
39 #define KEY_ESC 27
40 #define KEY_DEL 127
41 
42 #define KEY_SCAN_UP 72
43 #define KEY_SCAN_DOWN 80
44 
45 /* Scan codes of keyboard keys: */
46 #define KEYSC_END 0x004f
47 #define KEYSC_PAGEUP 0x0049
48 #define KEYSC_PAGEDOWN 0x0051
49 #define KEYSC_HOME 0x0047
50 #define KEYSC_ARROWUP 0x0048
51 
52 #define KDB_ENTER_CONDITION_TO_STRING(cond) \
53  ((cond) == KdbDoNotEnter ? "never" : \
54  ((cond) == KdbEnterAlways ? "always" : \
55  ((cond) == KdbEnterFromKmode ? "kmode" : "umode")))
56 
57 #define KDB_ACCESS_TYPE_TO_STRING(type) \
58  ((type) == KdbAccessRead ? "read" : \
59  ((type) == KdbAccessWrite ? "write" : \
60  ((type) == KdbAccessReadWrite ? "rdwr" : "exec")))
61 
62 #define NPX_STATE_TO_STRING(state) \
63  ((state) == NPX_STATE_LOADED ? "Loaded" : \
64  ((state) == NPX_STATE_NOT_LOADED ? "Not loaded" : "Unknown"))
65 
66 /* PROTOTYPES ****************************************************************/
67 
68 static BOOLEAN KdbpCmdEvalExpression(ULONG Argc, PCHAR Argv[]);
69 static BOOLEAN KdbpCmdDisassembleX(ULONG Argc, PCHAR Argv[]);
70 static BOOLEAN KdbpCmdRegs(ULONG Argc, PCHAR Argv[]);
71 static BOOLEAN KdbpCmdBackTrace(ULONG Argc, PCHAR Argv[]);
72 
73 static BOOLEAN KdbpCmdContinue(ULONG Argc, PCHAR Argv[]);
74 static BOOLEAN KdbpCmdStep(ULONG Argc, PCHAR Argv[]);
75 static BOOLEAN KdbpCmdBreakPointList(ULONG Argc, PCHAR Argv[]);
77 static BOOLEAN KdbpCmdBreakPoint(ULONG Argc, PCHAR Argv[]);
78 
79 static BOOLEAN KdbpCmdThread(ULONG Argc, PCHAR Argv[]);
80 static BOOLEAN KdbpCmdProc(ULONG Argc, PCHAR Argv[]);
81 
82 static BOOLEAN KdbpCmdMod(ULONG Argc, PCHAR Argv[]);
83 static BOOLEAN KdbpCmdGdtLdtIdt(ULONG Argc, PCHAR Argv[]);
84 static BOOLEAN KdbpCmdPcr(ULONG Argc, PCHAR Argv[]);
85 static BOOLEAN KdbpCmdTss(ULONG Argc, PCHAR Argv[]);
86 
87 static BOOLEAN KdbpCmdBugCheck(ULONG Argc, PCHAR Argv[]);
88 static BOOLEAN KdbpCmdReboot(ULONG Argc, PCHAR Argv[]);
89 static BOOLEAN KdbpCmdFilter(ULONG Argc, PCHAR Argv[]);
90 static BOOLEAN KdbpCmdSet(ULONG Argc, PCHAR Argv[]);
91 static BOOLEAN KdbpCmdHelp(ULONG Argc, PCHAR Argv[]);
92 static BOOLEAN KdbpCmdDmesg(ULONG Argc, PCHAR Argv[]);
93 
94 BOOLEAN ExpKdbgExtPool(ULONG Argc, PCHAR Argv[]);
99 BOOLEAN ExpKdbgExtIrpFind(ULONG Argc, PCHAR Argv[]);
100 BOOLEAN ExpKdbgExtHandle(ULONG Argc, PCHAR Argv[]);
101 
102 #ifdef __ROS_DWARF__
103 static BOOLEAN KdbpCmdPrintStruct(ULONG Argc, PCHAR Argv[]);
104 #endif
105 
106 /* GLOBALS *******************************************************************/
107 
108 static PKDBG_CLI_ROUTINE KdbCliCallbacks[10];
109 static BOOLEAN KdbUseIntelSyntax = FALSE; /* Set to TRUE for intel syntax */
110 static BOOLEAN KdbBreakOnModuleLoad = FALSE; /* Set to TRUE to break into KDB when a module is loaded */
111 
112 static CHAR KdbCommandHistoryBuffer[2048]; /* Command history string ringbuffer */
113 static PCHAR KdbCommandHistory[sizeof(KdbCommandHistoryBuffer) / 8] = { NULL }; /* Command history ringbuffer */
116 
123 
124 PCHAR KdbInitFileBuffer = NULL; /* Buffer where KDBinit file is loaded into during initialization */
126 
127 /* Vars for dmesg */
128 /* defined in ../kd/kdio.c, declare here: */
129 extern volatile BOOLEAN KdbpIsInDmesgMode;
130 extern const ULONG KdpDmesgBufferSize;
131 extern PCHAR KdpDmesgBuffer;
132 extern volatile ULONG KdpDmesgCurrentPosition;
133 extern volatile ULONG KdpDmesgFreeBytes;
134 extern volatile ULONG KdbDmesgTotalWritten;
135 
136 static const struct
137 {
141  BOOLEAN (*Fn)(ULONG Argc, PCHAR Argv[]);
142 } KdbDebuggerCommands[] = {
143  /* Data */
144  { NULL, NULL, "Data", NULL },
145  { "?", "? expression", "Evaluate expression.", KdbpCmdEvalExpression },
146  { "disasm", "disasm [address] [L count]", "Disassemble count instructions at address.", KdbpCmdDisassembleX },
147  { "x", "x [address] [L count]", "Display count dwords, starting at addr.", KdbpCmdDisassembleX },
148  { "regs", "regs", "Display general purpose registers.", KdbpCmdRegs },
149  { "cregs", "cregs", "Display control registers.", KdbpCmdRegs },
150  { "sregs", "sregs", "Display status registers.", KdbpCmdRegs },
151  { "dregs", "dregs", "Display debug registers.", KdbpCmdRegs },
152  { "bt", "bt [*frameaddr|thread id]", "Prints current backtrace or from given frame addr", KdbpCmdBackTrace },
153 #ifdef __ROS_DWARF__
154  { "dt", "dt [mod] [type] [addr]", "Print a struct. Addr is optional.", KdbpCmdPrintStruct },
155 #endif
156 
157  /* Flow control */
158  { NULL, NULL, "Flow control", NULL },
159  { "cont", "cont", "Continue execution (leave debugger)", KdbpCmdContinue },
160  { "step", "step [count]", "Execute single instructions, stepping into interrupts.", KdbpCmdStep },
161  { "next", "next [count]", "Execute single instructions, skipping calls and reps.", KdbpCmdStep },
162  { "bl", "bl", "List breakpoints.", KdbpCmdBreakPointList },
163  { "be", "be [breakpoint]", "Enable breakpoint.", KdbpCmdEnableDisableClearBreakPoint },
164  { "bd", "bd [breakpoint]", "Disable breakpoint.", KdbpCmdEnableDisableClearBreakPoint },
165  { "bc", "bc [breakpoint]", "Clear breakpoint.", KdbpCmdEnableDisableClearBreakPoint },
166  { "bpx", "bpx [address] [IF condition]", "Set software execution breakpoint at address.", KdbpCmdBreakPoint },
167  { "bpm", "bpm [r|w|rw|x] [byte|word|dword] [address] [IF condition]", "Set memory breakpoint at address.", KdbpCmdBreakPoint },
168 
169  /* Process/Thread */
170  { NULL, NULL, "Process/Thread", NULL },
171  { "thread", "thread [list[ pid]|[attach ]tid]", "List threads in current or specified process, display thread with given id or attach to thread.", KdbpCmdThread },
172  { "proc", "proc [list|[attach ]pid]", "List processes, display process with given id or attach to process.", KdbpCmdProc },
173 
174  /* System information */
175  { NULL, NULL, "System info", NULL },
176  { "mod", "mod [address]", "List all modules or the one containing address.", KdbpCmdMod },
177  { "gdt", "gdt", "Display global descriptor table.", KdbpCmdGdtLdtIdt },
178  { "ldt", "ldt", "Display local descriptor table.", KdbpCmdGdtLdtIdt },
179  { "idt", "idt", "Display interrupt descriptor table.", KdbpCmdGdtLdtIdt },
180  { "pcr", "pcr", "Display processor control region.", KdbpCmdPcr },
181  { "tss", "tss", "Display task state segment.", KdbpCmdTss },
182 
183  /* Others */
184  { NULL, NULL, "Others", NULL },
185  { "bugcheck", "bugcheck", "Bugchecks the system.", KdbpCmdBugCheck },
186  { "reboot", "reboot", "Reboots the system.", KdbpCmdReboot},
187  { "filter", "filter [error|warning|trace|info|level]+|-[componentname|default]", "Enable/disable debug channels", KdbpCmdFilter },
188  { "set", "set [var] [value]", "Sets var to value or displays value of var.", KdbpCmdSet },
189  { "dmesg", "dmesg", "Display debug messages on screen, with navigation on pages.", KdbpCmdDmesg },
190  { "kmsg", "kmsg", "Kernel dmesg. Alias for dmesg.", KdbpCmdDmesg },
191  { "help", "help", "Display help screen.", KdbpCmdHelp },
192  { "!pool", "!pool [Address [Flags]]", "Display information about pool allocations.", ExpKdbgExtPool },
193  { "!poolused", "!poolused [Flags [Tag]]", "Display pool usage.", ExpKdbgExtPoolUsed },
194  { "!poolfind", "!poolfind Tag [Pool]", "Search for pool tag allocations.", ExpKdbgExtPoolFind },
195  { "!filecache", "!filecache", "Display cache usage.", ExpKdbgExtFileCache },
196  { "!defwrites", "!defwrites", "Display cache write values.", ExpKdbgExtDefWrites },
197  { "!irpfind", "!irpfind [Pool [startaddress [criteria data]]]", "Lists IRPs potentially matching criteria", ExpKdbgExtIrpFind },
198  { "!handle", "!handle [Handle]", "Displays info about handles", ExpKdbgExtHandle },
199 };
200 
201 /* FUNCTIONS *****************************************************************/
202 
211 static BOOLEAN
213  IN PCCH ComponentName,
215 {
216  ULONG i;
217 
218  static struct
219  {
220  PCCH Name;
221  ULONG Id;
222  }
223  ComponentTable[] =
224  {
225  { "DEFAULT", MAXULONG },
226  { "SYSTEM", DPFLTR_SYSTEM_ID },
227  { "SMSS", DPFLTR_SMSS_ID },
228  { "SETUP", DPFLTR_SETUP_ID },
229  { "NTFS", DPFLTR_NTFS_ID },
230  { "FSTUB", DPFLTR_FSTUB_ID },
231  { "CRASHDUMP", DPFLTR_CRASHDUMP_ID },
232  { "CDAUDIO", DPFLTR_CDAUDIO_ID },
233  { "CDROM", DPFLTR_CDROM_ID },
234  { "CLASSPNP", DPFLTR_CLASSPNP_ID },
235  { "DISK", DPFLTR_DISK_ID },
236  { "REDBOOK", DPFLTR_REDBOOK_ID },
237  { "STORPROP", DPFLTR_STORPROP_ID },
238  { "SCSIPORT", DPFLTR_SCSIPORT_ID },
239  { "SCSIMINIPORT", DPFLTR_SCSIMINIPORT_ID },
240  { "CONFIG", DPFLTR_CONFIG_ID },
241  { "I8042PRT", DPFLTR_I8042PRT_ID },
242  { "SERMOUSE", DPFLTR_SERMOUSE_ID },
243  { "LSERMOUS", DPFLTR_LSERMOUS_ID },
244  { "KBDHID", DPFLTR_KBDHID_ID },
245  { "MOUHID", DPFLTR_MOUHID_ID },
246  { "KBDCLASS", DPFLTR_KBDCLASS_ID },
247  { "MOUCLASS", DPFLTR_MOUCLASS_ID },
248  { "TWOTRACK", DPFLTR_TWOTRACK_ID },
249  { "WMILIB", DPFLTR_WMILIB_ID },
250  { "ACPI", DPFLTR_ACPI_ID },
251  { "AMLI", DPFLTR_AMLI_ID },
252  { "HALIA64", DPFLTR_HALIA64_ID },
253  { "VIDEO", DPFLTR_VIDEO_ID },
254  { "SVCHOST", DPFLTR_SVCHOST_ID },
255  { "VIDEOPRT", DPFLTR_VIDEOPRT_ID },
256  { "TCPIP", DPFLTR_TCPIP_ID },
257  { "DMSYNTH", DPFLTR_DMSYNTH_ID },
258  { "NTOSPNP", DPFLTR_NTOSPNP_ID },
259  { "FASTFAT", DPFLTR_FASTFAT_ID },
260  { "SAMSS", DPFLTR_SAMSS_ID },
261  { "PNPMGR", DPFLTR_PNPMGR_ID },
262  { "NETAPI", DPFLTR_NETAPI_ID },
263  { "SCSERVER", DPFLTR_SCSERVER_ID },
264  { "SCCLIENT", DPFLTR_SCCLIENT_ID },
265  { "SERIAL", DPFLTR_SERIAL_ID },
266  { "SERENUM", DPFLTR_SERENUM_ID },
267  { "UHCD", DPFLTR_UHCD_ID },
268  { "RPCPROXY", DPFLTR_RPCPROXY_ID },
269  { "AUTOCHK", DPFLTR_AUTOCHK_ID },
270  { "DCOMSS", DPFLTR_DCOMSS_ID },
271  { "UNIMODEM", DPFLTR_UNIMODEM_ID },
272  { "SIS", DPFLTR_SIS_ID },
273  { "FLTMGR", DPFLTR_FLTMGR_ID },
274  { "WMICORE", DPFLTR_WMICORE_ID },
275  { "BURNENG", DPFLTR_BURNENG_ID },
276  { "IMAPI", DPFLTR_IMAPI_ID },
277  { "SXS", DPFLTR_SXS_ID },
278  { "FUSION", DPFLTR_FUSION_ID },
279  { "IDLETASK", DPFLTR_IDLETASK_ID },
280  { "SOFTPCI", DPFLTR_SOFTPCI_ID },
281  { "TAPE", DPFLTR_TAPE_ID },
282  { "MCHGR", DPFLTR_MCHGR_ID },
283  { "IDEP", DPFLTR_IDEP_ID },
284  { "PCIIDE", DPFLTR_PCIIDE_ID },
285  { "FLOPPY", DPFLTR_FLOPPY_ID },
286  { "FDC", DPFLTR_FDC_ID },
287  { "TERMSRV", DPFLTR_TERMSRV_ID },
288  { "W32TIME", DPFLTR_W32TIME_ID },
289  { "PREFETCHER", DPFLTR_PREFETCHER_ID },
290  { "RSFILTER", DPFLTR_RSFILTER_ID },
291  { "FCPORT", DPFLTR_FCPORT_ID },
292  { "PCI", DPFLTR_PCI_ID },
293  { "DMIO", DPFLTR_DMIO_ID },
294  { "DMCONFIG", DPFLTR_DMCONFIG_ID },
295  { "DMADMIN", DPFLTR_DMADMIN_ID },
296  { "WSOCKTRANSPORT", DPFLTR_WSOCKTRANSPORT_ID },
297  { "VSS", DPFLTR_VSS_ID },
298  { "PNPMEM", DPFLTR_PNPMEM_ID },
299  { "PROCESSOR", DPFLTR_PROCESSOR_ID },
300  { "DMSERVER", DPFLTR_DMSERVER_ID },
301  { "SR", DPFLTR_SR_ID },
302  { "INFINIBAND", DPFLTR_INFINIBAND_ID },
303  { "IHVDRIVER", DPFLTR_IHVDRIVER_ID },
304  { "IHVVIDEO", DPFLTR_IHVVIDEO_ID },
305  { "IHVAUDIO", DPFLTR_IHVAUDIO_ID },
306  { "IHVNETWORK", DPFLTR_IHVNETWORK_ID },
307  { "IHVSTREAMING", DPFLTR_IHVSTREAMING_ID },
308  { "IHVBUS", DPFLTR_IHVBUS_ID },
309  { "HPS", DPFLTR_HPS_ID },
310  { "RTLTHREADPOOL", DPFLTR_RTLTHREADPOOL_ID },
311  { "LDR", DPFLTR_LDR_ID },
312  { "TCPIP6", DPFLTR_TCPIP6_ID },
313  { "ISAPNP", DPFLTR_ISAPNP_ID },
314  { "SHPC", DPFLTR_SHPC_ID },
315  { "STORPORT", DPFLTR_STORPORT_ID },
316  { "STORMINIPORT", DPFLTR_STORMINIPORT_ID },
317  { "PRINTSPOOLER", DPFLTR_PRINTSPOOLER_ID },
318  { "VSSDYNDISK", DPFLTR_VSSDYNDISK_ID },
319  { "VERIFIER", DPFLTR_VERIFIER_ID },
320  { "VDS", DPFLTR_VDS_ID },
321  { "VDSBAS", DPFLTR_VDSBAS_ID },
322  { "VDSDYN", DPFLTR_VDSDYN_ID },
323  { "VDSDYNDR", DPFLTR_VDSDYNDR_ID },
324  { "VDSLDR", DPFLTR_VDSLDR_ID },
325  { "VDSUTIL", DPFLTR_VDSUTIL_ID },
326  { "DFRGIFC", DPFLTR_DFRGIFC_ID },
327  { "MM", DPFLTR_MM_ID },
328  { "DFSC", DPFLTR_DFSC_ID },
329  { "WOW64", DPFLTR_WOW64_ID },
330  { "ALPC", DPFLTR_ALPC_ID },
331  { "WDI", DPFLTR_WDI_ID },
332  { "PERFLIB", DPFLTR_PERFLIB_ID },
333  { "KTM", DPFLTR_KTM_ID },
334  { "IOSTRESS", DPFLTR_IOSTRESS_ID },
335  { "HEAP", DPFLTR_HEAP_ID },
336  { "WHEA", DPFLTR_WHEA_ID },
337  { "USERGDI", DPFLTR_USERGDI_ID },
338  { "MMCSS", DPFLTR_MMCSS_ID },
339  { "TPM", DPFLTR_TPM_ID },
340  { "THREADORDER", DPFLTR_THREADORDER_ID },
341  { "ENVIRON", DPFLTR_ENVIRON_ID },
342  { "EMS", DPFLTR_EMS_ID },
343  { "WDT", DPFLTR_WDT_ID },
344  { "FVEVOL", DPFLTR_FVEVOL_ID },
345  { "NDIS", DPFLTR_NDIS_ID },
346  { "NVCTRACE", DPFLTR_NVCTRACE_ID },
347  { "LUAFV", DPFLTR_LUAFV_ID },
348  { "APPCOMPAT", DPFLTR_APPCOMPAT_ID },
349  { "USBSTOR", DPFLTR_USBSTOR_ID },
350  { "SBP2PORT", DPFLTR_SBP2PORT_ID },
351  { "COVERAGE", DPFLTR_COVERAGE_ID },
352  { "CACHEMGR", DPFLTR_CACHEMGR_ID },
353  { "MOUNTMGR", DPFLTR_MOUNTMGR_ID },
354  { "CFR", DPFLTR_CFR_ID },
355  { "TXF", DPFLTR_TXF_ID },
356  { "KSECDD", DPFLTR_KSECDD_ID },
357  { "FLTREGRESS", DPFLTR_FLTREGRESS_ID },
358  { "MPIO", DPFLTR_MPIO_ID },
359  { "MSDSM", DPFLTR_MSDSM_ID },
360  { "UDFS", DPFLTR_UDFS_ID },
361  { "PSHED", DPFLTR_PSHED_ID },
362  { "STORVSP", DPFLTR_STORVSP_ID },
363  { "LSASS", DPFLTR_LSASS_ID },
364  { "SSPICLI", DPFLTR_SSPICLI_ID },
365  { "CNG", DPFLTR_CNG_ID },
366  { "EXFAT", DPFLTR_EXFAT_ID },
367  { "FILETRACE", DPFLTR_FILETRACE_ID },
368  { "XSAVE", DPFLTR_XSAVE_ID },
369  { "SE", DPFLTR_SE_ID },
370  { "DRIVEEXTENDER", DPFLTR_DRIVEEXTENDER_ID },
371  };
372 
373  for (i = 0; i < sizeof(ComponentTable) / sizeof(ComponentTable[0]); i++)
374  {
375  if (_stricmp(ComponentName, ComponentTable[i].Name) == 0)
376  {
377  *ComponentId = ComponentTable[i].Id;
378  return TRUE;
379  }
380  }
381 
382  return FALSE;
383 }
384 
397 static BOOLEAN
400  IN LONG ErrOffset,
402 {
403  static CHAR ErrMsgBuffer[130] = "^ ";
404  LONG ExpressionErrOffset = -1;
405  PCHAR ErrMsg = ErrMsgBuffer;
406  BOOLEAN Ok;
407 
409  &ExpressionErrOffset, ErrMsgBuffer + 2);
410  if (!Ok)
411  {
412  if (ExpressionErrOffset >= 0)
413  ExpressionErrOffset += ErrOffset;
414  else
415  ErrMsg += 2;
416 
417  KdbpPrint("%*s%s\n", ExpressionErrOffset, "", ErrMsg);
418  }
419 
420  return Ok;
421 }
422 
423 BOOLEAN
424 NTAPI
426  IN PCHAR pszNum,
427  OUT ULONG_PTR *pulValue)
428 {
429  char *endptr;
430 
431  /* Skip optional '0x' prefix */
432  if ((pszNum[0] == '0') && ((pszNum[1] == 'x') || (pszNum[1] == 'X')))
433  pszNum += 2;
434 
435  /* Make a number from the string (hex) */
436  *pulValue = strtoul(pszNum, &endptr, 16);
437 
438  return (*endptr == '\0');
439 }
440 
443 static BOOLEAN
445  ULONG Argc,
446  PCHAR Argv[])
447 {
448  ULONG i, len;
449  ULONGLONG Result = 0;
450  ULONG ul;
451  LONG l = 0;
452  BOOLEAN Ok;
453 
454  if (Argc < 2)
455  {
456  KdbpPrint("?: Argument required\n");
457  return TRUE;
458  }
459 
460  /* Put the arguments back together */
461  Argc--;
462  for (i = 1; i < Argc; i++)
463  {
464  len = strlen(Argv[i]);
465  Argv[i][len] = ' ';
466  }
467 
468  /* Evaluate the expression */
469  Ok = KdbpEvaluateExpression(Argv[1], sizeof("kdb:> ")-1 + (Argv[1]-Argv[0]), &Result);
470  if (Ok)
471  {
472  if (Result > 0x00000000ffffffffLL)
473  {
474  if (Result & 0x8000000000000000LL)
475  KdbpPrint("0x%016I64x %20I64u %20I64d\n", Result, Result, Result);
476  else
477  KdbpPrint("0x%016I64x %20I64u\n", Result, Result);
478  }
479  else
480  {
481  ul = (ULONG)Result;
482 
483  if (ul <= 0xff && ul >= 0x80)
484  l = (LONG)((CHAR)ul);
485  else if (ul <= 0xffff && ul >= 0x8000)
486  l = (LONG)((SHORT)ul);
487  else
488  l = (LONG)ul;
489 
490  if (l < 0)
491  KdbpPrint("0x%08lx %10lu %10ld\n", ul, ul, l);
492  else
493  KdbpPrint("0x%08lx %10lu\n", ul, ul);
494  }
495  }
496 
497  return TRUE;
498 }
499 
500 #ifdef __ROS_DWARF__
501 
504 static VOID
505 KdbpPrintStructInternal
507  PCHAR Indent,
508  BOOLEAN DoRead,
510  PROSSYM_AGGREGATE Aggregate)
511 {
512  ULONG i;
515  ULONG IndentLen = strlen(Indent);
516  ROSSYM_AGGREGATE MemberAggregate = {0 };
517 
518  for (i = 0; i < Aggregate->NumElements; i++) {
519  Member = &Aggregate->Elements[i];
520  KdbpPrint("%s%p+%x: %s", Indent, ((PCHAR)BaseAddress) + Member->BaseOffset, Member->Size, Member->Name ? Member->Name : "<anoymous>");
521  if (DoRead) {
522  if (!strcmp(Member->Type, "_UNICODE_STRING")) {
523  KdbpPrint("\"%wZ\"\n", ((PCHAR)BaseAddress) + Member->BaseOffset);
524  continue;
525  } else if (!strcmp(Member->Type, "PUNICODE_STRING")) {
526  KdbpPrint("\"%wZ\"\n", *(((PUNICODE_STRING*)((PCHAR)BaseAddress) + Member->BaseOffset)));
527  continue;
528  }
529  switch (Member->Size) {
530  case 1:
531  case 2:
532  case 4:
533  case 8: {
534  Result = 0;
535  if (NT_SUCCESS(KdbpSafeReadMemory(&Result, ((PCHAR)BaseAddress) + Member->BaseOffset, Member->Size))) {
536  if (Member->Bits) {
537  Result >>= Member->FirstBit;
538  Result &= ((1 << Member->Bits) - 1);
539  }
540  KdbpPrint(" %lx\n", Result);
541  }
542  else goto readfail;
543  break;
544  }
545  default: {
546  if (Member->Size < 8) {
547  if (NT_SUCCESS(KdbpSafeReadMemory(&Result, ((PCHAR)BaseAddress) + Member->BaseOffset, Member->Size))) {
548  ULONG j;
549  for (j = 0; j < Member->Size; j++) {
550  KdbpPrint(" %02x", (int)(Result & 0xff));
551  Result >>= 8;
552  }
553  } else goto readfail;
554  } else {
555  KdbpPrint(" %s @ %p {\n", Member->Type, ((PCHAR)BaseAddress) + Member->BaseOffset);
556  Indent[IndentLen] = ' ';
557  if (RosSymAggregate(Info, Member->Type, &MemberAggregate)) {
558  KdbpPrintStructInternal(Info, Indent, DoRead, ((PCHAR)BaseAddress) + Member->BaseOffset, &MemberAggregate);
559  RosSymFreeAggregate(&MemberAggregate);
560  }
561  Indent[IndentLen] = 0;
562  KdbpPrint("%s}\n", Indent);
563  } break;
564  }
565  }
566  } else {
567  readfail:
568  if (Member->Size <= 8) {
569  KdbpPrint(" ??\n");
570  } else {
571  KdbpPrint(" %s @ %x {\n", Member->Type, Member->BaseOffset);
572  Indent[IndentLen] = ' ';
573  if (RosSymAggregate(Info, Member->Type, &MemberAggregate)) {
574  KdbpPrintStructInternal(Info, Indent, DoRead, BaseAddress, &MemberAggregate);
575  RosSymFreeAggregate(&MemberAggregate);
576  }
577  Indent[IndentLen] = 0;
578  KdbpPrint("%s}\n", Indent);
579  }
580  }
581  }
582 }
583 
585 
586 static BOOLEAN
587 KdbpCmdPrintStruct(
588  ULONG Argc,
589  PCHAR Argv[])
590 {
591  ULONG i;
592  ULONGLONG Result = 0;
593  PVOID BaseAddress = 0;
594  ROSSYM_AGGREGATE Aggregate = {0};
595  UNICODE_STRING ModName = {0};
596  ANSI_STRING AnsiName = {0};
597  CHAR Indent[100] = {0};
599 
600  if (Argc < 3) goto end;
601  AnsiName.Length = AnsiName.MaximumLength = strlen(Argv[1]);
602  AnsiName.Buffer = Argv[1];
603  RtlAnsiStringToUnicodeString(&ModName, &AnsiName, TRUE);
604  Info = KdbpSymFindCachedFile(&ModName);
605 
606  if (!Info || !RosSymAggregate(Info, Argv[2], &Aggregate)) {
607  DPRINT1("Could not get aggregate\n");
608  goto end;
609  }
610 
611  // Get an argument for location if it was given
612  if (Argc > 3) {
613  ULONG len;
614  PCHAR ArgStart = Argv[3];
615  DPRINT1("Trying to get expression\n");
616  for (i = 3; i < Argc - 1; i++)
617  {
618  len = strlen(Argv[i]);
619  Argv[i][len] = ' ';
620  }
621 
622  /* Evaluate the expression */
623  DPRINT1("Arg: %s\n", ArgStart);
624  if (KdbpEvaluateExpression(ArgStart, strlen(ArgStart), &Result)) {
626  DPRINT1("BaseAddress: %p\n", BaseAddress);
627  }
628  }
629  DPRINT1("BaseAddress %p\n", BaseAddress);
630  KdbpPrintStructInternal(Info, Indent, !!BaseAddress, BaseAddress, &Aggregate);
631 end:
632  RosSymFreeAggregate(&Aggregate);
633  RtlFreeUnicodeString(&ModName);
634  return TRUE;
635 }
636 #endif
637 
640 static BOOLEAN
642  ULONG Argc,
643  PCHAR Argv[])
644 {
646  ULONG set = DPFLTR_MASK, clear = DPFLTR_MASK;
647  PCHAR pend;
648  LPCSTR opt, p;
649 
650  static struct
651  {
652  LPCSTR Name;
653  ULONG Level;
654  }
655  debug_classes[] =
656  {
657  { "error", 1 << DPFLTR_ERROR_LEVEL },
658  { "warning", 1 << DPFLTR_WARNING_LEVEL },
659  { "trace", 1 << DPFLTR_TRACE_LEVEL },
660  { "info", 1 << DPFLTR_INFO_LEVEL },
661  };
662 
663  for (i = 1; i < Argc; i++)
664  {
665  opt = Argv[i];
666  p = opt + strcspn(opt, "+-");
667  if (!p[0]) p = opt; /* assume it's a debug channel name */
668 
669  if (p > opt)
670  {
671  for (j = 0; j < sizeof(debug_classes) / sizeof(debug_classes[0]); j++)
672  {
674  if (len != (p - opt))
675  continue;
676  if (_strnicmp(opt, debug_classes[j].Name, len) == 0) /* found it */
677  {
678  if (*p == '+')
679  set |= debug_classes[j].Level;
680  else
681  clear |= debug_classes[j].Level;
682  break;
683  }
684  }
685  if (j == sizeof(debug_classes) / sizeof(debug_classes[0]))
686  {
687  Level = strtoul(opt, &pend, 0);
688  if (pend != p)
689  {
690  KdbpPrint("filter: bad class name '%.*s'\n", p - opt, opt);
691  continue;
692  }
693  if (*p == '+')
694  set |= Level;
695  else
696  clear |= Level;
697  }
698  }
699  else
700  {
701  if (*p == '-')
702  clear = MAXULONG;
703  else
704  set = MAXULONG;
705  }
706  if (*p == '+' || *p == '-')
707  p++;
708 
710  {
711  KdbpPrint("filter: '%s' is not a valid component name!\n", p);
712  return TRUE;
713  }
714 
715  /* Get current mask value */
718  }
719 
720  return TRUE;
721 }
722 
726 static BOOLEAN
728  ULONG Argc,
729  PCHAR Argv[])
730 {
731  ULONG Count;
732  ULONG ul;
733  INT i;
734  ULONGLONG Result = 0;
736  LONG InstLen;
737 
738  if (Argv[0][0] == 'x') /* display memory */
739  Count = 16;
740  else /* disassemble */
741  Count = 10;
742 
743  if (Argc >= 2)
744  {
745  /* Check for [L count] part */
746  ul = 0;
747  if (strcmp(Argv[Argc-2], "L") == 0)
748  {
749  ul = strtoul(Argv[Argc-1], NULL, 0);
750  if (ul > 0)
751  {
752  Count = ul;
753  Argc -= 2;
754  }
755  }
756  else if (Argv[Argc-1][0] == 'L')
757  {
758  ul = strtoul(Argv[Argc-1] + 1, NULL, 0);
759  if (ul > 0)
760  {
761  Count = ul;
762  Argc--;
763  }
764  }
765 
766  /* Put the remaining arguments back together */
767  Argc--;
768  for (ul = 1; ul < Argc; ul++)
769  {
770  Argv[ul][strlen(Argv[ul])] = ' ';
771  }
772  Argc++;
773  }
774 
775  /* Evaluate the expression */
776  if (Argc > 1)
777  {
778  if (!KdbpEvaluateExpression(Argv[1], sizeof("kdb:> ")-1 + (Argv[1]-Argv[0]), &Result))
779  return TRUE;
780 
781  if (Result > (ULONGLONG)(~((ULONG_PTR)0)))
782  KdbpPrint("Warning: Address %I64x is beeing truncated\n",Result);
783 
785  }
786  else if (Argv[0][0] == 'x')
787  {
788  KdbpPrint("x: Address argument required.\n");
789  return TRUE;
790  }
791 
792  if (Argv[0][0] == 'x')
793  {
794  /* Display dwords */
795  ul = 0;
796 
797  while (Count > 0)
798  {
800  KdbpPrint("<%x>:", Address);
801  else
802  KdbpPrint(":");
803 
804  i = min(4, Count);
805  Count -= i;
806 
807  while (--i >= 0)
808  {
809  if (!NT_SUCCESS(KdbpSafeReadMemory(&ul, (PVOID)Address, sizeof(ul))))
810  KdbpPrint(" ????????");
811  else
812  KdbpPrint(" %08x", ul);
813 
814  Address += sizeof(ul);
815  }
816 
817  KdbpPrint("\n");
818  }
819  }
820  else
821  {
822  /* Disassemble */
823  while (Count-- > 0)
824  {
826  KdbpPrint("<%08x>: ", Address);
827  else
828  KdbpPrint(": ");
829 
831  if (InstLen < 0)
832  {
833  KdbpPrint("<INVALID>\n");
834  return TRUE;
835  }
836 
837  KdbpPrint("\n");
838  Address += InstLen;
839  }
840  }
841 
842  return TRUE;
843 }
844 
847 static BOOLEAN
849  ULONG Argc,
850  PCHAR Argv[])
851 {
853  INT i;
854  static const PCHAR EflagsBits[32] = { " CF", NULL, " PF", " BIT3", " AF", " BIT5",
855  " ZF", " SF", " TF", " IF", " DF", " OF",
856  NULL, NULL, " NT", " BIT15", " RF", " VF",
857  " AC", " VIF", " VIP", " ID", " BIT22",
858  " BIT23", " BIT24", " BIT25", " BIT26",
859  " BIT27", " BIT28", " BIT29", " BIT30",
860  " BIT31" };
861 
862  if (Argv[0][0] == 'r') /* regs */
863  {
864  KdbpPrint("CS:EIP 0x%04x:0x%08x\n"
865  "SS:ESP 0x%04x:0x%08x\n"
866  " EAX 0x%08x EBX 0x%08x\n"
867  " ECX 0x%08x EDX 0x%08x\n"
868  " ESI 0x%08x EDI 0x%08x\n"
869  " EBP 0x%08x\n",
870  Tf->SegCs & 0xFFFF, Tf->Eip,
871  Tf->SegSs, Tf->Esp,
872  Tf->Eax, Tf->Ebx,
873  Tf->Ecx, Tf->Edx,
874  Tf->Esi, Tf->Edi,
875  Tf->Ebp);
876  KdbpPrint("EFLAGS 0x%08x ", Tf->EFlags);
877 
878  for (i = 0; i < 32; i++)
879  {
880  if (i == 1)
881  {
882  if ((Tf->EFlags & (1 << 1)) == 0)
883  KdbpPrint(" !BIT1");
884  }
885  else if (i == 12)
886  {
887  KdbpPrint(" IOPL%d", (Tf->EFlags >> 12) & 3);
888  }
889  else if (i == 13)
890  {
891  }
892  else if ((Tf->EFlags & (1 << i)) != 0)
893  {
894  KdbpPrint(EflagsBits[i]);
895  }
896  }
897 
898  KdbpPrint("\n");
899  }
900  else if (Argv[0][0] == 'c') /* cregs */
901  {
902  ULONG Cr0, Cr2, Cr3, Cr4;
903  KDESCRIPTOR Gdtr = {0, 0, 0}, Idtr = {0, 0, 0};
904  USHORT Ldtr;
905  static const PCHAR Cr0Bits[32] = { " PE", " MP", " EM", " TS", " ET", " NE", NULL, NULL,
906  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
907  " WP", NULL, " AM", NULL, NULL, NULL, NULL, NULL,
908  NULL, NULL, NULL, NULL, NULL, " NW", " CD", " PG" };
909  static const PCHAR Cr4Bits[32] = { " VME", " PVI", " TSD", " DE", " PSE", " PAE", " MCE", " PGE",
910  " PCE", " OSFXSR", " OSXMMEXCPT", NULL, NULL, NULL, NULL, NULL,
911  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
912  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
913 
914  Cr0 = KdbCurrentTrapFrame->Cr0;
915  Cr2 = KdbCurrentTrapFrame->Cr2;
916  Cr3 = KdbCurrentTrapFrame->Cr3;
917  Cr4 = KdbCurrentTrapFrame->Cr4;
918 
919  /* Get descriptor table regs */
920  Ke386GetGlobalDescriptorTable(&Gdtr.Limit);
921  Ldtr = Ke386GetLocalDescriptorTable();
922  __sidt(&Idtr.Limit);
923 
924  /* Display the control registers */
925  KdbpPrint("CR0 0x%08x ", Cr0);
926 
927  for (i = 0; i < 32; i++)
928  {
929  if (!Cr0Bits[i])
930  continue;
931 
932  if ((Cr0 & (1 << i)) != 0)
933  KdbpPrint(Cr0Bits[i]);
934  }
935 
936  KdbpPrint("\nCR2 0x%08x\n", Cr2);
937  KdbpPrint("CR3 0x%08x Pagedir-Base 0x%08x %s%s\n", Cr3, (Cr3 & 0xfffff000),
938  (Cr3 & (1 << 3)) ? " PWT" : "", (Cr3 & (1 << 4)) ? " PCD" : "" );
939  KdbpPrint("CR4 0x%08x ", Cr4);
940 
941  for (i = 0; i < 32; i++)
942  {
943  if (!Cr4Bits[i])
944  continue;
945 
946  if ((Cr4 & (1 << i)) != 0)
947  KdbpPrint(Cr4Bits[i]);
948  }
949 
950  /* Display the descriptor table regs */
951  KdbpPrint("\nGDTR Base 0x%08x Size 0x%04x\n", Gdtr.Base, Gdtr.Limit);
952  KdbpPrint("LDTR 0x%04x\n", Ldtr);
953  KdbpPrint("IDTR Base 0x%08x Size 0x%04x\n", Idtr.Base, Idtr.Limit);
954  }
955  else if (Argv[0][0] == 's') /* sregs */
956  {
957  KdbpPrint("CS 0x%04x Index 0x%04x %cDT RPL%d\n",
958  Tf->SegCs & 0xffff, (Tf->SegCs & 0xffff) >> 3,
959  (Tf->SegCs & (1 << 2)) ? 'L' : 'G', Tf->SegCs & 3);
960  KdbpPrint("DS 0x%04x Index 0x%04x %cDT RPL%d\n",
961  Tf->SegDs, Tf->SegDs >> 3, (Tf->SegDs & (1 << 2)) ? 'L' : 'G', Tf->SegDs & 3);
962  KdbpPrint("ES 0x%04x Index 0x%04x %cDT RPL%d\n",
963  Tf->SegEs, Tf->SegEs >> 3, (Tf->SegEs & (1 << 2)) ? 'L' : 'G', Tf->SegEs & 3);
964  KdbpPrint("FS 0x%04x Index 0x%04x %cDT RPL%d\n",
965  Tf->SegFs, Tf->SegFs >> 3, (Tf->SegFs & (1 << 2)) ? 'L' : 'G', Tf->SegFs & 3);
966  KdbpPrint("GS 0x%04x Index 0x%04x %cDT RPL%d\n",
967  Tf->SegGs, Tf->SegGs >> 3, (Tf->SegGs & (1 << 2)) ? 'L' : 'G', Tf->SegGs & 3);
968  KdbpPrint("SS 0x%04x Index 0x%04x %cDT RPL%d\n",
969  Tf->SegSs, Tf->SegSs >> 3, (Tf->SegSs & (1 << 2)) ? 'L' : 'G', Tf->SegSs & 3);
970  }
971  else /* dregs */
972  {
973  ASSERT(Argv[0][0] == 'd');
974  KdbpPrint("DR0 0x%08x\n"
975  "DR1 0x%08x\n"
976  "DR2 0x%08x\n"
977  "DR3 0x%08x\n"
978  "DR6 0x%08x\n"
979  "DR7 0x%08x\n",
980  Tf->Dr0, Tf->Dr1, Tf->Dr2, Tf->Dr3,
981  Tf->Dr6, Tf->Dr7);
982  }
983 
984  return TRUE;
985 }
986 
987 static BOOLEAN
989  PCONTEXT TrapFrame)
990 {
991  ULONG_PTR Eip, Ebp;
992  KDESCRIPTOR Gdtr;
993  KGDTENTRY Desc;
994  USHORT Sel;
995  PKTSS Tss;
996 
997  Ke386GetGlobalDescriptorTable(&Gdtr.Limit);
998  Sel = Ke386GetTr();
999 
1000  if ((Sel & (sizeof(KGDTENTRY) - 1)) ||
1001  (Sel < sizeof(KGDTENTRY)) ||
1002  (Sel + sizeof(KGDTENTRY) - 1 > Gdtr.Limit))
1003  return FALSE;
1004 
1005  if (!NT_SUCCESS(KdbpSafeReadMemory(&Desc,
1006  (PVOID)(Gdtr.Base + Sel),
1007  sizeof(KGDTENTRY))))
1008  return FALSE;
1009 
1010  if (Desc.HighWord.Bits.Type != 0xB)
1011  return FALSE;
1012 
1013  Tss = (PKTSS)(ULONG_PTR)(Desc.BaseLow |
1014  Desc.HighWord.Bytes.BaseMid << 16 |
1015  Desc.HighWord.Bytes.BaseHi << 24);
1016 
1017  if (!NT_SUCCESS(KdbpSafeReadMemory(&Sel,
1018  (PVOID)&Tss->Backlink,
1019  sizeof(USHORT))))
1020  return FALSE;
1021 
1022  if ((Sel & (sizeof(KGDTENTRY) - 1)) ||
1023  (Sel < sizeof(KGDTENTRY)) ||
1024  (Sel + sizeof(KGDTENTRY) - 1 > Gdtr.Limit))
1025  return FALSE;
1026 
1027  if (!NT_SUCCESS(KdbpSafeReadMemory(&Desc,
1028  (PVOID)(Gdtr.Base + Sel),
1029  sizeof(KGDTENTRY))))
1030  return FALSE;
1031 
1032  if (Desc.HighWord.Bits.Type != 0xB)
1033  return FALSE;
1034 
1035  Tss = (PKTSS)(ULONG_PTR)(Desc.BaseLow |
1036  Desc.HighWord.Bytes.BaseMid << 16 |
1037  Desc.HighWord.Bytes.BaseHi << 24);
1038 
1039  if (!NT_SUCCESS(KdbpSafeReadMemory(&Eip,
1040  (PVOID)&Tss->Eip,
1041  sizeof(ULONG_PTR))))
1042  return FALSE;
1043 
1044  if (!NT_SUCCESS(KdbpSafeReadMemory(&Ebp,
1045  (PVOID)&Tss->Ebp,
1046  sizeof(ULONG_PTR))))
1047  return FALSE;
1048 
1049  TrapFrame->Eip = Eip;
1050  TrapFrame->Ebp = Ebp;
1051  return TRUE;
1052 }
1053 
1058 
1059 static BOOLEAN
1062 {
1065 }
1066 
1069 static BOOLEAN
1071  ULONG Argc,
1072  PCHAR Argv[])
1073 {
1074  ULONG ul;
1075  ULONGLONG Result = 0;
1078  CONTEXT TrapFrame;
1079 
1080  if (Argc >= 2)
1081  {
1082  /* Check for [L count] part */
1083  ul = 0;
1084 
1085  if (strcmp(Argv[Argc-2], "L") == 0)
1086  {
1087  ul = strtoul(Argv[Argc-1], NULL, 0);
1088  if (ul > 0)
1089  {
1090  Argc -= 2;
1091  }
1092  }
1093  else if (Argv[Argc-1][0] == 'L')
1094  {
1095  ul = strtoul(Argv[Argc-1] + 1, NULL, 0);
1096  if (ul > 0)
1097  {
1098  Argc--;
1099  }
1100  }
1101 
1102  /* Put the remaining arguments back together */
1103  Argc--;
1104  for (ul = 1; ul < Argc; ul++)
1105  {
1106  Argv[ul][strlen(Argv[ul])] = ' ';
1107  }
1108  Argc++;
1109  }
1110 
1111  /* Check if frame addr or thread id is given. */
1112  if (Argc > 1)
1113  {
1114  if (Argv[1][0] == '*')
1115  {
1116  Argv[1]++;
1117 
1118  /* Evaluate the expression */
1119  if (!KdbpEvaluateExpression(Argv[1], sizeof("kdb:> ")-1 + (Argv[1]-Argv[0]), &Result))
1120  return TRUE;
1121 
1122  if (Result > (ULONGLONG)(~((ULONG_PTR)0)))
1123  KdbpPrint("Warning: Address %I64x is beeing truncated\n",Result);
1124 
1125  Frame = (ULONG_PTR)Result;
1126  }
1127  else
1128  {
1129  KdbpPrint("Thread backtrace not supported yet!\n");
1130  return TRUE;
1131  }
1132  }
1133  else
1134  {
1135  KdbpPrint("Eip:\n");
1136 
1137  /* Try printing the function at EIP */
1139  KdbpPrint("<%08x>\n", KdbCurrentTrapFrame->Tf.Eip);
1140  else
1141  KdbpPrint("\n");
1142  }
1143 
1144  TrapFrame = KdbCurrentTrapFrame->Tf;
1145  KdbpPrint("Frames:\n");
1146 
1147  for (;;)
1148  {
1149  BOOLEAN GotNextFrame;
1150 
1151  if (Frame == 0)
1152  break;
1153 
1154  if (!NT_SUCCESS(KdbpSafeReadMemory(&Address, (PVOID)(Frame + sizeof(ULONG_PTR)), sizeof (ULONG_PTR))))
1155  {
1156  KdbpPrint("Couldn't access memory at 0x%p!\n", Frame + sizeof(ULONG_PTR));
1157  break;
1158  }
1159 
1160  if ((GotNextFrame = NT_SUCCESS(KdbpSafeReadMemory(&Frame, (PVOID)Frame, sizeof (ULONG_PTR)))))
1161  TrapFrame.Ebp = Frame;
1162 
1163  /* Print the location of the call instruction */
1164  if (!KdbSymPrintAddress((PVOID)(Address - 5), &TrapFrame))
1165  KdbpPrint("<%08x>\n", Address);
1166  else
1167  KdbpPrint("\n");
1168 
1169  if (KdbOutputAborted) break;
1170 
1171  if (Address == 0)
1172  break;
1173 
1175  {
1176  if ((GotNextFrame = KdbpTrapFrameFromPrevTss(&TrapFrame)))
1177  {
1178  Address = TrapFrame.Eip;
1179  Frame = TrapFrame.Ebp;
1180 
1181  if (!KdbSymPrintAddress((PVOID)Address, &TrapFrame))
1182  KdbpPrint("<%08x>\n", Address);
1183  else
1184  KdbpPrint("\n");
1185  }
1186  }
1187 
1188  if (!GotNextFrame)
1189  {
1190  KdbpPrint("Couldn't access memory at 0x%p!\n", Frame);
1191  break;
1192  }
1193  }
1194 
1195  return TRUE;
1196 }
1197 
1200 static BOOLEAN
1202  ULONG Argc,
1203  PCHAR Argv[])
1204 {
1205  /* Exit the main loop */
1206  return FALSE;
1207 }
1208 
1211 static BOOLEAN
1213  ULONG Argc,
1214  PCHAR Argv[])
1215 {
1216  ULONG Count = 1;
1217 
1218  if (Argc > 1)
1219  {
1220  Count = strtoul(Argv[1], NULL, 0);
1221  if (Count == 0)
1222  {
1223  KdbpPrint("%s: Integer argument required\n", Argv[0]);
1224  return TRUE;
1225  }
1226  }
1227 
1228  if (Argv[0][0] == 'n')
1230  else
1232 
1233  /* Set the number of single steps and return to the interrupted code. */
1235 
1236  return FALSE;
1237 }
1238 
1241 static BOOLEAN
1243  ULONG Argc,
1244  PCHAR Argv[])
1245 {
1246  LONG l;
1247  ULONG_PTR Address = 0;
1249  KDB_ACCESS_TYPE AccessType = 0;
1250  UCHAR Size = 0;
1251  UCHAR DebugReg = 0;
1252  BOOLEAN Enabled = FALSE;
1253  BOOLEAN Global = FALSE;
1255  PCHAR str1, str2, ConditionExpr, GlobalOrLocal;
1256  CHAR Buffer[20];
1257 
1259  if (l < 0)
1260  {
1261  KdbpPrint("No breakpoints.\n");
1262  return TRUE;
1263  }
1264 
1265  KdbpPrint("Breakpoints:\n");
1266  do
1267  {
1268  if (!KdbpGetBreakPointInfo(l, &Address, &Type, &Size, &AccessType, &DebugReg,
1269  &Enabled, &Global, &Process, &ConditionExpr))
1270  {
1271  continue;
1272  }
1273 
1274  if (l == KdbLastBreakPointNr)
1275  {
1276  str1 = "\x1b[1m*";
1277  str2 = "\x1b[0m";
1278  }
1279  else
1280  {
1281  str1 = " ";
1282  str2 = "";
1283  }
1284 
1285  if (Global)
1286  {
1287  GlobalOrLocal = " global";
1288  }
1289  else
1290  {
1291  GlobalOrLocal = Buffer;
1292  sprintf(Buffer, " PID 0x%08lx",
1293  (ULONG)(Process ? Process->UniqueProcessId : INVALID_HANDLE_VALUE));
1294  }
1295 
1297  {
1298  KdbpPrint(" %s%03d BPX 0x%08x%s%s%s%s%s\n",
1299  str1, l, Address,
1300  Enabled ? "" : " disabled",
1301  GlobalOrLocal,
1302  ConditionExpr ? " IF " : "",
1303  ConditionExpr ? ConditionExpr : "",
1304  str2);
1305  }
1306  else if (Type == KdbBreakPointHardware)
1307  {
1308  if (!Enabled)
1309  {
1310  KdbpPrint(" %s%03d BPM 0x%08x %-5s %-5s disabled%s%s%s%s\n", str1, l, Address,
1311  KDB_ACCESS_TYPE_TO_STRING(AccessType),
1312  Size == 1 ? "byte" : (Size == 2 ? "word" : "dword"),
1313  GlobalOrLocal,
1314  ConditionExpr ? " IF " : "",
1315  ConditionExpr ? ConditionExpr : "",
1316  str2);
1317  }
1318  else
1319  {
1320  KdbpPrint(" %s%03d BPM 0x%08x %-5s %-5s DR%d%s%s%s%s\n", str1, l, Address,
1321  KDB_ACCESS_TYPE_TO_STRING(AccessType),
1322  Size == 1 ? "byte" : (Size == 2 ? "word" : "dword"),
1323  DebugReg,
1324  GlobalOrLocal,
1325  ConditionExpr ? " IF " : "",
1326  ConditionExpr ? ConditionExpr : "",
1327  str2);
1328  }
1329  }
1330  }
1331  while ((l = KdbpGetNextBreakPointNr(l+1)) >= 0);
1332 
1333  return TRUE;
1334 }
1335 
1338 static BOOLEAN
1340  ULONG Argc,
1341  PCHAR Argv[])
1342 {
1343  PCHAR pend;
1344  ULONG BreakPointNr;
1345 
1346  if (Argc < 2)
1347  {
1348  KdbpPrint("%s: argument required\n", Argv[0]);
1349  return TRUE;
1350  }
1351 
1352  pend = Argv[1];
1353  BreakPointNr = strtoul(Argv[1], &pend, 0);
1354  if (pend == Argv[1] || *pend != '\0')
1355  {
1356  KdbpPrint("%s: integer argument required\n", Argv[0]);
1357  return TRUE;
1358  }
1359 
1360  if (Argv[0][1] == 'e') /* enable */
1361  {
1362  KdbpEnableBreakPoint(BreakPointNr, NULL);
1363  }
1364  else if (Argv [0][1] == 'd') /* disable */
1365  {
1366  KdbpDisableBreakPoint(BreakPointNr, NULL);
1367  }
1368  else /* clear */
1369  {
1370  ASSERT(Argv[0][1] == 'c');
1371  KdbpDeleteBreakPoint(BreakPointNr, NULL);
1372  }
1373 
1374  return TRUE;
1375 }
1376 
1379 static BOOLEAN
1381 {
1382  ULONGLONG Result = 0;
1385  UCHAR Size = 0;
1386  KDB_ACCESS_TYPE AccessType = 0;
1387  ULONG AddressArgIndex, i;
1388  LONG ConditionArgIndex;
1389  BOOLEAN Global = TRUE;
1390 
1391  if (Argv[0][2] == 'x') /* software breakpoint */
1392  {
1393  if (Argc < 2)
1394  {
1395  KdbpPrint("bpx: Address argument required.\n");
1396  return TRUE;
1397  }
1398 
1399  AddressArgIndex = 1;
1401  }
1402  else /* memory breakpoint */
1403  {
1404  ASSERT(Argv[0][2] == 'm');
1405 
1406  if (Argc < 2)
1407  {
1408  KdbpPrint("bpm: Access type argument required (one of r, w, rw, x)\n");
1409  return TRUE;
1410  }
1411 
1412  if (_stricmp(Argv[1], "x") == 0)
1413  AccessType = KdbAccessExec;
1414  else if (_stricmp(Argv[1], "r") == 0)
1415  AccessType = KdbAccessRead;
1416  else if (_stricmp(Argv[1], "w") == 0)
1417  AccessType = KdbAccessWrite;
1418  else if (_stricmp(Argv[1], "rw") == 0)
1419  AccessType = KdbAccessReadWrite;
1420  else
1421  {
1422  KdbpPrint("bpm: Unknown access type '%s'\n", Argv[1]);
1423  return TRUE;
1424  }
1425 
1426  if (Argc < 3)
1427  {
1428  KdbpPrint("bpm: %s argument required.\n", AccessType == KdbAccessExec ? "Address" : "Memory size");
1429  return TRUE;
1430  }
1431 
1432  AddressArgIndex = 3;
1433  if (_stricmp(Argv[2], "byte") == 0)
1434  Size = 1;
1435  else if (_stricmp(Argv[2], "word") == 0)
1436  Size = 2;
1437  else if (_stricmp(Argv[2], "dword") == 0)
1438  Size = 4;
1439  else if (AccessType == KdbAccessExec)
1440  {
1441  Size = 1;
1442  AddressArgIndex--;
1443  }
1444  else
1445  {
1446  KdbpPrint("bpm: Unknown memory size '%s'\n", Argv[2]);
1447  return TRUE;
1448  }
1449 
1450  if (Argc <= AddressArgIndex)
1451  {
1452  KdbpPrint("bpm: Address argument required.\n");
1453  return TRUE;
1454  }
1455 
1457  }
1458 
1459  /* Put the arguments back together */
1460  ConditionArgIndex = -1;
1461  for (i = AddressArgIndex; i < (Argc-1); i++)
1462  {
1463  if (strcmp(Argv[i+1], "IF") == 0) /* IF found */
1464  {
1465  ConditionArgIndex = i + 2;
1466  if ((ULONG)ConditionArgIndex >= Argc)
1467  {
1468  KdbpPrint("%s: IF requires condition expression.\n", Argv[0]);
1469  return TRUE;
1470  }
1471 
1472  for (i = ConditionArgIndex; i < (Argc-1); i++)
1473  Argv[i][strlen(Argv[i])] = ' ';
1474 
1475  break;
1476  }
1477 
1478  Argv[i][strlen(Argv[i])] = ' ';
1479  }
1480 
1481  /* Evaluate the address expression */
1482  if (!KdbpEvaluateExpression(Argv[AddressArgIndex],
1483  sizeof("kdb:> ")-1 + (Argv[AddressArgIndex]-Argv[0]),
1484  &Result))
1485  {
1486  return TRUE;
1487  }
1488 
1489  if (Result > (ULONGLONG)(~((ULONG_PTR)0)))
1490  KdbpPrint("%s: Warning: Address %I64x is beeing truncated\n", Argv[0],Result);
1491 
1493 
1494  KdbpInsertBreakPoint(Address, Type, Size, AccessType,
1495  (ConditionArgIndex < 0) ? NULL : Argv[ConditionArgIndex],
1496  Global, NULL);
1497 
1498  return TRUE;
1499 }
1500 
1503 static BOOLEAN
1505  ULONG Argc,
1506  PCHAR Argv[])
1507 {
1509  PETHREAD Thread = NULL;
1511  BOOLEAN ReferencedThread = FALSE, ReferencedProcess = FALSE;
1512  PULONG Esp;
1513  PULONG Ebp;
1514  ULONG Eip;
1515  ULONG ul = 0;
1516  PCHAR State, pend, str1, str2;
1517  static const PCHAR ThreadStateToString[DeferredReady+1] =
1518  {
1519  "Initialized", "Ready", "Running",
1520  "Standby", "Terminated", "Waiting",
1521  "Transition", "DeferredReady"
1522  };
1523 
1525 
1526  if (Argc >= 2 && _stricmp(Argv[1], "list") == 0)
1527  {
1529 
1530  if (Argc >= 3)
1531  {
1532  ul = strtoul(Argv[2], &pend, 0);
1533  if (Argv[2] == pend)
1534  {
1535  KdbpPrint("thread: '%s' is not a valid process id!\n", Argv[2]);
1536  return TRUE;
1537  }
1538 
1540  {
1541  KdbpPrint("thread: Invalid process id!\n");
1542  return TRUE;
1543  }
1544 
1545  /* Remember our reference */
1546  ReferencedProcess = TRUE;
1547  }
1548 
1549  Entry = Process->ThreadListHead.Flink;
1550  if (Entry == &Process->ThreadListHead)
1551  {
1552  if (Argc >= 3)
1553  KdbpPrint("No threads in process 0x%08x!\n", ul);
1554  else
1555  KdbpPrint("No threads in current process!\n");
1556 
1557  if (ReferencedProcess)
1559 
1560  return TRUE;
1561  }
1562 
1563  KdbpPrint(" TID State Prior. Affinity EBP EIP\n");
1564  do
1565  {
1566  Thread = CONTAINING_RECORD(Entry, ETHREAD, ThreadListEntry);
1567 
1568  if (Thread == KdbCurrentThread)
1569  {
1570  str1 = "\x1b[1m*";
1571  str2 = "\x1b[0m";
1572  }
1573  else
1574  {
1575  str1 = " ";
1576  str2 = "";
1577  }
1578 
1579  if (!Thread->Tcb.InitialStack)
1580  {
1581  /* Thread has no kernel stack (probably terminated) */
1582  Esp = Ebp = NULL;
1583  Eip = 0;
1584  }
1585  else if (Thread->Tcb.TrapFrame)
1586  {
1588  Esp = (PULONG)Thread->Tcb.TrapFrame->TempEsp;
1589  else
1591 
1592  Ebp = (PULONG)Thread->Tcb.TrapFrame->Ebp;
1593  Eip = Thread->Tcb.TrapFrame->Eip;
1594  }
1595  else
1596  {
1597  Esp = (PULONG)Thread->Tcb.KernelStack;
1598  Ebp = (PULONG)Esp[4];
1599  Eip = 0;
1600 
1601  if (Ebp) /* FIXME: Should we attach to the process to read Ebp[1]? */
1602  KdbpSafeReadMemory(&Eip, Ebp + 1, sizeof (Eip));
1603  }
1604 
1605  if (Thread->Tcb.State < (DeferredReady + 1))
1606  State = ThreadStateToString[Thread->Tcb.State];
1607  else
1608  State = "Unknown";
1609 
1610  KdbpPrint(" %s0x%08x %-11s %3d 0x%08x 0x%08x 0x%08x%s\n",
1611  str1,
1613  State,
1614  Thread->Tcb.Priority,
1615  Thread->Tcb.Affinity,
1616  Ebp,
1617  Eip,
1618  str2);
1619 
1620  Entry = Entry->Flink;
1621  }
1622  while (Entry != &Process->ThreadListHead);
1623 
1624  /* Release our reference, if any */
1625  if (ReferencedProcess)
1627  }
1628  else if (Argc >= 2 && _stricmp(Argv[1], "attach") == 0)
1629  {
1630  if (Argc < 3)
1631  {
1632  KdbpPrint("thread attach: thread id argument required!\n");
1633  return TRUE;
1634  }
1635 
1636  ul = strtoul(Argv[2], &pend, 0);
1637  if (Argv[2] == pend)
1638  {
1639  KdbpPrint("thread attach: '%s' is not a valid thread id!\n", Argv[2]);
1640  return TRUE;
1641  }
1642 
1643  if (!KdbpAttachToThread((PVOID)ul))
1644  {
1645  return TRUE;
1646  }
1647 
1648  KdbpPrint("Attached to thread 0x%08x.\n", ul);
1649  }
1650  else
1651  {
1653 
1654  if (Argc >= 2)
1655  {
1656  ul = strtoul(Argv[1], &pend, 0);
1657  if (Argv[1] == pend)
1658  {
1659  KdbpPrint("thread: '%s' is not a valid thread id!\n", Argv[1]);
1660  return TRUE;
1661  }
1662 
1664  {
1665  KdbpPrint("thread: Invalid thread id!\n");
1666  return TRUE;
1667  }
1668 
1669  /* Remember our reference */
1670  ReferencedThread = TRUE;
1671  }
1672 
1673  if (Thread->Tcb.State < (DeferredReady + 1))
1674  State = ThreadStateToString[Thread->Tcb.State];
1675  else
1676  State = "Unknown";
1677 
1678  KdbpPrint("%s"
1679  " TID: 0x%08x\n"
1680  " State: %s (0x%x)\n"
1681  " Priority: %d\n"
1682  " Affinity: 0x%08x\n"
1683  " Initial Stack: 0x%08x\n"
1684  " Stack Limit: 0x%08x\n"
1685  " Stack Base: 0x%08x\n"
1686  " Kernel Stack: 0x%08x\n"
1687  " Trap Frame: 0x%08x\n"
1688  " NPX State: %s (0x%x)\n",
1689  (Argc < 2) ? "Current Thread:\n" : "",
1691  State, Thread->Tcb.State,
1692  Thread->Tcb.Priority,
1693  Thread->Tcb.Affinity,
1696  Thread->Tcb.StackBase,
1698  Thread->Tcb.TrapFrame,
1700 
1701  /* Release our reference if we had one */
1702  if (ReferencedThread)
1704  }
1705 
1706  return TRUE;
1707 }
1708 
1711 static BOOLEAN
1713  ULONG Argc,
1714  PCHAR Argv[])
1715 {
1718  BOOLEAN ReferencedProcess = FALSE;
1719  PCHAR State, pend, str1, str2;
1720  ULONG ul;
1722 
1723  if (Argc >= 2 && _stricmp(Argv[1], "list") == 0)
1724  {
1726  if (!Entry || Entry == &PsActiveProcessHead)
1727  {
1728  KdbpPrint("No processes in the system!\n");
1729  return TRUE;
1730  }
1731 
1732  KdbpPrint(" PID State Filename\n");
1733  do
1734  {
1735  Process = CONTAINING_RECORD(Entry, EPROCESS, ActiveProcessLinks);
1736 
1737  if (Process == KdbCurrentProcess)
1738  {
1739  str1 = "\x1b[1m*";
1740  str2 = "\x1b[0m";
1741  }
1742  else
1743  {
1744  str1 = " ";
1745  str2 = "";
1746  }
1747 
1748  State = ((Process->Pcb.State == ProcessInMemory) ? "In Memory" :
1749  ((Process->Pcb.State == ProcessOutOfMemory) ? "Out of Memory" : "In Transition"));
1750 
1751  KdbpPrint(" %s0x%08x %-10s %s%s\n",
1752  str1,
1753  Process->UniqueProcessId,
1754  State,
1755  Process->ImageFileName,
1756  str2);
1757 
1758  Entry = Entry->Flink;
1759  }
1760  while(Entry != &PsActiveProcessHead);
1761  }
1762  else if (Argc >= 2 && _stricmp(Argv[1], "attach") == 0)
1763  {
1764  if (Argc < 3)
1765  {
1766  KdbpPrint("process attach: process id argument required!\n");
1767  return TRUE;
1768  }
1769 
1770  ul = strtoul(Argv[2], &pend, 0);
1771  if (Argv[2] == pend)
1772  {
1773  KdbpPrint("process attach: '%s' is not a valid process id!\n", Argv[2]);
1774  return TRUE;
1775  }
1776 
1777  if (!KdbpAttachToProcess((PVOID)ul))
1778  {
1779  return TRUE;
1780  }
1781 
1782  KdbpPrint("Attached to process 0x%08x, thread 0x%08x.\n", (ULONG)ul,
1784  }
1785  else
1786  {
1788 
1789  if (Argc >= 2)
1790  {
1791  ul = strtoul(Argv[1], &pend, 0);
1792  if (Argv[1] == pend)
1793  {
1794  KdbpPrint("proc: '%s' is not a valid process id!\n", Argv[1]);
1795  return TRUE;
1796  }
1797 
1799  {
1800  KdbpPrint("proc: Invalid process id!\n");
1801  return TRUE;
1802  }
1803 
1804  /* Remember our reference */
1805  ReferencedProcess = TRUE;
1806  }
1807 
1808  State = ((Process->Pcb.State == ProcessInMemory) ? "In Memory" :
1809  ((Process->Pcb.State == ProcessOutOfMemory) ? "Out of Memory" : "In Transition"));
1810  KdbpPrint("%s"
1811  " PID: 0x%08x\n"
1812  " State: %s (0x%x)\n"
1813  " Image Filename: %s\n",
1814  (Argc < 2) ? "Current process:\n" : "",
1815  Process->UniqueProcessId,
1816  State, Process->Pcb.State,
1817  Process->ImageFileName);
1818 
1819  /* Release our reference, if any */
1820  if (ReferencedProcess)
1822  }
1823 
1824  return TRUE;
1825 }
1826 
1829 static BOOLEAN
1831  ULONG Argc,
1832  PCHAR Argv[])
1833 {
1834  ULONGLONG Result = 0;
1836  PLDR_DATA_TABLE_ENTRY LdrEntry;
1837  BOOLEAN DisplayOnlyOneModule = FALSE;
1838  INT i = 0;
1839 
1840  if (Argc >= 2)
1841  {
1842  /* Put the arguments back together */
1843  Argc--;
1844  while (--Argc >= 1)
1845  Argv[Argc][strlen(Argv[Argc])] = ' ';
1846 
1847  /* Evaluate the expression */
1848  if (!KdbpEvaluateExpression(Argv[1], sizeof("kdb:> ")-1 + (Argv[1]-Argv[0]), &Result))
1849  {
1850  return TRUE;
1851  }
1852 
1853  if (Result > (ULONGLONG)(~((ULONG_PTR)0)))
1854  KdbpPrint("%s: Warning: Address %I64x is beeing truncated\n", Argv[0],Result);
1855 
1857 
1858  if (!KdbpSymFindModule((PVOID)Address, NULL, -1, &LdrEntry))
1859  {
1860  KdbpPrint("No module containing address 0x%p found!\n", Address);
1861  return TRUE;
1862  }
1863 
1864  DisplayOnlyOneModule = TRUE;
1865  }
1866  else
1867  {
1868  if (!KdbpSymFindModule(NULL, NULL, 0, &LdrEntry))
1869  {
1870  ULONG_PTR ntoskrnlBase = ((ULONG_PTR)KdbpCmdMod) & 0xfff00000;
1871  KdbpPrint(" Base Size Name\n");
1872  KdbpPrint(" %08x %08x %s\n", ntoskrnlBase, 0, "ntoskrnl.exe");
1873  return TRUE;
1874  }
1875 
1876  i = 1;
1877  }
1878 
1879  KdbpPrint(" Base Size Name\n");
1880  for (;;)
1881  {
1882  KdbpPrint(" %08x %08x %wZ\n", LdrEntry->DllBase, LdrEntry->SizeOfImage, &LdrEntry->BaseDllName);
1883 
1884  if(DisplayOnlyOneModule || !KdbpSymFindModule(NULL, NULL, i++, &LdrEntry))
1885  break;
1886  }
1887 
1888  return TRUE;
1889 }
1890 
1893 static BOOLEAN
1895  ULONG Argc,
1896  PCHAR Argv[])
1897 {
1898  KDESCRIPTOR Reg;
1899  ULONG SegDesc[2];
1900  ULONG SegBase;
1901  ULONG SegLimit;
1902  PCHAR SegType;
1903  USHORT SegSel;
1904  UCHAR Type, Dpl;
1905  INT i;
1906  ULONG ul;
1907 
1908  if (Argv[0][0] == 'i')
1909  {
1910  /* Read IDTR */
1911  __sidt(&Reg.Limit);
1912 
1913  if (Reg.Limit < 7)
1914  {
1915  KdbpPrint("Interrupt descriptor table is empty.\n");
1916  return TRUE;
1917  }
1918 
1919  KdbpPrint("IDT Base: 0x%08x Limit: 0x%04x\n", Reg.Base, Reg.Limit);
1920  KdbpPrint(" Idx Type Seg. Sel. Offset DPL\n");
1921 
1922  for (i = 0; (i + sizeof(SegDesc) - 1) <= Reg.Limit; i += 8)
1923  {
1924  if (!NT_SUCCESS(KdbpSafeReadMemory(SegDesc, (PVOID)(Reg.Base + i), sizeof(SegDesc))))
1925  {
1926  KdbpPrint("Couldn't access memory at 0x%08x!\n", Reg.Base + i);
1927  return TRUE;
1928  }
1929 
1930  Dpl = ((SegDesc[1] >> 13) & 3);
1931  if ((SegDesc[1] & 0x1f00) == 0x0500) /* Task gate */
1932  SegType = "TASKGATE";
1933  else if ((SegDesc[1] & 0x1fe0) == 0x0e00) /* 32 bit Interrupt gate */
1934  SegType = "INTGATE32";
1935  else if ((SegDesc[1] & 0x1fe0) == 0x0600) /* 16 bit Interrupt gate */
1936  SegType = "INTGATE16";
1937  else if ((SegDesc[1] & 0x1fe0) == 0x0f00) /* 32 bit Trap gate */
1938  SegType = "TRAPGATE32";
1939  else if ((SegDesc[1] & 0x1fe0) == 0x0700) /* 16 bit Trap gate */
1940  SegType = "TRAPGATE16";
1941  else
1942  SegType = "UNKNOWN";
1943 
1944  if ((SegDesc[1] & (1 << 15)) == 0) /* not present */
1945  {
1946  KdbpPrint(" %03d %-10s [NP] [NP] %02d\n",
1947  i / 8, SegType, Dpl);
1948  }
1949  else if ((SegDesc[1] & 0x1f00) == 0x0500) /* Task gate */
1950  {
1951  SegSel = SegDesc[0] >> 16;
1952  KdbpPrint(" %03d %-10s 0x%04x %02d\n",
1953  i / 8, SegType, SegSel, Dpl);
1954  }
1955  else
1956  {
1957  SegSel = SegDesc[0] >> 16;
1958  SegBase = (SegDesc[1] & 0xffff0000) | (SegDesc[0] & 0x0000ffff);
1959  KdbpPrint(" %03d %-10s 0x%04x 0x%08x %02d\n",
1960  i / 8, SegType, SegSel, SegBase, Dpl);
1961  }
1962  }
1963  }
1964  else
1965  {
1966  ul = 0;
1967 
1968  if (Argv[0][0] == 'g')
1969  {
1970  /* Read GDTR */
1971  Ke386GetGlobalDescriptorTable(&Reg.Limit);
1972  i = 8;
1973  }
1974  else
1975  {
1976  ASSERT(Argv[0][0] == 'l');
1977 
1978  /* Read LDTR */
1979  Reg.Limit = Ke386GetLocalDescriptorTable();
1980  Reg.Base = 0;
1981  i = 0;
1982  ul = 1 << 2;
1983  }
1984 
1985  if (Reg.Limit < 7)
1986  {
1987  KdbpPrint("%s descriptor table is empty.\n",
1988  Argv[0][0] == 'g' ? "Global" : "Local");
1989  return TRUE;
1990  }
1991 
1992  KdbpPrint("%cDT Base: 0x%08x Limit: 0x%04x\n",
1993  Argv[0][0] == 'g' ? 'G' : 'L', Reg.Base, Reg.Limit);
1994  KdbpPrint(" Idx Sel. Type Base Limit DPL Attribs\n");
1995 
1996  for (; (i + sizeof(SegDesc) - 1) <= Reg.Limit; i += 8)
1997  {
1998  if (!NT_SUCCESS(KdbpSafeReadMemory(SegDesc, (PVOID)(Reg.Base + i), sizeof(SegDesc))))
1999  {
2000  KdbpPrint("Couldn't access memory at 0x%08x!\n", Reg.Base + i);
2001  return TRUE;
2002  }
2003 
2004  Dpl = ((SegDesc[1] >> 13) & 3);
2005  Type = ((SegDesc[1] >> 8) & 0xf);
2006 
2007  SegBase = SegDesc[0] >> 16;
2008  SegBase |= (SegDesc[1] & 0xff) << 16;
2009  SegBase |= SegDesc[1] & 0xff000000;
2010  SegLimit = SegDesc[0] & 0x0000ffff;
2011  SegLimit |= (SegDesc[1] >> 16) & 0xf;
2012 
2013  if ((SegDesc[1] & (1 << 23)) != 0)
2014  {
2015  SegLimit *= 4096;
2016  SegLimit += 4095;
2017  }
2018  else
2019  {
2020  SegLimit++;
2021  }
2022 
2023  if ((SegDesc[1] & (1 << 12)) == 0) /* System segment */
2024  {
2025  switch (Type)
2026  {
2027  case 1: SegType = "TSS16(Avl)"; break;
2028  case 2: SegType = "LDT"; break;
2029  case 3: SegType = "TSS16(Busy)"; break;
2030  case 4: SegType = "CALLGATE16"; break;
2031  case 5: SegType = "TASKGATE"; break;
2032  case 6: SegType = "INTGATE16"; break;
2033  case 7: SegType = "TRAPGATE16"; break;
2034  case 9: SegType = "TSS32(Avl)"; break;
2035  case 11: SegType = "TSS32(Busy)"; break;
2036  case 12: SegType = "CALLGATE32"; break;
2037  case 14: SegType = "INTGATE32"; break;
2038  case 15: SegType = "INTGATE32"; break;
2039  default: SegType = "UNKNOWN"; break;
2040  }
2041 
2042  if (!(Type >= 1 && Type <= 3) &&
2043  Type != 9 && Type != 11)
2044  {
2045  SegBase = 0;
2046  SegLimit = 0;
2047  }
2048  }
2049  else if ((SegDesc[1] & (1 << 11)) == 0) /* Data segment */
2050  {
2051  if ((SegDesc[1] & (1 << 22)) != 0)
2052  SegType = "DATA32";
2053  else
2054  SegType = "DATA16";
2055  }
2056  else /* Code segment */
2057  {
2058  if ((SegDesc[1] & (1 << 22)) != 0)
2059  SegType = "CODE32";
2060  else
2061  SegType = "CODE16";
2062  }
2063 
2064  if ((SegDesc[1] & (1 << 15)) == 0) /* not present */
2065  {
2066  KdbpPrint(" %03d 0x%04x %-11s [NP] [NP] %02d NP\n",
2067  i / 8, i | Dpl | ul, SegType, Dpl);
2068  }
2069  else
2070  {
2071  KdbpPrint(" %03d 0x%04x %-11s 0x%08x 0x%08x %02d ",
2072  i / 8, i | Dpl | ul, SegType, SegBase, SegLimit, Dpl);
2073 
2074  if ((SegDesc[1] & (1 << 12)) == 0) /* System segment */
2075  {
2076  /* FIXME: Display system segment */
2077  }
2078  else if ((SegDesc[1] & (1 << 11)) == 0) /* Data segment */
2079  {
2080  if ((SegDesc[1] & (1 << 10)) != 0) /* Expand-down */
2081  KdbpPrint(" E");
2082 
2083  KdbpPrint((SegDesc[1] & (1 << 9)) ? " R/W" : " R");
2084 
2085  if ((SegDesc[1] & (1 << 8)) != 0)
2086  KdbpPrint(" A");
2087  }
2088  else /* Code segment */
2089  {
2090  if ((SegDesc[1] & (1 << 10)) != 0) /* Conforming */
2091  KdbpPrint(" C");
2092 
2093  KdbpPrint((SegDesc[1] & (1 << 9)) ? " R/X" : " X");
2094 
2095  if ((SegDesc[1] & (1 << 8)) != 0)
2096  KdbpPrint(" A");
2097  }
2098 
2099  if ((SegDesc[1] & (1 << 20)) != 0)
2100  KdbpPrint(" AVL");
2101 
2102  KdbpPrint("\n");
2103  }
2104  }
2105  }
2106 
2107  return TRUE;
2108 }
2109 
2112 static BOOLEAN
2114  ULONG Argc,
2115  PCHAR Argv[])
2116 {
2117  PKIPCR Pcr = (PKIPCR)KeGetPcr();
2118 
2119  KdbpPrint("Current PCR is at 0x%08x.\n", (INT)Pcr);
2120  KdbpPrint(" Tib.ExceptionList: 0x%08x\n"
2121  " Tib.StackBase: 0x%08x\n"
2122  " Tib.StackLimit: 0x%08x\n"
2123  " Tib.SubSystemTib: 0x%08x\n"
2124  " Tib.FiberData/Version: 0x%08x\n"
2125  " Tib.ArbitraryUserPointer: 0x%08x\n"
2126  " Tib.Self: 0x%08x\n"
2127  " SelfPcr: 0x%08x\n"
2128  " PCRCB: 0x%08x\n"
2129  " Irql: 0x%02x\n"
2130  " IRR: 0x%08x\n"
2131  " IrrActive: 0x%08x\n"
2132  " IDR: 0x%08x\n"
2133  " KdVersionBlock: 0x%08x\n"
2134  " IDT: 0x%08x\n"
2135  " GDT: 0x%08x\n"
2136  " TSS: 0x%08x\n"
2137  " MajorVersion: 0x%04x\n"
2138  " MinorVersion: 0x%04x\n"
2139  " SetMember: 0x%08x\n"
2140  " StallScaleFactor: 0x%08x\n"
2141  " Number: 0x%02x\n"
2142  " L2CacheAssociativity: 0x%02x\n"
2143  " VdmAlert: 0x%08x\n"
2144  " L2CacheSize: 0x%08x\n"
2145  " InterruptMode: 0x%08x\n",
2146  Pcr->NtTib.ExceptionList, Pcr->NtTib.StackBase, Pcr->NtTib.StackLimit,
2147  Pcr->NtTib.SubSystemTib, Pcr->NtTib.FiberData, Pcr->NtTib.ArbitraryUserPointer,
2148  Pcr->NtTib.Self, Pcr->SelfPcr, Pcr->Prcb, Pcr->Irql, Pcr->IRR, Pcr->IrrActive,
2149  Pcr->IDR, Pcr->KdVersionBlock, Pcr->IDT, Pcr->GDT, Pcr->TSS,
2150  Pcr->MajorVersion, Pcr->MinorVersion, Pcr->SetMember, Pcr->StallScaleFactor,
2151  Pcr->Number, Pcr->SecondLevelCacheAssociativity,
2152  Pcr->VdmAlert, Pcr->SecondLevelCacheSize, Pcr->InterruptMode);
2153 
2154  return TRUE;
2155 }
2156 
2159 static BOOLEAN
2161  ULONG Argc,
2162  PCHAR Argv[])
2163 {
2164  KTSS *Tss = KeGetPcr()->TSS;
2165 
2166  KdbpPrint("Current TSS is at 0x%08x.\n", (INT)Tss);
2167  KdbpPrint(" Eip: 0x%08x\n"
2168  " Es: 0x%04x\n"
2169  " Cs: 0x%04x\n"
2170  " Ss: 0x%04x\n"
2171  " Ds: 0x%04x\n"
2172  " Fs: 0x%04x\n"
2173  " Gs: 0x%04x\n"
2174  " IoMapBase: 0x%04x\n",
2175  Tss->Eip, Tss->Es, Tss->Cs, Tss->Ds, Tss->Fs, Tss->Gs, Tss->IoMapBase);
2176 
2177  return TRUE;
2178 }
2179 
2182 static BOOLEAN
2184  ULONG Argc,
2185  PCHAR Argv[])
2186 {
2187  /* Set the flag and quit looping */
2189 
2190  return FALSE;
2191 }
2192 
2193 static BOOLEAN
2195  ULONG Argc,
2196  PCHAR Argv[])
2197 {
2198  /* Reboot immediately (we do not return) */
2200  return FALSE;
2201 }
2202 
2203 
2204 VOID
2205 KdbpPager(
2206  IN PCHAR Buffer,
2207  IN ULONG BufLength);
2208 
2214 static BOOLEAN
2216  ULONG Argc,
2217  PCHAR Argv[])
2218 {
2219  ULONG beg, end;
2220 
2221  KdbpIsInDmesgMode = TRUE; /* Toggle logging flag */
2222  if (!KdpDmesgBuffer)
2223  {
2224  KdbpPrint("Dmesg: error, buffer is not allocated! /DEBUGPORT=SCREEN kernel param required for dmesg.\n");
2225  return TRUE;
2226  }
2227 
2228  KdbpPrint("*** Dmesg *** TotalWritten=%lu, BufferSize=%lu, CurrentPosition=%lu\n",
2230 
2231  // Pass data to the pager:
2234 
2235  // no roll-overs, and overwritten=lost bytes
2237  {
2238  // show buffer (KdpDmesgBuffer + beg, num)
2240  }
2241  else
2242  {
2243  // show 2 buffers: (KdpDmesgBuffer + beg, KdpDmesgBufferSize - beg)
2244  // and: (KdpDmesgBuffer, end)
2246  KdbpPrint("*** Dmesg: buffer rollup ***\n");
2248  }
2249  KdbpPrint("*** Dmesg: end of output ***\n");
2250 
2251  KdbpIsInDmesgMode = FALSE; /* Toggle logging flag */
2252 
2253  return TRUE;
2254 }
2255 
2258 static BOOLEAN
2260  ULONG Argc,
2261  PCHAR Argv[])
2262 {
2263  LONG l;
2264  BOOLEAN First;
2265  PCHAR pend = 0;
2266  KDB_ENTER_CONDITION ConditionFirst = KdbDoNotEnter;
2267  KDB_ENTER_CONDITION ConditionLast = KdbDoNotEnter;
2268 
2269  static const PCHAR ExceptionNames[21] =
2270  {
2271  "ZERODEVIDE", "DEBUGTRAP", "NMI", "INT3", "OVERFLOW", "BOUND", "INVALIDOP",
2272  "NOMATHCOP", "DOUBLEFAULT", "RESERVED(9)", "INVALIDTSS", "SEGMENTNOTPRESENT",
2273  "STACKFAULT", "GPF", "PAGEFAULT", "RESERVED(15)", "MATHFAULT", "ALIGNMENTCHECK",
2274  "MACHINECHECK", "SIMDFAULT", "OTHERS"
2275  };
2276 
2277  if (Argc == 1)
2278  {
2279  KdbpPrint("Available settings:\n");
2280  KdbpPrint(" syntax [intel|at&t]\n");
2281  KdbpPrint(" condition [exception|*] [first|last] [never|always|kmode|umode]\n");
2282  KdbpPrint(" break_on_module_load [true|false]\n");
2283  }
2284  else if (strcmp(Argv[1], "syntax") == 0)
2285  {
2286  if (Argc == 2)
2287  {
2288  KdbpPrint("syntax = %s\n", KdbUseIntelSyntax ? "intel" : "at&t");
2289  }
2290  else if (Argc >= 3)
2291  {
2292  if (_stricmp(Argv[2], "intel") == 0)
2294  else if (_stricmp(Argv[2], "at&t") == 0)
2296  else
2297  KdbpPrint("Unknown syntax '%s'.\n", Argv[2]);
2298  }
2299  }
2300  else if (strcmp(Argv[1], "condition") == 0)
2301  {
2302  if (Argc == 2)
2303  {
2304  KdbpPrint("Conditions: (First) (Last)\n");
2305  for (l = 0; l < RTL_NUMBER_OF(ExceptionNames) - 1; l++)
2306  {
2307  if (!ExceptionNames[l])
2308  continue;
2309 
2310  if (!KdbpGetEnterCondition(l, TRUE, &ConditionFirst))
2311  ASSERT(0);
2312 
2313  if (!KdbpGetEnterCondition(l, FALSE, &ConditionLast))
2314  ASSERT(0);
2315 
2316  KdbpPrint(" #%02d %-20s %-8s %-8s\n", l, ExceptionNames[l],
2317  KDB_ENTER_CONDITION_TO_STRING(ConditionFirst),
2318  KDB_ENTER_CONDITION_TO_STRING(ConditionLast));
2319  }
2320 
2321  ASSERT(l == (RTL_NUMBER_OF(ExceptionNames) - 1));
2322  KdbpPrint(" %-20s %-8s %-8s\n", ExceptionNames[l],
2323  KDB_ENTER_CONDITION_TO_STRING(ConditionFirst),
2324  KDB_ENTER_CONDITION_TO_STRING(ConditionLast));
2325  }
2326  else
2327  {
2328  if (Argc >= 5 && strcmp(Argv[2], "*") == 0) /* Allow * only when setting condition */
2329  {
2330  l = -1;
2331  }
2332  else
2333  {
2334  l = strtoul(Argv[2], &pend, 0);
2335 
2336  if (Argv[2] == pend)
2337  {
2338  for (l = 0; l < RTL_NUMBER_OF(ExceptionNames); l++)
2339  {
2340  if (!ExceptionNames[l])
2341  continue;
2342 
2343  if (_stricmp(ExceptionNames[l], Argv[2]) == 0)
2344  break;
2345  }
2346  }
2347 
2348  if (l >= RTL_NUMBER_OF(ExceptionNames))
2349  {
2350  KdbpPrint("Unknown exception '%s'.\n", Argv[2]);
2351  return TRUE;
2352  }
2353  }
2354 
2355  if (Argc > 4)
2356  {
2357  if (_stricmp(Argv[3], "first") == 0)
2358  First = TRUE;
2359  else if (_stricmp(Argv[3], "last") == 0)
2360  First = FALSE;
2361  else
2362  {
2363  KdbpPrint("set condition: second argument must be 'first' or 'last'\n");
2364  return TRUE;
2365  }
2366 
2367  if (_stricmp(Argv[4], "never") == 0)
2368  ConditionFirst = KdbDoNotEnter;
2369  else if (_stricmp(Argv[4], "always") == 0)
2370  ConditionFirst = KdbEnterAlways;
2371  else if (_stricmp(Argv[4], "umode") == 0)
2372  ConditionFirst = KdbEnterFromUmode;
2373  else if (_stricmp(Argv[4], "kmode") == 0)
2374  ConditionFirst = KdbEnterFromKmode;
2375  else
2376  {
2377  KdbpPrint("set condition: third argument must be 'never', 'always', 'umode' or 'kmode'\n");
2378  return TRUE;
2379  }
2380 
2381  if (!KdbpSetEnterCondition(l, First, ConditionFirst))
2382  {
2383  if (l >= 0)
2384  KdbpPrint("Couldn't change condition for exception #%02d\n", l);
2385  else
2386  KdbpPrint("Couldn't change condition for all exceptions\n", l);
2387  }
2388  }
2389  else /* Argc >= 3 */
2390  {
2391  if (!KdbpGetEnterCondition(l, TRUE, &ConditionFirst))
2392  ASSERT(0);
2393 
2394  if (!KdbpGetEnterCondition(l, FALSE, &ConditionLast))
2395  ASSERT(0);
2396 
2397  if (l < (RTL_NUMBER_OF(ExceptionNames) - 1))
2398  {
2399  KdbpPrint("Condition for exception #%02d (%s): FirstChance %s LastChance %s\n",
2400  l, ExceptionNames[l],
2401  KDB_ENTER_CONDITION_TO_STRING(ConditionFirst),
2402  KDB_ENTER_CONDITION_TO_STRING(ConditionLast));
2403  }
2404  else
2405  {
2406  KdbpPrint("Condition for all other exceptions: FirstChance %s LastChance %s\n",
2407  KDB_ENTER_CONDITION_TO_STRING(ConditionFirst),
2408  KDB_ENTER_CONDITION_TO_STRING(ConditionLast));
2409  }
2410  }
2411  }
2412  }
2413  else if (strcmp(Argv[1], "break_on_module_load") == 0)
2414  {
2415  if (Argc == 2)
2416  KdbpPrint("break_on_module_load = %s\n", KdbBreakOnModuleLoad ? "enabled" : "disabled");
2417  else if (Argc >= 3)
2418  {
2419  if (_stricmp(Argv[2], "enable") == 0 || _stricmp(Argv[2], "enabled") == 0 || _stricmp(Argv[2], "true") == 0)
2421  else if (_stricmp(Argv[2], "disable") == 0 || _stricmp(Argv[2], "disabled") == 0 || _stricmp(Argv[2], "false") == 0)
2423  else
2424  KdbpPrint("Unknown setting '%s'.\n", Argv[2]);
2425  }
2426  }
2427  else
2428  {
2429  KdbpPrint("Unknown setting '%s'.\n", Argv[1]);
2430  }
2431 
2432  return TRUE;
2433 }
2434 
2437 static BOOLEAN
2439  ULONG Argc,
2440  PCHAR Argv[])
2441 {
2442  ULONG i;
2443 
2444  KdbpPrint("Kernel debugger commands:\n");
2445  for (i = 0; i < RTL_NUMBER_OF(KdbDebuggerCommands); i++)
2446  {
2447  if (!KdbDebuggerCommands[i].Syntax) /* Command group */
2448  {
2449  if (i > 0)
2450  KdbpPrint("\n");
2451 
2452  KdbpPrint("\x1b[7m* %s:\x1b[0m\n", KdbDebuggerCommands[i].Help);
2453  continue;
2454  }
2455 
2456  KdbpPrint(" %-20s - %s\n",
2459  }
2460 
2461  return TRUE;
2462 }
2463 
2473 VOID
2475  IN PCHAR Format,
2476  IN ... OPTIONAL)
2477 {
2478  static CHAR Buffer[4096];
2479  static BOOLEAN TerminalInitialized = FALSE;
2480  static BOOLEAN TerminalConnected = FALSE;
2481  static BOOLEAN TerminalReportsSize = TRUE;
2482  CHAR c = '\0';
2483  PCHAR p, p2;
2484  ULONG Length;
2485  ULONG i, j;
2486  LONG RowsPrintedByTerminal;
2487  ULONG ScanCode;
2488  va_list ap;
2489 
2490  /* Check if the user has aborted output of the current command */
2491  if (KdbOutputAborted)
2492  return;
2493 
2494  /* Initialize the terminal */
2495  if (!TerminalInitialized)
2496  {
2497  DbgPrint("\x1b[7h"); /* Enable linewrap */
2498 
2499  /* Query terminal type */
2500  /*DbgPrint("\x1b[Z");*/
2501  DbgPrint("\x05");
2502 
2503  TerminalInitialized = TRUE;
2504  Length = 0;
2505  KeStallExecutionProcessor(100000);
2506 
2507  for (;;)
2508  {
2509  c = KdbpTryGetCharSerial(5000);
2510  if (c == -1)
2511  break;
2512 
2513  Buffer[Length++] = c;
2514  if (Length >= (sizeof (Buffer) - 1))
2515  break;
2516  }
2517 
2518  Buffer[Length] = '\0';
2519  if (Length > 0)
2520  TerminalConnected = TRUE;
2521  }
2522 
2523  /* Get number of rows and columns in terminal */
2524  if ((KdbNumberOfRowsTerminal < 0) || (KdbNumberOfColsTerminal < 0) ||
2525  (KdbNumberOfRowsPrinted) == 0) /* Refresh terminal size each time when number of rows printed is 0 */
2526  {
2527  if ((KdbDebugState & KD_DEBUG_KDSERIAL) && TerminalConnected && TerminalReportsSize)
2528  {
2529  /* Try to query number of rows from terminal. A reply looks like "\x1b[8;24;80t" */
2530  TerminalReportsSize = FALSE;
2531  KeStallExecutionProcessor(100000);
2532  DbgPrint("\x1b[18t");
2533  c = KdbpTryGetCharSerial(5000);
2534 
2535  if (c == KEY_ESC)
2536  {
2537  c = KdbpTryGetCharSerial(5000);
2538  if (c == '[')
2539  {
2540  Length = 0;
2541 
2542  for (;;)
2543  {
2544  c = KdbpTryGetCharSerial(5000);
2545  if (c == -1)
2546  break;
2547 
2548  Buffer[Length++] = c;
2549  if (isalpha(c) || Length >= (sizeof (Buffer) - 1))
2550  break;
2551  }
2552 
2553  Buffer[Length] = '\0';
2554  if (Buffer[0] == '8' && Buffer[1] == ';')
2555  {
2556  for (i = 2; (i < Length) && (Buffer[i] != ';'); i++);
2557 
2558  if (Buffer[i] == ';')
2559  {
2560  Buffer[i++] = '\0';
2561 
2562  /* Number of rows is now at Buffer + 2 and number of cols at Buffer + i */
2565  TerminalReportsSize = TRUE;
2566  }
2567  }
2568  }
2569  /* Clear further characters */
2570  while ((c = KdbpTryGetCharSerial(5000)) != -1);
2571  }
2572  }
2573 
2574  if (KdbNumberOfRowsTerminal <= 0)
2575  {
2576  /* Set number of rows to the default. */
2577  KdbNumberOfRowsTerminal = 23; //24; //Mna.: 23 for SCREEN debugport
2578  }
2579  else if (KdbNumberOfColsTerminal <= 0)
2580  {
2581  /* Set number of cols to the default. */
2582  KdbNumberOfColsTerminal = 75; //80; //Mna.: 75 for SCREEN debugport
2583  }
2584  }
2585 
2586  /* Get the string */
2587  va_start(ap, Format);
2588  Length = _vsnprintf(Buffer, sizeof (Buffer) - 1, Format, ap);
2589  Buffer[Length] = '\0';
2590  va_end(ap);
2591 
2592  p = Buffer;
2593  while (p[0] != '\0')
2594  {
2595  i = strcspn(p, "\n");
2596 
2597  /* Calculate the number of lines which will be printed in the terminal
2598  * when outputting the current line
2599  */
2600  if (i > 0)
2601  RowsPrintedByTerminal = (i + KdbNumberOfColsPrinted - 1) / KdbNumberOfColsTerminal;
2602  else
2603  RowsPrintedByTerminal = 0;
2604 
2605  if (p[i] == '\n')
2606  RowsPrintedByTerminal++;
2607 
2608  /*DbgPrint("!%d!%d!%d!%d!", KdbNumberOfRowsPrinted, KdbNumberOfColsPrinted, i, RowsPrintedByTerminal);*/
2609 
2610  /* Display a prompt if we printed one screen full of text */
2611  if (KdbNumberOfRowsTerminal > 0 &&
2612  (LONG)(KdbNumberOfRowsPrinted + RowsPrintedByTerminal) >= KdbNumberOfRowsTerminal)
2613  {
2615 
2616  if (KdbNumberOfColsPrinted > 0)
2617  DbgPrint("\n");
2618 
2619  DbgPrint("--- Press q to abort, any other key to continue ---");
2620  RowsPrintedByTerminal++; /* added by Mna. */
2621 
2623  c = KdbpGetCharSerial();
2624  else
2626 
2627  if (c == '\r')
2628  {
2629  /* Try to read '\n' which might follow '\r' - if \n is not received here
2630  * it will be interpreted as "return" when the next command should be read.
2631  */
2633  c = KdbpTryGetCharSerial(5);
2634  else
2636  }
2637 
2638  DbgPrint("\n");
2639  if (c == 'q')
2640  {
2642  return;
2643  }
2644 
2647  }
2648 
2649  /* Insert a NUL after the line and print only the current line. */
2650  if (p[i] == '\n' && p[i + 1] != '\0')
2651  {
2652  c = p[i + 1];
2653  p[i + 1] = '\0';
2654  }
2655  else
2656  {
2657  c = '\0';
2658  }
2659 
2660  /* Remove escape sequences from the line if there's no terminal connected */
2661  if (!TerminalConnected)
2662  {
2663  while ((p2 = strrchr(p, '\x1b'))) /* Look for escape character */
2664  {
2665  if (p2[1] == '[')
2666  {
2667  j = 2;
2668  while (!isalpha(p2[j++]));
2669  strcpy(p2, p2 + j);
2670  }
2671  else
2672  {
2673  strcpy(p2, p2 + 1);
2674  }
2675  }
2676  }
2677 
2678  DbgPrint("%s", p);
2679 
2680  if (c != '\0')
2681  p[i + 1] = c;
2682 
2683  /* Set p to the start of the next line and
2684  * remember the number of rows/cols printed
2685  */
2686  p += i;
2687  if (p[0] == '\n')
2688  {
2689  p++;
2691  }
2692  else
2693  {
2694  ASSERT(p[0] == '\0');
2696  }
2697 
2698  KdbNumberOfRowsPrinted += RowsPrintedByTerminal;
2699  }
2700 }
2701 
2703 /*
2704  * Reverse memchr()
2705  * Find the last occurrence of 'c' in the buffer 's' of size 'n'.
2706  */
2707 void *
2708 memrchr(const void *s, int c, size_t n)
2709 {
2710  const unsigned char *cp;
2711 
2712  if (n != 0)
2713  {
2714  cp = (unsigned char *)s + n;
2715  do
2716  {
2717  if (*(--cp) == (unsigned char)c)
2718  return (void *)cp;
2719  } while (--n != 0);
2720  }
2721  return NULL;
2722 }
2723 
2735 PCHAR
2736 CountOnePageUp(PCHAR Buffer, ULONG BufLength, PCHAR pCurPos)
2737 {
2738  PCHAR p;
2739  // p0 is initial guess of Page Start
2741  PCHAR p0 = pCurPos - p0len;
2742  PCHAR prev_p = p0, p1;
2743  ULONG j;
2744 
2745  if (pCurPos < Buffer)
2746  pCurPos = Buffer;
2747  ASSERT(pCurPos <= Buffer + BufLength);
2748 
2749  p = memrchr(p0, '\n', p0len);
2750  if (NULL == p)
2751  p = p0;
2752  for (j = KdbNumberOfRowsTerminal; j--; )
2753  {
2754  int linesCnt;
2755  p1 = memrchr(p0, '\n', p-p0);
2756  prev_p = p;
2757  p = p1;
2758  if (NULL == p)
2759  {
2760  p = prev_p;
2761  if (NULL == p)
2762  p = p0;
2763  break;
2764  }
2765  linesCnt = (KdbNumberOfColsTerminal+prev_p-p-2) / KdbNumberOfColsTerminal;
2766  if (linesCnt > 1)
2767  j -= linesCnt-1;
2768  }
2769 
2770  ASSERT(p != 0);
2771  ++p;
2772  return p;
2773 }
2774 
2787 VOID
2789  IN PCHAR Buffer,
2790  IN ULONG BufLength)
2791 {
2792  static CHAR InBuffer[4096];
2793  static BOOLEAN TerminalInitialized = FALSE;
2794  static BOOLEAN TerminalConnected = FALSE;
2795  static BOOLEAN TerminalReportsSize = TRUE;
2796  CHAR c = '\0';
2797  PCHAR p, p2;
2798  ULONG Length;
2799  ULONG i, j;
2800  LONG RowsPrintedByTerminal;
2801  ULONG ScanCode;
2802 
2803  if( BufLength == 0)
2804  return;
2805 
2806  /* Check if the user has aborted output of the current command */
2807  if (KdbOutputAborted)
2808  return;
2809 
2810  /* Initialize the terminal */
2811  if (!TerminalInitialized)
2812  {
2813  DbgPrint("\x1b[7h"); /* Enable linewrap */
2814 
2815  /* Query terminal type */
2816  /*DbgPrint("\x1b[Z");*/
2817  DbgPrint("\x05");
2818 
2819  TerminalInitialized = TRUE;
2820  Length = 0;
2821  KeStallExecutionProcessor(100000);
2822 
2823  for (;;)
2824  {
2825  c = KdbpTryGetCharSerial(5000);
2826  if (c == -1)
2827  break;
2828 
2829  InBuffer[Length++] = c;
2830  if (Length >= (sizeof (InBuffer) - 1))
2831  break;
2832  }
2833 
2834  InBuffer[Length] = '\0';
2835  if (Length > 0)
2836  TerminalConnected = TRUE;
2837  }
2838 
2839  /* Get number of rows and columns in terminal */
2840  if ((KdbNumberOfRowsTerminal < 0) || (KdbNumberOfColsTerminal < 0) ||
2841  (KdbNumberOfRowsPrinted) == 0) /* Refresh terminal size each time when number of rows printed is 0 */
2842  {
2843  if ((KdbDebugState & KD_DEBUG_KDSERIAL) && TerminalConnected && TerminalReportsSize)
2844  {
2845  /* Try to query number of rows from terminal. A reply looks like "\x1b[8;24;80t" */
2846  TerminalReportsSize = FALSE;
2847  KeStallExecutionProcessor(100000);
2848  DbgPrint("\x1b[18t");
2849  c = KdbpTryGetCharSerial(5000);
2850 
2851  if (c == KEY_ESC)
2852  {
2853  c = KdbpTryGetCharSerial(5000);
2854  if (c == '[')
2855  {
2856  Length = 0;
2857 
2858  for (;;)
2859  {
2860  c = KdbpTryGetCharSerial(5000);
2861  if (c == -1)
2862  break;
2863 
2864  InBuffer[Length++] = c;
2865  if (isalpha(c) || Length >= (sizeof (InBuffer) - 1))
2866  break;
2867  }
2868 
2869  InBuffer[Length] = '\0';
2870  if (InBuffer[0] == '8' && InBuffer[1] == ';')
2871  {
2872  for (i = 2; (i < Length) && (InBuffer[i] != ';'); i++);
2873 
2874  if (Buffer[i] == ';')
2875  {
2876  Buffer[i++] = '\0';
2877 
2878  /* Number of rows is now at Buffer + 2 and number of cols at Buffer + i */
2879  KdbNumberOfRowsTerminal = strtoul(InBuffer + 2, NULL, 0);
2880  KdbNumberOfColsTerminal = strtoul(InBuffer + i, NULL, 0);
2881  TerminalReportsSize = TRUE;
2882  }
2883  }
2884  }
2885  /* Clear further characters */
2886  while ((c = KdbpTryGetCharSerial(5000)) != -1);
2887  }
2888  }
2889 
2890  if (KdbNumberOfRowsTerminal <= 0)
2891  {
2892  /* Set number of rows to the default. */
2894  }
2895  else if (KdbNumberOfColsTerminal <= 0)
2896  {
2897  /* Set number of cols to the default. */
2899  }
2900  }
2901 
2902  /* Get the string */
2903  p = Buffer;
2904 
2905  while (p[0] != '\0')
2906  {
2907  if ( p > Buffer+BufLength)
2908  {
2909  DbgPrint("Dmesg: error, p > Buffer+BufLength,d=%d", p - (Buffer+BufLength));
2910  return;
2911  }
2912  i = strcspn(p, "\n");
2913 
2914  // Are we out of buffer?
2915  if (p + i > Buffer + BufLength)
2916  // Leaving pager function:
2917  break;
2918 
2919  /* Calculate the number of lines which will be printed in the terminal
2920  * when outputting the current line
2921  */
2922  if (i > 0)
2923  RowsPrintedByTerminal = (i + KdbNumberOfColsPrinted - 1) / KdbNumberOfColsTerminal;
2924  else
2925  RowsPrintedByTerminal = 0;
2926 
2927  if (p[i] == '\n')
2928  RowsPrintedByTerminal++;
2929 
2930  /*DbgPrint("!%d!%d!%d!%d!", KdbNumberOfRowsPrinted, KdbNumberOfColsPrinted, i, RowsPrintedByTerminal);*/
2931 
2932  /* Display a prompt if we printed one screen full of text */
2933  if (KdbNumberOfRowsTerminal > 0 &&
2934  (LONG)(KdbNumberOfRowsPrinted + RowsPrintedByTerminal) >= KdbNumberOfRowsTerminal)
2935  {
2937 
2938  if (KdbNumberOfColsPrinted > 0)
2939  DbgPrint("\n");
2940 
2941  DbgPrint("--- Press q to abort, e/End,h/Home,u/PgUp, other key/PgDn ---");
2942  RowsPrintedByTerminal++;
2943 
2945  c = KdbpGetCharSerial();
2946  else
2948 
2949  if (c == '\r')
2950  {
2951  /* Try to read '\n' which might follow '\r' - if \n is not received here
2952  * it will be interpreted as "return" when the next command should be read.
2953  */
2955  c = KdbpTryGetCharSerial(5);
2956  else
2958  }
2959 
2960  //DbgPrint("\n"); //Consize version: don't show pressed key
2961  DbgPrint(" '%c'/scan=%04x\n", c, ScanCode); // Shows pressed key
2962 
2963  if (c == 'q')
2964  {
2966  return;
2967  }
2968  if ( ScanCode == KEYSC_END || c=='e')
2969  {
2970  PCHAR pBufEnd = Buffer + BufLength;
2971  p = CountOnePageUp(Buffer, BufLength, pBufEnd);
2972  i = strcspn(p, "\n");
2973  }
2974  else if (ScanCode == KEYSC_PAGEUP || c=='u')
2975  {
2976  p = CountOnePageUp(Buffer, BufLength, p);
2977  i = strcspn(p, "\n");
2978  }
2979  else if (ScanCode == KEYSC_HOME || c=='h')
2980  {
2981  p = Buffer;
2982  i = strcspn(p, "\n");
2983  }
2984  else if (ScanCode == KEYSC_ARROWUP)
2985  {
2986  p = CountOnePageUp(Buffer, BufLength, p);
2987  i = strcspn(p, "\n");
2988  }
2989 
2992  }
2993 
2994  /* Insert a NUL after the line and print only the current line. */
2995  if (p[i] == '\n' && p[i + 1] != '\0')
2996  {
2997  c = p[i + 1];
2998  p[i + 1] = '\0';
2999  }
3000  else
3001  {
3002  c = '\0';
3003  }
3004 
3005  /* Remove escape sequences from the line if there's no terminal connected */
3006  if (!TerminalConnected)
3007  {
3008  while ((p2 = strrchr(p, '\x1b'))) /* Look for escape character */
3009  {
3010  if (p2[1] == '[')
3011  {
3012  j = 2;
3013  while (!isalpha(p2[j++]));
3014  strcpy(p2, p2 + j);
3015  }
3016  else
3017  {
3018  strcpy(p2, p2 + 1);
3019  }
3020  }
3021  }
3022 
3023  // The main printing of the current line:
3024  DbgPrint(p);
3025 
3026  // restore not null char with saved:
3027  if (c != '\0')
3028  p[i + 1] = c;
3029 
3030  /* Set p to the start of the next line and
3031  * remember the number of rows/cols printed
3032  */
3033  p += i;
3034  if (p[0] == '\n')
3035  {
3036  p++;
3038  }
3039  else
3040  {
3041  ASSERT(p[0] == '\0');
3043  }
3044 
3045  KdbNumberOfRowsPrinted += RowsPrintedByTerminal;
3046  }
3047 }
3048 
3053 static VOID
3055  IN PCHAR Command)
3056 {
3057  ULONG Length1 = strlen(Command) + 1;
3058  ULONG Length2 = 0;
3059  INT i;
3060  PCHAR Buffer;
3061 
3063 
3064  if (Length1 <= 1 ||
3067  {
3068  return;
3069  }
3070 
3071  /* Calculate Length1 and Length2 */
3075  {
3078  Length1 -= Length2;
3079  }
3080 
3081  /* Remove previous commands until there is enough space to append the new command */
3083  {
3084  if ((Length2 > 0 &&
3085  (KdbCommandHistory[i] >= Buffer ||
3087  (Length2 <= 0 &&
3088  (KdbCommandHistory[i] >= Buffer &&
3090  {
3092  }
3093 
3094  i--;
3095  if (i < 0)
3097 
3098  if (i == KdbCommandHistoryIndex)
3099  break;
3100  }
3101 
3102  /* Make sure the new command history entry is free */
3106  {
3108  }
3109 
3110  /* Append command */
3114  if (Length2 > 0)
3115  {
3117  }
3118 }
3119 
3127 static VOID
3129  OUT PCHAR Buffer,
3130  IN ULONG Size)
3131 {
3132  CHAR Key;
3133  PCHAR Orig = Buffer;
3134  ULONG ScanCode = 0;
3135  BOOLEAN EchoOn;
3136  static CHAR LastCommand[1024];
3137  static CHAR NextKey = '\0';
3138  INT CmdHistIndex = -1;
3139  INT i;
3140 
3141  EchoOn = !((KdbDebugState & KD_DEBUG_KDNOECHO) != 0);
3142 
3143  for (;;)
3144  {
3146  {
3147  Key = (NextKey == '\0') ? KdbpGetCharSerial() : NextKey;
3148  NextKey = '\0';
3149  ScanCode = 0;
3150  if (Key == KEY_ESC) /* ESC */
3151  {
3152  Key = KdbpGetCharSerial();
3153  if (Key == '[')
3154  {
3155  Key = KdbpGetCharSerial();
3156 
3157  switch (Key)
3158  {
3159  case 'A':
3161  break;
3162  case 'B':
3164  break;
3165  case 'C':
3166  break;
3167  case 'D':
3168  break;
3169  }
3170  }
3171  }
3172  }
3173  else
3174  {
3175  ScanCode = 0;
3176  Key = (NextKey == '\0') ? KdbpGetCharKeyboard(&ScanCode) : NextKey;
3177  NextKey = '\0';
3178  }
3179 
3180  if ((ULONG)(Buffer - Orig) >= (Size - 1))
3181  {
3182  /* Buffer is full, accept only newlines */
3183  if (Key != '\n')
3184  continue;
3185  }
3186 
3187  if (Key == '\r')
3188  {
3189  /* Read the next char - this is to throw away a \n which most clients should
3190  * send after \r.
3191  */
3192  KeStallExecutionProcessor(100000);
3193 
3195  NextKey = KdbpTryGetCharSerial(5);
3196  else
3197  NextKey = KdbpTryGetCharKeyboard(&ScanCode, 5);
3198 
3199  if (NextKey == '\n' || NextKey == -1) /* \n or no response at all */
3200  NextKey = '\0';
3201 
3202  KdbpPrint("\n");
3203 
3204  /*
3205  * Repeat the last command if the user presses enter. Reduces the
3206  * risk of RSI when single-stepping.
3207  */
3208  if (Buffer != Orig)
3209  {
3211  *Buffer = '\0';
3212  RtlStringCbCopyA(LastCommand, sizeof(LastCommand), Orig);
3213  }
3214  else if (KdbRepeatLastCommand)
3215  RtlStringCbCopyA(Buffer, Size, LastCommand);
3216  else
3217  *Buffer = '\0';
3218 
3219  return;
3220  }
3221  else if (Key == KEY_BS || Key == KEY_DEL)
3222  {
3223  if (Buffer > Orig)
3224  {
3225  Buffer--;
3226  *Buffer = 0;
3227 
3228  if (EchoOn)
3229  KdbpPrint("%c %c", KEY_BS, KEY_BS);
3230  else
3231  KdbpPrint(" %c", KEY_BS);
3232  }
3233  }
3234  else if (ScanCode == KEY_SCAN_UP)
3235  {
3236  BOOLEAN Print = TRUE;
3237 
3238  if (CmdHistIndex < 0)
3239  {
3240  CmdHistIndex = KdbCommandHistoryIndex;
3241  }
3242  else
3243  {
3244  i = CmdHistIndex - 1;
3245 
3246  if (i < 0)
3247  CmdHistIndex = RTL_NUMBER_OF(KdbCommandHistory) - 1;
3248 
3250  CmdHistIndex = i;
3251  else
3252  Print = FALSE;
3253  }
3254 
3255  if (Print && KdbCommandHistory[CmdHistIndex])
3256  {
3257  while (Buffer > Orig)
3258  {
3259  Buffer--;
3260  *Buffer = 0;
3261 
3262  if (EchoOn)
3263  KdbpPrint("%c %c", KEY_BS, KEY_BS);
3264  else
3265  KdbpPrint(" %c", KEY_BS);
3266  }
3267 
3268  i = min(strlen(KdbCommandHistory[CmdHistIndex]), Size - 1);
3269  memcpy(Orig, KdbCommandHistory[CmdHistIndex], i);
3270  Orig[i] = '\0';
3271  Buffer = Orig + i;
3272  KdbpPrint("%s", Orig);
3273  }
3274  }
3275  else if (ScanCode == KEY_SCAN_DOWN)
3276  {
3277  if (CmdHistIndex > 0 && CmdHistIndex != KdbCommandHistoryIndex)
3278  {
3279  i = CmdHistIndex + 1;
3281  i = 0;
3282 
3283  if (KdbCommandHistory[i])
3284  {
3285  CmdHistIndex = i;
3286  while (Buffer > Orig)
3287  {
3288  Buffer--;
3289  *Buffer = 0;
3290 
3291  if (EchoOn)
3292  KdbpPrint("%c %c", KEY_BS, KEY_BS);
3293  else
3294  KdbpPrint(" %c", KEY_BS);
3295  }
3296 
3297  i = min(strlen(KdbCommandHistory[CmdHistIndex]), Size - 1);
3298  memcpy(Orig, KdbCommandHistory[CmdHistIndex], i);
3299  Orig[i] = '\0';
3300  Buffer = Orig + i;
3301  KdbpPrint("%s", Orig);
3302  }
3303  }
3304  }
3305  else
3306  {
3307  if (EchoOn)
3308  KdbpPrint("%c", Key);
3309 
3310  *Buffer = Key;
3311  Buffer++;
3312  }
3313  }
3314 }
3315 
3316 
3317 BOOLEAN
3318 NTAPI
3320  PVOID Callback,
3321  BOOLEAN Deregister)
3322 {
3323  ULONG i;
3324 
3325  /* Loop all entries */
3326  for (i = 0; i < _countof(KdbCliCallbacks); i++)
3327  {
3328  /* Check if deregistering was requested */
3329  if (Deregister)
3330  {
3331  /* Check if this entry is the one that was registered */
3332  if (KdbCliCallbacks[i] == Callback)
3333  {
3334  /* Delete it and report success */
3335  KdbCliCallbacks[i] = NULL;
3336  return TRUE;
3337  }
3338  }
3339  else
3340  {
3341  /* Check if this entry is free */
3342  if (KdbCliCallbacks[i] == NULL)
3343  {
3344  /* Set it and and report success */
3346  return TRUE;
3347  }
3348  }
3349  }
3350 
3351  /* Unsuccessful */
3352  return FALSE;
3353 }
3354 
3364 static
3365 BOOLEAN
3367  IN PCHAR Command,
3368  IN ULONG Argc,
3369  IN PCH Argv[])
3370 {
3371  ULONG i;
3372 
3373  /* Loop all entries */
3374  for (i = 0; i < _countof(KdbCliCallbacks); i++)
3375  {
3376  /* Check if this entry is registered */
3377  if (KdbCliCallbacks[i])
3378  {
3379  /* Invoke the callback and check if it handled the command */
3380  if (KdbCliCallbacks[i](Command, Argc, Argv))
3381  {
3382  return TRUE;
3383  }
3384  }
3385  }
3386 
3387  /* None of the callbacks handled the command */
3388  return FALSE;
3389 }
3390 
3391 
3399 static BOOLEAN
3401  IN PCHAR Command)
3402 {
3403  ULONG i;
3404  PCHAR p;
3405  ULONG Argc;
3406  // FIXME: for what do we need a 1024 characters command line and 256 tokens?
3407  static PCH Argv[256];
3408  static CHAR OrigCommand[1024];
3409 
3410  RtlStringCbCopyA(OrigCommand, sizeof(OrigCommand), Command);
3411 
3412  Argc = 0;
3413  p = Command;
3414 
3415  for (;;)
3416  {
3417  while (*p == '\t' || *p == ' ')
3418  p++;
3419 
3420  if (*p == '\0')
3421  break;
3422 
3423  i = strcspn(p, "\t ");
3424  Argv[Argc++] = p;
3425  p += i;
3426  if (*p == '\0')
3427  break;
3428 
3429  *p = '\0';
3430  p++;
3431  }
3432 
3433  if (Argc < 1)
3434  return TRUE;
3435 
3436  for (i = 0; i < RTL_NUMBER_OF(KdbDebuggerCommands); i++)
3437  {
3438  if (!KdbDebuggerCommands[i].Name)
3439  continue;
3440 
3441  if (strcmp(KdbDebuggerCommands[i].Name, Argv[0]) == 0)
3442  {
3443  return KdbDebuggerCommands[i].Fn(Argc, Argv);
3444  }
3445  }
3446 
3447  /* Now invoke the registered callbacks */
3448  if (KdbpInvokeCliCallbacks(Command, Argc, Argv))
3449  {
3450  return TRUE;
3451  }
3452 
3453  KdbpPrint("Command '%s' is unknown.\n", OrigCommand);
3454  return TRUE;
3455 }
3456 
3461 VOID
3463  IN BOOLEAN EnteredOnSingleStep)
3464 {
3465  static CHAR Command[1024];
3466  BOOLEAN Continue;
3467 
3468  if (EnteredOnSingleStep)
3469  {
3471  {
3472  KdbpPrint("<%x>", KdbCurrentTrapFrame->Tf.Eip);
3473  }
3474 
3475  KdbpPrint(": ");
3477  {
3478  KdbpPrint("<INVALID>");
3479  }
3480  KdbpPrint("\n");
3481  }
3482 
3483  /* Flush the input buffer */
3485  {
3486  while (KdbpTryGetCharSerial(1) != -1);
3487  }
3488  else
3489  {
3490  ULONG ScanCode;
3491  while (KdbpTryGetCharKeyboard(&ScanCode, 1) != -1);
3492  }
3493 
3494  /* Main loop */
3495  do
3496  {
3497  /* Reset the number of rows/cols printed */
3499 
3500  /* Print the prompt */
3501  KdbpPrint("kdb:> ");
3502 
3503  /* Read a command and remember it */
3504  KdbpReadCommand(Command, sizeof (Command));
3506 
3507  /* Reset the number of rows/cols printed and output aborted state */
3510 
3511  /* Call the command */
3514  }
3515  while (Continue);
3516 }
3517 
3522 VOID
3525 {
3526  if (!KdbBreakOnModuleLoad)
3527  return;
3528 
3529  KdbpPrint("Module %wZ loaded.\n", Name);
3531 }
3532 
3539 VOID
3541 {
3542  PCHAR p1, p2;
3543  INT i;
3544  CHAR c;
3545 
3546  /* Execute the commands in the init file */
3547  DPRINT("KDB: Executing KDBinit file...\n");
3548  p1 = KdbInitFileBuffer;
3549  while (p1[0] != '\0')
3550  {
3551  i = strcspn(p1, "\r\n");
3552  if (i > 0)
3553  {
3554  c = p1[i];
3555  p1[i] = '\0';
3556 
3557  /* Look for "break" command and comments */
3558  p2 = p1;
3559 
3560  while (isspace(p2[0]))
3561  p2++;
3562 
3563  if (strncmp(p2, "break", sizeof("break")-1) == 0 &&
3564  (p2[sizeof("break")-1] == '\0' || isspace(p2[sizeof("break")-1])))
3565  {
3566  /* break into the debugger */
3568  }
3569  else if (p2[0] != '#' && p2[0] != '\0') /* Ignore empty lines and comments */
3570  {
3571  KdbpDoCommand(p1);
3572  }
3573 
3574  p1[i] = c;
3575  }
3576 
3577  p1 += i;
3578  while (p1[0] == '\r' || p1[0] == '\n')
3579  p1++;
3580  }
3581  DPRINT("KDB: KDBinit executed\n");
3582 }
3583 
3588 VOID
3590 {
3591  NTSTATUS Status;
3595  FILE_STANDARD_INFORMATION FileStdInfo;
3596  HANDLE hFile = NULL;
3597  INT FileSize;
3598  PCHAR FileBuffer;
3599  ULONG OldEflags;
3600 
3601  /* Initialize the object attributes */
3602  RtlInitUnicodeString(&FileName, L"\\SystemRoot\\System32\\drivers\\etc\\KDBinit");
3604 
3605  /* Open the file */
3607  &ObjectAttributes, &Iosb, 0,
3610  if (!NT_SUCCESS(Status))
3611  {
3612  DPRINT("Could not open \\SystemRoot\\System32\\drivers\\etc\\KDBinit (Status 0x%x)", Status);
3613  return;
3614  }
3615 
3616  /* Get the size of the file */
3617  Status = ZwQueryInformationFile(hFile, &Iosb, &FileStdInfo, sizeof (FileStdInfo),
3619  if (!NT_SUCCESS(Status))
3620  {
3621  ZwClose(hFile);
3622  DPRINT("Could not query size of \\SystemRoot\\System32\\drivers\\etc\\KDBinit (Status 0x%x)", Status);
3623  return;
3624  }
3625  FileSize = FileStdInfo.EndOfFile.u.LowPart;
3626 
3627  /* Allocate memory for the file */
3628  FileBuffer = ExAllocatePool(PagedPool, FileSize + 1); /* add 1 byte for terminating '\0' */
3629  if (!FileBuffer)
3630  {
3631  ZwClose(hFile);
3632  DPRINT("Could not allocate %d bytes for KDBinit file\n", FileSize);
3633  return;
3634  }
3635 
3636  /* Load file into memory */
3637  Status = ZwReadFile(hFile, NULL, NULL, NULL, &Iosb, FileBuffer, FileSize, NULL, NULL);
3638  ZwClose(hFile);
3639 
3641  {
3642  ExFreePool(FileBuffer);
3643  DPRINT("Could not read KDBinit file into memory (Status 0x%lx)\n", Status);
3644  return;
3645  }
3646 
3647  FileSize = min(FileSize, (INT)Iosb.Information);
3648  FileBuffer[FileSize] = '\0';
3649 
3650  /* Enter critical section */
3651  OldEflags = __readeflags();
3652  _disable();
3653 
3654  /* Interpret the init file... */
3655  KdbInitFileBuffer = FileBuffer;
3656  KdbEnter();
3658 
3659  /* Leave critical section */
3660  __writeeflags(OldEflags);
3661 
3662  ExFreePool(FileBuffer);
3663 }
3664 
3665 VOID
3666 NTAPI
3668  LPSTR Message,
3669  ULONG Length
3670 );
3671 
3674 
3675 USHORT
3676 NTAPI
3678  _In_reads_bytes_(InStringLength) PCHAR UnsafeInString,
3679  _In_ USHORT InStringLength,
3680  _Out_writes_bytes_(OutStringLength) PCHAR UnsafeOutString,
3681  _In_ USHORT OutStringLength,
3683  _In_ PKTRAP_FRAME TrapFrame,
3684  _In_ PKEXCEPTION_FRAME ExceptionFrame)
3685 {
3686  USHORT i;
3687  CHAR Response;
3688  ULONG DummyScanCode;
3689  KIRQL OldIrql;
3690  PCHAR InString;
3691  PCHAR OutString;
3692  CHAR InStringBuffer[512];
3693  CHAR OutStringBuffer[512];
3694 
3695  /* Normalize the lengths */
3696  InStringLength = min(InStringLength,
3697  sizeof(InStringBuffer));
3698  OutStringLength = min(OutStringLength,
3699  sizeof(OutStringBuffer));
3700 
3701  /* Check if we need to verify the string */
3702  if (PreviousMode != KernelMode)
3703  {
3704  /* Handle user-mode buffers safely */
3705  _SEH2_TRY
3706  {
3707  /* Probe the prompt */
3708  ProbeForRead(UnsafeInString,
3709  InStringLength,
3710  1);
3711 
3712  /* Capture prompt */
3713  InString = InStringBuffer;
3714  RtlCopyMemory(InString,
3715  UnsafeInString,
3716  InStringLength);
3717 
3718  /* Probe and make room for response */
3719  ProbeForWrite(UnsafeOutString,
3720  OutStringLength,
3721  1);
3722  OutString = OutStringBuffer;
3723  }
3725  {
3726  /* Bad string pointer, bail out */
3727  _SEH2_YIELD(return 0);
3728  }
3729  _SEH2_END;
3730  }
3731  else
3732  {
3733  InString = UnsafeInString;
3734  OutString = UnsafeOutString;
3735  }
3736 
3737  /* Acquire the printing spinlock without waiting at raised IRQL */
3738  while (TRUE)
3739  {
3740  /* Wait when the spinlock becomes available */
3741  while (!KeTestSpinLock(&KdpSerialSpinLock));
3742 
3743  /* Spinlock was free, raise IRQL */
3745 
3746  /* Try to get the spinlock */
3748  break;
3749 
3750  /* Someone else got the spinlock, lower IRQL back */
3752  }
3753 
3754  /* Loop the string to send */
3755  for (i = 0; i < InStringLength; i++)
3756  {
3757  /* Print it to serial */
3758  KdPortPutByteEx(&SerialPortInfo, *(PCHAR)(InString + i));
3759  }
3760 
3761  /* Print a new line for log neatness */
3764 
3765  /* Print the kdb prompt */
3766  for (i = 0; i < KdpPromptString.Length; i++)
3767  {
3768  /* Print it to serial */
3770  *(KdpPromptString.Buffer + i));
3771  }
3772 
3774  KbdDisableMouse();
3775 
3776  /* Loop the whole string */
3777  for (i = 0; i < OutStringLength; i++)
3778  {
3779  /* Check if this is serial debugging mode */
3781  {
3782  /* Get the character from serial */
3783  do
3784  {
3786  } while (Response == -1);
3787  }
3788  else
3789  {
3790  /* Get the response from the keyboard */
3791  do
3792  {
3793  Response = KdbpTryGetCharKeyboard(&DummyScanCode, MAXULONG);
3794  } while (Response == -1);
3795  }
3796 
3797  /* Check for return */
3798  if (Response == '\r')
3799  {
3800  /*
3801  * We might need to discard the next '\n'.
3802  * Wait a bit to make sure we receive it.
3803  */
3804  KeStallExecutionProcessor(100000);
3805 
3806  /* Check the mode */
3808  {
3809  /* Read and discard the next character, if any */
3811  }
3812  else
3813  {
3814  /* Read and discard the next character, if any */
3815  KdbpTryGetCharKeyboard(&DummyScanCode, 5);
3816  }
3817 
3818  /*
3819  * Null terminate the output string -- documentation states that
3820  * DbgPrompt does not null terminate, but it does
3821  */
3822  *(PCHAR)(OutString + i) = 0;
3823  break;
3824  }
3825 
3826  /* Write it back and print it to the log */
3827  *(PCHAR)(OutString + i) = Response;
3829  }
3830 
3832  KbdEnableMouse();
3833 
3834  /* Print a new line */
3837 
3838  /* Release spinlock */
3840 
3841  /* Lower IRQL back */
3843 
3844  /* Copy back response if required */
3845  if (PreviousMode != KernelMode)
3846  {
3847  _SEH2_TRY
3848  {
3849  /* Safely copy back response to user mode */
3850  RtlCopyMemory(UnsafeOutString,
3851  OutString,
3852  i);
3853  }
3855  {
3856  /* String became invalid after we exited, fail */
3857  _SEH2_YIELD(return 0);
3858  }
3859  _SEH2_END;
3860  }
3861 
3862  /* Return the length */
3863  return i;
3864 }
PCHAR KdpDmesgBuffer
Definition: kdio.c:41
BOOLEAN KdbpDeleteBreakPoint(IN LONG BreakPointNr OPTIONAL, IN OUT PKDB_BREAKPOINT BreakPoint OPTIONAL)
Deletes a breakpoint.
Definition: kdb.c:706
signed char * PCHAR
Definition: retypes.h:7
ULONG TempEsp
Definition: ketypes.h:244
#define KEY_ESC
Definition: kdb_cli.c:39
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
ULONG Cr3
Definition: kdb.h:18
#define IN
Definition: typedefs.h:38
#define isspace(c)
Definition: acclib.h:69
static BOOLEAN KdbpCmdFilter(ULONG Argc, PCHAR Argv[])
Display list of active debug channels.
Definition: kdb_cli.c:641
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:1103
PCWSTR Expression
static VOID KdbpReadCommand(OUT PCHAR Buffer, IN ULONG Size)
Reads a line of user-input.
Definition: kdb_cli.c:3128
UINT32 strtoul(const char *String, char **Terminator, UINT32 Base)
Definition: utclib.c:696
#define KeRaiseIrql(irql, oldIrql)
Definition: env_spec_w32.h:597
void * memrchr(const void *s, int c, size_t n)
Definition: kdb_cli.c:2708
static VOID KdbpCommandHistoryAppend(IN PCHAR Command)
Appends a command to the command history.
Definition: kdb_cli.c:3054
volatile BOOLEAN KdbpIsInDmesgMode
Definition: kdio.c:46
static PKDBG_CLI_ROUTINE KdbCliCallbacks[10]
Definition: kdb_cli.c:108
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
struct _KGDTENTRY::@2327::@2328 Bytes
#define KeLowerIrql(oldIrql)
Definition: env_spec_w32.h:602
ULONG ScanCode
Definition: api.c:39
ULONG Esp
Definition: nt_native.h:1479
#define NPX_STATE_TO_STRING(state)
Definition: kdb_cli.c:62
IN PLARGE_INTEGER IN PLARGE_INTEGER PEPROCESS ULONG Key
Definition: fatprocs.h:2697
Type
Definition: Type.h:6
ULONG Eip
Definition: nt_native.h:1476
struct _Entry Entry
Definition: kefuncs.h:640
static BOOLEAN KdbpCmdProc(ULONG Argc, PCHAR Argv[])
Lists processes or switches to another process context.
Definition: kdb_cli.c:1712
#define __cdecl
Definition: accygwin.h:79
ULONG KdbDebugState
Definition: kdb.c:45
VOID KdbEnter(VOID)
PROSSYM_INFO KdbpSymFindCachedFile(IN PUNICODE_STRING FileName)
Find cached symbol file.
#define DbgPrint
Definition: loader.c:25
KSPIN_LOCK KdpSerialSpinLock
Definition: kdio.c:29
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
BOOLEAN NTAPI KdbpGetHexNumber(IN PCHAR pszNum, OUT ULONG_PTR *pulValue)
Definition: kdb_cli.c:425
#define KdbpGetCharKeyboard(ScanCode)
Definition: kdb.h:250
static BOOLEAN KdbpEvaluateExpression(IN PCHAR Expression, IN LONG ErrOffset, OUT PULONGLONG Result)
Evaluates an expression...
Definition: kdb_cli.c:398
static BOOLEAN KdbpCmdBreakPointList(ULONG Argc, PCHAR Argv[])
Lists breakpoints.
Definition: kdb_cli.c:1242
#define KDB_ACCESS_TYPE_TO_STRING(type)
Definition: kdb_cli.c:57
BOOLEAN KdbpAttachToThread(PVOID ThreadId)
Switches to another thread context.
Definition: kdb.c:1144
USHORT BaseLow
Definition: ketypes.h:334
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
PEPROCESS KdbCurrentProcess
Definition: kdb.c:47
_Check_return_ _CRTIMP size_t __cdecl strcspn(_In_z_ const char *_Str, _In_z_ const char *_Control)
#define _countof(array)
Definition: fontsub.cpp:30
ULONG Cr4
Definition: kdb.h:19
#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:2474
#define KEYSC_PAGEUP
Definition: kdb_cli.c:47
PCHAR Name
Definition: kdb_cli.c:138
ULONG Ecx
Definition: nt_native.h:1467
LONG NTSTATUS
Definition: precomp.h:26
BOOLEAN RosSymAggregate(PROSSYM_INFO RosSymInfo, PCHAR Type, PROSSYM_AGGREGATE Aggregate)
Definition: find.c:137
#define KEYSC_HOME
Definition: kdb_cli.c:49
KTHREAD Tcb
Definition: pstypes.h:1034
struct _KIPCR * PKIPCR
static BOOLEAN KdbpCmdBugCheck(ULONG Argc, PCHAR Argv[])
Bugchecks the system.
Definition: kdb_cli.c:2183
ULONG NumElements
Definition: rossym.h:101
SCHAR Priority
Definition: ketypes.h:1672
GLdouble n
Definition: glext.h:7729
#define DPFLTR_MASK
Definition: kdtypes.h:34
ULONG SizeOfImage
Definition: ldrtypes.h:142
INT Length2
Definition: FsRtlDissect.c:16
#define INVALID_HANDLE_VALUE
Definition: compat.h:391
const ULONG KdpDmesgBufferSize
Definition: kdio.c:40
_Inout_ __drv_aliasesMem PSLIST_ENTRY _Inout_ PSLIST_ENTRY _In_ ULONG Count
Definition: exfuncs.h:1015
#define KDB_ENTER_CONDITION_TO_STRING(cond)
Definition: kdb_cli.c:52
BOOLEAN ExpKdbgExtPool(ULONG Argc, PCHAR Argv[])
PKTRAP_FRAME TrapFrame
Definition: ketypes.h:1664
#define isalpha(c)
Definition: acclib.h:74
static BOOLEAN KdbpGetComponentId(IN PCCH ComponentName, OUT PULONG ComponentId)
Transform a component name to an integer.
Definition: kdb_cli.c:212
_IRQL_requires_same_ typedef _In_ ULONG _In_ UCHAR Level
Definition: wmitypes.h:55
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:1252
VOID NTAPI ObDereferenceObject(IN PVOID Object)
Definition: obref.c:375
#define KdbpGetCharSerial()
Definition: kdb.h:254
ULONG SegGs
Definition: nt_native.h:1453
GLuint GLuint end
Definition: gl.h:1545
BOOLEAN KdbSymPrintAddress(IN PVOID Address, IN PCONTEXT Context)
Print address...
Definition: kdb_symbols.c:148
ULONG SegFs
Definition: nt_native.h:1454
_Check_return_ _CRTIMP _CONST_RETURN char *__cdecl strrchr(_In_z_ const char *_Str, _In_ int _Ch)
Definition: shell.h:41
ULONG SegDs
Definition: nt_native.h:1456
USHORT Backlink
Definition: ketypes.h:789
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:585
char * LPSTR
Definition: xmlstorage.h:182
USHORT NTAPI KdpPrompt(_In_reads_bytes_(InStringLength) PCHAR UnsafeInString, _In_ USHORT InStringLength, _Out_writes_bytes_(OutStringLength) PCHAR UnsafeOutString, _In_ USHORT OutStringLength, _In_ KPROCESSOR_MODE PreviousMode, _In_ PKTRAP_FRAME TrapFrame, _In_ PKEXCEPTION_FRAME ExceptionFrame)
Definition: kdb_cli.c:3677
#define FASTCALL
Definition: nt_native.h:50
#define _stricmp
Definition: cat.c:22
UNICODE_STRING Global
Definition: symlink.c:37
int32_t INT
Definition: typedefs.h:56
PVOID Base
Definition: ketypes.h:486
VOID NTAPI ProbeForWrite(IN PVOID Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:143
ULONG Dr7
Definition: nt_native.h:1439
ULONG Dr3
Definition: nt_native.h:1437
#define KeGetPcr()
Definition: ke.h:25
#define DPFLTR_WARNING_LEVEL
Definition: kdtypes.h:31
struct TraceInfo Info
static BOOLEAN KdbpCmdEnableDisableClearBreakPoint(ULONG Argc, PCHAR Argv[])
Enables, disables or clears a breakpoint.
Definition: kdb_cli.c:1339
CHAR KdbpTryGetCharSerial(ULONG Retry)
Definition: kdb_serial.c:19
CHAR KdbpTryGetCharKeyboard(PULONG ScanCode, ULONG Retry)
Definition: kdb_keyboard.c:104
#define KEY_SCAN_DOWN
Definition: kdb_cli.c:43
void Print(USHORT Window, LPSTR p)
Definition: hardware.c:797
USHORT Limit
Definition: ketypes.h:485
_SEH2_TRY
Definition: create.c:4250
DWORD Id
volatile ULONG KdbDmesgTotalWritten
Definition: kdio.c:44
static ULONG KdbNumberOfRowsPrinted
Definition: kdb_cli.c:117
#define STATUS_END_OF_FILE
Definition: shellext.h:62
uint32_t ULONG_PTR
Definition: typedefs.h:63
NTSTRSAFEAPI RtlStringCbCopyA(_Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest, _In_ size_t cbDest, _In_ NTSTRSAFE_PCSTR pszSrc)
Definition: ntstrsafe.h:163
INT Length1
Definition: FsRtlDissect.c:15
BOOLEAN KdbpDisableBreakPoint(IN LONG BreakPointNr OPTIONAL, IN OUT PKDB_BREAKPOINT BreakPoint OPTIONAL)
Disables a breakpoint.
Definition: kdb.c:976
PVOID DllBase
Definition: btrfs_drv.h:1835
#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:3400
WCHAR First[]
Definition: FormatMessage.c:11
UCHAR KIRQL
Definition: env_spec_w32.h:591
VOID NTAPI KdpSerialDebugPrint(LPSTR Message, ULONG Length)
Definition: kdio.c:321
static BOOLEAN KdbpCmdStep(ULONG Argc, PCHAR Argv[])
Continues execution of the system/leaves KDB.
Definition: kdb_cli.c:1212
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
#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:1201
static BOOLEAN KdbpCmdMod(ULONG Argc, PCHAR Argv[])
Lists loaded modules or the one containing the specified address.
Definition: kdb_cli.c:1830
__INTRIN_INLINE uintptr_t __readeflags(void)
Definition: intrin_x86.h:1555
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
VOID KdbpCliModuleLoaded(IN PUNICODE_STRING Name)
Called when a module is loaded.
Definition: kdb_cli.c:3523
static ULONG KdbNumberOfColsPrinted
Definition: kdb_cli.c:118
VOID FASTCALL KiReleaseSpinLock(IN PKSPIN_LOCK SpinLock)
Definition: ntoskrnl.c:39
long LONG
Definition: pedump.c:60
__INTRIN_INLINE void __sidt(void *Destination)
Definition: intrin_x86.h:1920
short SHORT
Definition: pedump.c:59
#define FILE_READ_DATA
Definition: nt_native.h:628
volatile ULONG KdpDmesgCurrentPosition
Definition: kdio.c:42
ULONG SegEs
Definition: nt_native.h:1455
_Check_return_ _CRTIMP int __cdecl _strnicmp(_In_reads_or_z_(_MaxCount) const char *_Str1, _In_reads_or_z_(_MaxCount) const char *_Str2, _In_ size_t _MaxCount)
ULONG Esi
Definition: nt_native.h:1464
CHAR * PCH
Definition: ntbasedef.h:398
BOOLEAN NTAPI KdbRegisterCliCallback(PVOID Callback, BOOLEAN Deregister)
Definition: kdb_cli.c:3319
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
ULONG Dr1
Definition: nt_native.h:1435
ULONG SegCs
Definition: nt_native.h:1477
unsigned char BOOLEAN
static BOOLEAN KdbRepeatLastCommand
Definition: kdb_cli.c:120
smooth NULL
Definition: ftsmooth.c:416
ULONG Edx
Definition: nt_native.h:1466
static WCHAR Address[46]
Definition: ping.c:68
unsigned char
Definition: typeof.h:29
#define _Out_writes_bytes_(size)
Definition: no_sal2.h:370
_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:787
VOID KbdEnableMouse(VOID)
PCHAR CountOnePageUp(PCHAR Buffer, ULONG BufLength, PCHAR pCurPos)
Calculate pointer position for N lines upper of current position.
Definition: kdb_cli.c:2736
char * va_list
Definition: acmsvcex.h:78
void DPRINT(...)
Definition: polytest.cpp:61
static BOOLEAN KdbpCmdHelp(ULONG Argc, PCHAR Argv[])
Displays help screen.
Definition: kdb_cli.c:2438
ULONG EFlags
Definition: nt_native.h:1478
Definition: bufpool.h:45
PVOID KernelStack
Definition: ketypes.h:1565
VOID NTAPI KdPortPutByteEx(PCPPORT PortInformation, UCHAR ByteToSend)
ULONG Dr2
Definition: nt_native.h:1436
#define KEY_BS
Definition: kdb_cli.c:38
ULONG Ebx
Definition: nt_native.h:1465
const char * LPCSTR
Definition: xmlstorage.h:183
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:1380
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
VOID KdbpCliMainLoop(IN BOOLEAN EnteredOnSingleStep)
KDB Main Loop.
Definition: kdb_cli.c:3462
static BOOLEAN KdbpCmdSet(ULONG Argc, PCHAR Argv[])
Sets or displays a config variables value.
Definition: kdb_cli.c:2259
#define KEY_SCAN_UP
Definition: kdb_cli.c:42
BOOLEAN KdbpBugCheckRequested
Definition: kdb_cli.c:125
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
#define KEYSC_END
Definition: kdb_cli.c:46
static BOOLEAN KdbpCmdTss(ULONG Argc, PCHAR Argv[])
Displays the TSS.
Definition: kdb_cli.c:2160
#define PCHAR
Definition: match.c:90
BOOLEAN FASTCALL KeTestSpinLock(IN PKSPIN_LOCK SpinLock)
Definition: spinlock.c:442
PKDB_KTRAP_FRAME KdbCurrentTrapFrame
Definition: kdb.c:51
r l[0]
Definition: byte_order.h:167
ULONG64 NpxState
Definition: ketypes.h:1958
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:809
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
static BOOLEAN KdbpTrapFrameFromPrevTss(PCONTEXT TrapFrame)
Definition: kdb_cli.c:988
CONST CHAR * PCCH
Definition: ntbasedef.h:399
_In_ KPROCESSOR_MODE PreviousMode
Definition: sefuncs.h:103
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID * BaseAddress
Definition: mmfuncs.h:404
static BOOLEAN KdbOutputAborted
Definition: kdb_cli.c:119
#define _SEH2_YIELD(STMT_)
Definition: pseh2_64.h:8
static const char *const debug_classes[]
Definition: debug.c:51
PCHAR Syntax
Definition: kdb_cli.c:139
static LONG KdbCommandHistoryBufferIndex
Definition: kdb_cli.c:114
return Iosb
Definition: create.c:4426
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
ULONG Eip
Definition: ketypes.h:796
struct Command Command
VOID FASTCALL KiTrap03Handler(IN PKTRAP_FRAME)
Definition: traphdlr.c:608
uint64_t ULONGLONG
Definition: typedefs.h:65
static BOOLEAN KdbBreakOnModuleLoad
Definition: kdb_cli.c:110
CLIENT_ID Cid
Definition: pstypes.h:1059
static BOOLEAN KdbpCmdRegs(ULONG Argc, PCHAR Argv[])
Displays CPU registers.
Definition: kdb_cli.c:848
BOOLEAN ExpKdbgExtPoolFind(ULONG Argc, PCHAR Argv[])
LONG KdbpGetNextBreakPointNr(IN ULONG Start OPTIONAL)
Gets the number of the next breakpoint >= Start.
Definition: kdb.c:489
static BOOLEAN KdbpCmdThread(ULONG Argc, PCHAR Argv[])
Lists threads or switches to another thread context.
Definition: kdb_cli.c:1504
static BOOLEAN KdbUseIntelSyntax
Definition: kdb_cli.c:109
const GLubyte * c
Definition: glext.h:8905
static BOOLEAN KdbpCmdReboot(ULONG Argc, PCHAR Argv[])
Definition: kdb_cli.c:2194
STRING KdpPromptString
Definition: kdb_cli.c:3672
int strncmp(const char *String1, const char *String2, ACPI_SIZE Count)
Definition: utclib.c:534
ULONG HardwareEsp
Definition: ketypes.h:268
volatile VOID * StackLimit
Definition: ketypes.h:1555
VOID KbdDisableMouse(VOID)
static LONG KdbNumberOfRowsTerminal
Definition: kdb_cli.c:121
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
VOID NTAPI HalReturnToFirmware(IN FIRMWARE_REENTRY Action)
Definition: reboot.c:22
static const struct @1740 KdbDebuggerCommands[]
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
Definition: ncftp.h:89
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:727
HANDLE UniqueThread
Definition: compat.h:475
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
CHAR Message[80]
Definition: alive.c:5
std::wstring STRING
Definition: fontsub.cpp:33
enum _KDB_ACCESS_TYPE KDB_ACCESS_TYPE
#define PKTSS
Definition: ketypes.h:921
NTSYSAPI NTSTATUS NTAPI ZwOpenFile(_Out_ PHANDLE FileHandle, _In_ ACCESS_MASK DesiredAccess, _In_ POBJECT_ATTRIBUTES ObjectAttributes, _Out_ PIO_STATUS_BLOCK IoStatusBlock, _In_ ULONG ShareAccess, _In_ ULONG OpenOptions)
volatile int Continue
Definition: gdblib.c:102
NTSTATUS NTAPI PsLookupProcessByProcessId(IN HANDLE ProcessId, OUT PEPROCESS *Process)
Definition: process.c:919
unsigned char UCHAR
Definition: xmlstorage.h:181
static LONG KdbNumberOfColsTerminal
Definition: kdb_cli.c:122
ULONG KdbNumSingleSteps
Definition: kdb.c:43
VOID NTAPI ProbeForRead(IN CONST VOID *Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:102
static const WCHAR L[]
Definition: oid.c:1250
enum _KDB_ENTER_CONDITION KDB_ENTER_CONDITION
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:803
static BOOLEAN KdbpCmdGdtLdtIdt(ULONG Argc, PCHAR Argv[])
Displays GDT, LDT or IDTd.
Definition: kdb_cli.c:1894
VOID RosSymFreeAggregate(PROSSYM_AGGREGATE Aggregate)
Definition: find.c:126
CONTEXT Tf
Definition: kdb.h:15
__INTRIN_INLINE void __writeeflags(uintptr_t Value)
Definition: intrin_x86.h:1550
#define ExAllocatePool(type, size)
Definition: fbtusb.h:44
#define FILE_NON_DIRECTORY_FILE
Definition: constants.h:492
Definition: btrfs_drv.h:1831
static BOOLEAN KdbpInNmiOrDoubleFaultHandler(ULONG_PTR Address)
Definition: kdb_cli.c:1060
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
GLenum GLsizei len
Definition: glext.h:6722
PCHAR Help
Definition: kdb_cli.c:140
VOID __cdecl KiTrap02(VOID)
Definition: traphdlr.c:461
_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:2788
static BOOLEAN KdbpInvokeCliCallbacks(IN PCHAR Command, IN ULONG Argc, IN PCH Argv[])
Invokes registered CLI callbacks until one of them handled the Command.
Definition: kdb_cli.c:3366
BOOLEAN KdbSingleStepOver
Definition: kdb.c:44
Definition: typedefs.h:117
BOOLEAN ExpKdbgExtPoolUsed(ULONG Argc, PCHAR Argv[])
ULONG Eax
Definition: nt_native.h:1468
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:359
#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:1225
ULONG Eip
Definition: ketypes.h:265
#define _In_reads_bytes_(size)
Definition: no_sal2.h:229
static BOOLEAN KdbpCmdPcr(ULONG Argc, PCHAR Argv[])
Displays the KPCR.
Definition: kdb_cli.c:2113
Status
Definition: gdiplustypes.h:24
static BOOLEAN KdbpCmdDmesg(ULONG Argc, PCHAR Argv[])
Display debug messages on screen, with paging.
Definition: kdb_cli.c:2215
#define MAXULONG
Definition: typedefs.h:250
#define _In_
Definition: no_sal2.h:204
ULONG PreviousPreviousMode
Definition: ketypes.h:257
PVOID StackBase
Definition: ketypes.h:1556
static LONG KdbCommandHistoryIndex
Definition: kdb_cli.c:115
ULONG_PTR SIZE_T
Definition: typedefs.h:78
BOOLEAN ExpKdbgExtIrpFind(ULONG Argc, PCHAR Argv[])
ULONG Cr0
Definition: kdb.h:16
#define HIGH_LEVEL
Definition: env_spec_w32.h:703
VOID __cdecl KiTrap08(VOID)
struct _FileName FileName
Definition: fatprocs.h:884
NTSTATUS KdbpSafeReadMemory(OUT PVOID Dest, IN PVOID Src, IN ULONG Bytes)
Definition: kdb.c:1787
enum State_ State
Definition: pofuncs.h:54
BOOLEAN ExpKdbgExtFileCache(ULONG Argc, PCHAR Argv[])
_SEH2_END
Definition: create.c:4424
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:516
static PCHAR KdbCommandHistory[sizeof(KdbCommandHistoryBuffer)/8]
Definition: kdb_cli.c:113
ULONG SegSs
Definition: nt_native.h:1480
static BOOLEAN KdbpCmdEvalExpression(ULONG Argc, PCHAR Argv[])
Evaluates an expression and displays the result.
Definition: kdb_cli.c:444
#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:141
#define RTL_NUMBER_OF(x)
Definition: RtlRegistry.c:12
ULONG Ebp
Definition: ketypes.h:803
NTSYSAPI NTSTATUS NTAPI RtlAnsiStringToUnicodeString(PUNICODE_STRING DestinationString, PANSI_STRING SourceString, BOOLEAN AllocateDestinationString)
LONG KdbLastBreakPointNr
Definition: kdb.c:42
struct _LARGE_INTEGER::@2196 u
ULONG KSPIN_LOCK
Definition: env_spec_w32.h:72
ULONG Dr6
Definition: nt_native.h:1438
UNICODE_STRING BaseDllName
Definition: ldrtypes.h:144
#define KEYSC_ARROWUP
Definition: kdb_cli.c:50
unsigned int * PULONG
Definition: retypes.h:1
#define va_start(ap, A)
Definition: acmsvcex.h:91
#define min(a, b)
Definition: monoChain.cc:55
CPPORT SerialPortInfo
Definition: kdio.c:31
VOID __cdecl KiTrap09(VOID)
static CHAR KdbCommandHistoryBuffer[2048]
Definition: kdb_cli.c:112
#define KEY_DEL
Definition: kdb_cli.c:40
VOID KdbpCliInit(VOID)
Called when KDB is initialized.
Definition: kdb_cli.c:3589
#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
ULONG Dr0
Definition: nt_native.h:1434
#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:39
__GNU_EXTENSION typedef unsigned __int64 * PULONGLONG
Definition: ntbasedef.h:390
volatile UCHAR State
Definition: ketypes.h:1679
void __cdecl _disable(void)
Definition: intrin_arm.h:365
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
GROUP_AFFINITY Affinity
Definition: ketypes.h:1828
#define c
Definition: ke_i.h:80
unsigned int ULONG
Definition: retypes.h:1
BOOLEAN ExpKdbgExtDefWrites(ULONG Argc, PCHAR Argv[])
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
struct Response Response
#define ULONG_PTR
Definition: config.h:101
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
__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:1081
GLfloat GLfloat p
Definition: glext.h:8902
ULONG Cr2
Definition: kdb.h:17
struct _KGDTENTRY::@2327::@2329 Bits
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
BOOLEAN FASTCALL KeTryToAcquireSpinLockAtDpcLevel(IN OUT PKSPIN_LOCK SpinLock)
Definition: spinlock.c:303
LONG KdbpDisassemble(IN ULONG_PTR Address, IN ULONG IntelSyntax)
Definition: i386-dis.c:123
union _KGDTENTRY::@2327 HighWord
Definition: _set.h:46
#define DPFLTR_TRACE_LEVEL
Definition: kdtypes.h:32
LPFNPSPCALLBACK Callback
Definition: desk.c:111
PVOID InitialStack
Definition: ketypes.h:1554
VOID KdbpCliInterpretInitFile(VOID)
This function is called by KdbEnterDebuggerException...
Definition: kdb_cli.c:3540
PCHAR KdbInitFileBuffer
Definition: kdb_cli.c:124
NTSTATUS NTAPI NtSetDebugFilterState(IN ULONG ComponentId, IN ULONG Level, IN BOOLEAN State)
Definition: kdmain.c:417
VOID NTAPI KeStallExecutionProcessor(IN ULONG MicroSeconds)
Definition: ntoskrnl.c:99
BOOLEAN KdbpSymFindModule(IN PVOID Address OPTIONAL, IN LPCWSTR Name OPTIONAL, IN INT Index OPTIONAL, OUT PLDR_DATA_TABLE_ENTRY *pLdrEntry)
Find a module...
Definition: kdb_symbols.c:76
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:1091
volatile ULONG KdpDmesgFreeBytes
Definition: kdio.c:43
ULONG Ebp
Definition: nt_native.h:1475
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:1070
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
ULONG Ebp
Definition: ketypes.h:263
ULONG Edi
Definition: nt_native.h:1463
#define RTL_CONSTANT_STRING(s)
Definition: tunneltest.c:14
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
BOOLEAN ExpKdbgExtHandle(ULONG Argc, PCHAR Argv[])