ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

kdb_cli.c
Go to the documentation of this file.
00001 /*
00002  *  ReactOS kernel
00003  *  Copyright (C) 2005 ReactOS Team
00004  *
00005  *  This program is free software; you can redistribute it and/or modify
00006  *  it under the terms of the GNU General Public License as published by
00007  *  the Free Software Foundation; either version 2 of the License, or
00008  *  (at your option) any later version.
00009  *
00010  *  This program is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  *  GNU General Public License for more details.
00014  *
00015  *  You should have received a copy of the GNU General Public License along
00016  *  with this program; if not, write to the Free Software Foundation, Inc.,
00017  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00018  */
00019 /*
00020  * PROJECT:         ReactOS kernel
00021  * FILE:            ntoskrnl/dbg/kdb_cli.c
00022  * PURPOSE:         Kernel debugger command line interface
00023  * PROGRAMMER:      Gregor Anich (blight@blight.eu.org)
00024  *                  Hervé Poussineau
00025  * UPDATE HISTORY:
00026  *                  Created 16/01/2005
00027  */
00028 
00029 /* INCLUDES ******************************************************************/
00030 
00031 #include <ntoskrnl.h>
00032 
00033 #define NDEBUG
00034 #include <debug.h>
00035 
00036 /* DEFINES *******************************************************************/
00037 
00038 #define KEY_BS          8
00039 #define KEY_ESC         27
00040 #define KEY_DEL         127
00041 
00042 #define KEY_SCAN_UP     72
00043 #define KEY_SCAN_DOWN   80
00044 
00045 /* Scan codes of keyboard keys: */
00046 #define KEYSC_END       0x004f
00047 #define KEYSC_PAGEUP    0x0049
00048 #define KEYSC_PAGEDOWN  0x0051
00049 #define KEYSC_HOME      0x0047
00050 #define KEYSC_ARROWUP   0x0048
00051 
00052 #define KDB_ENTER_CONDITION_TO_STRING(cond)                               \
00053                    ((cond) == KdbDoNotEnter ? "never" :                   \
00054                    ((cond) == KdbEnterAlways ? "always" :                 \
00055                    ((cond) == KdbEnterFromKmode ? "kmode" : "umode")))
00056 
00057 #define KDB_ACCESS_TYPE_TO_STRING(type)                                   \
00058                    ((type) == KdbAccessRead ? "read" :                    \
00059                    ((type) == KdbAccessWrite ? "write" :                  \
00060                    ((type) == KdbAccessReadWrite ? "rdwr" : "exec")))
00061 
00062 #define NPX_STATE_TO_STRING(state)                                        \
00063                    ((state) == NPX_STATE_LOADED ? "Loaded" :              \
00064                    ((state) == NPX_STATE_NOT_LOADED ? "Not loaded" : "Unknown"))
00065 
00066 /* PROTOTYPES ****************************************************************/
00067 
00068 static BOOLEAN KdbpCmdEvalExpression(ULONG Argc, PCHAR Argv[]);
00069 static BOOLEAN KdbpCmdDisassembleX(ULONG Argc, PCHAR Argv[]);
00070 static BOOLEAN KdbpCmdRegs(ULONG Argc, PCHAR Argv[]);
00071 static BOOLEAN KdbpCmdBackTrace(ULONG Argc, PCHAR Argv[]);
00072 
00073 static BOOLEAN KdbpCmdContinue(ULONG Argc, PCHAR Argv[]);
00074 static BOOLEAN KdbpCmdStep(ULONG Argc, PCHAR Argv[]);
00075 static BOOLEAN KdbpCmdBreakPointList(ULONG Argc, PCHAR Argv[]);
00076 static BOOLEAN KdbpCmdEnableDisableClearBreakPoint(ULONG Argc, PCHAR Argv[]);
00077 static BOOLEAN KdbpCmdBreakPoint(ULONG Argc, PCHAR Argv[]);
00078 
00079 static BOOLEAN KdbpCmdThread(ULONG Argc, PCHAR Argv[]);
00080 static BOOLEAN KdbpCmdProc(ULONG Argc, PCHAR Argv[]);
00081 
00082 static BOOLEAN KdbpCmdMod(ULONG Argc, PCHAR Argv[]);
00083 static BOOLEAN KdbpCmdGdtLdtIdt(ULONG Argc, PCHAR Argv[]);
00084 static BOOLEAN KdbpCmdPcr(ULONG Argc, PCHAR Argv[]);
00085 static BOOLEAN KdbpCmdTss(ULONG Argc, PCHAR Argv[]);
00086 
00087 static BOOLEAN KdbpCmdBugCheck(ULONG Argc, PCHAR Argv[]);
00088 static BOOLEAN KdbpCmdFilter(ULONG Argc, PCHAR Argv[]);
00089 static BOOLEAN KdbpCmdSet(ULONG Argc, PCHAR Argv[]);
00090 static BOOLEAN KdbpCmdHelp(ULONG Argc, PCHAR Argv[]);
00091 static BOOLEAN KdbpCmdDmesg(ULONG Argc, PCHAR Argv[]);
00092 
00093 #ifdef __ROS_DWARF__
00094 static BOOLEAN KdbpCmdPrintStruct(ULONG Argc, PCHAR Argv[]);
00095 #endif
00096 
00097 /* GLOBALS *******************************************************************/
00098 
00099 static BOOLEAN KdbUseIntelSyntax = FALSE; /* Set to TRUE for intel syntax */
00100 static BOOLEAN KdbBreakOnModuleLoad = FALSE; /* Set to TRUE to break into KDB when a module is loaded */
00101 
00102 static CHAR KdbCommandHistoryBuffer[2048]; /* Command history string ringbuffer */
00103 static PCHAR KdbCommandHistory[sizeof(KdbCommandHistoryBuffer) / 8] = { NULL }; /* Command history ringbuffer */
00104 static LONG KdbCommandHistoryBufferIndex = 0;
00105 static LONG KdbCommandHistoryIndex = 0;
00106 
00107 static ULONG KdbNumberOfRowsPrinted = 0;
00108 static ULONG KdbNumberOfColsPrinted = 0;
00109 static BOOLEAN KdbOutputAborted = FALSE;
00110 static BOOLEAN KdbRepeatLastCommand = FALSE;
00111 static LONG KdbNumberOfRowsTerminal = -1;
00112 static LONG KdbNumberOfColsTerminal = -1;
00113 
00114 PCHAR KdbInitFileBuffer = NULL; /* Buffer where KDBinit file is loaded into during initialization */
00115 BOOLEAN KdbpBugCheckRequested = FALSE;
00116 
00117 /* Vars for dmesg */
00118 /* defined in ../kd/kdio.c, declare here: */
00119 extern volatile BOOLEAN KdbpIsInDmesgMode;
00120 extern const ULONG KdpDmesgBufferSize;
00121 extern PCHAR KdpDmesgBuffer;
00122 extern volatile ULONG KdpDmesgCurrentPosition;
00123 extern volatile ULONG KdpDmesgFreeBytes;
00124 extern volatile ULONG KdbDmesgTotalWritten;
00125 
00126 static const struct
00127 {
00128     PCHAR Name;
00129     PCHAR Syntax;
00130     PCHAR Help;
00131     BOOLEAN (*Fn)(ULONG Argc, PCHAR Argv[]);
00132 } KdbDebuggerCommands[] = {
00133     /* Data */
00134     { NULL, NULL, "Data", NULL },
00135     { "?", "? expression", "Evaluate expression.", KdbpCmdEvalExpression },
00136     { "disasm", "disasm [address] [L count]", "Disassemble count instructions at address.", KdbpCmdDisassembleX },
00137     { "x", "x [address] [L count]", "Display count dwords, starting at addr.", KdbpCmdDisassembleX },
00138     { "regs", "regs", "Display general purpose registers.", KdbpCmdRegs },
00139     { "cregs", "cregs", "Display control registers.", KdbpCmdRegs },
00140     { "sregs", "sregs", "Display status registers.", KdbpCmdRegs },
00141     { "dregs", "dregs", "Display debug registers.", KdbpCmdRegs },
00142     { "bt", "bt [*frameaddr|thread id]", "Prints current backtrace or from given frame addr", KdbpCmdBackTrace },
00143 #ifdef __ROS_DWARF__
00144     { "dt", "dt [mod] [type] [addr]", "Print a struct.  Addr is optional.", KdbpCmdPrintStruct },
00145 #endif
00146 
00147     /* Flow control */
00148     { NULL, NULL, "Flow control", NULL },
00149     { "cont", "cont", "Continue execution (leave debugger)", KdbpCmdContinue },
00150     { "step", "step [count]", "Execute single instructions, stepping into interrupts.", KdbpCmdStep },
00151     { "next", "next [count]", "Execute single instructions, skipping calls and reps.", KdbpCmdStep },
00152     { "bl", "bl", "List breakpoints.", KdbpCmdBreakPointList },
00153     { "be", "be [breakpoint]", "Enable breakpoint.", KdbpCmdEnableDisableClearBreakPoint },
00154     { "bd", "bd [breakpoint]", "Disable breakpoint.", KdbpCmdEnableDisableClearBreakPoint },
00155     { "bc", "bc [breakpoint]", "Clear breakpoint.", KdbpCmdEnableDisableClearBreakPoint },
00156     { "bpx", "bpx [address] [IF condition]", "Set software execution breakpoint at address.", KdbpCmdBreakPoint },
00157     { "bpm", "bpm [r|w|rw|x] [byte|word|dword] [address] [IF condition]", "Set memory breakpoint at address.", KdbpCmdBreakPoint },
00158 
00159     /* Process/Thread */
00160     { NULL, NULL, "Process/Thread", NULL },
00161     { "thread", "thread [list[ pid]|[attach ]tid]", "List threads in current or specified process, display thread with given id or attach to thread.", KdbpCmdThread },
00162     { "proc", "proc [list|[attach ]pid]", "List processes, display process with given id or attach to process.", KdbpCmdProc },
00163 
00164     /* System information */
00165     { NULL, NULL, "System info", NULL },
00166     { "mod", "mod [address]", "List all modules or the one containing address.", KdbpCmdMod },
00167     { "gdt", "gdt", "Display global descriptor table.", KdbpCmdGdtLdtIdt },
00168     { "ldt", "ldt", "Display local descriptor table.", KdbpCmdGdtLdtIdt },
00169     { "idt", "idt", "Display interrupt descriptor table.", KdbpCmdGdtLdtIdt },
00170     { "pcr", "pcr", "Display processor control region.", KdbpCmdPcr },
00171     { "tss", "tss", "Display task state segment.", KdbpCmdTss },
00172 
00173     /* Others */
00174     { NULL, NULL, "Others", NULL },
00175     { "bugcheck", "bugcheck", "Bugchecks the system.", KdbpCmdBugCheck },
00176     { "filter", "filter [error|warning|trace|info|level]+|-[componentname|default]", "Enable/disable debug channels", KdbpCmdFilter },
00177     { "set", "set [var] [value]", "Sets var to value or displays value of var.", KdbpCmdSet },
00178     { "dmesg", "dmesg", "Display debug messages on screen, with navigation on pages.", KdbpCmdDmesg },
00179     { "kmsg", "kmsg", "Kernel dmesg. Alias for dmesg.", KdbpCmdDmesg },
00180     { "help", "help", "Display help screen.", KdbpCmdHelp }
00181 };
00182 
00183 /* FUNCTIONS *****************************************************************/
00184 
00193 static BOOLEAN
00194 KdbpGetComponentId(
00195     IN  PCCH ComponentName,
00196     OUT PULONG ComponentId)
00197 {
00198     ULONG i;
00199 
00200     static struct
00201     {
00202         PCCH Name;
00203         ULONG Id;
00204     }
00205     ComponentTable[] =
00206     {
00207         { "DEFAULT", DPFLTR_DEFAULT_ID },
00208         { "SYSTEM", DPFLTR_SYSTEM_ID },
00209         { "SMSS", DPFLTR_SMSS_ID },
00210         { "SETUP", DPFLTR_SETUP_ID },
00211         { "NTFS", DPFLTR_NTFS_ID },
00212         { "FSTUB", DPFLTR_FSTUB_ID },
00213         { "CRASHDUMP", DPFLTR_CRASHDUMP_ID },
00214         { "CDAUDIO", DPFLTR_CDAUDIO_ID },
00215         { "CDROM", DPFLTR_CDROM_ID },
00216         { "CLASSPNP", DPFLTR_CLASSPNP_ID },
00217         { "DISK", DPFLTR_DISK_ID },
00218         { "REDBOOK", DPFLTR_REDBOOK_ID },
00219         { "STORPROP", DPFLTR_STORPROP_ID },
00220         { "SCSIPORT", DPFLTR_SCSIPORT_ID },
00221         { "SCSIMINIPORT", DPFLTR_SCSIMINIPORT_ID },
00222         { "CONFIG", DPFLTR_CONFIG_ID },
00223         { "I8042PRT", DPFLTR_I8042PRT_ID },
00224         { "SERMOUSE", DPFLTR_SERMOUSE_ID },
00225         { "LSERMOUS", DPFLTR_LSERMOUS_ID },
00226         { "KBDHID", DPFLTR_KBDHID_ID },
00227         { "MOUHID", DPFLTR_MOUHID_ID },
00228         { "KBDCLASS", DPFLTR_KBDCLASS_ID },
00229         { "MOUCLASS", DPFLTR_MOUCLASS_ID },
00230         { "TWOTRACK", DPFLTR_TWOTRACK_ID },
00231         { "WMILIB", DPFLTR_WMILIB_ID },
00232         { "ACPI", DPFLTR_ACPI_ID },
00233         { "AMLI", DPFLTR_AMLI_ID },
00234         { "HALIA64", DPFLTR_HALIA64_ID },
00235         { "VIDEO", DPFLTR_VIDEO_ID },
00236         { "SVCHOST", DPFLTR_SVCHOST_ID },
00237         { "VIDEOPRT", DPFLTR_VIDEOPRT_ID },
00238         { "TCPIP", DPFLTR_TCPIP_ID },
00239         { "DMSYNTH", DPFLTR_DMSYNTH_ID },
00240         { "NTOSPNP", DPFLTR_NTOSPNP_ID },
00241         { "FASTFAT", DPFLTR_FASTFAT_ID },
00242         { "SAMSS", DPFLTR_SAMSS_ID },
00243         { "PNPMGR", DPFLTR_PNPMGR_ID },
00244         { "NETAPI", DPFLTR_NETAPI_ID },
00245         { "SCSERVER", DPFLTR_SCSERVER_ID },
00246         { "SCCLIENT", DPFLTR_SCCLIENT_ID },
00247         { "SERIAL", DPFLTR_SERIAL_ID },
00248         { "SERENUM", DPFLTR_SERENUM_ID },
00249         { "UHCD", DPFLTR_UHCD_ID },
00250         { "RPCPROXY", DPFLTR_RPCPROXY_ID },
00251         { "AUTOCHK", DPFLTR_AUTOCHK_ID },
00252         { "DCOMSS", DPFLTR_DCOMSS_ID },
00253         { "UNIMODEM", DPFLTR_UNIMODEM_ID },
00254         { "SIS", DPFLTR_SIS_ID },
00255         { "FLTMGR", DPFLTR_FLTMGR_ID },
00256         { "WMICORE", DPFLTR_WMICORE_ID },
00257         { "BURNENG", DPFLTR_BURNENG_ID },
00258         { "IMAPI", DPFLTR_IMAPI_ID },
00259         { "SXS", DPFLTR_SXS_ID },
00260         { "FUSION", DPFLTR_FUSION_ID },
00261         { "IDLETASK", DPFLTR_IDLETASK_ID },
00262         { "SOFTPCI", DPFLTR_SOFTPCI_ID },
00263         { "TAPE", DPFLTR_TAPE_ID },
00264         { "MCHGR", DPFLTR_MCHGR_ID },
00265         { "IDEP", DPFLTR_IDEP_ID },
00266         { "PCIIDE", DPFLTR_PCIIDE_ID },
00267         { "FLOPPY", DPFLTR_FLOPPY_ID },
00268         { "FDC", DPFLTR_FDC_ID },
00269         { "TERMSRV", DPFLTR_TERMSRV_ID },
00270         { "W32TIME", DPFLTR_W32TIME_ID },
00271         { "PREFETCHER", DPFLTR_PREFETCHER_ID },
00272         { "RSFILTER", DPFLTR_RSFILTER_ID },
00273         { "FCPORT", DPFLTR_FCPORT_ID },
00274         { "PCI", DPFLTR_PCI_ID },
00275         { "DMIO", DPFLTR_DMIO_ID },
00276         { "DMCONFIG", DPFLTR_DMCONFIG_ID },
00277         { "DMADMIN", DPFLTR_DMADMIN_ID },
00278         { "WSOCKTRANSPORT", DPFLTR_WSOCKTRANSPORT_ID },
00279         { "VSS", DPFLTR_VSS_ID },
00280         { "PNPMEM", DPFLTR_PNPMEM_ID },
00281         { "PROCESSOR", DPFLTR_PROCESSOR_ID },
00282         { "DMSERVER", DPFLTR_DMSERVER_ID },
00283         { "SR", DPFLTR_SR_ID },
00284         { "INFINIBAND", DPFLTR_INFINIBAND_ID },
00285         { "IHVDRIVER", DPFLTR_IHVDRIVER_ID },
00286         { "IHVVIDEO", DPFLTR_IHVVIDEO_ID },
00287         { "IHVAUDIO", DPFLTR_IHVAUDIO_ID },
00288         { "IHVNETWORK", DPFLTR_IHVNETWORK_ID },
00289         { "IHVSTREAMING", DPFLTR_IHVSTREAMING_ID },
00290         { "IHVBUS", DPFLTR_IHVBUS_ID },
00291         { "HPS", DPFLTR_HPS_ID },
00292         { "RTLTHREADPOOL", DPFLTR_RTLTHREADPOOL_ID },
00293         { "LDR", DPFLTR_LDR_ID },
00294         { "TCPIP6", DPFLTR_TCPIP6_ID },
00295         { "ISAPNP", DPFLTR_ISAPNP_ID },
00296         { "SHPC", DPFLTR_SHPC_ID },
00297         { "STORPORT", DPFLTR_STORPORT_ID },
00298         { "STORMINIPORT", DPFLTR_STORMINIPORT_ID },
00299         { "PRINTSPOOLER", DPFLTR_PRINTSPOOLER_ID },
00300         { "VSSDYNDISK", DPFLTR_VSSDYNDISK_ID },
00301         { "VERIFIER", DPFLTR_VERIFIER_ID },
00302         { "VDS", DPFLTR_VDS_ID },
00303         { "VDSBAS", DPFLTR_VDSBAS_ID },
00304         { "VDSDYN", DPFLTR_VDSDYN_ID },
00305         { "VDSDYNDR", DPFLTR_VDSDYNDR_ID },
00306         { "VDSLDR", DPFLTR_VDSLDR_ID },
00307         { "VDSUTIL", DPFLTR_VDSUTIL_ID },
00308         { "DFRGIFC", DPFLTR_DFRGIFC_ID },
00309         { "MM", DPFLTR_MM_ID },
00310         { "DFSC", DPFLTR_DFSC_ID },
00311         { "WOW64", DPFLTR_WOW64_ID },
00312         { "ALPC", DPFLTR_ALPC_ID },
00313         { "WDI", DPFLTR_WDI_ID },
00314         { "PERFLIB", DPFLTR_PERFLIB_ID },
00315         { "KTM", DPFLTR_KTM_ID },
00316         { "IOSTRESS", DPFLTR_IOSTRESS_ID },
00317         { "HEAP", DPFLTR_HEAP_ID },
00318         { "WHEA", DPFLTR_WHEA_ID },
00319         { "USERGDI", DPFLTR_USERGDI_ID },
00320         { "MMCSS", DPFLTR_MMCSS_ID },
00321         { "TPM", DPFLTR_TPM_ID },
00322         { "THREADORDER", DPFLTR_THREADORDER_ID },
00323         { "ENVIRON", DPFLTR_ENVIRON_ID },
00324         { "EMS", DPFLTR_EMS_ID },
00325         { "WDT", DPFLTR_WDT_ID },
00326         { "FVEVOL", DPFLTR_FVEVOL_ID },
00327         { "NDIS", DPFLTR_NDIS_ID },
00328         { "NVCTRACE", DPFLTR_NVCTRACE_ID },
00329         { "LUAFV", DPFLTR_LUAFV_ID },
00330         { "APPCOMPAT", DPFLTR_APPCOMPAT_ID },
00331         { "USBSTOR", DPFLTR_USBSTOR_ID },
00332         { "SBP2PORT", DPFLTR_SBP2PORT_ID },
00333         { "COVERAGE", DPFLTR_COVERAGE_ID },
00334         { "CACHEMGR", DPFLTR_CACHEMGR_ID },
00335         { "MOUNTMGR", DPFLTR_MOUNTMGR_ID },
00336         { "CFR", DPFLTR_CFR_ID },
00337         { "TXF", DPFLTR_TXF_ID },
00338         { "KSECDD", DPFLTR_KSECDD_ID },
00339         { "FLTREGRESS", DPFLTR_FLTREGRESS_ID },
00340         { "MPIO", DPFLTR_MPIO_ID },
00341         { "MSDSM", DPFLTR_MSDSM_ID },
00342         { "UDFS", DPFLTR_UDFS_ID },
00343         { "PSHED", DPFLTR_PSHED_ID },
00344         { "STORVSP", DPFLTR_STORVSP_ID },
00345         { "LSASS", DPFLTR_LSASS_ID },
00346         { "SSPICLI", DPFLTR_SSPICLI_ID },
00347         { "CNG", DPFLTR_CNG_ID },
00348         { "EXFAT", DPFLTR_EXFAT_ID },
00349         { "FILETRACE", DPFLTR_FILETRACE_ID },
00350         { "XSAVE", DPFLTR_XSAVE_ID },
00351         { "SE", DPFLTR_SE_ID },
00352         { "DRIVEEXTENDER", DPFLTR_DRIVEEXTENDER_ID },
00353     };
00354 
00355     for (i = 0; i < sizeof(ComponentTable) / sizeof(ComponentTable[0]); i++)
00356     {
00357         if (_stricmp(ComponentName, ComponentTable[i].Name) == 0)
00358         {
00359             *ComponentId = ComponentTable[i].Id;
00360             return TRUE;
00361         }
00362     }
00363 
00364     return FALSE;
00365 }
00366 
00379 static BOOLEAN
00380 KdbpEvaluateExpression(
00381     IN  PCHAR Expression,
00382     IN  LONG ErrOffset,
00383     OUT PULONGLONG Result)
00384 {
00385     static CHAR ErrMsgBuffer[130] = "^ ";
00386     LONG ExpressionErrOffset = -1;
00387     PCHAR ErrMsg = ErrMsgBuffer;
00388     BOOLEAN Ok;
00389 
00390     Ok = KdbpRpnEvaluateExpression(Expression, KdbCurrentTrapFrame, Result,
00391                                    &ExpressionErrOffset, ErrMsgBuffer + 2);
00392     if (!Ok)
00393     {
00394         if (ExpressionErrOffset >= 0)
00395             ExpressionErrOffset += ErrOffset;
00396         else
00397             ErrMsg += 2;
00398 
00399         KdbpPrint("%*s%s\n", ExpressionErrOffset, "", ErrMsg);
00400     }
00401 
00402     return Ok;
00403 }
00404 
00407 static BOOLEAN
00408 KdbpCmdEvalExpression(
00409     ULONG Argc,
00410     PCHAR Argv[])
00411 {
00412     ULONG i, len;
00413     ULONGLONG Result = 0;
00414     ULONG ul;
00415     LONG l = 0;
00416     BOOLEAN Ok;
00417 
00418     if (Argc < 2)
00419     {
00420         KdbpPrint("?: Argument required\n");
00421         return TRUE;
00422     }
00423 
00424     /* Put the arguments back together */
00425     Argc--;
00426     for (i = 1; i < Argc; i++)
00427     {
00428         len = strlen(Argv[i]);
00429         Argv[i][len] = ' ';
00430     }
00431 
00432     /* Evaluate the expression */
00433     Ok = KdbpEvaluateExpression(Argv[1], sizeof("kdb:> ")-1 + (Argv[1]-Argv[0]), &Result);
00434     if (Ok)
00435     {
00436         if (Result > 0x00000000ffffffffLL)
00437         {
00438             if (Result & 0x8000000000000000LL)
00439                 KdbpPrint("0x%016I64x  %20I64u  %20I64d\n", Result, Result, Result);
00440             else
00441                 KdbpPrint("0x%016I64x  %20I64u\n", Result, Result);
00442         }
00443         else
00444         {
00445             ul = (ULONG)Result;
00446 
00447             if (ul <= 0xff && ul >= 0x80)
00448                 l = (LONG)((CHAR)ul);
00449             else if (ul <= 0xffff && ul >= 0x8000)
00450                 l = (LONG)((SHORT)ul);
00451             else
00452                 l = (LONG)ul;
00453 
00454             if (l < 0)
00455                 KdbpPrint("0x%08lx  %10lu  %10ld\n", ul, ul, l);
00456             else
00457                 KdbpPrint("0x%08lx  %10lu\n", ul, ul);
00458         }
00459     }
00460 
00461     return TRUE;
00462 }
00463 
00464 #ifdef __ROS_DWARF__
00465 
00468 static VOID
00469 KdbpPrintStructInternal
00470 (PROSSYM_INFO Info,
00471  PCHAR Indent,
00472  BOOLEAN DoRead,
00473  PVOID BaseAddress,
00474  PROSSYM_AGGREGATE Aggregate)
00475 {
00476     ULONG i;
00477     ULONGLONG Result;
00478     PROSSYM_AGGREGATE_MEMBER Member;
00479     ULONG IndentLen = strlen(Indent);
00480     ROSSYM_AGGREGATE MemberAggregate = {0 };
00481 
00482     for (i = 0; i < Aggregate->NumElements; i++) {
00483         Member = &Aggregate->Elements[i];
00484         KdbpPrint("%s%p+%x: %s", Indent, ((PCHAR)BaseAddress) + Member->BaseOffset, Member->Size, Member->Name ? Member->Name : "<anoymous>");
00485         if (DoRead) {
00486             if (!strcmp(Member->Type, "_UNICODE_STRING")) {
00487                 KdbpPrint("\"%wZ\"\n", ((PCHAR)BaseAddress) + Member->BaseOffset);
00488                 continue;
00489             } else if (!strcmp(Member->Type, "PUNICODE_STRING")) {
00490                 KdbpPrint("\"%wZ\"\n", *(((PUNICODE_STRING*)((PCHAR)BaseAddress) + Member->BaseOffset)));
00491                 continue;
00492             }
00493             switch (Member->Size) {
00494             case 1:
00495             case 2:
00496             case 4:
00497             case 8: {
00498                 Result = 0;
00499                 if (NT_SUCCESS(KdbpSafeReadMemory(&Result, ((PCHAR)BaseAddress) + Member->BaseOffset, Member->Size))) {
00500                     if (Member->Bits) {
00501                         Result >>= Member->FirstBit;
00502                         Result &= ((1 << Member->Bits) - 1);
00503                     }
00504                     KdbpPrint(" %lx\n", Result);
00505                 }
00506                 else goto readfail;
00507                 break;
00508             }
00509             default: {
00510                 if (Member->Size < 8) {
00511                     if (NT_SUCCESS(KdbpSafeReadMemory(&Result, ((PCHAR)BaseAddress) + Member->BaseOffset, Member->Size))) {
00512                         ULONG j;
00513                         for (j = 0; j < Member->Size; j++) {
00514                             KdbpPrint(" %02x", (int)(Result & 0xff));
00515                             Result >>= 8;
00516                         }
00517                     } else goto readfail;
00518                 } else {
00519                     KdbpPrint(" %s @ %p {\n", Member->Type, ((PCHAR)BaseAddress) + Member->BaseOffset);
00520                     Indent[IndentLen] = ' ';
00521                     if (RosSymAggregate(Info, Member->Type, &MemberAggregate)) {
00522                         KdbpPrintStructInternal(Info, Indent, DoRead, ((PCHAR)BaseAddress) + Member->BaseOffset, &MemberAggregate);
00523                         RosSymFreeAggregate(&MemberAggregate);
00524                     }
00525                     Indent[IndentLen] = 0;
00526                     KdbpPrint("%s}\n", Indent);
00527                 } break;
00528             }
00529             }
00530         } else {
00531         readfail:
00532             if (Member->Size <= 8) {
00533                 KdbpPrint(" ??\n");
00534             } else {
00535                 KdbpPrint(" %s @ %x {\n", Member->Type, Member->BaseOffset);
00536                 Indent[IndentLen] = ' ';
00537                 if (RosSymAggregate(Info, Member->Type, &MemberAggregate)) {
00538                     KdbpPrintStructInternal(Info, Indent, DoRead, BaseAddress, &MemberAggregate);
00539                     RosSymFreeAggregate(&MemberAggregate);
00540                 }
00541                 Indent[IndentLen] = 0;
00542                 KdbpPrint("%s}\n", Indent);
00543             }
00544         }
00545     }
00546 }
00547 
00548 PROSSYM_INFO KdbpSymFindCachedFile(PUNICODE_STRING ModName);
00549 
00550 static BOOLEAN
00551 KdbpCmdPrintStruct(
00552     ULONG Argc,
00553     PCHAR Argv[])
00554 {
00555     ULONG i;
00556     ULONGLONG Result = 0;
00557     PVOID BaseAddress = 0;
00558     ROSSYM_AGGREGATE Aggregate = {0};
00559     UNICODE_STRING ModName = {0};
00560     ANSI_STRING AnsiName = {0};
00561     CHAR Indent[100] = {0};
00562     PROSSYM_INFO Info;
00563 
00564     if (Argc < 3) goto end;
00565     AnsiName.Length = AnsiName.MaximumLength = strlen(Argv[1]);
00566     AnsiName.Buffer = Argv[1];
00567     RtlAnsiStringToUnicodeString(&ModName, &AnsiName, TRUE);
00568     Info = KdbpSymFindCachedFile(&ModName);
00569 
00570     if (!Info || !RosSymAggregate(Info, Argv[2], &Aggregate)) {
00571         DPRINT1("Could not get aggregate\n");
00572         goto end;
00573     }
00574 
00575     // Get an argument for location if it was given
00576     if (Argc > 3) {
00577         ULONG len;
00578         PCHAR ArgStart = Argv[3];
00579         DPRINT1("Trying to get expression\n");
00580         for (i = 3; i < Argc - 1; i++)
00581         {
00582             len = strlen(Argv[i]);
00583             Argv[i][len] = ' ';
00584         }
00585 
00586         /* Evaluate the expression */
00587         DPRINT1("Arg: %s\n", ArgStart);
00588         if (KdbpEvaluateExpression(ArgStart, strlen(ArgStart), &Result)) {
00589             BaseAddress = (PVOID)(ULONG_PTR)Result;
00590             DPRINT1("BaseAddress: %p\n", BaseAddress);
00591         }
00592     }
00593     DPRINT1("BaseAddress %p\n", BaseAddress);
00594     KdbpPrintStructInternal(Info, Indent, !!BaseAddress, BaseAddress, &Aggregate);
00595 end:
00596     RosSymFreeAggregate(&Aggregate);
00597     RtlFreeUnicodeString(&ModName);
00598     return TRUE;
00599 }
00600 #endif
00601 
00604 static BOOLEAN
00605 KdbpCmdFilter(
00606     ULONG Argc,
00607     PCHAR Argv[])
00608 {
00609     ULONG i, j, ComponentId, Level;
00610     ULONG set = DPFLTR_MASK, clear = DPFLTR_MASK;
00611     PCHAR pend;
00612     LPCSTR opt, p;
00613 
00614     static struct
00615     {
00616         LPCSTR Name;
00617         ULONG Level;
00618     }
00619     debug_classes[] =
00620     {
00621         { "error", 1 << DPFLTR_ERROR_LEVEL },
00622         { "warning", 1 << DPFLTR_WARNING_LEVEL },
00623         { "trace", 1 << DPFLTR_TRACE_LEVEL },
00624         { "info", 1 << DPFLTR_INFO_LEVEL },
00625     };
00626 
00627     for (i = 1; i < Argc; i++)
00628     {
00629         opt = Argv[i];
00630         p = opt + strcspn(opt, "+-");
00631         if (!p[0]) p = opt; /* assume it's a debug channel name */
00632 
00633         if (p > opt)
00634         {
00635             for (j = 0; j < sizeof(debug_classes) / sizeof(debug_classes[0]); j++)
00636             {
00637                 SIZE_T len = strlen(debug_classes[j].Name);
00638                 if (len != (p - opt))
00639                     continue;
00640                 if (_strnicmp(opt, debug_classes[j].Name, len) == 0) /* found it */
00641                 {
00642                     if (*p == '+')
00643                         set |= debug_classes[j].Level;
00644                     else
00645                         clear |= debug_classes[j].Level;
00646                     break;
00647                 }
00648             }
00649             if (j == sizeof(debug_classes) / sizeof(debug_classes[0]))
00650             {
00651                 Level = strtoul(opt, &pend, 0);
00652                 if (pend != p)
00653                 {
00654                     KdbpPrint("filter: bad class name '%.*s'\n", p - opt, opt);
00655                     continue;
00656                 }
00657                 if (*p == '+')
00658                     set |= Level;
00659                 else
00660                     clear |= Level;
00661             }
00662         }
00663         else
00664         {
00665             if (*p == '-')
00666                 clear = MAXULONG;
00667             else
00668                 set = MAXULONG;
00669         }
00670         if (*p == '+' || *p == '-')
00671             p++;
00672 
00673         if (!KdbpGetComponentId(p, &ComponentId))
00674         {
00675             KdbpPrint("filter: '%s' is not a valid component name!\n", p);
00676             return TRUE;
00677         }
00678 
00679         /* Get current mask value */
00680         NtSetDebugFilterState(ComponentId, set, TRUE);
00681         NtSetDebugFilterState(ComponentId, clear, FALSE);
00682     }
00683 
00684     return TRUE;
00685 }
00686 
00690 static BOOLEAN
00691 KdbpCmdDisassembleX(
00692     ULONG Argc,
00693     PCHAR Argv[])
00694 {
00695     ULONG Count;
00696     ULONG ul;
00697     INT i;
00698     ULONGLONG Result = 0;
00699     ULONG_PTR Address = KdbCurrentTrapFrame->Tf.Eip;
00700     LONG InstLen;
00701 
00702     if (Argv[0][0] == 'x') /* display memory */
00703         Count = 16;
00704     else /* disassemble */
00705         Count = 10;
00706 
00707     if (Argc >= 2)
00708     {
00709         /* Check for [L count] part */
00710         ul = 0;
00711         if (strcmp(Argv[Argc-2], "L") == 0)
00712         {
00713             ul = strtoul(Argv[Argc-1], NULL, 0);
00714             if (ul > 0)
00715             {
00716                 Count = ul;
00717                 Argc -= 2;
00718             }
00719         }
00720         else if (Argv[Argc-1][0] == 'L')
00721         {
00722             ul = strtoul(Argv[Argc-1] + 1, NULL, 0);
00723             if (ul > 0)
00724             {
00725                 Count = ul;
00726                 Argc--;
00727             }
00728         }
00729 
00730         /* Put the remaining arguments back together */
00731         Argc--;
00732         for (ul = 1; ul < Argc; ul++)
00733         {
00734             Argv[ul][strlen(Argv[ul])] = ' ';
00735         }
00736         Argc++;
00737     }
00738 
00739     /* Evaluate the expression */
00740     if (Argc > 1)
00741     {
00742         if (!KdbpEvaluateExpression(Argv[1], sizeof("kdb:> ")-1 + (Argv[1]-Argv[0]), &Result))
00743             return TRUE;
00744 
00745         if (Result > (ULONGLONG)(~((ULONG_PTR)0)))
00746             KdbpPrint("Warning: Address %I64x is beeing truncated\n",Result);
00747 
00748         Address = (ULONG_PTR)Result;
00749     }
00750     else if (Argv[0][0] == 'x')
00751     {
00752         KdbpPrint("x: Address argument required.\n");
00753         return TRUE;
00754     }
00755 
00756     if (Argv[0][0] == 'x')
00757     {
00758         /* Display dwords */
00759         ul = 0;
00760 
00761         while (Count > 0)
00762         {
00763             if (!KdbSymPrintAddress((PVOID)Address, NULL))
00764                 KdbpPrint("<%x>:", Address);
00765             else
00766                 KdbpPrint(":");
00767 
00768             i = min(4, Count);
00769             Count -= i;
00770 
00771             while (--i >= 0)
00772             {
00773                 if (!NT_SUCCESS(KdbpSafeReadMemory(&ul, (PVOID)Address, sizeof(ul))))
00774                     KdbpPrint(" ????????");
00775                 else
00776                     KdbpPrint(" %08x", ul);
00777 
00778                 Address += sizeof(ul);
00779             }
00780 
00781             KdbpPrint("\n");
00782         }
00783     }
00784     else
00785     {
00786         /* Disassemble */
00787         while (Count-- > 0)
00788         {
00789             if (!KdbSymPrintAddress((PVOID)Address, NULL))
00790                 KdbpPrint("<%08x>: ", Address);
00791             else
00792                 KdbpPrint(": ");
00793 
00794             InstLen = KdbpDisassemble(Address, KdbUseIntelSyntax);
00795             if (InstLen < 0)
00796             {
00797                 KdbpPrint("<INVALID>\n");
00798                 return TRUE;
00799             }
00800 
00801             KdbpPrint("\n");
00802             Address += InstLen;
00803         }
00804     }
00805 
00806     return TRUE;
00807 }
00808 
00811 static BOOLEAN
00812 KdbpCmdRegs(
00813     ULONG Argc,
00814     PCHAR Argv[])
00815 {
00816     PKTRAP_FRAME Tf = &KdbCurrentTrapFrame->Tf;
00817     INT i;
00818     static const PCHAR EflagsBits[32] = { " CF", NULL, " PF", " BIT3", " AF", " BIT5",
00819                                           " ZF", " SF", " TF", " IF", " DF", " OF",
00820                                           NULL, NULL, " NT", " BIT15", " RF", " VF",
00821                                           " AC", " VIF", " VIP", " ID", " BIT22",
00822                                           " BIT23", " BIT24", " BIT25", " BIT26",
00823                                           " BIT27", " BIT28", " BIT29", " BIT30",
00824                                           " BIT31" };
00825 
00826     if (Argv[0][0] == 'r') /* regs */
00827     {
00828         KdbpPrint("CS:EIP  0x%04x:0x%08x\n"
00829                   "SS:ESP  0x%04x:0x%08x\n"
00830                   "   EAX  0x%08x   EBX  0x%08x\n"
00831                   "   ECX  0x%08x   EDX  0x%08x\n"
00832                   "   ESI  0x%08x   EDI  0x%08x\n"
00833                   "   EBP  0x%08x\n",
00834                   Tf->SegCs & 0xFFFF, Tf->Eip,
00835                   Tf->HardwareSegSs, Tf->HardwareEsp,
00836                   Tf->Eax, Tf->Ebx,
00837                   Tf->Ecx, Tf->Edx,
00838                   Tf->Esi, Tf->Edi,
00839                   Tf->Ebp);
00840         KdbpPrint("EFLAGS  0x%08x ", Tf->EFlags);
00841 
00842         for (i = 0; i < 32; i++)
00843         {
00844             if (i == 1)
00845             {
00846                 if ((Tf->EFlags & (1 << 1)) == 0)
00847                     KdbpPrint(" !BIT1");
00848             }
00849             else if (i == 12)
00850             {
00851                 KdbpPrint(" IOPL%d", (Tf->EFlags >> 12) & 3);
00852             }
00853             else if (i == 13)
00854             {
00855             }
00856             else if ((Tf->EFlags & (1 << i)) != 0)
00857             {
00858                 KdbpPrint(EflagsBits[i]);
00859             }
00860         }
00861 
00862         KdbpPrint("\n");
00863     }
00864     else if (Argv[0][0] == 'c') /* cregs */
00865     {
00866         ULONG Cr0, Cr2, Cr3, Cr4;
00867         KDESCRIPTOR Gdtr, Idtr;
00868         USHORT Ldtr;
00869         static const PCHAR Cr0Bits[32] = { " PE", " MP", " EM", " TS", " ET", " NE", NULL, NULL,
00870                                            NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
00871                                            " WP", NULL, " AM", NULL, NULL, NULL, NULL, NULL,
00872                                            NULL, NULL, NULL, NULL, NULL, " NW", " CD", " PG" };
00873         static const PCHAR Cr4Bits[32] = { " VME", " PVI", " TSD", " DE", " PSE", " PAE", " MCE", " PGE",
00874                                            " PCE", " OSFXSR", " OSXMMEXCPT", NULL, NULL, NULL, NULL, NULL,
00875                                            NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
00876                                            NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
00877 
00878         Cr0 = KdbCurrentTrapFrame->Cr0;
00879         Cr2 = KdbCurrentTrapFrame->Cr2;
00880         Cr3 = KdbCurrentTrapFrame->Cr3;
00881         Cr4 = KdbCurrentTrapFrame->Cr4;
00882 
00883         /* Get descriptor table regs */
00884         Ke386GetGlobalDescriptorTable(&Gdtr.Limit);
00885         Ldtr = Ke386GetLocalDescriptorTable();
00886         __sidt(&Idtr.Limit);
00887 
00888         /* Display the control registers */
00889         KdbpPrint("CR0  0x%08x ", Cr0);
00890 
00891         for (i = 0; i < 32; i++)
00892         {
00893             if (!Cr0Bits[i])
00894                 continue;
00895 
00896             if ((Cr0 & (1 << i)) != 0)
00897                 KdbpPrint(Cr0Bits[i]);
00898         }
00899 
00900         KdbpPrint("\nCR2  0x%08x\n", Cr2);
00901         KdbpPrint("CR3  0x%08x  Pagedir-Base 0x%08x %s%s\n", Cr3, (Cr3 & 0xfffff000),
00902                   (Cr3 & (1 << 3)) ? " PWT" : "", (Cr3 & (1 << 4)) ? " PCD" : "" );
00903         KdbpPrint("CR4  0x%08x ", Cr4);
00904 
00905         for (i = 0; i < 32; i++)
00906         {
00907             if (!Cr4Bits[i])
00908                 continue;
00909 
00910             if ((Cr4 & (1 << i)) != 0)
00911                 KdbpPrint(Cr4Bits[i]);
00912         }
00913 
00914         /* Display the descriptor table regs */
00915         KdbpPrint("\nGDTR  Base 0x%08x  Size 0x%04x\n", Gdtr.Base, Gdtr.Limit);
00916         KdbpPrint("LDTR  0x%04x\n", Ldtr);
00917         KdbpPrint("IDTR  Base 0x%08x  Size 0x%04x\n", Idtr.Base, Idtr.Limit);
00918     }
00919     else if (Argv[0][0] == 's') /* sregs */
00920     {
00921         KdbpPrint("CS  0x%04x  Index 0x%04x  %cDT RPL%d\n",
00922                   Tf->SegCs & 0xffff, (Tf->SegCs & 0xffff) >> 3,
00923                   (Tf->SegCs & (1 << 2)) ? 'L' : 'G', Tf->SegCs & 3);
00924         KdbpPrint("DS  0x%04x  Index 0x%04x  %cDT RPL%d\n",
00925                   Tf->SegDs, Tf->SegDs >> 3, (Tf->SegDs & (1 << 2)) ? 'L' : 'G', Tf->SegDs & 3);
00926         KdbpPrint("ES  0x%04x  Index 0x%04x  %cDT RPL%d\n",
00927                   Tf->SegEs, Tf->SegEs >> 3, (Tf->SegEs & (1 << 2)) ? 'L' : 'G', Tf->SegEs & 3);
00928         KdbpPrint("FS  0x%04x  Index 0x%04x  %cDT RPL%d\n",
00929                   Tf->SegFs, Tf->SegFs >> 3, (Tf->SegFs & (1 << 2)) ? 'L' : 'G', Tf->SegFs & 3);
00930         KdbpPrint("GS  0x%04x  Index 0x%04x  %cDT RPL%d\n",
00931                   Tf->SegGs, Tf->SegGs >> 3, (Tf->SegGs & (1 << 2)) ? 'L' : 'G', Tf->SegGs & 3);
00932         KdbpPrint("SS  0x%04x  Index 0x%04x  %cDT RPL%d\n",
00933                   Tf->HardwareSegSs, Tf->HardwareSegSs >> 3, (Tf->HardwareSegSs & (1 << 2)) ? 'L' : 'G', Tf->HardwareSegSs & 3);
00934     }
00935     else /* dregs */
00936     {
00937         ASSERT(Argv[0][0] == 'd');
00938         KdbpPrint("DR0  0x%08x\n"
00939                   "DR1  0x%08x\n"
00940                   "DR2  0x%08x\n"
00941                   "DR3  0x%08x\n"
00942                   "DR6  0x%08x\n"
00943                   "DR7  0x%08x\n",
00944                   Tf->Dr0, Tf->Dr1, Tf->Dr2, Tf->Dr3,
00945                   Tf->Dr6, Tf->Dr7);
00946     }
00947 
00948     return TRUE;
00949 }
00950 
00951 static BOOLEAN
00952 KdbpTrapFrameFromPrevTss(
00953     PKTRAP_FRAME TrapFrame)
00954 {
00955     ULONG_PTR Eip, Ebp;
00956     KDESCRIPTOR Gdtr;
00957     KGDTENTRY Desc;
00958     USHORT Sel;
00959     PKTSS Tss;
00960 
00961     Ke386GetGlobalDescriptorTable(&Gdtr.Limit);
00962     Sel = Ke386GetTr();
00963 
00964     if ((Sel & (sizeof(KGDTENTRY) - 1)) ||
00965         (Sel < sizeof(KGDTENTRY)) ||
00966         (Sel + sizeof(KGDTENTRY) - 1 > Gdtr.Limit))
00967         return FALSE;
00968 
00969     if (!NT_SUCCESS(KdbpSafeReadMemory(&Desc,
00970                                        (PVOID)(Gdtr.Base + Sel),
00971                                        sizeof(KGDTENTRY))))
00972         return FALSE;
00973 
00974     if (Desc.HighWord.Bits.Type != 0xB)
00975         return FALSE;
00976 
00977     Tss = (PKTSS)(ULONG_PTR)(Desc.BaseLow |
00978                              Desc.HighWord.Bytes.BaseMid << 16 |
00979                              Desc.HighWord.Bytes.BaseHi << 24);
00980 
00981     if (!NT_SUCCESS(KdbpSafeReadMemory(&Sel,
00982                                        (PVOID)&Tss->Backlink,
00983                                        sizeof(USHORT))))
00984         return FALSE;
00985 
00986     if ((Sel & (sizeof(KGDTENTRY) - 1)) ||
00987         (Sel < sizeof(KGDTENTRY)) ||
00988         (Sel + sizeof(KGDTENTRY) - 1 > Gdtr.Limit))
00989         return FALSE;
00990 
00991     if (!NT_SUCCESS(KdbpSafeReadMemory(&Desc,
00992                                        (PVOID)(Gdtr.Base + Sel),
00993                                        sizeof(KGDTENTRY))))
00994         return FALSE;
00995 
00996     if (Desc.HighWord.Bits.Type != 0xB)
00997         return FALSE;
00998 
00999     Tss = (PKTSS)(ULONG_PTR)(Desc.BaseLow |
01000                              Desc.HighWord.Bytes.BaseMid << 16 |
01001                              Desc.HighWord.Bytes.BaseHi << 24);
01002 
01003     if (!NT_SUCCESS(KdbpSafeReadMemory(&Eip,
01004                                        (PVOID)&Tss->Eip,
01005                                        sizeof(ULONG_PTR))))
01006         return FALSE;
01007 
01008     if (!NT_SUCCESS(KdbpSafeReadMemory(&Ebp,
01009                                        (PVOID)&Tss->Ebp,
01010                                        sizeof(ULONG_PTR))))
01011         return FALSE;
01012 
01013     TrapFrame->Eip = Eip;
01014     TrapFrame->Ebp = Ebp;
01015     return TRUE;
01016 }
01017 
01018 VOID __cdecl KiTrap02(VOID);
01019 VOID FASTCALL KiTrap03Handler(IN PKTRAP_FRAME);
01020 VOID __cdecl KiTrap08(VOID);
01021 VOID __cdecl KiTrap09(VOID);
01022 
01023 static BOOLEAN
01024 KdbpInNmiOrDoubleFaultHandler(
01025     ULONG_PTR Address)
01026 {
01027     return (Address > (ULONG_PTR)KiTrap02 && Address < (ULONG_PTR)KiTrap03Handler) ||
01028            (Address > (ULONG_PTR)KiTrap08 && Address < (ULONG_PTR)KiTrap09);
01029 }
01030 
01033 static BOOLEAN
01034 KdbpCmdBackTrace(
01035     ULONG Argc,
01036     PCHAR Argv[])
01037 {
01038     ULONG ul;
01039     ULONGLONG Result = 0;
01040     ULONG_PTR Frame = KdbCurrentTrapFrame->Tf.Ebp;
01041     ULONG_PTR Address;
01042     KTRAP_FRAME TrapFrame;
01043 
01044     if (Argc >= 2)
01045     {
01046         /* Check for [L count] part */
01047         ul = 0;
01048 
01049         if (strcmp(Argv[Argc-2], "L") == 0)
01050         {
01051             ul = strtoul(Argv[Argc-1], NULL, 0);
01052             if (ul > 0)
01053             {
01054                 Argc -= 2;
01055             }
01056         }
01057         else if (Argv[Argc-1][0] == 'L')
01058         {
01059             ul = strtoul(Argv[Argc-1] + 1, NULL, 0);
01060             if (ul > 0)
01061             {
01062                 Argc--;
01063             }
01064         }
01065 
01066         /* Put the remaining arguments back together */
01067         Argc--;
01068         for (ul = 1; ul < Argc; ul++)
01069         {
01070             Argv[ul][strlen(Argv[ul])] = ' ';
01071         }
01072         Argc++;
01073     }
01074 
01075     /* Check if frame addr or thread id is given. */
01076     if (Argc > 1)
01077     {
01078         if (Argv[1][0] == '*')
01079         {
01080             Argv[1]++;
01081 
01082             /* Evaluate the expression */
01083             if (!KdbpEvaluateExpression(Argv[1], sizeof("kdb:> ")-1 + (Argv[1]-Argv[0]), &Result))
01084                 return TRUE;
01085 
01086             if (Result > (ULONGLONG)(~((ULONG_PTR)0)))
01087                 KdbpPrint("Warning: Address %I64x is beeing truncated\n",Result);
01088 
01089             Frame = (ULONG_PTR)Result;
01090         }
01091         else
01092         {
01093             KdbpPrint("Thread backtrace not supported yet!\n");
01094             return TRUE;
01095         }
01096     }
01097     else
01098     {
01099         KdbpPrint("Eip:\n");
01100 
01101         /* Try printing the function at EIP */
01102         if (!KdbSymPrintAddress((PVOID)KdbCurrentTrapFrame->Tf.Eip, &KdbCurrentTrapFrame->Tf))
01103             KdbpPrint("<%08x>\n", KdbCurrentTrapFrame->Tf.Eip);
01104         else
01105             KdbpPrint("\n");
01106     }
01107 
01108     TrapFrame = KdbCurrentTrapFrame->Tf;
01109     KdbpPrint("Frames:\n");
01110 
01111     for (;;)
01112     {
01113         BOOLEAN GotNextFrame;
01114 
01115         if (Frame == 0)
01116             break;
01117 
01118         if (!NT_SUCCESS(KdbpSafeReadMemory(&Address, (PVOID)(Frame + sizeof(ULONG_PTR)), sizeof (ULONG_PTR))))
01119         {
01120             KdbpPrint("Couldn't access memory at 0x%p!\n", Frame + sizeof(ULONG_PTR));
01121             break;
01122         }
01123 
01124         if ((GotNextFrame = NT_SUCCESS(KdbpSafeReadMemory(&Frame, (PVOID)Frame, sizeof (ULONG_PTR)))))
01125             TrapFrame.Ebp = Frame;
01126 
01127         /* Print the location of the call instruction */
01128         if (!KdbSymPrintAddress((PVOID)(Address - 5), &TrapFrame))
01129             KdbpPrint("<%08x>\n", Address);
01130         else
01131             KdbpPrint("\n");
01132 
01133         if (KdbOutputAborted) break;
01134 
01135         if (Address == 0)
01136             break;
01137 
01138         if (KdbpInNmiOrDoubleFaultHandler(Address))
01139         {
01140             if ((GotNextFrame = KdbpTrapFrameFromPrevTss(&TrapFrame)))
01141             {
01142                 Address = TrapFrame.Eip;
01143                 Frame = TrapFrame.Ebp;
01144 
01145                 if (!KdbSymPrintAddress((PVOID)Address, &TrapFrame))
01146                     KdbpPrint("<%08x>\n", Address);
01147                 else
01148                     KdbpPrint("\n");
01149             }
01150         }
01151 
01152         if (!GotNextFrame)
01153         {
01154             KdbpPrint("Couldn't access memory at 0x%p!\n", Frame);
01155             break;
01156         }
01157     }
01158 
01159     return TRUE;
01160 }
01161 
01164 static BOOLEAN
01165 KdbpCmdContinue(
01166     ULONG Argc,
01167     PCHAR Argv[])
01168 {
01169     /* Exit the main loop */
01170     return FALSE;
01171 }
01172 
01175 static BOOLEAN
01176 KdbpCmdStep(
01177     ULONG Argc,
01178     PCHAR Argv[])
01179 {
01180     ULONG Count = 1;
01181 
01182     if (Argc > 1)
01183     {
01184         Count = strtoul(Argv[1], NULL, 0);
01185         if (Count == 0)
01186         {
01187             KdbpPrint("%s: Integer argument required\n", Argv[0]);
01188             return TRUE;
01189         }
01190     }
01191 
01192     if (Argv[0][0] == 'n')
01193         KdbSingleStepOver = TRUE;
01194     else
01195         KdbSingleStepOver = FALSE;
01196 
01197     /* Set the number of single steps and return to the interrupted code. */
01198     KdbNumSingleSteps = Count;
01199 
01200     return FALSE;
01201 }
01202 
01205 static BOOLEAN
01206 KdbpCmdBreakPointList(
01207     ULONG Argc,
01208     PCHAR Argv[])
01209 {
01210     LONG l;
01211     ULONG_PTR Address = 0;
01212     KDB_BREAKPOINT_TYPE Type = 0;
01213     KDB_ACCESS_TYPE AccessType = 0;
01214     UCHAR Size = 0;
01215     UCHAR DebugReg = 0;
01216     BOOLEAN Enabled = FALSE;
01217     BOOLEAN Global = FALSE;
01218     PEPROCESS Process = NULL;
01219     PCHAR str1, str2, ConditionExpr, GlobalOrLocal;
01220     CHAR Buffer[20];
01221 
01222     l = KdbpGetNextBreakPointNr(0);
01223     if (l < 0)
01224     {
01225         KdbpPrint("No breakpoints.\n");
01226         return TRUE;
01227     }
01228 
01229     KdbpPrint("Breakpoints:\n");
01230     do
01231     {
01232         if (!KdbpGetBreakPointInfo(l, &Address, &Type, &Size, &AccessType, &DebugReg,
01233                                    &Enabled, &Global, &Process, &ConditionExpr))
01234         {
01235             continue;
01236         }
01237 
01238         if (l == KdbLastBreakPointNr)
01239         {
01240             str1 = "\x1b[1m*";
01241             str2 = "\x1b[0m";
01242         }
01243         else
01244         {
01245             str1 = " ";
01246             str2 = "";
01247         }
01248 
01249         if (Global)
01250         {
01251             GlobalOrLocal = "  global";
01252         }
01253         else
01254         {
01255             GlobalOrLocal = Buffer;
01256             sprintf(Buffer, "  PID 0x%08lx",
01257                     (ULONG)(Process ? Process->UniqueProcessId : INVALID_HANDLE_VALUE));
01258         }
01259 
01260         if (Type == KdbBreakPointSoftware || Type == KdbBreakPointTemporary)
01261         {
01262             KdbpPrint(" %s%03d  BPX  0x%08x%s%s%s%s%s\n",
01263                       str1, l, Address,
01264                       Enabled ? "" : "  disabled",
01265                       GlobalOrLocal,
01266                       ConditionExpr ? "  IF " : "",
01267                       ConditionExpr ? ConditionExpr : "",
01268                       str2);
01269         }
01270         else if (Type == KdbBreakPointHardware)
01271         {
01272             if (!Enabled)
01273             {
01274                 KdbpPrint(" %s%03d  BPM  0x%08x  %-5s %-5s  disabled%s%s%s%s\n", str1, l, Address,
01275                           KDB_ACCESS_TYPE_TO_STRING(AccessType),
01276                           Size == 1 ? "byte" : (Size == 2 ? "word" : "dword"),
01277                           GlobalOrLocal,
01278                           ConditionExpr ? "  IF " : "",
01279                           ConditionExpr ? ConditionExpr : "",
01280                           str2);
01281             }
01282             else
01283             {
01284                 KdbpPrint(" %s%03d  BPM  0x%08x  %-5s %-5s  DR%d%s%s%s%s\n", str1, l, Address,
01285                           KDB_ACCESS_TYPE_TO_STRING(AccessType),
01286                           Size == 1 ? "byte" : (Size == 2 ? "word" : "dword"),
01287                           DebugReg,
01288                           GlobalOrLocal,
01289                           ConditionExpr ? "  IF " : "",
01290                           ConditionExpr ? ConditionExpr : "",
01291                           str2);
01292             }
01293         }
01294     }
01295     while ((l = KdbpGetNextBreakPointNr(l+1)) >= 0);
01296 
01297     return TRUE;
01298 }
01299 
01302 static BOOLEAN
01303 KdbpCmdEnableDisableClearBreakPoint(
01304     ULONG Argc,
01305     PCHAR Argv[])
01306 {
01307     PCHAR pend;
01308     ULONG BreakPointNr;
01309 
01310     if (Argc < 2)
01311     {
01312         KdbpPrint("%s: argument required\n", Argv[0]);
01313         return TRUE;
01314     }
01315 
01316     pend = Argv[1];
01317     BreakPointNr = strtoul(Argv[1], &pend, 0);
01318     if (pend == Argv[1] || *pend != '\0')
01319     {
01320         KdbpPrint("%s: integer argument required\n", Argv[0]);
01321         return TRUE;
01322     }
01323 
01324     if (Argv[0][1] == 'e') /* enable */
01325     {
01326         KdbpEnableBreakPoint(BreakPointNr, NULL);
01327     }
01328     else if (Argv [0][1] == 'd') /* disable */
01329     {
01330         KdbpDisableBreakPoint(BreakPointNr, NULL);
01331     }
01332     else /* clear */
01333     {
01334         ASSERT(Argv[0][1] == 'c');
01335         KdbpDeleteBreakPoint(BreakPointNr, NULL);
01336     }
01337 
01338     return TRUE;
01339 }
01340 
01343 static BOOLEAN
01344 KdbpCmdBreakPoint(ULONG Argc, PCHAR Argv[])
01345 {
01346     ULONGLONG Result = 0;
01347     ULONG_PTR Address;
01348     KDB_BREAKPOINT_TYPE Type;
01349     UCHAR Size = 0;
01350     KDB_ACCESS_TYPE AccessType = 0;
01351     ULONG AddressArgIndex, i;
01352     LONG ConditionArgIndex;
01353     BOOLEAN Global = TRUE;
01354 
01355     if (Argv[0][2] == 'x') /* software breakpoint */
01356     {
01357         if (Argc < 2)
01358         {
01359             KdbpPrint("bpx: Address argument required.\n");
01360             return TRUE;
01361         }
01362 
01363         AddressArgIndex = 1;
01364         Type = KdbBreakPointSoftware;
01365     }
01366     else /* memory breakpoint */
01367     {
01368         ASSERT(Argv[0][2] == 'm');
01369 
01370         if (Argc < 2)
01371         {
01372             KdbpPrint("bpm: Access type argument required (one of r, w, rw, x)\n");
01373             return TRUE;
01374         }
01375 
01376         if (_stricmp(Argv[1], "x") == 0)
01377             AccessType = KdbAccessExec;
01378         else if (_stricmp(Argv[1], "r") == 0)
01379             AccessType = KdbAccessRead;
01380         else if (_stricmp(Argv[1], "w") == 0)
01381             AccessType = KdbAccessWrite;
01382         else if (_stricmp(Argv[1], "rw") == 0)
01383             AccessType = KdbAccessReadWrite;
01384         else
01385         {
01386             KdbpPrint("bpm: Unknown access type '%s'\n", Argv[1]);
01387             return TRUE;
01388         }
01389 
01390         if (Argc < 3)
01391         {
01392             KdbpPrint("bpm: %s argument required.\n", AccessType == KdbAccessExec ? "Address" : "Memory size");
01393             return TRUE;
01394         }
01395 
01396         AddressArgIndex = 3;
01397         if (_stricmp(Argv[2], "byte") == 0)
01398             Size = 1;
01399         else if (_stricmp(Argv[2], "word") == 0)
01400             Size = 2;
01401         else if (_stricmp(Argv[2], "dword") == 0)
01402             Size = 4;
01403         else if (AccessType == KdbAccessExec)
01404         {
01405             Size = 1;
01406             AddressArgIndex--;
01407         }
01408         else
01409         {
01410             KdbpPrint("bpm: Unknown memory size '%s'\n", Argv[2]);
01411             return TRUE;
01412         }
01413 
01414         if (Argc <= AddressArgIndex)
01415         {
01416             KdbpPrint("bpm: Address argument required.\n");
01417             return TRUE;
01418         }
01419 
01420         Type = KdbBreakPointHardware;
01421     }
01422 
01423     /* Put the arguments back together */
01424     ConditionArgIndex = -1;
01425     for (i = AddressArgIndex; i < (Argc-1); i++)
01426     {
01427         if (strcmp(Argv[i+1], "IF") == 0) /* IF found */
01428         {
01429             ConditionArgIndex = i + 2;
01430             if ((ULONG)ConditionArgIndex >= Argc)
01431             {
01432                 KdbpPrint("%s: IF requires condition expression.\n", Argv[0]);
01433                 return TRUE;
01434             }
01435 
01436             for (i = ConditionArgIndex; i < (Argc-1); i++)
01437                 Argv[i][strlen(Argv[i])] = ' ';
01438 
01439             break;
01440         }
01441 
01442         Argv[i][strlen(Argv[i])] = ' ';
01443     }
01444 
01445     /* Evaluate the address expression */
01446     if (!KdbpEvaluateExpression(Argv[AddressArgIndex],
01447                                 sizeof("kdb:> ")-1 + (Argv[AddressArgIndex]-Argv[0]),
01448                                 &Result))
01449     {
01450         return TRUE;
01451     }
01452 
01453     if (Result > (ULONGLONG)(~((ULONG_PTR)0)))
01454         KdbpPrint("%s: Warning: Address %I64x is beeing truncated\n", Argv[0],Result);
01455 
01456     Address = (ULONG_PTR)Result;
01457 
01458     KdbpInsertBreakPoint(Address, Type, Size, AccessType,
01459                          (ConditionArgIndex < 0) ? NULL : Argv[ConditionArgIndex],
01460                          Global, NULL);
01461 
01462     return TRUE;
01463 }
01464 
01467 static BOOLEAN
01468 KdbpCmdThread(
01469     ULONG Argc,
01470     PCHAR Argv[])
01471 {
01472     PLIST_ENTRY Entry;
01473     PETHREAD Thread = NULL;
01474     PEPROCESS Process = NULL;
01475     BOOLEAN ReferencedThread = FALSE, ReferencedProcess = FALSE;
01476     PULONG Esp;
01477     PULONG Ebp;
01478     ULONG Eip;
01479     ULONG ul = 0;
01480     PCHAR State, pend, str1, str2;
01481     static const PCHAR ThreadStateToString[DeferredReady+1] =
01482     {
01483         "Initialized", "Ready", "Running",
01484         "Standby", "Terminated", "Waiting",
01485         "Transition", "DeferredReady"
01486     };
01487 
01488     ASSERT(KdbCurrentProcess);
01489 
01490     if (Argc >= 2 && _stricmp(Argv[1], "list") == 0)
01491     {
01492         Process = KdbCurrentProcess;
01493 
01494         if (Argc >= 3)
01495         {
01496             ul = strtoul(Argv[2], &pend, 0);
01497             if (Argv[2] == pend)
01498             {
01499                 KdbpPrint("thread: '%s' is not a valid process id!\n", Argv[2]);
01500                 return TRUE;
01501             }
01502 
01503             if (!NT_SUCCESS(PsLookupProcessByProcessId((PVOID)ul, &Process)))
01504             {
01505                 KdbpPrint("thread: Invalid process id!\n");
01506                 return TRUE;
01507             }
01508 
01509             /* Remember our reference */
01510             ReferencedProcess = TRUE;
01511         }
01512 
01513         Entry = Process->ThreadListHead.Flink;
01514         if (Entry == &Process->ThreadListHead)
01515         {
01516             if (Argc >= 3)
01517                 KdbpPrint("No threads in process 0x%08x!\n", ul);
01518             else
01519                 KdbpPrint("No threads in current process!\n");
01520 
01521             if (ReferencedProcess)
01522                 ObDereferenceObject(Process);
01523 
01524             return TRUE;
01525         }
01526 
01527         KdbpPrint("  TID         State        Prior.  Affinity    EBP         EIP\n");
01528         do
01529         {
01530             Thread = CONTAINING_RECORD(Entry, ETHREAD, ThreadListEntry);
01531 
01532             if (Thread == KdbCurrentThread)
01533             {
01534                 str1 = "\x1b[1m*";
01535                 str2 = "\x1b[0m";
01536             }
01537             else
01538             {
01539                 str1 = " ";
01540                 str2 = "";
01541             }
01542 
01543             if (!Thread->Tcb.InitialStack)
01544             {
01545                 /* Thread has no kernel stack (probably terminated) */
01546                 Esp = Ebp = NULL;
01547                 Eip = 0;
01548             }
01549             else if (Thread->Tcb.TrapFrame)
01550             {
01551                 if (Thread->Tcb.TrapFrame->PreviousPreviousMode == KernelMode)
01552                     Esp = (PULONG)Thread->Tcb.TrapFrame->TempEsp;
01553                 else
01554                     Esp = (PULONG)Thread->Tcb.TrapFrame->HardwareEsp;
01555 
01556                 Ebp = (PULONG)Thread->Tcb.TrapFrame->Ebp;
01557                 Eip = Thread->Tcb.TrapFrame->Eip;
01558             }
01559             else
01560             {
01561                 Esp = (PULONG)Thread->Tcb.KernelStack;
01562                 Ebp = (PULONG)Esp[4];
01563                 Eip = 0;
01564 
01565                 if (Ebp) /* FIXME: Should we attach to the process to read Ebp[1]? */
01566                     KdbpSafeReadMemory(&Eip, Ebp + 1, sizeof (Eip));
01567             }
01568 
01569             if (Thread->Tcb.State < (DeferredReady + 1))
01570                 State = ThreadStateToString[Thread->Tcb.State];
01571             else
01572                 State = "Unknown";
01573 
01574             KdbpPrint(" %s0x%08x  %-11s  %3d     0x%08x  0x%08x  0x%08x%s\n",
01575                       str1,
01576                       Thread->Cid.UniqueThread,
01577                       State,
01578                       Thread->Tcb.Priority,
01579                       Thread->Tcb.Affinity,
01580                       Ebp,
01581                       Eip,
01582                       str2);
01583 
01584             Entry = Entry->Flink;
01585         }
01586         while (Entry != &Process->ThreadListHead);
01587 
01588         /* Release our reference, if any */
01589         if (ReferencedProcess)
01590             ObDereferenceObject(Process);
01591     }
01592     else if (Argc >= 2 && _stricmp(Argv[1], "attach") == 0)
01593     {
01594         if (Argc < 3)
01595         {
01596             KdbpPrint("thread attach: thread id argument required!\n");
01597             return TRUE;
01598         }
01599 
01600         ul = strtoul(Argv[2], &pend, 0);
01601         if (Argv[2] == pend)
01602         {
01603             KdbpPrint("thread attach: '%s' is not a valid thread id!\n", Argv[2]);
01604             return TRUE;
01605         }
01606 
01607         if (!KdbpAttachToThread((PVOID)ul))
01608         {
01609             return TRUE;
01610         }
01611 
01612         KdbpPrint("Attached to thread 0x%08x.\n", ul);
01613     }
01614     else
01615     {
01616         Thread = KdbCurrentThread;
01617 
01618         if (Argc >= 2)
01619         {
01620             ul = strtoul(Argv[1], &pend, 0);
01621             if (Argv[1] == pend)
01622             {
01623                 KdbpPrint("thread: '%s' is not a valid thread id!\n", Argv[1]);
01624                 return TRUE;
01625             }
01626 
01627             if (!NT_SUCCESS(PsLookupThreadByThreadId((PVOID)ul, &Thread)))
01628             {
01629                 KdbpPrint("thread: Invalid thread id!\n");
01630                 return TRUE;
01631             }
01632 
01633             /* Remember our reference */
01634             ReferencedThread = TRUE;
01635         }
01636 
01637         if (Thread->Tcb.State < (DeferredReady + 1))
01638             State = ThreadStateToString[Thread->Tcb.State];
01639         else
01640             State = "Unknown";
01641 
01642         KdbpPrint("%s"
01643                   "  TID:            0x%08x\n"
01644                   "  State:          %s (0x%x)\n"
01645                   "  Priority:       %d\n"
01646                   "  Affinity:       0x%08x\n"
01647                   "  Initial Stack:  0x%08x\n"
01648                   "  Stack Limit:    0x%08x\n"
01649                   "  Stack Base:     0x%08x\n"
01650                   "  Kernel Stack:   0x%08x\n"
01651                   "  Trap Frame:     0x%08x\n"
01652                   "  NPX State:      %s (0x%x)\n",
01653                   (Argc < 2) ? "Current Thread:\n" : "",
01654                   Thread->Cid.UniqueThread,
01655                   State, Thread->Tcb.State,
01656                   Thread->Tcb.Priority,
01657                   Thread->Tcb.Affinity,
01658                   Thread->Tcb.InitialStack,
01659                   Thread->Tcb.StackLimit,
01660                   Thread->Tcb.StackBase,
01661                   Thread->Tcb.KernelStack,
01662                   Thread->Tcb.TrapFrame,
01663                   NPX_STATE_TO_STRING(Thread->Tcb.NpxState), Thread->Tcb.NpxState);
01664 
01665             /* Release our reference if we had one */
01666             if (ReferencedThread)
01667                 ObDereferenceObject(Thread);
01668     }
01669 
01670     return TRUE;
01671 }
01672 
01675 static BOOLEAN
01676 KdbpCmdProc(
01677     ULONG Argc,
01678     PCHAR Argv[])
01679 {
01680     PLIST_ENTRY Entry;
01681     PEPROCESS Process;
01682     BOOLEAN ReferencedProcess = FALSE;
01683     PCHAR State, pend, str1, str2;
01684     ULONG ul;
01685     extern LIST_ENTRY PsActiveProcessHead;
01686 
01687     if (Argc >= 2 && _stricmp(Argv[1], "list") == 0)
01688     {
01689         Entry = PsActiveProcessHead.Flink;
01690         if (!Entry || Entry == &PsActiveProcessHead)
01691         {
01692             KdbpPrint("No processes in the system!\n");
01693             return TRUE;
01694         }
01695 
01696         KdbpPrint("  PID         State       Filename\n");
01697         do
01698         {
01699             Process = CONTAINING_RECORD(Entry, EPROCESS, ActiveProcessLinks);
01700 
01701             if (Process == KdbCurrentProcess)
01702             {
01703                 str1 = "\x1b[1m*";
01704                 str2 = "\x1b[0m";
01705             }
01706             else
01707             {
01708                 str1 = " ";
01709                 str2 = "";
01710             }
01711 
01712             State = ((Process->Pcb.State == ProcessInMemory) ? "In Memory" :
01713                     ((Process->Pcb.State == ProcessOutOfMemory) ? "Out of Memory" : "In Transition"));
01714 
01715             KdbpPrint(" %s0x%08x  %-10s  %s%s\n",
01716                       str1,
01717                       Process->UniqueProcessId,
01718                       State,
01719                       Process->ImageFileName,
01720                       str2);
01721 
01722             Entry = Entry->Flink;
01723         }
01724         while(Entry != &PsActiveProcessHead);
01725     }
01726     else if (Argc >= 2 && _stricmp(Argv[1], "attach") == 0)
01727     {
01728         if (Argc < 3)
01729         {
01730             KdbpPrint("process attach: process id argument required!\n");
01731             return TRUE;
01732         }
01733 
01734         ul = strtoul(Argv[2], &pend, 0);
01735         if (Argv[2] == pend)
01736         {
01737             KdbpPrint("process attach: '%s' is not a valid process id!\n", Argv[2]);
01738             return TRUE;
01739         }
01740 
01741         if (!KdbpAttachToProcess((PVOID)ul))
01742         {
01743             return TRUE;
01744         }
01745 
01746         KdbpPrint("Attached to process 0x%08x, thread 0x%08x.\n", (ULONG)ul,
01747                   (ULONG)KdbCurrentThread->Cid.UniqueThread);
01748     }
01749     else
01750     {
01751         Process = KdbCurrentProcess;
01752 
01753         if (Argc >= 2)
01754         {
01755             ul = strtoul(Argv[1], &pend, 0);
01756             if (Argv[1] == pend)
01757             {
01758                 KdbpPrint("proc: '%s' is not a valid process id!\n", Argv[1]);
01759                 return TRUE;
01760             }
01761 
01762             if (!NT_SUCCESS(PsLookupProcessByProcessId((PVOID)ul, &Process)))
01763             {
01764                 KdbpPrint("proc: Invalid process id!\n");
01765                 return TRUE;
01766             }
01767 
01768             /* Remember our reference */
01769             ReferencedProcess = TRUE;
01770         }
01771 
01772         State = ((Process->Pcb.State == ProcessInMemory) ? "In Memory" :
01773                 ((Process->Pcb.State == ProcessOutOfMemory) ? "Out of Memory" : "In Transition"));
01774         KdbpPrint("%s"
01775                   "  PID:             0x%08x\n"
01776                   "  State:           %s (0x%x)\n"
01777                   "  Image Filename:  %s\n",
01778                   (Argc < 2) ? "Current process:\n" : "",
01779                   Process->UniqueProcessId,
01780                   State, Process->Pcb.State,
01781                   Process->ImageFileName);
01782 
01783         /* Release our reference, if any */
01784         if (ReferencedProcess)
01785             ObDereferenceObject(Process);
01786     }
01787 
01788     return TRUE;
01789 }
01790 
01793 static BOOLEAN
01794 KdbpCmdMod(
01795     ULONG Argc,
01796     PCHAR Argv[])
01797 {
01798     ULONGLONG Result = 0;
01799     ULONG_PTR Address;
01800     PLDR_DATA_TABLE_ENTRY LdrEntry;
01801     BOOLEAN DisplayOnlyOneModule = FALSE;
01802     INT i = 0;
01803 
01804     if (Argc >= 2)
01805     {
01806         /* Put the arguments back together */
01807         Argc--;
01808         while (--Argc >= 1)
01809             Argv[Argc][strlen(Argv[Argc])] = ' ';
01810 
01811         /* Evaluate the expression */
01812         if (!KdbpEvaluateExpression(Argv[1], sizeof("kdb:> ")-1 + (Argv[1]-Argv[0]), &Result))
01813         {
01814             return TRUE;
01815         }
01816 
01817         if (Result > (ULONGLONG)(~((ULONG_PTR)0)))
01818             KdbpPrint("%s: Warning: Address %I64x is beeing truncated\n", Argv[0],Result);
01819 
01820         Address = (ULONG_PTR)Result;
01821 
01822         if (!KdbpSymFindModule((PVOID)Address, NULL, -1, &LdrEntry))
01823         {
01824             KdbpPrint("No module containing address 0x%p found!\n", Address);
01825             return TRUE;
01826         }
01827 
01828         DisplayOnlyOneModule = TRUE;
01829     }
01830     else
01831     {
01832         if (!KdbpSymFindModule(NULL, NULL, 0, &LdrEntry))
01833         {
01834             ULONG_PTR ntoskrnlBase = ((ULONG_PTR)KdbpCmdMod) & 0xfff00000;
01835             KdbpPrint("  Base      Size      Name\n");
01836             KdbpPrint("  %08x  %08x  %s\n", ntoskrnlBase, 0, "ntoskrnl.exe");
01837             return TRUE;
01838         }
01839 
01840         i = 1;
01841     }
01842 
01843     KdbpPrint("  Base      Size      Name\n");
01844     for (;;)
01845     {
01846         KdbpPrint("  %08x  %08x  %wZ\n", LdrEntry->DllBase, LdrEntry->SizeOfImage, &LdrEntry->BaseDllName);
01847 
01848         if(DisplayOnlyOneModule || !KdbpSymFindModule(NULL, NULL, i++, &LdrEntry))
01849             break;
01850     }
01851 
01852     return TRUE;
01853 }
01854 
01857 static BOOLEAN
01858 KdbpCmdGdtLdtIdt(
01859     ULONG Argc,
01860     PCHAR Argv[])
01861 {
01862     KDESCRIPTOR Reg;
01863     ULONG SegDesc[2];
01864     ULONG SegBase;
01865     ULONG SegLimit;
01866     PCHAR SegType;
01867     USHORT SegSel;
01868     UCHAR Type, Dpl;
01869     INT i;
01870     ULONG ul;
01871 
01872     if (Argv[0][0] == 'i')
01873     {
01874         /* Read IDTR */
01875         __sidt(&Reg.Limit);
01876 
01877         if (Reg.Limit < 7)
01878         {
01879             KdbpPrint("Interrupt descriptor table is empty.\n");
01880             return TRUE;
01881         }
01882 
01883         KdbpPrint("IDT Base: 0x%08x  Limit: 0x%04x\n", Reg.Base, Reg.Limit);
01884         KdbpPrint("  Idx  Type        Seg. Sel.  Offset      DPL\n");
01885 
01886         for (i = 0; (i + sizeof(SegDesc) - 1) <= Reg.Limit; i += 8)
01887         {
01888             if (!NT_SUCCESS(KdbpSafeReadMemory(SegDesc, (PVOID)(Reg.Base + i), sizeof(SegDesc))))
01889             {
01890                 KdbpPrint("Couldn't access memory at 0x%08x!\n", Reg.Base + i);
01891                 return TRUE;
01892             }
01893 
01894             Dpl = ((SegDesc[1] >> 13) & 3);
01895             if ((SegDesc[1] & 0x1f00) == 0x0500)        /* Task gate */
01896                 SegType = "TASKGATE";
01897             else if ((SegDesc[1] & 0x1fe0) == 0x0e00)   /* 32 bit Interrupt gate */
01898                 SegType = "INTGATE32";
01899             else if ((SegDesc[1] & 0x1fe0) == 0x0600)   /* 16 bit Interrupt gate */
01900                 SegType = "INTGATE16";
01901             else if ((SegDesc[1] & 0x1fe0) == 0x0f00)   /* 32 bit Trap gate */
01902                 SegType = "TRAPGATE32";
01903             else if ((SegDesc[1] & 0x1fe0) == 0x0700)   /* 16 bit Trap gate */
01904                 SegType = "TRAPGATE16";
01905             else
01906                 SegType = "UNKNOWN";
01907 
01908             if ((SegDesc[1] & (1 << 15)) == 0) /* not present */
01909             {
01910                 KdbpPrint("  %03d  %-10s  [NP]       [NP]        %02d\n",
01911                           i / 8, SegType, Dpl);
01912             }
01913             else if ((SegDesc[1] & 0x1f00) == 0x0500) /* Task gate */
01914             {
01915                 SegSel = SegDesc[0] >> 16;
01916                 KdbpPrint("  %03d  %-10s  0x%04x                 %02d\n",
01917                           i / 8, SegType, SegSel, Dpl);
01918             }
01919             else
01920             {
01921                 SegSel = SegDesc[0] >> 16;
01922                 SegBase = (SegDesc[1] & 0xffff0000) | (SegDesc[0] & 0x0000ffff);
01923                 KdbpPrint("  %03d  %-10s  0x%04x     0x%08x  %02d\n",
01924                           i / 8, SegType, SegSel, SegBase, Dpl);
01925             }
01926         }
01927     }
01928     else
01929     {
01930         ul = 0;
01931 
01932         if (Argv[0][0] == 'g')
01933         {
01934             /* Read GDTR */
01935             Ke386GetGlobalDescriptorTable(&Reg.Limit);
01936             i = 8;
01937         }
01938         else
01939         {
01940             ASSERT(Argv[0][0] == 'l');
01941 
01942             /* Read LDTR */
01943             Reg.Limit = Ke386GetLocalDescriptorTable();
01944             Reg.Base = 0;
01945             i = 0;
01946             ul = 1 << 2;
01947         }
01948 
01949         if (Reg.Limit < 7)
01950         {
01951             KdbpPrint("%s descriptor table is empty.\n",
01952                       Argv[0][0] == 'g' ? "Global" : "Local");
01953             return TRUE;
01954         }
01955 
01956         KdbpPrint("%cDT Base: 0x%08x  Limit: 0x%04x\n",
01957                   Argv[0][0] == 'g' ? 'G' : 'L', Reg.Base, Reg.Limit);
01958         KdbpPrint("  Idx  Sel.    Type         Base        Limit       DPL  Attribs\n");
01959 
01960         for (; (i + sizeof(SegDesc) - 1) <= Reg.Limit; i += 8)
01961         {
01962             if (!NT_SUCCESS(KdbpSafeReadMemory(SegDesc, (PVOID)(Reg.Base + i), sizeof(SegDesc))))
01963             {
01964                 KdbpPrint("Couldn't access memory at 0x%08x!\n", Reg.Base + i);
01965                 return TRUE;
01966             }
01967 
01968             Dpl = ((SegDesc[1] >> 13) & 3);
01969             Type = ((SegDesc[1] >> 8) & 0xf);
01970 
01971             SegBase = SegDesc[0] >> 16;
01972             SegBase |= (SegDesc[1] & 0xff) << 16;
01973             SegBase |= SegDesc[1] & 0xff000000;
01974             SegLimit = SegDesc[0] & 0x0000ffff;
01975             SegLimit |= (SegDesc[1] >> 16) & 0xf;
01976 
01977             if ((SegDesc[1] & (1 << 23)) != 0)
01978             {
01979                 SegLimit *= 4096;
01980                 SegLimit += 4095;
01981             }
01982             else
01983             {
01984                 SegLimit++;
01985             }
01986 
01987             if ((SegDesc[1] & (1 << 12)) == 0) /* System segment */
01988             {
01989                 switch (Type)
01990                 {
01991                     case 1: SegType = "TSS16(Avl)"; break;
01992                     case 2: SegType = "LDT"; break;
01993                     case 3: SegType = "TSS16(Busy)"; break;
01994                     case 4: SegType = "CALLGATE16"; break;
01995                     case 5: SegType = "TASKGATE"; break;
01996                     case 6: SegType = "INTGATE16"; break;
01997                     case 7: SegType = "TRAPGATE16"; break;
01998                     case 9: SegType = "TSS32(Avl)"; break;
01999                     case 11: SegType = "TSS32(Busy)"; break;
02000                     case 12: SegType = "CALLGATE32"; break;
02001                     case 14: SegType = "INTGATE32"; break;
02002                     case 15: SegType = "INTGATE32"; break;
02003                     default: SegType = "UNKNOWN"; break;
02004                 }
02005 
02006                 if (!(Type >= 1 && Type <= 3) &&
02007                     Type != 9 && Type != 11)
02008                 {
02009                     SegBase = 0;
02010                     SegLimit = 0;
02011                 }
02012             }
02013             else if ((SegDesc[1] & (1 << 11)) == 0) /* Data segment */
02014             {
02015                 if ((SegDesc[1] & (1 << 22)) != 0)
02016                     SegType = "DATA32";
02017                 else
02018                     SegType = "DATA16";
02019             }
02020             else /* Code segment */
02021             {
02022                 if ((SegDesc[1] & (1 << 22)) != 0)
02023                     SegType = "CODE32";
02024                 else
02025                     SegType = "CODE16";
02026             }
02027 
02028             if ((SegDesc[1] & (1 << 15)) == 0) /* not present */
02029             {
02030                 KdbpPrint("  %03d  0x%04x  %-11s  [NP]        [NP]        %02d   NP\n",
02031                           i / 8, i | Dpl | ul, SegType, Dpl);
02032             }
02033             else
02034             {
02035                 KdbpPrint("  %03d  0x%04x  %-11s  0x%08x  0x%08x  %02d  ",
02036                           i / 8, i | Dpl | ul, SegType, SegBase, SegLimit, Dpl);
02037 
02038                 if ((SegDesc[1] & (1 << 12)) == 0) /* System segment */
02039                 {
02040                     /* FIXME: Display system segment */
02041                 }
02042                 else if ((SegDesc[1] & (1 << 11)) == 0) /* Data segment */
02043                 {
02044                     if ((SegDesc[1] & (1 << 10)) != 0) /* Expand-down */
02045                         KdbpPrint(" E");
02046 
02047                     KdbpPrint((SegDesc[1] & (1 << 9)) ? " R/W" : " R");
02048 
02049                     if ((SegDesc[1] & (1 << 8)) != 0)
02050                         KdbpPrint(" A");
02051                 }
02052                 else /* Code segment */
02053                 {
02054                     if ((SegDesc[1] & (1 << 10)) != 0) /* Conforming */
02055                         KdbpPrint(" C");
02056 
02057                     KdbpPrint((SegDesc[1] & (1 << 9)) ? " R/X" : " X");
02058 
02059                     if ((SegDesc[1] & (1 << 8)) != 0)
02060                         KdbpPrint(" A");
02061                 }
02062 
02063                 if ((SegDesc[1] & (1 << 20)) != 0)
02064                     KdbpPrint(" AVL");
02065 
02066                 KdbpPrint("\n");
02067             }
02068         }
02069     }
02070 
02071     return TRUE;
02072 }
02073 
02076 static BOOLEAN
02077 KdbpCmdPcr(
02078     ULONG Argc,
02079     PCHAR Argv[])
02080 {
02081     PKIPCR Pcr = (PKIPCR)KeGetPcr();
02082 
02083     KdbpPrint("Current PCR is at 0x%08x.\n", (INT)Pcr);
02084     KdbpPrint("  Tib.ExceptionList:         0x%08x\n"
02085               "  Tib.StackBase:             0x%08x\n"
02086               "  Tib.StackLimit:            0x%08x\n"
02087               "  Tib.SubSystemTib:          0x%08x\n"
02088               "  Tib.FiberData/Version:     0x%08x\n"
02089               "  Tib.ArbitraryUserPointer:  0x%08x\n"
02090               "  Tib.Self:                  0x%08x\n"
02091               "  Self:                      0x%08x\n"
02092               "  PCRCB:                     0x%08x\n"
02093               "  Irql:                      0x%02x\n"
02094               "  IRR:                       0x%08x\n"
02095               "  IrrActive:                 0x%08x\n"
02096               "  IDR:                       0x%08x\n"
02097               "  KdVersionBlock:            0x%08x\n"
02098               "  IDT:                       0x%08x\n"
02099               "  GDT:                       0x%08x\n"
02100               "  TSS:                       0x%08x\n"
02101               "  MajorVersion:              0x%04x\n"
02102               "  MinorVersion:              0x%04x\n"
02103               "  SetMember:                 0x%08x\n"
02104               "  StallScaleFactor:          0x%08x\n"
02105               "  Number:                    0x%02x\n"
02106               "  L2CacheAssociativity:      0x%02x\n"
02107               "  VdmAlert:                  0x%08x\n"
02108               "  L2CacheSize:               0x%08x\n"
02109               "  InterruptMode:             0x%08x\n",
02110               Pcr->NtTib.ExceptionList, Pcr->NtTib.StackBase, Pcr->NtTib.StackLimit,
02111               Pcr->NtTib.SubSystemTib, Pcr->NtTib.FiberData, Pcr->NtTib.ArbitraryUserPointer,
02112               Pcr->NtTib.Self, Pcr->Self, Pcr->Prcb, Pcr->Irql, Pcr->IRR, Pcr->IrrActive,
02113               Pcr->IDR, Pcr->KdVersionBlock, Pcr->IDT, Pcr->GDT, Pcr->TSS,
02114               Pcr->MajorVersion, Pcr->MinorVersion, Pcr->SetMember, Pcr->StallScaleFactor,
02115               Pcr->Number, Pcr->SecondLevelCacheAssociativity,
02116               Pcr->VdmAlert, Pcr->SecondLevelCacheSize, Pcr->InterruptMode);
02117 
02118     return TRUE;
02119 }
02120 
02123 static BOOLEAN
02124 KdbpCmdTss(
02125     ULONG Argc,
02126     PCHAR Argv[])
02127 {
02128     KTSS *Tss = KeGetPcr()->TSS;
02129 
02130     KdbpPrint("Current TSS is at 0x%08x.\n", (INT)Tss);
02131     KdbpPrint("  Eip:           0x%08x\n"
02132               "  Es:            0x%04x\n"
02133               "  Cs:            0x%04x\n"
02134               "  Ss:            0x%04x\n"
02135               "  Ds:            0x%04x\n"
02136               "  Fs:            0x%04x\n"
02137               "  Gs:            0x%04x\n"
02138               "  IoMapBase:     0x%04x\n",
02139               Tss->Eip, Tss->Es, Tss->Cs, Tss->Ds, Tss->Fs, Tss->Gs, Tss->IoMapBase);
02140 
02141     return TRUE;
02142 }
02143 
02146 static BOOLEAN
02147 KdbpCmdBugCheck(
02148     ULONG Argc,
02149     PCHAR Argv[])
02150 {
02151     /* Set the flag and quit looping */
02152     KdbpBugCheckRequested = TRUE;
02153 
02154     return FALSE;
02155 }
02156 
02157 VOID
02158 KdbpPager(
02159     IN PCHAR Buffer,
02160     IN ULONG BufLength);
02161 
02167 static BOOLEAN
02168 KdbpCmdDmesg(
02169     ULONG Argc,
02170     PCHAR Argv[])
02171 {
02172   ULONG beg, end;
02173 
02174   KdbpIsInDmesgMode = TRUE; /* Toggle logging flag */
02175   if (!KdpDmesgBuffer)
02176   {
02177     KdbpPrint("Dmesg: error, buffer is not allocated! /DEBUGPORT=SCREEN kernel param required for dmesg.\n");
02178     return TRUE;
02179   }
02180 
02181   KdbpPrint("*** Dmesg *** TotalWritten=%lu, BufferSize=%lu, CurrentPosition=%lu\n",
02182             KdbDmesgTotalWritten, KdpDmesgBufferSize, KdpDmesgCurrentPosition);
02183 
02184   // Pass data to the pager:
02185   end = KdpDmesgCurrentPosition;
02186   beg = (end + KdpDmesgFreeBytes) % KdpDmesgBufferSize;
02187 
02188   // no roll-overs, and overwritten=lost bytes
02189   if (KdbDmesgTotalWritten <= KdpDmesgBufferSize)
02190   {
02191     // show buffer (KdpDmesgBuffer + beg, num)
02192     KdbpPager(KdpDmesgBuffer, KdpDmesgCurrentPosition);
02193   }
02194   else
02195   {
02196     // show 2 buffers: (KdpDmesgBuffer + beg, KdpDmesgBufferSize - beg)
02197     //            and: (KdpDmesgBuffer,       end)
02198     KdbpPager(KdpDmesgBuffer + beg, KdpDmesgBufferSize - beg);
02199     KdbpPrint("*** Dmesg: buffer rollup ***\n");
02200     KdbpPager(KdpDmesgBuffer,       end);
02201   }
02202   KdbpPrint("*** Dmesg: end of output ***\n");
02203 
02204   KdbpIsInDmesgMode = FALSE; /* Toggle logging flag */
02205 
02206   return TRUE;
02207 }
02208 
02211 static BOOLEAN
02212 KdbpCmdSet(
02213     ULONG Argc,
02214     PCHAR Argv[])
02215 {
02216     LONG l;
02217     BOOLEAN First;
02218     PCHAR pend = 0;
02219     KDB_ENTER_CONDITION ConditionFirst = KdbDoNotEnter;
02220     KDB_ENTER_CONDITION ConditionLast = KdbDoNotEnter;
02221 
02222     static const PCHAR ExceptionNames[21] =
02223     {
02224         "ZERODEVIDE", "DEBUGTRAP", "NMI", "INT3", "OVERFLOW", "BOUND", "INVALIDOP",
02225         "NOMATHCOP", "DOUBLEFAULT", "RESERVED(9)", "INVALIDTSS", "SEGMENTNOTPRESENT",
02226         "STACKFAULT", "GPF", "PAGEFAULT", "RESERVED(15)", "MATHFAULT", "ALIGNMENTCHECK",
02227         "MACHINECHECK", "SIMDFAULT", "OTHERS"
02228     };
02229 
02230     if (Argc == 1)
02231     {
02232         KdbpPrint("Available settings:\n");
02233         KdbpPrint("  syntax [intel|at&t]\n");
02234         KdbpPrint("  condition [exception|*] [first|last] [never|always|kmode|umode]\n");
02235         KdbpPrint("  break_on_module_load [true|false]\n");
02236     }
02237     else if (strcmp(Argv[1], "syntax") == 0)
02238     {
02239         if (Argc == 2)
02240         {
02241             KdbpPrint("syntax = %s\n", KdbUseIntelSyntax ? "intel" : "at&t");
02242         }
02243         else if (Argc >= 3)
02244         {
02245             if (_stricmp(Argv[2], "intel") == 0)
02246                 KdbUseIntelSyntax = TRUE;
02247             else if (_stricmp(Argv[2], "at&t") == 0)
02248                 KdbUseIntelSyntax = FALSE;
02249             else
02250                 KdbpPrint("Unknown syntax '%s'.\n", Argv[2]);
02251         }
02252     }
02253     else if (strcmp(Argv[1], "condition") == 0)
02254     {
02255         if (Argc == 2)
02256         {
02257             KdbpPrint("Conditions:                 (First)  (Last)\n");
02258             for (l = 0; l < RTL_NUMBER_OF(ExceptionNames) - 1; l++)
02259             {
02260                 if (!ExceptionNames[l])
02261                     continue;
02262 
02263                 if (!KdbpGetEnterCondition(l, TRUE, &ConditionFirst))
02264                     ASSERT(0);
02265 
02266                 if (!KdbpGetEnterCondition(l, FALSE, &ConditionLast))
02267                     ASSERT(0);
02268 
02269                 KdbpPrint("  #%02d  %-20s %-8s %-8s\n", l, ExceptionNames[l],
02270                           KDB_ENTER_CONDITION_TO_STRING(ConditionFirst),
02271                           KDB_ENTER_CONDITION_TO_STRING(ConditionLast));
02272             }
02273 
02274             ASSERT(l == (RTL_NUMBER_OF(ExceptionNames) - 1));
02275             KdbpPrint("       %-20s %-8s %-8s\n", ExceptionNames[l],
02276                       KDB_ENTER_CONDITION_TO_STRING(ConditionFirst),
02277                       KDB_ENTER_CONDITION_TO_STRING(ConditionLast));
02278         }
02279         else
02280         {
02281             if (Argc >= 5 && strcmp(Argv[2], "*") == 0) /* Allow * only when setting condition */
02282             {
02283                 l = -1;
02284             }
02285             else
02286             {
02287                 l = strtoul(Argv[2], &pend, 0);
02288 
02289                 if (Argv[2] == pend)
02290                 {
02291                     for (l = 0; l < RTL_NUMBER_OF(ExceptionNames); l++)
02292                     {
02293                         if (!ExceptionNames[l])
02294                             continue;
02295 
02296                         if (_stricmp(ExceptionNames[l], Argv[2]) == 0)
02297                             break;
02298                     }
02299                 }
02300 
02301                 if (l >= RTL_NUMBER_OF(ExceptionNames))
02302                 {
02303                     KdbpPrint("Unknown exception '%s'.\n", Argv[2]);
02304                     return TRUE;
02305                 }
02306             }
02307 
02308             if (Argc > 4)
02309             {
02310                 if (_stricmp(Argv[3], "first") == 0)
02311                     First = TRUE;
02312                 else if (_stricmp(Argv[3], "last") == 0)
02313                     First = FALSE;
02314                 else
02315                 {
02316                     KdbpPrint("set condition: second argument must be 'first' or 'last'\n");
02317                     return TRUE;
02318                 }
02319 
02320                 if (_stricmp(Argv[4], "never") == 0)
02321                     ConditionFirst = KdbDoNotEnter;
02322                 else if (_stricmp(Argv[4], "always") == 0)
02323                     ConditionFirst = KdbEnterAlways;
02324                 else if (_stricmp(Argv[4], "umode") == 0)
02325                     ConditionFirst = KdbEnterFromUmode;
02326                 else if (_stricmp(Argv[4], "kmode") == 0)
02327                     ConditionFirst = KdbEnterFromKmode;
02328                 else
02329                 {
02330                     KdbpPrint("set condition: third argument must be 'never', 'always', 'umode' or 'kmode'\n");
02331                     return TRUE;
02332                 }
02333 
02334                 if (!KdbpSetEnterCondition(l, First, ConditionFirst))
02335                 {
02336                     if (l >= 0)
02337                         KdbpPrint("Couldn't change condition for exception #%02d\n", l);
02338                     else
02339                         KdbpPrint("Couldn't change condition for all exceptions\n", l);
02340                 }
02341             }
02342             else /* Argc >= 3 */
02343             {
02344                 if (!KdbpGetEnterCondition(l, TRUE, &ConditionFirst))
02345                     ASSERT(0);
02346 
02347                 if (!KdbpGetEnterCondition(l, FALSE, &ConditionLast))
02348                     ASSERT(0);
02349 
02350                 if (l < (RTL_NUMBER_OF(ExceptionNames) - 1))
02351                 {
02352                     KdbpPrint("Condition for exception #%02d (%s): FirstChance %s  LastChance %s\n",
02353                               l, ExceptionNames[l],
02354                               KDB_ENTER_CONDITION_TO_STRING(ConditionFirst),
02355                               KDB_ENTER_CONDITION_TO_STRING(ConditionLast));
02356                 }
02357                 else
02358                 {
02359                     KdbpPrint("Condition for all other exceptions: FirstChance %s  LastChance %s\n",
02360                               KDB_ENTER_CONDITION_TO_STRING(ConditionFirst),
02361                               KDB_ENTER_CONDITION_TO_STRING(ConditionLast));
02362                 }
02363             }
02364         }
02365     }
02366     else if (strcmp(Argv[1], "break_on_module_load") == 0)
02367     {
02368         if (Argc == 2)
02369             KdbpPrint("break_on_module_load = %s\n", KdbBreakOnModuleLoad ? "enabled" : "disabled");
02370         else if (Argc >= 3)
02371         {
02372             if (_stricmp(Argv[2], "enable") == 0 || _stricmp(Argv[2], "enabled") == 0 || _stricmp(Argv[2], "true") == 0)
02373                 KdbBreakOnModuleLoad = TRUE;
02374             else if (_stricmp(Argv[2], "disable") == 0 || _stricmp(Argv[2], "disabled") == 0 || _stricmp(Argv[2], "false") == 0)
02375                 KdbBreakOnModuleLoad = FALSE;
02376             else
02377                 KdbpPrint("Unknown setting '%s'.\n", Argv[2]);
02378         }
02379     }
02380     else
02381     {
02382         KdbpPrint("Unknown setting '%s'.\n", Argv[1]);
02383     }
02384 
02385     return TRUE;
02386 }
02387 
02390 static BOOLEAN
02391 KdbpCmdHelp(
02392     ULONG Argc,
02393     PCHAR Argv[])
02394 {
02395     ULONG i;
02396 
02397     KdbpPrint("Kernel debugger commands:\n");
02398     for (i = 0; i < RTL_NUMBER_OF(KdbDebuggerCommands); i++)
02399     {
02400         if (!KdbDebuggerCommands[i].Syntax) /* Command group */
02401         {
02402             if (i > 0)
02403                 KdbpPrint("\n");
02404 
02405             KdbpPrint("\x1b[7m* %s:\x1b[0m\n", KdbDebuggerCommands[i].Help);
02406             continue;
02407         }
02408 
02409         KdbpPrint("  %-20s - %s\n",
02410                   KdbDebuggerCommands[i].Syntax,
02411                   KdbDebuggerCommands[i].Help);
02412     }
02413 
02414     return TRUE;
02415 }
02416 
02426 VOID
02427 KdbpPrint(
02428     IN PCHAR Format,
02429     IN ...  OPTIONAL)
02430 {
02431     static CHAR Buffer[4096];
02432     static BOOLEAN TerminalInitialized = FALSE;
02433     static BOOLEAN TerminalConnected = FALSE;
02434     static BOOLEAN TerminalReportsSize = TRUE;
02435     CHAR c = '\0';
02436     PCHAR p, p2;
02437     ULONG Length;
02438     ULONG i, j;
02439     LONG RowsPrintedByTerminal;
02440     ULONG ScanCode;
02441     va_list ap;
02442 
02443     /* Check if the user has aborted output of the current command */
02444     if (KdbOutputAborted)
02445         return;
02446 
02447     /* Initialize the terminal */
02448     if (!TerminalInitialized)
02449     {
02450         DbgPrint("\x1b[7h");      /* Enable linewrap */
02451 
02452         /* Query terminal type */
02453         /*DbgPrint("\x1b[Z");*/
02454         DbgPrint("\x05");
02455 
02456         TerminalInitialized = TRUE;
02457         Length = 0;
02458         KeStallExecutionProcessor(100000);
02459 
02460         for (;;)
02461         {
02462             c = KdbpTryGetCharSerial(5000);
02463             if (c == -1)
02464                 break;
02465 
02466             Buffer[Length++] = c;
02467             if (Length >= (sizeof (Buffer) - 1))
02468                 break;
02469         }
02470 
02471         Buffer[Length] = '\0';
02472         if (Length > 0)
02473             TerminalConnected = TRUE;
02474     }
02475 
02476     /* Get number of rows and columns in terminal */
02477     if ((KdbNumberOfRowsTerminal < 0) || (KdbNumberOfColsTerminal < 0) ||
02478         (KdbNumberOfRowsPrinted) == 0) /* Refresh terminal size each time when number of rows printed is 0 */
02479     {
02480         if ((KdbDebugState & KD_DEBUG_KDSERIAL) && TerminalConnected && TerminalReportsSize)
02481         {
02482             /* Try to query number of rows from terminal. A reply looks like "\x1b[8;24;80t" */
02483             TerminalReportsSize = FALSE;
02484             KeStallExecutionProcessor(100000);
02485             DbgPrint("\x1b[18t");
02486             c = KdbpTryGetCharSerial(5000);
02487 
02488             if (c == KEY_ESC)
02489             {
02490                 c = KdbpTryGetCharSerial(5000);
02491                 if (c == '[')
02492                 {
02493                     Length = 0;
02494 
02495                     for (;;)
02496                     {
02497                         c = KdbpTryGetCharSerial(5000);
02498                         if (c == -1)
02499                             break;
02500 
02501                         Buffer[Length++] = c;
02502                         if (isalpha(c) || Length >= (sizeof (Buffer) - 1))
02503                             break;
02504                     }
02505 
02506                     Buffer[Length] = '\0';
02507                     if (Buffer[0] == '8' && Buffer[1] == ';')
02508                     {
02509                         for (i = 2; (i < Length) && (Buffer[i] != ';'); i++);
02510 
02511                         if (Buffer[i] == ';')
02512                         {
02513                             Buffer[i++] = '\0';
02514 
02515                             /* Number of rows is now at Buffer + 2 and number of cols at Buffer + i */
02516                             KdbNumberOfRowsTerminal = strtoul(Buffer + 2, NULL, 0);
02517                             KdbNumberOfColsTerminal = strtoul(Buffer + i, NULL, 0);
02518                             TerminalReportsSize = TRUE;
02519                         }
02520                     }
02521                 }
02522                 /* Clear further characters */
02523                 while ((c = KdbpTryGetCharSerial(5000)) != -1);
02524             }
02525         }
02526 
02527         if (KdbNumberOfRowsTerminal <= 0)
02528         {
02529             /* Set number of rows to the default. */
02530             KdbNumberOfRowsTerminal = 23; //24; //Mna.: 23 for SCREEN debugport
02531         }
02532         else if (KdbNumberOfColsTerminal <= 0)
02533         {
02534             /* Set number of cols to the default. */
02535             KdbNumberOfColsTerminal = 75; //80; //Mna.: 75 for SCREEN debugport
02536         }
02537     }
02538 
02539     /* Get the string */
02540     va_start(ap, Format);
02541     Length = _vsnprintf(Buffer, sizeof (Buffer) - 1, Format, ap);
02542     Buffer[Length] = '\0';
02543     va_end(ap);
02544 
02545     p = Buffer;
02546     while (p[0] != '\0')
02547     {
02548         i = strcspn(p, "\n");
02549 
02550         /* Calculate the number of lines which will be printed in the terminal
02551          * when outputting the current line
02552          */
02553         if (i > 0)
02554             RowsPrintedByTerminal = (i + KdbNumberOfColsPrinted - 1) / KdbNumberOfColsTerminal;
02555         else
02556             RowsPrintedByTerminal = 0;
02557 
02558         if (p[i] == '\n')
02559             RowsPrintedByTerminal++;
02560 
02561         /*DbgPrint("!%d!%d!%d!%d!", KdbNumberOfRowsPrinted, KdbNumberOfColsPrinted, i, RowsPrintedByTerminal);*/
02562 
02563         /* Display a prompt if we printed one screen full of text */
02564         if (KdbNumberOfRowsTerminal > 0 &&
02565             (LONG)(KdbNumberOfRowsPrinted + RowsPrintedByTerminal) >= KdbNumberOfRowsTerminal)
02566         {
02567             KdbRepeatLastCommand = FALSE;
02568 
02569             if (KdbNumberOfColsPrinted > 0)
02570                 DbgPrint("\n");
02571 
02572             DbgPrint("--- Press q to abort, any other key to continue ---");
02573             RowsPrintedByTerminal++; /* added by Mna. */
02574 
02575             if (KdbDebugState & KD_DEBUG_KDSERIAL)
02576                 c = KdbpGetCharSerial();
02577             else
02578                 c = KdbpGetCharKeyboard(&ScanCode);
02579 
02580             if (c == '\r')
02581             {
02582                 /* Try to read '\n' which might follow '\r' - if \n is not received here
02583                  * it will be interpreted as "return" when the next command should be read.
02584                  */
02585                 if (KdbDebugState & KD_DEBUG_KDSERIAL)
02586                     c = KdbpTryGetCharSerial(5);
02587                 else
02588                     c = KdbpTryGetCharKeyboard(&ScanCode, 5);
02589             }
02590 
02591             DbgPrint("\n");
02592             if (c == 'q')
02593             {
02594                 KdbOutputAborted = TRUE;
02595                 return;
02596             }
02597 
02598             KdbNumberOfRowsPrinted = 0;
02599             KdbNumberOfColsPrinted = 0;
02600         }
02601 
02602         /* Insert a NUL after the line and print only the current line. */
02603         if (p[i] == '\n' && p[i + 1] != '\0')
02604         {
02605             c = p[i + 1];
02606             p[i + 1] = '\0';
02607         }
02608         else
02609         {
02610             c = '\0';
02611         }
02612 
02613         /* Remove escape sequences from the line if there's no terminal connected */
02614         if (!TerminalConnected)
02615         {
02616             while ((p2 = strrchr(p, '\x1b'))) /* Look for escape character */
02617             {
02618                 if (p2[1] == '[')
02619                 {
02620                     j = 2;
02621                     while (!isalpha(p2[j++]));
02622                     strcpy(p2, p2 + j);
02623                 }
02624                 else
02625                 {
02626                     strcpy(p2, p2 + 1);
02627                 }
02628             }
02629         }
02630 
02631         DbgPrint("%s", p);
02632 
02633         if (c != '\0')
02634             p[i + 1] = c;
02635 
02636         /* Set p to the start of the next line and
02637          * remember the number of rows/cols printed
02638          */
02639         p += i;
02640         if (p[0] == '\n')
02641         {
02642             p++;
02643             KdbNumberOfColsPrinted = 0;
02644         }
02645         else
02646         {
02647             ASSERT(p[0] == '\0');
02648             KdbNumberOfColsPrinted += i;
02649         }
02650 
02651         KdbNumberOfRowsPrinted += RowsPrintedByTerminal;
02652     }
02653 }
02654 
02656 /*
02657  * Reverse memchr()
02658  * Find the last occurrence of 'c' in the buffer 's' of size 'n'.
02659  */
02660 void *
02661 memrchr(const void *s, int c, size_t n)
02662 {
02663     const unsigned char *cp;
02664 
02665     if (n != 0)
02666     {
02667         cp = (unsigned char *)s + n;
02668         do
02669         {
02670             if (*(--cp) == (unsigned char)c)
02671                 return (void *)cp;
02672         } while (--n != 0);
02673     }
02674     return NULL;
02675 }
02676 
02688 PCHAR
02689 CountOnePageUp(PCHAR Buffer, ULONG BufLength, PCHAR pCurPos)
02690 {
02691     PCHAR p;
02692     // p0 is initial guess of Page Start
02693     ULONG p0len = KdbNumberOfRowsTerminal * KdbNumberOfColsTerminal;
02694     PCHAR p0 = pCurPos - p0len;
02695     PCHAR prev_p = p0, p1;
02696     ULONG j;
02697 
02698     if (pCurPos < Buffer)
02699         pCurPos = Buffer;
02700     ASSERT(pCurPos <= Buffer + BufLength);
02701 
02702     p = memrchr(p0, '\n', p0len);
02703     if (NULL == p)
02704         p = p0;
02705     for (j = KdbNumberOfRowsTerminal; j--; )
02706     {
02707         int linesCnt;
02708         p1 = memrchr(p0, '\n', p-p0);
02709         prev_p = p;
02710         p = p1;
02711         if (NULL == p)
02712         {
02713             p = prev_p;
02714             if (NULL == p)
02715                 p = p0;
02716             break;
02717         }
02718         linesCnt = (KdbNumberOfColsTerminal+prev_p-p-2) / KdbNumberOfColsTerminal;
02719         if (linesCnt > 1)
02720             j -= linesCnt-1;
02721     }
02722 
02723     ASSERT(p != 0);
02724     ++p;
02725     return p;
02726 }
02727 
02740 VOID
02741 KdbpPager(
02742     IN PCHAR Buffer,
02743     IN ULONG BufLength)
02744 {
02745     static CHAR InBuffer[4096];
02746     static BOOLEAN TerminalInitialized = FALSE;
02747     static BOOLEAN TerminalConnected = FALSE;
02748     static BOOLEAN TerminalReportsSize = TRUE;
02749     CHAR c = '\0';
02750     PCHAR p, p2;
02751     ULONG Length;
02752     ULONG i, j;
02753     LONG RowsPrintedByTerminal;
02754     ULONG ScanCode;
02755 
02756     if( BufLength == 0)
02757       return;
02758 
02759     /* Check if the user has aborted output of the current command */
02760     if (KdbOutputAborted)
02761         return;
02762 
02763     /* Initialize the terminal */
02764     if (!TerminalInitialized)
02765     {
02766         DbgPrint("\x1b[7h");      /* Enable linewrap */
02767 
02768         /* Query terminal type */
02769         /*DbgPrint("\x1b[Z");*/
02770         DbgPrint("\x05");
02771 
02772         TerminalInitialized = TRUE;
02773         Length = 0;
02774         KeStallExecutionProcessor(100000);
02775 
02776         for (;;)
02777         {
02778             c = KdbpTryGetCharSerial(5000);
02779             if (c == -1)
02780                 break;
02781 
02782             InBuffer[Length++] = c;
02783             if (Length >= (sizeof (InBuffer) - 1))
02784                 break;
02785         }
02786 
02787         InBuffer[Length] = '\0';
02788         if (Length > 0)
02789             TerminalConnected = TRUE;
02790     }
02791 
02792     /* Get number of rows and columns in terminal */
02793     if ((KdbNumberOfRowsTerminal < 0) || (KdbNumberOfColsTerminal < 0) ||
02794         (KdbNumberOfRowsPrinted) == 0) /* Refresh terminal size each time when number of rows printed is 0 */
02795     {
02796         if ((KdbDebugState & KD_DEBUG_KDSERIAL) && TerminalConnected && TerminalReportsSize)
02797         {
02798             /* Try to query number of rows from terminal. A reply looks like "\x1b[8;24;80t" */
02799             TerminalReportsSize = FALSE;
02800             KeStallExecutionProcessor(100000);
02801             DbgPrint("\x1b[18t");
02802             c = KdbpTryGetCharSerial(5000);
02803 
02804             if (c == KEY_ESC)
02805             {
02806                 c = KdbpTryGetCharSerial(5000);
02807                 if (c == '[')
02808                 {
02809                     Length = 0;
02810 
02811                     for (;;)
02812                     {
02813                         c = KdbpTryGetCharSerial(5000);
02814                         if (c == -1)
02815                             break;
02816 
02817                         InBuffer[Length++] = c;
02818                         if (isalpha(c) || Length >= (sizeof (InBuffer) - 1))
02819                             break;
02820                     }
02821 
02822                     InBuffer[Length] = '\0';
02823                     if (InBuffer[0] == '8' && InBuffer[1] == ';')
02824                     {
02825                         for (i = 2; (i < Length) && (InBuffer[i] != ';'); i++);
02826 
02827                         if (Buffer[i] == ';')
02828                         {
02829                             Buffer[i++] = '\0';
02830 
02831                             /* Number of rows is now at Buffer + 2 and number of cols at Buffer + i */
02832                             KdbNumberOfRowsTerminal = strtoul(InBuffer + 2, NULL, 0);
02833                             KdbNumberOfColsTerminal = strtoul(InBuffer + i, NULL, 0);
02834                             TerminalReportsSize = TRUE;
02835                         }
02836                     }
02837                 }
02838                 /* Clear further characters */
02839                 while ((c = KdbpTryGetCharSerial(5000)) != -1);
02840             }
02841         }
02842 
02843         if (KdbNumberOfRowsTerminal <= 0)
02844         {
02845             /* Set number of rows to the default. */
02846             KdbNumberOfRowsTerminal = 24;
02847         }
02848         else if (KdbNumberOfColsTerminal <= 0)
02849         {
02850             /* Set number of cols to the default. */
02851             KdbNumberOfColsTerminal = 80;
02852         }
02853     }
02854 
02855     /* Get the string */
02856     p = Buffer;
02857 
02858     while (p[0] != '\0')
02859     {
02860         if ( p > Buffer+BufLength)
02861         {
02862           DbgPrint("Dmesg: error, p > Buffer+BufLength,d=%d", p - (Buffer+BufLength));
02863           return;
02864         }
02865         i = strcspn(p, "\n");
02866 
02867         // Are we out of buffer?
02868         if (p + i > Buffer + BufLength)
02869           // Leaving pager function:
02870           break;
02871 
02872         /* Calculate the number of lines which will be printed in the terminal
02873          * when outputting the current line
02874          */
02875         if (i > 0)
02876             RowsPrintedByTerminal = (i + KdbNumberOfColsPrinted - 1) / KdbNumberOfColsTerminal;
02877         else
02878             RowsPrintedByTerminal = 0;
02879 
02880         if (p[i] == '\n')
02881             RowsPrintedByTerminal++;
02882 
02883         /*DbgPrint("!%d!%d!%d!%d!", KdbNumberOfRowsPrinted, KdbNumberOfColsPrinted, i, RowsPrintedByTerminal);*/
02884 
02885         /* Display a prompt if we printed one screen full of text */
02886         if (KdbNumberOfRowsTerminal > 0 &&
02887             (LONG)(KdbNumberOfRowsPrinted + RowsPrintedByTerminal) >= KdbNumberOfRowsTerminal)
02888         {
02889             KdbRepeatLastCommand = FALSE;
02890 
02891             if (KdbNumberOfColsPrinted > 0)
02892                 DbgPrint("\n");
02893 
02894             DbgPrint("--- Press q to abort, e/End,h/Home,u/PgUp, other key/PgDn ---");
02895             RowsPrintedByTerminal++;
02896 
02897             if (KdbDebugState & KD_DEBUG_KDSERIAL)
02898                 c = KdbpGetCharSerial();
02899             else
02900                 c = KdbpGetCharKeyboard(&ScanCode);
02901 
02902             if (c == '\r')
02903             {
02904                 /* Try to read '\n' which might follow '\r' - if \n is not received here
02905                  * it will be interpreted as "return" when the next command should be read.
02906                  */
02907                 if (KdbDebugState & KD_DEBUG_KDSERIAL)
02908                     c = KdbpTryGetCharSerial(5);
02909                 else
02910                     c = KdbpTryGetCharKeyboard(&ScanCode, 5);
02911             }
02912 
02913             //DbgPrint("\n"); //Consize version: don't show pressed key
02914             DbgPrint(" '%c'/scan=%04x\n", c, ScanCode); // Shows pressed key
02915 
02916             if (c == 'q')
02917             {
02918                 KdbOutputAborted = TRUE;
02919                 return;
02920             }
02921             if (     ScanCode == KEYSC_END || c=='e')
02922             {
02923               PCHAR pBufEnd = Buffer + BufLength;
02924               p = CountOnePageUp(Buffer, BufLength, pBufEnd);
02925               i = strcspn(p, "\n");
02926             }
02927             else if (ScanCode == KEYSC_PAGEUP  || c=='u')
02928             {
02929               p = CountOnePageUp(Buffer, BufLength, p);
02930               i = strcspn(p, "\n");
02931             }
02932             else if (ScanCode == KEYSC_HOME || c=='h')
02933             {
02934               p = Buffer;
02935               i = strcspn(p, "\n");
02936             }
02937             else if (ScanCode == KEYSC_ARROWUP)
02938             {
02939               p = CountOnePageUp(Buffer, BufLength, p);
02940               i = strcspn(p, "\n");
02941             }
02942 
02943             KdbNumberOfRowsPrinted = 0;
02944             KdbNumberOfColsPrinted = 0;
02945         }
02946 
02947         /* Insert a NUL after the line and print only the current line. */
02948         if (p[i] == '\n' && p[i + 1] != '\0')
02949         {
02950             c = p[i + 1];
02951             p[i + 1] = '\0';
02952         }
02953         else
02954         {
02955             c = '\0';
02956         }
02957 
02958         /* Remove escape sequences from the line if there's no terminal connected */
02959         if (!TerminalConnected)
02960         {
02961             while ((p2 = strrchr(p, '\x1b'))) /* Look for escape character */
02962             {
02963                 if (p2[1] == '[')
02964                 {
02965                     j = 2;
02966                     while (!isalpha(p2[j++]));
02967                     strcpy(p2, p2 + j);
02968                 }
02969                 else
02970                 {
02971                     strcpy(p2, p2 + 1);
02972                 }
02973             }
02974         }
02975 
02976         // The main printing of the current line:
02977         DbgPrint(p);
02978 
02979         // restore not null char with saved:
02980         if (c != '\0')
02981             p[i + 1] = c;
02982 
02983         /* Set p to the start of the next line and
02984          * remember the number of rows/cols printed
02985          */
02986         p += i;
02987         if (p[0] == '\n')
02988         {
02989             p++;
02990             KdbNumberOfColsPrinted = 0;
02991         }
02992         else
02993         {
02994             ASSERT(p[0] == '\0');
02995             KdbNumberOfColsPrinted += i;
02996         }
02997 
02998         KdbNumberOfRowsPrinted += RowsPrintedByTerminal;
02999     }
03000 }
03001 
03006 static VOID
03007 KdbpCommandHistoryAppend(
03008     IN PCHAR Command)
03009 {
03010     ULONG Length1 = strlen(Command) + 1;
03011     ULONG Length2 = 0;
03012     INT i;
03013     PCHAR Buffer;
03014 
03015     ASSERT(Length1 <= RTL_NUMBER_OF(KdbCommandHistoryBuffer));
03016 
03017     if (Length1 <= 1 ||
03018         (KdbCommandHistory[KdbCommandHistoryIndex] &&
03019          strcmp(KdbCommandHistory[KdbCommandHistoryIndex], Command) == 0))
03020     {
03021         return;
03022     }
03023 
03024     /* Calculate Length1 and Length2 */
03025     Buffer = KdbCommandHistoryBuffer + KdbCommandHistoryBufferIndex;
03026     KdbCommandHistoryBufferIndex += Length1;
03027     if (KdbCommandHistoryBufferIndex >= (LONG)RTL_NUMBER_OF(KdbCommandHistoryBuffer))
03028     {
03029         KdbCommandHistoryBufferIndex -= RTL_NUMBER_OF(KdbCommandHistoryBuffer);
03030         Length2 = KdbCommandHistoryBufferIndex;
03031         Length1 -= Length2;
03032     }
03033 
03034     /* Remove previous commands until there is enough space to append the new command */
03035     for (i = KdbCommandHistoryIndex; KdbCommandHistory[i];)
03036     {
03037         if ((Length2 > 0 &&
03038             (KdbCommandHistory[i] >= Buffer ||
03039              KdbCommandHistory[i] < (KdbCommandHistoryBuffer + KdbCommandHistoryBufferIndex))) ||
03040             (Length2 <= 0 &&
03041              (KdbCommandHistory[i] >= Buffer &&
03042               KdbCommandHistory[i] < (KdbCommandHistoryBuffer + KdbCommandHistoryBufferIndex))))
03043         {
03044             KdbCommandHistory[i] = NULL;
03045         }
03046 
03047         i--;
03048         if (i < 0)
03049             i = RTL_NUMBER_OF(KdbCommandHistory) - 1;
03050 
03051         if (i == KdbCommandHistoryIndex)
03052             break;
03053     }
03054 
03055     /* Make sure the new command history entry is free */
03056     KdbCommandHistoryIndex++;
03057     KdbCommandHistoryIndex %= RTL_NUMBER_OF(KdbCommandHistory);
03058     if (KdbCommandHistory[KdbCommandHistoryIndex])
03059     {
03060         KdbCommandHistory[KdbCommandHistoryIndex] = NULL;
03061     }
03062 
03063     /* Append command */
03064     KdbCommandHistory[KdbCommandHistoryIndex] = Buffer;
03065     ASSERT((KdbCommandHistory[KdbCommandHistoryIndex] + Length1) <= KdbCommandHistoryBuffer + RTL_NUMBER_OF(KdbCommandHistoryBuffer));
03066     memcpy(KdbCommandHistory[KdbCommandHistoryIndex], Command, Length1);
03067     if (Length2 > 0)
03068     {
03069         memcpy(KdbCommandHistoryBuffer, Command + Length1, Length2);
03070     }
03071 }
03072 
03080 static VOID
03081 KdbpReadCommand(
03082     OUT PCHAR Buffer,
03083     IN  ULONG Size)
03084 {
03085     CHAR Key;
03086     PCHAR Orig = Buffer;
03087     ULONG ScanCode = 0;
03088     BOOLEAN EchoOn;
03089     static CHAR LastCommand[1024];
03090     static CHAR NextKey = '\0';
03091     INT CmdHistIndex = -1;
03092     INT i;
03093 
03094     EchoOn = !((KdbDebugState & KD_DEBUG_KDNOECHO) != 0);
03095 
03096     for (;;)
03097     {
03098         if (KdbDebugState & KD_DEBUG_KDSERIAL)
03099         {
03100             Key = (NextKey == '\0') ? KdbpGetCharSerial() : NextKey;
03101             NextKey = '\0';
03102             ScanCode = 0;
03103             if (Key == KEY_ESC) /* ESC */
03104             {
03105                 Key = KdbpGetCharSerial();
03106                 if (Key == '[')
03107                 {
03108                     Key = KdbpGetCharSerial();
03109 
03110                     switch (Key)
03111                     {
03112                         case 'A':
03113                             ScanCode = KEY_SCAN_UP;
03114                             break;
03115                         case 'B':
03116                             ScanCode = KEY_SCAN_DOWN;
03117                             break;
03118                         case 'C':
03119                             break;
03120                         case 'D':
03121                             break;
03122                     }
03123                 }
03124             }
03125         }
03126         else
03127         {
03128             ScanCode = 0;
03129             Key = (NextKey == '\0') ? KdbpGetCharKeyboard(&ScanCode) : NextKey;
03130             NextKey = '\0';
03131         }
03132 
03133         if ((ULONG)(Buffer - Orig) >= (Size - 1))
03134         {
03135             /* Buffer is full, accept only newlines */
03136             if (Key != '\n')
03137                 continue;
03138         }
03139 
03140         if (Key == '\r')
03141         {
03142             /* Read the next char - this is to throw away a \n which most clients should
03143              * send after \r.
03144              */
03145             KeStallExecutionProcessor(100000);
03146 
03147             if (KdbDebugState & KD_DEBUG_KDSERIAL)
03148                 NextKey = KdbpTryGetCharSerial(5);
03149             else
03150                 NextKey = KdbpTryGetCharKeyboard(&ScanCode, 5);
03151 
03152             if (NextKey == '\n' || NextKey == -1) /* \n or no response at all */
03153                 NextKey = '\0';
03154 
03155             KdbpPrint("\n");
03156 
03157             /*
03158              * Repeat the last command if the user presses enter. Reduces the
03159              * risk of RSI when single-stepping.
03160              */
03161             if (Buffer != Orig)
03162             {
03163                 KdbRepeatLastCommand = TRUE;
03164                 *Buffer = '\0';
03165                 RtlStringCbCopyA(LastCommand, sizeof(LastCommand), Orig);
03166             }
03167             else if (KdbRepeatLastCommand)
03168                 RtlStringCbCopyA(Buffer, Size, LastCommand);
03169             else
03170                 *Buffer = '\0';
03171 
03172             return;
03173         }
03174         else if (Key == KEY_BS || Key == KEY_DEL)
03175         {
03176             if (Buffer > Orig)
03177             {
03178                 Buffer--;
03179                 *Buffer = 0;
03180 
03181                 if (EchoOn)
03182                     KdbpPrint("%c %c", KEY_BS, KEY_BS);
03183                 else
03184                     KdbpPrint(" %c", KEY_BS);
03185             }
03186         }
03187         else if (ScanCode == KEY_SCAN_UP)
03188         {
03189             BOOLEAN Print = TRUE;
03190 
03191             if (CmdHistIndex < 0)
03192             {
03193                 CmdHistIndex = KdbCommandHistoryIndex;
03194             }
03195             else
03196             {
03197                 i = CmdHistIndex - 1;
03198 
03199                 if (i < 0)
03200                     CmdHistIndex = RTL_NUMBER_OF(KdbCommandHistory) - 1;
03201 
03202                 if (KdbCommandHistory[i] && i != KdbCommandHistoryIndex)
03203                     CmdHistIndex = i;
03204                 else
03205                     Print = FALSE;
03206             }
03207 
03208             if (Print && KdbCommandHistory[CmdHistIndex])
03209             {
03210                 while (Buffer > Orig)
03211                 {
03212                     Buffer--;
03213                     *Buffer = 0;
03214 
03215                     if (EchoOn)
03216                         KdbpPrint("%c %c", KEY_BS, KEY_BS);
03217                     else
03218                         KdbpPrint(" %c", KEY_BS);
03219                 }
03220 
03221                 i = min(strlen(KdbCommandHistory[CmdHistIndex]), Size - 1);
03222                 memcpy(Orig, KdbCommandHistory[CmdHistIndex], i);
03223                 Orig[i] = '\0';
03224                 Buffer = Orig + i;
03225                 KdbpPrint("%s", Orig);
03226             }
03227         }
03228         else if (ScanCode == KEY_SCAN_DOWN)
03229         {
03230             if (CmdHistIndex > 0 && CmdHistIndex != KdbCommandHistoryIndex)
03231             {
03232                 i = CmdHistIndex + 1;
03233                 if (i >= (INT)RTL_NUMBER_OF(KdbCommandHistory))
03234                     i = 0;
03235 
03236                 if (KdbCommandHistory[i])
03237                 {
03238                     CmdHistIndex = i;
03239                     while (Buffer > Orig)
03240                     {
03241                         Buffer--;
03242                         *Buffer = 0;
03243 
03244                         if (EchoOn)
03245                             KdbpPrint("%c %c", KEY_BS, KEY_BS);
03246                         else
03247                             KdbpPrint(" %c", KEY_BS);
03248                     }
03249 
03250                     i = min(strlen(KdbCommandHistory[CmdHistIndex]), Size - 1);
03251                     memcpy(Orig, KdbCommandHistory[CmdHistIndex], i);
03252                     Orig[i] = '\0';
03253                     Buffer = Orig + i;
03254                     KdbpPrint("%s", Orig);
03255                 }
03256             }
03257         }
03258         else
03259         {
03260             if (EchoOn)
03261                 KdbpPrint("%c", Key);
03262 
03263             *Buffer = Key;
03264             Buffer++;
03265         }
03266     }
03267 }
03268 
03276 static BOOLEAN
03277 KdbpDoCommand(
03278     IN PCHAR Command)
03279 {
03280     ULONG i;
03281     PCHAR p;
03282     ULONG Argc;
03283     static PCH Argv[256];
03284     static CHAR OrigCommand[1024];
03285 
03286     RtlStringCbCopyA(OrigCommand, sizeof(OrigCommand), Command);
03287 
03288     Argc = 0;
03289     p = Command;
03290 
03291     for (;;)
03292     {
03293         while (*p == '\t' || *p == ' ')
03294             p++;
03295 
03296         if (*p == '\0')
03297             break;
03298 
03299         i = strcspn(p, "\t ");
03300         Argv[Argc++] = p;
03301         p += i;
03302         if (*p == '\0')
03303             break;
03304 
03305         *p = '\0';
03306         p++;
03307     }
03308 
03309     if (Argc < 1)
03310         return TRUE;
03311 
03312     for (i = 0; i < RTL_NUMBER_OF(KdbDebuggerCommands); i++)
03313     {
03314         if (!KdbDebuggerCommands[i].Name)
03315             continue;
03316 
03317         if (strcmp(KdbDebuggerCommands[i].Name, Argv[0]) == 0)
03318         {
03319             return KdbDebuggerCommands[i].Fn(Argc, Argv);
03320         }
03321     }
03322 
03323     KdbpPrint("Command '%s' is unknown.\n", OrigCommand);
03324     return TRUE;
03325 }
03326 
03331 VOID
03332 KdbpCliMainLoop(
03333     IN BOOLEAN EnteredOnSingleStep)
03334 {
03335     static CHAR Command[1024];
03336     BOOLEAN Continue;
03337 
03338     if (EnteredOnSingleStep)
03339     {
03340         if (!KdbSymPrintAddress((PVOID)KdbCurrentTrapFrame->Tf.Eip, &KdbCurrentTrapFrame->Tf))
03341         {
03342             KdbpPrint("<%x>", KdbCurrentTrapFrame->Tf.Eip);
03343         }
03344 
03345         KdbpPrint(": ");
03346         if (KdbpDisassemble(KdbCurrentTrapFrame->Tf.Eip, KdbUseIntelSyntax) < 0)
03347         {
03348             KdbpPrint("<INVALID>");
03349         }
03350         KdbpPrint("\n");
03351     }
03352 
03353     /* Flush the input buffer */
03354     if (KdbDebugState & KD_DEBUG_KDSERIAL)
03355     {
03356         while (KdbpTryGetCharSerial(1) != -1);
03357     }
03358     else
03359     {
03360         ULONG ScanCode;
03361         while (KdbpTryGetCharKeyboard(&ScanCode, 1) != -1);
03362     }
03363 
03364     /* Main loop */
03365     do
03366     {
03367         /* Reset the number of rows/cols printed */
03368         KdbNumberOfRowsPrinted = KdbNumberOfColsPrinted = 0;
03369 
03370         /* Print the prompt */
03371         KdbpPrint("kdb:> ");
03372 
03373         /* Read a command and remember it */
03374         KdbpReadCommand(Command, sizeof (Command));
03375         KdbpCommandHistoryAppend(Command);
03376 
03377         /* Reset the number of rows/cols printed and output aborted state */
03378         KdbNumberOfRowsPrinted = KdbNumberOfColsPrinted = 0;
03379         KdbOutputAborted = FALSE;
03380 
03381         /* Call the command */
03382         Continue = KdbpDoCommand(Command);
03383         KdbOutputAborted = FALSE;
03384     }
03385     while (Continue);
03386 }
03387 
03392 VOID
03393 KdbpCliModuleLoaded(
03394     IN PUNICODE_STRING Name)
03395 {
03396     if (!KdbBreakOnModuleLoad)
03397         return;
03398 
03399     KdbpPrint("Module %wZ loaded.\n", Name);
03400     DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C);
03401 }
03402 
03409 VOID
03410 KdbpCliInterpretInitFile()
03411 {
03412     PCHAR p1, p2;
03413     INT i;
03414     CHAR c;
03415 
03416     /* Execute the commands in the init file */
03417     DPRINT("KDB: Executing KDBinit file...\n");
03418     p1 = KdbInitFileBuffer;
03419     while (p1[0] != '\0')
03420     {
03421         i = strcspn(p1, "\r\n");
03422         if (i > 0)
03423         {
03424             c = p1[i];
03425             p1[i] = '\0';
03426 
03427             /* Look for "break" command and comments */
03428             p2 = p1;
03429 
03430             while (isspace(p2[0]))
03431                 p2++;
03432 
03433             if (strncmp(p2, "break", sizeof("break")-1) == 0 &&
03434                 (p2[sizeof("break")-1] == '\0' || isspace(p2[sizeof("break")-1])))
03435             {
03436                 /* break into the debugger */
03437                 KdbpCliMainLoop(FALSE);
03438             }
03439             else if (p2[0] != '#' && p2[0] != '\0') /* Ignore empty lines and comments */
03440             {
03441                 KdbpDoCommand(p1);
03442             }
03443 
03444             p1[i] = c;
03445         }
03446 
03447         p1 += i;
03448         while (p1[0] == '\r' || p1[0] == '\n')
03449             p1++;
03450     }
03451     DPRINT("KDB: KDBinit executed\n");
03452 }
03453 
03458 VOID
03459 KdbpCliInit()
03460 {
03461     NTSTATUS Status;
03462     OBJECT_ATTRIBUTES ObjectAttributes;
03463     UNICODE_STRING FileName;
03464     IO_STATUS_BLOCK Iosb;
03465     FILE_STANDARD_INFORMATION FileStdInfo;
03466     HANDLE hFile = NULL;
03467     INT FileSize;
03468     PCHAR FileBuffer;
03469     ULONG OldEflags;
03470 
03471     /* Initialize the object attributes */
03472     RtlInitUnicodeString(&FileName, L"\\SystemRoot\\system32\\drivers\\etc\\KDBinit");
03473     InitializeObjectAttributes(&ObjectAttributes, &FileName, 0, NULL, NULL);
03474 
03475     /* Open the file */
03476     Status = ZwOpenFile(&hFile, FILE_READ_DATA, &ObjectAttributes, &Iosb, 0,
03477                         FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT |
03478                         FILE_NO_INTERMEDIATE_BUFFERING);
03479     if (!NT_SUCCESS(Status))
03480     {
03481         DPRINT("Could not open \\SystemRoot\\system32\\drivers\\etc\\KDBinit (Status 0x%x)", Status);
03482         return;
03483     }
03484 
03485     /* Get the size of the file */
03486     Status = ZwQueryInformationFile(hFile, &Iosb, &FileStdInfo, sizeof (FileStdInfo),
03487                                     FileStandardInformation);
03488     if (!NT_SUCCESS(Status))
03489     {
03490         ZwClose(hFile);
03491         DPRINT("Could not query size of \\SystemRoot\\system32\\drivers\\etc\\KDBinit (Status 0x%x)", Status);
03492         return;
03493     }
03494     FileSize = FileStdInfo.EndOfFile.u.LowPart;
03495 
03496     /* Allocate memory for the file */
03497     FileBuffer = ExAllocatePool(PagedPool, FileSize + 1); /* add 1 byte for terminating '\0' */
03498     if (!FileBuffer)
03499     {
03500         ZwClose(hFile);
03501         DPRINT("Could not allocate %d bytes for KDBinit file\n", FileSize);
03502         return;
03503     }
03504 
03505     /* Load file into memory */
03506     Status = ZwReadFile(hFile, 0, 0, 0, &Iosb, FileBuffer, FileSize, 0, 0);
03507     ZwClose(hFile);
03508 
03509     if (!NT_SUCCESS(Status) && Status != STATUS_END_OF_FILE)
03510     {
03511         ExFreePool(FileBuffer);
03512         DPRINT("Could not read KDBinit file into memory (Status 0x%lx)\n", Status);
03513         return;
03514     }
03515 
03516     FileSize = min(FileSize, (INT)Iosb.Information);
03517     FileBuffer[FileSize] = '\0';
03518 
03519     /* Enter critical section */
03520     OldEflags = __readeflags();
03521     _disable();
03522 
03523     /* Interpret the init file... */
03524     KdbInitFileBuffer = FileBuffer;
03525     KdbEnter();
03526     KdbInitFileBuffer = NULL;
03527 
03528     /* Leave critical section */
03529     __writeeflags(OldEflags);
03530 
03531     ExFreePool(FileBuffer);
03532 }
03533 
03534 VOID
03535 NTAPI
03536 KdpSerialDebugPrint(
03537     LPSTR Message,
03538     ULONG Length
03539 );
03540 
03541 STRING KdpPromptString = RTL_CONSTANT_STRING("kdb:> ");
03542 extern KSPIN_LOCK KdpSerialSpinLock;
03543 
03544 ULONG
03545 NTAPI
03546 KdpPrompt(IN LPSTR InString,
03547           IN USHORT InStringLength,
03548           OUT LPSTR OutString,
03549           IN USHORT OutStringLength)
03550 {
03551     USHORT i;
03552     CHAR Response;
03553     ULONG DummyScanCode;
03554     KIRQL OldIrql;
03555 
03556     /* Acquire the printing spinlock without waiting at raised IRQL */
03557     while (TRUE)
03558     {
03559         /* Wait when the spinlock becomes available */
03560         while (!KeTestSpinLock(&KdpSerialSpinLock));
03561 
03562         /* Spinlock was free, raise IRQL */
03563         KeRaiseIrql(HIGH_LEVEL, &OldIrql);
03564 
03565         /* Try to get the spinlock */
03566         if (KeTryToAcquireSpinLockAtDpcLevel(&KdpSerialSpinLock))
03567             break;
03568 
03569         /* Someone else got the spinlock, lower IRQL back */
03570         KeLowerIrql(OldIrql);
03571     }
03572 
03573     /* Loop the string to send */
03574     for (i = 0; i < InStringLength; i++)
03575     {
03576         /* Print it to serial */
03577         KdPortPutByteEx(&SerialPortInfo, *(PCHAR)(InString + i));
03578     }
03579 
03580     /* Print a new line for log neatness */
03581     KdPortPutByteEx(&SerialPortInfo, '\r');
03582     KdPortPutByteEx(&SerialPortInfo, '\n');
03583 
03584     /* Print the kdb prompt */
03585     for (i = 0; i < KdpPromptString.Length; i++)
03586     {
03587         /* Print it to serial */
03588         KdPortPutByteEx(&SerialPortInfo,
03589                         *(KdpPromptString.Buffer + i));
03590     }
03591 
03592     if (!(KdbDebugState & KD_DEBUG_KDSERIAL))
03593         KbdDisableMouse();
03594 
03595     /* Loop the whole string */
03596     for (i = 0; i < OutStringLength; i++)
03597     {
03598         /* Check if this is serial debugging mode */
03599         if (KdbDebugState & KD_DEBUG_KDSERIAL)
03600         {
03601             /* Get the character from serial */
03602             do
03603             {
03604                 Response = KdbpTryGetCharSerial(MAXULONG);
03605             } while (Response == -1);
03606         }
03607         else
03608         {
03609             /* Get the response from the keyboard */
03610             do
03611             {
03612                 Response = KdbpTryGetCharKeyboard(&DummyScanCode, MAXULONG);
03613             } while (Response == -1);
03614         }
03615 
03616         /* Check for return */
03617         if (Response == '\r')
03618         {
03619             /*
03620              * We might need to discard the next '\n'.
03621              * Wait a bit to make sure we receive it.
03622              */
03623             KeStallExecutionProcessor(100000);
03624 
03625             /* Check the mode */
03626             if (KdbDebugState & KD_DEBUG_KDSERIAL)
03627             {
03628                 /* Read and discard the next character, if any */
03629                 KdbpTryGetCharSerial(5);
03630             }
03631             else
03632             {
03633                 /* Read and discard the next character, if any */
03634                 KdbpTryGetCharKeyboard(&DummyScanCode, 5);
03635             }
03636 
03637             /*
03638              * Null terminate the output string -- documentation states that
03639              * DbgPrompt does not null terminate, but it does
03640              */
03641             *(PCHAR)(OutString + i) = 0;
03642 
03643             /* Print a new line */
03644             KdPortPutByteEx(&SerialPortInfo, '\r');
03645             KdPortPutByteEx(&SerialPortInfo, '\n');
03646 
03647             /* Release spinlock */
03648             KiReleaseSpinLock(&KdpSerialSpinLock);
03649 
03650             /* Lower IRQL back */
03651             KeLowerIrql(OldIrql);
03652 
03653             /* Return the length  */
03654             return OutStringLength + 1;
03655         }
03656 
03657         /* Write it back and print it to the log */
03658         *(PCHAR)(OutString + i) = Response;
03659         KdPortPutByteEx(&SerialPortInfo, Response);
03660     }
03661 
03662     if (!(KdbDebugState & KD_DEBUG_KDSERIAL))
03663         KbdEnableMouse();
03664 
03665     /* Print a new line */
03666     KdPortPutByteEx(&SerialPortInfo, '\r');
03667     KdPortPutByteEx(&SerialPortInfo, '\n');
03668 
03669     /* Release spinlock */
03670     KiReleaseSpinLock(&KdpSerialSpinLock);
03671 
03672     /* Lower IRQL back */
03673     KeLowerIrql(OldIrql);
03674 
03675     /* Return the length  */
03676     return OutStringLength;
03677 }

Generated on Mon May 28 2012 04:37:23 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.