xref: /reactos/ntoskrnl/kdbg/kdb_cli.c (revision 52192f19)
1c2c66affSColin Finck /*
2c2c66affSColin Finck  *  ReactOS kernel
3c2c66affSColin Finck  *  Copyright (C) 2005 ReactOS Team
4c2c66affSColin Finck  *
5c2c66affSColin Finck  *  This program is free software; you can redistribute it and/or modify
6c2c66affSColin Finck  *  it under the terms of the GNU General Public License as published by
7c2c66affSColin Finck  *  the Free Software Foundation; either version 2 of the License, or
8c2c66affSColin Finck  *  (at your option) any later version.
9c2c66affSColin Finck  *
10c2c66affSColin Finck  *  This program is distributed in the hope that it will be useful,
11c2c66affSColin Finck  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12c2c66affSColin Finck  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13c2c66affSColin Finck  *  GNU General Public License for more details.
14c2c66affSColin Finck  *
15c2c66affSColin Finck  *  You should have received a copy of the GNU General Public License along
16c2c66affSColin Finck  *  with this program; if not, write to the Free Software Foundation, Inc.,
17c2c66affSColin Finck  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18c2c66affSColin Finck  */
19c2c66affSColin Finck /*
20c2c66affSColin Finck  * PROJECT:         ReactOS kernel
21c2c66affSColin Finck  * FILE:            ntoskrnl/kdbg/kdb_cli.c
22c2c66affSColin Finck  * PURPOSE:         Kernel debugger command line interface
23c2c66affSColin Finck  * PROGRAMMER:      Gregor Anich (blight@blight.eu.org)
2425336250STimo Kreuzer  *                  Hervé Poussineau
25c2c66affSColin Finck  * UPDATE HISTORY:
26c2c66affSColin Finck  *                  Created 16/01/2005
27c2c66affSColin Finck  */
28c2c66affSColin Finck 
29c2c66affSColin Finck /* INCLUDES ******************************************************************/
30c2c66affSColin Finck 
31c2c66affSColin Finck #include <ntoskrnl.h>
328de4d4d2SSerge Gautherie 
33579eab8aSHermès Bélusca-Maïto #include "kdb.h"
34f3dd7133SHermès Bélusca-Maïto #include "../kd/kdterminal.h"
35c2c66affSColin Finck 
36c2c66affSColin Finck #define NDEBUG
379808d32fSHermès Bélusca-Maïto #include "debug.h"
38c2c66affSColin Finck 
39c2c66affSColin Finck /* DEFINES *******************************************************************/
40c2c66affSColin Finck 
41c2c66affSColin Finck #define KDB_ENTER_CONDITION_TO_STRING(cond)                               \
42c2c66affSColin Finck                    ((cond) == KdbDoNotEnter ? "never" :                   \
43c2c66affSColin Finck                    ((cond) == KdbEnterAlways ? "always" :                 \
44c2c66affSColin Finck                    ((cond) == KdbEnterFromKmode ? "kmode" : "umode")))
45c2c66affSColin Finck 
46c2c66affSColin Finck #define KDB_ACCESS_TYPE_TO_STRING(type)                                   \
47c2c66affSColin Finck                    ((type) == KdbAccessRead ? "read" :                    \
48c2c66affSColin Finck                    ((type) == KdbAccessWrite ? "write" :                  \
49c2c66affSColin Finck                    ((type) == KdbAccessReadWrite ? "rdwr" : "exec")))
50c2c66affSColin Finck 
51c2c66affSColin Finck #define NPX_STATE_TO_STRING(state)                                        \
52c2c66affSColin Finck                    ((state) == NPX_STATE_LOADED ? "Loaded" :              \
53c2c66affSColin Finck                    ((state) == NPX_STATE_NOT_LOADED ? "Not loaded" : "Unknown"))
54c2c66affSColin Finck 
55c2c66affSColin Finck /* PROTOTYPES ****************************************************************/
56c2c66affSColin Finck 
57c2c66affSColin Finck static BOOLEAN KdbpCmdEvalExpression(ULONG Argc, PCHAR Argv[]);
58c2c66affSColin Finck static BOOLEAN KdbpCmdDisassembleX(ULONG Argc, PCHAR Argv[]);
59c2c66affSColin Finck static BOOLEAN KdbpCmdRegs(ULONG Argc, PCHAR Argv[]);
60c2c66affSColin Finck static BOOLEAN KdbpCmdBackTrace(ULONG Argc, PCHAR Argv[]);
61c2c66affSColin Finck 
62c2c66affSColin Finck static BOOLEAN KdbpCmdContinue(ULONG Argc, PCHAR Argv[]);
63c2c66affSColin Finck static BOOLEAN KdbpCmdStep(ULONG Argc, PCHAR Argv[]);
64c2c66affSColin Finck static BOOLEAN KdbpCmdBreakPointList(ULONG Argc, PCHAR Argv[]);
65c2c66affSColin Finck static BOOLEAN KdbpCmdEnableDisableClearBreakPoint(ULONG Argc, PCHAR Argv[]);
66c2c66affSColin Finck static BOOLEAN KdbpCmdBreakPoint(ULONG Argc, PCHAR Argv[]);
67c2c66affSColin Finck 
68c2c66affSColin Finck static BOOLEAN KdbpCmdThread(ULONG Argc, PCHAR Argv[]);
69c2c66affSColin Finck static BOOLEAN KdbpCmdProc(ULONG Argc, PCHAR Argv[]);
70c2c66affSColin Finck 
71c2c66affSColin Finck static BOOLEAN KdbpCmdMod(ULONG Argc, PCHAR Argv[]);
72c2c66affSColin Finck static BOOLEAN KdbpCmdGdtLdtIdt(ULONG Argc, PCHAR Argv[]);
73c2c66affSColin Finck static BOOLEAN KdbpCmdPcr(ULONG Argc, PCHAR Argv[]);
743726b992SJérôme Gardou #ifdef _M_IX86
75c2c66affSColin Finck static BOOLEAN KdbpCmdTss(ULONG Argc, PCHAR Argv[]);
763726b992SJérôme Gardou #endif
77c2c66affSColin Finck 
78c2c66affSColin Finck static BOOLEAN KdbpCmdBugCheck(ULONG Argc, PCHAR Argv[]);
79c2c66affSColin Finck static BOOLEAN KdbpCmdReboot(ULONG Argc, PCHAR Argv[]);
80c2c66affSColin Finck static BOOLEAN KdbpCmdFilter(ULONG Argc, PCHAR Argv[]);
81c2c66affSColin Finck static BOOLEAN KdbpCmdSet(ULONG Argc, PCHAR Argv[]);
82c2c66affSColin Finck static BOOLEAN KdbpCmdHelp(ULONG Argc, PCHAR Argv[]);
83c2c66affSColin Finck static BOOLEAN KdbpCmdDmesg(ULONG Argc, PCHAR Argv[]);
84c2c66affSColin Finck 
85c2c66affSColin Finck BOOLEAN ExpKdbgExtPool(ULONG Argc, PCHAR Argv[]);
8678b55550SPierre Schweitzer BOOLEAN ExpKdbgExtPoolUsed(ULONG Argc, PCHAR Argv[]);
8712e57956SPierre Schweitzer BOOLEAN ExpKdbgExtPoolFind(ULONG Argc, PCHAR Argv[]);
88cb52c821SPierre Schweitzer BOOLEAN ExpKdbgExtFileCache(ULONG Argc, PCHAR Argv[]);
89d35243d4SPierre Schweitzer BOOLEAN ExpKdbgExtDefWrites(ULONG Argc, PCHAR Argv[]);
9047b48520SPierre Schweitzer BOOLEAN ExpKdbgExtIrpFind(ULONG Argc, PCHAR Argv[]);
912991f6e7SPierre Schweitzer BOOLEAN ExpKdbgExtHandle(ULONG Argc, PCHAR Argv[]);
92d6dc1fd2SPierre Schweitzer 
9325336250STimo Kreuzer extern char __ImageBase;
9425336250STimo Kreuzer 
95c2c66affSColin Finck #ifdef __ROS_DWARF__
96c2c66affSColin Finck static BOOLEAN KdbpCmdPrintStruct(ULONG Argc, PCHAR Argv[]);
97c2c66affSColin Finck #endif
98c2c66affSColin Finck 
993726b992SJérôme Gardou /* Be more descriptive than intrinsics */
1003726b992SJérôme Gardou #ifndef Ke386GetGlobalDescriptorTable
1013726b992SJérôme Gardou # define Ke386GetGlobalDescriptorTable __sgdt
1023726b992SJérôme Gardou #endif
1033726b992SJérôme Gardou #ifndef Ke386GetLocalDescriptorTable
1043726b992SJérôme Gardou # define Ke386GetLocalDescriptorTable __sldt
1053726b992SJérôme Gardou #endif
1063726b992SJérôme Gardou 
1073726b992SJérôme Gardou /* Portability */
1083726b992SJérôme Gardou FORCEINLINE
1093726b992SJérôme Gardou ULONG_PTR
strtoulptr(const char * nptr,char ** endptr,int base)1103726b992SJérôme Gardou strtoulptr(const char* nptr, char** endptr, int base)
1113726b992SJérôme Gardou {
1123726b992SJérôme Gardou #ifdef _M_IX86
1133726b992SJérôme Gardou     return strtoul(nptr, endptr, base);
1143726b992SJérôme Gardou #else
1153726b992SJérôme Gardou     return strtoull(nptr, endptr, base);
1163726b992SJérôme Gardou #endif
1173726b992SJérôme Gardou }
1183726b992SJérôme Gardou 
119c2c66affSColin Finck /* GLOBALS *******************************************************************/
120c2c66affSColin Finck 
121ba37323aSHervé Poussineau typedef
122ba37323aSHervé Poussineau BOOLEAN
123ba37323aSHervé Poussineau (NTAPI *PKDBG_CLI_ROUTINE)(
124ba37323aSHervé Poussineau     IN PCHAR Command,
125ba37323aSHervé Poussineau     IN ULONG Argc,
126ba37323aSHervé Poussineau     IN PCH Argv[]);
127ba37323aSHervé Poussineau 
128c2c66affSColin Finck static PKDBG_CLI_ROUTINE KdbCliCallbacks[10];
129c2c66affSColin Finck static BOOLEAN KdbUseIntelSyntax = FALSE; /* Set to TRUE for intel syntax */
130c2c66affSColin Finck static BOOLEAN KdbBreakOnModuleLoad = FALSE; /* Set to TRUE to break into KDB when a module is loaded */
131c2c66affSColin Finck 
132c2c66affSColin Finck static ULONG KdbNumberOfRowsPrinted = 0;
133c2c66affSColin Finck static ULONG KdbNumberOfColsPrinted = 0;
134c2c66affSColin Finck static BOOLEAN KdbOutputAborted = FALSE;
135c2c66affSColin Finck static BOOLEAN KdbRepeatLastCommand = FALSE;
136c2c66affSColin Finck 
137b15963abSHermès Bélusca-Maïto volatile PCHAR KdbInitFileBuffer = NULL; /* Buffer where KDBinit file is loaded into during initialization */
138c2c66affSColin Finck BOOLEAN KdbpBugCheckRequested = FALSE;
139c2c66affSColin Finck 
140bf734e53SHervé Poussineau /* Variables for Dmesg */
141bf734e53SHervé Poussineau static const ULONG KdpDmesgBufferSize = 128 * 1024; // 512*1024;
142bf734e53SHervé Poussineau static PCHAR KdpDmesgBuffer = NULL;
143bf734e53SHervé Poussineau static volatile ULONG KdpDmesgCurrentPosition = 0;
144bf734e53SHervé Poussineau static volatile ULONG KdpDmesgFreeBytes = 0;
145bf734e53SHervé Poussineau static volatile ULONG KdbDmesgTotalWritten = 0;
146bf734e53SHervé Poussineau static volatile BOOLEAN KdbpIsInDmesgMode = FALSE;
147bf734e53SHervé Poussineau static KSPIN_LOCK KdpDmesgLogSpinLock;
148c2c66affSColin Finck 
149f620ce77SHermès Bélusca-Maïto const CSTRING KdbPromptStr = RTL_CONSTANT_STRING("kdb:> ");
150a890fc64SHermès Bélusca-Maïto 
15140c57de7SHermès Bélusca-Maïto //
15240c57de7SHermès Bélusca-Maïto // Debug Filter Component Table
15340c57de7SHermès Bélusca-Maïto //
1547d3dac32SHermès Bélusca-Maïto #define KD_DEBUG_PRINT_FILTER(Name) \
1557d3dac32SHermès Bélusca-Maïto     { #Name, DPFLTR_##Name##_ID }
1567d3dac32SHermès Bélusca-Maïto 
157c2c66affSColin Finck static struct
158c2c66affSColin Finck {
15940c57de7SHermès Bélusca-Maïto     PCSTR Name;
160c2c66affSColin Finck     ULONG Id;
161c2c66affSColin Finck }
162c2c66affSColin Finck ComponentTable[] =
163c2c66affSColin Finck {
1646c1aac69SHermès Bélusca-Maïto //
1656c1aac69SHermès Bélusca-Maïto // Default components
1666c1aac69SHermès Bélusca-Maïto //
1676c1aac69SHermès Bélusca-Maïto     { "WIN2000", MAXULONG },
1687d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(DEFAULT),
1696c1aac69SHermès Bélusca-Maïto //
1706c1aac69SHermès Bélusca-Maïto // Standard components
1716c1aac69SHermès Bélusca-Maïto //
1727d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(SYSTEM),
1737d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(SMSS),
1747d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(SETUP),
1757d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(NTFS),
1767d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(FSTUB),
1777d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(CRASHDUMP),
1787d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(CDAUDIO),
1797d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(CDROM),
1807d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(CLASSPNP),
1817d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(DISK),
1827d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(REDBOOK),
1837d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(STORPROP),
1847d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(SCSIPORT),
1857d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(SCSIMINIPORT),
1867d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(CONFIG),
1877d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(I8042PRT),
1887d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(SERMOUSE),
1897d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(LSERMOUS),
1907d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(KBDHID),
1917d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(MOUHID),
1927d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(KBDCLASS),
1937d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(MOUCLASS),
1947d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(TWOTRACK),
1957d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(WMILIB),
1967d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(ACPI),
1977d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(AMLI),
1987d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(HALIA64),
1997d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(VIDEO),
2007d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(SVCHOST),
2017d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(VIDEOPRT),
2027d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(TCPIP),
2037d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(DMSYNTH),
2047d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(NTOSPNP),
2057d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(FASTFAT),
2067d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(SAMSS),
2077d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(PNPMGR),
2087d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(NETAPI),
2097d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(SCSERVER),
2107d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(SCCLIENT),
2117d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(SERIAL),
2127d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(SERENUM),
2137d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(UHCD),
2147d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(RPCPROXY),
2157d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(AUTOCHK),
2167d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(DCOMSS),
2177d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(UNIMODEM),
2187d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(SIS),
2197d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(FLTMGR),
2207d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(WMICORE),
2217d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(BURNENG),
2227d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(IMAPI),
2237d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(SXS),
2247d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(FUSION),
2257d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(IDLETASK),
2267d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(SOFTPCI),
2277d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(TAPE),
2287d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(MCHGR),
2297d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(IDEP),
2307d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(PCIIDE),
2317d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(FLOPPY),
2327d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(FDC),
2337d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(TERMSRV),
2347d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(W32TIME),
2357d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(PREFETCHER),
2367d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(RSFILTER),
2377d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(FCPORT),
2387d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(PCI),
2397d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(DMIO),
2407d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(DMCONFIG),
2417d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(DMADMIN),
2427d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(WSOCKTRANSPORT),
2437d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(VSS),
2447d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(PNPMEM),
2457d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(PROCESSOR),
2467d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(DMSERVER),
2477d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(SR),
2487d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(INFINIBAND),
2497d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(IHVDRIVER),
2507d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(IHVVIDEO),
2517d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(IHVAUDIO),
2527d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(IHVNETWORK),
2537d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(IHVSTREAMING),
2547d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(IHVBUS),
2557d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(HPS),
2567d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(RTLTHREADPOOL),
2577d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(LDR),
2587d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(TCPIP6),
2597d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(ISAPNP),
2607d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(SHPC),
2617d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(STORPORT),
2627d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(STORMINIPORT),
2637d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(PRINTSPOOLER),
2647d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(VSSDYNDISK),
2657d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(VERIFIER),
2667d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(VDS),
2677d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(VDSBAS),
2687d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(VDSDYN),  // Specified in Vista+
2697d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(VDSDYNDR),
2707d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(VDSLDR),  // Specified in Vista+
2717d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(VDSUTIL),
2727d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(DFRGIFC),
2737d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(MM),
2747d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(DFSC),
2757d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(WOW64),
2766c1aac69SHermès Bélusca-Maïto //
2776c1aac69SHermès Bélusca-Maïto // Components specified in Vista+, some of which we also use in ReactOS
2786c1aac69SHermès Bélusca-Maïto //
2797d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(ALPC),
2807d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(WDI),
2817d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(PERFLIB),
2827d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(KTM),
2837d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(IOSTRESS),
2847d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(HEAP),
2857d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(WHEA),
2867d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(USERGDI),
2877d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(MMCSS),
2887d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(TPM),
2897d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(THREADORDER),
2907d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(ENVIRON),
2917d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(EMS),
2927d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(WDT),
2937d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(FVEVOL),
2947d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(NDIS),
2957d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(NVCTRACE),
2967d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(LUAFV),
2977d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(APPCOMPAT),
2987d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(USBSTOR),
2997d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(SBP2PORT),
3007d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(COVERAGE),
3017d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(CACHEMGR),
3027d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(MOUNTMGR),
3037d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(CFR),
3047d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(TXF),
3057d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(KSECDD),
3067d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(FLTREGRESS),
3077d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(MPIO),
3087d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(MSDSM),
3097d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(UDFS),
3107d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(PSHED),
3117d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(STORVSP),
3127d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(LSASS),
3137d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(SSPICLI),
3147d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(CNG),
3157d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(EXFAT),
3167d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(FILETRACE),
3177d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(XSAVE),
3187d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(SE),
3197d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(DRIVEEXTENDER),
320ceb58c82SHermès Bélusca-Maïto //
321ceb58c82SHermès Bélusca-Maïto // Components specified in Windows 8
322ceb58c82SHermès Bélusca-Maïto //
3237d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(POWER),
3247d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(CRASHDUMPXHCI),
3257d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(GPIO),
3267d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(REFS),
3277d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(WER),
328ceb58c82SHermès Bélusca-Maïto //
329ceb58c82SHermès Bélusca-Maïto // Components specified in Windows 10
330ceb58c82SHermès Bélusca-Maïto //
3317d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(CAPIMG),
3327d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(VPCI),
3337d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(STORAGECLASSMEMORY),
3347d3dac32SHermès Bélusca-Maïto     KD_DEBUG_PRINT_FILTER(FSLIB),
335c2c66affSColin Finck };
3367d3dac32SHermès Bélusca-Maïto #undef KD_DEBUG_PRINT_FILTER
337c2c66affSColin Finck 
33840c57de7SHermès Bélusca-Maïto //
33940c57de7SHermès Bélusca-Maïto // Command Table
34040c57de7SHermès Bélusca-Maïto //
34140c57de7SHermès Bélusca-Maïto static const struct
342c2c66affSColin Finck {
34340c57de7SHermès Bélusca-Maïto     PCHAR Name;
34440c57de7SHermès Bélusca-Maïto     PCHAR Syntax;
34540c57de7SHermès Bélusca-Maïto     PCHAR Help;
34640c57de7SHermès Bélusca-Maïto     BOOLEAN (*Fn)(ULONG Argc, PCHAR Argv[]);
34740c57de7SHermès Bélusca-Maïto } KdbDebuggerCommands[] = {
34840c57de7SHermès Bélusca-Maïto     /* Data */
34940c57de7SHermès Bélusca-Maïto     { NULL, NULL, "Data", NULL },
35040c57de7SHermès Bélusca-Maïto     { "?", "? expression", "Evaluate expression.", KdbpCmdEvalExpression },
35125336250STimo Kreuzer #ifdef _M_IX86 // FIXME: this is broken on x64
35240c57de7SHermès Bélusca-Maïto     { "disasm", "disasm [address] [L count]", "Disassemble count instructions at address.", KdbpCmdDisassembleX },
35325336250STimo Kreuzer #endif // _M_IX86
35440c57de7SHermès Bélusca-Maïto     { "x", "x [address] [L count]", "Display count dwords, starting at address.", KdbpCmdDisassembleX },
35540c57de7SHermès Bélusca-Maïto     { "regs", "regs", "Display general purpose registers.", KdbpCmdRegs },
35640c57de7SHermès Bélusca-Maïto     { "sregs", "sregs", "Display status registers.", KdbpCmdRegs },
35740c57de7SHermès Bélusca-Maïto     { "dregs", "dregs", "Display debug registers.", KdbpCmdRegs },
35840c57de7SHermès Bélusca-Maïto     { "bt", "bt [*frameaddr|thread id]", "Prints current backtrace or from given frame address.", KdbpCmdBackTrace },
35940c57de7SHermès Bélusca-Maïto #ifdef __ROS_DWARF__
36040c57de7SHermès Bélusca-Maïto     { "dt", "dt [mod] [type] [addr]", "Print a struct. The address is optional.", KdbpCmdPrintStruct },
36140c57de7SHermès Bélusca-Maïto #endif
36240c57de7SHermès Bélusca-Maïto     /* Flow control */
36340c57de7SHermès Bélusca-Maïto     { NULL, NULL, "Flow control", NULL },
36440c57de7SHermès Bélusca-Maïto     { "cont", "cont", "Continue execution (leave debugger).", KdbpCmdContinue },
36540c57de7SHermès Bélusca-Maïto     { "step", "step [count]", "Execute single instructions, stepping into interrupts.", KdbpCmdStep },
36640c57de7SHermès Bélusca-Maïto     { "next", "next [count]", "Execute single instructions, skipping calls and reps.", KdbpCmdStep },
36740c57de7SHermès Bélusca-Maïto     { "bl", "bl", "List breakpoints.", KdbpCmdBreakPointList },
36840c57de7SHermès Bélusca-Maïto     { "be", "be [breakpoint]", "Enable breakpoint.", KdbpCmdEnableDisableClearBreakPoint },
36940c57de7SHermès Bélusca-Maïto     { "bd", "bd [breakpoint]", "Disable breakpoint.", KdbpCmdEnableDisableClearBreakPoint },
37040c57de7SHermès Bélusca-Maïto     { "bc", "bc [breakpoint]", "Clear breakpoint.", KdbpCmdEnableDisableClearBreakPoint },
37140c57de7SHermès Bélusca-Maïto     { "bpx", "bpx [address] [IF condition]", "Set software execution breakpoint at address.", KdbpCmdBreakPoint },
37240c57de7SHermès Bélusca-Maïto     { "bpm", "bpm [r|w|rw|x] [byte|word|dword] [address] [IF condition]", "Set memory breakpoint at address.", KdbpCmdBreakPoint },
37340c57de7SHermès Bélusca-Maïto 
37440c57de7SHermès Bélusca-Maïto     /* Process/Thread */
37540c57de7SHermès Bélusca-Maïto     { NULL, NULL, "Process/Thread", NULL },
37640c57de7SHermès Bélusca-Maïto     { "thread", "thread [list[ pid]|[attach ]tid]", "List threads in current or specified process, display thread with given id or attach to thread.", KdbpCmdThread },
37740c57de7SHermès Bélusca-Maïto     { "proc", "proc [list|[attach ]pid]", "List processes, display process with given id or attach to process.", KdbpCmdProc },
37840c57de7SHermès Bélusca-Maïto 
37940c57de7SHermès Bélusca-Maïto     /* System information */
38040c57de7SHermès Bélusca-Maïto     { NULL, NULL, "System info", NULL },
38140c57de7SHermès Bélusca-Maïto     { "mod", "mod [address]", "List all modules or the one containing address.", KdbpCmdMod },
38240c57de7SHermès Bélusca-Maïto     { "gdt", "gdt", "Display the global descriptor table.", KdbpCmdGdtLdtIdt },
38340c57de7SHermès Bélusca-Maïto     { "ldt", "ldt", "Display the local descriptor table.", KdbpCmdGdtLdtIdt },
38440c57de7SHermès Bélusca-Maïto     { "idt", "idt", "Display the interrupt descriptor table.", KdbpCmdGdtLdtIdt },
38540c57de7SHermès Bélusca-Maïto     { "pcr", "pcr", "Display the processor control region.", KdbpCmdPcr },
3863726b992SJérôme Gardou #ifdef _M_IX86
38740c57de7SHermès Bélusca-Maïto     { "tss", "tss [selector|*descaddr]", "Display the current task state segment, or the one specified by its selector number or descriptor address.", KdbpCmdTss },
3883726b992SJérôme Gardou #endif
38940c57de7SHermès Bélusca-Maïto 
39040c57de7SHermès Bélusca-Maïto     /* Others */
39140c57de7SHermès Bélusca-Maïto     { NULL, NULL, "Others", NULL },
39240c57de7SHermès Bélusca-Maïto     { "bugcheck", "bugcheck", "Bugchecks the system.", KdbpCmdBugCheck },
39340c57de7SHermès Bélusca-Maïto     { "reboot", "reboot", "Reboots the system.", KdbpCmdReboot},
39440c57de7SHermès Bélusca-Maïto     { "filter", "filter [error|warning|trace|info|level]+|-[componentname|default]", "Enable/disable debug channels.", KdbpCmdFilter },
39540c57de7SHermès Bélusca-Maïto     { "set", "set [var] [value]", "Sets var to value or displays value of var.", KdbpCmdSet },
39640c57de7SHermès Bélusca-Maïto     { "dmesg", "dmesg", "Display debug messages on screen, with navigation on pages.", KdbpCmdDmesg },
39740c57de7SHermès Bélusca-Maïto     { "kmsg", "kmsg", "Kernel dmesg. Alias for dmesg.", KdbpCmdDmesg },
39840c57de7SHermès Bélusca-Maïto     { "help", "help", "Display help screen.", KdbpCmdHelp },
39940c57de7SHermès Bélusca-Maïto     { "!pool", "!pool [Address [Flags]]", "Display information about pool allocations.", ExpKdbgExtPool },
40040c57de7SHermès Bélusca-Maïto     { "!poolused", "!poolused [Flags [Tag]]", "Display pool usage.", ExpKdbgExtPoolUsed },
40140c57de7SHermès Bélusca-Maïto     { "!poolfind", "!poolfind Tag [Pool]", "Search for pool tag allocations.", ExpKdbgExtPoolFind },
40240c57de7SHermès Bélusca-Maïto     { "!filecache", "!filecache", "Display cache usage.", ExpKdbgExtFileCache },
40340c57de7SHermès Bélusca-Maïto     { "!defwrites", "!defwrites", "Display cache write values.", ExpKdbgExtDefWrites },
40440c57de7SHermès Bélusca-Maïto     { "!irpfind", "!irpfind [Pool [startaddress [criteria data]]]", "Lists IRPs potentially matching criteria.", ExpKdbgExtIrpFind },
40540c57de7SHermès Bélusca-Maïto     { "!handle", "!handle [Handle]", "Displays info about handles.", ExpKdbgExtHandle },
40640c57de7SHermès Bélusca-Maïto };
40740c57de7SHermès Bélusca-Maïto 
40840c57de7SHermès Bélusca-Maïto /* FUNCTIONS *****************************************************************/
409c2c66affSColin Finck 
410c2c66affSColin Finck /*!\brief Evaluates an expression...
411c2c66affSColin Finck  *
412c2c66affSColin Finck  * Much like KdbpRpnEvaluateExpression, but prints the error message (if any)
413c2c66affSColin Finck  * at the given offset.
414c2c66affSColin Finck  *
415c2c66affSColin Finck  * \param Expression  Expression to evaluate.
416c2c66affSColin Finck  * \param ErrOffset   Offset (in characters) to print the error message at.
417c2c66affSColin Finck  * \param Result      Receives the result on success.
418c2c66affSColin Finck  *
419c2c66affSColin Finck  * \retval TRUE   Success.
420c2c66affSColin Finck  * \retval FALSE  Failure.
421c2c66affSColin Finck  */
422c2c66affSColin Finck static BOOLEAN
KdbpEvaluateExpression(IN PCHAR Expression,IN LONG ErrOffset,OUT PULONGLONG Result)423c2c66affSColin Finck KdbpEvaluateExpression(
424c2c66affSColin Finck     IN  PCHAR Expression,
425c2c66affSColin Finck     IN  LONG ErrOffset,
426c2c66affSColin Finck     OUT PULONGLONG Result)
427c2c66affSColin Finck {
428c2c66affSColin Finck     static CHAR ErrMsgBuffer[130] = "^ ";
429c2c66affSColin Finck     LONG ExpressionErrOffset = -1;
430c2c66affSColin Finck     PCHAR ErrMsg = ErrMsgBuffer;
431c2c66affSColin Finck     BOOLEAN Ok;
432c2c66affSColin Finck 
433c2c66affSColin Finck     Ok = KdbpRpnEvaluateExpression(Expression, KdbCurrentTrapFrame, Result,
434c2c66affSColin Finck                                    &ExpressionErrOffset, ErrMsgBuffer + 2);
435c2c66affSColin Finck     if (!Ok)
436c2c66affSColin Finck     {
437c2c66affSColin Finck         if (ExpressionErrOffset >= 0)
438c2c66affSColin Finck             ExpressionErrOffset += ErrOffset;
439c2c66affSColin Finck         else
440c2c66affSColin Finck             ErrMsg += 2;
441c2c66affSColin Finck 
442c2c66affSColin Finck         KdbpPrint("%*s%s\n", ExpressionErrOffset, "", ErrMsg);
443c2c66affSColin Finck     }
444c2c66affSColin Finck 
445c2c66affSColin Finck     return Ok;
446c2c66affSColin Finck }
447c2c66affSColin Finck 
448c2c66affSColin Finck BOOLEAN
449c2c66affSColin Finck NTAPI
KdbpGetHexNumber(IN PCHAR pszNum,OUT ULONG_PTR * pulValue)450c2c66affSColin Finck KdbpGetHexNumber(
451c2c66affSColin Finck     IN PCHAR pszNum,
452c2c66affSColin Finck     OUT ULONG_PTR *pulValue)
453c2c66affSColin Finck {
454c2c66affSColin Finck     char *endptr;
455c2c66affSColin Finck 
456c2c66affSColin Finck     /* Skip optional '0x' prefix */
457c2c66affSColin Finck     if ((pszNum[0] == '0') && ((pszNum[1] == 'x') || (pszNum[1] == 'X')))
458c2c66affSColin Finck         pszNum += 2;
459c2c66affSColin Finck 
460c2c66affSColin Finck     /* Make a number from the string (hex) */
461c2c66affSColin Finck     *pulValue = strtoul(pszNum, &endptr, 16);
462c2c66affSColin Finck 
463c2c66affSColin Finck     return (*endptr == '\0');
464c2c66affSColin Finck }
465c2c66affSColin Finck 
466c2c66affSColin Finck /*!\brief Evaluates an expression and displays the result.
467c2c66affSColin Finck  */
468c2c66affSColin Finck static BOOLEAN
KdbpCmdEvalExpression(ULONG Argc,PCHAR Argv[])469c2c66affSColin Finck KdbpCmdEvalExpression(
470c2c66affSColin Finck     ULONG Argc,
471c2c66affSColin Finck     PCHAR Argv[])
472c2c66affSColin Finck {
47325336250STimo Kreuzer     ULONG i;
47425336250STimo Kreuzer     SIZE_T len;
475c2c66affSColin Finck     ULONGLONG Result = 0;
476c2c66affSColin Finck     ULONG ul;
477c2c66affSColin Finck     LONG l = 0;
478c2c66affSColin Finck     BOOLEAN Ok;
479c2c66affSColin Finck 
480c2c66affSColin Finck     if (Argc < 2)
481c2c66affSColin Finck     {
482c2c66affSColin Finck         KdbpPrint("?: Argument required\n");
483c2c66affSColin Finck         return TRUE;
484c2c66affSColin Finck     }
485c2c66affSColin Finck 
486c2c66affSColin Finck     /* Put the arguments back together */
487c2c66affSColin Finck     Argc--;
488c2c66affSColin Finck     for (i = 1; i < Argc; i++)
489c2c66affSColin Finck     {
490c2c66affSColin Finck         len = strlen(Argv[i]);
491c2c66affSColin Finck         Argv[i][len] = ' ';
492c2c66affSColin Finck     }
493c2c66affSColin Finck 
494c2c66affSColin Finck     /* Evaluate the expression */
495f620ce77SHermès Bélusca-Maïto     Ok = KdbpEvaluateExpression(Argv[1], KdbPromptStr.Length + (Argv[1]-Argv[0]), &Result);
496c2c66affSColin Finck     if (Ok)
497c2c66affSColin Finck     {
498c2c66affSColin Finck         if (Result > 0x00000000ffffffffLL)
499c2c66affSColin Finck         {
500c2c66affSColin Finck             if (Result & 0x8000000000000000LL)
501c2c66affSColin Finck                 KdbpPrint("0x%016I64x  %20I64u  %20I64d\n", Result, Result, Result);
502c2c66affSColin Finck             else
503c2c66affSColin Finck                 KdbpPrint("0x%016I64x  %20I64u\n", Result, Result);
504c2c66affSColin Finck         }
505c2c66affSColin Finck         else
506c2c66affSColin Finck         {
507c2c66affSColin Finck             ul = (ULONG)Result;
508c2c66affSColin Finck 
509c2c66affSColin Finck             if (ul <= 0xff && ul >= 0x80)
510c2c66affSColin Finck                 l = (LONG)((CHAR)ul);
511c2c66affSColin Finck             else if (ul <= 0xffff && ul >= 0x8000)
512c2c66affSColin Finck                 l = (LONG)((SHORT)ul);
513c2c66affSColin Finck             else
514c2c66affSColin Finck                 l = (LONG)ul;
515c2c66affSColin Finck 
516c2c66affSColin Finck             if (l < 0)
517c2c66affSColin Finck                 KdbpPrint("0x%08lx  %10lu  %10ld\n", ul, ul, l);
518c2c66affSColin Finck             else
519c2c66affSColin Finck                 KdbpPrint("0x%08lx  %10lu\n", ul, ul);
520c2c66affSColin Finck         }
521c2c66affSColin Finck     }
522c2c66affSColin Finck 
523c2c66affSColin Finck     return TRUE;
524c2c66affSColin Finck }
525c2c66affSColin Finck 
526c2c66affSColin Finck #ifdef __ROS_DWARF__
527c2c66affSColin Finck 
528c2c66affSColin Finck /*!\brief Print a struct
529c2c66affSColin Finck  */
530c2c66affSColin Finck static VOID
KdbpPrintStructInternal(PROSSYM_INFO Info,PCHAR Indent,BOOLEAN DoRead,PVOID BaseAddress,PROSSYM_AGGREGATE Aggregate)531c2c66affSColin Finck KdbpPrintStructInternal
532c2c66affSColin Finck (PROSSYM_INFO Info,
533c2c66affSColin Finck  PCHAR Indent,
534c2c66affSColin Finck  BOOLEAN DoRead,
535c2c66affSColin Finck  PVOID BaseAddress,
536c2c66affSColin Finck  PROSSYM_AGGREGATE Aggregate)
537c2c66affSColin Finck {
538c2c66affSColin Finck     ULONG i;
539c2c66affSColin Finck     ULONGLONG Result;
540c2c66affSColin Finck     PROSSYM_AGGREGATE_MEMBER Member;
541c2c66affSColin Finck     ULONG IndentLen = strlen(Indent);
542c2c66affSColin Finck     ROSSYM_AGGREGATE MemberAggregate = {0 };
543c2c66affSColin Finck 
544c2c66affSColin Finck     for (i = 0; i < Aggregate->NumElements; i++) {
545c2c66affSColin Finck         Member = &Aggregate->Elements[i];
546c2c66affSColin Finck         KdbpPrint("%s%p+%x: %s", Indent, ((PCHAR)BaseAddress) + Member->BaseOffset, Member->Size, Member->Name ? Member->Name : "<anoymous>");
547c2c66affSColin Finck         if (DoRead) {
548c2c66affSColin Finck             if (!strcmp(Member->Type, "_UNICODE_STRING")) {
54931a5fa61STimo Kreuzer                 KdbpPrint("\"");
55031a5fa61STimo Kreuzer                 KdbpPrintUnicodeString(((PCHAR)BaseAddress) + Member->BaseOffset);
55131a5fa61STimo Kreuzer                 KdbpPrint("\"\n");
552c2c66affSColin Finck                 continue;
553c2c66affSColin Finck             } else if (!strcmp(Member->Type, "PUNICODE_STRING")) {
55431a5fa61STimo Kreuzer                 KdbpPrint("\"");
55531a5fa61STimo Kreuzer                 KdbpPrintUnicodeString(*(((PUNICODE_STRING*)((PCHAR)BaseAddress) + Member->BaseOffset)));
55631a5fa61STimo Kreuzer                 KdbpPrint("\"\n");
557c2c66affSColin Finck                 continue;
558c2c66affSColin Finck             }
559c2c66affSColin Finck             switch (Member->Size) {
560c2c66affSColin Finck             case 1:
561c2c66affSColin Finck             case 2:
562c2c66affSColin Finck             case 4:
563c2c66affSColin Finck             case 8: {
564c2c66affSColin Finck                 Result = 0;
565c2c66affSColin Finck                 if (NT_SUCCESS(KdbpSafeReadMemory(&Result, ((PCHAR)BaseAddress) + Member->BaseOffset, Member->Size))) {
566c2c66affSColin Finck                     if (Member->Bits) {
567c2c66affSColin Finck                         Result >>= Member->FirstBit;
568c2c66affSColin Finck                         Result &= ((1 << Member->Bits) - 1);
569c2c66affSColin Finck                     }
570c2c66affSColin Finck                     KdbpPrint(" %lx\n", Result);
571c2c66affSColin Finck                 }
572c2c66affSColin Finck                 else goto readfail;
573c2c66affSColin Finck                 break;
574c2c66affSColin Finck             }
575c2c66affSColin Finck             default: {
576c2c66affSColin Finck                 if (Member->Size < 8) {
577c2c66affSColin Finck                     if (NT_SUCCESS(KdbpSafeReadMemory(&Result, ((PCHAR)BaseAddress) + Member->BaseOffset, Member->Size))) {
578c2c66affSColin Finck                         ULONG j;
579c2c66affSColin Finck                         for (j = 0; j < Member->Size; j++) {
580c2c66affSColin Finck                             KdbpPrint(" %02x", (int)(Result & 0xff));
581c2c66affSColin Finck                             Result >>= 8;
582c2c66affSColin Finck                         }
583c2c66affSColin Finck                     } else goto readfail;
584c2c66affSColin Finck                 } else {
585c2c66affSColin Finck                     KdbpPrint(" %s @ %p {\n", Member->Type, ((PCHAR)BaseAddress) + Member->BaseOffset);
586c2c66affSColin Finck                     Indent[IndentLen] = ' ';
587c2c66affSColin Finck                     if (RosSymAggregate(Info, Member->Type, &MemberAggregate)) {
588c2c66affSColin Finck                         KdbpPrintStructInternal(Info, Indent, DoRead, ((PCHAR)BaseAddress) + Member->BaseOffset, &MemberAggregate);
589c2c66affSColin Finck                         RosSymFreeAggregate(&MemberAggregate);
590c2c66affSColin Finck                     }
591c2c66affSColin Finck                     Indent[IndentLen] = 0;
592c2c66affSColin Finck                     KdbpPrint("%s}\n", Indent);
593c2c66affSColin Finck                 } break;
594c2c66affSColin Finck             }
595c2c66affSColin Finck             }
596c2c66affSColin Finck         } else {
597c2c66affSColin Finck         readfail:
598c2c66affSColin Finck             if (Member->Size <= 8) {
599c2c66affSColin Finck                 KdbpPrint(" ??\n");
600c2c66affSColin Finck             } else {
601c2c66affSColin Finck                 KdbpPrint(" %s @ %x {\n", Member->Type, Member->BaseOffset);
602c2c66affSColin Finck                 Indent[IndentLen] = ' ';
603c2c66affSColin Finck                 if (RosSymAggregate(Info, Member->Type, &MemberAggregate)) {
604c2c66affSColin Finck                     KdbpPrintStructInternal(Info, Indent, DoRead, BaseAddress, &MemberAggregate);
605c2c66affSColin Finck                     RosSymFreeAggregate(&MemberAggregate);
606c2c66affSColin Finck                 }
607c2c66affSColin Finck                 Indent[IndentLen] = 0;
608c2c66affSColin Finck                 KdbpPrint("%s}\n", Indent);
609c2c66affSColin Finck             }
610c2c66affSColin Finck         }
611c2c66affSColin Finck     }
612c2c66affSColin Finck }
613c2c66affSColin Finck 
614c2c66affSColin Finck PROSSYM_INFO KdbpSymFindCachedFile(PUNICODE_STRING ModName);
615c2c66affSColin Finck 
616c2c66affSColin Finck static BOOLEAN
KdbpCmdPrintStruct(ULONG Argc,PCHAR Argv[])617c2c66affSColin Finck KdbpCmdPrintStruct(
618c2c66affSColin Finck     ULONG Argc,
619c2c66affSColin Finck     PCHAR Argv[])
620c2c66affSColin Finck {
621c2c66affSColin Finck     ULONG i;
622c2c66affSColin Finck     ULONGLONG Result = 0;
6238de4d4d2SSerge Gautherie     PVOID BaseAddress = NULL;
624c2c66affSColin Finck     ROSSYM_AGGREGATE Aggregate = {0};
625c2c66affSColin Finck     UNICODE_STRING ModName = {0};
626c2c66affSColin Finck     ANSI_STRING AnsiName = {0};
627c2c66affSColin Finck     CHAR Indent[100] = {0};
628c2c66affSColin Finck     PROSSYM_INFO Info;
629c2c66affSColin Finck 
630c2c66affSColin Finck     if (Argc < 3) goto end;
631c2c66affSColin Finck     AnsiName.Length = AnsiName.MaximumLength = strlen(Argv[1]);
632c2c66affSColin Finck     AnsiName.Buffer = Argv[1];
633c2c66affSColin Finck     RtlAnsiStringToUnicodeString(&ModName, &AnsiName, TRUE);
634c2c66affSColin Finck     Info = KdbpSymFindCachedFile(&ModName);
635c2c66affSColin Finck 
636c2c66affSColin Finck     if (!Info || !RosSymAggregate(Info, Argv[2], &Aggregate)) {
637c2c66affSColin Finck         DPRINT1("Could not get aggregate\n");
638c2c66affSColin Finck         goto end;
639c2c66affSColin Finck     }
640c2c66affSColin Finck 
641c2c66affSColin Finck     // Get an argument for location if it was given
642c2c66affSColin Finck     if (Argc > 3) {
643c2c66affSColin Finck         ULONG len;
644c2c66affSColin Finck         PCHAR ArgStart = Argv[3];
6458de4d4d2SSerge Gautherie         DPRINT("Trying to get expression\n");
646c2c66affSColin Finck         for (i = 3; i < Argc - 1; i++)
647c2c66affSColin Finck         {
648c2c66affSColin Finck             len = strlen(Argv[i]);
649c2c66affSColin Finck             Argv[i][len] = ' ';
650c2c66affSColin Finck         }
651c2c66affSColin Finck 
652c2c66affSColin Finck         /* Evaluate the expression */
6538de4d4d2SSerge Gautherie         DPRINT("Arg: %s\n", ArgStart);
6548de4d4d2SSerge Gautherie         if (KdbpEvaluateExpression(ArgStart, strlen(ArgStart), &Result))
655c2c66affSColin Finck             BaseAddress = (PVOID)(ULONG_PTR)Result;
656c2c66affSColin Finck     }
6578de4d4d2SSerge Gautherie     DPRINT("BaseAddress: %p\n", BaseAddress);
658c2c66affSColin Finck     KdbpPrintStructInternal(Info, Indent, !!BaseAddress, BaseAddress, &Aggregate);
659c2c66affSColin Finck end:
660c2c66affSColin Finck     RosSymFreeAggregate(&Aggregate);
661c2c66affSColin Finck     RtlFreeUnicodeString(&ModName);
662c2c66affSColin Finck     return TRUE;
663c2c66affSColin Finck }
6648de4d4d2SSerge Gautherie #endif // __ROS_DWARF__
665c2c66affSColin Finck 
66640c57de7SHermès Bélusca-Maïto /*!\brief Retrieves the component ID corresponding to a given component name.
66740c57de7SHermès Bélusca-Maïto  *
66840c57de7SHermès Bélusca-Maïto  * \param ComponentName  The name of the component.
66940c57de7SHermès Bélusca-Maïto  * \param ComponentId    Receives the component id on success.
67040c57de7SHermès Bélusca-Maïto  *
67140c57de7SHermès Bélusca-Maïto  * \retval TRUE   Success.
67240c57de7SHermès Bélusca-Maïto  * \retval FALSE  Failure.
67340c57de7SHermès Bélusca-Maïto  */
67440c57de7SHermès Bélusca-Maïto static BOOLEAN
KdbpGetComponentId(IN PCSTR ComponentName,OUT PULONG ComponentId)67540c57de7SHermès Bélusca-Maïto KdbpGetComponentId(
67640c57de7SHermès Bélusca-Maïto     IN  PCSTR ComponentName,
67740c57de7SHermès Bélusca-Maïto     OUT PULONG ComponentId)
67840c57de7SHermès Bélusca-Maïto {
67940c57de7SHermès Bélusca-Maïto     ULONG i;
68040c57de7SHermès Bélusca-Maïto 
681b2eaf905SHermès Bélusca-Maïto     for (i = 0; i < RTL_NUMBER_OF(ComponentTable); i++)
68240c57de7SHermès Bélusca-Maïto     {
68340c57de7SHermès Bélusca-Maïto         if (_stricmp(ComponentName, ComponentTable[i].Name) == 0)
68440c57de7SHermès Bélusca-Maïto         {
68540c57de7SHermès Bélusca-Maïto             *ComponentId = ComponentTable[i].Id;
68640c57de7SHermès Bélusca-Maïto             return TRUE;
68740c57de7SHermès Bélusca-Maïto         }
68840c57de7SHermès Bélusca-Maïto     }
68940c57de7SHermès Bélusca-Maïto 
69040c57de7SHermès Bélusca-Maïto     return FALSE;
69140c57de7SHermès Bélusca-Maïto }
69240c57de7SHermès Bélusca-Maïto 
69340c57de7SHermès Bélusca-Maïto /*!\brief Displays the list of active debug channels, or enable/disable debug channels.
694c2c66affSColin Finck  */
695c2c66affSColin Finck static BOOLEAN
KdbpCmdFilter(ULONG Argc,PCHAR Argv[])696c2c66affSColin Finck KdbpCmdFilter(
697c2c66affSColin Finck     ULONG Argc,
698c2c66affSColin Finck     PCHAR Argv[])
699c2c66affSColin Finck {
700c2c66affSColin Finck     ULONG i, j, ComponentId, Level;
701c2c66affSColin Finck     ULONG set = DPFLTR_MASK, clear = DPFLTR_MASK;
702c2c66affSColin Finck     PCHAR pend;
70340c57de7SHermès Bélusca-Maïto     PCSTR opt, p;
704c2c66affSColin Finck 
705c2c66affSColin Finck     static struct
706c2c66affSColin Finck     {
70740c57de7SHermès Bélusca-Maïto         PCSTR Name;
708c2c66affSColin Finck         ULONG Level;
709c2c66affSColin Finck     }
710c2c66affSColin Finck     debug_classes[] =
711c2c66affSColin Finck     {
712c2c66affSColin Finck         { "error",   1 << DPFLTR_ERROR_LEVEL   },
713c2c66affSColin Finck         { "warning", 1 << DPFLTR_WARNING_LEVEL },
714c2c66affSColin Finck         { "trace",   1 << DPFLTR_TRACE_LEVEL   },
715c2c66affSColin Finck         { "info",    1 << DPFLTR_INFO_LEVEL    },
716c2c66affSColin Finck     };
717c2c66affSColin Finck 
71840c57de7SHermès Bélusca-Maïto     if (Argc <= 1)
71940c57de7SHermès Bélusca-Maïto     {
72040c57de7SHermès Bélusca-Maïto         /* Display the list of available debug filter components */
72140c57de7SHermès Bélusca-Maïto         KdbpPrint("REMARKS:\n"
72240c57de7SHermès Bélusca-Maïto                   "- The 'WIN2000' system-wide debug filter component is used for DbgPrint()\n"
72340c57de7SHermès Bélusca-Maïto                   "  messages without Component ID and Level.\n"
72440c57de7SHermès Bélusca-Maïto                   "- The 'DEFAULT' debug filter component is used for DbgPrint() messages with\n"
72540c57de7SHermès Bélusca-Maïto                   "  an unknown Component ID.\n\n");
72640c57de7SHermès Bélusca-Maïto         KdbpPrint("The list of debug filter components currently available on your system is:\n\n");
72740c57de7SHermès Bélusca-Maïto         KdbpPrint("    Component Name         Component ID\n"
72846416a62SHermès Bélusca-Maïto                   "  ==================     ================\n");
729b2eaf905SHermès Bélusca-Maïto         for (i = 0; i < RTL_NUMBER_OF(ComponentTable); i++)
73040c57de7SHermès Bélusca-Maïto         {
73146416a62SHermès Bélusca-Maïto             KdbpPrint("%20s        0x%08lx\n", ComponentTable[i].Name, ComponentTable[i].Id);
73240c57de7SHermès Bélusca-Maïto         }
73340c57de7SHermès Bélusca-Maïto         return TRUE;
73440c57de7SHermès Bélusca-Maïto     }
73540c57de7SHermès Bélusca-Maïto 
736c2c66affSColin Finck     for (i = 1; i < Argc; i++)
737c2c66affSColin Finck     {
738c2c66affSColin Finck         opt = Argv[i];
739c2c66affSColin Finck         p = opt + strcspn(opt, "+-");
74040c57de7SHermès Bélusca-Maïto         if (!p[0]) p = opt; /* Assume it's a debug channel name */
741c2c66affSColin Finck 
742c2c66affSColin Finck         if (p > opt)
743c2c66affSColin Finck         {
744b2eaf905SHermès Bélusca-Maïto             for (j = 0; j < RTL_NUMBER_OF(debug_classes); j++)
745c2c66affSColin Finck             {
746c2c66affSColin Finck                 SIZE_T len = strlen(debug_classes[j].Name);
747c2c66affSColin Finck                 if (len != (p - opt))
748c2c66affSColin Finck                     continue;
74940c57de7SHermès Bélusca-Maïto                 if (_strnicmp(opt, debug_classes[j].Name, len) == 0) /* Found it */
750c2c66affSColin Finck                 {
751c2c66affSColin Finck                     if (*p == '+')
752c2c66affSColin Finck                         set |= debug_classes[j].Level;
753c2c66affSColin Finck                     else
754c2c66affSColin Finck                         clear |= debug_classes[j].Level;
755c2c66affSColin Finck                     break;
756c2c66affSColin Finck                 }
757c2c66affSColin Finck             }
758b2eaf905SHermès Bélusca-Maïto             if (j == RTL_NUMBER_OF(debug_classes))
759c2c66affSColin Finck             {
760c2c66affSColin Finck                 Level = strtoul(opt, &pend, 0);
761c2c66affSColin Finck                 if (pend != p)
762c2c66affSColin Finck                 {
763c2c66affSColin Finck                     KdbpPrint("filter: bad class name '%.*s'\n", p - opt, opt);
764c2c66affSColin Finck                     continue;
765c2c66affSColin Finck                 }
766c2c66affSColin Finck                 if (*p == '+')
767c2c66affSColin Finck                     set |= Level;
768c2c66affSColin Finck                 else
769c2c66affSColin Finck                     clear |= Level;
770c2c66affSColin Finck             }
771c2c66affSColin Finck         }
772c2c66affSColin Finck         else
773c2c66affSColin Finck         {
774c2c66affSColin Finck             if (*p == '-')
775c2c66affSColin Finck                 clear = MAXULONG;
776c2c66affSColin Finck             else
777c2c66affSColin Finck                 set = MAXULONG;
778c2c66affSColin Finck         }
779c2c66affSColin Finck         if (*p == '+' || *p == '-')
780c2c66affSColin Finck             p++;
781c2c66affSColin Finck 
782c2c66affSColin Finck         if (!KdbpGetComponentId(p, &ComponentId))
783c2c66affSColin Finck         {
784c2c66affSColin Finck             KdbpPrint("filter: '%s' is not a valid component name!\n", p);
785c2c66affSColin Finck             return TRUE;
786c2c66affSColin Finck         }
787c2c66affSColin Finck 
788c2c66affSColin Finck         /* Get current mask value */
789c2c66affSColin Finck         NtSetDebugFilterState(ComponentId, set, TRUE);
790c2c66affSColin Finck         NtSetDebugFilterState(ComponentId, clear, FALSE);
791c2c66affSColin Finck     }
792c2c66affSColin Finck 
793c2c66affSColin Finck     return TRUE;
794c2c66affSColin Finck }
795c2c66affSColin Finck 
796c2c66affSColin Finck /*!\brief Disassembles 10 instructions at eip or given address or
797c2c66affSColin Finck  *        displays 16 dwords from memory at given address.
798c2c66affSColin Finck  */
799c2c66affSColin Finck static BOOLEAN
KdbpCmdDisassembleX(ULONG Argc,PCHAR Argv[])800c2c66affSColin Finck KdbpCmdDisassembleX(
801c2c66affSColin Finck     ULONG Argc,
802c2c66affSColin Finck     PCHAR Argv[])
803c2c66affSColin Finck {
804c2c66affSColin Finck     ULONG Count;
805c2c66affSColin Finck     ULONG ul;
806c2c66affSColin Finck     INT i;
807c2c66affSColin Finck     ULONGLONG Result = 0;
8083726b992SJérôme Gardou     ULONG_PTR Address = KeGetContextPc(KdbCurrentTrapFrame);
809c2c66affSColin Finck     LONG InstLen;
810c2c66affSColin Finck 
811c2c66affSColin Finck     if (Argv[0][0] == 'x') /* display memory */
812c2c66affSColin Finck         Count = 16;
813c2c66affSColin Finck     else /* disassemble */
814c2c66affSColin Finck         Count = 10;
815c2c66affSColin Finck 
816c2c66affSColin Finck     if (Argc >= 2)
817c2c66affSColin Finck     {
818c2c66affSColin Finck         /* Check for [L count] part */
819c2c66affSColin Finck         ul = 0;
820c2c66affSColin Finck         if (strcmp(Argv[Argc-2], "L") == 0)
821c2c66affSColin Finck         {
822c2c66affSColin Finck             ul = strtoul(Argv[Argc-1], NULL, 0);
823c2c66affSColin Finck             if (ul > 0)
824c2c66affSColin Finck             {
825c2c66affSColin Finck                 Count = ul;
826c2c66affSColin Finck                 Argc -= 2;
827c2c66affSColin Finck             }
828c2c66affSColin Finck         }
829c2c66affSColin Finck         else if (Argv[Argc-1][0] == 'L')
830c2c66affSColin Finck         {
831c2c66affSColin Finck             ul = strtoul(Argv[Argc-1] + 1, NULL, 0);
832c2c66affSColin Finck             if (ul > 0)
833c2c66affSColin Finck             {
834c2c66affSColin Finck                 Count = ul;
835c2c66affSColin Finck                 Argc--;
836c2c66affSColin Finck             }
837c2c66affSColin Finck         }
838c2c66affSColin Finck 
839c2c66affSColin Finck         /* Put the remaining arguments back together */
840c2c66affSColin Finck         Argc--;
841c2c66affSColin Finck         for (ul = 1; ul < Argc; ul++)
842c2c66affSColin Finck         {
843c2c66affSColin Finck             Argv[ul][strlen(Argv[ul])] = ' ';
844c2c66affSColin Finck         }
845c2c66affSColin Finck         Argc++;
846c2c66affSColin Finck     }
847c2c66affSColin Finck 
848c2c66affSColin Finck     /* Evaluate the expression */
849c2c66affSColin Finck     if (Argc > 1)
850c2c66affSColin Finck     {
851f620ce77SHermès Bélusca-Maïto         if (!KdbpEvaluateExpression(Argv[1], KdbPromptStr.Length + (Argv[1]-Argv[0]), &Result))
852c2c66affSColin Finck             return TRUE;
853c2c66affSColin Finck 
854c2c66affSColin Finck         if (Result > (ULONGLONG)(~((ULONG_PTR)0)))
855c2c66affSColin Finck             KdbpPrint("Warning: Address %I64x is beeing truncated\n",Result);
856c2c66affSColin Finck 
857c2c66affSColin Finck         Address = (ULONG_PTR)Result;
858c2c66affSColin Finck     }
859c2c66affSColin Finck     else if (Argv[0][0] == 'x')
860c2c66affSColin Finck     {
861c2c66affSColin Finck         KdbpPrint("x: Address argument required.\n");
862c2c66affSColin Finck         return TRUE;
863c2c66affSColin Finck     }
864c2c66affSColin Finck 
865c2c66affSColin Finck     if (Argv[0][0] == 'x')
866c2c66affSColin Finck     {
867c2c66affSColin Finck         /* Display dwords */
868c2c66affSColin Finck         ul = 0;
869c2c66affSColin Finck 
870c2c66affSColin Finck         while (Count > 0)
871c2c66affSColin Finck         {
872c2c66affSColin Finck             if (!KdbSymPrintAddress((PVOID)Address, NULL))
87325336250STimo Kreuzer                 KdbpPrint("<%p>:", (PVOID)Address);
874c2c66affSColin Finck             else
875c2c66affSColin Finck                 KdbpPrint(":");
876c2c66affSColin Finck 
877c2c66affSColin Finck             i = min(4, Count);
878c2c66affSColin Finck             Count -= i;
879c2c66affSColin Finck 
880c2c66affSColin Finck             while (--i >= 0)
881c2c66affSColin Finck             {
882c2c66affSColin Finck                 if (!NT_SUCCESS(KdbpSafeReadMemory(&ul, (PVOID)Address, sizeof(ul))))
883c2c66affSColin Finck                     KdbpPrint(" ????????");
884c2c66affSColin Finck                 else
885c2c66affSColin Finck                     KdbpPrint(" %08x", ul);
886c2c66affSColin Finck 
887c2c66affSColin Finck                 Address += sizeof(ul);
888c2c66affSColin Finck             }
889c2c66affSColin Finck 
890c2c66affSColin Finck             KdbpPrint("\n");
891c2c66affSColin Finck         }
892c2c66affSColin Finck     }
893c2c66affSColin Finck     else
894c2c66affSColin Finck     {
895c2c66affSColin Finck         /* Disassemble */
896c2c66affSColin Finck         while (Count-- > 0)
897c2c66affSColin Finck         {
898c2c66affSColin Finck             if (!KdbSymPrintAddress((PVOID)Address, NULL))
899c2c66affSColin Finck                 KdbpPrint("<%08x>: ", Address);
900c2c66affSColin Finck             else
901c2c66affSColin Finck                 KdbpPrint(": ");
902c2c66affSColin Finck 
903c2c66affSColin Finck             InstLen = KdbpDisassemble(Address, KdbUseIntelSyntax);
904c2c66affSColin Finck             if (InstLen < 0)
905c2c66affSColin Finck             {
906c2c66affSColin Finck                 KdbpPrint("<INVALID>\n");
907c2c66affSColin Finck                 return TRUE;
908c2c66affSColin Finck             }
909c2c66affSColin Finck 
910c2c66affSColin Finck             KdbpPrint("\n");
911c2c66affSColin Finck             Address += InstLen;
912c2c66affSColin Finck         }
913c2c66affSColin Finck     }
914c2c66affSColin Finck 
915c2c66affSColin Finck     return TRUE;
916c2c66affSColin Finck }
917c2c66affSColin Finck 
918c2c66affSColin Finck /*!\brief Displays CPU registers.
919c2c66affSColin Finck  */
920c2c66affSColin Finck static BOOLEAN
KdbpCmdRegs(ULONG Argc,PCHAR Argv[])921c2c66affSColin Finck KdbpCmdRegs(
922c2c66affSColin Finck     ULONG Argc,
923c2c66affSColin Finck     PCHAR Argv[])
924c2c66affSColin Finck {
925baa47fa5SHervé Poussineau     PCONTEXT Context = KdbCurrentTrapFrame;
926c2c66affSColin Finck     INT i;
927c2c66affSColin Finck     static const PCHAR EflagsBits[32] = { " CF", NULL, " PF", " BIT3", " AF", " BIT5",
928c2c66affSColin Finck                                           " ZF", " SF", " TF", " IF", " DF", " OF",
929c2c66affSColin Finck                                           NULL, NULL, " NT", " BIT15", " RF", " VF",
930c2c66affSColin Finck                                           " AC", " VIF", " VIP", " ID", " BIT22",
931c2c66affSColin Finck                                           " BIT23", " BIT24", " BIT25", " BIT26",
932c2c66affSColin Finck                                           " BIT27", " BIT28", " BIT29", " BIT30",
933c2c66affSColin Finck                                           " BIT31" };
934c2c66affSColin Finck 
935c2c66affSColin Finck     if (Argv[0][0] == 'r') /* regs */
936c2c66affSColin Finck     {
9373726b992SJérôme Gardou #ifdef _M_IX86
938c2c66affSColin Finck         KdbpPrint("CS:EIP  0x%04x:0x%08x\n"
939c2c66affSColin Finck                   "SS:ESP  0x%04x:0x%08x\n"
940c2c66affSColin Finck                   "   EAX  0x%08x   EBX  0x%08x\n"
941c2c66affSColin Finck                   "   ECX  0x%08x   EDX  0x%08x\n"
942c2c66affSColin Finck                   "   ESI  0x%08x   EDI  0x%08x\n"
943c2c66affSColin Finck                   "   EBP  0x%08x\n",
944baa47fa5SHervé Poussineau                   Context->SegCs & 0xFFFF, Context->Eip,
945baa47fa5SHervé Poussineau                   Context->SegSs, Context->Esp,
946baa47fa5SHervé Poussineau                   Context->Eax, Context->Ebx,
947baa47fa5SHervé Poussineau                   Context->Ecx, Context->Edx,
948baa47fa5SHervé Poussineau                   Context->Esi, Context->Edi,
949baa47fa5SHervé Poussineau                   Context->Ebp);
9503726b992SJérôme Gardou #else
9513726b992SJérôme Gardou         KdbpPrint("CS:RIP  0x%04x:0x%p\n"
9523726b992SJérôme Gardou                   "SS:RSP  0x%04x:0x%p\n"
9533726b992SJérôme Gardou                   "   RAX  0x%p     RBX  0x%p\n"
9543726b992SJérôme Gardou                   "   RCX  0x%p     RDX  0x%p\n"
9553726b992SJérôme Gardou                   "   RSI  0x%p     RDI  0x%p\n"
9563726b992SJérôme Gardou                   "   RBP  0x%p\n",
9573726b992SJérôme Gardou                   Context->SegCs & 0xFFFF, Context->Rip,
9583726b992SJérôme Gardou                   Context->SegSs, Context->Rsp,
9593726b992SJérôme Gardou                   Context->Rax, Context->Rbx,
9603726b992SJérôme Gardou                   Context->Rcx, Context->Rdx,
9613726b992SJérôme Gardou                   Context->Rsi, Context->Rdi,
9623726b992SJérôme Gardou                   Context->Rbp);
9633726b992SJérôme Gardou #endif
964dc0c721fSHermès Bélusca-Maïto         /* Display the EFlags */
965baa47fa5SHervé Poussineau         KdbpPrint("EFLAGS  0x%08x ", Context->EFlags);
966c2c66affSColin Finck         for (i = 0; i < 32; i++)
967c2c66affSColin Finck         {
968c2c66affSColin Finck             if (i == 1)
969c2c66affSColin Finck             {
970baa47fa5SHervé Poussineau                 if ((Context->EFlags & (1 << 1)) == 0)
971c2c66affSColin Finck                     KdbpPrint(" !BIT1");
972c2c66affSColin Finck             }
973c2c66affSColin Finck             else if (i == 12)
974c2c66affSColin Finck             {
975baa47fa5SHervé Poussineau                 KdbpPrint(" IOPL%d", (Context->EFlags >> 12) & 3);
976c2c66affSColin Finck             }
977c2c66affSColin Finck             else if (i == 13)
978c2c66affSColin Finck             {
979c2c66affSColin Finck             }
980baa47fa5SHervé Poussineau             else if ((Context->EFlags & (1 << i)) != 0)
981c2c66affSColin Finck             {
982c2c66affSColin Finck                 KdbpPrint(EflagsBits[i]);
983c2c66affSColin Finck             }
984c2c66affSColin Finck         }
985c2c66affSColin Finck         KdbpPrint("\n");
986c2c66affSColin Finck     }
987c2c66affSColin Finck     else if (Argv[0][0] == 's') /* sregs */
988c2c66affSColin Finck     {
989c2c66affSColin Finck         KdbpPrint("CS  0x%04x  Index 0x%04x  %cDT RPL%d\n",
990baa47fa5SHervé Poussineau                   Context->SegCs & 0xffff, (Context->SegCs & 0xffff) >> 3,
991baa47fa5SHervé Poussineau                   (Context->SegCs & (1 << 2)) ? 'L' : 'G', Context->SegCs & 3);
992c2c66affSColin Finck         KdbpPrint("DS  0x%04x  Index 0x%04x  %cDT RPL%d\n",
993baa47fa5SHervé Poussineau                   Context->SegDs, Context->SegDs >> 3, (Context->SegDs & (1 << 2)) ? 'L' : 'G', Context->SegDs & 3);
994c2c66affSColin Finck         KdbpPrint("ES  0x%04x  Index 0x%04x  %cDT RPL%d\n",
995baa47fa5SHervé Poussineau                   Context->SegEs, Context->SegEs >> 3, (Context->SegEs & (1 << 2)) ? 'L' : 'G', Context->SegEs & 3);
996c2c66affSColin Finck         KdbpPrint("FS  0x%04x  Index 0x%04x  %cDT RPL%d\n",
997baa47fa5SHervé Poussineau                   Context->SegFs, Context->SegFs >> 3, (Context->SegFs & (1 << 2)) ? 'L' : 'G', Context->SegFs & 3);
998c2c66affSColin Finck         KdbpPrint("GS  0x%04x  Index 0x%04x  %cDT RPL%d\n",
999baa47fa5SHervé Poussineau                   Context->SegGs, Context->SegGs >> 3, (Context->SegGs & (1 << 2)) ? 'L' : 'G', Context->SegGs & 3);
1000c2c66affSColin Finck         KdbpPrint("SS  0x%04x  Index 0x%04x  %cDT RPL%d\n",
1001baa47fa5SHervé Poussineau                   Context->SegSs, Context->SegSs >> 3, (Context->SegSs & (1 << 2)) ? 'L' : 'G', Context->SegSs & 3);
1002c2c66affSColin Finck     }
1003c2c66affSColin Finck     else /* dregs */
1004c2c66affSColin Finck     {
1005c2c66affSColin Finck         ASSERT(Argv[0][0] == 'd');
1006c2c66affSColin Finck         KdbpPrint("DR0  0x%08x\n"
1007c2c66affSColin Finck                   "DR1  0x%08x\n"
1008c2c66affSColin Finck                   "DR2  0x%08x\n"
1009c2c66affSColin Finck                   "DR3  0x%08x\n"
1010c2c66affSColin Finck                   "DR6  0x%08x\n"
1011c2c66affSColin Finck                   "DR7  0x%08x\n",
1012baa47fa5SHervé Poussineau                   Context->Dr0, Context->Dr1, Context->Dr2, Context->Dr3,
1013baa47fa5SHervé Poussineau                   Context->Dr6, Context->Dr7);
1014c2c66affSColin Finck     }
1015c2c66affSColin Finck 
1016c2c66affSColin Finck     return TRUE;
1017c2c66affSColin Finck }
1018c2c66affSColin Finck 
10193726b992SJérôme Gardou #ifdef _M_IX86
10208826ee8fSHermès Bélusca-Maïto static PKTSS
KdbpRetrieveTss(IN USHORT TssSelector,OUT PULONG pType OPTIONAL,IN PKDESCRIPTOR pGdtr OPTIONAL)10218826ee8fSHermès Bélusca-Maïto KdbpRetrieveTss(
10228826ee8fSHermès Bélusca-Maïto     IN USHORT TssSelector,
10238826ee8fSHermès Bélusca-Maïto     OUT PULONG pType OPTIONAL,
10248826ee8fSHermès Bélusca-Maïto     IN PKDESCRIPTOR pGdtr OPTIONAL)
10258826ee8fSHermès Bélusca-Maïto {
10268826ee8fSHermès Bélusca-Maïto     KDESCRIPTOR Gdtr;
10278826ee8fSHermès Bélusca-Maïto     KGDTENTRY Desc;
10288826ee8fSHermès Bélusca-Maïto     PKTSS Tss;
10298826ee8fSHermès Bélusca-Maïto 
10308826ee8fSHermès Bélusca-Maïto     /* Retrieve the Global Descriptor Table (user-provided or system) */
10318826ee8fSHermès Bélusca-Maïto     if (pGdtr)
10328826ee8fSHermès Bélusca-Maïto         Gdtr = *pGdtr;
10338826ee8fSHermès Bélusca-Maïto     else
10348826ee8fSHermès Bélusca-Maïto         Ke386GetGlobalDescriptorTable(&Gdtr.Limit);
10358826ee8fSHermès Bélusca-Maïto 
10368826ee8fSHermès Bélusca-Maïto     /* Check limits */
10378826ee8fSHermès Bélusca-Maïto     if ((TssSelector & (sizeof(KGDTENTRY) - 1)) ||
10388826ee8fSHermès Bélusca-Maïto         (TssSelector < sizeof(KGDTENTRY)) ||
10398826ee8fSHermès Bélusca-Maïto         (TssSelector + sizeof(KGDTENTRY) - 1 > Gdtr.Limit))
10408826ee8fSHermès Bélusca-Maïto     {
10418826ee8fSHermès Bélusca-Maïto         return NULL;
10428826ee8fSHermès Bélusca-Maïto     }
10438826ee8fSHermès Bélusca-Maïto 
10448826ee8fSHermès Bélusca-Maïto     /* Retrieve the descriptor */
10458826ee8fSHermès Bélusca-Maïto     if (!NT_SUCCESS(KdbpSafeReadMemory(&Desc,
10468826ee8fSHermès Bélusca-Maïto                                        (PVOID)(Gdtr.Base + TssSelector),
10478826ee8fSHermès Bélusca-Maïto                                        sizeof(KGDTENTRY))))
10488826ee8fSHermès Bélusca-Maïto     {
10498826ee8fSHermès Bélusca-Maïto         return NULL;
10508826ee8fSHermès Bélusca-Maïto     }
10518826ee8fSHermès Bélusca-Maïto 
10528826ee8fSHermès Bélusca-Maïto     /* Check for TSS32(Avl) or TSS32(Busy) */
10538826ee8fSHermès Bélusca-Maïto     if (Desc.HighWord.Bits.Type != 9 && Desc.HighWord.Bits.Type != 11)
10548826ee8fSHermès Bélusca-Maïto     {
10558826ee8fSHermès Bélusca-Maïto         return NULL;
10568826ee8fSHermès Bélusca-Maïto     }
10578826ee8fSHermès Bélusca-Maïto     if (pType) *pType = Desc.HighWord.Bits.Type;
10588826ee8fSHermès Bélusca-Maïto 
10598826ee8fSHermès Bélusca-Maïto     Tss = (PKTSS)(ULONG_PTR)(Desc.BaseLow |
10608826ee8fSHermès Bélusca-Maïto                              Desc.HighWord.Bytes.BaseMid << 16 |
10618826ee8fSHermès Bélusca-Maïto                              Desc.HighWord.Bytes.BaseHi << 24);
10628826ee8fSHermès Bélusca-Maïto 
10638826ee8fSHermès Bélusca-Maïto     return Tss;
10648826ee8fSHermès Bélusca-Maïto }
10658826ee8fSHermès Bélusca-Maïto 
1066d21ff0edSHermès Bélusca-Maïto FORCEINLINE BOOLEAN
KdbpIsNestedTss(IN USHORT TssSelector,IN PKTSS Tss)1067d21ff0edSHermès Bélusca-Maïto KdbpIsNestedTss(
1068d21ff0edSHermès Bélusca-Maïto     IN USHORT TssSelector,
1069d21ff0edSHermès Bélusca-Maïto     IN PKTSS Tss)
1070c2c66affSColin Finck {
1071d21ff0edSHermès Bélusca-Maïto     USHORT Backlink;
1072c2c66affSColin Finck 
1073d21ff0edSHermès Bélusca-Maïto     if (!Tss)
1074c2c66affSColin Finck         return FALSE;
1075c2c66affSColin Finck 
107625336250STimo Kreuzer #ifdef _M_AMD64
107725336250STimo Kreuzer     // HACK
107825336250STimo Kreuzer     return FALSE;
107925336250STimo Kreuzer #else
1080d21ff0edSHermès Bélusca-Maïto     /* Retrieve the TSS Backlink */
1081d21ff0edSHermès Bélusca-Maïto     if (!NT_SUCCESS(KdbpSafeReadMemory(&Backlink,
1082c2c66affSColin Finck                                        (PVOID)&Tss->Backlink,
1083c2c66affSColin Finck                                        sizeof(USHORT))))
1084d21ff0edSHermès Bélusca-Maïto     {
1085c2c66affSColin Finck         return FALSE;
1086d21ff0edSHermès Bélusca-Maïto     }
108725336250STimo Kreuzer #endif
1088c2c66affSColin Finck 
1089d21ff0edSHermès Bélusca-Maïto     return (Backlink != 0 && Backlink != TssSelector);
1090d21ff0edSHermès Bélusca-Maïto }
1091d21ff0edSHermès Bélusca-Maïto 
1092d21ff0edSHermès Bélusca-Maïto static BOOLEAN
KdbpContextFromPrevTss(IN OUT PCONTEXT Context,OUT PUSHORT TssSelector,IN OUT PKTSS * pTss,IN PKDESCRIPTOR pGdtr)1093baa47fa5SHervé Poussineau KdbpContextFromPrevTss(
1094baa47fa5SHervé Poussineau     IN OUT PCONTEXT Context,
1095d21ff0edSHermès Bélusca-Maïto     OUT PUSHORT TssSelector,
1096d21ff0edSHermès Bélusca-Maïto     IN OUT PKTSS* pTss,
1097d21ff0edSHermès Bélusca-Maïto     IN PKDESCRIPTOR pGdtr)
1098d21ff0edSHermès Bélusca-Maïto {
1099d21ff0edSHermès Bélusca-Maïto     ULONG_PTR Eip, Ebp;
1100d21ff0edSHermès Bélusca-Maïto     USHORT Backlink;
1101d21ff0edSHermès Bélusca-Maïto     PKTSS Tss = *pTss;
1102d21ff0edSHermès Bélusca-Maïto 
110325336250STimo Kreuzer #ifdef _M_AMD64
110425336250STimo Kreuzer     // HACK
110525336250STimo Kreuzer     return FALSE;
110625336250STimo Kreuzer #else
1107d21ff0edSHermès Bélusca-Maïto     /* Retrieve the TSS Backlink */
1108d21ff0edSHermès Bélusca-Maïto     if (!NT_SUCCESS(KdbpSafeReadMemory(&Backlink,
1109d21ff0edSHermès Bélusca-Maïto                                        (PVOID)&Tss->Backlink,
1110d21ff0edSHermès Bélusca-Maïto                                        sizeof(USHORT))))
1111d21ff0edSHermès Bélusca-Maïto     {
1112c2c66affSColin Finck         return FALSE;
1113d21ff0edSHermès Bélusca-Maïto     }
1114c2c66affSColin Finck 
1115d21ff0edSHermès Bélusca-Maïto     /* Retrieve the parent TSS */
1116d21ff0edSHermès Bélusca-Maïto     Tss = KdbpRetrieveTss(Backlink, NULL, pGdtr);
1117d21ff0edSHermès Bélusca-Maïto     if (!Tss)
1118c2c66affSColin Finck         return FALSE;
1119c2c66affSColin Finck 
1120c2c66affSColin Finck     if (!NT_SUCCESS(KdbpSafeReadMemory(&Eip,
1121c2c66affSColin Finck                                        (PVOID)&Tss->Eip,
1122c2c66affSColin Finck                                        sizeof(ULONG_PTR))))
1123d21ff0edSHermès Bélusca-Maïto     {
1124c2c66affSColin Finck         return FALSE;
1125d21ff0edSHermès Bélusca-Maïto     }
1126c2c66affSColin Finck 
1127c2c66affSColin Finck     if (!NT_SUCCESS(KdbpSafeReadMemory(&Ebp,
1128c2c66affSColin Finck                                        (PVOID)&Tss->Ebp,
1129c2c66affSColin Finck                                        sizeof(ULONG_PTR))))
1130d21ff0edSHermès Bélusca-Maïto     {
1131c2c66affSColin Finck         return FALSE;
1132d21ff0edSHermès Bélusca-Maïto     }
1133c2c66affSColin Finck 
1134d21ff0edSHermès Bélusca-Maïto     /* Return the parent TSS and its trap frame */
1135d21ff0edSHermès Bélusca-Maïto     *TssSelector = Backlink;
1136d21ff0edSHermès Bélusca-Maïto     *pTss = Tss;
1137baa47fa5SHervé Poussineau     Context->Eip = Eip;
1138baa47fa5SHervé Poussineau     Context->Ebp = Ebp;
113925336250STimo Kreuzer #endif
1140c2c66affSColin Finck     return TRUE;
1141c2c66affSColin Finck }
11428de4d4d2SSerge Gautherie #endif // _M_IX86
1143c2c66affSColin Finck 
114425336250STimo Kreuzer #ifdef _M_AMD64
114525336250STimo Kreuzer 
114625336250STimo Kreuzer static
114725336250STimo Kreuzer BOOLEAN
GetNextFrame(_Inout_ PCONTEXT Context)114825336250STimo Kreuzer GetNextFrame(
114925336250STimo Kreuzer     _Inout_ PCONTEXT Context)
115025336250STimo Kreuzer {
115125336250STimo Kreuzer     PRUNTIME_FUNCTION FunctionEntry;
115225336250STimo Kreuzer     ULONG64 ImageBase, EstablisherFrame;
115325336250STimo Kreuzer     PVOID HandlerData;
115425336250STimo Kreuzer 
115525336250STimo Kreuzer     _SEH2_TRY
115625336250STimo Kreuzer     {
115725336250STimo Kreuzer         /* Lookup the FunctionEntry for the current RIP */
115825336250STimo Kreuzer         FunctionEntry = RtlLookupFunctionEntry(Context->Rip, &ImageBase, NULL);
115925336250STimo Kreuzer         if (FunctionEntry == NULL)
116025336250STimo Kreuzer         {
116125336250STimo Kreuzer             /* No function entry, so this must be a leaf function. Pop the return address from the stack.
116225336250STimo Kreuzer             Note: this can happen after the first frame as the result of an exception */
116325336250STimo Kreuzer             Context->Rip = *(DWORD64*)Context->Rsp;
116425336250STimo Kreuzer             Context->Rsp += sizeof(DWORD64);
116525336250STimo Kreuzer             return TRUE;
116625336250STimo Kreuzer         }
116725336250STimo Kreuzer         else
116825336250STimo Kreuzer         {
116925336250STimo Kreuzer             RtlVirtualUnwind(UNW_FLAG_NHANDLER,
117025336250STimo Kreuzer                              ImageBase,
117125336250STimo Kreuzer                              Context->Rip,
117225336250STimo Kreuzer                              FunctionEntry,
117325336250STimo Kreuzer                              Context,
117425336250STimo Kreuzer                              &HandlerData,
117525336250STimo Kreuzer                              &EstablisherFrame,
117625336250STimo Kreuzer                              NULL);
117725336250STimo Kreuzer         }
117825336250STimo Kreuzer     }
117925336250STimo Kreuzer     _SEH2_EXCEPT(1)
118025336250STimo Kreuzer     {
118125336250STimo Kreuzer         return FALSE;
118225336250STimo Kreuzer     }
118325336250STimo Kreuzer     _SEH2_END
118425336250STimo Kreuzer 
118525336250STimo Kreuzer     return TRUE;
118625336250STimo Kreuzer }
118725336250STimo Kreuzer 
118825336250STimo Kreuzer static BOOLEAN
KdbpCmdBackTrace(ULONG Argc,PCHAR Argv[])118925336250STimo Kreuzer KdbpCmdBackTrace(
119025336250STimo Kreuzer     ULONG Argc,
119125336250STimo Kreuzer     PCHAR Argv[])
119225336250STimo Kreuzer {
119325336250STimo Kreuzer     CONTEXT Context = *KdbCurrentTrapFrame;
119425336250STimo Kreuzer 
119525336250STimo Kreuzer     /* Walk through the frames */
119625336250STimo Kreuzer     KdbpPrint("Frames:\n");
119774014e74STimo Kreuzer     do
119825336250STimo Kreuzer     {
119974014e74STimo Kreuzer         BOOLEAN GotNextFrame;
120025336250STimo Kreuzer 
120174014e74STimo Kreuzer         KdbpPrint("[%p] ", (PVOID)Context.Rsp);
120225336250STimo Kreuzer 
120374014e74STimo Kreuzer         /* Print the location after the call instruction */
120474014e74STimo Kreuzer         if (!KdbSymPrintAddress((PVOID)Context.Rip, &Context))
120525336250STimo Kreuzer             KdbpPrint("<%p>", (PVOID)Context.Rip);
120674014e74STimo Kreuzer         KdbpPrint("\n");
120725336250STimo Kreuzer 
120825336250STimo Kreuzer         if (KdbOutputAborted)
120925336250STimo Kreuzer             break;
121025336250STimo Kreuzer 
121174014e74STimo Kreuzer         GotNextFrame = GetNextFrame(&Context);
121225336250STimo Kreuzer         if (!GotNextFrame)
121325336250STimo Kreuzer         {
121474014e74STimo Kreuzer             KdbpPrint("Couldn't get next frame\n");
121525336250STimo Kreuzer             break;
121625336250STimo Kreuzer         }
121774014e74STimo Kreuzer     } while ((Context.Rip != 0) && (Context.Rsp != 0));
121825336250STimo Kreuzer 
121925336250STimo Kreuzer     return TRUE;
122025336250STimo Kreuzer }
122125336250STimo Kreuzer #else
1222c2c66affSColin Finck /*!\brief Displays a backtrace.
1223c2c66affSColin Finck  */
1224c2c66affSColin Finck static BOOLEAN
KdbpCmdBackTrace(ULONG Argc,PCHAR Argv[])1225c2c66affSColin Finck KdbpCmdBackTrace(
1226c2c66affSColin Finck     ULONG Argc,
1227c2c66affSColin Finck     PCHAR Argv[])
1228c2c66affSColin Finck {
1229c2c66affSColin Finck     ULONG ul;
1230c2c66affSColin Finck     ULONGLONG Result = 0;
1231baa47fa5SHervé Poussineau     CONTEXT Context = *KdbCurrentTrapFrame;
12323726b992SJérôme Gardou     ULONG_PTR Frame = KeGetContextFrameRegister(&Context);
1233c2c66affSColin Finck     ULONG_PTR Address;
1234c2c66affSColin Finck 
1235c2c66affSColin Finck     if (Argc >= 2)
1236c2c66affSColin Finck     {
1237c2c66affSColin Finck         /* Check for [L count] part */
1238c2c66affSColin Finck         ul = 0;
1239c2c66affSColin Finck         if (strcmp(Argv[Argc-2], "L") == 0)
1240c2c66affSColin Finck         {
1241c2c66affSColin Finck             ul = strtoul(Argv[Argc-1], NULL, 0);
1242c2c66affSColin Finck             if (ul > 0)
1243c2c66affSColin Finck             {
1244c2c66affSColin Finck                 Argc -= 2;
1245c2c66affSColin Finck             }
1246c2c66affSColin Finck         }
1247c2c66affSColin Finck         else if (Argv[Argc-1][0] == 'L')
1248c2c66affSColin Finck         {
1249c2c66affSColin Finck             ul = strtoul(Argv[Argc-1] + 1, NULL, 0);
1250c2c66affSColin Finck             if (ul > 0)
1251c2c66affSColin Finck             {
1252c2c66affSColin Finck                 Argc--;
1253c2c66affSColin Finck             }
1254c2c66affSColin Finck         }
1255c2c66affSColin Finck 
1256c2c66affSColin Finck         /* Put the remaining arguments back together */
1257c2c66affSColin Finck         Argc--;
1258c2c66affSColin Finck         for (ul = 1; ul < Argc; ul++)
1259c2c66affSColin Finck         {
1260c2c66affSColin Finck             Argv[ul][strlen(Argv[ul])] = ' ';
1261c2c66affSColin Finck         }
1262c2c66affSColin Finck         Argc++;
1263c2c66affSColin Finck     }
1264c2c66affSColin Finck 
1265d21ff0edSHermès Bélusca-Maïto     /* Check if a Frame Address or Thread ID is given */
1266c2c66affSColin Finck     if (Argc > 1)
1267c2c66affSColin Finck     {
1268c2c66affSColin Finck         if (Argv[1][0] == '*')
1269c2c66affSColin Finck         {
1270c2c66affSColin Finck             Argv[1]++;
1271c2c66affSColin Finck 
1272c2c66affSColin Finck             /* Evaluate the expression */
1273f620ce77SHermès Bélusca-Maïto             if (!KdbpEvaluateExpression(Argv[1], KdbPromptStr.Length + (Argv[1]-Argv[0]), &Result))
1274c2c66affSColin Finck                 return TRUE;
1275c2c66affSColin Finck 
1276c2c66affSColin Finck             if (Result > (ULONGLONG)(~((ULONG_PTR)0)))
1277c2c66affSColin Finck                 KdbpPrint("Warning: Address %I64x is beeing truncated\n", Result);
1278c2c66affSColin Finck 
1279c2c66affSColin Finck             Frame = (ULONG_PTR)Result;
1280c2c66affSColin Finck         }
1281c2c66affSColin Finck         else
1282c2c66affSColin Finck         {
1283c2c66affSColin Finck             KdbpPrint("Thread backtrace not supported yet!\n");
1284c2c66affSColin Finck             return TRUE;
1285c2c66affSColin Finck         }
1286c2c66affSColin Finck     }
1287d21ff0edSHermès Bélusca-Maïto 
12883726b992SJérôme Gardou #ifdef _M_IX86
12893726b992SJérôme Gardou     KDESCRIPTOR Gdtr;
12903726b992SJérôme Gardou     USHORT TssSelector;
12913726b992SJérôme Gardou     PKTSS Tss;
12923726b992SJérôme Gardou 
1293d21ff0edSHermès Bélusca-Maïto     /* Retrieve the Global Descriptor Table */
1294d21ff0edSHermès Bélusca-Maïto     Ke386GetGlobalDescriptorTable(&Gdtr.Limit);
1295d21ff0edSHermès Bélusca-Maïto 
1296d21ff0edSHermès Bélusca-Maïto     /* Retrieve the current (active) TSS */
1297d21ff0edSHermès Bélusca-Maïto     TssSelector = Ke386GetTr();
1298d21ff0edSHermès Bélusca-Maïto     Tss = KdbpRetrieveTss(TssSelector, NULL, &Gdtr);
1299d21ff0edSHermès Bélusca-Maïto     if (KdbpIsNestedTss(TssSelector, Tss))
1300d21ff0edSHermès Bélusca-Maïto     {
1301d21ff0edSHermès Bélusca-Maïto         /* Display the active TSS if it is nested */
1302d21ff0edSHermès Bélusca-Maïto         KdbpPrint("[Active TSS 0x%04x @ 0x%p]\n", TssSelector, Tss);
1303d21ff0edSHermès Bélusca-Maïto     }
13043726b992SJérôme Gardou #endif
1305d21ff0edSHermès Bélusca-Maïto 
1306d21ff0edSHermès Bélusca-Maïto     /* If no Frame Address or Thread ID was given, try printing the function at EIP */
1307d21ff0edSHermès Bélusca-Maïto     if (Argc <= 1)
1308c2c66affSColin Finck     {
1309c2c66affSColin Finck         KdbpPrint("Eip:\n");
13103726b992SJérôme Gardou         if (!KdbSymPrintAddress((PVOID)KeGetContextPc(&Context), &Context))
13113726b992SJérôme Gardou             KdbpPrint("<%p>\n", KeGetContextPc(&Context));
1312c2c66affSColin Finck         else
1313c2c66affSColin Finck             KdbpPrint("\n");
1314c2c66affSColin Finck     }
1315c2c66affSColin Finck 
1316d21ff0edSHermès Bélusca-Maïto     /* Walk through the frames */
1317c2c66affSColin Finck     KdbpPrint("Frames:\n");
1318c2c66affSColin Finck     for (;;)
1319c2c66affSColin Finck     {
1320c2c66affSColin Finck         BOOLEAN GotNextFrame;
1321c2c66affSColin Finck 
1322c2c66affSColin Finck         if (Frame == 0)
1323d21ff0edSHermès Bélusca-Maïto             goto CheckForParentTSS;
1324c2c66affSColin Finck 
1325d21ff0edSHermès Bélusca-Maïto         Address = 0;
1326c2c66affSColin Finck         if (!NT_SUCCESS(KdbpSafeReadMemory(&Address, (PVOID)(Frame + sizeof(ULONG_PTR)), sizeof(ULONG_PTR))))
1327c2c66affSColin Finck         {
1328c2c66affSColin Finck             KdbpPrint("Couldn't access memory at 0x%p!\n", Frame + sizeof(ULONG_PTR));
1329d21ff0edSHermès Bélusca-Maïto             goto CheckForParentTSS;
1330c2c66affSColin Finck         }
1331c2c66affSColin Finck 
1332d21ff0edSHermès Bélusca-Maïto         if (Address == 0)
1333d21ff0edSHermès Bélusca-Maïto             goto CheckForParentTSS;
1334c2c66affSColin Finck 
1335d21ff0edSHermès Bélusca-Maïto         GotNextFrame = NT_SUCCESS(KdbpSafeReadMemory(&Frame, (PVOID)Frame, sizeof(ULONG_PTR)));
1336d21ff0edSHermès Bélusca-Maïto         if (GotNextFrame)
13373726b992SJérôme Gardou         {
13383726b992SJérôme Gardou             KeSetContextFrameRegister(&Context, Frame);
13393726b992SJérôme Gardou         }
1340d21ff0edSHermès Bélusca-Maïto         // else
1341d21ff0edSHermès Bélusca-Maïto             // Frame = 0;
1342d21ff0edSHermès Bélusca-Maïto 
1343d21ff0edSHermès Bélusca-Maïto         /* Print the location of the call instruction (assumed 5 bytes length) */
1344baa47fa5SHervé Poussineau         if (!KdbSymPrintAddress((PVOID)(Address - 5), &Context))
1345c2c66affSColin Finck             KdbpPrint("<%08x>\n", Address);
1346c2c66affSColin Finck         else
1347c2c66affSColin Finck             KdbpPrint("\n");
1348c2c66affSColin Finck 
1349d21ff0edSHermès Bélusca-Maïto         if (KdbOutputAborted)
1350c2c66affSColin Finck             break;
1351c2c66affSColin Finck 
1352d21ff0edSHermès Bélusca-Maïto         if (!GotNextFrame)
1353c2c66affSColin Finck         {
1354d21ff0edSHermès Bélusca-Maïto             KdbpPrint("Couldn't access memory at 0x%p!\n", Frame);
1355d21ff0edSHermès Bélusca-Maïto             goto CheckForParentTSS; // break;
1356d21ff0edSHermès Bélusca-Maïto         }
1357d21ff0edSHermès Bélusca-Maïto 
1358d21ff0edSHermès Bélusca-Maïto         continue;
1359d21ff0edSHermès Bélusca-Maïto 
1360d21ff0edSHermès Bélusca-Maïto CheckForParentTSS:
13613726b992SJérôme Gardou #ifndef _M_IX86
13623726b992SJérôme Gardou         break;
13633726b992SJérôme Gardou #else
1364d21ff0edSHermès Bélusca-Maïto         /*
1365d21ff0edSHermès Bélusca-Maïto          * We have ended the stack walking for the current (active) TSS.
1366d21ff0edSHermès Bélusca-Maïto          * Check whether this TSS was nested, and if so switch to its parent
1367d21ff0edSHermès Bélusca-Maïto          * and walk its stack.
1368d21ff0edSHermès Bélusca-Maïto          */
1369d21ff0edSHermès Bélusca-Maïto         if (!KdbpIsNestedTss(TssSelector, Tss))
1370d21ff0edSHermès Bélusca-Maïto             break; // The TSS is not nested, we stop there.
1371d21ff0edSHermès Bélusca-Maïto 
1372baa47fa5SHervé Poussineau         GotNextFrame = KdbpContextFromPrevTss(&Context, &TssSelector, &Tss, &Gdtr);
1373d21ff0edSHermès Bélusca-Maïto         if (!GotNextFrame)
1374c2c66affSColin Finck         {
1375d21ff0edSHermès Bélusca-Maïto             KdbpPrint("Couldn't access parent TSS 0x%04x\n", Tss->Backlink);
1376d21ff0edSHermès Bélusca-Maïto             break; // Cannot retrieve the parent TSS, we stop there.
1377d21ff0edSHermès Bélusca-Maïto         }
13783726b992SJérôme Gardou 
13793726b992SJérôme Gardou 
1380baa47fa5SHervé Poussineau         Address = Context.Eip;
1381baa47fa5SHervé Poussineau         Frame = Context.Ebp;
1382c2c66affSColin Finck 
1383d21ff0edSHermès Bélusca-Maïto         KdbpPrint("[Parent TSS 0x%04x @ 0x%p]\n", TssSelector, Tss);
1384d21ff0edSHermès Bélusca-Maïto 
1385baa47fa5SHervé Poussineau         if (!KdbSymPrintAddress((PVOID)Address, &Context))
1386c2c66affSColin Finck             KdbpPrint("<%08x>\n", Address);
1387c2c66affSColin Finck         else
1388c2c66affSColin Finck             KdbpPrint("\n");
13893726b992SJérôme Gardou #endif
1390c2c66affSColin Finck     }
1391c2c66affSColin Finck 
1392c2c66affSColin Finck     return TRUE;
1393c2c66affSColin Finck }
1394c2c66affSColin Finck 
139525336250STimo Kreuzer #endif // M_AMD64
139625336250STimo Kreuzer 
1397c2c66affSColin Finck /*!\brief Continues execution of the system/leaves KDB.
1398c2c66affSColin Finck  */
1399c2c66affSColin Finck static BOOLEAN
KdbpCmdContinue(ULONG Argc,PCHAR Argv[])1400c2c66affSColin Finck KdbpCmdContinue(
1401c2c66affSColin Finck     ULONG Argc,
1402c2c66affSColin Finck     PCHAR Argv[])
1403c2c66affSColin Finck {
1404c2c66affSColin Finck     /* Exit the main loop */
1405c2c66affSColin Finck     return FALSE;
1406c2c66affSColin Finck }
1407c2c66affSColin Finck 
1408c2c66affSColin Finck /*!\brief Continues execution of the system/leaves KDB.
1409c2c66affSColin Finck  */
1410c2c66affSColin Finck static BOOLEAN
KdbpCmdStep(ULONG Argc,PCHAR Argv[])1411c2c66affSColin Finck KdbpCmdStep(
1412c2c66affSColin Finck     ULONG Argc,
1413c2c66affSColin Finck     PCHAR Argv[])
1414c2c66affSColin Finck {
1415c2c66affSColin Finck     ULONG Count = 1;
1416c2c66affSColin Finck 
1417c2c66affSColin Finck     if (Argc > 1)
1418c2c66affSColin Finck     {
1419c2c66affSColin Finck         Count = strtoul(Argv[1], NULL, 0);
1420c2c66affSColin Finck         if (Count == 0)
1421c2c66affSColin Finck         {
1422c2c66affSColin Finck             KdbpPrint("%s: Integer argument required\n", Argv[0]);
1423c2c66affSColin Finck             return TRUE;
1424c2c66affSColin Finck         }
1425c2c66affSColin Finck     }
1426c2c66affSColin Finck 
1427c2c66affSColin Finck     if (Argv[0][0] == 'n')
1428c2c66affSColin Finck         KdbSingleStepOver = TRUE;
1429c2c66affSColin Finck     else
1430c2c66affSColin Finck         KdbSingleStepOver = FALSE;
1431c2c66affSColin Finck 
1432c2c66affSColin Finck     /* Set the number of single steps and return to the interrupted code. */
1433c2c66affSColin Finck     KdbNumSingleSteps = Count;
1434c2c66affSColin Finck 
1435c2c66affSColin Finck     return FALSE;
1436c2c66affSColin Finck }
1437c2c66affSColin Finck 
1438c2c66affSColin Finck /*!\brief Lists breakpoints.
1439c2c66affSColin Finck  */
1440c2c66affSColin Finck static BOOLEAN
KdbpCmdBreakPointList(ULONG Argc,PCHAR Argv[])1441c2c66affSColin Finck KdbpCmdBreakPointList(
1442c2c66affSColin Finck     ULONG Argc,
1443c2c66affSColin Finck     PCHAR Argv[])
1444c2c66affSColin Finck {
1445c2c66affSColin Finck     LONG l;
1446c2c66affSColin Finck     ULONG_PTR Address = 0;
1447c2c66affSColin Finck     KDB_BREAKPOINT_TYPE Type = 0;
1448c2c66affSColin Finck     KDB_ACCESS_TYPE AccessType = 0;
1449c2c66affSColin Finck     UCHAR Size = 0;
1450c2c66affSColin Finck     UCHAR DebugReg = 0;
1451c2c66affSColin Finck     BOOLEAN Enabled = FALSE;
1452c2c66affSColin Finck     BOOLEAN Global = FALSE;
1453c2c66affSColin Finck     PEPROCESS Process = NULL;
1454c2c66affSColin Finck     PCHAR str1, str2, ConditionExpr, GlobalOrLocal;
1455c2c66affSColin Finck     CHAR Buffer[20];
1456c2c66affSColin Finck 
1457c2c66affSColin Finck     l = KdbpGetNextBreakPointNr(0);
1458c2c66affSColin Finck     if (l < 0)
1459c2c66affSColin Finck     {
1460c2c66affSColin Finck         KdbpPrint("No breakpoints.\n");
1461c2c66affSColin Finck         return TRUE;
1462c2c66affSColin Finck     }
1463c2c66affSColin Finck 
1464c2c66affSColin Finck     KdbpPrint("Breakpoints:\n");
1465c2c66affSColin Finck     do
1466c2c66affSColin Finck     {
1467c2c66affSColin Finck         if (!KdbpGetBreakPointInfo(l, &Address, &Type, &Size, &AccessType, &DebugReg,
1468c2c66affSColin Finck                                    &Enabled, &Global, &Process, &ConditionExpr))
1469c2c66affSColin Finck         {
1470c2c66affSColin Finck             continue;
1471c2c66affSColin Finck         }
1472c2c66affSColin Finck 
1473c2c66affSColin Finck         if (l == KdbLastBreakPointNr)
1474c2c66affSColin Finck         {
1475c2c66affSColin Finck             str1 = "\x1b[1m*";
1476c2c66affSColin Finck             str2 = "\x1b[0m";
1477c2c66affSColin Finck         }
1478c2c66affSColin Finck         else
1479c2c66affSColin Finck         {
1480c2c66affSColin Finck             str1 = " ";
1481c2c66affSColin Finck             str2 = "";
1482c2c66affSColin Finck         }
1483c2c66affSColin Finck 
1484c2c66affSColin Finck         if (Global)
1485c2c66affSColin Finck         {
1486c2c66affSColin Finck             GlobalOrLocal = "  global";
1487c2c66affSColin Finck         }
1488c2c66affSColin Finck         else
1489c2c66affSColin Finck         {
1490c2c66affSColin Finck             GlobalOrLocal = Buffer;
149125336250STimo Kreuzer             sprintf(Buffer, "  PID 0x%Ix",
14923726b992SJérôme Gardou                     (ULONG_PTR)(Process ? Process->UniqueProcessId : INVALID_HANDLE_VALUE));
1493c2c66affSColin Finck         }
1494c2c66affSColin Finck 
1495c2c66affSColin Finck         if (Type == KdbBreakPointSoftware || Type == KdbBreakPointTemporary)
1496c2c66affSColin Finck         {
1497c2c66affSColin Finck             KdbpPrint(" %s%03d  BPX  0x%08x%s%s%s%s%s\n",
1498c2c66affSColin Finck                       str1, l, Address,
1499c2c66affSColin Finck                       Enabled ? "" : "  disabled",
1500c2c66affSColin Finck                       GlobalOrLocal,
1501c2c66affSColin Finck                       ConditionExpr ? "  IF " : "",
1502c2c66affSColin Finck                       ConditionExpr ? ConditionExpr : "",
1503c2c66affSColin Finck                       str2);
1504c2c66affSColin Finck         }
1505c2c66affSColin Finck         else if (Type == KdbBreakPointHardware)
1506c2c66affSColin Finck         {
1507c2c66affSColin Finck             if (!Enabled)
1508c2c66affSColin Finck             {
1509c2c66affSColin Finck                 KdbpPrint(" %s%03d  BPM  0x%08x  %-5s %-5s  disabled%s%s%s%s\n", str1, l, Address,
1510c2c66affSColin Finck                           KDB_ACCESS_TYPE_TO_STRING(AccessType),
1511c2c66affSColin Finck                           Size == 1 ? "byte" : (Size == 2 ? "word" : "dword"),
1512c2c66affSColin Finck                           GlobalOrLocal,
1513c2c66affSColin Finck                           ConditionExpr ? "  IF " : "",
1514c2c66affSColin Finck                           ConditionExpr ? ConditionExpr : "",
1515c2c66affSColin Finck                           str2);
1516c2c66affSColin Finck             }
1517c2c66affSColin Finck             else
1518c2c66affSColin Finck             {
1519c2c66affSColin Finck                 KdbpPrint(" %s%03d  BPM  0x%08x  %-5s %-5s  DR%d%s%s%s%s\n", str1, l, Address,
1520c2c66affSColin Finck                           KDB_ACCESS_TYPE_TO_STRING(AccessType),
1521c2c66affSColin Finck                           Size == 1 ? "byte" : (Size == 2 ? "word" : "dword"),
1522c2c66affSColin Finck                           DebugReg,
1523c2c66affSColin Finck                           GlobalOrLocal,
1524c2c66affSColin Finck                           ConditionExpr ? "  IF " : "",
1525c2c66affSColin Finck                           ConditionExpr ? ConditionExpr : "",
1526c2c66affSColin Finck                           str2);
1527c2c66affSColin Finck             }
1528c2c66affSColin Finck         }
1529c2c66affSColin Finck     }
1530c2c66affSColin Finck     while ((l = KdbpGetNextBreakPointNr(l+1)) >= 0);
1531c2c66affSColin Finck 
1532c2c66affSColin Finck     return TRUE;
1533c2c66affSColin Finck }
1534c2c66affSColin Finck 
1535c2c66affSColin Finck /*!\brief Enables, disables or clears a breakpoint.
1536c2c66affSColin Finck  */
1537c2c66affSColin Finck static BOOLEAN
KdbpCmdEnableDisableClearBreakPoint(ULONG Argc,PCHAR Argv[])1538c2c66affSColin Finck KdbpCmdEnableDisableClearBreakPoint(
1539c2c66affSColin Finck     ULONG Argc,
1540c2c66affSColin Finck     PCHAR Argv[])
1541c2c66affSColin Finck {
1542c2c66affSColin Finck     PCHAR pend;
1543c2c66affSColin Finck     ULONG BreakPointNr;
1544c2c66affSColin Finck 
1545c2c66affSColin Finck     if (Argc < 2)
1546c2c66affSColin Finck     {
1547c2c66affSColin Finck         KdbpPrint("%s: argument required\n", Argv[0]);
1548c2c66affSColin Finck         return TRUE;
1549c2c66affSColin Finck     }
1550c2c66affSColin Finck 
1551c2c66affSColin Finck     pend = Argv[1];
1552c2c66affSColin Finck     BreakPointNr = strtoul(Argv[1], &pend, 0);
1553c2c66affSColin Finck     if (pend == Argv[1] || *pend != '\0')
1554c2c66affSColin Finck     {
1555c2c66affSColin Finck         KdbpPrint("%s: integer argument required\n", Argv[0]);
1556c2c66affSColin Finck         return TRUE;
1557c2c66affSColin Finck     }
1558c2c66affSColin Finck 
1559c2c66affSColin Finck     if (Argv[0][1] == 'e') /* enable */
1560c2c66affSColin Finck     {
1561c2c66affSColin Finck         KdbpEnableBreakPoint(BreakPointNr, NULL);
1562c2c66affSColin Finck     }
1563c2c66affSColin Finck     else if (Argv [0][1] == 'd') /* disable */
1564c2c66affSColin Finck     {
1565c2c66affSColin Finck         KdbpDisableBreakPoint(BreakPointNr, NULL);
1566c2c66affSColin Finck     }
1567c2c66affSColin Finck     else /* clear */
1568c2c66affSColin Finck     {
1569c2c66affSColin Finck         ASSERT(Argv[0][1] == 'c');
1570c2c66affSColin Finck         KdbpDeleteBreakPoint(BreakPointNr, NULL);
1571c2c66affSColin Finck     }
1572c2c66affSColin Finck 
1573c2c66affSColin Finck     return TRUE;
1574c2c66affSColin Finck }
1575c2c66affSColin Finck 
1576c2c66affSColin Finck /*!\brief Sets a software or hardware (memory) breakpoint at the given address.
1577c2c66affSColin Finck  */
1578c2c66affSColin Finck static BOOLEAN
KdbpCmdBreakPoint(ULONG Argc,PCHAR Argv[])1579c2c66affSColin Finck KdbpCmdBreakPoint(ULONG Argc, PCHAR Argv[])
1580c2c66affSColin Finck {
1581c2c66affSColin Finck     ULONGLONG Result = 0;
1582c2c66affSColin Finck     ULONG_PTR Address;
1583c2c66affSColin Finck     KDB_BREAKPOINT_TYPE Type;
1584c2c66affSColin Finck     UCHAR Size = 0;
1585c2c66affSColin Finck     KDB_ACCESS_TYPE AccessType = 0;
1586c2c66affSColin Finck     ULONG AddressArgIndex, i;
1587c2c66affSColin Finck     LONG ConditionArgIndex;
1588c2c66affSColin Finck     BOOLEAN Global = TRUE;
1589c2c66affSColin Finck 
1590c2c66affSColin Finck     if (Argv[0][2] == 'x') /* software breakpoint */
1591c2c66affSColin Finck     {
1592c2c66affSColin Finck         if (Argc < 2)
1593c2c66affSColin Finck         {
1594c2c66affSColin Finck             KdbpPrint("bpx: Address argument required.\n");
1595c2c66affSColin Finck             return TRUE;
1596c2c66affSColin Finck         }
1597c2c66affSColin Finck 
1598c2c66affSColin Finck         AddressArgIndex = 1;
1599c2c66affSColin Finck         Type = KdbBreakPointSoftware;
1600c2c66affSColin Finck     }
1601c2c66affSColin Finck     else /* memory breakpoint */
1602c2c66affSColin Finck     {
1603c2c66affSColin Finck         ASSERT(Argv[0][2] == 'm');
1604c2c66affSColin Finck 
1605c2c66affSColin Finck         if (Argc < 2)
1606c2c66affSColin Finck         {
1607c2c66affSColin Finck             KdbpPrint("bpm: Access type argument required (one of r, w, rw, x)\n");
1608c2c66affSColin Finck             return TRUE;
1609c2c66affSColin Finck         }
1610c2c66affSColin Finck 
1611c2c66affSColin Finck         if (_stricmp(Argv[1], "x") == 0)
1612c2c66affSColin Finck             AccessType = KdbAccessExec;
1613c2c66affSColin Finck         else if (_stricmp(Argv[1], "r") == 0)
1614c2c66affSColin Finck             AccessType = KdbAccessRead;
1615c2c66affSColin Finck         else if (_stricmp(Argv[1], "w") == 0)
1616c2c66affSColin Finck             AccessType = KdbAccessWrite;
1617c2c66affSColin Finck         else if (_stricmp(Argv[1], "rw") == 0)
1618c2c66affSColin Finck             AccessType = KdbAccessReadWrite;
1619c2c66affSColin Finck         else
1620c2c66affSColin Finck         {
1621c2c66affSColin Finck             KdbpPrint("bpm: Unknown access type '%s'\n", Argv[1]);
1622c2c66affSColin Finck             return TRUE;
1623c2c66affSColin Finck         }
1624c2c66affSColin Finck 
1625c2c66affSColin Finck         if (Argc < 3)
1626c2c66affSColin Finck         {
1627c2c66affSColin Finck             KdbpPrint("bpm: %s argument required.\n", AccessType == KdbAccessExec ? "Address" : "Memory size");
1628c2c66affSColin Finck             return TRUE;
1629c2c66affSColin Finck         }
1630c2c66affSColin Finck 
1631c2c66affSColin Finck         AddressArgIndex = 3;
1632c2c66affSColin Finck         if (_stricmp(Argv[2], "byte") == 0)
1633c2c66affSColin Finck             Size = 1;
1634c2c66affSColin Finck         else if (_stricmp(Argv[2], "word") == 0)
1635c2c66affSColin Finck             Size = 2;
1636c2c66affSColin Finck         else if (_stricmp(Argv[2], "dword") == 0)
1637c2c66affSColin Finck             Size = 4;
1638c2c66affSColin Finck         else if (AccessType == KdbAccessExec)
1639c2c66affSColin Finck         {
1640c2c66affSColin Finck             Size = 1;
1641c2c66affSColin Finck             AddressArgIndex--;
1642c2c66affSColin Finck         }
1643c2c66affSColin Finck         else
1644c2c66affSColin Finck         {
1645c2c66affSColin Finck             KdbpPrint("bpm: Unknown memory size '%s'\n", Argv[2]);
1646c2c66affSColin Finck             return TRUE;
1647c2c66affSColin Finck         }
1648c2c66affSColin Finck 
1649c2c66affSColin Finck         if (Argc <= AddressArgIndex)
1650c2c66affSColin Finck         {
1651c2c66affSColin Finck             KdbpPrint("bpm: Address argument required.\n");
1652c2c66affSColin Finck             return TRUE;
1653c2c66affSColin Finck         }
1654c2c66affSColin Finck 
1655c2c66affSColin Finck         Type = KdbBreakPointHardware;
1656c2c66affSColin Finck     }
1657c2c66affSColin Finck 
1658c2c66affSColin Finck     /* Put the arguments back together */
1659c2c66affSColin Finck     ConditionArgIndex = -1;
1660c2c66affSColin Finck     for (i = AddressArgIndex; i < (Argc-1); i++)
1661c2c66affSColin Finck     {
1662c2c66affSColin Finck         if (strcmp(Argv[i+1], "IF") == 0) /* IF found */
1663c2c66affSColin Finck         {
1664c2c66affSColin Finck             ConditionArgIndex = i + 2;
1665c2c66affSColin Finck             if ((ULONG)ConditionArgIndex >= Argc)
1666c2c66affSColin Finck             {
1667c2c66affSColin Finck                 KdbpPrint("%s: IF requires condition expression.\n", Argv[0]);
1668c2c66affSColin Finck                 return TRUE;
1669c2c66affSColin Finck             }
1670c2c66affSColin Finck 
1671c2c66affSColin Finck             for (i = ConditionArgIndex; i < (Argc-1); i++)
1672c2c66affSColin Finck                 Argv[i][strlen(Argv[i])] = ' ';
1673c2c66affSColin Finck 
1674c2c66affSColin Finck             break;
1675c2c66affSColin Finck         }
1676c2c66affSColin Finck 
1677c2c66affSColin Finck         Argv[i][strlen(Argv[i])] = ' ';
1678c2c66affSColin Finck     }
1679c2c66affSColin Finck 
1680c2c66affSColin Finck     /* Evaluate the address expression */
1681c2c66affSColin Finck     if (!KdbpEvaluateExpression(Argv[AddressArgIndex],
1682f620ce77SHermès Bélusca-Maïto                                 KdbPromptStr.Length + (Argv[AddressArgIndex]-Argv[0]),
1683c2c66affSColin Finck                                 &Result))
1684c2c66affSColin Finck     {
1685c2c66affSColin Finck         return TRUE;
1686c2c66affSColin Finck     }
1687c2c66affSColin Finck 
1688c2c66affSColin Finck     if (Result > (ULONGLONG)(~((ULONG_PTR)0)))
1689c2c66affSColin Finck         KdbpPrint("%s: Warning: Address %I64x is beeing truncated\n", Argv[0],Result);
1690c2c66affSColin Finck 
1691c2c66affSColin Finck     Address = (ULONG_PTR)Result;
1692c2c66affSColin Finck 
1693c2c66affSColin Finck     KdbpInsertBreakPoint(Address, Type, Size, AccessType,
1694c2c66affSColin Finck                          (ConditionArgIndex < 0) ? NULL : Argv[ConditionArgIndex],
1695c2c66affSColin Finck                          Global, NULL);
1696c2c66affSColin Finck 
1697c2c66affSColin Finck     return TRUE;
1698c2c66affSColin Finck }
1699c2c66affSColin Finck 
1700c2c66affSColin Finck /*!\brief Lists threads or switches to another thread context.
1701c2c66affSColin Finck  */
1702c2c66affSColin Finck static BOOLEAN
KdbpCmdThread(ULONG Argc,PCHAR Argv[])1703c2c66affSColin Finck KdbpCmdThread(
1704c2c66affSColin Finck     ULONG Argc,
1705c2c66affSColin Finck     PCHAR Argv[])
1706c2c66affSColin Finck {
1707c2c66affSColin Finck     PLIST_ENTRY Entry;
1708c2c66affSColin Finck     PETHREAD Thread = NULL;
1709c2c66affSColin Finck     PEPROCESS Process = NULL;
1710c2c66affSColin Finck     BOOLEAN ReferencedThread = FALSE, ReferencedProcess = FALSE;
17113726b992SJérôme Gardou     PULONG_PTR Stack;
17123726b992SJérôme Gardou     PULONG_PTR Frame;
17133726b992SJérôme Gardou     ULONG_PTR Pc;
17143726b992SJérôme Gardou     ULONG_PTR ul = 0;
1715c2c66affSColin Finck     PCHAR State, pend, str1, str2;
1716c2c66affSColin Finck     static const PCHAR ThreadStateToString[DeferredReady+1] =
1717c2c66affSColin Finck     {
1718c2c66affSColin Finck         "Initialized", "Ready", "Running",
1719c2c66affSColin Finck         "Standby", "Terminated", "Waiting",
1720c2c66affSColin Finck         "Transition", "DeferredReady"
1721c2c66affSColin Finck     };
1722c2c66affSColin Finck 
1723c2c66affSColin Finck     ASSERT(KdbCurrentProcess);
1724c2c66affSColin Finck 
1725c2c66affSColin Finck     if (Argc >= 2 && _stricmp(Argv[1], "list") == 0)
1726c2c66affSColin Finck     {
1727c2c66affSColin Finck         Process = KdbCurrentProcess;
1728c2c66affSColin Finck 
1729c2c66affSColin Finck         if (Argc >= 3)
1730c2c66affSColin Finck         {
17313726b992SJérôme Gardou             ul = strtoulptr(Argv[2], &pend, 0);
1732c2c66affSColin Finck             if (Argv[2] == pend)
1733c2c66affSColin Finck             {
1734c2c66affSColin Finck                 KdbpPrint("thread: '%s' is not a valid process id!\n", Argv[2]);
1735c2c66affSColin Finck                 return TRUE;
1736c2c66affSColin Finck             }
1737c2c66affSColin Finck 
1738c2c66affSColin Finck             if (!NT_SUCCESS(PsLookupProcessByProcessId((PVOID)ul, &Process)))
1739c2c66affSColin Finck             {
1740c2c66affSColin Finck                 KdbpPrint("thread: Invalid process id!\n");
1741c2c66affSColin Finck                 return TRUE;
1742c2c66affSColin Finck             }
1743c2c66affSColin Finck 
1744c2c66affSColin Finck             /* Remember our reference */
1745c2c66affSColin Finck             ReferencedProcess = TRUE;
1746c2c66affSColin Finck         }
1747c2c66affSColin Finck 
1748c2c66affSColin Finck         Entry = Process->ThreadListHead.Flink;
1749c2c66affSColin Finck         if (Entry == &Process->ThreadListHead)
1750c2c66affSColin Finck         {
1751c2c66affSColin Finck             if (Argc >= 3)
17523726b992SJérôme Gardou                 KdbpPrint("No threads in process 0x%px!\n", (PVOID)ul);
1753c2c66affSColin Finck             else
1754c2c66affSColin Finck                 KdbpPrint("No threads in current process!\n");
1755c2c66affSColin Finck 
1756c2c66affSColin Finck             if (ReferencedProcess)
1757c2c66affSColin Finck                 ObDereferenceObject(Process);
1758c2c66affSColin Finck 
1759c2c66affSColin Finck             return TRUE;
1760c2c66affSColin Finck         }
1761c2c66affSColin Finck 
1762c2c66affSColin Finck         KdbpPrint("  TID         State        Prior.  Affinity    EBP         EIP\n");
1763c2c66affSColin Finck         do
1764c2c66affSColin Finck         {
1765c2c66affSColin Finck             Thread = CONTAINING_RECORD(Entry, ETHREAD, ThreadListEntry);
1766c2c66affSColin Finck 
1767c2c66affSColin Finck             if (Thread == KdbCurrentThread)
1768c2c66affSColin Finck             {
1769c2c66affSColin Finck                 str1 = "\x1b[1m*";
1770c2c66affSColin Finck                 str2 = "\x1b[0m";
1771c2c66affSColin Finck             }
1772c2c66affSColin Finck             else
1773c2c66affSColin Finck             {
1774c2c66affSColin Finck                 str1 = " ";
1775c2c66affSColin Finck                 str2 = "";
1776c2c66affSColin Finck             }
1777c2c66affSColin Finck 
1778c2c66affSColin Finck             if (!Thread->Tcb.InitialStack)
1779c2c66affSColin Finck             {
1780c2c66affSColin Finck                 /* Thread has no kernel stack (probably terminated) */
17813726b992SJérôme Gardou                 Stack = Frame = NULL;
17823726b992SJérôme Gardou                 Pc = 0;
1783c2c66affSColin Finck             }
1784c2c66affSColin Finck             else if (Thread->Tcb.TrapFrame)
1785c2c66affSColin Finck             {
17863726b992SJérôme Gardou                 Stack = (PULONG_PTR)KeGetTrapFrameStackRegister(Thread->Tcb.TrapFrame);
17873726b992SJérôme Gardou                 Frame = (PULONG_PTR)KeGetTrapFrameFrameRegister(Thread->Tcb.TrapFrame);
17883726b992SJérôme Gardou                 Pc = KeGetTrapFramePc(Thread->Tcb.TrapFrame);
1789c2c66affSColin Finck             }
1790c2c66affSColin Finck             else
1791c2c66affSColin Finck             {
17923726b992SJérôme Gardou                 Stack = (PULONG_PTR)Thread->Tcb.KernelStack;
17933726b992SJérôme Gardou                 Frame = (PULONG_PTR)Stack[4];
17943726b992SJérôme Gardou                 Pc = 0;
1795c2c66affSColin Finck 
17963726b992SJérôme Gardou                 if (Frame) /* FIXME: Should we attach to the process to read Ebp[1]? */
17973726b992SJérôme Gardou                     KdbpSafeReadMemory(&Pc, Frame + 1, sizeof(Pc));
1798c2c66affSColin Finck             }
1799c2c66affSColin Finck 
1800c2c66affSColin Finck             if (Thread->Tcb.State < (DeferredReady + 1))
1801c2c66affSColin Finck                 State = ThreadStateToString[Thread->Tcb.State];
1802c2c66affSColin Finck             else
1803c2c66affSColin Finck                 State = "Unknown";
1804c2c66affSColin Finck 
1805c2c66affSColin Finck             KdbpPrint(" %s0x%08x  %-11s  %3d     0x%08x  0x%08x  0x%08x%s\n",
1806c2c66affSColin Finck                       str1,
1807c2c66affSColin Finck                       Thread->Cid.UniqueThread,
1808c2c66affSColin Finck                       State,
1809c2c66affSColin Finck                       Thread->Tcb.Priority,
1810c2c66affSColin Finck                       Thread->Tcb.Affinity,
18113726b992SJérôme Gardou                       Frame,
18123726b992SJérôme Gardou                       Pc,
1813c2c66affSColin Finck                       str2);
1814c2c66affSColin Finck 
1815c2c66affSColin Finck             Entry = Entry->Flink;
1816c2c66affSColin Finck         }
1817c2c66affSColin Finck         while (Entry != &Process->ThreadListHead);
1818c2c66affSColin Finck 
1819c2c66affSColin Finck         /* Release our reference, if any */
1820c2c66affSColin Finck         if (ReferencedProcess)
1821c2c66affSColin Finck             ObDereferenceObject(Process);
1822c2c66affSColin Finck     }
1823c2c66affSColin Finck     else if (Argc >= 2 && _stricmp(Argv[1], "attach") == 0)
1824c2c66affSColin Finck     {
1825c2c66affSColin Finck         if (Argc < 3)
1826c2c66affSColin Finck         {
1827c2c66affSColin Finck             KdbpPrint("thread attach: thread id argument required!\n");
1828c2c66affSColin Finck             return TRUE;
1829c2c66affSColin Finck         }
1830c2c66affSColin Finck 
18313726b992SJérôme Gardou         ul = strtoulptr(Argv[2], &pend, 0);
1832c2c66affSColin Finck         if (Argv[2] == pend)
1833c2c66affSColin Finck         {
1834c2c66affSColin Finck             KdbpPrint("thread attach: '%s' is not a valid thread id!\n", Argv[2]);
1835c2c66affSColin Finck             return TRUE;
1836c2c66affSColin Finck         }
1837c2c66affSColin Finck 
1838c2c66affSColin Finck         if (!KdbpAttachToThread((PVOID)ul))
1839c2c66affSColin Finck         {
1840c2c66affSColin Finck             return TRUE;
1841c2c66affSColin Finck         }
1842c2c66affSColin Finck 
1843c2c66affSColin Finck         KdbpPrint("Attached to thread 0x%08x.\n", ul);
1844c2c66affSColin Finck     }
1845c2c66affSColin Finck     else
1846c2c66affSColin Finck     {
1847c2c66affSColin Finck         Thread = KdbCurrentThread;
1848c2c66affSColin Finck 
1849c2c66affSColin Finck         if (Argc >= 2)
1850c2c66affSColin Finck         {
18513726b992SJérôme Gardou             ul = strtoulptr(Argv[1], &pend, 0);
1852c2c66affSColin Finck             if (Argv[1] == pend)
1853c2c66affSColin Finck             {
1854c2c66affSColin Finck                 KdbpPrint("thread: '%s' is not a valid thread id!\n", Argv[1]);
1855c2c66affSColin Finck                 return TRUE;
1856c2c66affSColin Finck             }
1857c2c66affSColin Finck 
1858c2c66affSColin Finck             if (!NT_SUCCESS(PsLookupThreadByThreadId((PVOID)ul, &Thread)))
1859c2c66affSColin Finck             {
1860c2c66affSColin Finck                 KdbpPrint("thread: Invalid thread id!\n");
1861c2c66affSColin Finck                 return TRUE;
1862c2c66affSColin Finck             }
1863c2c66affSColin Finck 
1864c2c66affSColin Finck             /* Remember our reference */
1865c2c66affSColin Finck             ReferencedThread = TRUE;
1866c2c66affSColin Finck         }
1867c2c66affSColin Finck 
1868c2c66affSColin Finck         if (Thread->Tcb.State < (DeferredReady + 1))
1869c2c66affSColin Finck             State = ThreadStateToString[Thread->Tcb.State];
1870c2c66affSColin Finck         else
1871c2c66affSColin Finck             State = "Unknown";
1872c2c66affSColin Finck 
1873c2c66affSColin Finck         KdbpPrint("%s"
1874c2c66affSColin Finck                   "  TID:            0x%08x\n"
1875c2c66affSColin Finck                   "  State:          %s (0x%x)\n"
1876c2c66affSColin Finck                   "  Priority:       %d\n"
1877c2c66affSColin Finck                   "  Affinity:       0x%08x\n"
1878c2c66affSColin Finck                   "  Initial Stack:  0x%08x\n"
1879c2c66affSColin Finck                   "  Stack Limit:    0x%08x\n"
1880c2c66affSColin Finck                   "  Stack Base:     0x%08x\n"
1881c2c66affSColin Finck                   "  Kernel Stack:   0x%08x\n"
1882c2c66affSColin Finck                   "  Trap Frame:     0x%08x\n"
1883b97d5fd2SJérôme Gardou #ifndef _M_AMD64
1884b97d5fd2SJérôme Gardou                   "  NPX State:      %s (0x%x)\n"
1885b97d5fd2SJérôme Gardou #endif
1886b97d5fd2SJérôme Gardou                   , (Argc < 2) ? "Current Thread:\n" : ""
1887b97d5fd2SJérôme Gardou                   , Thread->Cid.UniqueThread
1888b97d5fd2SJérôme Gardou                   , State, Thread->Tcb.State
1889b97d5fd2SJérôme Gardou                   , Thread->Tcb.Priority
1890b97d5fd2SJérôme Gardou                   , Thread->Tcb.Affinity
1891b97d5fd2SJérôme Gardou                   , Thread->Tcb.InitialStack
1892b97d5fd2SJérôme Gardou                   , Thread->Tcb.StackLimit
1893b97d5fd2SJérôme Gardou                   , Thread->Tcb.StackBase
1894b97d5fd2SJérôme Gardou                   , Thread->Tcb.KernelStack
1895b97d5fd2SJérôme Gardou                   , Thread->Tcb.TrapFrame
18963726b992SJérôme Gardou #ifndef _M_AMD64
18973726b992SJérôme Gardou                   , NPX_STATE_TO_STRING(Thread->Tcb.NpxState), Thread->Tcb.NpxState
18983726b992SJérôme Gardou #endif
18993726b992SJérôme Gardou             );
1900c2c66affSColin Finck 
1901c2c66affSColin Finck             /* Release our reference if we had one */
1902c2c66affSColin Finck             if (ReferencedThread)
1903c2c66affSColin Finck                 ObDereferenceObject(Thread);
1904c2c66affSColin Finck     }
1905c2c66affSColin Finck 
1906c2c66affSColin Finck     return TRUE;
1907c2c66affSColin Finck }
1908c2c66affSColin Finck 
1909c2c66affSColin Finck /*!\brief Lists processes or switches to another process context.
1910c2c66affSColin Finck  */
1911c2c66affSColin Finck static BOOLEAN
KdbpCmdProc(ULONG Argc,PCHAR Argv[])1912c2c66affSColin Finck KdbpCmdProc(
1913c2c66affSColin Finck     ULONG Argc,
1914c2c66affSColin Finck     PCHAR Argv[])
1915c2c66affSColin Finck {
1916c2c66affSColin Finck     PLIST_ENTRY Entry;
1917c2c66affSColin Finck     PEPROCESS Process;
1918c2c66affSColin Finck     BOOLEAN ReferencedProcess = FALSE;
1919c2c66affSColin Finck     PCHAR State, pend, str1, str2;
19203726b992SJérôme Gardou     ULONG_PTR ul;
1921c2c66affSColin Finck     extern LIST_ENTRY PsActiveProcessHead;
1922c2c66affSColin Finck 
1923c2c66affSColin Finck     if (Argc >= 2 && _stricmp(Argv[1], "list") == 0)
1924c2c66affSColin Finck     {
1925c2c66affSColin Finck         Entry = PsActiveProcessHead.Flink;
1926c2c66affSColin Finck         if (!Entry || Entry == &PsActiveProcessHead)
1927c2c66affSColin Finck         {
1928c2c66affSColin Finck             KdbpPrint("No processes in the system!\n");
1929c2c66affSColin Finck             return TRUE;
1930c2c66affSColin Finck         }
1931c2c66affSColin Finck 
1932c2c66affSColin Finck         KdbpPrint("  PID         State       Filename\n");
1933c2c66affSColin Finck         do
1934c2c66affSColin Finck         {
1935c2c66affSColin Finck             Process = CONTAINING_RECORD(Entry, EPROCESS, ActiveProcessLinks);
1936c2c66affSColin Finck 
1937c2c66affSColin Finck             if (Process == KdbCurrentProcess)
1938c2c66affSColin Finck             {
1939c2c66affSColin Finck                 str1 = "\x1b[1m*";
1940c2c66affSColin Finck                 str2 = "\x1b[0m";
1941c2c66affSColin Finck             }
1942c2c66affSColin Finck             else
1943c2c66affSColin Finck             {
1944c2c66affSColin Finck                 str1 = " ";
1945c2c66affSColin Finck                 str2 = "";
1946c2c66affSColin Finck             }
1947c2c66affSColin Finck 
1948c2c66affSColin Finck             State = ((Process->Pcb.State == ProcessInMemory) ? "In Memory" :
1949c2c66affSColin Finck                     ((Process->Pcb.State == ProcessOutOfMemory) ? "Out of Memory" : "In Transition"));
1950c2c66affSColin Finck 
1951c2c66affSColin Finck             KdbpPrint(" %s0x%08x  %-10s  %s%s\n",
1952c2c66affSColin Finck                       str1,
1953c2c66affSColin Finck                       Process->UniqueProcessId,
1954c2c66affSColin Finck                       State,
1955c2c66affSColin Finck                       Process->ImageFileName,
1956c2c66affSColin Finck                       str2);
1957c2c66affSColin Finck 
1958c2c66affSColin Finck             Entry = Entry->Flink;
1959c2c66affSColin Finck         }
1960c2c66affSColin Finck         while(Entry != &PsActiveProcessHead);
1961c2c66affSColin Finck     }
1962c2c66affSColin Finck     else if (Argc >= 2 && _stricmp(Argv[1], "attach") == 0)
1963c2c66affSColin Finck     {
1964c2c66affSColin Finck         if (Argc < 3)
1965c2c66affSColin Finck         {
1966c2c66affSColin Finck             KdbpPrint("process attach: process id argument required!\n");
1967c2c66affSColin Finck             return TRUE;
1968c2c66affSColin Finck         }
1969c2c66affSColin Finck 
19703726b992SJérôme Gardou         ul = strtoulptr(Argv[2], &pend, 0);
1971c2c66affSColin Finck         if (Argv[2] == pend)
1972c2c66affSColin Finck         {
1973c2c66affSColin Finck             KdbpPrint("process attach: '%s' is not a valid process id!\n", Argv[2]);
1974c2c66affSColin Finck             return TRUE;
1975c2c66affSColin Finck         }
1976c2c66affSColin Finck 
1977c2c66affSColin Finck         if (!KdbpAttachToProcess((PVOID)ul))
1978c2c66affSColin Finck         {
1979c2c66affSColin Finck             return TRUE;
1980c2c66affSColin Finck         }
1981c2c66affSColin Finck 
19823726b992SJérôme Gardou         KdbpPrint("Attached to process 0x%p, thread 0x%p.\n", (PVOID)ul,
19833726b992SJérôme Gardou                   KdbCurrentThread->Cid.UniqueThread);
1984c2c66affSColin Finck     }
1985c2c66affSColin Finck     else
1986c2c66affSColin Finck     {
1987c2c66affSColin Finck         Process = KdbCurrentProcess;
1988c2c66affSColin Finck 
1989c2c66affSColin Finck         if (Argc >= 2)
1990c2c66affSColin Finck         {
19913726b992SJérôme Gardou             ul = strtoulptr(Argv[1], &pend, 0);
1992c2c66affSColin Finck             if (Argv[1] == pend)
1993c2c66affSColin Finck             {
1994c2c66affSColin Finck                 KdbpPrint("proc: '%s' is not a valid process id!\n", Argv[1]);
1995c2c66affSColin Finck                 return TRUE;
1996c2c66affSColin Finck             }
1997c2c66affSColin Finck 
1998c2c66affSColin Finck             if (!NT_SUCCESS(PsLookupProcessByProcessId((PVOID)ul, &Process)))
1999c2c66affSColin Finck             {
2000c2c66affSColin Finck                 KdbpPrint("proc: Invalid process id!\n");
2001c2c66affSColin Finck                 return TRUE;
2002c2c66affSColin Finck             }
2003c2c66affSColin Finck 
2004c2c66affSColin Finck             /* Remember our reference */
2005c2c66affSColin Finck             ReferencedProcess = TRUE;
2006c2c66affSColin Finck         }
2007c2c66affSColin Finck 
2008c2c66affSColin Finck         State = ((Process->Pcb.State == ProcessInMemory) ? "In Memory" :
2009c2c66affSColin Finck                 ((Process->Pcb.State == ProcessOutOfMemory) ? "Out of Memory" : "In Transition"));
2010c2c66affSColin Finck         KdbpPrint("%s"
2011c2c66affSColin Finck                   "  PID:             0x%08x\n"
2012c2c66affSColin Finck                   "  State:           %s (0x%x)\n"
2013c2c66affSColin Finck                   "  Image Filename:  %s\n",
2014c2c66affSColin Finck                   (Argc < 2) ? "Current process:\n" : "",
2015c2c66affSColin Finck                   Process->UniqueProcessId,
2016c2c66affSColin Finck                   State, Process->Pcb.State,
2017c2c66affSColin Finck                   Process->ImageFileName);
2018c2c66affSColin Finck 
2019c2c66affSColin Finck         /* Release our reference, if any */
2020c2c66affSColin Finck         if (ReferencedProcess)
2021c2c66affSColin Finck             ObDereferenceObject(Process);
2022c2c66affSColin Finck     }
2023c2c66affSColin Finck 
2024c2c66affSColin Finck     return TRUE;
2025c2c66affSColin Finck }
2026c2c66affSColin Finck 
2027c2c66affSColin Finck /*!\brief Lists loaded modules or the one containing the specified address.
2028c2c66affSColin Finck  */
2029c2c66affSColin Finck static BOOLEAN
KdbpCmdMod(ULONG Argc,PCHAR Argv[])2030c2c66affSColin Finck KdbpCmdMod(
2031c2c66affSColin Finck     ULONG Argc,
2032c2c66affSColin Finck     PCHAR Argv[])
2033c2c66affSColin Finck {
2034c2c66affSColin Finck     ULONGLONG Result = 0;
2035c2c66affSColin Finck     ULONG_PTR Address;
2036c2c66affSColin Finck     PLDR_DATA_TABLE_ENTRY LdrEntry;
2037c2c66affSColin Finck     BOOLEAN DisplayOnlyOneModule = FALSE;
2038c2c66affSColin Finck     INT i = 0;
2039c2c66affSColin Finck 
2040c2c66affSColin Finck     if (Argc >= 2)
2041c2c66affSColin Finck     {
2042c2c66affSColin Finck         /* Put the arguments back together */
2043c2c66affSColin Finck         Argc--;
2044c2c66affSColin Finck         while (--Argc >= 1)
2045c2c66affSColin Finck             Argv[Argc][strlen(Argv[Argc])] = ' ';
2046c2c66affSColin Finck 
2047c2c66affSColin Finck         /* Evaluate the expression */
2048f620ce77SHermès Bélusca-Maïto         if (!KdbpEvaluateExpression(Argv[1], KdbPromptStr.Length + (Argv[1]-Argv[0]), &Result))
2049c2c66affSColin Finck         {
2050c2c66affSColin Finck             return TRUE;
2051c2c66affSColin Finck         }
2052c2c66affSColin Finck 
2053c2c66affSColin Finck         if (Result > (ULONGLONG)(~((ULONG_PTR)0)))
2054c2c66affSColin Finck             KdbpPrint("%s: Warning: Address %I64x is beeing truncated\n", Argv[0],Result);
2055c2c66affSColin Finck 
2056c2c66affSColin Finck         Address = (ULONG_PTR)Result;
2057c2c66affSColin Finck 
2058835c3023SJérôme Gardou         if (!KdbpSymFindModule((PVOID)Address, -1, &LdrEntry))
2059c2c66affSColin Finck         {
2060c2c66affSColin Finck             KdbpPrint("No module containing address 0x%p found!\n", Address);
2061c2c66affSColin Finck             return TRUE;
2062c2c66affSColin Finck         }
2063c2c66affSColin Finck 
2064c2c66affSColin Finck         DisplayOnlyOneModule = TRUE;
2065c2c66affSColin Finck     }
2066c2c66affSColin Finck     else
2067c2c66affSColin Finck     {
2068835c3023SJérôme Gardou         if (!KdbpSymFindModule(NULL, 0, &LdrEntry))
2069c2c66affSColin Finck         {
207025336250STimo Kreuzer             ULONG_PTR ntoskrnlBase = (ULONG_PTR)__ImageBase;
2071c2c66affSColin Finck             KdbpPrint("  Base      Size      Name\n");
207225336250STimo Kreuzer             KdbpPrint("  %p  %08x  %s\n", (PVOID)ntoskrnlBase, 0, "ntoskrnl.exe");
2073c2c66affSColin Finck             return TRUE;
2074c2c66affSColin Finck         }
2075c2c66affSColin Finck 
2076c2c66affSColin Finck         i = 1;
2077c2c66affSColin Finck     }
2078c2c66affSColin Finck 
2079c2c66affSColin Finck     KdbpPrint("  Base      Size      Name\n");
2080c2c66affSColin Finck     for (;;)
2081c2c66affSColin Finck     {
208231a5fa61STimo Kreuzer         KdbpPrint("  %p  %08x  ", LdrEntry->DllBase, LdrEntry->SizeOfImage);
208331a5fa61STimo Kreuzer         KdbpPrintUnicodeString(&LdrEntry->BaseDllName);
208431a5fa61STimo Kreuzer         KdbpPrint("\n");
2085c2c66affSColin Finck 
2086835c3023SJérôme Gardou         if(DisplayOnlyOneModule || !KdbpSymFindModule(NULL, i++, &LdrEntry))
2087c2c66affSColin Finck             break;
2088c2c66affSColin Finck     }
2089c2c66affSColin Finck 
2090c2c66affSColin Finck     return TRUE;
2091c2c66affSColin Finck }
2092c2c66affSColin Finck 
2093f0d59e74SHermès Bélusca-Maïto /*!\brief Displays GDT, LDT or IDT.
2094c2c66affSColin Finck  */
2095c2c66affSColin Finck static BOOLEAN
KdbpCmdGdtLdtIdt(ULONG Argc,PCHAR Argv[])2096c2c66affSColin Finck KdbpCmdGdtLdtIdt(
2097c2c66affSColin Finck     ULONG Argc,
2098c2c66affSColin Finck     PCHAR Argv[])
2099c2c66affSColin Finck {
2100c2c66affSColin Finck     KDESCRIPTOR Reg;
2101c2c66affSColin Finck     ULONG SegDesc[2];
2102c2c66affSColin Finck     ULONG SegBase;
2103c2c66affSColin Finck     ULONG SegLimit;
2104c2c66affSColin Finck     PCHAR SegType;
2105c2c66affSColin Finck     USHORT SegSel;
2106c2c66affSColin Finck     UCHAR Type, Dpl;
2107c2c66affSColin Finck     INT i;
2108c2c66affSColin Finck     ULONG ul;
2109c2c66affSColin Finck 
2110c2c66affSColin Finck     if (Argv[0][0] == 'i')
2111c2c66affSColin Finck     {
2112c2c66affSColin Finck         /* Read IDTR */
2113c2c66affSColin Finck         __sidt(&Reg.Limit);
2114c2c66affSColin Finck 
2115c2c66affSColin Finck         if (Reg.Limit < 7)
2116c2c66affSColin Finck         {
2117c2c66affSColin Finck             KdbpPrint("Interrupt descriptor table is empty.\n");
2118c2c66affSColin Finck             return TRUE;
2119c2c66affSColin Finck         }
2120c2c66affSColin Finck 
2121c2c66affSColin Finck         KdbpPrint("IDT Base: 0x%08x  Limit: 0x%04x\n", Reg.Base, Reg.Limit);
2122c2c66affSColin Finck         KdbpPrint("  Idx  Type        Seg. Sel.  Offset      DPL\n");
2123c2c66affSColin Finck 
2124c2c66affSColin Finck         for (i = 0; (i + sizeof(SegDesc) - 1) <= Reg.Limit; i += 8)
2125c2c66affSColin Finck         {
21263726b992SJérôme Gardou             if (!NT_SUCCESS(KdbpSafeReadMemory(SegDesc, (PVOID)((ULONG_PTR)Reg.Base + i), sizeof(SegDesc))))
2127c2c66affSColin Finck             {
21283726b992SJérôme Gardou                 KdbpPrint("Couldn't access memory at 0x%p!\n", (PVOID)((ULONG_PTR)Reg.Base + i));
2129c2c66affSColin Finck                 return TRUE;
2130c2c66affSColin Finck             }
2131c2c66affSColin Finck 
2132c2c66affSColin Finck             Dpl = ((SegDesc[1] >> 13) & 3);
2133c2c66affSColin Finck             if ((SegDesc[1] & 0x1f00) == 0x0500)        /* Task gate */
2134c2c66affSColin Finck                 SegType = "TASKGATE";
2135c2c66affSColin Finck             else if ((SegDesc[1] & 0x1fe0) == 0x0e00)   /* 32 bit Interrupt gate */
2136c2c66affSColin Finck                 SegType = "INTGATE32";
2137c2c66affSColin Finck             else if ((SegDesc[1] & 0x1fe0) == 0x0600)   /* 16 bit Interrupt gate */
2138c2c66affSColin Finck                 SegType = "INTGATE16";
2139c2c66affSColin Finck             else if ((SegDesc[1] & 0x1fe0) == 0x0f00)   /* 32 bit Trap gate */
2140c2c66affSColin Finck                 SegType = "TRAPGATE32";
2141c2c66affSColin Finck             else if ((SegDesc[1] & 0x1fe0) == 0x0700)   /* 16 bit Trap gate */
2142c2c66affSColin Finck                 SegType = "TRAPGATE16";
2143c2c66affSColin Finck             else
2144c2c66affSColin Finck                 SegType = "UNKNOWN";
2145c2c66affSColin Finck 
2146c2c66affSColin Finck             if ((SegDesc[1] & (1 << 15)) == 0) /* not present */
2147c2c66affSColin Finck             {
2148c2c66affSColin Finck                 KdbpPrint("  %03d  %-10s  [NP]       [NP]        %02d\n",
2149c2c66affSColin Finck                           i / 8, SegType, Dpl);
2150c2c66affSColin Finck             }
2151c2c66affSColin Finck             else if ((SegDesc[1] & 0x1f00) == 0x0500) /* Task gate */
2152c2c66affSColin Finck             {
2153c2c66affSColin Finck                 SegSel = SegDesc[0] >> 16;
2154c2c66affSColin Finck                 KdbpPrint("  %03d  %-10s  0x%04x                 %02d\n",
2155c2c66affSColin Finck                           i / 8, SegType, SegSel, Dpl);
2156c2c66affSColin Finck             }
2157c2c66affSColin Finck             else
2158c2c66affSColin Finck             {
2159c2c66affSColin Finck                 SegSel = SegDesc[0] >> 16;
2160c2c66affSColin Finck                 SegBase = (SegDesc[1] & 0xffff0000) | (SegDesc[0] & 0x0000ffff);
2161c2c66affSColin Finck                 KdbpPrint("  %03d  %-10s  0x%04x     0x%08x  %02d\n",
2162c2c66affSColin Finck                           i / 8, SegType, SegSel, SegBase, Dpl);
2163c2c66affSColin Finck             }
2164c2c66affSColin Finck         }
2165c2c66affSColin Finck     }
2166c2c66affSColin Finck     else
2167c2c66affSColin Finck     {
2168c2c66affSColin Finck         ul = 0;
2169c2c66affSColin Finck 
2170c2c66affSColin Finck         if (Argv[0][0] == 'g')
2171c2c66affSColin Finck         {
2172c2c66affSColin Finck             /* Read GDTR */
2173c2c66affSColin Finck             Ke386GetGlobalDescriptorTable(&Reg.Limit);
2174c2c66affSColin Finck             i = 8;
2175c2c66affSColin Finck         }
2176c2c66affSColin Finck         else
2177c2c66affSColin Finck         {
2178c2c66affSColin Finck             ASSERT(Argv[0][0] == 'l');
2179c2c66affSColin Finck 
2180c2c66affSColin Finck             /* Read LDTR */
21813726b992SJérôme Gardou             Ke386GetLocalDescriptorTable(&Reg.Limit);
2182c2c66affSColin Finck             Reg.Base = 0;
2183c2c66affSColin Finck             i = 0;
2184c2c66affSColin Finck             ul = 1 << 2;
2185c2c66affSColin Finck         }
2186c2c66affSColin Finck 
2187c2c66affSColin Finck         if (Reg.Limit < 7)
2188c2c66affSColin Finck         {
2189c2c66affSColin Finck             KdbpPrint("%s descriptor table is empty.\n",
2190c2c66affSColin Finck                       Argv[0][0] == 'g' ? "Global" : "Local");
2191c2c66affSColin Finck             return TRUE;
2192c2c66affSColin Finck         }
2193c2c66affSColin Finck 
2194c2c66affSColin Finck         KdbpPrint("%cDT Base: 0x%08x  Limit: 0x%04x\n",
2195c2c66affSColin Finck                   Argv[0][0] == 'g' ? 'G' : 'L', Reg.Base, Reg.Limit);
2196c2c66affSColin Finck         KdbpPrint("  Idx  Sel.    Type         Base        Limit       DPL  Attribs\n");
2197c2c66affSColin Finck 
2198c2c66affSColin Finck         for (; (i + sizeof(SegDesc) - 1) <= Reg.Limit; i += 8)
2199c2c66affSColin Finck         {
22003726b992SJérôme Gardou             if (!NT_SUCCESS(KdbpSafeReadMemory(SegDesc, (PVOID)((ULONG_PTR)Reg.Base + i), sizeof(SegDesc))))
2201c2c66affSColin Finck             {
22023726b992SJérôme Gardou                 KdbpPrint("Couldn't access memory at 0x%p!\n", (ULONG_PTR)Reg.Base + i);
2203c2c66affSColin Finck                 return TRUE;
2204c2c66affSColin Finck             }
2205c2c66affSColin Finck 
2206c2c66affSColin Finck             Dpl = ((SegDesc[1] >> 13) & 3);
2207c2c66affSColin Finck             Type = ((SegDesc[1] >> 8) & 0xf);
2208c2c66affSColin Finck 
2209c2c66affSColin Finck             SegBase = SegDesc[0] >> 16;
2210c2c66affSColin Finck             SegBase |= (SegDesc[1] & 0xff) << 16;
2211c2c66affSColin Finck             SegBase |= SegDesc[1] & 0xff000000;
2212c2c66affSColin Finck             SegLimit = SegDesc[0] & 0x0000ffff;
2213c2c66affSColin Finck             SegLimit |= (SegDesc[1] >> 16) & 0xf;
2214c2c66affSColin Finck 
2215c2c66affSColin Finck             if ((SegDesc[1] & (1 << 23)) != 0)
2216c2c66affSColin Finck             {
2217c2c66affSColin Finck                 SegLimit *= 4096;
2218c2c66affSColin Finck                 SegLimit += 4095;
2219c2c66affSColin Finck             }
2220c2c66affSColin Finck             else
2221c2c66affSColin Finck             {
2222c2c66affSColin Finck                 SegLimit++;
2223c2c66affSColin Finck             }
2224c2c66affSColin Finck 
2225c2c66affSColin Finck             if ((SegDesc[1] & (1 << 12)) == 0) /* System segment */
2226c2c66affSColin Finck             {
2227c2c66affSColin Finck                 switch (Type)
2228c2c66affSColin Finck                 {
2229c2c66affSColin Finck                     case  1: SegType = "TSS16(Avl)";    break;
2230c2c66affSColin Finck                     case  2: SegType = "LDT";           break;
2231c2c66affSColin Finck                     case  3: SegType = "TSS16(Busy)";   break;
2232c2c66affSColin Finck                     case  4: SegType = "CALLGATE16";    break;
2233c2c66affSColin Finck                     case  5: SegType = "TASKGATE";      break;
2234c2c66affSColin Finck                     case  6: SegType = "INTGATE16";     break;
2235c2c66affSColin Finck                     case  7: SegType = "TRAPGATE16";    break;
2236c2c66affSColin Finck                     case  9: SegType = "TSS32(Avl)";    break;
2237c2c66affSColin Finck                     case 11: SegType = "TSS32(Busy)";   break;
2238c2c66affSColin Finck                     case 12: SegType = "CALLGATE32";    break;
2239c2c66affSColin Finck                     case 14: SegType = "INTGATE32";     break;
224029f6d029SHermès Bélusca-Maïto                     case 15: SegType = "TRAPGATE32";    break;
2241c2c66affSColin Finck                     default: SegType = "UNKNOWN";       break;
2242c2c66affSColin Finck                 }
2243c2c66affSColin Finck 
2244c2c66affSColin Finck                 if (!(Type >= 1 && Type <= 3) &&
2245c2c66affSColin Finck                     Type != 9 && Type != 11)
2246c2c66affSColin Finck                 {
2247c2c66affSColin Finck                     SegBase = 0;
2248c2c66affSColin Finck                     SegLimit = 0;
2249c2c66affSColin Finck                 }
2250c2c66affSColin Finck             }
2251c2c66affSColin Finck             else if ((SegDesc[1] & (1 << 11)) == 0) /* Data segment */
2252c2c66affSColin Finck             {
2253c2c66affSColin Finck                 if ((SegDesc[1] & (1 << 22)) != 0)
2254c2c66affSColin Finck                     SegType = "DATA32";
2255c2c66affSColin Finck                 else
2256c2c66affSColin Finck                     SegType = "DATA16";
2257c2c66affSColin Finck             }
2258c2c66affSColin Finck             else /* Code segment */
2259c2c66affSColin Finck             {
2260c2c66affSColin Finck                 if ((SegDesc[1] & (1 << 22)) != 0)
2261c2c66affSColin Finck                     SegType = "CODE32";
2262c2c66affSColin Finck                 else
2263c2c66affSColin Finck                     SegType = "CODE16";
2264c2c66affSColin Finck             }
2265c2c66affSColin Finck 
226629f6d029SHermès Bélusca-Maïto             if ((SegDesc[1] & (1 << 15)) == 0) /* Not present */
2267c2c66affSColin Finck             {
2268c2c66affSColin Finck                 KdbpPrint("  %03d  0x%04x  %-11s  [NP]        [NP]        %02d   NP\n",
2269c2c66affSColin Finck                           i / 8, i | Dpl | ul, SegType, Dpl);
2270c2c66affSColin Finck             }
2271c2c66affSColin Finck             else
2272c2c66affSColin Finck             {
2273c2c66affSColin Finck                 KdbpPrint("  %03d  0x%04x  %-11s  0x%08x  0x%08x  %02d  ",
2274c2c66affSColin Finck                           i / 8, i | Dpl | ul, SegType, SegBase, SegLimit, Dpl);
2275c2c66affSColin Finck 
2276c2c66affSColin Finck                 if ((SegDesc[1] & (1 << 12)) == 0) /* System segment */
2277c2c66affSColin Finck                 {
2278c2c66affSColin Finck                     /* FIXME: Display system segment */
2279c2c66affSColin Finck                 }
2280c2c66affSColin Finck                 else if ((SegDesc[1] & (1 << 11)) == 0) /* Data segment */
2281c2c66affSColin Finck                 {
2282c2c66affSColin Finck                     if ((SegDesc[1] & (1 << 10)) != 0) /* Expand-down */
2283c2c66affSColin Finck                         KdbpPrint(" E");
2284c2c66affSColin Finck 
2285c2c66affSColin Finck                     KdbpPrint((SegDesc[1] & (1 << 9)) ? " R/W" : " R");
2286c2c66affSColin Finck 
2287c2c66affSColin Finck                     if ((SegDesc[1] & (1 << 8)) != 0)
2288c2c66affSColin Finck                         KdbpPrint(" A");
2289c2c66affSColin Finck                 }
2290c2c66affSColin Finck                 else /* Code segment */
2291c2c66affSColin Finck                 {
2292c2c66affSColin Finck                     if ((SegDesc[1] & (1 << 10)) != 0) /* Conforming */
2293c2c66affSColin Finck                         KdbpPrint(" C");
2294c2c66affSColin Finck 
2295c2c66affSColin Finck                     KdbpPrint((SegDesc[1] & (1 << 9)) ? " R/X" : " X");
2296c2c66affSColin Finck 
2297c2c66affSColin Finck                     if ((SegDesc[1] & (1 << 8)) != 0)
2298c2c66affSColin Finck                         KdbpPrint(" A");
2299c2c66affSColin Finck                 }
2300c2c66affSColin Finck 
2301c2c66affSColin Finck                 if ((SegDesc[1] & (1 << 20)) != 0)
2302c2c66affSColin Finck                     KdbpPrint(" AVL");
2303c2c66affSColin Finck 
2304c2c66affSColin Finck                 KdbpPrint("\n");
2305c2c66affSColin Finck             }
2306c2c66affSColin Finck         }
2307c2c66affSColin Finck     }
2308c2c66affSColin Finck 
2309c2c66affSColin Finck     return TRUE;
2310c2c66affSColin Finck }
2311c2c66affSColin Finck 
2312c2c66affSColin Finck /*!\brief Displays the KPCR
2313c2c66affSColin Finck  */
2314c2c66affSColin Finck static BOOLEAN
KdbpCmdPcr(ULONG Argc,PCHAR Argv[])2315c2c66affSColin Finck KdbpCmdPcr(
2316c2c66affSColin Finck     ULONG Argc,
2317c2c66affSColin Finck     PCHAR Argv[])
2318c2c66affSColin Finck {
2319c2c66affSColin Finck     PKIPCR Pcr = (PKIPCR)KeGetPcr();
2320c2c66affSColin Finck 
232189b44cfaSHermès Bélusca-Maïto     KdbpPrint("Current PCR is at 0x%p.\n", Pcr);
232225336250STimo Kreuzer #ifdef _M_IX86
2323c2c66affSColin Finck     KdbpPrint("  Tib.ExceptionList:         0x%08x\n"
2324c2c66affSColin Finck               "  Tib.StackBase:             0x%08x\n"
2325c2c66affSColin Finck               "  Tib.StackLimit:            0x%08x\n"
2326c2c66affSColin Finck               "  Tib.SubSystemTib:          0x%08x\n"
2327c2c66affSColin Finck               "  Tib.FiberData/Version:     0x%08x\n"
2328c2c66affSColin Finck               "  Tib.ArbitraryUserPointer:  0x%08x\n"
2329c2c66affSColin Finck               "  Tib.Self:                  0x%08x\n"
2330631a14ffSAmine Khaldi               "  SelfPcr:                   0x%08x\n"
2331c2c66affSColin Finck               "  PCRCB:                     0x%08x\n"
2332c2c66affSColin Finck               "  Irql:                      0x%02x\n"
2333c2c66affSColin Finck               "  IRR:                       0x%08x\n"
2334c2c66affSColin Finck               "  IrrActive:                 0x%08x\n"
2335c2c66affSColin Finck               "  IDR:                       0x%08x\n"
2336c2c66affSColin Finck               "  KdVersionBlock:            0x%08x\n"
2337c2c66affSColin Finck               "  IDT:                       0x%08x\n"
2338c2c66affSColin Finck               "  GDT:                       0x%08x\n"
2339c2c66affSColin Finck               "  TSS:                       0x%08x\n"
2340c2c66affSColin Finck               "  MajorVersion:              0x%04x\n"
2341c2c66affSColin Finck               "  MinorVersion:              0x%04x\n"
2342c2c66affSColin Finck               "  SetMember:                 0x%08x\n"
2343c2c66affSColin Finck               "  StallScaleFactor:          0x%08x\n"
2344c2c66affSColin Finck               "  Number:                    0x%02x\n"
2345c2c66affSColin Finck               "  L2CacheAssociativity:      0x%02x\n"
2346c2c66affSColin Finck               "  VdmAlert:                  0x%08x\n"
2347c2c66affSColin Finck               "  L2CacheSize:               0x%08x\n"
23483726b992SJérôme Gardou               "  InterruptMode:             0x%08x\n"
23493726b992SJérôme Gardou               , Pcr->NtTib.ExceptionList, Pcr->NtTib.StackBase, Pcr->NtTib.StackLimit,
2350c2c66affSColin Finck               Pcr->NtTib.SubSystemTib, Pcr->NtTib.FiberData, Pcr->NtTib.ArbitraryUserPointer,
23513726b992SJérôme Gardou               Pcr->NtTib.Self
23523726b992SJérôme Gardou               , Pcr->SelfPcr
23533726b992SJérôme Gardou               , Pcr->Prcb, Pcr->Irql
23543726b992SJérôme Gardou               , Pcr->IRR, Pcr->IrrActive , Pcr->IDR
23553726b992SJérôme Gardou               , Pcr->KdVersionBlock
23563726b992SJérôme Gardou               , Pcr->IDT, Pcr->GDT, Pcr->TSS
23573726b992SJérôme Gardou               , Pcr->MajorVersion, Pcr->MinorVersion
23583726b992SJérôme Gardou               , Pcr->SetMember
23593726b992SJérôme Gardou               , Pcr->StallScaleFactor
23603726b992SJérôme Gardou               , Pcr->Number
23613726b992SJérôme Gardou               , Pcr->SecondLevelCacheAssociativity
23623726b992SJérôme Gardou               , Pcr->VdmAlert
23633726b992SJérôme Gardou               , Pcr->SecondLevelCacheSize
236425336250STimo Kreuzer               , Pcr->InterruptMode);
236525336250STimo Kreuzer #else
236625336250STimo Kreuzer     KdbpPrint("  GdtBase:                       0x%p\n", Pcr->GdtBase);
236725336250STimo Kreuzer     KdbpPrint("  TssBase:                       0x%p\n", Pcr->TssBase);
236825336250STimo Kreuzer     KdbpPrint("  UserRsp:                       0x%p\n", (PVOID)Pcr->UserRsp);
236925336250STimo Kreuzer     KdbpPrint("  Self:                          0x%p\n", Pcr->Self);
237025336250STimo Kreuzer     KdbpPrint("  CurrentPrcb:                   0x%p\n", Pcr->CurrentPrcb);
237125336250STimo Kreuzer     KdbpPrint("  LockArray:                     0x%p\n", Pcr->LockArray);
237225336250STimo Kreuzer     KdbpPrint("  Used_Self:                     0x%p\n", Pcr->Used_Self);
237325336250STimo Kreuzer     KdbpPrint("  IdtBase:                       0x%p\n", Pcr->IdtBase);
237425336250STimo Kreuzer     KdbpPrint("  Irql:                          %u\n", Pcr->Irql);
237525336250STimo Kreuzer     KdbpPrint("  SecondLevelCacheAssociativity: 0x%u\n", Pcr->SecondLevelCacheAssociativity);
237625336250STimo Kreuzer     KdbpPrint("  ObsoleteNumber:                %u\n", Pcr->ObsoleteNumber);
237725336250STimo Kreuzer     KdbpPrint("  MajorVersion:                  0x%x\n", Pcr->MajorVersion);
237825336250STimo Kreuzer     KdbpPrint("  MinorVersion:                  0x%x\n", Pcr->MinorVersion);
237925336250STimo Kreuzer     KdbpPrint("  StallScaleFactor:              0x%lx\n", Pcr->StallScaleFactor);
238025336250STimo Kreuzer     KdbpPrint("  SecondLevelCacheSize:          0x%lx\n", Pcr->SecondLevelCacheSize);
238125336250STimo Kreuzer     KdbpPrint("  KdVersionBlock:                0x%p\n", Pcr->KdVersionBlock);
23823726b992SJérôme Gardou #endif
2383c2c66affSColin Finck 
2384c2c66affSColin Finck     return TRUE;
2385c2c66affSColin Finck }
2386c2c66affSColin Finck 
23873726b992SJérôme Gardou #ifdef _M_IX86
2388c2c66affSColin Finck /*!\brief Displays the TSS
2389c2c66affSColin Finck  */
2390c2c66affSColin Finck static BOOLEAN
KdbpCmdTss(ULONG Argc,PCHAR Argv[])2391c2c66affSColin Finck KdbpCmdTss(
2392c2c66affSColin Finck     ULONG Argc,
2393c2c66affSColin Finck     PCHAR Argv[])
2394c2c66affSColin Finck {
23958826ee8fSHermès Bélusca-Maïto     USHORT TssSelector;
23968826ee8fSHermès Bélusca-Maïto     PKTSS Tss = NULL;
2397c2c66affSColin Finck 
23988826ee8fSHermès Bélusca-Maïto     if (Argc >= 2)
23998826ee8fSHermès Bélusca-Maïto     {
24008826ee8fSHermès Bélusca-Maïto         /*
24018826ee8fSHermès Bélusca-Maïto          * Specified TSS via its selector [selector] or descriptor address [*descaddr].
24028826ee8fSHermès Bélusca-Maïto          * Note that we ignore any other argument values.
24038826ee8fSHermès Bélusca-Maïto          */
24048826ee8fSHermès Bélusca-Maïto         PCHAR Param, pszNext;
24058826ee8fSHermès Bélusca-Maïto         ULONG ulValue;
24068826ee8fSHermès Bélusca-Maïto 
24078826ee8fSHermès Bélusca-Maïto         Param = Argv[1];
24088826ee8fSHermès Bélusca-Maïto         if (Argv[1][0] == '*')
24098826ee8fSHermès Bélusca-Maïto             ++Param;
24108826ee8fSHermès Bélusca-Maïto 
24118826ee8fSHermès Bélusca-Maïto         ulValue = strtoul(Param, &pszNext, 0);
24128826ee8fSHermès Bélusca-Maïto         if (pszNext && *pszNext)
24138826ee8fSHermès Bélusca-Maïto         {
24148826ee8fSHermès Bélusca-Maïto             KdbpPrint("Invalid TSS specification.\n");
24158826ee8fSHermès Bélusca-Maïto             return TRUE;
24168826ee8fSHermès Bélusca-Maïto         }
24178826ee8fSHermès Bélusca-Maïto 
24188826ee8fSHermès Bélusca-Maïto         if (Argv[1][0] == '*')
24198826ee8fSHermès Bélusca-Maïto         {
24208826ee8fSHermès Bélusca-Maïto             /* Descriptor specified */
24218826ee8fSHermès Bélusca-Maïto             TssSelector = 0; // Unknown selector!
24228826ee8fSHermès Bélusca-Maïto             // TODO: Room for improvement: Find the TSS descriptor
24238826ee8fSHermès Bélusca-Maïto             // in the GDT so as to validate it.
24248826ee8fSHermès Bélusca-Maïto             Tss = (PKTSS)(ULONG_PTR)ulValue;
24258826ee8fSHermès Bélusca-Maïto             if (!Tss)
24268826ee8fSHermès Bélusca-Maïto             {
24278826ee8fSHermès Bélusca-Maïto                 KdbpPrint("Invalid 32-bit TSS descriptor.\n");
24288826ee8fSHermès Bélusca-Maïto                 return TRUE;
24298826ee8fSHermès Bélusca-Maïto             }
24308826ee8fSHermès Bélusca-Maïto         }
24318826ee8fSHermès Bélusca-Maïto         else
24328826ee8fSHermès Bélusca-Maïto         {
24338826ee8fSHermès Bélusca-Maïto             /* Selector specified, retrive the corresponding TSS */
24348826ee8fSHermès Bélusca-Maïto             TssSelector = (USHORT)ulValue;
24358826ee8fSHermès Bélusca-Maïto             Tss = KdbpRetrieveTss(TssSelector, NULL, NULL);
24368826ee8fSHermès Bélusca-Maïto             if (!Tss)
24378826ee8fSHermès Bélusca-Maïto             {
24388826ee8fSHermès Bélusca-Maïto                 KdbpPrint("Invalid 32-bit TSS selector.\n");
24398826ee8fSHermès Bélusca-Maïto                 return TRUE;
24408826ee8fSHermès Bélusca-Maïto             }
24418826ee8fSHermès Bélusca-Maïto         }
24428826ee8fSHermès Bélusca-Maïto     }
24438826ee8fSHermès Bélusca-Maïto 
24448826ee8fSHermès Bélusca-Maïto     if (!Tss)
24458826ee8fSHermès Bélusca-Maïto     {
24468826ee8fSHermès Bélusca-Maïto         /* If no TSS was specified, use the current TSS descriptor */
24478826ee8fSHermès Bélusca-Maïto         TssSelector = Ke386GetTr();
24488826ee8fSHermès Bélusca-Maïto         Tss = KeGetPcr()->TSS;
24498826ee8fSHermès Bélusca-Maïto         // NOTE: If everything works OK, Tss is the current TSS corresponding to the TR selector.
24508826ee8fSHermès Bélusca-Maïto     }
24518826ee8fSHermès Bélusca-Maïto 
24528826ee8fSHermès Bélusca-Maïto     KdbpPrint("%s TSS 0x%04x is at 0x%p.\n",
24538826ee8fSHermès Bélusca-Maïto               (Tss == KeGetPcr()->TSS) ? "Current" : "Specified", TssSelector, Tss);
24548826ee8fSHermès Bélusca-Maïto     KdbpPrint("  Backlink:  0x%04x\n"
24558826ee8fSHermès Bélusca-Maïto               "  Ss0:Esp0:  0x%04x:0x%08x\n"
24568826ee8fSHermès Bélusca-Maïto               // NOTE: Ss1:Esp1 and Ss2:Esp2: are in the NotUsed1 field.
24578826ee8fSHermès Bélusca-Maïto               "  CR3:       0x%08x\n"
24588826ee8fSHermès Bélusca-Maïto               "  EFlags:    0x%08x\n"
24598826ee8fSHermès Bélusca-Maïto               "  Eax:       0x%08x\n"
24608826ee8fSHermès Bélusca-Maïto               "  Ebx:       0x%08x\n"
24618826ee8fSHermès Bélusca-Maïto               "  Ecx:       0x%08x\n"
24628826ee8fSHermès Bélusca-Maïto               "  Edx:       0x%08x\n"
24638826ee8fSHermès Bélusca-Maïto               "  Esi:       0x%08x\n"
24648826ee8fSHermès Bélusca-Maïto               "  Edi:       0x%08x\n"
24658826ee8fSHermès Bélusca-Maïto               "  Eip:       0x%08x\n"
24668826ee8fSHermès Bélusca-Maïto               "  Esp:       0x%08x\n"
24678826ee8fSHermès Bélusca-Maïto               "  Ebp:       0x%08x\n"
2468c2c66affSColin Finck               "  Cs:        0x%04x\n"
2469c2c66affSColin Finck               "  Ss:        0x%04x\n"
2470c2c66affSColin Finck               "  Ds:        0x%04x\n"
24718826ee8fSHermès Bélusca-Maïto               "  Es:        0x%04x\n"
2472c2c66affSColin Finck               "  Fs:        0x%04x\n"
2473c2c66affSColin Finck               "  Gs:        0x%04x\n"
24748826ee8fSHermès Bélusca-Maïto               "  LDT:       0x%04x\n"
24758826ee8fSHermès Bélusca-Maïto               "  Flags:     0x%04x\n"
2476c2c66affSColin Finck               "  IoMapBase: 0x%04x\n",
24778826ee8fSHermès Bélusca-Maïto               Tss->Backlink, Tss->Ss0, Tss->Esp0, Tss->CR3, Tss->EFlags,
24788826ee8fSHermès Bélusca-Maïto               Tss->Eax, Tss->Ebx, Tss->Ecx, Tss->Edx, Tss->Esi, Tss->Edi,
24798826ee8fSHermès Bélusca-Maïto               Tss->Eip, Tss->Esp, Tss->Ebp,
24808826ee8fSHermès Bélusca-Maïto               Tss->Cs, Tss->Ss, Tss->Ds, Tss->Es, Tss->Fs, Tss->Gs,
24818826ee8fSHermès Bélusca-Maïto               Tss->LDT, Tss->Flags, Tss->IoMapBase);
2482c2c66affSColin Finck 
2483c2c66affSColin Finck     return TRUE;
2484c2c66affSColin Finck }
248525336250STimo Kreuzer #endif // _M_IX86
2486c2c66affSColin Finck 
2487c2c66affSColin Finck /*!\brief Bugchecks the system.
2488c2c66affSColin Finck  */
2489c2c66affSColin Finck static BOOLEAN
KdbpCmdBugCheck(ULONG Argc,PCHAR Argv[])2490c2c66affSColin Finck KdbpCmdBugCheck(
2491c2c66affSColin Finck     ULONG Argc,
2492c2c66affSColin Finck     PCHAR Argv[])
2493c2c66affSColin Finck {
2494c2c66affSColin Finck     /* Set the flag and quit looping */
2495c2c66affSColin Finck     KdbpBugCheckRequested = TRUE;
2496c2c66affSColin Finck     return FALSE;
2497c2c66affSColin Finck }
2498c2c66affSColin Finck 
2499c2c66affSColin Finck static BOOLEAN
KdbpCmdReboot(ULONG Argc,PCHAR Argv[])2500c2c66affSColin Finck KdbpCmdReboot(
2501c2c66affSColin Finck     ULONG Argc,
2502c2c66affSColin Finck     PCHAR Argv[])
2503c2c66affSColin Finck {
2504c2c66affSColin Finck     /* Reboot immediately (we do not return) */
2505c2c66affSColin Finck     HalReturnToFirmware(HalRebootRoutine);
2506c2c66affSColin Finck     return FALSE;
2507c2c66affSColin Finck }
2508c2c66affSColin Finck 
2509c2c66affSColin Finck /*!\brief Display debug messages on screen, with paging.
2510c2c66affSColin Finck  *
2511c2c66affSColin Finck  * Keys for per-page view: Home, End, PageUp, Arrow Up, PageDown,
2512c2c66affSColin Finck  * all others are as PageDown.
2513c2c66affSColin Finck  */
2514c2c66affSColin Finck static BOOLEAN
KdbpCmdDmesg(ULONG Argc,PCHAR Argv[])2515c2c66affSColin Finck KdbpCmdDmesg(
2516c2c66affSColin Finck     ULONG Argc,
2517c2c66affSColin Finck     PCHAR Argv[])
2518c2c66affSColin Finck {
2519c2c66affSColin Finck     ULONG beg, end;
2520c2c66affSColin Finck 
2521c2c66affSColin Finck     KdbpIsInDmesgMode = TRUE; /* Toggle logging flag */
2522c2c66affSColin Finck     if (!KdpDmesgBuffer)
2523c2c66affSColin Finck     {
2524c2c66affSColin Finck         KdbpPrint("Dmesg: error, buffer is not allocated! /DEBUGPORT=SCREEN kernel param required for dmesg.\n");
2525c2c66affSColin Finck         return TRUE;
2526c2c66affSColin Finck     }
2527c2c66affSColin Finck 
2528c2c66affSColin Finck     KdbpPrint("*** Dmesg *** TotalWritten=%lu, BufferSize=%lu, CurrentPosition=%lu\n",
2529c2c66affSColin Finck               KdbDmesgTotalWritten, KdpDmesgBufferSize, KdpDmesgCurrentPosition);
2530c2c66affSColin Finck 
2531f0d59e74SHermès Bélusca-Maïto     /* Pass data to the pager */
2532c2c66affSColin Finck     end = KdpDmesgCurrentPosition;
2533c2c66affSColin Finck     beg = (end + KdpDmesgFreeBytes) % KdpDmesgBufferSize;
2534c2c66affSColin Finck 
2535f0d59e74SHermès Bélusca-Maïto     /* No roll-overs, and overwritten=lost bytes */
2536c2c66affSColin Finck     if (KdbDmesgTotalWritten <= KdpDmesgBufferSize)
2537c2c66affSColin Finck     {
2538f0d59e74SHermès Bélusca-Maïto         /* Show buffer (KdpDmesgBuffer + beg, num) */
2539c2c66affSColin Finck         KdbpPager(KdpDmesgBuffer, KdpDmesgCurrentPosition);
2540c2c66affSColin Finck     }
2541c2c66affSColin Finck     else
2542c2c66affSColin Finck     {
2543f0d59e74SHermès Bélusca-Maïto         /* Show 2 buffers: (KdpDmesgBuffer + beg, KdpDmesgBufferSize - beg)
2544f0d59e74SHermès Bélusca-Maïto          *            and: (KdpDmesgBuffer,       end) */
2545c2c66affSColin Finck         KdbpPager(KdpDmesgBuffer + beg, KdpDmesgBufferSize - beg);
2546c2c66affSColin Finck         KdbpPrint("*** Dmesg: buffer rollup ***\n");
2547c2c66affSColin Finck         KdbpPager(KdpDmesgBuffer,       end);
2548c2c66affSColin Finck     }
2549c2c66affSColin Finck     KdbpPrint("*** Dmesg: end of output ***\n");
2550c2c66affSColin Finck 
2551c2c66affSColin Finck     KdbpIsInDmesgMode = FALSE; /* Toggle logging flag */
2552c2c66affSColin Finck 
2553c2c66affSColin Finck     return TRUE;
2554c2c66affSColin Finck }
2555c2c66affSColin Finck 
2556c2c66affSColin Finck /*!\brief Sets or displays a config variables value.
2557c2c66affSColin Finck  */
2558c2c66affSColin Finck static BOOLEAN
KdbpCmdSet(ULONG Argc,PCHAR Argv[])2559c2c66affSColin Finck KdbpCmdSet(
2560c2c66affSColin Finck     ULONG Argc,
2561c2c66affSColin Finck     PCHAR Argv[])
2562c2c66affSColin Finck {
2563c2c66affSColin Finck     LONG l;
2564c2c66affSColin Finck     BOOLEAN First;
2565c2c66affSColin Finck     PCHAR pend = 0;
2566c2c66affSColin Finck     KDB_ENTER_CONDITION ConditionFirst = KdbDoNotEnter;
2567c2c66affSColin Finck     KDB_ENTER_CONDITION ConditionLast = KdbDoNotEnter;
2568c2c66affSColin Finck 
2569c2c66affSColin Finck     static const PCHAR ExceptionNames[21] =
2570c2c66affSColin Finck     {
2571c2c66affSColin Finck         "ZERODEVIDE", "DEBUGTRAP", "NMI", "INT3", "OVERFLOW", "BOUND", "INVALIDOP",
2572c2c66affSColin Finck         "NOMATHCOP", "DOUBLEFAULT", "RESERVED(9)", "INVALIDTSS", "SEGMENTNOTPRESENT",
2573c2c66affSColin Finck         "STACKFAULT", "GPF", "PAGEFAULT", "RESERVED(15)", "MATHFAULT", "ALIGNMENTCHECK",
2574c2c66affSColin Finck         "MACHINECHECK", "SIMDFAULT", "OTHERS"
2575c2c66affSColin Finck     };
2576c2c66affSColin Finck 
2577c2c66affSColin Finck     if (Argc == 1)
2578c2c66affSColin Finck     {
2579c2c66affSColin Finck         KdbpPrint("Available settings:\n");
2580c2c66affSColin Finck         KdbpPrint("  syntax [intel|at&t]\n");
2581c2c66affSColin Finck         KdbpPrint("  condition [exception|*] [first|last] [never|always|kmode|umode]\n");
2582c2c66affSColin Finck         KdbpPrint("  break_on_module_load [true|false]\n");
2583c2c66affSColin Finck     }
2584c2c66affSColin Finck     else if (strcmp(Argv[1], "syntax") == 0)
2585c2c66affSColin Finck     {
2586c2c66affSColin Finck         if (Argc == 2)
2587c2c66affSColin Finck         {
2588c2c66affSColin Finck             KdbpPrint("syntax = %s\n", KdbUseIntelSyntax ? "intel" : "at&t");
2589c2c66affSColin Finck         }
2590c2c66affSColin Finck         else if (Argc >= 3)
2591c2c66affSColin Finck         {
2592c2c66affSColin Finck             if (_stricmp(Argv[2], "intel") == 0)
2593c2c66affSColin Finck                 KdbUseIntelSyntax = TRUE;
2594c2c66affSColin Finck             else if (_stricmp(Argv[2], "at&t") == 0)
2595c2c66affSColin Finck                 KdbUseIntelSyntax = FALSE;
2596c2c66affSColin Finck             else
2597c2c66affSColin Finck                 KdbpPrint("Unknown syntax '%s'.\n", Argv[2]);
2598c2c66affSColin Finck         }
2599c2c66affSColin Finck     }
2600c2c66affSColin Finck     else if (strcmp(Argv[1], "condition") == 0)
2601c2c66affSColin Finck     {
2602c2c66affSColin Finck         if (Argc == 2)
2603c2c66affSColin Finck         {
2604c2c66affSColin Finck             KdbpPrint("Conditions:                 (First)  (Last)\n");
2605c2c66affSColin Finck             for (l = 0; l < RTL_NUMBER_OF(ExceptionNames) - 1; l++)
2606c2c66affSColin Finck             {
2607c2c66affSColin Finck                 if (!ExceptionNames[l])
2608c2c66affSColin Finck                     continue;
2609c2c66affSColin Finck 
2610c2c66affSColin Finck                 if (!KdbpGetEnterCondition(l, TRUE, &ConditionFirst))
2611f0d59e74SHermès Bélusca-Maïto                     ASSERT(FALSE);
2612c2c66affSColin Finck 
2613c2c66affSColin Finck                 if (!KdbpGetEnterCondition(l, FALSE, &ConditionLast))
2614f0d59e74SHermès Bélusca-Maïto                     ASSERT(FALSE);
2615c2c66affSColin Finck 
2616c2c66affSColin Finck                 KdbpPrint("  #%02d  %-20s %-8s %-8s\n", l, ExceptionNames[l],
2617c2c66affSColin Finck                           KDB_ENTER_CONDITION_TO_STRING(ConditionFirst),
2618c2c66affSColin Finck                           KDB_ENTER_CONDITION_TO_STRING(ConditionLast));
2619c2c66affSColin Finck             }
2620c2c66affSColin Finck 
2621c2c66affSColin Finck             ASSERT(l == (RTL_NUMBER_OF(ExceptionNames) - 1));
2622c2c66affSColin Finck             KdbpPrint("       %-20s %-8s %-8s\n", ExceptionNames[l],
2623c2c66affSColin Finck                       KDB_ENTER_CONDITION_TO_STRING(ConditionFirst),
2624c2c66affSColin Finck                       KDB_ENTER_CONDITION_TO_STRING(ConditionLast));
2625c2c66affSColin Finck         }
2626c2c66affSColin Finck         else
2627c2c66affSColin Finck         {
2628c2c66affSColin Finck             if (Argc >= 5 && strcmp(Argv[2], "*") == 0) /* Allow * only when setting condition */
2629c2c66affSColin Finck             {
2630c2c66affSColin Finck                 l = -1;
2631c2c66affSColin Finck             }
2632c2c66affSColin Finck             else
2633c2c66affSColin Finck             {
2634c2c66affSColin Finck                 l = strtoul(Argv[2], &pend, 0);
2635c2c66affSColin Finck 
2636c2c66affSColin Finck                 if (Argv[2] == pend)
2637c2c66affSColin Finck                 {
2638c2c66affSColin Finck                     for (l = 0; l < RTL_NUMBER_OF(ExceptionNames); l++)
2639c2c66affSColin Finck                     {
2640c2c66affSColin Finck                         if (!ExceptionNames[l])
2641c2c66affSColin Finck                             continue;
2642c2c66affSColin Finck 
2643c2c66affSColin Finck                         if (_stricmp(ExceptionNames[l], Argv[2]) == 0)
2644c2c66affSColin Finck                             break;
2645c2c66affSColin Finck                     }
2646c2c66affSColin Finck                 }
2647c2c66affSColin Finck 
2648c2c66affSColin Finck                 if (l >= RTL_NUMBER_OF(ExceptionNames))
2649c2c66affSColin Finck                 {
2650c2c66affSColin Finck                     KdbpPrint("Unknown exception '%s'.\n", Argv[2]);
2651c2c66affSColin Finck                     return TRUE;
2652c2c66affSColin Finck                 }
2653c2c66affSColin Finck             }
2654c2c66affSColin Finck 
2655c2c66affSColin Finck             if (Argc > 4)
2656c2c66affSColin Finck             {
2657c2c66affSColin Finck                 if (_stricmp(Argv[3], "first") == 0)
2658c2c66affSColin Finck                     First = TRUE;
2659c2c66affSColin Finck                 else if (_stricmp(Argv[3], "last") == 0)
2660c2c66affSColin Finck                     First = FALSE;
2661c2c66affSColin Finck                 else
2662c2c66affSColin Finck                 {
2663c2c66affSColin Finck                     KdbpPrint("set condition: second argument must be 'first' or 'last'\n");
2664c2c66affSColin Finck                     return TRUE;
2665c2c66affSColin Finck                 }
2666c2c66affSColin Finck 
2667c2c66affSColin Finck                 if (_stricmp(Argv[4], "never") == 0)
2668c2c66affSColin Finck                     ConditionFirst = KdbDoNotEnter;
2669c2c66affSColin Finck                 else if (_stricmp(Argv[4], "always") == 0)
2670c2c66affSColin Finck                     ConditionFirst = KdbEnterAlways;
2671c2c66affSColin Finck                 else if (_stricmp(Argv[4], "umode") == 0)
2672c2c66affSColin Finck                     ConditionFirst = KdbEnterFromUmode;
2673c2c66affSColin Finck                 else if (_stricmp(Argv[4], "kmode") == 0)
2674c2c66affSColin Finck                     ConditionFirst = KdbEnterFromKmode;
2675c2c66affSColin Finck                 else
2676c2c66affSColin Finck                 {
2677c2c66affSColin Finck                     KdbpPrint("set condition: third argument must be 'never', 'always', 'umode' or 'kmode'\n");
2678c2c66affSColin Finck                     return TRUE;
2679c2c66affSColin Finck                 }
2680c2c66affSColin Finck 
2681c2c66affSColin Finck                 if (!KdbpSetEnterCondition(l, First, ConditionFirst))
2682c2c66affSColin Finck                 {
2683c2c66affSColin Finck                     if (l >= 0)
2684c2c66affSColin Finck                         KdbpPrint("Couldn't change condition for exception #%02d\n", l);
2685c2c66affSColin Finck                     else
2686c2c66affSColin Finck                         KdbpPrint("Couldn't change condition for all exceptions\n", l);
2687c2c66affSColin Finck                 }
2688c2c66affSColin Finck             }
2689c2c66affSColin Finck             else /* Argc >= 3 */
2690c2c66affSColin Finck             {
2691c2c66affSColin Finck                 if (!KdbpGetEnterCondition(l, TRUE, &ConditionFirst))
2692f0d59e74SHermès Bélusca-Maïto                     ASSERT(FALSE);
2693c2c66affSColin Finck 
2694c2c66affSColin Finck                 if (!KdbpGetEnterCondition(l, FALSE, &ConditionLast))
2695f0d59e74SHermès Bélusca-Maïto                     ASSERT(FALSE);
2696c2c66affSColin Finck 
2697c2c66affSColin Finck                 if (l < (RTL_NUMBER_OF(ExceptionNames) - 1))
2698c2c66affSColin Finck                 {
2699c2c66affSColin Finck                     KdbpPrint("Condition for exception #%02d (%s): FirstChance %s  LastChance %s\n",
2700c2c66affSColin Finck                               l, ExceptionNames[l],
2701c2c66affSColin Finck                               KDB_ENTER_CONDITION_TO_STRING(ConditionFirst),
2702c2c66affSColin Finck                               KDB_ENTER_CONDITION_TO_STRING(ConditionLast));
2703c2c66affSColin Finck                 }
2704c2c66affSColin Finck                 else
2705c2c66affSColin Finck                 {
2706c2c66affSColin Finck                     KdbpPrint("Condition for all other exceptions: FirstChance %s  LastChance %s\n",
2707c2c66affSColin Finck                               KDB_ENTER_CONDITION_TO_STRING(ConditionFirst),
2708c2c66affSColin Finck                               KDB_ENTER_CONDITION_TO_STRING(ConditionLast));
2709c2c66affSColin Finck                 }
2710c2c66affSColin Finck             }
2711c2c66affSColin Finck         }
2712c2c66affSColin Finck     }
2713c2c66affSColin Finck     else if (strcmp(Argv[1], "break_on_module_load") == 0)
2714c2c66affSColin Finck     {
2715c2c66affSColin Finck         if (Argc == 2)
2716c2c66affSColin Finck             KdbpPrint("break_on_module_load = %s\n", KdbBreakOnModuleLoad ? "enabled" : "disabled");
2717c2c66affSColin Finck         else if (Argc >= 3)
2718c2c66affSColin Finck         {
2719c2c66affSColin Finck             if (_stricmp(Argv[2], "enable") == 0 || _stricmp(Argv[2], "enabled") == 0 || _stricmp(Argv[2], "true") == 0)
2720c2c66affSColin Finck                 KdbBreakOnModuleLoad = TRUE;
2721c2c66affSColin Finck             else if (_stricmp(Argv[2], "disable") == 0 || _stricmp(Argv[2], "disabled") == 0 || _stricmp(Argv[2], "false") == 0)
2722c2c66affSColin Finck                 KdbBreakOnModuleLoad = FALSE;
2723c2c66affSColin Finck             else
2724c2c66affSColin Finck                 KdbpPrint("Unknown setting '%s'.\n", Argv[2]);
2725c2c66affSColin Finck         }
2726c2c66affSColin Finck     }
2727c2c66affSColin Finck     else
2728c2c66affSColin Finck     {
2729c2c66affSColin Finck         KdbpPrint("Unknown setting '%s'.\n", Argv[1]);
2730c2c66affSColin Finck     }
2731c2c66affSColin Finck 
2732c2c66affSColin Finck     return TRUE;
2733c2c66affSColin Finck }
2734c2c66affSColin Finck 
2735c2c66affSColin Finck /*!\brief Displays help screen.
2736c2c66affSColin Finck  */
2737c2c66affSColin Finck static BOOLEAN
KdbpCmdHelp(ULONG Argc,PCHAR Argv[])2738c2c66affSColin Finck KdbpCmdHelp(
2739c2c66affSColin Finck     ULONG Argc,
2740c2c66affSColin Finck     PCHAR Argv[])
2741c2c66affSColin Finck {
2742c2c66affSColin Finck     ULONG i;
2743c2c66affSColin Finck 
2744c2c66affSColin Finck     KdbpPrint("Kernel debugger commands:\n");
2745c2c66affSColin Finck     for (i = 0; i < RTL_NUMBER_OF(KdbDebuggerCommands); i++)
2746c2c66affSColin Finck     {
2747c2c66affSColin Finck         if (!KdbDebuggerCommands[i].Syntax) /* Command group */
2748c2c66affSColin Finck         {
2749c2c66affSColin Finck             if (i > 0)
2750c2c66affSColin Finck                 KdbpPrint("\n");
2751c2c66affSColin Finck 
2752c2c66affSColin Finck             KdbpPrint("\x1b[7m* %s:\x1b[0m\n", KdbDebuggerCommands[i].Help);
2753c2c66affSColin Finck             continue;
2754c2c66affSColin Finck         }
2755c2c66affSColin Finck 
2756c2c66affSColin Finck         KdbpPrint("  %-20s - %s\n",
2757c2c66affSColin Finck                   KdbDebuggerCommands[i].Syntax,
2758c2c66affSColin Finck                   KdbDebuggerCommands[i].Help);
2759c2c66affSColin Finck     }
2760c2c66affSColin Finck 
2761c2c66affSColin Finck     return TRUE;
2762c2c66affSColin Finck }
2763c2c66affSColin Finck 
2764c2c66affSColin Finck 
2765c2c66affSColin Finck /*
27669337ea6aSHermès Bélusca-Maïto  * memrchr(), explicitly defined, since absent in the CRT.
2767c2c66affSColin Finck  * Reverse memchr()
2768c2c66affSColin Finck  * Find the last occurrence of 'c' in the buffer 's' of size 'n'.
2769c2c66affSColin Finck  */
2770c2c66affSColin Finck void *
memrchr(const void * s,int c,size_t n)2771c2c66affSColin Finck memrchr(const void *s, int c, size_t n)
2772c2c66affSColin Finck {
2773c2c66affSColin Finck     const unsigned char *cp;
2774c2c66affSColin Finck 
2775c2c66affSColin Finck     if (n != 0)
2776c2c66affSColin Finck     {
2777c2c66affSColin Finck         cp = (unsigned char *)s + n;
2778c2c66affSColin Finck         do
2779c2c66affSColin Finck         {
2780c2c66affSColin Finck             if (*(--cp) == (unsigned char)c)
2781c2c66affSColin Finck                 return (void *)cp;
2782c2c66affSColin Finck         } while (--n != 0);
2783c2c66affSColin Finck     }
2784c2c66affSColin Finck     return NULL;
2785c2c66affSColin Finck }
2786c2c66affSColin Finck 
278735180b3aSHermès Bélusca-Maïto /**
278835180b3aSHermès Bélusca-Maïto  * @brief   Calculate pointer position for N lines above the current position.
2789c2c66affSColin Finck  *
279035180b3aSHermès Bélusca-Maïto  * Calculate pointer position for N lines above the current displaying
279135180b3aSHermès Bélusca-Maïto  * position within the given buffer. Used by KdbpPager().
2792c2c66affSColin Finck  *
279335180b3aSHermès Bélusca-Maïto  * @param[in]   Buffer
279435180b3aSHermès Bélusca-Maïto  * Character buffer to operate on.
2795c2c66affSColin Finck  *
279635180b3aSHermès Bélusca-Maïto  * @param[in]   BufLength
279735180b3aSHermès Bélusca-Maïto  * Size of the buffer.
279835180b3aSHermès Bélusca-Maïto  *
279935180b3aSHermès Bélusca-Maïto  * @param[in]   pCurPos
280035180b3aSHermès Bélusca-Maïto  * Current position within the buffer.
280135180b3aSHermès Bélusca-Maïto  *
280235180b3aSHermès Bélusca-Maïto  * @return  Beginning of the previous page of text.
280335180b3aSHermès Bélusca-Maïto  *
280435180b3aSHermès Bélusca-Maïto  * @note    N lines count is hardcoded to the terminal's number of rows.
280535180b3aSHermès Bélusca-Maïto  **/
28069337ea6aSHermès Bélusca-Maïto static PCHAR
CountOnePageUp(_In_ PCCH Buffer,_In_ ULONG BufLength,_In_ PCCH pCurPos,_In_ const SIZE * TermSize)28079337ea6aSHermès Bélusca-Maïto CountOnePageUp(
28089337ea6aSHermès Bélusca-Maïto     _In_ PCCH Buffer,
28099337ea6aSHermès Bélusca-Maïto     _In_ ULONG BufLength,
281035180b3aSHermès Bélusca-Maïto     _In_ PCCH pCurPos,
281135180b3aSHermès Bélusca-Maïto     _In_ const SIZE* TermSize)
2812c2c66affSColin Finck {
28139337ea6aSHermès Bélusca-Maïto     PCCH p;
2814c2c66affSColin Finck     // p0 is initial guess of Page Start
281535180b3aSHermès Bélusca-Maïto     ULONG p0len = TermSize->cx * TermSize->cy;
28169337ea6aSHermès Bélusca-Maïto     PCCH p0 = pCurPos - p0len;
28179337ea6aSHermès Bélusca-Maïto     PCCH prev_p = p0, p1;
2818c2c66affSColin Finck     ULONG j;
2819c2c66affSColin Finck 
2820c2c66affSColin Finck     if (pCurPos < Buffer)
2821c2c66affSColin Finck         pCurPos = Buffer;
2822c2c66affSColin Finck     ASSERT(pCurPos <= Buffer + BufLength);
2823c2c66affSColin Finck 
2824c2c66affSColin Finck     p = memrchr(p0, '\n', p0len);
28259337ea6aSHermès Bélusca-Maïto     if (!p)
2826c2c66affSColin Finck         p = p0;
282735180b3aSHermès Bélusca-Maïto     for (j = TermSize->cy; j--; )
2828c2c66affSColin Finck     {
2829c2c66affSColin Finck         int linesCnt;
2830c2c66affSColin Finck         p1 = memrchr(p0, '\n', p-p0);
2831c2c66affSColin Finck         prev_p = p;
2832c2c66affSColin Finck         p = p1;
28339337ea6aSHermès Bélusca-Maïto         if (!p)
2834c2c66affSColin Finck         {
2835c2c66affSColin Finck             p = prev_p;
28369337ea6aSHermès Bélusca-Maïto             if (!p)
2837c2c66affSColin Finck                 p = p0;
2838c2c66affSColin Finck             break;
2839c2c66affSColin Finck         }
284035180b3aSHermès Bélusca-Maïto         linesCnt = (TermSize->cx+prev_p-p-2) / TermSize->cx;
2841c2c66affSColin Finck         if (linesCnt > 1)
2842c2c66affSColin Finck             j -= linesCnt-1;
2843c2c66affSColin Finck     }
2844c2c66affSColin Finck 
28459337ea6aSHermès Bélusca-Maïto     ASSERT(p != NULL);
2846c2c66affSColin Finck     ++p;
28479337ea6aSHermès Bélusca-Maïto     return (PCHAR)p;
28489337ea6aSHermès Bélusca-Maïto }
28499337ea6aSHermès Bélusca-Maïto 
28509337ea6aSHermès Bélusca-Maïto static VOID
KdpFilterEscapes(_Inout_ PSTR String)28519337ea6aSHermès Bélusca-Maïto KdpFilterEscapes(
28529337ea6aSHermès Bélusca-Maïto     _Inout_ PSTR String)
28539337ea6aSHermès Bélusca-Maïto {
28549337ea6aSHermès Bélusca-Maïto     PCHAR p;
28559337ea6aSHermès Bélusca-Maïto     SIZE_T i;
28569337ea6aSHermès Bélusca-Maïto     size_t len;
28579337ea6aSHermès Bélusca-Maïto 
28589337ea6aSHermès Bélusca-Maïto     while ((p = strrchr(String, '\x1b'))) /* Look for escape character */
28599337ea6aSHermès Bélusca-Maïto     {
28609337ea6aSHermès Bélusca-Maïto         len = strlen(p);
28619337ea6aSHermès Bélusca-Maïto         if (p[1] == '[')
28629337ea6aSHermès Bélusca-Maïto         {
28639337ea6aSHermès Bélusca-Maïto             i = 2;
28649337ea6aSHermès Bélusca-Maïto             while (!isalpha(p[i++]));
28659337ea6aSHermès Bélusca-Maïto             memmove(p, p + i, len + 1 - i);
28669337ea6aSHermès Bélusca-Maïto         }
28679337ea6aSHermès Bélusca-Maïto         else
28689337ea6aSHermès Bélusca-Maïto         {
28699337ea6aSHermès Bélusca-Maïto             memmove(p, p + 1, len);
28709337ea6aSHermès Bélusca-Maïto         }
28719337ea6aSHermès Bélusca-Maïto     }
2872c2c66affSColin Finck }
2873c2c66affSColin Finck 
2874c2c66affSColin Finck /*!\brief Prints the given string with, page by page.
2875c2c66affSColin Finck  *
2876c2c66affSColin Finck  * \param Buffer     Characters buffer to print.
2877c2c66affSColin Finck  * \param BufferLen  Buffer size.
2878c2c66affSColin Finck  *
2879c2c66affSColin Finck  * \note Doesn't correctly handle \\t and terminal escape sequences when calculating the
2880c2c66affSColin Finck  *       number of lines required to print a single line from the Buffer in the terminal.
2881c2c66affSColin Finck  *       Maximum length of buffer is limited only by memory size.
2882f620ce77SHermès Bélusca-Maïto  *       Uses KdbPrintf internally.
2883c2c66affSColin Finck  *
288435180b3aSHermès Bélusca-Maïto  * Note: BufLength should be greater than (KdTermSize.cx * KdTermSize.cy).
2885c2c66affSColin Finck  */
288635180b3aSHermès Bélusca-Maïto static VOID
KdbpPagerInternal(_In_ PCHAR Buffer,_In_ ULONG BufLength,_In_ BOOLEAN DoPage)28879337ea6aSHermès Bélusca-Maïto KdbpPagerInternal(
28889337ea6aSHermès Bélusca-Maïto     _In_ PCHAR Buffer,
28899337ea6aSHermès Bélusca-Maïto     _In_ ULONG BufLength,
28909337ea6aSHermès Bélusca-Maïto     _In_ BOOLEAN DoPage)
2891c2c66affSColin Finck {
2892c2c66affSColin Finck     static BOOLEAN TerminalInitialized = FALSE;
28939337ea6aSHermès Bélusca-Maïto     CHAR c;
2894c2c66affSColin Finck     ULONG ScanCode;
28959337ea6aSHermès Bélusca-Maïto     PCHAR p;
28969337ea6aSHermès Bélusca-Maïto     SIZE_T i;
28979337ea6aSHermès Bélusca-Maïto     LONG RowsPrintedByTerminal;
2898c2c66affSColin Finck 
2899c2c66affSColin Finck     if (BufLength == 0)
2900c2c66affSColin Finck         return;
2901c2c66affSColin Finck 
2902c2c66affSColin Finck     /* Check if the user has aborted output of the current command */
2903c2c66affSColin Finck     if (KdbOutputAborted)
2904c2c66affSColin Finck         return;
2905c2c66affSColin Finck 
2906c2c66affSColin Finck     /* Initialize the terminal */
2907c2c66affSColin Finck     if (!TerminalInitialized)
2908c2c66affSColin Finck     {
29099337ea6aSHermès Bélusca-Maïto         TerminalInitialized = TRUE;
291035180b3aSHermès Bélusca-Maïto         KdpInitTerminal();
2911c2c66affSColin Finck     }
2912c2c66affSColin Finck 
2913b86c4bd5SHermès Bélusca-Maïto     /* Refresh terminal size each time when number of printed rows is 0 */
291435180b3aSHermès Bélusca-Maïto     if (KdbNumberOfRowsPrinted == 0)
2915c2c66affSColin Finck     {
291635180b3aSHermès Bélusca-Maïto         KdpUpdateTerminalSize(&KdTermSize);
2917c2c66affSColin Finck     }
2918c2c66affSColin Finck 
29199337ea6aSHermès Bélusca-Maïto     /* Loop through the strings */
2920c2c66affSColin Finck     p = Buffer;
2921c2c66affSColin Finck     while (p[0] != '\0')
2922c2c66affSColin Finck     {
29239337ea6aSHermès Bélusca-Maïto         if (DoPage)
29249337ea6aSHermès Bélusca-Maïto         {
2925c2c66affSColin Finck             if (p > Buffer + BufLength)
2926c2c66affSColin Finck             {
2927f620ce77SHermès Bélusca-Maïto                 KdbPrintf("Dmesg: error, p > Buffer+BufLength,d=%d", p - (Buffer + BufLength));
2928c2c66affSColin Finck                 return;
2929c2c66affSColin Finck             }
29309337ea6aSHermès Bélusca-Maïto         }
2931c2c66affSColin Finck         i = strcspn(p, "\n");
2932c2c66affSColin Finck 
29339337ea6aSHermès Bélusca-Maïto         if (DoPage)
29349337ea6aSHermès Bélusca-Maïto         {
29359337ea6aSHermès Bélusca-Maïto             /* Are we out of buffer? */
2936c2c66affSColin Finck             if (p + i > Buffer + BufLength)
29379337ea6aSHermès Bélusca-Maïto                 break; // Leaving pager function
29389337ea6aSHermès Bélusca-Maïto         }
2939c2c66affSColin Finck 
29409337ea6aSHermès Bélusca-Maïto         /* Calculate the number of lines which will be printed in
29419337ea6aSHermès Bélusca-Maïto          * the terminal when outputting the current line. */
2942c2c66affSColin Finck         if (i > 0)
294335180b3aSHermès Bélusca-Maïto             RowsPrintedByTerminal = (i + KdbNumberOfColsPrinted - 1) / KdTermSize.cx;
2944c2c66affSColin Finck         else
2945c2c66affSColin Finck             RowsPrintedByTerminal = 0;
2946c2c66affSColin Finck 
2947c2c66affSColin Finck         if (p[i] == '\n')
2948c2c66affSColin Finck             RowsPrintedByTerminal++;
2949c2c66affSColin Finck 
2950f620ce77SHermès Bélusca-Maïto         //KdbPrintf("!%d!%d!%d!%d!", KdbNumberOfRowsPrinted, KdbNumberOfColsPrinted, i, RowsPrintedByTerminal);
2951c2c66affSColin Finck 
2952c2c66affSColin Finck         /* Display a prompt if we printed one screen full of text */
295335180b3aSHermès Bélusca-Maïto         if (KdTermSize.cy > 0 &&
295435180b3aSHermès Bélusca-Maïto             (LONG)(KdbNumberOfRowsPrinted + RowsPrintedByTerminal) >= KdTermSize.cy)
2955c2c66affSColin Finck         {
2956f620ce77SHermès Bélusca-Maïto             PCSTR Prompt;
2957f620ce77SHermès Bélusca-Maïto 
295835180b3aSHermès Bélusca-Maïto             /* Disable the repetition of previous command with long many-page output */
2959c2c66affSColin Finck             KdbRepeatLastCommand = FALSE;
2960c2c66affSColin Finck 
2961c2c66affSColin Finck             if (KdbNumberOfColsPrinted > 0)
2962f620ce77SHermès Bélusca-Maïto                 KdbPuts("\n");
2963c2c66affSColin Finck 
29649337ea6aSHermès Bélusca-Maïto             if (DoPage)
2965f620ce77SHermès Bélusca-Maïto                 Prompt = "--- Press q to abort, e/End,h/Home,u/PgUp, other key/PgDn ---";
29669337ea6aSHermès Bélusca-Maïto             else
2967f620ce77SHermès Bélusca-Maïto                 Prompt = "--- Press q to abort, any other key to continue ---";
2968c2c66affSColin Finck 
2969f620ce77SHermès Bélusca-Maïto             KdbPuts(Prompt);
297035180b3aSHermès Bélusca-Maïto             c = KdpReadTermKey(&ScanCode);
2971f620ce77SHermès Bélusca-Maïto             if (DoPage) // Show pressed key
2972f620ce77SHermès Bélusca-Maïto                 KdbPrintf(" '%c'/scan=%04x\n", c, ScanCode);
29739337ea6aSHermès Bélusca-Maïto             else
2974f620ce77SHermès Bélusca-Maïto                 KdbPuts("\n");
2975f620ce77SHermès Bélusca-Maïto 
2976f620ce77SHermès Bélusca-Maïto             RowsPrintedByTerminal++;
2977c2c66affSColin Finck 
2978c2c66affSColin Finck             if (c == 'q')
2979c2c66affSColin Finck             {
2980c2c66affSColin Finck                 KdbOutputAborted = TRUE;
2981c2c66affSColin Finck                 return;
2982c2c66affSColin Finck             }
29839337ea6aSHermès Bélusca-Maïto 
29849337ea6aSHermès Bélusca-Maïto             if (DoPage)
29859337ea6aSHermès Bélusca-Maïto             {
2986c2c66affSColin Finck                 if (ScanCode == KEYSC_END || c == 'e')
2987c2c66affSColin Finck                 {
2988c2c66affSColin Finck                     PCHAR pBufEnd = Buffer + BufLength;
298935180b3aSHermès Bélusca-Maïto                     p = CountOnePageUp(Buffer, BufLength, pBufEnd, &KdTermSize);
2990c2c66affSColin Finck                     i = strcspn(p, "\n");
2991c2c66affSColin Finck                 }
2992430d7ebbSHermès Bélusca-Maïto                 else if (ScanCode == KEYSC_PAGEUP  ||
2993430d7ebbSHermès Bélusca-Maïto                          ScanCode == KEYSC_ARROWUP || c == 'u')
2994c2c66affSColin Finck                 {
299535180b3aSHermès Bélusca-Maïto                     p = CountOnePageUp(Buffer, BufLength, p, &KdTermSize);
2996c2c66affSColin Finck                     i = strcspn(p, "\n");
2997c2c66affSColin Finck                 }
2998c2c66affSColin Finck                 else if (ScanCode == KEYSC_HOME || c == 'h')
2999c2c66affSColin Finck                 {
3000c2c66affSColin Finck                     p = Buffer;
3001c2c66affSColin Finck                     i = strcspn(p, "\n");
3002c2c66affSColin Finck                 }
30039337ea6aSHermès Bélusca-Maïto             }
3004c2c66affSColin Finck 
3005c2c66affSColin Finck             KdbNumberOfRowsPrinted = 0;
3006c2c66affSColin Finck             KdbNumberOfColsPrinted = 0;
3007c2c66affSColin Finck         }
3008c2c66affSColin Finck 
30099337ea6aSHermès Bélusca-Maïto         /* Insert a NUL after the line and print only the current line */
3010c2c66affSColin Finck         if (p[i] == '\n' && p[i + 1] != '\0')
3011c2c66affSColin Finck         {
3012c2c66affSColin Finck             c = p[i + 1];
3013c2c66affSColin Finck             p[i + 1] = '\0';
3014c2c66affSColin Finck         }
3015c2c66affSColin Finck         else
3016c2c66affSColin Finck         {
3017c2c66affSColin Finck             c = '\0';
3018c2c66affSColin Finck         }
3019c2c66affSColin Finck 
30209337ea6aSHermès Bélusca-Maïto         /* Remove escape sequences from the line if there is no terminal connected */
30219337ea6aSHermès Bélusca-Maïto         // FIXME: Dangerous operation since we modify the source string!!
302235180b3aSHermès Bélusca-Maïto         if (!KdTermConnected)
30239337ea6aSHermès Bélusca-Maïto             KdpFilterEscapes(p);
3024c2c66affSColin Finck 
30259337ea6aSHermès Bélusca-Maïto         /* Print the current line */
3026f620ce77SHermès Bélusca-Maïto         KdbPuts(p);
3027c2c66affSColin Finck 
30289337ea6aSHermès Bélusca-Maïto         /* Restore not null char with saved */
3029c2c66affSColin Finck         if (c != '\0')
3030c2c66affSColin Finck             p[i + 1] = c;
3031c2c66affSColin Finck 
3032c2c66affSColin Finck         /* Set p to the start of the next line and
3033b86c4bd5SHermès Bélusca-Maïto          * remember the number of printed rows/cols */
3034c2c66affSColin Finck         p += i;
3035c2c66affSColin Finck         if (p[0] == '\n')
3036c2c66affSColin Finck         {
3037c2c66affSColin Finck             p++;
3038c2c66affSColin Finck             KdbNumberOfColsPrinted = 0;
3039c2c66affSColin Finck         }
3040c2c66affSColin Finck         else
3041c2c66affSColin Finck         {
3042c2c66affSColin Finck             ASSERT(p[0] == '\0');
3043c2c66affSColin Finck             KdbNumberOfColsPrinted += i;
3044c2c66affSColin Finck         }
3045c2c66affSColin Finck 
3046c2c66affSColin Finck         KdbNumberOfRowsPrinted += RowsPrintedByTerminal;
3047c2c66affSColin Finck     }
3048c2c66affSColin Finck }
3049c2c66affSColin Finck 
30509337ea6aSHermès Bélusca-Maïto /*!\brief Prints the given string with, page by page.
30519337ea6aSHermès Bélusca-Maïto  *
30529337ea6aSHermès Bélusca-Maïto  * \param Buffer     Characters buffer to print.
30539337ea6aSHermès Bélusca-Maïto  * \param BufferLen  Buffer size.
30549337ea6aSHermès Bélusca-Maïto  *
30559337ea6aSHermès Bélusca-Maïto  * \note Doesn't correctly handle \\t and terminal escape sequences when calculating the
30569337ea6aSHermès Bélusca-Maïto  *       number of lines required to print a single line from the Buffer in the terminal.
30579337ea6aSHermès Bélusca-Maïto  *       Maximum length of buffer is limited only by memory size.
3058f620ce77SHermès Bélusca-Maïto  *       Uses KdbPrintf internally.
30599337ea6aSHermès Bélusca-Maïto  *
306035180b3aSHermès Bélusca-Maïto  * Note: BufLength should be greater than (KdTermSize.cx * KdTermSize.cy).
30619337ea6aSHermès Bélusca-Maïto  */
30629337ea6aSHermès Bélusca-Maïto VOID
KdbpPager(_In_ PCHAR Buffer,_In_ ULONG BufLength)30639337ea6aSHermès Bélusca-Maïto KdbpPager(
30649337ea6aSHermès Bélusca-Maïto     _In_ PCHAR Buffer,
30659337ea6aSHermès Bélusca-Maïto     _In_ ULONG BufLength)
30669337ea6aSHermès Bélusca-Maïto {
30679337ea6aSHermès Bélusca-Maïto     /* Call the internal function */
30689337ea6aSHermès Bélusca-Maïto     KdbpPagerInternal(Buffer, BufLength, TRUE);
30699337ea6aSHermès Bélusca-Maïto }
30709337ea6aSHermès Bélusca-Maïto 
30719337ea6aSHermès Bélusca-Maïto /*!\brief Prints the given string with printf-like formatting.
30729337ea6aSHermès Bélusca-Maïto  *
30739337ea6aSHermès Bélusca-Maïto  * \param Format  Format of the string/arguments.
30749337ea6aSHermès Bélusca-Maïto  * \param ...     Variable number of arguments matching the format specified in \a Format.
30759337ea6aSHermès Bélusca-Maïto  *
30769337ea6aSHermès Bélusca-Maïto  * \note Doesn't correctly handle \\t and terminal escape sequences when calculating the
30779337ea6aSHermès Bélusca-Maïto  *       number of lines required to print a single line from the Buffer in the terminal.
30789337ea6aSHermès Bélusca-Maïto  *       Prints maximum 4096 chars, because of its buffer size.
30799337ea6aSHermès Bélusca-Maïto  */
30809337ea6aSHermès Bélusca-Maïto VOID
KdbpPrint(_In_ PSTR Format,_In_...)30819337ea6aSHermès Bélusca-Maïto KdbpPrint(
30829337ea6aSHermès Bélusca-Maïto     _In_ PSTR Format,
30839337ea6aSHermès Bélusca-Maïto     _In_ ...)
30849337ea6aSHermès Bélusca-Maïto {
30859337ea6aSHermès Bélusca-Maïto     static CHAR Buffer[4096];
30869337ea6aSHermès Bélusca-Maïto     ULONG Length;
30879337ea6aSHermès Bélusca-Maïto     va_list ap;
30889337ea6aSHermès Bélusca-Maïto 
30899337ea6aSHermès Bélusca-Maïto     /* Check if the user has aborted output of the current command */
30909337ea6aSHermès Bélusca-Maïto     if (KdbOutputAborted)
30919337ea6aSHermès Bélusca-Maïto         return;
30929337ea6aSHermès Bélusca-Maïto 
30939337ea6aSHermès Bélusca-Maïto     /* Build the string */
30949337ea6aSHermès Bélusca-Maïto     va_start(ap, Format);
30959337ea6aSHermès Bélusca-Maïto     Length = _vsnprintf(Buffer, sizeof(Buffer) - 1, Format, ap);
30969337ea6aSHermès Bélusca-Maïto     Buffer[Length] = '\0';
30979337ea6aSHermès Bélusca-Maïto     va_end(ap);
30989337ea6aSHermès Bélusca-Maïto 
30999337ea6aSHermès Bélusca-Maïto     /* Actually print it */
31009337ea6aSHermès Bélusca-Maïto     KdbpPagerInternal(Buffer, Length, FALSE);
31019337ea6aSHermès Bélusca-Maïto }
31029337ea6aSHermès Bélusca-Maïto 
31039337ea6aSHermès Bélusca-Maïto VOID
KdbpPrintUnicodeString(_In_ PCUNICODE_STRING String)31049337ea6aSHermès Bélusca-Maïto KdbpPrintUnicodeString(
31059337ea6aSHermès Bélusca-Maïto     _In_ PCUNICODE_STRING String)
31069337ea6aSHermès Bélusca-Maïto {
31079337ea6aSHermès Bélusca-Maïto     ULONG i;
31089337ea6aSHermès Bélusca-Maïto 
31099337ea6aSHermès Bélusca-Maïto     if ((String == NULL) || (String->Buffer == NULL))
31109337ea6aSHermès Bélusca-Maïto     {
31119337ea6aSHermès Bélusca-Maïto         KdbpPrint("<NULL>");
31129337ea6aSHermès Bélusca-Maïto         return;
31139337ea6aSHermès Bélusca-Maïto     }
31149337ea6aSHermès Bélusca-Maïto 
31159337ea6aSHermès Bélusca-Maïto     for (i = 0; i < String->Length / sizeof(WCHAR); i++)
31169337ea6aSHermès Bélusca-Maïto     {
31179337ea6aSHermès Bélusca-Maïto         KdbpPrint("%c", (CHAR)String->Buffer[i]);
31189337ea6aSHermès Bélusca-Maïto     }
31199337ea6aSHermès Bélusca-Maïto }
31209337ea6aSHermès Bélusca-Maïto 
31219337ea6aSHermès Bélusca-Maïto 
3122c2c66affSColin Finck BOOLEAN
3123c2c66affSColin Finck NTAPI
KdbRegisterCliCallback(PVOID Callback,BOOLEAN Deregister)3124c2c66affSColin Finck KdbRegisterCliCallback(
3125c2c66affSColin Finck     PVOID Callback,
3126c2c66affSColin Finck     BOOLEAN Deregister)
3127c2c66affSColin Finck {
3128c2c66affSColin Finck     ULONG i;
3129c2c66affSColin Finck 
3130c2c66affSColin Finck     /* Loop all entries */
3131c2c66affSColin Finck     for (i = 0; i < _countof(KdbCliCallbacks); i++)
3132c2c66affSColin Finck     {
3133c2c66affSColin Finck         /* Check if deregistering was requested */
3134c2c66affSColin Finck         if (Deregister)
3135c2c66affSColin Finck         {
3136c2c66affSColin Finck             /* Check if this entry is the one that was registered */
3137c2c66affSColin Finck             if (KdbCliCallbacks[i] == Callback)
3138c2c66affSColin Finck             {
3139c2c66affSColin Finck                 /* Delete it and report success */
3140c2c66affSColin Finck                 KdbCliCallbacks[i] = NULL;
3141c2c66affSColin Finck                 return TRUE;
3142c2c66affSColin Finck             }
3143c2c66affSColin Finck         }
3144c2c66affSColin Finck         else
3145c2c66affSColin Finck         {
3146c2c66affSColin Finck             /* Check if this entry is free */
3147c2c66affSColin Finck             if (KdbCliCallbacks[i] == NULL)
3148c2c66affSColin Finck             {
3149c2c66affSColin Finck                 /* Set it and and report success */
3150c2c66affSColin Finck                 KdbCliCallbacks[i] = Callback;
3151c2c66affSColin Finck                 return TRUE;
3152c2c66affSColin Finck             }
3153c2c66affSColin Finck         }
3154c2c66affSColin Finck     }
3155c2c66affSColin Finck 
3156c2c66affSColin Finck     /* Unsuccessful */
3157c2c66affSColin Finck     return FALSE;
3158c2c66affSColin Finck }
3159c2c66affSColin Finck 
3160c2c66affSColin Finck /*! \brief Invokes registered CLI callbacks until one of them handled the
3161c2c66affSColin Finck  *         Command.
3162c2c66affSColin Finck  *
3163c2c66affSColin Finck  * \param Command - Command line to parse and execute if possible.
3164c2c66affSColin Finck  * \param Argc - Number of arguments in Argv
3165c2c66affSColin Finck  * \param Argv - Array of strings, each of them containing one argument.
3166c2c66affSColin Finck  *
3167c2c66affSColin Finck  * \return TRUE, if the command was handled, FALSE if it was not handled.
3168c2c66affSColin Finck  */
3169c2c66affSColin Finck static
3170c2c66affSColin Finck BOOLEAN
KdbpInvokeCliCallbacks(IN PCHAR Command,IN ULONG Argc,IN PCHAR Argv[])3171c2c66affSColin Finck KdbpInvokeCliCallbacks(
3172c2c66affSColin Finck     IN PCHAR Command,
3173c2c66affSColin Finck     IN ULONG Argc,
317440c57de7SHermès Bélusca-Maïto     IN PCHAR Argv[])
3175c2c66affSColin Finck {
3176c2c66affSColin Finck     ULONG i;
3177c2c66affSColin Finck 
3178c2c66affSColin Finck     /* Loop all entries */
3179c2c66affSColin Finck     for (i = 0; i < _countof(KdbCliCallbacks); i++)
3180c2c66affSColin Finck     {
3181c2c66affSColin Finck         /* Check if this entry is registered */
3182c2c66affSColin Finck         if (KdbCliCallbacks[i])
3183c2c66affSColin Finck         {
3184c2c66affSColin Finck             /* Invoke the callback and check if it handled the command */
3185c2c66affSColin Finck             if (KdbCliCallbacks[i](Command, Argc, Argv))
3186c2c66affSColin Finck             {
3187c2c66affSColin Finck                 return TRUE;
3188c2c66affSColin Finck             }
3189c2c66affSColin Finck         }
3190c2c66affSColin Finck     }
3191c2c66affSColin Finck 
3192c2c66affSColin Finck     /* None of the callbacks handled the command */
3193c2c66affSColin Finck     return FALSE;
3194c2c66affSColin Finck }
3195c2c66affSColin Finck 
3196c2c66affSColin Finck 
3197c2c66affSColin Finck /*!\brief Parses command line and executes command if found
3198c2c66affSColin Finck  *
3199c2c66affSColin Finck  * \param Command    Command line to parse and execute if possible.
3200c2c66affSColin Finck  *
3201c2c66affSColin Finck  * \retval TRUE   Don't continue execution.
3202c2c66affSColin Finck  * \retval FALSE  Continue execution (leave KDB)
3203c2c66affSColin Finck  */
3204c2c66affSColin Finck static BOOLEAN
KdbpDoCommand(IN PCHAR Command)3205c2c66affSColin Finck KdbpDoCommand(
3206c2c66affSColin Finck     IN PCHAR Command)
3207c2c66affSColin Finck {
3208b86c4bd5SHermès Bélusca-Maïto     BOOLEAN Continue = TRUE;
320925336250STimo Kreuzer     SIZE_T i;
3210c2c66affSColin Finck     PCHAR p;
3211c2c66affSColin Finck     ULONG Argc;
3212c2c66affSColin Finck     // FIXME: for what do we need a 1024 characters command line and 256 tokens?
321340c57de7SHermès Bélusca-Maïto     static PCHAR Argv[256];
3214c2c66affSColin Finck     static CHAR OrigCommand[1024];
3215c2c66affSColin Finck 
3216c2c66affSColin Finck     RtlStringCbCopyA(OrigCommand, sizeof(OrigCommand), Command);
3217c2c66affSColin Finck 
3218c2c66affSColin Finck     Argc = 0;
3219c2c66affSColin Finck     p = Command;
3220c2c66affSColin Finck 
3221c2c66affSColin Finck     for (;;)
3222c2c66affSColin Finck     {
3223c2c66affSColin Finck         while (*p == '\t' || *p == ' ')
3224c2c66affSColin Finck             p++;
3225c2c66affSColin Finck 
3226c2c66affSColin Finck         if (*p == '\0')
3227c2c66affSColin Finck             break;
3228c2c66affSColin Finck 
3229c2c66affSColin Finck         i = strcspn(p, "\t ");
3230c2c66affSColin Finck         Argv[Argc++] = p;
3231c2c66affSColin Finck         p += i;
3232c2c66affSColin Finck         if (*p == '\0')
3233c2c66affSColin Finck             break;
3234c2c66affSColin Finck 
3235c2c66affSColin Finck         *p = '\0';
3236c2c66affSColin Finck         p++;
3237c2c66affSColin Finck     }
3238c2c66affSColin Finck 
3239c2c66affSColin Finck     if (Argc < 1)
3240c2c66affSColin Finck         return TRUE;
3241c2c66affSColin Finck 
3242b86c4bd5SHermès Bélusca-Maïto     /* Reset the pager state: number of printed rows/cols and aborted output flag */
3243b86c4bd5SHermès Bélusca-Maïto     KdbNumberOfRowsPrinted = KdbNumberOfColsPrinted = 0;
3244b86c4bd5SHermès Bélusca-Maïto     KdbOutputAborted = FALSE;
3245b86c4bd5SHermès Bélusca-Maïto 
3246c2c66affSColin Finck     for (i = 0; i < RTL_NUMBER_OF(KdbDebuggerCommands); i++)
3247c2c66affSColin Finck     {
3248c2c66affSColin Finck         if (!KdbDebuggerCommands[i].Name)
3249c2c66affSColin Finck             continue;
3250c2c66affSColin Finck 
3251c2c66affSColin Finck         if (strcmp(KdbDebuggerCommands[i].Name, Argv[0]) == 0)
3252c2c66affSColin Finck         {
3253b86c4bd5SHermès Bélusca-Maïto             Continue = KdbDebuggerCommands[i].Fn(Argc, Argv);
3254b86c4bd5SHermès Bélusca-Maïto             goto Done;
3255c2c66affSColin Finck         }
3256c2c66affSColin Finck     }
3257c2c66affSColin Finck 
3258c2c66affSColin Finck     /* Now invoke the registered callbacks */
3259c2c66affSColin Finck     if (KdbpInvokeCliCallbacks(Command, Argc, Argv))
3260b86c4bd5SHermès Bélusca-Maïto         goto Done;
3261c2c66affSColin Finck 
3262b86c4bd5SHermès Bélusca-Maïto     KdbPrintf("Command '%s' is unknown.\n", OrigCommand);
3263b86c4bd5SHermès Bélusca-Maïto 
3264b86c4bd5SHermès Bélusca-Maïto Done:
3265b86c4bd5SHermès Bélusca-Maïto     KdbOutputAborted = FALSE;
3266b86c4bd5SHermès Bélusca-Maïto     return Continue;
3267c2c66affSColin Finck }
3268c2c66affSColin Finck 
3269c2c66affSColin Finck /*!\brief KDB Main Loop.
3270c2c66affSColin Finck  *
3271c2c66affSColin Finck  * \param EnteredOnSingleStep  TRUE if KDB was entered on single step.
3272c2c66affSColin Finck  */
3273c2c66affSColin Finck VOID
KdbpCliMainLoop(IN BOOLEAN EnteredOnSingleStep)3274c2c66affSColin Finck KdbpCliMainLoop(
3275c2c66affSColin Finck     IN BOOLEAN EnteredOnSingleStep)
3276c2c66affSColin Finck {
3277b86c4bd5SHermès Bélusca-Maïto     BOOLEAN Continue = TRUE;
3278f3dd7133SHermès Bélusca-Maïto     static CHAR Command[1024];
3279f3dd7133SHermès Bélusca-Maïto     static CHAR LastCommand[1024] = "";
3280c2c66affSColin Finck 
3281*52192f19SHermès Bélusca-Maïto // FIXME HACK: SYSREG SUPPORT CORE-19807 -- Emit a backtrace.
3282*52192f19SHermès Bélusca-Maïto // TODO: Remove once SYSREG "bt" command emission is fixed!
3283*52192f19SHermès Bélusca-Maïto #if 1
3284*52192f19SHermès Bélusca-Maïto     KdbpDoCommand("bt");
3285*52192f19SHermès Bélusca-Maïto #endif
3286*52192f19SHermès Bélusca-Maïto 
3287c2c66affSColin Finck     if (EnteredOnSingleStep)
3288c2c66affSColin Finck     {
32893726b992SJérôme Gardou         if (!KdbSymPrintAddress((PVOID)KeGetContextPc(KdbCurrentTrapFrame), KdbCurrentTrapFrame))
3290b86c4bd5SHermès Bélusca-Maïto             KdbPrintf("<%p>", KeGetContextPc(KdbCurrentTrapFrame));
3291c2c66affSColin Finck 
3292b86c4bd5SHermès Bélusca-Maïto         KdbPuts(": ");
32933726b992SJérôme Gardou         if (KdbpDisassemble(KeGetContextPc(KdbCurrentTrapFrame), KdbUseIntelSyntax) < 0)
3294b86c4bd5SHermès Bélusca-Maïto             KdbPuts("<INVALID>");
3295b86c4bd5SHermès Bélusca-Maïto         KdbPuts("\n");
3296c2c66affSColin Finck     }
3297b86c4bd5SHermès Bélusca-Maïto     else
3298b86c4bd5SHermès Bélusca-Maïto     {
3299b86c4bd5SHermès Bélusca-Maïto         /* Preceding this message is one of the "Entered debugger..." banners */
3300b86c4bd5SHermès Bélusca-Maïto         // KdbPuts("\nEntered debugger\n");
3301b86c4bd5SHermès Bélusca-Maïto         KdbPuts("\nType \"help\" for a list of commands.\n");
3302c2c66affSColin Finck     }
3303c2c66affSColin Finck 
3304c2c66affSColin Finck     /* Main loop */
3305b86c4bd5SHermès Bélusca-Maïto     while (Continue)
3306c2c66affSColin Finck     {
3307f3dd7133SHermès Bélusca-Maïto         /*
3308f620ce77SHermès Bélusca-Maïto          * Print the prompt and read a command.
3309f620ce77SHermès Bélusca-Maïto          * Repeat the last one if the user pressed Enter.
3310f3dd7133SHermès Bélusca-Maïto          * This reduces the risk of RSI when single-stepping!
3311f3dd7133SHermès Bélusca-Maïto          */
33128c0c2e2bSHermès Bélusca-Maïto         // TEMP HACK! Issue an empty string instead of duplicating "kdb:>"
3313b86c4bd5SHermès Bélusca-Maïto         SIZE_T CmdLen = KdbPrompt(/*KdbPromptStr.Buffer*/"", Command, sizeof(Command));
3314f620ce77SHermès Bélusca-Maïto         if (CmdLen == 0)
3315f620ce77SHermès Bélusca-Maïto         {
3316f620ce77SHermès Bélusca-Maïto             /* Nothing received but the user didn't press Enter, retry */
3317f620ce77SHermès Bélusca-Maïto             continue;
3318f620ce77SHermès Bélusca-Maïto         }
3319f620ce77SHermès Bélusca-Maïto         else if (CmdLen > 1) // i.e. (*Command != ANSI_NULL)
3320f3dd7133SHermès Bélusca-Maïto         {
3321f3dd7133SHermès Bélusca-Maïto             /* Save this new last command */
3322f3dd7133SHermès Bélusca-Maïto             KdbRepeatLastCommand = TRUE;
3323f3dd7133SHermès Bélusca-Maïto             RtlStringCbCopyA(LastCommand, sizeof(LastCommand), Command);
3324f3dd7133SHermès Bélusca-Maïto 
3325f3dd7133SHermès Bélusca-Maïto             /* Remember it */
3326c2c66affSColin Finck             KdbpCommandHistoryAppend(Command);
3327f3dd7133SHermès Bélusca-Maïto         }
3328f3dd7133SHermès Bélusca-Maïto         else if (KdbRepeatLastCommand)
3329f3dd7133SHermès Bélusca-Maïto         {
3330f3dd7133SHermès Bélusca-Maïto             /* The user directly pressed Enter */
3331f3dd7133SHermès Bélusca-Maïto             RtlStringCbCopyA(Command, sizeof(Command), LastCommand);
3332f3dd7133SHermès Bélusca-Maïto         }
3333c2c66affSColin Finck 
3334b86c4bd5SHermès Bélusca-Maïto         /* Invoke the command */
3335c2c66affSColin Finck         Continue = KdbpDoCommand(Command);
3336c2c66affSColin Finck     }
3337c2c66affSColin Finck }
3338c2c66affSColin Finck 
3339b15963abSHermès Bélusca-Maïto /**
3340b15963abSHermès Bélusca-Maïto  * @brief
3341b15963abSHermès Bélusca-Maïto  * Interprets the KDBinit file from the \SystemRoot\System32\drivers\etc
3342b15963abSHermès Bélusca-Maïto  * directory, that has been loaded by KdbpCliInit().
3343c2c66affSColin Finck  *
3344b15963abSHermès Bélusca-Maïto  * This function is used to interpret the init file in the debugger context
3345b15963abSHermès Bélusca-Maïto  * with a trap frame set up. KdbpCliInit() enters the debugger by calling
3346b15963abSHermès Bélusca-Maïto  * DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C). In turn, this will call
3347b15963abSHermès Bélusca-Maïto  * KdbEnterDebuggerException() which will finally call this function if
3348b15963abSHermès Bélusca-Maïto  * KdbInitFileBuffer is not NULL.
3349b15963abSHermès Bélusca-Maïto  **/
3350c2c66affSColin Finck VOID
KdbpCliInterpretInitFile(VOID)3351c2c66affSColin Finck KdbpCliInterpretInitFile(VOID)
3352c2c66affSColin Finck {
3353c2c66affSColin Finck     PCHAR p1, p2;
3354c2c66affSColin Finck 
3355b15963abSHermès Bélusca-Maïto     p1 = InterlockedExchangePointer((PVOID*)&KdbInitFileBuffer, NULL);
3356b15963abSHermès Bélusca-Maïto     if (!p1)
3357b15963abSHermès Bélusca-Maïto         return;
3358b15963abSHermès Bélusca-Maïto 
3359c2c66affSColin Finck     /* Execute the commands in the init file */
3360b15963abSHermès Bélusca-Maïto     KdbPuts("KDB: Executing KDBinit file...\n");
3361c2c66affSColin Finck     while (p1[0] != '\0')
3362c2c66affSColin Finck     {
3363842e40d7SHermès Bélusca-Maïto         size_t i = strcspn(p1, "\r\n");
3364c2c66affSColin Finck         if (i > 0)
3365c2c66affSColin Finck         {
3366842e40d7SHermès Bélusca-Maïto             CHAR c = p1[i];
3367c2c66affSColin Finck             p1[i] = '\0';
3368c2c66affSColin Finck 
3369c2c66affSColin Finck             /* Look for "break" command and comments */
3370c2c66affSColin Finck             p2 = p1;
3371c2c66affSColin Finck             while (isspace(p2[0]))
3372c2c66affSColin Finck                 p2++;
3373c2c66affSColin Finck 
3374c2c66affSColin Finck             if (strncmp(p2, "break", sizeof("break")-1) == 0 &&
3375c2c66affSColin Finck                 (p2[sizeof("break")-1] == '\0' || isspace(p2[sizeof("break")-1])))
3376c2c66affSColin Finck             {
3377b15963abSHermès Bélusca-Maïto                 /* Run the interactive debugger loop */
3378c2c66affSColin Finck                 KdbpCliMainLoop(FALSE);
3379c2c66affSColin Finck             }
3380c2c66affSColin Finck             else if (p2[0] != '#' && p2[0] != '\0') /* Ignore empty lines and comments */
3381c2c66affSColin Finck             {
3382b15963abSHermès Bélusca-Maïto                 /* Invoke the command */
3383c2c66affSColin Finck                 KdbpDoCommand(p1);
3384c2c66affSColin Finck             }
3385c2c66affSColin Finck 
3386c2c66affSColin Finck             p1[i] = c;
3387c2c66affSColin Finck         }
3388c2c66affSColin Finck 
3389c2c66affSColin Finck         p1 += i;
3390c2c66affSColin Finck         while (p1[0] == '\r' || p1[0] == '\n')
3391c2c66affSColin Finck             p1++;
3392c2c66affSColin Finck     }
3393b15963abSHermès Bélusca-Maïto     KdbPuts("KDB: KDBinit executed\n");
3394c2c66affSColin Finck }
3395c2c66affSColin Finck 
33964ce819caSHermès Bélusca-Maïto /**
33974ce819caSHermès Bélusca-Maïto  * @brief   Called when KDB is initialized.
3398c2c66affSColin Finck  *
3399b15963abSHermès Bélusca-Maïto  * Loads the KDBinit file from the \SystemRoot\System32\drivers\etc
3400b15963abSHermès Bélusca-Maïto  * directory and interprets it, by calling back into the debugger.
34014ce819caSHermès Bélusca-Maïto  **/
34024ce819caSHermès Bélusca-Maïto NTSTATUS
KdbpCliInit(VOID)3403c2c66affSColin Finck KdbpCliInit(VOID)
3404c2c66affSColin Finck {
3405c2c66affSColin Finck     NTSTATUS Status;
3406c2c66affSColin Finck     OBJECT_ATTRIBUTES ObjectAttributes;
3407c2c66affSColin Finck     UNICODE_STRING FileName;
3408c2c66affSColin Finck     IO_STATUS_BLOCK Iosb;
3409c2c66affSColin Finck     FILE_STANDARD_INFORMATION FileStdInfo;
3410c2c66affSColin Finck     HANDLE hFile = NULL;
3411b15963abSHermès Bélusca-Maïto     ULONG FileSize;
3412c2c66affSColin Finck     PCHAR FileBuffer;
3413c2c66affSColin Finck 
34144ce819caSHermès Bélusca-Maïto     /* Don't load the KDBinit file if its buffer is already lying around */
34154ce819caSHermès Bélusca-Maïto     if (KdbInitFileBuffer)
34164ce819caSHermès Bélusca-Maïto         return STATUS_SUCCESS;
34174ce819caSHermès Bélusca-Maïto 
3418c2c66affSColin Finck     /* Initialize the object attributes */
3419c2c66affSColin Finck     RtlInitUnicodeString(&FileName, L"\\SystemRoot\\System32\\drivers\\etc\\KDBinit");
3420b910409aSSerge Gautherie     InitializeObjectAttributes(&ObjectAttributes,
3421b910409aSSerge Gautherie                                &FileName,
3422b910409aSSerge Gautherie                                OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
3423b910409aSSerge Gautherie                                NULL,
3424b910409aSSerge Gautherie                                NULL);
3425c2c66affSColin Finck 
3426c2c66affSColin Finck     /* Open the file */
3427c2c66affSColin Finck     Status = ZwOpenFile(&hFile, FILE_READ_DATA | SYNCHRONIZE,
3428c2c66affSColin Finck                         &ObjectAttributes, &Iosb, 0,
3429c2c66affSColin Finck                         FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT |
3430c2c66affSColin Finck                         FILE_NO_INTERMEDIATE_BUFFERING);
3431c2c66affSColin Finck     if (!NT_SUCCESS(Status))
3432c2c66affSColin Finck     {
3433b15963abSHermès Bélusca-Maïto         DPRINT("Could not open %wZ (Status 0x%lx)\n", &FileName, Status);
34344ce819caSHermès Bélusca-Maïto         return Status;
3435c2c66affSColin Finck     }
3436c2c66affSColin Finck 
3437c2c66affSColin Finck     /* Get the size of the file */
34384585372cSHermès Bélusca-Maïto     Status = ZwQueryInformationFile(hFile, &Iosb,
34394585372cSHermès Bélusca-Maïto                                     &FileStdInfo, sizeof(FileStdInfo),
3440c2c66affSColin Finck                                     FileStandardInformation);
3441c2c66affSColin Finck     if (!NT_SUCCESS(Status))
3442c2c66affSColin Finck     {
3443c2c66affSColin Finck         ZwClose(hFile);
3444b15963abSHermès Bélusca-Maïto         DPRINT1("Could not query size of %wZ (Status 0x%lx)\n", &FileName, Status);
34454ce819caSHermès Bélusca-Maïto         return Status;
3446c2c66affSColin Finck     }
3447c2c66affSColin Finck     FileSize = FileStdInfo.EndOfFile.u.LowPart;
3448c2c66affSColin Finck 
3449b15963abSHermès Bélusca-Maïto     /* Allocate memory for the file (add 1 byte for terminating NUL) */
3450b15963abSHermès Bélusca-Maïto     FileBuffer = ExAllocatePool(NonPagedPool, FileSize + 1);
3451c2c66affSColin Finck     if (!FileBuffer)
3452c2c66affSColin Finck     {
3453c2c66affSColin Finck         ZwClose(hFile);
3454b15963abSHermès Bélusca-Maïto         DPRINT1("Could not allocate %lu bytes for KDBinit file\n", FileSize);
34554ce819caSHermès Bélusca-Maïto         return Status;
3456c2c66affSColin Finck     }
3457c2c66affSColin Finck 
3458c2c66affSColin Finck     /* Load file into memory */
3459b15963abSHermès Bélusca-Maïto     Status = ZwReadFile(hFile, NULL, NULL, NULL, &Iosb,
3460b15963abSHermès Bélusca-Maïto                         FileBuffer, FileSize, NULL, NULL);
3461c2c66affSColin Finck     ZwClose(hFile);
3462c2c66affSColin Finck 
34634585372cSHermès Bélusca-Maïto     if (!NT_SUCCESS(Status) && (Status != STATUS_END_OF_FILE))
3464c2c66affSColin Finck     {
3465c2c66affSColin Finck         ExFreePool(FileBuffer);
34668de4d4d2SSerge Gautherie         DPRINT1("Could not read KDBinit file into memory (Status 0x%lx)\n", Status);
34674ce819caSHermès Bélusca-Maïto         return Status;
3468c2c66affSColin Finck     }
3469c2c66affSColin Finck 
3470b15963abSHermès Bélusca-Maïto     FileSize = min(FileSize, (ULONG)Iosb.Information);
3471b15963abSHermès Bélusca-Maïto     FileBuffer[FileSize] = ANSI_NULL;
3472c2c66affSColin Finck 
3473b15963abSHermès Bélusca-Maïto     /* Interpret the KDBinit file by calling back into the debugger */
3474b15963abSHermès Bélusca-Maïto     InterlockedExchangePointer((PVOID*)&KdbInitFileBuffer, FileBuffer);
3475b15963abSHermès Bélusca-Maïto     DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C);
3476b15963abSHermès Bélusca-Maïto     InterlockedExchangePointer((PVOID*)&KdbInitFileBuffer, NULL);
3477c2c66affSColin Finck 
3478c2c66affSColin Finck     ExFreePool(FileBuffer);
34794ce819caSHermès Bélusca-Maïto 
34804ce819caSHermès Bélusca-Maïto     return STATUS_SUCCESS;
3481c2c66affSColin Finck }
3482dfb6996bSHermès Bélusca-Maïto 
3483dfb6996bSHermès Bélusca-Maïto 
3484bf734e53SHervé Poussineau /**
3485bf734e53SHervé Poussineau  * @brief   Debug logger function.
3486bf734e53SHervé Poussineau  *
3487bf734e53SHervé Poussineau  * This function writes text strings into KdpDmesgBuffer, using it as
3488bf734e53SHervé Poussineau  * a circular buffer. KdpDmesgBuffer contents can be later (re)viewed
3489bf734e53SHervé Poussineau  * using the dmesg command. KdbDebugPrint() protects KdpDmesgBuffer
3490bf734e53SHervé Poussineau  * from simultaneous writes by use of KdpDmesgLogSpinLock.
3491bf734e53SHervé Poussineau  **/
3492dfb6996bSHermès Bélusca-Maïto static VOID
3493dfb6996bSHermès Bélusca-Maïto NTAPI
KdbDebugPrint(_In_ PCCH String,_In_ ULONG Length)3494dfb6996bSHermès Bélusca-Maïto KdbDebugPrint(
3495412037a2SHermès Bélusca-Maïto     _In_ PCCH String,
3496bf734e53SHervé Poussineau     _In_ ULONG Length)
3497dfb6996bSHermès Bélusca-Maïto {
3498bf734e53SHervé Poussineau     KIRQL OldIrql;
3499bf734e53SHervé Poussineau     ULONG beg, end, num;
3500bf734e53SHervé Poussineau 
3501bf734e53SHervé Poussineau     /* Avoid recursive calling if we already are in Dmesg mode */
3502bf734e53SHervé Poussineau     if (KdbpIsInDmesgMode)
3503bf734e53SHervé Poussineau        return;
3504bf734e53SHervé Poussineau 
3505bf734e53SHervé Poussineau     if (KdpDmesgBuffer == NULL)
3506bf734e53SHervé Poussineau         return;
3507bf734e53SHervé Poussineau 
3508bf734e53SHervé Poussineau     /* Acquire the printing spinlock without waiting at raised IRQL */
3509bf734e53SHervé Poussineau     OldIrql = KdbpAcquireLock(&KdpDmesgLogSpinLock);
3510bf734e53SHervé Poussineau 
3511bf734e53SHervé Poussineau     beg = KdpDmesgCurrentPosition;
3512bf734e53SHervé Poussineau     /* Invariant: always_true(KdpDmesgFreeBytes == KdpDmesgBufferSize); */
3513bf734e53SHervé Poussineau     num = min(Length, KdpDmesgFreeBytes);
3514bf734e53SHervé Poussineau     if (num != 0)
3515bf734e53SHervé Poussineau     {
3516bf734e53SHervé Poussineau         end = (beg + num) % KdpDmesgBufferSize;
3517bf734e53SHervé Poussineau         if (end > beg)
3518bf734e53SHervé Poussineau         {
3519bf734e53SHervé Poussineau             RtlCopyMemory(KdpDmesgBuffer + beg, String, Length);
3520bf734e53SHervé Poussineau         }
3521bf734e53SHervé Poussineau         else
3522bf734e53SHervé Poussineau         {
3523bf734e53SHervé Poussineau             RtlCopyMemory(KdpDmesgBuffer + beg, String, KdpDmesgBufferSize - beg);
3524bf734e53SHervé Poussineau             RtlCopyMemory(KdpDmesgBuffer, String + (KdpDmesgBufferSize - beg), end);
3525bf734e53SHervé Poussineau         }
3526bf734e53SHervé Poussineau         KdpDmesgCurrentPosition = end;
3527bf734e53SHervé Poussineau 
3528bf734e53SHervé Poussineau         /* Counting the total bytes written */
3529bf734e53SHervé Poussineau         KdbDmesgTotalWritten += num;
3530bf734e53SHervé Poussineau     }
3531bf734e53SHervé Poussineau 
3532bf734e53SHervé Poussineau     /* Release the spinlock */
3533bf734e53SHervé Poussineau     KdbpReleaseLock(&KdpDmesgLogSpinLock, OldIrql);
3534bf734e53SHervé Poussineau 
3535bf734e53SHervé Poussineau     /* Optional step(?): find out a way to notify about buffer exhaustion,
3536bf734e53SHervé Poussineau      * and possibly fall into kbd to use dmesg command: user will read
3537bf734e53SHervé Poussineau      * debug strings before they will be wiped over by next writes. */
3538dfb6996bSHermès Bélusca-Maïto }
3539dfb6996bSHermès Bélusca-Maïto 
3540dfb6996bSHermès Bélusca-Maïto /**
3541dfb6996bSHermès Bélusca-Maïto  * @brief   Initializes the KDBG debugger.
3542dfb6996bSHermès Bélusca-Maïto  *
3543dfb6996bSHermès Bélusca-Maïto  * @param[in]   DispatchTable
3544dfb6996bSHermès Bélusca-Maïto  * Pointer to the KD dispatch table.
3545dfb6996bSHermès Bélusca-Maïto  *
3546dfb6996bSHermès Bélusca-Maïto  * @param[in]   BootPhase
3547dfb6996bSHermès Bélusca-Maïto  * Phase of initialization.
3548dfb6996bSHermès Bélusca-Maïto  *
35494ce819caSHermès Bélusca-Maïto  * @return  A status value.
3550dfb6996bSHermès Bélusca-Maïto  * @note    Also known as "KdpKdbgInit".
3551dfb6996bSHermès Bélusca-Maïto  **/
35524ce819caSHermès Bélusca-Maïto NTSTATUS
3553dfb6996bSHermès Bélusca-Maïto NTAPI
KdbInitialize(_In_ PKD_DISPATCH_TABLE DispatchTable,_In_ ULONG BootPhase)3554dfb6996bSHermès Bélusca-Maïto KdbInitialize(
3555dfb6996bSHermès Bélusca-Maïto     _In_ PKD_DISPATCH_TABLE DispatchTable,
3556dfb6996bSHermès Bélusca-Maïto     _In_ ULONG BootPhase)
3557dfb6996bSHermès Bélusca-Maïto {
3558934812c4SHermès Bélusca-Maïto     /* Saves the different symbol-loading status across boot phases */
3559934812c4SHermès Bélusca-Maïto     static ULONG LoadSymbols = 0;
3560934812c4SHermès Bélusca-Maïto 
3561dfb6996bSHermès Bélusca-Maïto     if (BootPhase == 0)
3562dfb6996bSHermès Bélusca-Maïto     {
3563dfb6996bSHermès Bélusca-Maïto         /* Write out the functions that we support for now */
3564dfb6996bSHermès Bélusca-Maïto         DispatchTable->KdpPrintRoutine = KdbDebugPrint;
3565dfb6996bSHermès Bélusca-Maïto 
356635180b3aSHermès Bélusca-Maïto         /* Check if we have a command line */
356735180b3aSHermès Bélusca-Maïto         if (KeLoaderBlock && KeLoaderBlock->LoadOptions)
356835180b3aSHermès Bélusca-Maïto         {
356935180b3aSHermès Bélusca-Maïto             /* Get the KDBG Settings */
357035180b3aSHermès Bélusca-Maïto             KdbpGetCommandLineSettings(KeLoaderBlock->LoadOptions);
357135180b3aSHermès Bélusca-Maïto         }
357235180b3aSHermès Bélusca-Maïto 
35734ce819caSHermès Bélusca-Maïto         /* Register for BootPhase 1 initialization and as a Provider */
35744ce819caSHermès Bélusca-Maïto         DispatchTable->KdpInitRoutine = KdbInitialize;
3575dfb6996bSHermès Bélusca-Maïto         InsertTailList(&KdProviders, &DispatchTable->KdProvidersList);
3576dfb6996bSHermès Bélusca-Maïto     }
3577bf734e53SHervé Poussineau     else if (BootPhase == 1)
3578bf734e53SHervé Poussineau     {
35794ce819caSHermès Bélusca-Maïto         /* Register for later BootPhase 2 reinitialization */
35804ce819caSHermès Bélusca-Maïto         DispatchTable->KdpInitRoutine = KdbInitialize;
35814ce819caSHermès Bélusca-Maïto 
3582bf734e53SHervé Poussineau         /* Initialize Dmesg support */
3583bf734e53SHervé Poussineau 
3584bf734e53SHervé Poussineau         /* Allocate a buffer for Dmesg log buffer. +1 for terminating null,
3585bf734e53SHervé Poussineau          * see kdbp_cli.c:KdbpCmdDmesg()/2 */
3586bf734e53SHervé Poussineau         KdpDmesgBuffer = ExAllocatePoolZero(NonPagedPool,
3587bf734e53SHervé Poussineau                                             KdpDmesgBufferSize + 1,
3588bf734e53SHervé Poussineau                                             TAG_KDBG);
3589bf734e53SHervé Poussineau         /* Ignore failure if KdpDmesgBuffer is NULL */
3590bf734e53SHervé Poussineau         KdpDmesgFreeBytes = KdpDmesgBufferSize;
3591bf734e53SHervé Poussineau         KdbDmesgTotalWritten = 0;
3592bf734e53SHervé Poussineau 
3593bf734e53SHervé Poussineau         /* Initialize spinlock */
3594bf734e53SHervé Poussineau         KeInitializeSpinLock(&KdpDmesgLogSpinLock);
3595bf734e53SHervé Poussineau     }
3596dfb6996bSHermès Bélusca-Maïto 
3597934812c4SHermès Bélusca-Maïto     /* Initialize symbols support in BootPhase 0 and 1 */
3598dfb6996bSHermès Bélusca-Maïto     if (BootPhase <= 1)
3599dfb6996bSHermès Bélusca-Maïto     {
3600934812c4SHermès Bélusca-Maïto         LoadSymbols <<= 1;
3601934812c4SHermès Bélusca-Maïto         LoadSymbols |= KdbSymInit(BootPhase);
3602dfb6996bSHermès Bélusca-Maïto     }
3603934812c4SHermès Bélusca-Maïto 
3604934812c4SHermès Bélusca-Maïto     if (BootPhase == 1)
3605934812c4SHermès Bélusca-Maïto     {
3606934812c4SHermès Bélusca-Maïto         /* Announce ourselves */
3607934812c4SHermès Bélusca-Maïto         CHAR buffer[60];
3608934812c4SHermès Bélusca-Maïto         RtlStringCbPrintfA(buffer, sizeof(buffer),
3609934812c4SHermès Bélusca-Maïto                            "   KDBG debugger enabled - %s\r\n",
3610934812c4SHermès Bélusca-Maïto                            !(LoadSymbols & 0x2) ? "No symbols loaded" :
3611934812c4SHermès Bélusca-Maïto                            !(LoadSymbols & 0x1) ? "Kernel symbols loaded"
3612934812c4SHermès Bélusca-Maïto                                                 : "Loading symbols");
3613934812c4SHermès Bélusca-Maïto         HalDisplayString(buffer);
3614934812c4SHermès Bélusca-Maïto     }
3615934812c4SHermès Bélusca-Maïto 
3616934812c4SHermès Bélusca-Maïto     if (BootPhase >= 2)
36174ce819caSHermès Bélusca-Maïto     {
3618b15963abSHermès Bélusca-Maïto         /* I/O is now set up for disk access: load the KDBinit file */
36194ce819caSHermès Bélusca-Maïto         NTSTATUS Status = KdbpCliInit();
36204ce819caSHermès Bélusca-Maïto 
36214ce819caSHermès Bélusca-Maïto         /* Schedule an I/O reinitialization if needed */
36224ce819caSHermès Bélusca-Maïto         if (Status == STATUS_OBJECT_NAME_NOT_FOUND ||
36234ce819caSHermès Bélusca-Maïto             Status == STATUS_OBJECT_PATH_NOT_FOUND)
36244ce819caSHermès Bélusca-Maïto         {
36254ce819caSHermès Bélusca-Maïto             DispatchTable->KdpInitRoutine = KdbInitialize;
36264ce819caSHermès Bélusca-Maïto         }
36274ce819caSHermès Bélusca-Maïto     }
36284ce819caSHermès Bélusca-Maïto 
36294ce819caSHermès Bélusca-Maïto     return STATUS_SUCCESS;
3630dfb6996bSHermès Bélusca-Maïto }
3631dfb6996bSHermès Bélusca-Maïto 
3632dfb6996bSHermès Bélusca-Maïto /* EOF */
3633