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