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